Hi James, great, thank you very much! This was the most important missing piece!
Is there an ia64 machine available where I could test the package? Best regards Ole On 02.06.19 00:57, James Clarke wrote: > On 1 Jun 2019, at 15:37, Ole Streicher <[email protected]> wrote: >> >> Dear Itanium specialists, >> >> A while ago, I got the "IRAF" package accepted into Debian [1]. Although >> the code is claimed to be portable, it needs a piece of assembler >> code for each platform that provides a (sort of) setjmp() to their >> Fortran variant. >> >> A "C" implementation for this looks like: >> >> #include <setjmp.h> >> >> int zsvjmp_( long *buf, long *status ) { >> *status = 0; >> ((long **)buf)[0] = status; >> return sigsetjmp ((void *)((long **)buf+1),0); >> } >> >> however this does not work, since the "sigsetjmp" call needs to be >> replaced by a jump to sigsetjmp instead. >> >> There is already some working code for x64 in the original distribution: >> >> -------------------------------8<----------------------------------- >> .file "zsvjmp.s" >> .globl zsvjmp_ >> .type zsvjmp_, @function >> >> zsvjmp_: >> # %rsi ... &status %rdi ... &jumpbuf >> movq %rsi, (%rdi) # store &status in jmpbuf[0] >> movl $0, (%rsi) # zero the value of status >> addq $8, %rdi # change point to &jmpbuf[1] >> movl $0, %esi # change arg2 to zero >> jmp __sigsetjmp@PLT # let sigsetjmp do the rest >> >> .section .note.GNU-stack,"",@progbits >> -------------------------------8<----------------------------------- >> >> The "zdojmp" counterpart is a portable C function. >> >> I created a small repository [2] that contains the assembler I collected >> so far as well as two test programs. >> >> However, I have no idea how to write the same for the ia64 platform. >> Maybe someone could help me here? Preferably under the IRAF >> license [3], so that it can be included upstream later. >> >> One way that worked for x32 and for arm64 was to compule the C snipped >> above (having the sigsetjmp function name by something else) with an >> optimizing compiler; however I didn't find cross compiler with the ia64 >> target? >> >> There is no request from the users to have this ported to ia64, and I >> doubt that ever will. My main motivation to get it ported is to check >> the package for hidden problems on "unusual" architectures. > > Hi, > Managed to get this to work, with one caveat (explained afterwards): > >> >> .file "zsvjmp.s" >> .explicit >> .text >> .align 64 >> .global zsvjmp_# >> .type zsvjmp_#, @function >> .proc zsvjmp_# >> zsvjmp_: >> # Normally, tail calls to a different shared object are forbidden, >> since a >> # function in our shared object can call us without needing to >> save/restore >> # its gp register, but if we tail call a function outside the shared >> object >> # then the PLT stub will clobber gp. However, since we're writing this >> in >> # assembly in its own file, the compiler shouldn't be able to prove that >> # any callers are in the same shared object as us, and therefore will be >> # forced to pessimistically spill gp, so we should be safe to break the >> ABI >> # and let gp be trashed by our tail call. >> >> st8 [r33] = r0 >> st8 [r32] = r33, 16 >> ;; >> mov r33 = r0 >> br.cond.sptk.many __sigsetjmp# >> .endp zsvjmp_# >> .section .note.GNU-stack,"",@progbits > > The caveat is that IA-64 has 128-bit floats saved as part of setjmp/longjmp, > and these must be aligned, so the entire jmp_buf must be 16-byte aligned. > Moreover, since zsvjmp_ uses the first long (8 bytes) of the buffer for its > status pointer, the second long now also needs to be reserved so we maintain > the alignment when passing it to __sigsetjmp. Thus, I needed to make two > changes to your test code on IA-64, which will need to be mirrored in the > actual Fortran callers (I didn't change jmptest.f, it just works by chance): > >> diff --git a/zdojmp.c b/zdojmp.c >> index 547d739..093d350 100644 >> --- a/zdojmp.c >> +++ b/zdojmp.c >> @@ -11,7 +11,7 @@ >> void zdojmp_ (long *jmpbuf, long *status) { >> int stat = *status ? *status : 1; >> long *status_ptr = ((long **)jmpbuf)[0]; >> - void *jb = (long **)jmpbuf+1; >> + void *jb = (long **)jmpbuf+2; >> *status_ptr = stat; >> siglongjmp (jb, stat); >> } >> diff --git a/zzdebug.c b/zzdebug.c >> index 824b3e3..1f350e5 100644 >> --- a/zzdebug.c >> +++ b/zzdebug.c >> @@ -6,7 +6,7 @@ void zsvjmp_(void*, volatile long *); >> void zdojmp_(void*, volatile long *); >> >> int main(void) { >> - long jmpbuf[180]; >> + long jmpbuf[180] __attribute__((__aligned__(16))); >> volatile long status = 9; >> volatile long step = 0; >> zsvjmp_((void *)jmpbuf, &status); > > > Regards, > James >

