From 536716ba84ace7af9a41d1183325c27fa0c73f9e Mon Sep 17 00:00:00 2001 From: ceriel Date: Wed, 20 Apr 1988 15:33:17 +0000 Subject: [PATCH] rewritten setjmp: compiler now gives a bit more support --- lang/cem/libcc/gen/setjmp.e | 203 ++++++++++++++---------------------- 1 file changed, 80 insertions(+), 123 deletions(-) diff --git a/lang/cem/libcc/gen/setjmp.e b/lang/cem/libcc/gen/setjmp.e index f9137590b..8bc5af41f 100644 --- a/lang/cem/libcc/gen/setjmp.e +++ b/lang/cem/libcc/gen/setjmp.e @@ -1,161 +1,118 @@ # mes 2,EM_WSIZE,EM_PSIZE - exp $setjmp - pro $setjmp,3*EM_WSIZE +; +; layout of a setjmp buffer: +; +; ----------------- +; | signal mask | (only for Berkeley 4.2) +; ----------------- +; | PC of caller | +; ----------------- +; | | +; | GTO descriptor | +; | (SP, LB, PC) | +; | | +; ----------------- +; +; setjmp saves the signalmask, PC, SP, and LB of caller, and creates a +; GTO descriptor with a program counter indicating a piece of code that +; gets the return value right before jumping to the caller of setjmp in +; the setjmp buffer, which has a layout as displayed above. +; The big problem here is how to het the return address, i.e. the PC of +; the caller; This problem is solved by the front-end, which must pass +; it as an extra parameter to setjmp. -; 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. +gtobuf + bss 3*EM_PSIZE,0,0 +retval + bss EM_WSIZE,0,0 +jmpbuf_addr + bss EM_PSIZE,0,0 + inp $fill_ret_area + exp $setjmp + pro $setjmp,0 + mes 11 #ifdef __BSD4_2 loc 0 cal $sigblock asp EM_WSIZE lfr EM_WSIZE - stl -3*EM_WSIZE -#endif - 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 + stf 4*EM_PSIZE +#endif + ; create GTO descriptor for longjmp + lxl 0 + dch ; Local Base of caller + lxa 0 ; Stackpointer of caller +.1 + rom *1 + lae .1 + loi EM_PSIZE ; where the longjmp ends up lal 0 loi EM_PSIZE - adp 2*EM_PSIZE - sti EM_WSIZE ; and also in the buffer - lal 0 + sti 3*EM_PSIZE ; stored in jmpbuf + ; also save return address, which has been supplied by the compiler + lal EM_PSIZE 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 + adp 3*EM_PSIZE + sti EM_PSIZE loc 0 ret EM_WSIZE - end 3*EM_WSIZE - - exp $longjmp - pro $longjmp,3*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 + ; so, the longjmp returns here. + ; now, create a GTO descriptor for the final GTO + lae jmpbuf_addr 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 + adp 3*EM_PSIZE loi EM_PSIZE - loi EM_PSIZE ; push saved StackPointer - lol EM_PSIZE ; push value to be returned by longjmp - lal 0 + lae gtobuf + sti EM_PSIZE ; this is the return address + lae jmpbuf_addr 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 + loi 2*EM_PSIZE + lae gtobuf+EM_PSIZE + sti 2*EM_PSIZE ; that's it, the GTO descriptor is ready; + ; now take care of the return value ... + cal $fill_ret_area + gto gtobuf ; there we go ... + end 0 + + pro $fill_ret_area,0 + loe retval + ret EM_WSIZE + end 0 + + exp $longjmp + pro $longjmp,? 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 #ifdef __BSD4_2 - lol -3*EM_WSIZE + dup EM_PSIZE + lof 4*EM_PSIZE cal $sigsetmask asp EM_WSIZE lfr EM_WSIZE asp EM_WSIZE #endif - lol -EM_WSIZE + lae jmpbuf_addr + sti EM_PSIZE ; save address of jmpbuf + lol EM_PSIZE dup EM_WSIZE zne *3 ; of course, longjmp may not return 0! asp EM_WSIZE loc 1 3 - ret EM_WSIZE - end 3*EM_WSIZE + ste retval ; save return value + lal 0 + loi EM_PSIZE + lae gtobuf + blm 3*EM_PSIZE ; create GTO descriptor + gto gtobuf ; and GTO + end 0 -- 2.34.1