Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Broken JSR in KLH10 built for ITS?

39 views
Skip to first unread message

Roch Kusiak

unread,
Aug 18, 2009, 1:58:57 PM8/18/09
to
Greetings.
To make things clear, I'm one of these kids who never saw
a real PDP-10, in early stages of learning.

I'm trying to set up an ITS system under KLH10, using the standard
set of files - PI disk image and bootstraps from klh10-2.0a-aux.tgz.

Unfortunately, attempts to boot the KN10 failed.
If I understand the assembly correctly, JSRs re-execute themselves
repeatedly instead of jumping to adr+1. Identical fragments of code
in the M.C. Lennox's minimal set of ITS tapes jump as they should
when ran under SIMH.

I've tried following configurations (all on x86-32):
- vanilla v2.0A from trailing-edge.com, GCC 4.3, Linux
- v2.0H from the Panda distribution, GCC 4.1, 4.2, 4.3, 4.4, Linux
- ---- " ---- ---- " ---- GCC 4.1, NetBSD.

Building the v2.0H required adding an ifdef check, I think
the dvlites add-on had been tested only in the KL configuration.
Building with GCC 4.1 and 4.2 required commenting-out two
"register" variable qualifiers.

Removal of the default optimization flags didn't affect the problem.

The PANDA distribution works out-of-the-box,
as do the TWONKY TOPS-10 on a locally built KLH10.
But both of these are using KN10-KL.

I have no easy way to try pre-4.x GCC; one option I hadn't tried yet
is PCC under NetBSD.

Example typescript follows.

KLH10 V2.0H (MyITS) built Aug 18 2009 15:34:07
Copyright 􏺩 2002 Kenneth L. Harrenstien -- All Rights Reserved.
This program comes "AS IS" with ABSOLUTELY NO WARRANTY.

Compiled for LINUX on I386 with word model USEHWD
Emulated config:
CPU: KS10 SYS: ITS Pager: ITS APRID: 4097
Memory: 512 pages of 1024 words (SHARED)
Time interval: INTRP Base: OSGET Quantums: OSVIRT
Interval default: 60Hz
Internal clock: OSINT
Other: CIRC JPC DEBUG PCCACHE CTYINT IMPINT EVHINT
Devices: RH11 RPXX(DP) TM03(DP) DZ11 LHDH(DPIMP)
[MEM: Allocating 512 pages shared memory, clearing...done]
(snip vanilla klh10-md.ini)
KLH10# [EOF on klh10-md.ini]
KLH10# tr
Tracing now ON
KLH10# go 774000
Starting KN10 at loc 0774000...
774000: SETZM 777073 777073/ 0
774001: SETZM 776774 776774/ 0
774002: JSR 777074 777074/ 700000,,774004
774002: JSR 777074 777074/ 774003
(snip few thousands of repetitions)
774002: JSR 777074 777074/ 774003
[HALTED: FE interrupt]
KLH10> q
(snip restart)
KLH10# ; go 774000 ; to start DDT, else "go" to start ITS
KLH10#
KLH10# [EOF on klh10-md.ini]
KLH10# tr
Tracing now ON
KLH10# go
Starting KN10 at loc 0144430...
144430: SKIPN 200000 200000/ 254000,,201506
144432: JSR 200001 200001/ 0
144432: JSR 200001 200001/ 144433
(ad nauseam...)
144432: JSR 200001 200001/ 144433
[HALTED: FE interrupt]
KLH10> q

What should I do?

Regards, RK

Rich Alderson

unread,
Aug 18, 2009, 3:36:18 PM8/18/09
to
Roch Kusiak <roch....@gmail.com> writes:

> I'm trying to set up an ITS system under KLH10, using the standard
> set of files - PI disk image and bootstraps from klh10-2.0a-aux.tgz.

[ snip lossage ]

> What should I do?

Besides the ITS people who hang out here, you might also want to ping the
its-hackers mailing list: its-h...@magrathea.cosmic.com . I don't remember
whether this is a(n auto-)moderated list; if so, send a SUBSCRIBE request to
its-hacke...@magrathea.cosmic.com to be able to post there.

I've only run ITS under SimH. I've been meaning to try it out under KLH10
since 2003, but there's lots and lots and lots of square tuits in here with me.

--
Rich Alderson "You get what anybody gets. You get a lifetime."
ne...@alderson.users.panix.com --Death, of the Endless

Roch Kusiak

unread,
Aug 18, 2009, 4:03:51 PM8/18/09
to
On 18 Sie, 21:36, Rich Alderson <n...@alderson.users.panix.com> wrote:

> Besides the ITS people who hang out here, you might also want to ping the

> its-hackers mailing list: its-hack...@magrathea.cosmic.com .  I don't remember


> whether this is a(n auto-)moderated list; if so, send a SUBSCRIBE request to

> its-hackers-requ...@magrathea.cosmic.com to be able to post there.

Thank you for the pointer.
Besides, I managed to verify that it's a bug _in_ GCC4, possibly even
tied to x86/x86-64. Thus I probably shouldn't bother the group with it
anymore,
unless I'll manage to find a workaround.

Thank you, RK

Roch Kusiak

unread,
Aug 18, 2009, 5:07:27 PM8/18/09
to
Sorry for double-post.

On 18 Aug, 22:03, Roch Kusiak <roch.kus...@gmail.com> wrote:
> Besides, I managed to verify that it's a bug _in_ GCC4, possibly even

More precisely, the KS version of the PC_ADDXCT(op_xct(...)) combo
is simple enough for GCC4 to keep the old value of PC in a register;
thus the change to cpu.mr_PC done inside i_jsr() get overwritten
by the result of (old_PC + 0_returned_from_i_jsr).

Interesting fact - adding 'volatile' qualifiers to cpu's struct as a
whole
nor the PC entry inside does not seem to change the behaviour...

Sincerely,
RK

Message has been deleted

Roch Kusiak

unread,
Aug 19, 2009, 4:39:18 AM8/19/09
to
Good morning.

I believe I've found a rudimentary work-around.
Not sure about the performance penalty, but better slow
than unusable.

--- kn10def.h.orig 2009-08-19 10:20:40.000000000 +0200
+++ kn10def.h 2009-08-19 10:20:23.000000000 +0200
@@ -234,6 +234,8 @@OC
*/
#if KLH10_EXTADR
# define PC_ADDXCT(x) { register pcinc_t i__ = (x); if (i__) PC_ADD
(i__); }
+#elif GCC4_WORKAROUND
+# define PC_ADDXCT(x) { volatile pcinc_t i__ = (x); cpu.mr_PC +=
i__; }
#else
# define PC_ADDXCT(x) (cpu.mr_PC += (x)) /* For now; fix up
later? */
#endif

I'm afraid that the original PC += (func_that_changes_PC()) expression
does actually fall under the C "undefined behaviour" category.

I apologize for taking your time.
Regards, RK

Rob Warnock

unread,
Aug 19, 2009, 5:47:24 AM8/19/09
to
Roch Kusiak <roch....@gmail.com> wrote:
+---------------

| I'm afraid that the original PC += (func_that_changes_PC()) expression
| does actually fall under the "undefined behaviour" category.
+---------------

I had to fix some cases like this in a program that used a "precise"
copying [relocating] garbage collector. Even though the address of
a GC'd variables in this program were "registered" with the garbage
collector [making them globally visible and thus were automatically
assumed volatile across subroutine calls], the C standard says that
accounting for such side effects only occurs at "sequence points",
and the fetch & store of "foo += bar()" isn't such a sequence point.
However, if you re-write it as "tmp = bar(); foo += tmp;"[2], then
things should work much better.

And, no, the comma operator *isn't* [AFAIK] a sequence point, so
you can't simply rewrite the macro to use "(tmp = bar(), foo += tmp)".
AFAIK in this case the C standard still permits the compiler to fetch
"foo" into a register [invisible to "bar()"!] *before* it calls "bar()".


-Rob

[2] Or as "tmp1 = foo; tmp2 = bar(); foo = tmp1 + tmp2;",
depending on exactly which semantics you want.

-----
Rob Warnock <rp...@rpw3.org>
627 26th Avenue <URL:http://rpw3.org/>
San Mateo, CA 94403 (650)572-2607

jmfbahciv

unread,
Aug 19, 2009, 7:42:37 AM8/19/09
to

Don't apologize for showing your work. Did you have fun debugging?

/BAH

Roch Kusiak

unread,
Aug 19, 2009, 12:01:14 PM8/19/09
to
On 19 Aug, 13:42, jmfbahciv <jmfbahciv@aol> wrote:
> Don't apologize for showing your work.  Did you have fun debugging?
>
> /BAH

Heh, yeah.
Debugging something for one's own, with no external pressure
can be fun. It's the kind where you're totally lost in
unfamiliar code that has to be fixed today which is problematic.

It would be even better if Linux had a good assembly-level debugger
in either of the DDT or OllyDBG styles; GDB's annoying at least.

Have a nice day,
RK

Mark Crispin

unread,
Aug 19, 2009, 4:59:01 PM8/19/09
to
On Wed, 19 Aug 2009, Roch Kusiak posted:

> Debugging something for one's own, with no external pressure
> can be fun. It's the kind where you're totally lost in
> unfamiliar code that has to be fixed today which is problematic.

For what it's worth, I have adopted your patch in the klh10-2.0h sources.
There are several other patches since the last distribution was made, but
I've been waiting for an external project to complete before making a new
distribution because it would be highly desirable to incorporate that
project.

> It would be even better if Linux had a good assembly-level debugger
> in either of the DDT or OllyDBG styles; GDB's annoying at least.

Yes, gdb is annoying. Although it mostly works, it has a terrible user
interface. I will refrain from saying more on that topic.

-- Mark --

http://panda.com/mrc
Democracy is two wolves and a sheep deciding what to eat for lunch.
Liberty is a well-armed sheep contesting the vote.

Roch Kusiak

unread,
Aug 19, 2009, 5:51:57 PM8/19/09
to
On 19 Aug, 22:59, Mark Crispin <m...@panda.com> wrote:
> For what it's worth, I have adopted your patch in the klh10-2.0h sources.

Why, thanks. Guess it could be changed from a manual switch into
something like #elif defined(__GNUC__) && (__GNUC__ == 4) ,
but i'm not sure if automating it would be better in this case.

While we're on the topic of #defines, there's this suspicious line:
cenv.h:270:# define _FILE_OFFSET_BITS=64 /* Use 64-bit file ops
*/
It "even" receives a warning from cpp. The macro actually expands into
"=64" afterwards, but somehow it doesn't create a syntax error
anywhere.

You may want to look into that in some spare time.

Regards,
RK

Mark Crispin

unread,
Aug 19, 2009, 8:35:20 PM8/19/09
to
On Wed, 19 Aug 2009, Roch Kusiak posted:
> cenv.h:270:# define _FILE_OFFSET_BITS=64 /* Use 64-bit file ops */

I encountered that some time ago. Already fixed in my newer bits. Thanks
anyway.

David Thompson

unread,
Aug 31, 2009, 4:19:32 AM8/31/09
to
On Wed, 19 Aug 2009 04:47:24 -0500, rp...@rpw3.org (Rob Warnock) wrote:

> Roch Kusiak <roch....@gmail.com> wrote:
> +---------------
> | I'm afraid that the original PC += (func_that_changes_PC()) expression
> | does actually fall under the "undefined behaviour" category.
> +---------------

> <snip> the C standard says that


> accounting for such side effects only occurs at "sequence points",
> and the fetch & store of "foo += bar()" isn't such a sequence point.
> However, if you re-write it as "tmp = bar(); foo += tmp;"[2], then
> things should work much better.
>
> And, no, the comma operator *isn't* [AFAIK] a sequence point, so
> you can't simply rewrite the macro to use "(tmp = bar(), foo += tmp)".

The C comma _operator_ is a sequence point. But the commas
in a function call such as foo(x,y,z) are part of the syntax, not
operators; and the order of evaluation of those arguments (and the
function designator, if nontrivial) are explicitly unsequenced.
(Formally it's not crystal clear if they're merely 'unspecified' or
fully 'undefined', and the attempt to get a formal seq-pt model that
would resolve gray areas like this into C99 failed, but is being tried
again for C0X. But they're definitely not portable nor reliable.)

In a declaration initializer-list like int a[3] = {x,y,z} the commas
again are syntax, but here they are (explicitly) seqpts. This matters
only for auto variables in C99, where aggregate initlists can be
nonconstant=runtime; initlists for statics in C99 and all in C90 must
have constant=compiletime elements, which don't allow any
object=memory access so their non/sequencing can't matter.

And in C++, the _builtin_ comma operator is a sequence point as in C,
but an overloaded comma operator for a user type is not; like all
operator overloads it is just sugar for a normal (not-ordering) call.

This confusion brought to you by the letters d m r b j s <G>.

Charles Richmond

unread,
Aug 31, 2009, 11:07:36 AM8/31/09
to
David Thompson wrote:
> On Wed, 19 Aug 2009 04:47:24 -0500, rp...@rpw3.org (Rob Warnock) wrote:
>
>> Roch Kusiak <roch....@gmail.com> wrote:
>> +---------------
>> | I'm afraid that the original PC += (func_that_changes_PC()) expression
>> | does actually fall under the "undefined behaviour" category.
>> +---------------
>
>> <snip> the C standard says that
>> accounting for such side effects only occurs at "sequence points",
>> and the fetch & store of "foo += bar()" isn't such a sequence point.
>> However, if you re-write it as "tmp = bar(); foo += tmp;"[2], then
>> things should work much better.
>>
>> And, no, the comma operator *isn't* [AFAIK] a sequence point, so
>> you can't simply rewrite the macro to use "(tmp = bar(), foo += tmp)".
>
> The C comma _operator_ is a sequence point. But the commas
> in a function call such as foo(x,y,z) are part of the syntax, not
> operators; and the order of evaluation of those arguments (and the
> function designator, if nontrivial) are explicitly unsequenced.
> (Formally it's not crystal clear if they're merely 'unspecified' or
> fully 'undefined', and the attempt to get a formal seq-pt model that
> would resolve gray areas like this into C99 failed, but is being tried
> again for C0X. But they're definitely not portable nor reliable.)
>

The commas used in a function call *can* sometimes be operators,
and act as sequence points. If you call a function like this:

myfunc(5,6,(7,8,9),10);


... then the commas in the *interior* set of parentheses *are*
operators. This call would use 9 as the third actual parameter to
the function call.

--
+----------------------------------------+
| Charles and Francis Richmond |
| |
| plano dot net at aquaporin4 dot com |
+----------------------------------------+

Rob Warnock

unread,
Aug 31, 2009, 10:49:11 PM8/31/09
to
David Thompson <dave.th...@verizon.net> wrote:
+---------------

| rp...@rpw3.org (Rob Warnock) wrote:
| > Roch Kusiak <roch....@gmail.com> wrote:
| > +---------------
| > | I'm afraid that the original PC += (func_that_changes_PC()) expression
| > | does actually fall under the "undefined behaviour" category.
| > +---------------
|
| > <snip> the C standard says that
| > accounting for such side effects only occurs at "sequence points",
| > and the fetch & store of "foo += bar()" isn't such a sequence point.
| > However, if you re-write it as "tmp = bar(); foo += tmp;"[2], then
| > things should work much better.
| >
| > And, no, the comma operator *isn't* [AFAIK] a sequence point, so
| > you can't simply rewrite the macro to use "(tmp = bar(), foo += tmp)".
|
| The C comma _operator_ is a sequence point. But the commas
| in a function call such as foo(x,y,z) are part of the syntax, not
| operators; and the order of evaluation of those arguments (and the
| function designator, if nontrivial) are explicitly unsequenced.
+---------------

Oh, o.k., thanks for the clarification. I'll have to go back and see
if the GC issues I was having [when I learned about sequence points]
were with the comma operator or the syntax. [I suspect the latter.]

In any case, the OP's "foo += bar();" certainly *didn't* contain a
sequence point between the fetch & store of "foo"! ;-}

+---------------


| And in C++, the _builtin_ comma operator is a sequence point as in C,
| but an overloaded comma operator for a user type is not; like all
| operator overloads it is just sugar for a normal (not-ordering) call.

+---------------

Yecch.


-Rob

Rhialto

unread,
Sep 13, 2009, 8:07:09 PM9/13/09
to
Roch Kusiak wrote:
> Why, thanks. Guess it could be changed from a manual switch into
> something like #elif defined(__GNUC__) && (__GNUC__ == 4) ,
> but i'm not sure if automating it would be better in this case.

No, it should not be covered by a switch at all, it should always be
used. The original code is plain wrong, as is clear from the subthread
about sequence points.

Probably it doesn't need the "volatile" though.

-Olaf
--
___ Olaf 'Rhialto' Seibert -- You author it, and I'll reader it.
\X/ rhialto/at/xs4all.nl -- Cetero censeo "authored" delendum esse.

0 new messages