From: Han on 30 Jun 2010 17:39 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 30 Jun 2010 18:24 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 30 Jun 2010 23:15 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 1 Jul 2010 00:36 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 1 Jul 2010 04:10
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 |