From: ervin@pinbot.enet.dec.com (Joseph James Ervin)
Subject: Re: memory map & System RPL CREATETEMP
Reply-To: ervin@pinbot.enet.dec.com (Joseph James Ervin)
Organization: Digital Equipment Corporation
Date: Fri, 4 Sep 1992 12:40:36 GMT


In article <2aa6b8de.1655comp.sys.hp48@hpcvbbs.cv.hp.com>,
akcs.rsanders@hpcvbbs.cv.hp.com (Robert Sanders) writes:

|>I've been working my way up from the many scattered (but informative!)
|>tidbits about ML programming on the '48, but I don't really feel
|>comfortable about what I'm doing unless I REALLY understand it. My main
|>concerns now are about memory allocation using CREATETEMP.

You may find it easier to use a different routine that is not quite as
low level.  Personally, I like to use the entry point that makes a string.
Then I just modify the prolog and such to transform it into what I really
want.  The nice thing about this is that it takes care of all the garbage 
collection and such automatically.  

The symbol name of the entry point is: MAKE$N, and it creates a string
with the body of the string N nibbles long, where N is passed in C.A.  On
return, R0 points to the prolog of the string object, and D0 points to 
the data section of the string.  


|>
|>1) I have a program that calls CREATETEMP.  I understand that if
|>CREATETEMP returns with carry set, an allocation error has occurred. I
|>then call GARBAGECOL (at #613e) and re-CREATETEMP.  However, I don't
|>think I'm doing this correctly, as my program ( a string reverser, what
|>else?) will work once (in low memory conditions) then corrupt the string.
|>I'm obviously not interpreting GARBAGECOL's exit conditions correctly,
|>but I can't get much information from EXPAND (PMC at #61c1c), and my
|>disassembly of GARBAGECOL might take a while.  Has anyone done this
|>already so that I can save a little time and study for finals? :)
|>
|>2) CREATETEMP moves the heap into the free space between what was the
|>heap and the RPL stack.  However, I don't think I really understand what
|>the memory areas referenced by the entries4 names RETTOP (saved B @
|>#70574) and TEMPTOP (ptr @ #7056F) are (er, sorry for that weak
|>sentence).  Does anyone have an informative memory map?  
|> 

Below is my disassembly of a section of the HP48 ROM which creates a binary
integer 13 nibbles long.  This is used by the TICKS command to create the
13 nibble binary integer into which is written the current TICKS value.
This should give you an idea of how to use the CREATETEMP entry point in
case you don't want to use the MAKE$N entry point described above.

I hope this helps.

>>>Joe Ervin


***********************************************************************
; This RPL command just puts 13d onto the stack as a system binary and then
; calls the RPL command to create a binary integer in TEMPOB.
0EDB9: ; *** create Binary Integer (13 nibbles) ***                             
0EDB9: 02D9D ! Program                                                          
0EDBE: 04071 ; <Dh>                                                             
0EDC3: 0EDE1 ; allocate Binary Integer (1:System Binary)                        
0EDC8: 0312B ! End Marker     



; This RPL command creates a binary integer with the body of the binary number
; having the number of nibbles given by the system binary in 1:.
0EDE1: ; *** allocate Binary Integer (1:System Binary) ***                      
0EDE1: 02D9D ! Program                                                          
0EDE6: 055D5 ; Binary Integer template                                          
0EDEB: 03223 ; Internal SWAP                                                    
0EDF0: 61C1C ; allocate nibbles (2:sized object,1:System Binary)                
0EDF5: 0312B ! End Marker 


HP:EXPAND
61C1C: ; *** allocate nibbles (2:sized object,1:System Binary) ***              
61C1C: 61C21 ! Machine Code at 61C21                                            
61C21: 8E7780     GOSUBL 6249E	; MC XFER: pop stk1 (System Binary) into A.A. 
61C27: 8FB9760    GOSBVL 0679B	; MC: save D0,D1,B,D (uses C,D0), clear carry 
61C2E: D8         B=A    A 	; Move size of object into B.a. 
61C30: 147        C=DAT1 A	; Get the next address from stack to level 1. 
				; This points to the template for the object 
				; type being created. 
61C33: 137        CD1EX     	; Point D1 to that template, C to stack level
				; 1. 
61C36: 174        D1=D1+ 5	; Point to the size field of the template.  
				; This indicates how many more nibbles than the
				; requested size we need to allocate for the
				; expanded object.
61C39: 143        A=DAT1 A	; Get the size field of the template into A. 
61C3C: C8         B=B+A  A	; Add this many nibbles to the requested size 
				; of the object.
61C3E: 137        CD1EX 	; Point D1 to stack level 1, C to the size
				; field of the template.
61C41: 06         RSTK=C   	; Save template pointer. 
61C43: D9         C=B    A	; Get # of nibbles into C. 
61C45: 24         P=     4                                                      
61C47: 809        C+P+1		; Add 5 nibbles to C.  C now contains the 
				; number of nibbles to allocate from memory, 
				; including what will be used by the object's
				; prolog. 
61C4A: 06         RSTK=C	; Save # of nibbles to allocate. 
61C4C: 84A        ST=0   10	; Clear ST<10> which is used for GC tracking. 
61C4F: 07         C=RSTK	; Pop the # of nibbles to allocate. 
61C51: 06         RSTK=C	; Push the number of nibbles to allocate.   
61C53: 8F8DA60    GOSBVL 06AD8	; HP:CREATETEMP (A = malloc(C nibbles)). 
61C5A: 5E3        GONC   61C99	; If no error, then continue at 61c99. 
61C5D: 86A01      ?ST=0  10 	; Have we done GC already? 
                  GOYES  61C70                                                  
61C62: 07         C=RSTK                                                        
61C64: 07         C=RSTK                                                        
61C66: 8E0480     GOSUBL 624AC	; MC XFER: restore D,B,D1,D0 (C=D0), 
				; clear carry. 
61C6C: 6051       GOTO   61DBD                                                  
                                                                                
61DBD: 8DBBF40    GOVLNG 04FBB	; MC: Error: Insufficient Memory   

61C99: 07         C=RSTK	; Pop # of nibbles allocated, for the new 
				; object, including the prolog, but excluding 
				; the 6 nibbles of TEMPOB overhead.
61C9B: D5         B=C    A 	; Save it in B. 
61C9D: 07         C=RSTK	; Pop pointer into object template. 
61C9F: 136        CD0EX  	; Point D0 to second word in template, C to 
				; top of TEMPOB+1. 
61CA2: 06         RSTK=C 	; Push pointer top of TEMPOB+1. 
61CA4: 137        CD1EX		; Point C to 5 nibbles into the newly allocated
				; TEMPOB RAM. D1 to top of TEMPOB+1.  This is
				; where the new object will start, i.e. where
				; it's prolog will be written.
61CA7: 146        C=DAT0 A   	; Get the object's excess size from the 
				; object template. 
61CAA: 24         P=     4                                                      
61CAC: 809        C+P+1   	; Add 5 to the object's excess size to account
				; for its prolog. 
61CAF: D7         D=C    A  	; Save the size of the prolog+size field in D. 
61CB1: 184        D0=D0- 5 	; Back up to the template's prolog. 
61CB4: 8FC0760    GOSBVL 0670C	; HP:MOVEDOWN, 
				; blockcopy (D0:src,D1:dst,C.A=nibbles).  This 
				; copies the template object pointed to by D0
				; into the TEMPOB area pointed to by D1. 
61CBB: 07         C=RSTK 	; Pop the pointer to the start of the new
				; object. 
61CBD: 136        CD0EX		;  
61CC0: D9         C=B    A 	; C Gets number of nibbles allocated.
61CC2: 136        CD0EX         ; And swap # of nibbles allocated into D0. 
61CC5: 184        D0=D0- 5	; Take away 5 nibbles for the object's prolog. 
61CC8: 136        CD0EX                                                         
61CCB: 164        D0=D0+ 5	; Add 5 to the starting address of the object. 
61CCE: 144        DAT0=C A	; ...and write out the object's size into its
				; size field.  The new object in TEMPOB now has 
				; a valid prolog and size field. 
61CD1: 184        D0=D0- 5	; Back up to the start of the object. 
61CD4: D9         C=B    A	; C gets the size of the object, including the
				; object's body, prolog, and size field. 
61CD6: EB         C=C-D  A	; Subract off the nibbles used up in the 
				; prolog and size field, so C contains the
				; size of the data field of the object. 
61CD8: 8FC5760    GOSBVL 0675C	; Clear C nibbles starting at D1 and 
				; and incrementing.  This just clears out the
				; body of the object.  
61CDF: 132        AD0EX		; Point D0 at the start of the object. 
61CE2: 8D27630    GOVLNG 03672	; Restore regs, Overwrite the level 1 stack
				; entry (a pointer) to point at the newly
				; created object in TEMP0B, and continue RPL. 

; *****************************************************************
; HP: CREATETEMP
06AD8: ; *** MC: A = malloc(C nibbles)  ***                                   
06AD8: 20         P=     0                                                      
06ADA: 818F25     C=C+CON A,6      	; Add 6 nibbles to the amount to
					; allocate.  This leaves room in TEMPOB
					; for a counter indicating the number
					; of nibbles which were allocated, and
					; one nibble for a GC flag (used by
					; the garbage collection routine). 
06AE0: 400        RTNC                                                          
06AE3: ; *** A=malloc(C Nibbles) ***                                            
06AE3: D5         B=C    A		; Number of nibbles to allocate. 
06AE5: 1F97507    D1=HEX 70579          ; saved D1 (RPL stack pointer)          
06AEC: 147        C=DAT1 A                                                      
06AEF: 1F47507    D1=HEX 70574          ; saved B (return stack pointer)        
06AF6: 143        A=DAT1 A                                                      
06AF9: E2         C=C-A  A 		; How many free nibbles are there? 
06AFB: E9         C=C-B  A		; Return with carry if we need to GC.  
06AFD: 400        RTNC                                                          
06B00: ; *** A=malloc(B Nibbles) (C.A=free nibbles) ***                         
06B00: 7A8F       GOSUB  06A8E          ; Let C.A = C.A / 5                     
06B04: 1BE6607    D0=HEX 7066E          ; saved D (free stack space)            
06B0B: 144        DAT0=C A		; Update with the new amount of free 
					; space. 
06B0E: 1BF6507    D0=HEX 7056F          ; D0 gets pointer to top of TEMPOB 
					; memory (grows towards higher 
					; addresses). 
06B15: 146        C=DAT0 A              ; Point D0 at top of TEMPOB memory.
06B18: C9         C=C+B  A              ; Move top of temp memory up by B
					; nibbles, thus allocating storage in
					; the temp object area. 
06B1A: 144        DAT0=C A              ; Update pointer to top of temp mem. 
06B1D: 143        A=DAT1 A  		; Get pointer to top of Return stack.
06B20: 130        D0=A    		; Point D0 to top of return stack. 
06B23: C0         A=A+B  A   		; Return stack gets moved up by B
					; nibbles as well.  This is because the
					; return stack sits on top of tempob,
					; so when tempob grows, the return 
					; stack needs to be pushed up in
					; memory.
06B25: 141        DAT1=A A		; Write new return stack pointer. 
06B28: 131        D1=A			; and point D1 to the NEW top of 
					; return stack. 
06B2B: EE         C=A-C  A 		; C=^top of return stack - ^top of
					; tempob memory.  Thus C= size of 
					; the return address stack. 
06B2D: 788B       GOSUB  066B9 		; Move the return address stack up to 
					; its new location. HP:MOVEUP.
06B31: 160        D0=D0+ 1 		; Point D0 to top of old TEMPOB+1.	
06B34: 1C4        D1=D1- 5 		; Point D1 5 nibbles back from the 
					; top of the new TEMPOB.
06B37: D9         C=B    A		; and write the number of nibbles just
					; allocated into the first 5 nibbles
					; of TEMPOB.  This value is used by
					; the garbage collection routine to
					; navigate through the TEMPOB area.
06B39: 145        DAT1=C A                                                      
06B3C: 03         RTNCC  


; *****************************************************************
; HP: MOVEUP, Block transfer.  Used to move the return address stack UP to 
; its new location after allocating storage in TEMPOB.
; This routine expects:
; D0	; Source pointer.
; D1	; destination pointer.
; C.a	; nibble count.
;
; The loop that does the move/decrement/loop action is heavily optimized for
; speed.  The nibble count is shifted down by a nibble so that they can count
; words and use word-wide moves for speed.  The decrement at the bottom of the
; loop is like this: first it decrements only the bottom byte, then when that 
; rolls over it decrements the next nibble (xs), then when that rolls over, 
; it decrements the top nibble.  Then when the word-count is zero, it finishes
; up the move by moving the excess nibbles.
066B9: CE         C=C-1  A      	; Decrement nibble count. 
066BB: 4C4        GOC    06708		; Branch to end if done. 
066BE: 80D0       P=C    0		; P saves excess nibble count-1 (see
					; below). 
066C2: F6         CSR    A		; C now holds the number of words to 
					; move. 
066C4: CE         C=C-1  A		; Decrement the word count. 
066C6: 442        GOC    066EB		; If we're done with the words, then 
					; continue moving the excess nibbles. 
066C9: 18F        D0=D0- 16		; Decrement the source pointer.
066CC: 1CF        D1=D1- 16		; Decrement the destination pointer.
066CF: 1527       A=DAT0 W     		; Move a word. 
066D3: 1517       DAT1=A W 
066D7: A6E        C=C-1  B		; Decrement the low byte of the
					; word counter. 
066DA: 5EE        GONC   066C9		; Continue until done or until 255 
					; words have been moved. 
066DD: A2E        C=C-1  XS		; Decrement the next higher nibble of 
					; the nibble count... 
066E0: 58E        GONC   066C9		; ...and continue if not done yet. 
066E3: B36        C=C+1  X    		; Else increment the word count. 
066E6: CE         C=C-1  A		; and decrement the next piece of the 
					; count. 
066E8: 50E        GONC   066C9 		; and continue if not done. 
066EB: D2         C=0    A                                                      
066ED: 809        C+P+1 		; C=excess nibble count. 
066F0: 132        AD0EX                                                         
066F3: EA         A=A-C  A		; Decrement source pointer by excess
					; nibbles.  
066F5: 130        D0=A			 
066F8: 133        AD1EX                                                         
066FB: EA         A=A-C  A		; Do the same thing to the destination
					; pointer. 
066FD: 131        D1=A                                                          
06700: 1521       A=DAT0 WP		; Move the excess nibbles. 
06704: 1511       DAT1=A WP             ; ... 
06708: 20         P=     0                                                      
0670A: 03         RTNCC    		; Exit with D0 pointing to the bottom
					; of the old return stack (oldest 
					; return address), and with D1 
					; pointing to the
					; top of the return address stack.


; *****************************************************************
; HP: MOVEDOWN.  See comments on MOVEUP.
0670C: ; *** MC: block copy (D0:src,D1:dst,C.A=nibbles) ***                     
0670C: CE         C=C-1  A		; Decrement 1 from num of nibbles. 
0670E: 494        GOC    06758                                                  
06711: 80D0       P=C    0                                                      
06715: F6         CSR    A  		; Number of 16 nibble words to move. 
06717: CE         C=C-1  A                                                      
06719: 442        GOC    0673E                                                  
0671C: 1527       A=DAT0 W       	; Move a word. 
06720: 1517       DAT1=A W                                                      
06724: 16F        D0=D0+ 16                                                     
06727: 17F        D1=D1+ 16                                                     
0672A: A6E        C=C-1  B		; Decrement.b 
0672D: 5EE        GONC   0671C                                                  
06730: A2E        C=C-1  XS		; decrement... 
06733: 58E        GONC   0671C                                                  
06736: B36        C=C+1  X                                                      
06739: CE         C=C-1  A		; decrement... 
0673B: 50E        GONC   0671C                                                  
0673E: 1521       A=DAT0 WP   		; Move the remaining nibbles. 
06742: 1511       DAT1=A WP                                                     
06746: 136        CD0EX                                                         
06749: 809        C+P+1                                                         
0674C: 134        D0=C                                                          
0674F: 137        CD1EX                                                         
06752: 809        C+P+1                                                         
06755: 135        D1=C                                                          
06758: 20         P=     0                                                      
0675A: 03         RTNCC  



; *****************************************************************
; Previously undocumented.
0675C: AF0        A=0    W                                                      
0675F: CE         C=C-1  A		; Decrement the number of nibbles. 
06761: 453        GOC    06797		; Skip to bottom if done. 
06764: 80D0       P=C    0		; Save excess nibbles-1 in P. 
06768: F6         CSR    A   		; Count words. 
0676A: CE         C=C-1  A  		; Decrement number of words. 
0676C: 4D1        GOC    0678A		; If done, then skip down. 
0676F: 1517       DAT1=A W    		; Else clear a word. 
06773: 17F        D1=D1+ 16   		; Move to next word. 
06776: A6E        C=C-1  B		; Decrement.b the word count. 
06779: 55F        GONC   0676F                                                  
0677C: A2E        C=C-1  XS 		; decrement... 
0677F: 5FE        GONC   0676F                                                  
06782: B36        C=C+1  X                                                      
06785: CE         C=C-1  A 		; decrement... 
06787: 57E        GONC   0676F
0678A: 1511       DAT1=A WP		; Zero out the excess nibbles. 
0678E: 137        CD1EX                                                         
06791: 809        C+P+1			; post-increment D1... 
06794: 135        D1=C                                                          
06797: 20         P=     0                                                      
06799: 03         RTNCC			; ...and return with D1 pointing to the
					; address one higher than the last one
					; cleared.  




From: akcs.sfm@hpcvbbs.cv.hp.com (S.F.Mauser)
Date: Thu, 27 Aug 1992 14:40:02 GMT
Subject: Re: Flight Software from HPCVBBS
Message-ID: <2a9cdd5b.1571.2comp.sys.hp48.1@hpcvbbs.cv.hp.com>