From: Han on
On Jun 30, 4:00 am, Andreas Möller <andreas_moellerNOS...(a)gmx.de>
wrote:
> Hello,
>
> > I would love to have a copy of the talk
> You got mail.
>
> Regards,
> Andreashttp://www.software49g.gmxhome.de

Just some initial thoughts:

1. I was unable to duplicate the bug as described in your talk -- at
least as far as non-system libraries were concerned. Storing objects
into PORT 0 did not change the table within SRRP (located at the
pointer stored in =USEROB (#80711h)). Whether an object or library was
stored, the SRRP's table was exactly the same. The table only changed
with either a library was attached/detached, or after a warmstart.

2. Manually attaching new libraries (e.g. :: 992 TOSRRP ; or << 992
ATTACH >>) updated the SRRP table, but again none of the entries was
overwritten with 0's. I then manually attached library 6 (not possible
with UserRPL; I used :: 6 TOSRRP ; instead). When this was attached,
the hash/message table was updated, but written with 0's only for the
hash address (makes sense if library 6 does not contain commands). The
message table, however, was correctly found. I tried other orders
(attach lib 6 first, then store something into PORT 0, etc) and got
the same results -- the hash/message table was updated correctly and
as expected. (Tested on ROM 1.23 and 2.15 with the same results.)

3. Warmstarts reset the SRRP hash/message table, so that library 6 is
no longer attached. However, newly installed libraries were correctly
added to the table, and old entries were left intact.

I have not tried to overwrite or adjust ROMPTAB to use replacement
libraries (e.g. replacing library 6). When I checked how the ROM
updates the table, I did not see anything out of the ordinary. In ROM
2.15, the only time the values in the table are overwritten with 0's
is if the attached library does not have an entry in ROMPTAB, or the
old values were invalid. The values are considered invalid if the
libraries are covered, and the old hash/msg table info did not point
to ACPTRs. Here's my dissassembly of the routine (with my own
comments) from Jazz:

L09811 D1=(5) =USEROB
A=DAT1 A
D1=A
D1=D1+ 5 skip DORRP prologue
C=DAT1 X get lib count
D=C X D[X] = lib count in SRRP
D1=D1- 10 prepare D1 to enter loop

L0982B D=D-1 X
RTNC CS: no more libs to search; RTN
D1=D1+ 13 skip to lib ID
A=DAT1 X A[X] = current lib ID in SRRP
D0=(5) =ROMPTAB
C=DAT0 X
B=C X B[X] = lib count in ROMPTAB
D0=D0+ 3
C=0 W
B=B-1 X prepare loop; 0-based count
GOC L0986E only reached if no libs exist!?

L09852 C=DAT0 X
?C=A X found a matching lib ID?
GOYES L0986E
D0=D0+ 16 no
B=B-1 X
GONC L09852 get next lib ID
C=0 A lib ID never found
DAT1=C 13 write 0's
GOTO L0982B and do next attached library

L0986E D0=D0+ 3 found matching lib ID
A=DAT0 A
A=A+CON A,3 A[A] = address of hash table offset
LC(5) #40000
?C>=A A is the library in main ROM? (e.g. lib 2)
GOYES L0982B yes, no need to update in SRRP
D1=D1+ 3 no, so skip lib ID; D1 -> hash offset
D0=D0+ 5
C=DAT0 A C[A] = config address from ROMPTAB
?C#0 A is the library covered?
GOYES L098C4 yes

* update SRRP info if library does not require configuring
D0=A no, D0 -> hash table offset
C=DAT0 A C[A] = hash table offset
?C=0 A does hash table exist?
GOYES L098A1 no, write 0's
C=C+A A yes, C[A] = address of hash table
L098A1 DAT1=C A save hash table info in SRRP
D1=D1+ 5 D1 -> message table in SRRP
D0=D0+ 5 D0 -> message table offset
A=A+CON A,5 A[A] = address of msg table offset
C=DAT0 A
?C=0 A do we have a message table?
GOYES L098BA no, write 0's
C=C+A A yes, C[A] = address of msg table
L098BA DAT1=C A save msg table info in SRRP
D1=D1- 8 D1 -> lib num in SRRP
GOTO L0982B do next attached library

* if library is covered, update SRRP info and necessary ACPTRs in RAM
L098C4 RSTK=C library was covered; RSTK : cfg addr
P= 0 P=0 means configure library
GOSUB L097BF PC=C
C=RSTK C[A] = cfg addr
RSTK=C
R0=A.F A R0[A] = addr of hash table offset
LA(5) =IRAMBUFF
R1=A.F A R1[A] = addr of IRAMBUFF
AD1EX
B=A A B[A] = addr of hash info in SRRP
C=0 S
LA(5) #A
P= 2 P=2 means copy from R0[A] to R1[A]
GOSUB L097BF PC=C (calls MOVEDOWN); restore Bank2
C=RSTK
BCEX A B[A] = cfg addr, C[A] = ->hash in SRRP
D1=C
A=R0.F A
A=A-CON A,10
D0=(5) =IRAMBUFF D0 -> hash table offset
GOSUB L0993D
D1=D1+ 5
A=R0.F A
A=A-CON A,5
D0=(5) (=IRAMBUFF)+5 D0 -> msg table offset
GOSUB L0993D
D1=D1- 8
GOTO L0982B do next attached library

* update the list RAM area containing ACPTRs to hash/msg tables
L0993D C=DAT0 A
?C#0 A do we have a hash or msg table?
GOYES L0994A
DAT1=C A no, write 0's
RTN
L0994A C=C+A A yes, C[A] = addr of table
A=DAT1 A A[A] = old table addr
D0=A
A=DAT0 A
CD0EX save C[A] in D0
LC(5) =DOACPTR
?C=A A was old table addr valid?
GOYES L0996B
C=0 A no, so write 0's
DAT1=C A
RTN
L0996B C=DAT1 A old hash addr was valid
CD0EX C[A] = addr of hash table; D0 -> ACPTR
D0=D0+ 5 skip prologue
DAT0=C A write the table address
D0=D0+ 5 skip address
C=B A get cfg addr
DAT0=C A and save
RTN


From: Andreas Möller on
Hi Han,

I have mailed you a code example so that you can investigate the bug
for yourself.

Regards,
Andreas
http://www.software49g.gmxhome.de
From: Han on
I tried your example, and indeed noticed that the table indeed gets
written with 0's -- but I think this was intended in design (as a
safety measure). When storing into ports, the SRRP table needs to be
validated for any possible changes in library configurations. If what
it finds is invalid, it writes 0's so that the system doesn't jump to
erroneous addresses when accessing a command, or possibly obtain an
extremely large message filled with garbage characters when retrieving
a message.

The problem is in the use of SETMESG. Somewhat related, the
documentation for SETMESG, GETMSG, SETHASH, etc. are either incomplete
or incorrect (as in the case for GETMSG, which returns an ACPTR to the
table and T/F). As far as I can tell, there does not appear to be any
SysRPL routine in ROM in the HP48 series which calls SETMESG (I have
not checked ROM 2.15 if this also the case). On the other hand, the ML
routines used by SETMESG (48, 49G, 49G+, 50G) are also the same ones
used by the system to set up the hash and message tables (see ML entry
=SET). Based on the disassembly, though, it seems reasonable to
conclude that the original design expects a library and all its
contents (including hash and message tables) to be located in the same
memory bank. In fact, if you look peek into the entry =SET, you will
see that:

* in the HP48SX, absolutely no checking is done whatsoever to ensure
that the object being set as the hash or message table is valid; it
simply sets the SRRP table to point to the object

* in the HP48GX and the HP50G, there is a check to see if the table is
a ROMPTR and then ACPTRs are created as necessary; the SRRP table gets
updated with the address to these ACPTRs; if the object is not a
ROMPTR, then the ROM first ensures the object is not in temporary
memory, and then behaves like the HP48SX code

In both cases, not much validation is done when setting tables. There
is no need to validate, since the system should know what to "feed"
the SETMESG command, or the =SET in ML and anyone programming in
SysRPL presumably knows what they're doing. Instead, validation is
done when a user does something that would require validating the SRRP
table (e.g. storing into port memory, attaching a library, etc.)

When validating the SRRP table, the ROM expects the library's message
table (and likewise, its hash table) to lie in the same bank of memory
as the library itself, as it should. The reason the SRRP table is
being overwritten with 0's is due the fact that ROM expects the
address in the SRRP table to point to an ACPTR. By replacing covered
message tables with tables stored in uncovered memory, you're
essentially asking that the system be able to handle cases where
libraries are partly covered (the main parts of the library) and
partly uncovered (the message table). While this may seem like a nice
feature, I don't think this was the intended design. In fact, this
would make library handling more difficult if the hash and message
tables were allowed to be separate from the library itself. (By
separate, I mean in a different memory bank).

You would get the exact same behavior described in your talk if you
tried to replace the message/hash tables of regular libraries using
SETMESG "incorrectly". Upon storing an object into a port, the SRRP
table gets re-validated and will simply be either written with 0's, or
reset to its default value (unless you also modify ROMPTAB). I see
this as a safety net to ensure that the pointers to a library's hash
and message tables get updated properly, or nullified when something
is amiss.

So that the SRRP table is not overwritten with 0's, one should ensure
that the message tables are referenced by ACPTRs (even if they are not
stored in covered memory) regardless of how we store the tables (be it
in global variables or even in covered memory). If the table is not in
covered memory, just use 0's for the config address in the ACPTRs and
make the ACPTRs point to the replacement table. Next, we would need to
adjust ROMPTAB so that when the SRRP table gets validated, it does not
reset the modified ACPTRs back to their original values. Older
versions of SpeedUI used this trick to shadow some of the keyob tables.
From: Han on
Minor fix: the ACPTRs config pointers should not be 0 if the
replacement table is not covered. Instead, it should point to whatever
place in ROM that simply does RTN (i.e. no config necessary)
From: Andreas Möller on
Hi Han,

nice explanation and advocacy of the ROM but you are making the wrong
conclusions IMHO.

1. This behavior does not happen in the 48GX series

2. The behavior happens on the 49G if you use a replacement message
table as an IDentifier, a ROMPTR for Port0 or an ACPTR for Port1 and
Port2 for the covered libraries (all libraries > 5).

3. From my understanding the problem is not SETMSG, here the same code
is used in the 48 and the 49. The problem is the dynamic rebuild of
the ROMPART which was introduced in the 49G as a feature to make
warmstarts unnecessary after a lib has been stored in a port.
In the 48GX the ROMPART is only rebuild at system start and this table
is fixed which means that you have to warmstart after installing a
library so that the config routines (if they exist) of each library is
run.
In the 49G this is done dynamically so that a warmstart is not
necessary. However, this feature has never worked correctly so that
everybody still gives the advise to warmstart after a library
installation, even HP still gives this advise in their official
documentation. See page 27 of the "HP 50g Graphing Calculator Quick
Start Guide".

4. The problem is the STO routine which behaves as explained above
while zeroing the message table and the hash table if something is
stored in a port *if* alternative message tables and hash tables are
used. I have a note somewhere from Cyrille where to look, but I can
not find it at the moment. However, this is buried so deeply in the
system that changing/fixing this would require a lot of work to keep
supported entries stable. Personally I do not expect that this will be
fixed ever because of the much work needed for it (Is there actually
any ROM development happening ?)
and because a workaround is possible and now exists. Note that the
workaround I programmed has no impact on speed of the machine because
the workaround is done completely in Saturn-ML.


> When storing into ports, the SRRP table needs
> to be validated for any possible changes in library
> configurations.
In the 48GX this is only done at system boot.
In the 49G this is done at system boot *and* dynamically each time
something is stored in a port and that is where the problem lies, in
the STO-code !


> GETMSG, which returns an ACPTR to the
> table and T/F
Yes, the documentation of SETHASH/GETHASH and SETMSG/GETMSG is
incomplete. GETMSG returns a pointer to the message table if the
library is not in covered memory and returns an ACPTR if the message
table is in covered memory.


> it seems reasonable to conclude that the original
> design expects a library and all its contents
> (including hash and message tables) to be located
> in the same memory bank.
This is an incorrect assumption from you, see below.


> When validating the SRRP table, the ROM
> expects the library's message table (and
> likewise, its hash table) to lie in the same bank
> of memory as the library itself, as it should.
Nope, this is a wishful assumption from you, because as an example the
code for the solver (Flashbank2) and the messages for it (FlashBank3)
are *not* in the same flashbanks. This is used frequently in the ROM.


> In fact, this would make library handling more
> difficult if the hash and message tables were
> allowed to be separate from the library itself. (By
> separate, I mean in a different memory bank).
As shown above this is intended by design. Some built-in libraries
even come without a message table and instead they have a PTR that
points to a message array somewhere in memory. This PTR either leads
directly to the message table or otherwise points to an ACPTR which
will then lead to the message table.


> So that the SRRP table is not overwritten with 0's,
> one should ensure that the message tables are
> referenced by ACPTRs (even if they are not stored
> in covered memory) regardless of how we store the
> tables (be it in global variables or even in covered
> memory).
Again, using an ACPTR does not help. The code example I sent to you
was just a very easy way to show the problem. I spend a lot of time
and effort to investigate this and to come up with a circumvention of
this.

HTH,
Andreas
http://www.software49g.gmxhome.de