diff options
Diffstat (limited to 'unix/as.linux64/zsvjmp_c')
-rw-r--r-- | unix/as.linux64/zsvjmp_c | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/unix/as.linux64/zsvjmp_c b/unix/as.linux64/zsvjmp_c new file mode 100644 index 00000000..2b42a0de --- /dev/null +++ b/unix/as.linux64/zsvjmp_c @@ -0,0 +1,170 @@ +/* +# ZSVJMP, ZDOJMP -- Set up a jump (non-local goto) by saving the processor +# registers in the buffer jmpbuf. A subsequent call to ZDOJMP restores +# the registers, effecting a call in the context of the procedure which +# originally called ZSVJMP, but with the new status code. These are Fortran +# callable procedusres. +# +# zsvjmp (jmp_buf, status) # (returns status) +# zdojmp (jmp_buf, status) # (passes status to zsvjmp) +# +# These routines are directly comparable to the UNIX setjmp/longjmp, except +# that they are Fortran callable kernel routines, i.e., trailing underscore, +# call by reference, and no function returns. ZSVJMP requires an assembler +# jacket routine to avoid modifying the call stack, but relies upon setjmp +# to do the real work. ZDOJMP is implemented as a portable C routine in OS, +# calling longjmp to do the restore. In these routines, JMP_BUF consists +# of one longword containing the address of the STATUS variable, followed +# by the "jmp_buf" used by setjmp/longjmp. +*/ + + +#ifdef I386 + +/* +asm("# Set the address of the MEM common to zero."); +asm(".globl mem_"); +asm(" mem_ = 0"); +*/ + +/* +#if defined(MACOSX) +asm(".globl _mem_"); +asm(" _mem_ = 0"); +#endif +*/ + +#if defined(LINUX) +asm(".text"); +asm(".globl zsvjmp_"); +asm("zsvjmp_:"); +asm(" movl 4(%esp), %ecx # &jmpbuf to ECX"); +asm(" movl 8(%esp), %eax # &status to EAX"); +asm(" movl %eax, (%ecx) # store &status in jmpbuf[0]"); +asm(" movl $0, (%eax) # zero the value of status"); +asm(" addl $4, %ecx # change stack to point to &jmpbuf[1]"); +asm(" movl %ecx, 4(%esp) # ..."); +asm(" movl $0, 8(%esp) # change arg2 to zero"); +asm(" jmp __sigsetjmp # let sigsetjmp do the rest"); +#endif /* LINUX */ + +#if (defined(CYGWIN) || defined(MACOSX)) +asm(".text"); +asm(".globl _zsvjmp_"); +asm("_zsvjmp_:"); +asm(" movl 4(%esp), %ecx # &jmpbuf to ECX"); +asm(" movl 8(%esp), %eax # &status to EAX"); +asm(" movl %eax, (%ecx) # store &status in jmpbuf[0]"); +asm(" movl $0, (%eax) # zero the value of status"); +asm(" addl $4, %ecx # change stack to point to &jmpbuf[1]"); +asm(" movl %ecx, 4(%esp) # ..."); +asm(" movl $0, 8(%esp) # change arg2 to zero"); +asm(" jmp _setjmp # let setjmp do the rest"); +#endif /* CYGWIN || MACOSX */ + +#endif /* I386 */ + + +#ifdef X86_64 + +/* +asm("# Set the address of the MEM common to zero."); +asm(".globl mem_"); +asm(" mem_ = 0"); +*/ + +#ifdef SPP_LP64 +/* LP64-SPP */ +asm(".text"); +asm(".globl zsvjmp_"); +asm("zsvjmp_:"); +asm(" # %rsi ... &status %rdi ... &jumpbuf"); +asm(" movq %rsi, (%rdi) # store &status in jmpbuf[0]"); +asm(" movl $0, (%rsi) # zero the value of status"); +asm(" addq $8, %rdi # change point to &jmpbuf[1]"); +asm(" movl $0, %esi # change arg2 to zero"); +asm(" jmp __sigsetjmp # let sigsetjmp do the rest"); +#else +/* ILP64-SPP */ +asm(".text"); +asm(".globl zsvjmp_"); +asm("zsvjmp_:"); +asm(" # %rsi ... &status %rdi ... &jumpbuf"); +asm(" movq %rsi, (%rdi) # store &status in jmpbuf[0]"); +asm(" movq $0, (%rsi) # zero the value of status"); +asm(" addq $8, %rdi # change point to &jmpbuf[1]"); +asm(" movl $0, %esi # change arg2 to zero"); +asm(" jmp __sigsetjmp # let sigsetjmp do the rest"); +#endif + +#endif /* X86_64 */ + + +#ifdef POWERPC + +#if defined(LINUX) +/* +asm(" # Set the address of the MEM common to zero."); +asm(" .globl mem_"); +asm(" mem_ = 0"); +*/ +asm(".text"); +asm(" # ZSVJMP -- SPP callable SETJMP."); +asm(" .align 2"); +asm(" .globl zsvjmp_"); +asm(" .type zsvjmp_,@function"); +asm("zsvjmp_:"); +asm(" # R3 = buf, R4 = &status"); +asm(" li r11,0 # r11 = 0"); +asm(" stw r11,0(r4) # set *status to zero"); +asm(" stw r4,0(r3) # store &status in buf[0]"); +asm(" addi r3,r3,4 # reference buf[1] for sigsetjmp"); +asm(" li r4,0 # zero signal mask for sigsetjmp"); +asm(" b __sigsetjmp"); +#endif /* LINUX */ + +#if defined(MACOSX) +/* +asm(" # Set the address of the MEM common to zero."); +asm(" .globl _mem_"); +asm(" _mem_ = 0"); +*/ +asm(".text"); +asm(" # ZSVJMP -- SPP callable SETJMP."); +asm(" .align 2"); +asm(" .globl _zsvjmp_"); +asm("_zsvjmp_:"); +asm(" # R3 = buf, R4 = &status"); +asm(" li r11,0 # r11 = 0"); +asm(" stw r11,0(r4) # set *status to zero"); +asm(" stw r4,0(r3) # store &status in buf[0]"); +asm(" addi r3,r3,4 # reference buf[1] for setjmp"); +asm(" b L_setjmp$stub"); +asm("L2:"); +asm(" lwz r1,0(r1)"); +asm(" lwz r0,8(r1)"); +asm(" mtlr r0"); +asm(" lmw r30,-8(r1)"); +asm(" blr"); +asm(""); +asm(" # The setjmp code is only available in a dynamic library on 10.1."); +asm(".picsymbol_stub"); +asm("L_setjmp$stub:"); +asm(" .indirect_symbol _setjmp"); +asm(" mflr r0"); +asm(" bcl 20,31,L1$pb"); +asm("L1$pb:"); +asm(" mflr r11"); +asm(" addis r11,r11,ha16(L1$lz-L1$pb)"); +asm(" mtlr r0"); +asm(" lwz r12,lo16(L1$lz-L1$pb)(r11)"); +asm(" mtctr r12"); +asm(" addi r11,r11,lo16(L1$lz-L1$pb)"); +asm(" bctr"); +asm(".lazy_symbol_pointer"); +asm("L1$lz:"); +asm(" .indirect_symbol _setjmp"); +asm(" .long dyld_stub_binding_helper"); +#endif /* MACOSX */ + +#endif /* POWERPC */ |