[9] | 1 | #
|
---|
| 2 | mes 2,_EM_WSIZE,_EM_PSIZE
|
---|
| 3 | ;
|
---|
| 4 | ; layout of a setjmp buffer:
|
---|
| 5 | ;
|
---|
| 6 | ; -----------------
|
---|
| 7 | ; | flag | (!0 when blocked signals saved (POSIX))
|
---|
| 8 | ; -----------------
|
---|
| 9 | ; | signal mask/set | (for Berkeley 4.[2-] / POSIX)
|
---|
| 10 | ; -----------------
|
---|
| 11 | ; | |
|
---|
| 12 | ; | GTO descriptor |
|
---|
| 13 | ; | (SP, LB, PC) |
|
---|
| 14 | ; | |
|
---|
| 15 | ; -----------------
|
---|
| 16 | ;
|
---|
| 17 | ; setjmp saves the signalmask, PC, SP, and LB of caller, and creates a
|
---|
| 18 | ; GTO descriptor from this.
|
---|
| 19 | ; The big problem here is how to get the return address, i.e. the PC of
|
---|
| 20 | ; the caller; This problem is solved by the front-end, which must pass
|
---|
| 21 | ; it as an extra parameter to setjmp.
|
---|
| 22 |
|
---|
| 23 | ; a GTO descriptor must be in the global data area
|
---|
| 24 | gtobuf
|
---|
| 25 | bss 3*_EM_PSIZE,0,0
|
---|
| 26 |
|
---|
| 27 | inp $fill_ret_area
|
---|
| 28 | exp $__setjmp
|
---|
| 29 | pro $__setjmp,0
|
---|
| 30 | #if defined(_POSIX_SOURCE)
|
---|
| 31 | ; save mask of currently blocked signals.
|
---|
| 32 | ; longjmp must restore this mask
|
---|
| 33 | lol _EM_PSIZE ; the flag integer at offset _EM_PSIZE
|
---|
| 34 | lal 0
|
---|
| 35 | loi _EM_PSIZE
|
---|
| 36 | stf 3*_EM_PSIZE+_EM_LSIZE
|
---|
| 37 | lol _EM_PSIZE ; the flag integer at offset _EM_PSIZE
|
---|
| 38 | zeq *1
|
---|
| 39 | lal 0
|
---|
| 40 | loi _EM_PSIZE
|
---|
| 41 | adp 3*_EM_PSIZE
|
---|
| 42 | cal $__newsigset
|
---|
| 43 | asp _EM_PSIZE
|
---|
| 44 | 1
|
---|
| 45 | #elif defined(__BSD4_2)
|
---|
| 46 | loc 0
|
---|
| 47 | cal $sigblock
|
---|
| 48 | asp _EM_WSIZE
|
---|
| 49 | lfr _EM_WSIZE
|
---|
| 50 | lal 0
|
---|
| 51 | loi _EM_PSIZE
|
---|
| 52 | stf 3*_EM_PSIZE
|
---|
| 53 | #endif
|
---|
| 54 | ; create GTO descriptor for longjmp
|
---|
| 55 | lxl 0
|
---|
| 56 | dch ; Local Base of caller
|
---|
| 57 | lxa 0 ; Stackpointer of caller
|
---|
| 58 | lal _EM_PSIZE+_EM_WSIZE
|
---|
| 59 | loi _EM_PSIZE ; Return address of caller
|
---|
| 60 | lal 0
|
---|
| 61 | loi _EM_PSIZE ; address of jmpbuf
|
---|
| 62 | sti 3*_EM_PSIZE ; LB, SP, and PC stored in jmpbuf
|
---|
| 63 | loc 0
|
---|
| 64 | ret _EM_WSIZE ; setjmp must return 0
|
---|
| 65 | end 0
|
---|
| 66 |
|
---|
| 67 | pro $fill_ret_area,0
|
---|
| 68 | ; put argument in function result area
|
---|
| 69 | lol 0
|
---|
| 70 | ret _EM_WSIZE
|
---|
| 71 | end 0
|
---|
| 72 |
|
---|
| 73 | exp $longjmp
|
---|
| 74 | pro $longjmp,?
|
---|
| 75 | #if defined(_POSIX_SOURCE)
|
---|
| 76 | ; restore blocked mask
|
---|
| 77 | lal 0
|
---|
| 78 | loi _EM_PSIZE
|
---|
| 79 | lof 3*_EM_PSIZE+_EM_LSIZE
|
---|
| 80 | zeq *2
|
---|
| 81 | lal 0
|
---|
| 82 | loi _EM_PSIZE
|
---|
| 83 | adp 3*_EM_PSIZE
|
---|
| 84 | cal $__oldsigset
|
---|
| 85 | asp _EM_PSIZE
|
---|
| 86 | 2
|
---|
| 87 | #elif defined(__BSD4_2)
|
---|
| 88 | ; restore signal mask
|
---|
| 89 | lal 0
|
---|
| 90 | loi _EM_PSIZE
|
---|
| 91 | lof 3*_EM_PSIZE
|
---|
| 92 | cal $_sigsetmask
|
---|
| 93 | asp _EM_WSIZE
|
---|
| 94 | lfr _EM_WSIZE
|
---|
| 95 | asp _EM_WSIZE
|
---|
| 96 | #endif
|
---|
| 97 | lal 0
|
---|
| 98 | loi _EM_PSIZE ; address of jmpbuf
|
---|
| 99 | lae gtobuf
|
---|
| 100 | blm 3*_EM_PSIZE ; fill GTO descriptor from jmpbuf
|
---|
| 101 | lol _EM_PSIZE ; second parameter of longjmp: the return value
|
---|
| 102 | dup _EM_WSIZE
|
---|
| 103 | zne *3
|
---|
| 104 | ; of course, longjmp may not return 0!
|
---|
| 105 | inc
|
---|
| 106 | 3
|
---|
| 107 | ; put return value in function result area
|
---|
| 108 | cal $fill_ret_area
|
---|
| 109 | asp _EM_WSIZE
|
---|
| 110 | gto gtobuf ; there we go ...
|
---|
| 111 | ; ASP and GTO do not damage function result area
|
---|
| 112 | end 0
|
---|