Initial revision
This commit is contained in:
147
lang/cem/libcc/gen/setjmp.e
Normal file
147
lang/cem/libcc/gen/setjmp.e
Normal file
@@ -0,0 +1,147 @@
|
||||
#
|
||||
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
|
||||
Reference in New Issue
Block a user