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.
.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
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);
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 286 |
Nodes: | 16 (2 / 14) |
Uptime: | 91:18:08 |
Calls: | 6,496 |
Calls today: | 7 |
Files: | 12,100 |
Messages: | 5,277,694 |