[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Help needed for small assembler script for the iraf package



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 <olebole@debian.org> 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
> 


Reply to: