147 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			147 lines
		
	
	
	
		
			3.4 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
| #
 | |
|  mes 2,EM_WSIZE,EM_PSIZE
 | |
| 
 | |
|  exp $setjmp
 | |
|  pro $setjmp,2*EM_WSIZE
 | |
| 
 | |
| ; setjmp saves the StackPointer and the LocalBase, and the chunk of
 | |
| ; memory between the StackPointer and the ArgumentBase, + its size in a
 | |
| ; buffer, pointed to by the parameter.
 | |
| ; longjump can then restore this buffer and return.
 | |
| ; Notice that this does not work on EM implementations in which every
 | |
| ; procedure frame has a different fragment in memory, because in this case
 | |
| ; the ArgumentBase will point into the fragment of the caller.
 | |
| ; What really is needed is a way to find out the size of the return
 | |
| ; status block.
 | |
| ; On EM-implementations in which the stack grows upwards it is untested,
 | |
| ; as there are no such implementations available now.
 | |
| ; This implementation of setjmp/longjmp
 | |
| ; depends on the assumption that the routine calling
 | |
| ; setjmp does not have register variables, and that it saves all registers
 | |
| ; that are available for variables.
 | |
| 
 | |
|  loc 0
 | |
|  stl -2*EM_WSIZE
 | |
|  lor 1		; load StackPointer
 | |
|  lal 0
 | |
|  loi EM_PSIZE
 | |
|  sti EM_PSIZE	; save it
 | |
|  lxl 0		; load LocalBase
 | |
|  lal 0
 | |
|  loi EM_PSIZE
 | |
|  adp EM_PSIZE
 | |
|  sti EM_PSIZE	; save it
 | |
|  lxa 0		; load ArgumentBase
 | |
|  lal 0
 | |
|  loi EM_PSIZE
 | |
|  loi EM_PSIZE	; load saved StackPointer
 | |
|  sbs EM_WSIZE	; gives size of block that is to be saved, or negative size
 | |
|  dup EM_WSIZE
 | |
|  zgt *5
 | |
|  ngi EM_WSIZE
 | |
|  loc 1
 | |
|  stl -2*EM_WSIZE; one if the stack grows upwards
 | |
| 5
 | |
|  stl -EM_WSIZE	; save size of block in local
 | |
|  lol -EM_WSIZE
 | |
|  lal 0
 | |
|  loi EM_PSIZE
 | |
|  adp 2*EM_PSIZE
 | |
|  sti EM_WSIZE	; and also in the buffer
 | |
|  lal 0
 | |
|  loi EM_PSIZE
 | |
|  loi EM_PSIZE	; load saved StackPointer
 | |
|  lol -2*EM_WSIZE; positive if the stack grows upwards
 | |
|  zle *6
 | |
|  asp EM_PSIZE
 | |
|  lxa 0
 | |
|  adp EM_WSIZE	; in this case the source address = ArgumentBase+EM_WSIZE
 | |
| 6
 | |
|  lal 0
 | |
|  loi EM_PSIZE
 | |
|  adp 2*EM_PSIZE+EM_WSIZE
 | |
| 		; destination address
 | |
|  lol -EM_WSIZE	; count
 | |
|  bls EM_WSIZE	; block copy
 | |
|  loc 0
 | |
|  ret EM_WSIZE
 | |
|  end 2*EM_WSIZE
 | |
| 
 | |
|  exp $longjmp
 | |
|  pro $longjmp,2*EM_WSIZE
 | |
| 
 | |
| ; first, find out wether the stack grows upwards
 | |
|  loc 0
 | |
|  stl -2*EM_WSIZE
 | |
|  lxa 0
 | |
|  lxl 0
 | |
|  cmp
 | |
|  zge *7
 | |
|  loc 1
 | |
|  stl -2*EM_WSIZE; this local contains 1 if it does, otherwise it contains 0
 | |
| 7
 | |
| ; then, adjust StackPointer until it is below the saved StackPointer (or
 | |
| ; above if it grows upwards)
 | |
| ; then push parameters
 | |
| ; then copy the saved block in its proper place
 | |
| ; notice that the parameters can not be used anymore now
 | |
| ; then restore the LocalBase and the Stackpointer and return.
 | |
| 1
 | |
|  loc 0
 | |
| 2
 | |
|  lor 1
 | |
|  lal 0
 | |
|  loi EM_PSIZE
 | |
|  loi EM_PSIZE	; saved StackPointer
 | |
|  cmp		; compare with current one
 | |
|  lol -2*EM_WSIZE
 | |
|  zle *8
 | |
|  zlt *1
 | |
|  bra *10
 | |
| 8
 | |
|  zgt *1
 | |
| 10
 | |
|  lal 0
 | |
|  loi EM_PSIZE
 | |
|  loi EM_PSIZE	; push saved StackPointer
 | |
|  lol EM_PSIZE	; push value to be returned by longjmp
 | |
|  lal 0
 | |
|  loi EM_PSIZE
 | |
|  adp EM_PSIZE
 | |
|  loi EM_PSIZE	; push saved LocalBase
 | |
|  lal 0
 | |
|  loi EM_PSIZE
 | |
|  adp 2*EM_PSIZE+EM_WSIZE
 | |
| 		; source address
 | |
|  lal 0
 | |
|  loi EM_PSIZE
 | |
|  loi EM_PSIZE	; saved stackpointer
 | |
|  lol -2*EM_WSIZE
 | |
|  zle *9		; if not positive, this is the destination address,
 | |
| 		; otherwise subtract the size of the saved area and add EM_WSIZE
 | |
|  adp EM_WSIZE
 | |
|  lal 0
 | |
|  loi EM_PSIZE
 | |
|  adp 2*EM_PSIZE
 | |
|  loi EM_WSIZE
 | |
|  ngi EM_WSIZE
 | |
|  ads EM_WSIZE
 | |
| 9		; destination address
 | |
|  lal 0
 | |
|  loi EM_PSIZE
 | |
|  adp 2*EM_PSIZE
 | |
|  loi EM_WSIZE	; size
 | |
|  bls EM_WSIZE	; now we have a frame exactly as it was in setjmp,
 | |
| 		; and exactly at the same place
 | |
|  str 0		; restore LocalBase
 | |
|  stl -EM_WSIZE	; saves the return value
 | |
|  str 1		; restores the StackPointer
 | |
|  lol -EM_WSIZE
 | |
|  dup EM_WSIZE
 | |
|  zne *3
 | |
| 		; of course, longjmp may not return 0!
 | |
|  asp EM_WSIZE
 | |
|  loc 1
 | |
| 3
 | |
|  ret EM_WSIZE
 | |
|  end 2*EM_WSIZE
 |