diff --git a/ChangeLog b/ChangeLog index eda04ef..f932b24 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,120 @@ +2022-02-12 Bruno Haible + + loongarch: Fix gcc installation. + * cross-tools/cross.conf (loongarch64): Change gcc version to match what + it actually reports. + +2022-02-12 Bruno Haible + + Fix cross-tools build. + * cross-tools/cross-build.sh (func_build_gcc): Set LD_LIBRARY_PATH, so + that libisl.so.15 gets found during installation. + +2022-02-12 Bruno Haible + + loongarch: Allow for continuous integration. + * cross-tools/cross-build.sh (func_build_gcc): Download fork tarball + from alpha.gnu.org. Adjust installation completeness test. + * cross-tools/cross.conf (loongarch64): Use binutils 2.38. + +2022-01-16 Bruno Haible + + loongarch: Add support for loongarch64 ABI. + * cross-tools/cross-build.sh (func_build_binutils): Add support for + newer binutils snapshots. + (func_build_gcc): Add support for GCC 10 and newer. + * cross-tools/cross.conf: Add configuration for loongarch64 cross tools. + * porting-tools/abis/call-used-registers.txt: Add info about + loongarch64. + * porting-tools/abis/reg-struct-return.txt: Likewise. + * porting-tools/abis/stack-frame.txt: Likewise. Some more tweaks. + * porting-tools/execstack/voidfunc.c: Add command for loongarch64. + * porting-tools/execstack/voidfunc-loongarch64.o: New generated file. + * porting-tools/execstack/main.c (voidfunc): Define also for loongarch. + * porting-tools/execstack/README: Add info about loongarch64. + * ffcall-abi.h: Add support for loongarch64-lp64. + * common/asm-loongarch.sh: New file. + * Makefile.in (SOURCE_FILES): Add it. + * avcall/avcall.h (__AV_STRUCT_RETURN, __AV_REGISTER_STRUCT_RETURN): Add + code for __loongarch64. + * avcall/avcall-alist.h (__av_alist): Likewise. + * avcall/avcall-internal.h: Add code for __loongarch64, especially + __av_start1, __av_reg_struct_return, __av_start_struct4, __av_word, + __av_long, __av_ulong, __av_ptr, __av_longlong, __av_ulonglong, + _av_float, _av_double, __av_struct. + * avcall/avcall-loongarch64.c: New file, based on + avcall/avcall-riscv64.c. + * avcall/Makefile.devel (avcall-loongarch64-linux.s, + avcall-loongarch64-macro.S): New targets. + * avcall/Makefile.in (avcall-loongarch64.lo, avcall-loongarch64.s): New + targets. + (clean): Remove avcall-loongarch64.s. + (SOURCE_FILES): Add avcall-loongarch64.c, avcall-loongarch64-linux.s, + avcall-loongarch64-macro.S. + * vacall/vacall.h (__VA_STRUCT_RETURN, __VA_REGISTER_STRUCT_RETURN): Add + code for __loongarch64. + * vacall/vacall-internal.h: Add code for __loongarch64, especially + __va_alist, __va_reg_struct_return, __va_start_struct2, + __va_arg_leftadjusted, __va_arg_adjusted, _va_arg_longlong, + _va_arg_ulonglong, __va_align_double, _va_arg_float, _va_arg_double, + __va_arg_struct, _va_return_longlong. + * vacall/vacall-loongarch64.c: New file, based on + vacall/vacall-riscv64.c. + * vacall/Makefile.devel (vacall-loongarch64-linux.s, + vacall-loongarch64-macro.S): New targets. + * vacall/Makefile.in (vacall-loongarch64.@OBJEXT@, + vacall-loongarch64.s): New targets. + (clean): Remove vacall-loongarch64.s. + (SOURCE_FILES): Add vacall-loongarch64.c, vacall-loongarch64-linux.s, + vacall-loongarch64-macro.S. + * callback/vacall_r/vacall_r.h (__VA_STRUCT_RETURN, + __VA_REGISTER_STRUCT_RETURN): Add code for __loongarch64. + * callback/vacall_r/Makefile.devel (vacall-loongarch64-linux.s, + vacall-loongarch64-macro.S): New targets. + * callback/vacall_r/Makefile.in (vacall-loongarch64.lo, + vacall-loongarch64.s): New targets. + (clean): Remove vacall-loongarch64.s. + (SOURCE_FILES): Add vacall-loongarch64-linux.s, + vacall-loongarch64-macro.S. + * trampoline/Makefile.devel (proto-loongarch64.s, tramp-loongarch64.o): + New targets. + * trampoline/proto-loongarch64.s: New generated file. + * trampoline/tramp-loongarch64.s: New file. + * trampoline/tramp-loongarch64.o: New generated file. + * trampoline/trampoline.c: Implement for __loongarch64. + * callback/trampoline_r/Makefile.devel (proto-loongarch64.s, + tramp-loongarch64.o): New targets. + * callback/trampoline_r/proto64.c: Add code for __loongarch64. + * callback/trampoline_r/proto-loongarch64.s: New generated file. + * callback/trampoline_r/tramp-loongarch64.s: New file. + * callback/trampoline_r/tramp-loongarch64.o: New generated file. + * callback/trampoline_r/trampoline.c: Implement for __loongarch64. + * callback/trampoline_r/test1.c: Add support for __loongarch64. + * PLATFORMS, */PLATFORMS: List the 64-bit LoongArch ABI. + * NEWS: Mention the new port. + +2022-01-16 Bruno Haible + + Simplify. + * callback/vacall_r/Makefile.in (vacall-alpha.s, vacall-powerpc.s, + vacall-s390.lo, vacall-s390x.s, vacall-riscv32-ilp32d.s, + vacall-riscv64-lp64d.s): Don't use -I options during preprocessing. + +2021-06-26 Bruno Haible + + x86_64: Create a read-only .eh_frame section on all platforms. + Reported by Thomas Klausner at + . + * common/asm-x86_64.h (EH_FRAME_SECTION): Use flags "a" (instead of + "aw") on all platforms. + +2021-06-13 Bruno Haible + + maint: Don't require an internet connection for running autogen.sh. + * libtool-patches: New directory. + * Makefile.maint (libtool-imported-files): Don't call wget. Take the + patches from libtool-patches/ instead. + 2021-06-13 Bruno Haible Prepare for 2.4 release. diff --git a/Makefile.in b/Makefile.in index 05a83dd..2a74ecc 100644 --- a/Makefile.in +++ b/Makefile.in @@ -151,6 +151,7 @@ SOURCE_FILES = \ common/asm-hppa.sh common/asm-hppa.h \ common/asm-hppa64.sh common/asm-hppa64.h \ common/asm-i386.sh common/asm-i386.h \ + common/asm-loongarch.sh \ common/asm-m68k.sh common/asm-m68k.h \ common/asm-mips.sh common/asm-mips.h \ common/asm-powerpc.sh \ diff --git a/NEWS b/NEWS index 5911682..af1dc48 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,9 @@ +New in 2.5: + +* Added support for the following platforms: + (Previously, a build on these platforms failed.) + - loongarch64: Linux with lp64d ABI. + New in 2.4: * Added support for the following platforms: diff --git a/PLATFORMS b/PLATFORMS index b7dc0c8..ca5a53c 100644 --- a/PLATFORMS +++ b/PLATFORMS @@ -49,4 +49,5 @@ Supported CPUs: (Put the GNU config.guess values here.) s390x s390x-ibm-linux (gcc) riscv32 riscv32-unknown-linux (gcc -mabi=ilp32d) riscv64 riscv64-unknown-linux (gcc -mabi=lp64d) + loongarch64 loongarch64-unknown-linux (gcc) diff --git a/avcall/Makefile.devel b/avcall/Makefile.devel index db392b6..2933060 100644 --- a/avcall/Makefile.devel +++ b/avcall/Makefile.devel @@ -25,7 +25,8 @@ precompiled : \ avcall-ia64-macro.S \ avcall-x86_64-macro.S avcall-x86_64-x32-linux.s avcall-x86_64-windows-macro.S \ avcall-s390-macro.S avcall-s390x-macro.S \ - avcall-riscv32-ilp32d-macro.S avcall-riscv64-lp64d-macro.S + avcall-riscv32-ilp32d-macro.S avcall-riscv64-lp64d-macro.S \ + avcall-loongarch64-macro.S avcall-i386-linux.s : avcall-i386.c avcall-internal.h avcall.h avcall-alist.h $(THISFILE) @@ -242,6 +243,13 @@ avcall-riscv64-lp64d-macro.S : avcall-riscv64-lp64d-linux.s ../common/asm-riscv. (../common/asm-riscv.sh < avcall-riscv64-lp64d-linux.s ; cat ../common/noexecstack.h) > avcall-riscv64-lp64d-macro.S +avcall-loongarch64-linux.s : avcall-loongarch64.c avcall-internal.h avcall.h avcall-alist.h $(THISFILE) + $(CROSS_TOOL) loongarch64-linux gcc $(GCCFLAGS) -D__loongarch64 -S avcall-loongarch64.c -o avcall-loongarch64-linux.s + +avcall-loongarch64-macro.S : avcall-loongarch64-linux.s ../common/asm-loongarch.sh ../common/noexecstack.h $(THISFILE) + (../common/asm-loongarch.sh < avcall-loongarch64-linux.s ; cat ../common/noexecstack.h) > avcall-loongarch64-macro.S + + # --------------- Rules for debugging test failures --------------- tests : tests-i386.s tests-m68k.s tests-mips.s tests-sparc.s tests-alpha.s tests-hppa.s tests-arm.s tests-powerpc.s tests-ia64.s tests-x86_64.s diff --git a/avcall/Makefile.in b/avcall/Makefile.in index 466023d..b78ba78 100644 --- a/avcall/Makefile.in +++ b/avcall/Makefile.in @@ -258,6 +258,12 @@ avcall-riscv64-lp64d.lo : avcall-riscv64-lp64d.s avcall-riscv64-lp64d.s : $(srcdir)/avcall-riscv64-lp64d-macro.S $(CPP) $(ASPFLAGS) $(srcdir)/avcall-riscv64-lp64d-macro.S | grep -v '^ *#line' | grep -v '^#' | sed -e 's,% ,%,g' -e 's,//.*$$,,' > avcall-riscv64-lp64d.s +avcall-loongarch64.lo : avcall-loongarch64.s + $(LIBTOOL_COMPILE) $(CC) @GCC_X_NONE@ -c avcall-loongarch64.s + +avcall-loongarch64.s : $(srcdir)/avcall-loongarch64-macro.S + $(CPP) $(ASPFLAGS) $(srcdir)/avcall-loongarch64-macro.S | grep -v '^ *#line' | grep -v '^#' | sed -e 's,% ,%,g' -e 's,//.*$$,,' > avcall-loongarch64.s + avcall-libapi.lo : $(srcdir)/avcall-libapi.c ../config.h $(srcdir)/avcall-internal.h $(srcdir)/avcall.h $(srcdir)/avcall-alist.h $(LIBTOOL_COMPILE) $(CC) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) @DISABLE_TYPE_BASED_ALIASING@ -c $(srcdir)/avcall-libapi.c @@ -353,7 +359,7 @@ mostlyclean : clean clean : force $(RM) *.@OBJEXT@ *.lo *.a libavcall.* core - $(RM) avcall-i386.s avcall-sparc.s avcall-sparc64.s avcall-m68k.s avcall-mips.s avcall-mipsn32.s avcall-mips64.s avcall-alpha.s avcall-hppa.s avcall-hppa64.s avcall-arm.s avcall-armhf.s avcall-arm64.s avcall-powerpc.s avcall-powerpc64.s avcall-powerpc64-elfv2.s avcall-ia64.s avcall-x86_64.s avcall-x86_64.asm avcall-x86_64-x32.s avcall-s390.s avcall-s390x.s avcall-riscv32-ilp32d.s avcall-riscv64-lp64d.s + $(RM) avcall-i386.s avcall-sparc.s avcall-sparc64.s avcall-m68k.s avcall-mips.s avcall-mipsn32.s avcall-mips64.s avcall-alpha.s avcall-hppa.s avcall-hppa64.s avcall-arm.s avcall-armhf.s avcall-arm64.s avcall-powerpc.s avcall-powerpc64.s avcall-powerpc64-elfv2.s avcall-ia64.s avcall-x86_64.s avcall-x86_64.asm avcall-x86_64-x32.s avcall-s390.s avcall-s390x.s avcall-riscv32-ilp32d.s avcall-riscv64-lp64d.s avcall-loongarch64.s $(RM) -r .libs _libs $(RM) minitests.@OBJEXT@ minitests.s minitests minitests.out $(RM) minitests-c++.@OBJEXT@ minitests-c++ minitests-c++.out @@ -381,6 +387,7 @@ SOURCE_FILES = \ avcall-hppa64.c avcall-hppa64-linux.s avcall-hppa64-macro.S \ avcall-i386.c avcall-i386-linux.s avcall-i386-macro.S \ avcall-ia64.c avcall-ia64-linux.s avcall-ia64-macro.S \ + avcall-loongarch64.c avcall-loongarch64-linux.s avcall-loongarch64-macro.S \ avcall-m68k.c avcall-m68k-linux.s avcall-m68k-sun.s avcall-m68k.mit.S avcall-m68k.motorola.S \ avcall-mips.c avcall-mipseb-linux.s avcall-mipsel-linux.s avcall-mipseb-macro.S avcall-mipsel-macro.S \ avcall-mipsn32.c avcall-mipsn32eb-linux.s avcall-mipsn32el-linux.s avcall-mipsn32eb-macro.S avcall-mipsn32el-macro.S \ diff --git a/avcall/PLATFORMS b/avcall/PLATFORMS index a823a51..5fcb26a 100644 --- a/avcall/PLATFORMS +++ b/avcall/PLATFORMS @@ -78,4 +78,5 @@ Supported CPUs: (Put the GNU config.guess values here.) s390x s390x-ibm-linux (gcc) emulated Linux riscv32 riscv32-unknown-linux (gcc -mabi=ilp32d) emulated Linux riscv64 riscv64-unknown-linux (gcc -mabi=lp64d) emulated Linux + loongarch64 loongarch64-unknown-linux (gcc) Loongson Linux diff --git a/avcall/avcall-alist.h b/avcall/avcall-alist.h index 797f730..0574055 100644 --- a/avcall/avcall-alist.h +++ b/avcall/avcall-alist.h @@ -1,6 +1,6 @@ /* * Copyright 1993-1995 Bill Triggs - * Copyright 1995-2021 Bruno Haible + * Copyright 1995-2022 Bruno Haible * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -197,7 +197,7 @@ typedef struct float fargs[__AV_FARG_NUM]; double dargs[__AV_FARG_NUM]; #endif -#if defined(__riscv32__) || defined(__riscv64__) +#if defined(__riscv32__) || defined(__riscv64__) || defined(__loongarch64) #define __AV_FARG_NUM 8 /* store the floating-point arguments in an extra array */ unsigned int fanum; /* number of fargs[] words that are occupied so far */ diff --git a/avcall/avcall-internal.h b/avcall/avcall-internal.h index c878134..72de32e 100644 --- a/avcall/avcall-internal.h +++ b/avcall/avcall-internal.h @@ -1,6 +1,6 @@ /* * Copyright 1993-1995 Bill Triggs - * Copyright 1995-2021 Bruno Haible + * Copyright 1995-2022 Bruno Haible * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -111,7 +111,7 @@ typedef int __av_alist_verify[2*(__AV_ALIST_SIZE_BOUND - (int)sizeof(__av_alist) (LIST).farg_mask = 0, \ (LIST).darg_mask = 0, #endif -#if defined(__riscv32__) || defined(__riscv64__) +#if defined(__riscv32__) || defined(__riscv64__) || defined(__loongarch64) #define __av_start1(LIST,LIST_ARGS_END) \ (LIST).aptr = &(LIST).args[0], \ (LIST).fanum = 0, \ @@ -262,7 +262,7 @@ typedef int __av_alist_verify[2*(__AV_ALIST_SIZE_BOUND - (int)sizeof(__av_alist) #define __av_start_struct3(LIST) \ ((LIST).flags |= __AV_REGISTER_STRUCT_RETURN, 0) #endif -#if defined(__hppa64__) || defined(__arm64__) || (defined(__powerpc64__) && defined(__powerpc64_elfv2__)) || defined(__x86_64_sysv__) || defined(__riscv64__) +#if defined(__hppa64__) || defined(__arm64__) || (defined(__powerpc64__) && defined(__powerpc64_elfv2__)) || defined(__x86_64_sysv__) || defined(__riscv64__) || defined(__loongarch64) #define __av_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE) \ ((TYPE_SIZE) <= 16) /* Turn on __AV_REGISTER_STRUCT_RETURN if __AV_SMALL_STRUCT_RETURN was set @@ -287,7 +287,7 @@ typedef int __av_alist_verify[2*(__AV_ALIST_SIZE_BOUND - (int)sizeof(__av_alist) #endif /* Return structure pointer is passed as first arg. */ -#if defined(__i386__) || defined(__alpha__) || (defined(__arm__) && !defined(__armhf__)) || defined(__powerpc_aix__) || defined(__powerpc64__) || defined(__riscv32__) || defined(__riscv64__) +#if defined(__i386__) || defined(__alpha__) || (defined(__arm__) && !defined(__armhf__)) || defined(__powerpc_aix__) || defined(__powerpc64__) || defined(__riscv32__) || defined(__riscv64__) || defined(__loongarch64) #define __av_start_struct4(LIST,TYPE_SIZE) \ (*(LIST).aptr++ = (__avword)((LIST).raddr), 0) #endif @@ -330,7 +330,7 @@ typedef int __av_alist_verify[2*(__AV_ALIST_SIZE_BOUND - (int)sizeof(__av_alist) * scalar argument types */ -#if defined(__i386__) || defined(__m68k__) || (defined(__sparc__) && !defined(__sparc64__)) || defined(__alpha__) || defined(__hppa64__) || (defined(__arm__) && !defined(__armhf__)) || defined(__arm64__) || defined(__powerpc__) || defined(__powerpc64__) || defined(__ia64__) || defined(__x86_64_sysv__) || defined(__s390__) || defined(__s390x__) || defined(__riscv32__) || defined(__riscv64__) +#if defined(__i386__) || defined(__m68k__) || (defined(__sparc__) && !defined(__sparc64__)) || defined(__alpha__) || defined(__hppa64__) || (defined(__arm__) && !defined(__armhf__)) || defined(__arm64__) || defined(__powerpc__) || defined(__powerpc64__) || defined(__ia64__) || defined(__x86_64_sysv__) || defined(__s390__) || defined(__s390x__) || defined(__riscv32__) || defined(__riscv64__) || defined(__loongarch64) /* Floats and all integer types are passed as words, * doubles as two words (on 32-bit platforms) or one word (on 64-bit platforms). */ @@ -465,7 +465,7 @@ typedef int __av_alist_verify[2*(__AV_ALIST_SIZE_BOUND - (int)sizeof(__av_alist) #define __av_ptr(LIST,VAL) __av_word(LIST,VAL) #endif -#if defined(__mips64__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm64__) || defined(__powerpc64__) || defined(__ia64__) || (defined(__x86_64__) && !defined(__x86_64_x32__) && !defined(__AV_LLP64)) || defined(__s390x__) || defined(__riscv64__) +#if defined(__mips64__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm64__) || defined(__powerpc64__) || defined(__ia64__) || (defined(__x86_64__) && !defined(__x86_64_x32__) && !defined(__AV_LLP64)) || defined(__s390x__) || defined(__riscv64__) || defined(__loongarch64) /* ‘long long’ and ‘long’ are identical. */ #define __av_longlong __av_long #define __av_ulonglong __av_ulong @@ -833,7 +833,7 @@ typedef int __av_alist_verify[2*(__AV_ALIST_SIZE_BOUND - (int)sizeof(__av_alist) #endif -#if defined(__arm64__) || defined(__riscv64__) +#if defined(__arm64__) || defined(__riscv64__) || defined(__loongarch64) /* Up to __AV_FARG_NUM float or double args can be passed in float registers. The remaining float or double args are passed in the general-purpose @@ -1535,7 +1535,7 @@ extern void avcall_structcpy (void* dest, const void* src, unsigned long size, u (LIST).aptr[-1] = (__avword)(LIST).eptr, \ 0)))) #endif -#if defined(__riscv32__) || defined(__riscv64__) +#if defined(__riscv32__) || defined(__riscv64__) || defined(__loongarch64) /* Structures <= 16 bytes are passed as embedded copies on the arg stack. * Big structures are passed as pointers to caller-made local copies. */ diff --git a/avcall/avcall-loongarch64-linux.s b/avcall/avcall-loongarch64-linux.s new file mode 100644 index 0000000..2d3a0d2 --- /dev/null +++ b/avcall/avcall-loongarch64-linux.s @@ -0,0 +1,344 @@ + .file "avcall-loongarch64.c" + .text + .align 2 + .globl avcall_call + .type avcall_call, @function +avcall_call: +.LFB0 = . + .cfi_startproc + addi.d $sp,$sp,-48 + .cfi_def_cfa_offset 48 + st.d $fp,$sp,32 + st.d $s0,$sp,24 + st.d $s1,$sp,16 + st.d $s2,$sp,8 + stptr.d $s3,$sp,0 + st.d $ra,$sp,40 + .cfi_offset 22, -16 + .cfi_offset 23, -24 + .cfi_offset 24, -32 + .cfi_offset 25, -40 + .cfi_offset 26, -48 + .cfi_offset 1, -8 + addi.d $fp,$sp,48 + .cfi_def_cfa 22, 0 + ld.d $s1,$a0,48 + ld.d $t0,$a0,40 + addi.w $t1,$r0,8 # 0x8 + ldptr.w $s3,$a0,64 + sub.d $t0,$t0,$s1 + srai.d $t0,$t0,3 + slli.w $s2,$t0,0 + or $s0,$a0,$r0 + addi.d $sp,$sp,-2048 + ble $s2,$t1,.L72 + addi.w $a2,$t0,-9 + or $t2,$sp,$r0 + bstrpick.d $a2,$a2,31,0 + alsl.d $a2,$a2,$zero,3 + addi.d $a2,$a2,8 + addi.d $a1,$s1,64 + or $a0,$t2,$r0 + bl %plt(memcpy) + ldptr.d $a0,$s1,0 +.L5: + addi.w $t0,$r0,2 # 0x2 + ld.d $a1,$s1,8 + beq $s2,$t0,.L6 + addi.w $t0,$r0,3 # 0x3 + ld.d $a2,$s1,16 + beq $s2,$t0,.L6 + addi.w $t0,$r0,4 # 0x4 + ld.d $a3,$s1,24 + beq $s2,$t0,.L6 + addi.w $t0,$r0,5 # 0x5 + ld.d $a4,$s1,32 + beq $s2,$t0,.L6 + addi.w $t0,$r0,6 # 0x6 + ld.d $a5,$s1,40 + beq $s2,$t0,.L6 + addi.w $t0,$r0,7 # 0x7 + ld.d $a6,$s1,48 + beq $s2,$t0,.L6 + ld.d $a7,$s1,56 +.L6: + beqz $s3,.L8 + ldptr.w $t0,$s0,72 + andi $t1,$t0,1 + beqz $t1,.L9 + fld.d $f0,$s0,112 +.L10: + addi.w $t1,$r0,1 # 0x1 + beq $s3,$t1,.L8 + andi $t1,$t0,2 + bnez $t1,.L73 + ldptr.w $t1,$s0,68 + andi $t1,$t1,2 + beqz $t1,.L13 + fld.s $f1,$s0,80 +.L13: + addi.w $t1,$r0,2 # 0x2 + beq $s3,$t1,.L8 + andi $t1,$t0,4 + beqz $t1,.L14 + fld.d $f2,$s0,128 +.L15: + addi.w $t1,$r0,3 # 0x3 + beq $s3,$t1,.L8 + andi $t1,$t0,8 + beqz $t1,.L16 + fld.d $f3,$s0,136 +.L17: + addi.w $t1,$r0,4 # 0x4 + beq $s3,$t1,.L8 + andi $t1,$t0,16 + bnez $t1,.L74 + ldptr.w $t1,$s0,68 + andi $t1,$t1,16 + beqz $t1,.L19 + fld.s $f4,$s0,92 +.L19: + addi.w $t1,$r0,5 # 0x5 + beq $s3,$t1,.L8 + andi $t1,$t0,32 + beqz $t1,.L20 + fld.d $f5,$s0,152 +.L21: + addi.w $t1,$r0,6 # 0x6 + beq $s3,$t1,.L8 + andi $t1,$t0,64 + beqz $t1,.L22 + fld.d $f6,$s0,160 +.L23: + addi.w $t1,$r0,7 # 0x7 + beq $s3,$t1,.L8 + andi $t0,$t0,128 + beqz $t0,.L24 + fld.d $f7,$s0,168 +.L8: + ldptr.w $t0,$s0,24 + addi.w $t1,$r0,13 # 0xd + ld.d $t2,$s0,8 + beq $t0,$t1,.L75 + addi.w $t1,$r0,14 # 0xe + beq $t0,$t1,.L76 + jirl $ra,$t2,0 + ldptr.w $t0,$s0,24 + addi.w $t1,$r0,1 # 0x1 + beq $t0,$t1,.L26 + addi.w $t1,$r0,16 # 0x10 + bgtu $t0,$t1,.L26 + la.local $t1,.L29 + slli.d $t0,$t0,3 + ldx.d $t0,$t1,$t0 + add.d $t1,$t1,$t0 + jr $t1 + .section .rodata + .align 3 + .align 2 +.L29: + .dword .L26-.L29 + .dword .L26-.L29 + .dword .L37-.L29 + .dword .L37-.L29 + .dword .L37-.L29 + .dword .L35-.L29 + .dword .L35-.L29 + .dword .L33-.L29 + .dword .L33-.L29 + .dword .L30-.L29 + .dword .L30-.L29 + .dword .L30-.L29 + .dword .L30-.L29 + .dword .L26-.L29 + .dword .L26-.L29 + .dword .L30-.L29 + .dword .L28-.L29 + .text +.L9: + ldptr.w $t1,$s0,68 + andi $t1,$t1,1 + beqz $t1,.L10 + fld.s $f0,$s0,76 + b .L10 +.L76: + ld.d $s0,$s0,16 + jirl $ra,$t2,0 + fst.d $f0,$s0,0 +.L26: + addi.d $sp,$fp,-48 + .cfi_remember_state + .cfi_def_cfa 3, 48 + ld.d $ra,$sp,40 + .cfi_restore 1 + ld.d $fp,$sp,32 + .cfi_restore 22 + ld.d $s0,$sp,24 + .cfi_restore 23 + ld.d $s1,$sp,16 + .cfi_restore 24 + ld.d $s2,$sp,8 + .cfi_restore 25 + ldptr.d $s3,$sp,0 + .cfi_restore 26 + or $a0,$zero,$r0 + addi.d $sp,$sp,48 + .cfi_def_cfa_offset 0 + jr $ra +.L72: + .cfi_restore_state + ble $s2,$r0,.L6 + addi.w $t0,$r0,1 # 0x1 + ldptr.d $a0,$s1,0 + bne $s2,$t0,.L5 + b .L6 +.L75: + ld.d $s0,$s0,16 + jirl $ra,$t2,0 + fst.s $f0,$s0,0 + b .L26 +.L73: + fld.d $f1,$s0,120 + b .L13 +.L30: + ld.d $t0,$s0,16 + stptr.d $a0,$t0,0 + b .L26 +.L37: + ld.d $t0,$s0,16 + st.b $a0,$t0,0 + b .L26 +.L14: + ldptr.w $t1,$s0,68 + andi $t1,$t1,4 + beqz $t1,.L15 + fld.s $f2,$s0,84 + b .L15 +.L16: + ldptr.w $t1,$s0,68 + andi $t1,$t1,8 + beqz $t1,.L17 + fld.s $f3,$s0,88 + b .L17 +.L74: + fld.d $f4,$s0,144 + b .L19 +.L35: + ld.d $t0,$s0,16 + st.h $a0,$t0,0 + b .L26 +.L33: + ld.d $t0,$s0,16 + stptr.w $a0,$t0,0 + b .L26 +.L28: + ldptr.w $t0,$s0,0 + andi $t0,$t0,512 + beqz $t0,.L26 + ld.d $s1,$s0,32 + addi.w $t0,$r0,15 # 0xf + addi.d $t1,$s1,-1 + bgtu $t1,$t0,.L26 + ld.d $t0,$s0,16 + addi.w $t4,$r0,-8 # 0xfffffffffffffff8 + addi.w $t1,$r0,1 # 0x1 + and $t4,$t0,$t4 + ldptr.d $t5,$t4,0 + andi $t0,$t0,7 + slli.w $t8,$t0,3 + add.d $s2,$s1,$t0 + sll.d $t7,$a0,$t8 + addi.w $s0,$r0,8 # 0x8 + sll.d $t1,$t1,$t8 + xor $t7,$t7,$t5 + slli.w $t6,$s2,3 + bgtu $s1,$s0,.L40 + bgtu $s2,$s0,.L41 + addi.w $t6,$t6,-1 + addi.w $t0,$r0,2 # 0x2 + sll.d $t0,$t0,$t6 + sub.d $t0,$t0,$t1 + and $t0,$t0,$t7 + xor $t0,$t0,$t5 + stptr.d $t0,$t4,0 + b .L26 +.L20: + ldptr.w $t1,$s0,68 + andi $t1,$t1,32 + beqz $t1,.L21 + fld.s $f5,$s0,96 + b .L21 +.L22: + ldptr.w $t1,$s0,68 + andi $t1,$t1,64 + beqz $t1,.L23 + fld.s $f6,$s0,100 + b .L23 +.L24: + ldptr.w $t0,$s0,68 + andi $t0,$t0,128 + beqz $t0,.L8 + fld.s $f7,$s0,104 + b .L8 +.L40: + sub.d $t1,$zero,$t1 + and $t1,$t1,$t7 + xor $t1,$t1,$t5 + stptr.d $t1,$t4,0 + addi.w $t1,$r0,16 # 0x10 + sub.d $t0,$s0,$t0 + sll.d $t8,$a1,$t8 + bgtu $s2,$t1,.L42 + slli.w $t0,$t0,2 + ld.d $t3,$t4,8 + sra.d $t2,$a0,$t0 + sra.d $t0,$t2,$t0 + addi.w $t6,$t6,-65 + addi.w $t1,$r0,2 # 0x2 + or $t0,$t0,$t8 + sll.d $t1,$t1,$t6 + xor $t0,$t0,$t3 + addi.d $t1,$t1,-1 + and $t0,$t0,$t1 + xor $t0,$t0,$t3 + st.d $t0,$t4,8 + b .L26 +.L41: + ld.d $t3,$t4,8 + sub.d $t0,$s0,$t0 + slli.w $t0,$t0,3 + addi.w $t6,$t6,-65 + addi.w $t2,$r0,2 # 0x2 + sra.d $t0,$a0,$t0 + sll.d $t2,$t2,$t6 + sub.d $t1,$zero,$t1 + xor $t0,$t0,$t3 + addi.d $t2,$t2,-1 + and $t1,$t1,$t7 + and $t0,$t0,$t2 + xor $t1,$t1,$t5 + xor $t0,$t0,$t3 + stptr.d $t1,$t4,0 + st.d $t0,$t4,8 + b .L26 +.L42: + ld.d $t7,$t4,16 + slli.w $t0,$t0,3 + addi.w $t1,$t6,-129 + addi.w $t5,$r0,2 # 0x2 + sll.d $t5,$t5,$t1 + sra.d $t1,$a1,$t0 + addi.d $t3,$t5,-1 + xor $t1,$t1,$t7 + sra.d $t0,$a0,$t0 + and $t1,$t3,$t1 + or $t0,$t0,$t8 + xor $t1,$t1,$t7 + st.d $t0,$t4,8 + st.d $t1,$t4,16 + b .L26 + .cfi_endproc +.LFE0: + .size avcall_call, .-avcall_call + .ident "GCC: (GNU) 12.0.1 20220317 (experimental)" + .section .note.GNU-stack,"",@progbits diff --git a/avcall/avcall-loongarch64-macro.S b/avcall/avcall-loongarch64-macro.S new file mode 100644 index 0000000..ab5dc24 --- /dev/null +++ b/avcall/avcall-loongarch64-macro.S @@ -0,0 +1,345 @@ + .file "avcall-loongarch64.c" + .text + .align 2 + .globl avcall_call + .type avcall_call, @function +avcall_call: +.LFB0 = . + .cfi_startproc + addi.d $sp,$sp,-48 + .cfi_def_cfa_offset 48 + st.d $fp,$sp,32 + st.d $s0,$sp,24 + st.d $s1,$sp,16 + st.d $s2,$sp,8 + stptr.d $s3,$sp,0 + st.d $ra,$sp,40 + .cfi_offset 22, -16 + .cfi_offset 23, -24 + .cfi_offset 24, -32 + .cfi_offset 25, -40 + .cfi_offset 26, -48 + .cfi_offset 1, -8 + addi.d $fp,$sp,48 + .cfi_def_cfa 22, 0 + ld.d $s1,$a0,48 + ld.d $t0,$a0,40 + addi.w $t1,$r0,8 # 0x8 + ldptr.w $s3,$a0,64 + sub.d $t0,$t0,$s1 + srai.d $t0,$t0,3 + slli.w $s2,$t0,0 + or $s0,$a0,$r0 + addi.d $sp,$sp,-2048 + ble $s2,$t1,.L72 + addi.w $a2,$t0,-9 + or $t2,$sp,$r0 + bstrpick.d $a2,$a2,31,0 + alsl.d $a2,$a2,$zero,3 + addi.d $a2,$a2,8 + addi.d $a1,$s1,64 + or $a0,$t2,$r0 + bl %plt(memcpy) + ldptr.d $a0,$s1,0 +.L5: + addi.w $t0,$r0,2 # 0x2 + ld.d $a1,$s1,8 + beq $s2,$t0,.L6 + addi.w $t0,$r0,3 # 0x3 + ld.d $a2,$s1,16 + beq $s2,$t0,.L6 + addi.w $t0,$r0,4 # 0x4 + ld.d $a3,$s1,24 + beq $s2,$t0,.L6 + addi.w $t0,$r0,5 # 0x5 + ld.d $a4,$s1,32 + beq $s2,$t0,.L6 + addi.w $t0,$r0,6 # 0x6 + ld.d $a5,$s1,40 + beq $s2,$t0,.L6 + addi.w $t0,$r0,7 # 0x7 + ld.d $a6,$s1,48 + beq $s2,$t0,.L6 + ld.d $a7,$s1,56 +.L6: + beqz $s3,.L8 + ldptr.w $t0,$s0,72 + andi $t1,$t0,1 + beqz $t1,.L9 + fld.d $f0,$s0,112 +.L10: + addi.w $t1,$r0,1 # 0x1 + beq $s3,$t1,.L8 + andi $t1,$t0,2 + bnez $t1,.L73 + ldptr.w $t1,$s0,68 + andi $t1,$t1,2 + beqz $t1,.L13 + fld.s $f1,$s0,80 +.L13: + addi.w $t1,$r0,2 # 0x2 + beq $s3,$t1,.L8 + andi $t1,$t0,4 + beqz $t1,.L14 + fld.d $f2,$s0,128 +.L15: + addi.w $t1,$r0,3 # 0x3 + beq $s3,$t1,.L8 + andi $t1,$t0,8 + beqz $t1,.L16 + fld.d $f3,$s0,136 +.L17: + addi.w $t1,$r0,4 # 0x4 + beq $s3,$t1,.L8 + andi $t1,$t0,16 + bnez $t1,.L74 + ldptr.w $t1,$s0,68 + andi $t1,$t1,16 + beqz $t1,.L19 + fld.s $f4,$s0,92 +.L19: + addi.w $t1,$r0,5 # 0x5 + beq $s3,$t1,.L8 + andi $t1,$t0,32 + beqz $t1,.L20 + fld.d $f5,$s0,152 +.L21: + addi.w $t1,$r0,6 # 0x6 + beq $s3,$t1,.L8 + andi $t1,$t0,64 + beqz $t1,.L22 + fld.d $f6,$s0,160 +.L23: + addi.w $t1,$r0,7 # 0x7 + beq $s3,$t1,.L8 + andi $t0,$t0,128 + beqz $t0,.L24 + fld.d $f7,$s0,168 +.L8: + ldptr.w $t0,$s0,24 + addi.w $t1,$r0,13 # 0xd + ld.d $t2,$s0,8 + beq $t0,$t1,.L75 + addi.w $t1,$r0,14 # 0xe + beq $t0,$t1,.L76 + jirl $ra,$t2,0 + ldptr.w $t0,$s0,24 + addi.w $t1,$r0,1 # 0x1 + beq $t0,$t1,.L26 + addi.w $t1,$r0,16 # 0x10 + bgtu $t0,$t1,.L26 + la.local $t1,.L29 + slli.d $t0,$t0,3 + ldx.d $t0,$t1,$t0 + add.d $t1,$t1,$t0 + jr $t1 + .section .rodata + .align 3 + .align 2 +.L29: + .dword .L26-.L29 + .dword .L26-.L29 + .dword .L37-.L29 + .dword .L37-.L29 + .dword .L37-.L29 + .dword .L35-.L29 + .dword .L35-.L29 + .dword .L33-.L29 + .dword .L33-.L29 + .dword .L30-.L29 + .dword .L30-.L29 + .dword .L30-.L29 + .dword .L30-.L29 + .dword .L26-.L29 + .dword .L26-.L29 + .dword .L30-.L29 + .dword .L28-.L29 + .text +.L9: + ldptr.w $t1,$s0,68 + andi $t1,$t1,1 + beqz $t1,.L10 + fld.s $f0,$s0,76 + b .L10 +.L76: + ld.d $s0,$s0,16 + jirl $ra,$t2,0 + fst.d $f0,$s0,0 +.L26: + addi.d $sp,$fp,-48 + .cfi_remember_state + .cfi_def_cfa 3, 48 + ld.d $ra,$sp,40 + .cfi_restore 1 + ld.d $fp,$sp,32 + .cfi_restore 22 + ld.d $s0,$sp,24 + .cfi_restore 23 + ld.d $s1,$sp,16 + .cfi_restore 24 + ld.d $s2,$sp,8 + .cfi_restore 25 + ldptr.d $s3,$sp,0 + .cfi_restore 26 + or $a0,$zero,$r0 + addi.d $sp,$sp,48 + .cfi_def_cfa_offset 0 + jr $ra +.L72: + .cfi_restore_state + ble $s2,$r0,.L6 + addi.w $t0,$r0,1 # 0x1 + ldptr.d $a0,$s1,0 + bne $s2,$t0,.L5 + b .L6 +.L75: + ld.d $s0,$s0,16 + jirl $ra,$t2,0 + fst.s $f0,$s0,0 + b .L26 +.L73: + fld.d $f1,$s0,120 + b .L13 +.L30: + ld.d $t0,$s0,16 + stptr.d $a0,$t0,0 + b .L26 +.L37: + ld.d $t0,$s0,16 + st.b $a0,$t0,0 + b .L26 +.L14: + ldptr.w $t1,$s0,68 + andi $t1,$t1,4 + beqz $t1,.L15 + fld.s $f2,$s0,84 + b .L15 +.L16: + ldptr.w $t1,$s0,68 + andi $t1,$t1,8 + beqz $t1,.L17 + fld.s $f3,$s0,88 + b .L17 +.L74: + fld.d $f4,$s0,144 + b .L19 +.L35: + ld.d $t0,$s0,16 + st.h $a0,$t0,0 + b .L26 +.L33: + ld.d $t0,$s0,16 + stptr.w $a0,$t0,0 + b .L26 +.L28: + ldptr.w $t0,$s0,0 + andi $t0,$t0,512 + beqz $t0,.L26 + ld.d $s1,$s0,32 + addi.w $t0,$r0,15 # 0xf + addi.d $t1,$s1,-1 + bgtu $t1,$t0,.L26 + ld.d $t0,$s0,16 + addi.w $t4,$r0,-8 # 0xfffffffffffffff8 + addi.w $t1,$r0,1 # 0x1 + and $t4,$t0,$t4 + ldptr.d $t5,$t4,0 + andi $t0,$t0,7 + slli.w $t8,$t0,3 + add.d $s2,$s1,$t0 + sll.d $t7,$a0,$t8 + addi.w $s0,$r0,8 # 0x8 + sll.d $t1,$t1,$t8 + xor $t7,$t7,$t5 + slli.w $t6,$s2,3 + bgtu $s1,$s0,.L40 + bgtu $s2,$s0,.L41 + addi.w $t6,$t6,-1 + addi.w $t0,$r0,2 # 0x2 + sll.d $t0,$t0,$t6 + sub.d $t0,$t0,$t1 + and $t0,$t0,$t7 + xor $t0,$t0,$t5 + stptr.d $t0,$t4,0 + b .L26 +.L20: + ldptr.w $t1,$s0,68 + andi $t1,$t1,32 + beqz $t1,.L21 + fld.s $f5,$s0,96 + b .L21 +.L22: + ldptr.w $t1,$s0,68 + andi $t1,$t1,64 + beqz $t1,.L23 + fld.s $f6,$s0,100 + b .L23 +.L24: + ldptr.w $t0,$s0,68 + andi $t0,$t0,128 + beqz $t0,.L8 + fld.s $f7,$s0,104 + b .L8 +.L40: + sub.d $t1,$zero,$t1 + and $t1,$t1,$t7 + xor $t1,$t1,$t5 + stptr.d $t1,$t4,0 + addi.w $t1,$r0,16 # 0x10 + sub.d $t0,$s0,$t0 + sll.d $t8,$a1,$t8 + bgtu $s2,$t1,.L42 + slli.w $t0,$t0,2 + ld.d $t3,$t4,8 + sra.d $t2,$a0,$t0 + sra.d $t0,$t2,$t0 + addi.w $t6,$t6,-65 + addi.w $t1,$r0,2 # 0x2 + or $t0,$t0,$t8 + sll.d $t1,$t1,$t6 + xor $t0,$t0,$t3 + addi.d $t1,$t1,-1 + and $t0,$t0,$t1 + xor $t0,$t0,$t3 + st.d $t0,$t4,8 + b .L26 +.L41: + ld.d $t3,$t4,8 + sub.d $t0,$s0,$t0 + slli.w $t0,$t0,3 + addi.w $t6,$t6,-65 + addi.w $t2,$r0,2 # 0x2 + sra.d $t0,$a0,$t0 + sll.d $t2,$t2,$t6 + sub.d $t1,$zero,$t1 + xor $t0,$t0,$t3 + addi.d $t2,$t2,-1 + and $t1,$t1,$t7 + and $t0,$t0,$t2 + xor $t1,$t1,$t5 + xor $t0,$t0,$t3 + stptr.d $t1,$t4,0 + st.d $t0,$t4,8 + b .L26 +.L42: + ld.d $t7,$t4,16 + slli.w $t0,$t0,3 + addi.w $t1,$t6,-129 + addi.w $t5,$r0,2 # 0x2 + sll.d $t5,$t5,$t1 + sra.d $t1,$a1,$t0 + addi.d $t3,$t5,-1 + xor $t1,$t1,$t7 + sra.d $t0,$a0,$t0 + and $t1,$t3,$t1 + or $t0,$t0,$t8 + xor $t1,$t1,$t7 + st.d $t0,$t4,8 + st.d $t1,$t4,16 + b .L26 + .cfi_endproc +.LFE0: + .size avcall_call, .-avcall_call +#if defined __linux__ || defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __DragonFly__ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/avcall/avcall-loongarch64.c b/avcall/avcall-loongarch64.c new file mode 100644 index 0000000..0e33033 --- /dev/null +++ b/avcall/avcall-loongarch64.c @@ -0,0 +1,358 @@ +/** + Copyright 1993 Bill Triggs + Copyright 1995-2022 Bruno Haible + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +**/ +/*---------------------------------------------------------------------- + Foreign function interface for LoongArch 64-bit CPU with LP64 ABI. + + This calls a C function with an argument list built up using macros + defined in avcall.h. + + LoongArch64 argument passing conventions: + + Up to 8 words are passed in integer registers (r4, ..., r11); remaining + words are passed on the stack. + Up to 8 float/double arguments are passed in floating point registers + (f0, ..., f7), further float/double arguments are passed in integer + registers, remaining float/double arguments are passed on the stack. + Arguments passed on the stack have 8-bytes alignment. + Structure args <= 16 bytes are passed as up to two words in registers + (floating-point fields of structures with at most two fields in + floating-point registers, other fields in integer registers). + Structure args larger than 16 bytes are passed as pointers to caller-made + local copies. + + Integers are returned in r4, r5. + Float/double values are returned in f0, f1. + Structures <= 16 bytes are returned in registers (floating-point fields + of structures with at most two fields in floating-point registers, other + fields in integer registers). + To return a structure larger than 16 bytes, the caller allocates the + space and passes a pointer to it as first argument (i.e. in r4). + ----------------------------------------------------------------------*/ +#include "avcall-internal.h" + +#define RETURN(TYPE,VAL) (*(TYPE*)l->raddr = (TYPE)(VAL)) + +register __avrword iarg1 __asm__("a0"); +register __avrword iarg2 __asm__("a1"); +register __avrword iarg3 __asm__("a2"); +register __avrword iarg4 __asm__("a3"); +register __avrword iarg5 __asm__("a4"); +register __avrword iarg6 __asm__("a5"); +register __avrword iarg7 __asm__("a6"); +register __avrword iarg8 __asm__("a7"); + +register float farg1 __asm__("f0"); +register float farg2 __asm__("f1"); +register float farg3 __asm__("f2"); +register float farg4 __asm__("f3"); +register float farg5 __asm__("f4"); +register float farg6 __asm__("f5"); +register float farg7 __asm__("f6"); +register float farg8 __asm__("f7"); + +register double darg1 __asm__("f0"); +register double darg2 __asm__("f1"); +register double darg3 __asm__("f2"); +register double darg4 __asm__("f3"); +register double darg5 __asm__("f4"); +register double darg6 __asm__("f5"); +register double darg7 __asm__("f6"); +register double darg8 __asm__("f7"); + +int +avcall_call(av_alist* list) +{ + register __avrword iretreg __asm__("a0"); + register __avrword iret2reg __asm__("a1"); + register double dret __asm__("f0"); + + __av_alist* l = &AV_LIST_INNER(list); + + __avword* argframe = __builtin_alloca(__AV_ALIST_WORDS * sizeof(__avword)); /* make room for argument list */ + int arglen = l->aptr - l->args; + unsigned int fanum = l->fanum; + + { + int i; + for (i = 8; i < arglen; i++) /* push function args onto stack */ + argframe[i-8] = l->args[i]; + } + + /* Put up to 8 integer args into registers. */ + if (arglen >= 1) { + iarg1 = l->args[0]; + if (arglen >= 2) { + iarg2 = l->args[1]; + if (arglen >= 3) { + iarg3 = l->args[2]; + if (arglen >= 4) { + iarg4 = l->args[3]; + if (arglen >= 5) { + iarg5 = l->args[4]; + if (arglen >= 6) { + iarg6 = l->args[5]; + if (arglen >= 7) { + iarg7 = l->args[6]; + if (arglen >= 8) { + iarg8 = l->args[7]; + } + } + } + } + } + } + } + } + + /* Put upto 8 floating-point args into registers. */ + if (fanum >= 1) { + if (l->darg_mask & (1 << 0)) darg1 = l->dargs[0]; + else if (l->farg_mask & (1 << 0)) farg1 = l->fargs[0]; + if (fanum >= 2) { + if (l->darg_mask & (1 << 1)) darg2 = l->dargs[1]; + else if (l->farg_mask & (1 << 1)) farg2 = l->fargs[1]; + if (fanum >= 3) { + if (l->darg_mask & (1 << 2)) darg3 = l->dargs[2]; + else if (l->farg_mask & (1 << 2)) farg3 = l->fargs[2]; + if (fanum >= 4) { + if (l->darg_mask & (1 << 3)) darg4 = l->dargs[3]; + else if (l->farg_mask & (1 << 3)) farg4 = l->fargs[3]; + if (fanum >= 5) { + if (l->darg_mask & (1 << 4)) darg5 = l->dargs[4]; + else if (l->farg_mask & (1 << 4)) farg5 = l->fargs[4]; + if (fanum >= 6) { + if (l->darg_mask & (1 << 5)) darg6 = l->dargs[5]; + else if (l->farg_mask & (1 << 5)) farg6 = l->fargs[5]; + if (fanum >= 7) { + if (l->darg_mask & (1 << 6)) darg7 = l->dargs[6]; + else if (l->farg_mask & (1 << 6)) farg7 = l->fargs[6]; + if (fanum >= 8) { + if (l->darg_mask & (1 << 7)) darg8 = l->dargs[7]; + else if (l->farg_mask & (1 << 7)) farg8 = l->fargs[7]; + } + } + } + } + } + } + } + } + + /* Call function. */ + if (l->rtype == __AVfloat) { + *(float*)l->raddr = (*(float(*)())l->func)(); + } else + if (l->rtype == __AVdouble) { + *(double*)l->raddr = (*(double(*)())l->func)(); + } else { + __avrword iret, iret2; + + iret = (*l->func)(); + iret2 = iret2reg; + + /* save return value */ + if (l->rtype == __AVvoid) { + } else + if (l->rtype == __AVchar) { + RETURN(char, iret); + } else + if (l->rtype == __AVschar) { + RETURN(signed char, iret); + } else + if (l->rtype == __AVuchar) { + RETURN(unsigned char, iret); + } else + if (l->rtype == __AVshort) { + RETURN(short, iret); + } else + if (l->rtype == __AVushort) { + RETURN(unsigned short, iret); + } else + if (l->rtype == __AVint) { + RETURN(int, iret); + } else + if (l->rtype == __AVuint) { + RETURN(unsigned int, iret); + } else + if (l->rtype == __AVlong || l->rtype == __AVlonglong) { + RETURN(long, iret); + } else + if (l->rtype == __AVulong || l->rtype == __AVulonglong) { + RETURN(unsigned long, iret); + } else + /* see above + if (l->rtype == __AVfloat) { + } else + if (l->rtype == __AVdouble) { + } else + */ + if (l->rtype == __AVvoidp) { + RETURN(void*, iret); + } else + if (l->rtype == __AVstruct) { + if (l->flags & __AV_REGISTER_STRUCT_RETURN) { + /* Return structs of size <= 16 in registers. */ + if (l->rsize > 0 && l->rsize <= 16) { + void* raddr = l->raddr; + #if 0 /* Unoptimized */ + if (l->rsize == 1) { + ((unsigned char *)raddr)[0] = (unsigned char)(iret); + } else + if (l->rsize == 2) { + ((unsigned char *)raddr)[0] = (unsigned char)(iret); + ((unsigned char *)raddr)[1] = (unsigned char)(iret>>8); + } else + if (l->rsize == 3) { + ((unsigned char *)raddr)[0] = (unsigned char)(iret); + ((unsigned char *)raddr)[1] = (unsigned char)(iret>>8); + ((unsigned char *)raddr)[2] = (unsigned char)(iret>>16); + } else + if (l->rsize == 4) { + ((unsigned char *)raddr)[0] = (unsigned char)(iret); + ((unsigned char *)raddr)[1] = (unsigned char)(iret>>8); + ((unsigned char *)raddr)[2] = (unsigned char)(iret>>16); + ((unsigned char *)raddr)[3] = (unsigned char)(iret>>24); + } else + if (l->rsize == 5) { + ((unsigned char *)raddr)[0] = (unsigned char)(iret); + ((unsigned char *)raddr)[1] = (unsigned char)(iret>>8); + ((unsigned char *)raddr)[2] = (unsigned char)(iret>>16); + ((unsigned char *)raddr)[3] = (unsigned char)(iret>>24); + ((unsigned char *)raddr)[4] = (unsigned char)(iret>>32); + } else + if (l->rsize == 6) { + ((unsigned char *)raddr)[0] = (unsigned char)(iret); + ((unsigned char *)raddr)[1] = (unsigned char)(iret>>8); + ((unsigned char *)raddr)[2] = (unsigned char)(iret>>16); + ((unsigned char *)raddr)[3] = (unsigned char)(iret>>24); + ((unsigned char *)raddr)[4] = (unsigned char)(iret>>32); + ((unsigned char *)raddr)[5] = (unsigned char)(iret>>40); + } else + if (l->rsize == 7) { + ((unsigned char *)raddr)[0] = (unsigned char)(iret); + ((unsigned char *)raddr)[1] = (unsigned char)(iret>>8); + ((unsigned char *)raddr)[2] = (unsigned char)(iret>>16); + ((unsigned char *)raddr)[3] = (unsigned char)(iret>>24); + ((unsigned char *)raddr)[4] = (unsigned char)(iret>>32); + ((unsigned char *)raddr)[5] = (unsigned char)(iret>>40); + ((unsigned char *)raddr)[6] = (unsigned char)(iret>>48); + } else + if (l->rsize >= 8 && l->rsize <= 16) { + ((unsigned char *)raddr)[0] = (unsigned char)(iret); + ((unsigned char *)raddr)[1] = (unsigned char)(iret>>8); + ((unsigned char *)raddr)[2] = (unsigned char)(iret>>16); + ((unsigned char *)raddr)[3] = (unsigned char)(iret>>24); + ((unsigned char *)raddr)[4] = (unsigned char)(iret>>32); + ((unsigned char *)raddr)[5] = (unsigned char)(iret>>40); + ((unsigned char *)raddr)[6] = (unsigned char)(iret>>48); + ((unsigned char *)raddr)[7] = (unsigned char)(iret>>56); + if (l->rsize == 8) { + } else + if (l->rsize == 9) { + ((unsigned char *)raddr)[8+0] = (unsigned char)(iret2); + } else + if (l->rsize == 10) { + ((unsigned char *)raddr)[8+0] = (unsigned char)(iret2); + ((unsigned char *)raddr)[8+1] = (unsigned char)(iret2>>8); + } else + if (l->rsize == 11) { + ((unsigned char *)raddr)[8+0] = (unsigned char)(iret2); + ((unsigned char *)raddr)[8+1] = (unsigned char)(iret2>>8); + ((unsigned char *)raddr)[8+2] = (unsigned char)(iret2>>16); + } else + if (l->rsize == 12) { + ((unsigned char *)raddr)[8+0] = (unsigned char)(iret2); + ((unsigned char *)raddr)[8+1] = (unsigned char)(iret2>>8); + ((unsigned char *)raddr)[8+2] = (unsigned char)(iret2>>16); + ((unsigned char *)raddr)[8+3] = (unsigned char)(iret2>>24); + } else + if (l->rsize == 13) { + ((unsigned char *)raddr)[8+0] = (unsigned char)(iret2); + ((unsigned char *)raddr)[8+1] = (unsigned char)(iret2>>8); + ((unsigned char *)raddr)[8+2] = (unsigned char)(iret2>>16); + ((unsigned char *)raddr)[8+3] = (unsigned char)(iret2>>24); + ((unsigned char *)raddr)[8+4] = (unsigned char)(iret2>>32); + } else + if (l->rsize == 14) { + ((unsigned char *)raddr)[8+0] = (unsigned char)(iret2); + ((unsigned char *)raddr)[8+1] = (unsigned char)(iret2>>8); + ((unsigned char *)raddr)[8+2] = (unsigned char)(iret2>>16); + ((unsigned char *)raddr)[8+3] = (unsigned char)(iret2>>24); + ((unsigned char *)raddr)[8+4] = (unsigned char)(iret2>>32); + ((unsigned char *)raddr)[8+5] = (unsigned char)(iret2>>40); + } else + if (l->rsize == 15) { + ((unsigned char *)raddr)[8+0] = (unsigned char)(iret2); + ((unsigned char *)raddr)[8+1] = (unsigned char)(iret2>>8); + ((unsigned char *)raddr)[8+2] = (unsigned char)(iret2>>16); + ((unsigned char *)raddr)[8+3] = (unsigned char)(iret2>>24); + ((unsigned char *)raddr)[8+4] = (unsigned char)(iret2>>32); + ((unsigned char *)raddr)[8+5] = (unsigned char)(iret2>>40); + ((unsigned char *)raddr)[8+6] = (unsigned char)(iret2>>48); + } else + if (l->rsize == 16) { + ((unsigned char *)raddr)[8+0] = (unsigned char)(iret2); + ((unsigned char *)raddr)[8+1] = (unsigned char)(iret2>>8); + ((unsigned char *)raddr)[8+2] = (unsigned char)(iret2>>16); + ((unsigned char *)raddr)[8+3] = (unsigned char)(iret2>>24); + ((unsigned char *)raddr)[8+4] = (unsigned char)(iret2>>32); + ((unsigned char *)raddr)[8+5] = (unsigned char)(iret2>>40); + ((unsigned char *)raddr)[8+6] = (unsigned char)(iret2>>48); + ((unsigned char *)raddr)[8+7] = (unsigned char)(iret2>>56); + } + } + #else /* Optimized: fewer conditional jumps, fewer memory accesses */ + uintptr_t count = l->rsize; /* > 0, ≤ 2*sizeof(__avrword) */ + __avrword* wordaddr = (__avrword*)((uintptr_t)raddr & ~(uintptr_t)(sizeof(__avrword)-1)); + uintptr_t start_offset = (uintptr_t)raddr & (uintptr_t)(sizeof(__avrword)-1); /* ≥ 0, < sizeof(__avrword) */ + uintptr_t end_offset = start_offset + count; /* > 0, < 3*sizeof(__avrword) */ + if (count <= sizeof(__avrword)) { + /* Use iret. */ + if (end_offset <= sizeof(__avrword)) { + /* 0 < end_offset ≤ sizeof(__avrword) */ + __avrword mask0 = ((__avrword)2 << (end_offset*8-1)) - ((__avrword)1 << (start_offset*8)); + wordaddr[0] ^= (wordaddr[0] ^ (iret << (start_offset*8))) & mask0; + } else { + /* sizeof(__avrword) < end_offset < 2*sizeof(__avrword), start_offset > 0 */ + __avrword mask0 = - ((__avrword)1 << (start_offset*8)); + __avrword mask1 = ((__avrword)2 << (end_offset*8-sizeof(__avrword)*8-1)) - 1; + wordaddr[0] ^= (wordaddr[0] ^ (iret << (start_offset*8))) & mask0; + wordaddr[1] ^= (wordaddr[1] ^ (iret >> (sizeof(__avrword)*8-start_offset*8))) & mask1; + } + } else { + /* Use iret, iret2. */ + __avrword mask0 = - ((__avrword)1 << (start_offset*8)); + wordaddr[0] ^= (wordaddr[0] ^ (iret << (start_offset*8))) & mask0; + if (end_offset <= 2*sizeof(__avrword)) { + /* sizeof(__avrword) < end_offset ≤ 2*sizeof(__avrword) */ + __avrword mask1 = ((__avrword)2 << (end_offset*8-sizeof(__avrword)*8-1)) - 1; + wordaddr[1] ^= (wordaddr[1] ^ ((iret >> (sizeof(__avrword)*4-start_offset*4) >> (sizeof(__avrword)*4-start_offset*4)) | (iret2 << (start_offset*8)))) & mask1; + } else { + /* 2*sizeof(__avrword) < end_offset < 3*sizeof(__avrword), start_offset > 0 */ + __avrword mask2 = ((__avrword)2 << (end_offset*8-2*sizeof(__avrword)*8-1)) - 1; + wordaddr[1] = (iret >> (sizeof(__avrword)*8-start_offset*8)) | (iret2 << (start_offset*8)); + wordaddr[2] ^= (wordaddr[2] ^ (iret2 >> (sizeof(__avrword)*8-start_offset*8))) & mask2; + } + } + #endif + } + } + } + } + return 0; +} diff --git a/avcall/avcall.h b/avcall/avcall.h index 3d10db4..66c9c19 100644 --- a/avcall/avcall.h +++ b/avcall/avcall.h @@ -1,6 +1,6 @@ /* * Copyright 1993-1995 Bill Triggs - * Copyright 1995-2021 Bruno Haible + * Copyright 1995-2022 Bruno Haible * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -148,7 +148,7 @@ enum __AV_alist_flags #if defined(__sparc__) && !defined(__sparc64__) && defined(__sun) && (defined(__SUNPRO_C) || defined(__SUNPRO_CC)) /* SUNWspro cc or CC */ __AV_SUNPROCC_STRUCT_RETURN, #else -#if (defined(__i386__) && (defined(_WIN32) || defined(__CYGWIN__) || (defined(__MACH__) && defined(__APPLE__)) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__))) || defined(__m68k__) || defined(__mipsn32__) || defined(__mips64__) || defined(__sparc64__) || defined(__hppa__) || defined(__hppa64__) || defined(__arm__) || defined(__armhf__) || defined(__arm64__) || defined(__powerpc64_elfv2__) || defined(__ia64__) || defined(__x86_64__) || defined(__riscv32__) || defined(__riscv64__) +#if (defined(__i386__) && (defined(_WIN32) || defined(__CYGWIN__) || (defined(__MACH__) && defined(__APPLE__)) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__))) || defined(__m68k__) || defined(__mipsn32__) || defined(__mips64__) || defined(__sparc64__) || defined(__hppa__) || defined(__hppa64__) || defined(__arm__) || defined(__armhf__) || defined(__arm64__) || defined(__powerpc64_elfv2__) || defined(__ia64__) || defined(__x86_64__) || defined(__riscv32__) || defined(__riscv64__) || defined(__loongarch64) __AV_SMALL_STRUCT_RETURN | #endif #if defined(__GNUC__) && !((defined(__mipsn32__) || defined(__mips64__)) && ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ > 3))) @@ -265,7 +265,7 @@ enum __AV_alist_flags #endif /* These are for internal use only */ -#if defined(__i386__) || defined(__m68k__) || defined(__mipsn32__) || defined(__mips64__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm__) || defined(__armhf__) || defined(__arm64__) || defined(__powerpc__) || defined(__powerpc64__) || defined(__ia64__) || defined(__x86_64__) || (defined(__s390__) && !defined(__s390x__)) || defined(__riscv64__) +#if defined(__i386__) || defined(__m68k__) || defined(__mipsn32__) || defined(__mips64__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm__) || defined(__armhf__) || defined(__arm64__) || defined(__powerpc__) || defined(__powerpc64__) || defined(__ia64__) || defined(__x86_64__) || (defined(__s390__) && !defined(__s390x__)) || defined(__riscv64__) || defined(__loongarch64) __AV_REGISTER_STRUCT_RETURN = 1<<9, #endif diff --git a/callback/PLATFORMS b/callback/PLATFORMS index df4c6e2..aded5a6 100644 --- a/callback/PLATFORMS +++ b/callback/PLATFORMS @@ -40,4 +40,5 @@ Supported CPUs: (Put the GNU config.guess values here.) s390x s390x-ibm-linux (gcc) riscv32 riscv32-unknown-linux (gcc -mabi=ilp32d) riscv64 riscv64-unknown-linux (gcc -mabi=lp64d) + loongarch64 loongarch64-unknown-linux (gcc) diff --git a/callback/trampoline_r/Makefile.devel b/callback/trampoline_r/Makefile.devel index 7abb351..a5c7e83 100644 --- a/callback/trampoline_r/Makefile.devel +++ b/callback/trampoline_r/Makefile.devel @@ -79,7 +79,7 @@ cache-powerpc64-elfv2-macro.S : cache-powerpc64-elfv2-linux.s ../../common/asm-p OLDGCCFLAGS = -O2 -fomit-frame-pointer ASPREFIX = /usr1/gnu/lib -proto-precompiled : proto-i386.s proto-m68k.s proto-mips.s proto-mipsn32.s proto-mips64.s proto-sparc.s proto-sparc64.s proto-alpha.s proto-hppa.s proto-hppa64.s proto-arm.s proto-arm64.s proto-powerpc-aix.s proto-powerpc-sysv4.s proto-powerpc-macos.s proto-powerpc64-aix.s proto-powerpc64-elfv2.s proto-ia64.c proto-x86_64.c proto-x86_64-x32.s proto-s390.s proto-s390x.s proto-riscv32.s proto-riscv64.s +proto-precompiled : proto-i386.s proto-m68k.s proto-mips.s proto-mipsn32.s proto-mips64.s proto-sparc.s proto-sparc64.s proto-alpha.s proto-hppa.s proto-hppa64.s proto-arm.s proto-arm64.s proto-powerpc-aix.s proto-powerpc-sysv4.s proto-powerpc-macos.s proto-powerpc64-aix.s proto-powerpc64-elfv2.s proto-ia64.c proto-x86_64.c proto-x86_64-x32.s proto-s390.s proto-s390x.s proto-riscv32.s proto-riscv64.s proto-loongarch64.s proto-i386.s : proto.c $(GCC) -V 2.7.2 -b i486-linuxaout $(OLDGCCFLAGS) -D__i386__ -S proto.c -o $@ @@ -153,6 +153,9 @@ proto-riscv32.s : proto.c proto-riscv64.s : proto64.c $(CROSS_TOOL) riscv64-linux gcc-7.3.0 $(OLDGCCFLAGS) -D__riscv64__ -S proto64.c -o $@ +proto-loongarch64.s : proto64.c + $(CROSS_TOOL) loongarch64-linux gcc $(OLDGCCFLAGS) -D__loongarch64 -S proto64.c -o $@ + tramp-i386.o : tramp-i386.s $(ASPREFIX)/i486-linux/bin/as tramp-i386.s -o $@ @@ -215,3 +218,6 @@ tramp-riscv32.o : tramp-riscv32.s tramp-riscv64.o : tramp-riscv64.s $(CROSS_TOOL) riscv64-linux as tramp-riscv64.s -o $@ + +tramp-loongarch64.o : tramp-loongarch64.s + $(CROSS_TOOL) loongarch64-linux as tramp-loongarch64.s -o $@ diff --git a/callback/trampoline_r/proto-loongarch64.s b/callback/trampoline_r/proto-loongarch64.s new file mode 100644 index 0000000..decf82e --- /dev/null +++ b/callback/trampoline_r/proto-loongarch64.s @@ -0,0 +1,29 @@ + .file "proto64.c" + .text + .align 2 + .globl tramp + .type tramp, @function +tramp: + lu12i.w $r20,1130504192>>12 # 0x43622000 + lu12i.w $r12,-559878144>>12 # 0xffffffffdea0f000 + ori $r20,$r20,341 + ori $r12,$r12,4011 + lu32i.d $r20,0x5471100000000>>32 + lu32i.d $r12,0xfffebec000000000>>32 + lu52i.d $r20,$r20,0x7350000000000000>>52 + lu52i.d $r12,$r12,0xbab0000000000000>>52 + jr $r12 + .size tramp, .-tramp + .section .text.unlikely,"ax",@progbits + .align 2 + .globl jump + .type jump, @function +jump: + lu12i.w $r12,-559878144>>12 # 0xffffffffdea0f000 + ori $r12,$r12,4011 + lu32i.d $r12,0xfffebec000000000>>32 + lu52i.d $r12,$r12,0xbab0000000000000>>52 + jr $r12 + .size jump, .-jump + .ident "GCC: (GNU) 12.0.0 20211224 (experimental)" + .section .note.GNU-stack,"",@progbits diff --git a/callback/trampoline_r/test1.c b/callback/trampoline_r/test1.c index 4b2f9f8..9105c8f 100644 --- a/callback/trampoline_r/test1.c +++ b/callback/trampoline_r/test1.c @@ -1,7 +1,7 @@ /* Trampoline test */ /* - * Copyright 1995-2021 Bruno Haible + * Copyright 1995-2022 Bruno Haible * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -83,6 +83,9 @@ register void* env __asm__("r0"); #endif #if defined(__riscv32__) || defined(__riscv64__) register void* env __asm__("t2"); +#endif +#ifdef __loongarch64 +register void* env __asm__("r20"); #endif return x + (int)(long)((void**)env)[1] + (int)(long)((void**)env)[0] + MAGIC3; diff --git a/callback/trampoline_r/tramp-loongarch64.s b/callback/trampoline_r/tramp-loongarch64.s new file mode 100644 index 0000000..9cd0a93 --- /dev/null +++ b/callback/trampoline_r/tramp-loongarch64.s @@ -0,0 +1,36 @@ +/* Trampoline for LoongArch CPU in 64-bit mode */ + +/* + * Copyright 1996-2022 Bruno Haible + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Available registers: $r12 ... $r20. */ + + .text + .align 3 + .globl tramp + .type tramp, @function +tramp: + pcaddu12i $r12, 0 + /* Now our own address (=tramp) is in $r12. */ + ld.d $r20, $r12, 16 /* $LC0-tramp */ + ld.d $r12, $r12, 24 /* $LC1-tramp */ + jr $r12 +$LC0: + .dword 0x7355471143622155 +$LC1: + .dword 0xbabebec0dea0ffab + .size tramp, .-tramp diff --git a/callback/trampoline_r/trampoline.c b/callback/trampoline_r/trampoline.c index 5d4f8c2..21751e3 100644 --- a/callback/trampoline_r/trampoline.c +++ b/callback/trampoline_r/trampoline.c @@ -1,7 +1,7 @@ /* Trampoline construction */ /* - * Copyright 1995-2021 Bruno Haible + * Copyright 1995-2022 Bruno Haible * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -326,6 +326,10 @@ static int open_noinherit (const char *filename, int flags, int mode) #define TRAMP_LENGTH 32 #define TRAMP_ALIGN 8 #endif +#ifdef __loongarch64 +#define TRAMP_LENGTH 32 +#define TRAMP_ALIGN 8 +#endif #ifndef TRAMP_BIAS #define TRAMP_BIAS 0 @@ -1257,6 +1261,32 @@ __TR_function alloc_trampoline_r (__TR_function address, void* data0, void* data (*(unsigned long *) (function +24)) #define tramp_data(function) \ (*(unsigned long *) (function +16)) +#endif +#ifdef __loongarch64 + /* function: + * pcaddu12i $r12,0 1C00000C + * ld.d $r20,$r12,16 28C04194 + * ld.d $r12,$r12,24 28C0618C + * jirl $r0,$r12,0 4C000180 + * .dword + * .dword
+ */ + *(unsigned int *) (function + 0) = 0x1C00000C; + *(unsigned int *) (function + 4) = 0x28C04194; + *(unsigned int *) (function + 8) = 0x28C0618C; + *(unsigned int *) (function +12) = 0x4C000180; + *(unsigned long *) (function +16) = (unsigned long) data; + *(unsigned long *) (function +24) = (unsigned long) address; +#define TRAMP_CODE_LENGTH 16 +#define is_tramp(function) \ + *(unsigned int *) (function + 0) == 0x1C00000C && \ + *(unsigned int *) (function + 4) == 0x28C04194 && \ + *(unsigned int *) (function + 8) == 0x28C0618C && \ + *(unsigned int *) (function +12) == 0x4C000180 +#define tramp_address(function) \ + *(unsigned long *) (function +24) +#define tramp_data(function) \ + *(unsigned long *) (function +16) #endif /* * data: @@ -1408,6 +1438,10 @@ __TR_function alloc_trampoline_r (__TR_function address, void* data0, void* data __asm__ __volatile__ ("fence.i"); #endif #endif +#if defined(__loongarch64) + /* Use the GCC built-in. It expands to 'ibar 0'. */ + __clear_cache((void*)function_x,(void*)(function_x+TRAMP_CODE_LENGTH)); +#endif #endif #endif diff --git a/callback/vacall_r/Makefile.devel b/callback/vacall_r/Makefile.devel index 1a2e62e..5eb626c 100644 --- a/callback/vacall_r/Makefile.devel +++ b/callback/vacall_r/Makefile.devel @@ -25,7 +25,8 @@ precompiled : \ vacall-ia64-macro.S \ vacall-x86_64-macro.S vacall-x86_64-x32-linux.s vacall-x86_64-windows-macro.S \ vacall-s390-macro.S vacall-s390x-macro.S \ - vacall-riscv32-ilp32d-macro.S vacall-riscv64-lp64d-macro.S + vacall-riscv32-ilp32d-macro.S vacall-riscv64-lp64d-macro.S \ + vacall-loongarch64-macro.S vacall-i386-linux.s : ../../vacall/vacall-i386.c ../../vacall/vacall-internal.h vacall_r.h $(THISFILE) @@ -233,3 +234,10 @@ vacall-riscv64-lp64d-linux.s : ../../vacall/vacall-riscv64.c ../../vacall/vacall vacall-riscv64-lp64d-macro.S : vacall-riscv64-lp64d-linux.s ../../common/asm-riscv.sh ../../common/noexecstack.h $(THISFILE) (../../common/asm-riscv.sh < vacall-riscv64-lp64d-linux.s ; cat ../../common/noexecstack.h) > vacall-riscv64-lp64d-macro.S + + +vacall-loongarch64-linux.s : ../../vacall/vacall-loongarch64.c ../../vacall/vacall-internal.h vacall_r.h $(THISFILE) + $(CROSS_TOOL) loongarch64-linux gcc $(GCCFLAGS) -D__loongarch64 -S ../../vacall/vacall-loongarch64.c -I../../vacall -I. -o vacall-loongarch64-linux.s + +vacall-loongarch64-macro.S : vacall-loongarch64-linux.s ../../common/asm-loongarch.sh ../../common/noexecstack.h $(THISFILE) + (../../common/asm-loongarch.sh < vacall-loongarch64-linux.s ; cat ../../common/noexecstack.h) > vacall-loongarch64-macro.S diff --git a/callback/vacall_r/Makefile.in b/callback/vacall_r/Makefile.in index 012f4d9..8cf11b3 100644 --- a/callback/vacall_r/Makefile.in +++ b/callback/vacall_r/Makefile.in @@ -242,6 +242,12 @@ vacall-riscv64-lp64d.lo : vacall-riscv64-lp64d.s vacall-riscv64-lp64d.s : $(srcdir)/vacall-riscv64-lp64d-macro.S $(CPP) $(ASPFLAGS) -I$(srcdir) $(srcdir)/vacall-riscv64-lp64d-macro.S | grep -v '^ *#line' | grep -v '^#' | sed -e 's,% ,%,g' -e 's,//.*$$,,' > vacall-riscv64-lp64d.s +vacall-loongarch64.lo : vacall-loongarch64.s + $(LIBTOOL_COMPILE) $(CC) @GCC_X_NONE@ -c vacall-loongarch64.s + +vacall-loongarch64.s : $(srcdir)/vacall-loongarch64-macro.S + $(CPP) $(ASPFLAGS) $(srcdir)/vacall-loongarch64-macro.S | grep -v '^ *#line' | grep -v '^#' | sed -e 's,% ,%,g' -e 's,//.*$$,,' > vacall-loongarch64.s + vacall-libapi.lo : $(srcdir)/vacall-libapi.c $(srcdir)/../../vacall/vacall-internal.h $(srcdir)/vacall_r.h ../../config.h $(LIBTOOL_COMPILE) $(CC) $(INCLUDES_WITH_GNULIB) $(CPPFLAGS) $(CFLAGS) @DISABLE_TYPE_BASED_ALIASING@ -DREENTRANT -c $(srcdir)/vacall-libapi.c @@ -295,7 +301,7 @@ mostlyclean : clean clean : force $(RM) *.@OBJEXT@ *.lo *.a libvacall.* core - $(RM) vacall-i386.s vacall-sparc.s vacall-sparc64.s vacall-m68k.s vacall-mips.s vacall-mipsn32.s vacall-mips64.s vacall-alpha.s vacall-hppa.s vacall-hppa64.s vacall-arm.s vacall-armhf.s vacall-arm64.s vacall-powerpc.s vacall-powerpc64.s vacall-powerpc64-elfv2.s vacall-ia64.s vacall-x86_64.s vacall-x86_64.asm vacall-x86_64-x32.s vacall-s390.s vacall-s390x.s vacall-riscv32-ilp32d.s vacall-riscv64-lp64d.s + $(RM) vacall-i386.s vacall-sparc.s vacall-sparc64.s vacall-m68k.s vacall-mips.s vacall-mipsn32.s vacall-mips64.s vacall-alpha.s vacall-hppa.s vacall-hppa64.s vacall-arm.s vacall-armhf.s vacall-arm64.s vacall-powerpc.s vacall-powerpc64.s vacall-powerpc64-elfv2.s vacall-ia64.s vacall-x86_64.s vacall-x86_64.asm vacall-x86_64-x32.s vacall-s390.s vacall-s390x.s vacall-riscv32-ilp32d.s vacall-riscv64-lp64d.s vacall-loongarch64.s $(RM) -r .libs _libs distclean : clean @@ -321,6 +327,7 @@ SOURCE_FILES = \ vacall-hppa64-linux.s vacall-hppa64-macro.S \ vacall-i386-linux.s vacall-i386-macro.S \ vacall-ia64-linux.s vacall-ia64-macro.S \ + vacall-loongarch64-linux.s vacall-loongarch64-macro.S \ vacall-m68k-linux.s vacall-m68k-sun.s vacall-m68k.mit.S vacall-m68k.motorola.S \ vacall-mipseb-linux.s vacall-mipsel-linux.s vacall-mipseb-macro.S vacall-mipsel-macro.S \ vacall-mipsn32eb-linux.s vacall-mipsn32el-linux.s vacall-mipsn32eb-macro.S vacall-mipsn32el-macro.S \ diff --git a/callback/vacall_r/vacall-loongarch64-linux.s b/callback/vacall_r/vacall-loongarch64-linux.s new file mode 100644 index 0000000..7277364 --- /dev/null +++ b/callback/vacall_r/vacall-loongarch64-linux.s @@ -0,0 +1,217 @@ + .file "vacall-loongarch64.c" + .text + .align 2 + .type callback_receiver, @function +callback_receiver: +.LFB0 = . + .cfi_startproc + addi.d $sp,$sp,-288 + .cfi_def_cfa_offset 288 + st.d $ra,$sp,264 + st.d $fp,$sp,256 + st.d $s0,$sp,248 + .cfi_offset 1, -24 + .cfi_offset 22, -32 + .cfi_offset 23, -40 + addi.d $fp,$sp,272 + .cfi_def_cfa 22, 16 + addi.d $t1,$fp,16 + ldptr.d $t0,$t8,0 + st.d $a7,$fp,8 + st.d $a1,$fp,-192 + st.d $a2,$fp,-184 + st.d $a3,$fp,-176 + st.d $a4,$fp,-168 + st.d $a5,$fp,-160 + st.d $a6,$fp,-152 + st.d $a7,$fp,-144 + fst.s $f0,$fp,-132 + fst.s $f1,$fp,-128 + fst.s $f2,$fp,-124 + fst.s $f3,$fp,-120 + fst.s $f4,$fp,-116 + fst.s $f5,$fp,-112 + fst.s $f6,$fp,-108 + fst.s $f7,$fp,-104 + fst.d $f0,$fp,-96 + fst.d $f1,$fp,-88 + fst.d $f2,$fp,-80 + fst.d $f3,$fp,-72 + fst.d $f4,$fp,-64 + fst.d $f5,$fp,-56 + fst.d $f6,$fp,-48 + fst.d $f7,$fp,-40 + st.d $t1,$fp,-240 + st.d $a0,$fp,-200 + st.w $zero,$fp,-264 + st.d $zero,$fp,-232 + ld.d $a0,$t8,8 + st.w $zero,$fp,-224 + st.w $zero,$fp,-208 + st.w $zero,$fp,-136 + addi.d $a1,$fp,-264 + jirl $ra,$t0,0 + ldptr.w $t0,$fp,-224 + beqz $t0,.L1 + addi.w $t1,$r0,15 # 0xf + bgtu $t0,$t1,.L1 + la.local $t1,.L4 + slli.d $t0,$t0,3 + ldx.d $t0,$t1,$t0 + add.d $t1,$t1,$t0 + jr $t1 + .section .rodata + .align 3 + .align 2 +.L4: + .dword .L1-.L4 + .dword .L15-.L4 + .dword .L15-.L4 + .dword .L14-.L4 + .dword .L13-.L4 + .dword .L12-.L4 + .dword .L11-.L4 + .dword .L10-.L4 + .dword .L5-.L4 + .dword .L5-.L4 + .dword .L5-.L4 + .dword .L5-.L4 + .dword .L7-.L4 + .dword .L6-.L4 + .dword .L5-.L4 + .dword .L3-.L4 + .text +.L5: + ld.d $a0,$fp,-256 +.L1: + ld.d $ra,$sp,264 + .cfi_remember_state + .cfi_restore 1 + ld.d $fp,$sp,256 + .cfi_restore 22 + ld.d $s0,$sp,248 + .cfi_restore 23 + addi.d $sp,$sp,288 + .cfi_def_cfa 3, 0 + jr $ra +.L15: + .cfi_restore_state + ld.b $a0,$fp,-256 + b .L1 +.L10: + ld.wu $a0,$fp,-256 + b .L1 +.L14: + ld.bu $a0,$fp,-256 + b .L1 +.L13: + ld.h $a0,$fp,-256 + b .L1 +.L12: + ld.hu $a0,$fp,-256 + b .L1 +.L11: + ldptr.w $a0,$fp,-256 + b .L1 +.L6: + fld.d $f0,$fp,-256 + b .L1 +.L7: + fld.s $f0,$fp,-256 + b .L1 +.L3: + ldptr.w $t0,$fp,-264 + andi $t0,$t0,1024 + beqz $t0,.L1 + ld.d $t0,$fp,-216 + addi.w $t1,$r0,15 # 0xf + addi.d $t2,$t0,-1 + bgtu $t2,$t1,.L1 + ld.d $t1,$fp,-232 + addi.w $t3,$r0,-8 # 0xfffffffffffffff8 + addi.w $s0,$r0,8 # 0x8 + andi $t2,$t1,7 + add.d $t4,$t0,$t2 + and $t1,$t1,$t3 + ldptr.d $t5,$t1,0 + slli.w $t3,$t4,3 + slli.w $t6,$t2,3 + bgtu $t0,$s0,.L17 + bgtu $t4,$s0,.L18 + addi.w $t3,$t3,-1 + addi.w $a0,$r0,2 # 0x2 + sll.d $a0,$a0,$t3 + addi.d $a0,$a0,-1 + and $a0,$a0,$t5 + sra.d $a0,$a0,$t6 + b .L1 +.L17: + addi.w $t0,$r0,16 # 0x10 + ld.d $t7,$t1,8 + sra.d $t5,$t5,$t6 + sub.d $s0,$s0,$t2 + bgtu $t4,$t0,.L19 + addi.w $t3,$t3,-65 + addi.w $a1,$r0,2 # 0x2 + sll.d $a1,$a1,$t3 + addi.d $a1,$a1,-1 + and $a1,$a1,$t7 + slli.w $s0,$s0,2 + sll.d $a0,$a1,$s0 + sll.d $a0,$a0,$s0 + or $a0,$a0,$t5 + sra.d $a1,$a1,$t6 + b .L1 +.L18: + ld.d $t4,$t1,8 + addi.w $t3,$t3,-65 + addi.w $t0,$r0,2 # 0x2 + sll.d $t0,$t0,$t3 + addi.d $t0,$t0,-1 + sub.d $t1,$s0,$t2 + and $t0,$t0,$t4 + slli.w $t1,$t1,3 + sll.d $t0,$t0,$t1 + sra.d $t5,$t5,$t6 + or $a0,$t0,$t5 + b .L1 +.L19: + ld.d $t2,$t1,16 + addi.w $t3,$t3,-129 + addi.w $t0,$r0,2 # 0x2 + sll.d $t0,$t0,$t3 + addi.d $t0,$t0,-1 + slli.w $t1,$s0,3 + and $t0,$t0,$t2 + sll.d $a0,$t7,$t1 + sll.d $t0,$t0,$t1 + sra.d $t7,$t7,$t6 + or $a0,$a0,$t5 + or $a1,$t0,$t7 + b .L1 + .cfi_endproc +.LFE0: + .size callback_receiver, .-callback_receiver + .align 2 + .globl callback_get_receiver + .type callback_get_receiver, @function +callback_get_receiver: +.LFB1 = . + .cfi_startproc + addi.d $sp,$sp,-16 + .cfi_def_cfa_offset 16 + st.d $fp,$sp,8 + .cfi_offset 22, -8 + addi.d $fp,$sp,16 + .cfi_def_cfa 22, 0 + ld.d $fp,$sp,8 + .cfi_restore 22 + la.local $a0,callback_receiver + addi.d $sp,$sp,16 + .cfi_def_cfa_register 3 + jr $ra + .cfi_endproc +.LFE1: + .size callback_get_receiver, .-callback_get_receiver + .ident "GCC: (GNU) 12.0.1 20220317 (experimental)" + .section .note.GNU-stack,"",@progbits diff --git a/callback/vacall_r/vacall-loongarch64-macro.S b/callback/vacall_r/vacall-loongarch64-macro.S new file mode 100644 index 0000000..3b3b3ad --- /dev/null +++ b/callback/vacall_r/vacall-loongarch64-macro.S @@ -0,0 +1,218 @@ + .file "vacall-loongarch64.c" + .text + .align 2 + .type callback_receiver, @function +callback_receiver: +.LFB0 = . + .cfi_startproc + addi.d $sp,$sp,-288 + .cfi_def_cfa_offset 288 + st.d $ra,$sp,264 + st.d $fp,$sp,256 + st.d $s0,$sp,248 + .cfi_offset 1, -24 + .cfi_offset 22, -32 + .cfi_offset 23, -40 + addi.d $fp,$sp,272 + .cfi_def_cfa 22, 16 + addi.d $t1,$fp,16 + ldptr.d $t0,$t8,0 + st.d $a7,$fp,8 + st.d $a1,$fp,-192 + st.d $a2,$fp,-184 + st.d $a3,$fp,-176 + st.d $a4,$fp,-168 + st.d $a5,$fp,-160 + st.d $a6,$fp,-152 + st.d $a7,$fp,-144 + fst.s $f0,$fp,-132 + fst.s $f1,$fp,-128 + fst.s $f2,$fp,-124 + fst.s $f3,$fp,-120 + fst.s $f4,$fp,-116 + fst.s $f5,$fp,-112 + fst.s $f6,$fp,-108 + fst.s $f7,$fp,-104 + fst.d $f0,$fp,-96 + fst.d $f1,$fp,-88 + fst.d $f2,$fp,-80 + fst.d $f3,$fp,-72 + fst.d $f4,$fp,-64 + fst.d $f5,$fp,-56 + fst.d $f6,$fp,-48 + fst.d $f7,$fp,-40 + st.d $t1,$fp,-240 + st.d $a0,$fp,-200 + st.w $zero,$fp,-264 + st.d $zero,$fp,-232 + ld.d $a0,$t8,8 + st.w $zero,$fp,-224 + st.w $zero,$fp,-208 + st.w $zero,$fp,-136 + addi.d $a1,$fp,-264 + jirl $ra,$t0,0 + ldptr.w $t0,$fp,-224 + beqz $t0,.L1 + addi.w $t1,$r0,15 # 0xf + bgtu $t0,$t1,.L1 + la.local $t1,.L4 + slli.d $t0,$t0,3 + ldx.d $t0,$t1,$t0 + add.d $t1,$t1,$t0 + jr $t1 + .section .rodata + .align 3 + .align 2 +.L4: + .dword .L1-.L4 + .dword .L15-.L4 + .dword .L15-.L4 + .dword .L14-.L4 + .dword .L13-.L4 + .dword .L12-.L4 + .dword .L11-.L4 + .dword .L10-.L4 + .dword .L5-.L4 + .dword .L5-.L4 + .dword .L5-.L4 + .dword .L5-.L4 + .dword .L7-.L4 + .dword .L6-.L4 + .dword .L5-.L4 + .dword .L3-.L4 + .text +.L5: + ld.d $a0,$fp,-256 +.L1: + ld.d $ra,$sp,264 + .cfi_remember_state + .cfi_restore 1 + ld.d $fp,$sp,256 + .cfi_restore 22 + ld.d $s0,$sp,248 + .cfi_restore 23 + addi.d $sp,$sp,288 + .cfi_def_cfa 3, 0 + jr $ra +.L15: + .cfi_restore_state + ld.b $a0,$fp,-256 + b .L1 +.L10: + ld.wu $a0,$fp,-256 + b .L1 +.L14: + ld.bu $a0,$fp,-256 + b .L1 +.L13: + ld.h $a0,$fp,-256 + b .L1 +.L12: + ld.hu $a0,$fp,-256 + b .L1 +.L11: + ldptr.w $a0,$fp,-256 + b .L1 +.L6: + fld.d $f0,$fp,-256 + b .L1 +.L7: + fld.s $f0,$fp,-256 + b .L1 +.L3: + ldptr.w $t0,$fp,-264 + andi $t0,$t0,1024 + beqz $t0,.L1 + ld.d $t0,$fp,-216 + addi.w $t1,$r0,15 # 0xf + addi.d $t2,$t0,-1 + bgtu $t2,$t1,.L1 + ld.d $t1,$fp,-232 + addi.w $t3,$r0,-8 # 0xfffffffffffffff8 + addi.w $s0,$r0,8 # 0x8 + andi $t2,$t1,7 + add.d $t4,$t0,$t2 + and $t1,$t1,$t3 + ldptr.d $t5,$t1,0 + slli.w $t3,$t4,3 + slli.w $t6,$t2,3 + bgtu $t0,$s0,.L17 + bgtu $t4,$s0,.L18 + addi.w $t3,$t3,-1 + addi.w $a0,$r0,2 # 0x2 + sll.d $a0,$a0,$t3 + addi.d $a0,$a0,-1 + and $a0,$a0,$t5 + sra.d $a0,$a0,$t6 + b .L1 +.L17: + addi.w $t0,$r0,16 # 0x10 + ld.d $t7,$t1,8 + sra.d $t5,$t5,$t6 + sub.d $s0,$s0,$t2 + bgtu $t4,$t0,.L19 + addi.w $t3,$t3,-65 + addi.w $a1,$r0,2 # 0x2 + sll.d $a1,$a1,$t3 + addi.d $a1,$a1,-1 + and $a1,$a1,$t7 + slli.w $s0,$s0,2 + sll.d $a0,$a1,$s0 + sll.d $a0,$a0,$s0 + or $a0,$a0,$t5 + sra.d $a1,$a1,$t6 + b .L1 +.L18: + ld.d $t4,$t1,8 + addi.w $t3,$t3,-65 + addi.w $t0,$r0,2 # 0x2 + sll.d $t0,$t0,$t3 + addi.d $t0,$t0,-1 + sub.d $t1,$s0,$t2 + and $t0,$t0,$t4 + slli.w $t1,$t1,3 + sll.d $t0,$t0,$t1 + sra.d $t5,$t5,$t6 + or $a0,$t0,$t5 + b .L1 +.L19: + ld.d $t2,$t1,16 + addi.w $t3,$t3,-129 + addi.w $t0,$r0,2 # 0x2 + sll.d $t0,$t0,$t3 + addi.d $t0,$t0,-1 + slli.w $t1,$s0,3 + and $t0,$t0,$t2 + sll.d $a0,$t7,$t1 + sll.d $t0,$t0,$t1 + sra.d $t7,$t7,$t6 + or $a0,$a0,$t5 + or $a1,$t0,$t7 + b .L1 + .cfi_endproc +.LFE0: + .size callback_receiver, .-callback_receiver + .align 2 + .globl callback_get_receiver + .type callback_get_receiver, @function +callback_get_receiver: +.LFB1 = . + .cfi_startproc + addi.d $sp,$sp,-16 + .cfi_def_cfa_offset 16 + st.d $fp,$sp,8 + .cfi_offset 22, -8 + addi.d $fp,$sp,16 + .cfi_def_cfa 22, 0 + ld.d $fp,$sp,8 + .cfi_restore 22 + la.local $a0,callback_receiver + addi.d $sp,$sp,16 + .cfi_def_cfa_register 3 + jr $ra + .cfi_endproc +.LFE1: + .size callback_get_receiver, .-callback_get_receiver +#if defined __linux__ || defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __DragonFly__ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/callback/vacall_r/vacall_r.h b/callback/vacall_r/vacall_r.h index 08b0f09..1bd3638 100644 --- a/callback/vacall_r/vacall_r.h +++ b/callback/vacall_r/vacall_r.h @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 Bruno Haible + * Copyright 1995-2022 Bruno Haible * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -175,7 +175,7 @@ enum __VA_alist_flags #if defined(__sparc__) && !defined(__sparc64__) && defined(__sun) && (defined(__SUNPRO_C) || defined(__SUNPRO_CC)) /* SUNWspro cc or CC */ __VA_SUNPROCC_STRUCT_RETURN, #else -#if (defined(__i386__) && (defined(_WIN32) || defined(__CYGWIN__) || (defined(__MACH__) && defined(__APPLE__)) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__))) || defined(__m68k__) || defined(__mipsn32__) || defined(__mips64__) || defined(__sparc64__) || defined(__hppa__) || defined(__hppa64__) || defined(__arm__) || defined(__armhf__) || defined(__arm64__) || defined(__powerpc64_elfv2__) || defined(__ia64__) || defined(__x86_64__) || defined(__riscv32__) || defined(__riscv64__) +#if (defined(__i386__) && (defined(_WIN32) || defined(__CYGWIN__) || (defined(__MACH__) && defined(__APPLE__)) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__))) || defined(__m68k__) || defined(__mipsn32__) || defined(__mips64__) || defined(__sparc64__) || defined(__hppa__) || defined(__hppa64__) || defined(__arm__) || defined(__armhf__) || defined(__arm64__) || defined(__powerpc64_elfv2__) || defined(__ia64__) || defined(__x86_64__) || defined(__riscv32__) || defined(__riscv64__) || defined(__loongarch64) __VA_SMALL_STRUCT_RETURN | #endif #if defined(__GNUC__) && !((defined(__mipsn32__) || defined(__mips64__)) && ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ > 3))) @@ -292,7 +292,7 @@ enum __VA_alist_flags #endif /* These are for internal use only */ -#if defined(__i386__) || defined(__m68k__) || defined(__mipsn32__) || defined(__mips64__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm__) || defined(__armhf__) || defined(__arm64__) || defined(__powerpc__) || defined(__powerpc64__) || defined(__ia64__) || defined(__x86_64__) || (defined(__s390__) && !defined(__s390x__)) || defined(__riscv64__) +#if defined(__i386__) || defined(__m68k__) || defined(__mipsn32__) || defined(__mips64__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm__) || defined(__armhf__) || defined(__arm64__) || defined(__powerpc__) || defined(__powerpc64__) || defined(__ia64__) || defined(__x86_64__) || (defined(__s390__) && !defined(__s390x__)) || defined(__riscv64__) || defined(__loongarch64) __VA_REGISTER_STRUCT_RETURN = 1<<10, #endif #if defined(__mipsn32__) || defined(__mips64__) diff --git a/common/asm-loongarch.sh b/common/asm-loongarch.sh new file mode 100755 index 0000000..ccab8c1 --- /dev/null +++ b/common/asm-loongarch.sh @@ -0,0 +1,44 @@ +#!/bin/sh +# Translate the assembler syntax of LoongArch assembler programs +# Usage: asm-loongarch.sh < loongarchlinux-asm-file > portable-asm-file +# The portable-asm-file has to be +# 1. preprocessed, +# 2. grep -v '^ *#line' | grep -v '^#' +# 3. sed -e 's,% ,%,g' -e 's,//.*$,,' + +# Copyright (C) 2017-2022 Bruno Haible +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +tmpscript1=sed$$tmp1 +tmpscript2=sed$$tmp2 +tmpremove='rm -f $tmpscript1 $tmpscript2' +trap "$tmpremove" 1 2 15 + +cat > $tmpscript1 << \EOF +# ----------- Remove gcc self-identification +/gcc2_compiled/d +/gnu_compiled_c/d +/\.ident/d +EOF + +cat > $tmpscript2 << \EOF +# ----------- Introduce macro syntax for assembler pseudo-ops +/\.section\([ ]\+\).*GNU-stack/d +EOF + +sed -f $tmpscript1 | \ +sed -f $tmpscript2 + +eval "$tmpremove" diff --git a/ffcall-abi.h b/ffcall-abi.h index 117fd65..4de0366 100644 --- a/ffcall-abi.h +++ b/ffcall-abi.h @@ -1,5 +1,5 @@ /* - * Copyright 2017-2019 Bruno Haible + * Copyright 2017-2022 Bruno Haible * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -249,3 +249,9 @@ #define __riscv64__ 1 #endif #endif + +#ifndef __loongarch64 +#if defined(__loongarch64) && defined(__LP64__) +#define __loongarch64 1 +#endif +#endif diff --git a/trampoline/Makefile.devel b/trampoline/Makefile.devel index ec9e0ae..bc3c6ff 100644 --- a/trampoline/Makefile.devel +++ b/trampoline/Makefile.devel @@ -79,7 +79,7 @@ cache-powerpc64-elfv2-macro.S : cache-powerpc64-elfv2-linux.s ../common/asm-powe OLDGCCFLAGS = -O2 -fomit-frame-pointer ASPREFIX = /usr1/gnu/lib -proto-precompiled : proto-i386.s proto-m68k.s proto-mips.s proto-mipsn32.s proto-mips64.s proto-sparc.s proto-sparc64.s proto-alpha.s proto-hppa.s proto-hppa64.s proto-arm.s proto-arm64.s proto-powerpc-aix.s proto-powerpc-sysv4.s proto-powerpc-macos.s proto-powerpc64-aix.s proto-powerpc64-elfv2.s proto-ia64.s proto-x86_64.s proto-x86_64-x32.s proto-s390.s proto-s390x.s proto-riscv32.s proto-riscv64.s +proto-precompiled : proto-i386.s proto-m68k.s proto-mips.s proto-mipsn32.s proto-mips64.s proto-sparc.s proto-sparc64.s proto-alpha.s proto-hppa.s proto-hppa64.s proto-arm.s proto-arm64.s proto-powerpc-aix.s proto-powerpc-sysv4.s proto-powerpc-macos.s proto-powerpc64-aix.s proto-powerpc64-elfv2.s proto-ia64.s proto-x86_64.s proto-x86_64-x32.s proto-s390.s proto-s390x.s proto-riscv32.s proto-riscv64.s proto-loongarch64.s proto-i386.s : proto.c $(GCC) -V 2.7.2 -b i486-linuxaout $(OLDGCCFLAGS) -D__i386__ -S proto.c -o $@ @@ -153,6 +153,9 @@ proto-riscv32.s : proto.c proto-riscv64.s : proto64.c $(CROSS_TOOL) riscv64-linux gcc-7.3.0 $(OLDGCCFLAGS) -D__riscv64__ -S proto64.c -o $@ +proto-loongarch64.s : proto64.c + $(CROSS_TOOL) loongarch64-linux gcc $(OLDGCCFLAGS) -D__loongarch64 -S proto64.c -o $@ + tramp-i386.o : tramp-i386.s $(ASPREFIX)/i486-linux/bin/as tramp-i386.s -o $@ @@ -215,3 +218,6 @@ tramp-riscv32.o : tramp-riscv32.s tramp-riscv64.o : tramp-riscv64.s $(CROSS_TOOL) riscv64-linux as tramp-riscv64.s -o $@ + +tramp-loongarch64.o : tramp-loongarch64.s + $(CROSS_TOOL) loongarch64-linux as tramp-loongarch64.s -o $@ diff --git a/trampoline/PLATFORMS b/trampoline/PLATFORMS index ef73e74..eeaf877 100644 --- a/trampoline/PLATFORMS +++ b/trampoline/PLATFORMS @@ -37,4 +37,5 @@ Supported CPUs: (Put the GNU config.guess values here.) s390x s390x-ibm-linux riscv32 riscv32-unknown-linux riscv64 riscv64-unknown-linux + loongarch64 loongarch64-unknown-linux diff --git a/trampoline/proto-loongarch64.s b/trampoline/proto-loongarch64.s new file mode 100644 index 0000000..2446569 --- /dev/null +++ b/trampoline/proto-loongarch64.s @@ -0,0 +1,44 @@ + .file "proto64.c" + .text + .align 2 + .globl tramp + .type tramp, @function +tramp: + lu12i.w $r12,324501504>>12 # 0x13578000 + ori $r12,$r12,1893 + lu32i.d $r12,0x4567800000000>>32 + lu52i.d $r12,$r12,0x1230000000000000>>52 + addi.w $r15,$r0,33 # 0x21 + st.b $r15,$r12,1 + addi.w $r15,$r0,98 # 0x62 + lu12i.w $r13,-559878144>>12 # 0xffffffffdea0f000 + st.b $r15,$r12,2 + addi.w $r15,$r0,67 # 0x43 + addi.w $r14,$r0,85 # 0x55 + ori $r13,$r13,4011 + st.b $r15,$r12,3 + addi.w $r15,$r0,17 # 0x11 + lu32i.d $r13,0xfffebec000000000>>32 + st.b $r14,$r12,0 + st.b $r15,$r12,4 + st.b $r14,$r12,6 + addi.w $r15,$r0,71 # 0x47 + addi.w $r14,$r0,115 # 0x73 + st.b $r15,$r12,5 + st.b $r14,$r12,7 + lu52i.d $r13,$r13,0xbab0000000000000>>52 + jr $r13 + .size tramp, .-tramp + .section .text.unlikely,"ax",@progbits + .align 2 + .globl jump + .type jump, @function +jump: + lu12i.w $r12,-559878144>>12 # 0xffffffffdea0f000 + ori $r12,$r12,4011 + lu32i.d $r12,0xfffebec000000000>>32 + lu52i.d $r12,$r12,0xbab0000000000000>>52 + jr $r12 + .size jump, .-jump + .ident "GCC: (GNU) 12.0.0 20211224 (experimental)" + .section .note.GNU-stack,"",@progbits diff --git a/trampoline/tramp-loongarch64.s b/trampoline/tramp-loongarch64.s new file mode 100644 index 0000000..52d887f --- /dev/null +++ b/trampoline/tramp-loongarch64.s @@ -0,0 +1,40 @@ +/* Trampoline for LoongArch CPU in 64-bit mode */ + +/* + * Copyright 1996-2022 Bruno Haible + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Available registers: $r12 ... $r20. */ + + .text + .align 3 + .globl tramp + .type tramp, @function +tramp: + pcaddu12i $r12, 0 + /* Now our own address (=tramp) is in $r12. */ + ld.d $r13, $r12, 24 /* $LC0-tramp */ + ld.d $r14, $r12, 32 /* $LC1-tramp */ + st.d $r14, $r13, 0 + ld.d $r12, $r12, 40 /* $LC2-tramp */ + jr $r12 +$LC0: + .dword 0x1234567813578765 +$LC1: + .dword 0x7355471143622155 +$LC2: + .dword 0xbabebec0dea0ffab + .size tramp, .-tramp diff --git a/trampoline/trampoline.c b/trampoline/trampoline.c index 9b79e0d..fdcbcd4 100644 --- a/trampoline/trampoline.c +++ b/trampoline/trampoline.c @@ -1,7 +1,7 @@ /* Trampoline construction */ /* - * Copyright 1995-2021 Bruno Haible + * Copyright 1995-2022 Bruno Haible * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -330,6 +330,10 @@ static int open_noinherit (const char *filename, int flags, int mode) #define TRAMP_LENGTH 48 #define TRAMP_ALIGN 8 #endif +#if defined(__loongarch64) +#define TRAMP_LENGTH 48 +#define TRAMP_ALIGN 8 +#endif #ifndef TRAMP_BIAS #define TRAMP_BIAS 0 @@ -1514,6 +1518,42 @@ trampoline_function_t alloc_trampoline (trampoline_function_t address, void** va #define tramp_data(function) \ (*(unsigned long *) (function +24)) #endif +#ifdef __loongarch64 + /* function: + * pcaddu12i $r12,0 1C00000C + * ld.d $r13,$r12,24 28C0618D + * ld.d $r14,$r12,32 28C0818E + * st.d $r14,$r13,0 29C001AE + * ld.d $r12,$r12,40 28C0A18C + * jirl $r0,$r12,0 4C000180 + * .dword + * .dword + * .dword
+ */ + *(unsigned int *) (function + 0) = 0x1C00000C; + *(unsigned int *) (function + 4) = 0x28C0618D; + *(unsigned int *) (function + 8) = 0x28C0818E; + *(unsigned int *) (function +12) = 0x29C001AE; + *(unsigned int *) (function +16) = 0x28C0A18C; + *(unsigned int *) (function +20) = 0x4C000180; + *(unsigned long *) (function +24) = (unsigned long) variable; + *(unsigned long *) (function +32) = (unsigned long) data; + *(unsigned long *) (function +40) = (unsigned long) address; +#define TRAMP_CODE_LENGTH 24 +#define is_tramp(function) \ + *(unsigned int *) (function + 0) == 0x1C00000C && \ + *(unsigned int *) (function + 4) == 0x28C0618D && \ + *(unsigned int *) (function + 8) == 0x28C0818E && \ + *(unsigned int *) (function +12) == 0x29C001AE && \ + *(unsigned int *) (function +16) == 0x28C0A18C && \ + *(unsigned int *) (function +20) == 0x4C000180 +#define tramp_address(function) \ + *(unsigned long *) (function +40) +#define tramp_variable(function) \ + *(unsigned long *) (function +24) +#define tramp_data(function) \ + *(unsigned long *) (function +32) +#endif /* 3. Set memory protection to "executable" */ @@ -1657,6 +1697,10 @@ trampoline_function_t alloc_trampoline (trampoline_function_t address, void** va __asm__ __volatile__ ("fence.i"); #endif #endif +#if defined(__loongarch64) + /* Use the GCC built-in. It expands to 'ibar 0'. */ + __clear_cache((void*)function_x,(void*)(function_x+TRAMP_CODE_LENGTH)); +#endif #endif #endif diff --git a/vacall/Makefile.devel b/vacall/Makefile.devel index 1c78798..7e41aad 100644 --- a/vacall/Makefile.devel +++ b/vacall/Makefile.devel @@ -25,7 +25,8 @@ precompiled : \ vacall-ia64-macro.S \ vacall-x86_64-macro.S vacall-x86_64-x32-linux.s vacall-x86_64-windows-macro.S \ vacall-s390-macro.S vacall-s390x-macro.S \ - vacall-riscv32-ilp32d-macro.S vacall-riscv64-lp64d-macro.S + vacall-riscv32-ilp32d-macro.S vacall-riscv64-lp64d-macro.S \ + vacall-loongarch64-macro.S vacall-i386-linux.s : vacall-i386.c vacall-internal.h vacall.h $(THISFILE) @@ -278,6 +279,13 @@ vacall-riscv64-lp64d-macro.S : vacall-riscv64-lp64d-linux.s ../common/asm-riscv. (../common/asm-riscv.sh < vacall-riscv64-lp64d-linux.s ; cat ../common/noexecstack.h) > vacall-riscv64-lp64d-macro.S +vacall-loongarch64-linux.s : vacall-loongarch64.c vacall-internal.h vacall.h $(THISFILE) + $(CROSS_TOOL) loongarch64-linux gcc $(GCCFLAGS) -D__loongarch64 -S vacall-loongarch64.c -o vacall-loongarch64-linux.s + +vacall-loongarch64-macro.S : vacall-loongarch64-linux.s ../common/asm-loongarch.sh ../common/noexecstack.h $(THISFILE) + (../common/asm-loongarch.sh < vacall-loongarch64-linux.s ; cat ../common/noexecstack.h) > vacall-loongarch64-macro.S + + # --------------- Rules for debugging test failures --------------- tests : tests-i386.s tests-m68k.s tests-mips.s tests-sparc.s tests-alpha.s tests-hppa.s tests-arm.s tests-powerpc.s tests-powerpc64.s tests-ia64.s tests-x86_64.s diff --git a/vacall/Makefile.in b/vacall/Makefile.in index ec31846..0101d7d 100644 --- a/vacall/Makefile.in +++ b/vacall/Makefile.in @@ -236,6 +236,12 @@ vacall-riscv64-lp64d.@OBJEXT@ : vacall-riscv64-lp64d.s vacall-riscv64-lp64d.s : $(srcdir)/vacall-riscv64-lp64d-macro.S $(CPP) $(ASPFLAGS) $(srcdir)/vacall-riscv64-lp64d-macro.S | grep -v '^ *#line' | grep -v '^#' | sed -e 's,% ,%,g' -e 's,//.*$$,,' > vacall-riscv64-lp64d.s +vacall-loongarch64.@OBJEXT@ : vacall-loongarch64.s + $(CC) @GCC_X_NONE@ -c vacall-loongarch64.s + +vacall-loongarch64.s : $(srcdir)/vacall-loongarch64-macro.S + $(CPP) $(ASPFLAGS) $(srcdir)/vacall-loongarch64-macro.S | grep -v '^ *#line' | grep -v '^#' | sed -e 's,% ,%,g' -e 's,//.*$$,,' > vacall-loongarch64.s + vacall-libapi.@OBJEXT@ : $(srcdir)/vacall-libapi.c $(srcdir)/vacall-internal.h $(srcdir)/vacall.h ../config.h $(CC) $(INCLUDES_WITH_GNULIB) $(CPPFLAGS) $(CFLAGS) @DISABLE_TYPE_BASED_ALIASING@ -c $(srcdir)/vacall-libapi.c @@ -319,7 +325,7 @@ mostlyclean : clean clean : force $(RM) *.@OBJEXT@ *.a core - $(RM) vacall-i386.s vacall-sparc.s vacall-sparc64.s vacall-m68k.s vacall-mips.s vacall-mipsn32.s vacall-mips64.s vacall-alpha.s vacall-hppa.s vacall-hppa64.s vacall-arm.s vacall-armhf.s vacall-arm64.s vacall-powerpc.s vacall-powerpc64.s vacall-powerpc64-elfv2.s vacall-ia64.s vacall-x86_64.s vacall-x86_64.asm vacall-x86_64-x32.s vacall-s390.s vacall-s390x.s vacall-riscv32-ilp32d.s vacall-riscv64-lp64d.s + $(RM) vacall-i386.s vacall-sparc.s vacall-sparc64.s vacall-m68k.s vacall-mips.s vacall-mipsn32.s vacall-mips64.s vacall-alpha.s vacall-hppa.s vacall-hppa64.s vacall-arm.s vacall-armhf.s vacall-arm64.s vacall-powerpc.s vacall-powerpc64.s vacall-powerpc64-elfv2.s vacall-ia64.s vacall-x86_64.s vacall-x86_64.asm vacall-x86_64-x32.s vacall-s390.s vacall-s390x.s vacall-riscv32-ilp32d.s vacall-riscv64-lp64d.s vacall-loongarch64.s $(RM) minitests.@OBJEXT@ minitests.s minitests minitests.out $(RM) minitests-c++.@OBJEXT@ minitests-c++ minitests-c++.out $(RM) tests.@OBJEXT@ tests.s tests tests.out @@ -346,6 +352,7 @@ SOURCE_FILES = \ vacall-hppa64.c vacall-hppa64-linux.s vacall-hppa64-macro.S \ vacall-i386.c vacall-i386-linux.s vacall-i386-linux-pic.s vacall-i386-macro.S \ vacall-ia64.c vacall-ia64-linux.s vacall-ia64-macro.S \ + vacall-loongarch64.c vacall-loongarch64-linux.s vacall-loongarch64-macro.S \ vacall-m68k.c vacall-m68k-linux.s vacall-m68k-sun.s vacall-m68k.mit.S vacall-m68k.motorola.S \ vacall-mips.c vacall-mipseb-linux.s vacall-mipsel-linux.s vacall-mipseb-macro.S vacall-mipsel-macro.S \ vacall-mipsn32.c vacall-mipsn32eb-linux.s vacall-mipsn32el-linux.s vacall-mipsn32eb-macro.S vacall-mipsn32el-macro.S \ diff --git a/vacall/PLATFORMS b/vacall/PLATFORMS index 01efe52..683e233 100644 --- a/vacall/PLATFORMS +++ b/vacall/PLATFORMS @@ -48,4 +48,5 @@ Supported CPUs: (Put the GNU config.guess values here.) s390x s390x-ibm-linux (gcc) riscv32 riscv32-unknown-linux (gcc -mabi=ilp32d) riscv64 riscv64-unknown-linux (gcc -mabi=lp64d) + loongarch64 loongarch64-unknown-linux (gcc) diff --git a/vacall/vacall-internal.h b/vacall/vacall-internal.h index c196348..f56b238 100644 --- a/vacall/vacall-internal.h +++ b/vacall/vacall-internal.h @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 Bruno Haible + * Copyright 1995-2022 Bruno Haible * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -92,7 +92,7 @@ typedef struct vacall_alist unsigned int _uint; long _long; unsigned long _ulong; -#if !(defined(__mips64__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm64__) || defined(__powerpc64__) || defined(__ia64__) || defined(__riscv64__)) +#if !(defined(__mips64__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm64__) || defined(__powerpc64__) || defined(__ia64__) || defined(__riscv64__) || defined(__loongarch64)) long long _longlong; unsigned long long _ulonglong; #endif @@ -215,7 +215,7 @@ typedef struct vacall_alist float farg[__VA_FARG_NUM]; double darg[__VA_FARG_NUM]; #endif -#if defined(__riscv32__) || defined(__riscv64__) +#if defined(__riscv32__) || defined(__riscv64__) || defined(__loongarch64) #define __VA_IARG_NUM 8 unsigned int ianum; __varword iarg[__VA_IARG_NUM]; @@ -371,7 +371,7 @@ typedef struct vacall_alist ((LIST)->flags |= __VA_REGISTER_STRUCT_RETURN, \ 0) #endif -#if defined(__hppa64__) || defined(__arm64__) || (defined(__powerpc64__) && defined(__powerpc64_elfv2__)) || defined(__x86_64_sysv__) || defined(__riscv64__) +#if defined(__hppa64__) || defined(__arm64__) || (defined(__powerpc64__) && defined(__powerpc64_elfv2__)) || defined(__x86_64_sysv__) || defined(__riscv64__) || defined(__loongarch64) #define __va_reg_struct_return(LIST,TYPE_SIZE,TYPE_SPLITTABLE) \ ((TYPE_SIZE) <= 16) /* Turn on __VA_REGISTER_STRUCT_RETURN if __VA_SMALL_STRUCT_RETURN was set @@ -419,7 +419,7 @@ typedef struct vacall_alist 0 \ ) #endif -#if defined(__powerpc_sysv4__) || defined(__x86_64_sysv__) || defined(__s390__) || defined(__s390x__) || defined(__riscv32__) || defined(__riscv64__) +#if defined(__powerpc_sysv4__) || defined(__x86_64_sysv__) || defined(__s390__) || defined(__s390x__) || defined(__riscv32__) || defined(__riscv64__) || defined(__loongarch64) /* Return structure pointer is passed as first arg. */ #define __va_start_struct2(LIST) \ ((LIST)->raddr = (void*)((LIST)->iarg[(LIST)->ianum++]), \ @@ -440,7 +440,7 @@ typedef struct vacall_alist /* Padding of non-struct arguments. */ #define __va_argsize(TYPE_SIZE) \ (((TYPE_SIZE) + sizeof(__vaword)-1) & -(intptr_t)sizeof(__vaword)) -#if defined(__i386__) || defined(__m68k__) || (defined(__mips__) && !defined(__mipsn32__) && !defined(__mips64__)) || (defined(__sparc__) && !defined(__sparc64__)) || defined(__alpha__) || (defined(__arm__) && !defined(__armhf__)) || defined(__arm64__) || defined(__powerpc_aix__) || defined(__powerpc64__) || defined(__ia64__) || defined(__x86_64_sysv__) || defined(__s390__) || defined(__s390x__) || defined(__riscv32__) || defined(__riscv64__) +#if defined(__i386__) || defined(__m68k__) || (defined(__mips__) && !defined(__mipsn32__) && !defined(__mips64__)) || (defined(__sparc__) && !defined(__sparc64__)) || defined(__alpha__) || (defined(__arm__) && !defined(__armhf__)) || defined(__arm64__) || defined(__powerpc_aix__) || defined(__powerpc64__) || defined(__ia64__) || defined(__x86_64_sysv__) || defined(__s390__) || defined(__s390x__) || defined(__riscv32__) || defined(__riscv64__) || defined(__loongarch64) /* args grow up */ /* small structures < 1 word are adjusted depending on compiler */ #define __va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ @@ -625,7 +625,7 @@ typedef struct vacall_alist (void*)__va_arg_rightadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ ) ) #endif -#if defined(__riscv32__) || defined(__riscv64__) +#if defined(__riscv32__) || defined(__riscv64__) || defined(__loongarch64) /* the first __VA_IARG_NUM argument words are passed in registers */ #define __va_arg_adjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ ((LIST)->ianum + ((TYPE_SIZE) + sizeof(__varword)-1) / sizeof(__varword) <= __VA_IARG_NUM \ @@ -655,7 +655,7 @@ typedef struct vacall_alist #define _va_arg_long(LIST) __va_arg(LIST,long) #define _va_arg_ulong(LIST) __va_arg(LIST,unsigned long) -#if defined(__mips64__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm64__) || defined(__powerpc64__) || defined(__ia64__) || (defined(__x86_64__) && !defined(__x86_64_x32__) && !defined(__VA_LLP64)) || defined(__s390x__) || defined(__riscv64__) +#if defined(__mips64__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm64__) || defined(__powerpc64__) || defined(__ia64__) || (defined(__x86_64__) && !defined(__x86_64_x32__) && !defined(__VA_LLP64)) || defined(__s390x__) || defined(__riscv64__) || defined(__loongarch64) /* ‘long long’ and ‘long’ are identical. */ #define _va_arg_longlong _va_arg_long #define _va_arg_ulonglong _va_arg_ulong @@ -719,7 +719,7 @@ typedef struct vacall_alist /* Floating point arguments. */ -#if defined(__i386__) || defined(__m68k__) || defined(__mipsn32__) || defined(__mips64__) || defined(__sparc__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm64__) || defined(__powerpc__) || defined(__powerpc64__) || defined(__ia64__) || defined(__x86_64__) || defined(__s390__) || defined(__s390x__) || defined(__riscv32__) || defined(__riscv64__) +#if defined(__i386__) || defined(__m68k__) || defined(__mipsn32__) || defined(__mips64__) || defined(__sparc__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm64__) || defined(__powerpc__) || defined(__powerpc64__) || defined(__ia64__) || defined(__x86_64__) || defined(__s390__) || defined(__s390x__) || defined(__riscv32__) || defined(__riscv64__) || defined(__loongarch64) #define __va_align_double(LIST) #endif #if defined(__mips__) && !defined(__mipsn32__) && !defined(__mips64__) || defined(__arm__) || defined(__armhf__) @@ -1005,7 +1005,7 @@ typedef struct vacall_alist *(double*)((LIST)->aptr - sizeof(double)) \ ) ) #endif -#if defined(__riscv32__) || defined(__riscv64__) +#if defined(__riscv32__) || defined(__riscv64__) || defined(__loongarch64) /* The first __VA_FARG_NUM floating-point args have been stored elsewhere. */ #define _va_arg_float(LIST) \ ((LIST)->fanum < __VA_FARG_NUM \ @@ -1115,7 +1115,7 @@ typedef struct vacall_alist (void*)__va_arg_leftadjusted(LIST,TYPE_SIZE,TYPE_ALIGN) \ ) #endif -#if defined(__arm64__) || defined(__riscv32__) || defined(__riscv64__) +#if defined(__arm64__) || defined(__riscv32__) || defined(__riscv64__) || defined(__loongarch64) /* Small structures are passed in registers or on the stack. */ /* Big structures are passed as pointers to caller-made local copies. */ #define __va_arg_struct(LIST,TYPE_SIZE,TYPE_ALIGN) \ @@ -1181,7 +1181,7 @@ typedef struct vacall_alist (__va_return(LIST,__VAlong), (LIST)->tmp._long = (VAL)) #define _va_return_ulong(LIST,VAL) \ (__va_return(LIST,__VAulong), (LIST)->tmp._ulong = (VAL)) -#if defined(__mips64__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm64__) || defined(__powerpc64__) || defined(__ia64__) || (defined(__x86_64__) && !defined(__x86_64_x32__) && !defined(__VA_LLP64)) || defined(__riscv64__) +#if defined(__mips64__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm64__) || defined(__powerpc64__) || defined(__ia64__) || (defined(__x86_64__) && !defined(__x86_64_x32__) && !defined(__VA_LLP64)) || defined(__riscv64__) || defined(__loongarch64) #define _va_return_longlong(LIST,VAL) \ (__va_return(LIST,__VAlonglong), (LIST)->tmp._long = (VAL)) #define _va_return_ulonglong(LIST,VAL) \ diff --git a/vacall/vacall-loongarch64-linux.s b/vacall/vacall-loongarch64-linux.s new file mode 100644 index 0000000..f430424 --- /dev/null +++ b/vacall/vacall-loongarch64-linux.s @@ -0,0 +1,192 @@ + .file "vacall-loongarch64.c" + .text + .align 2 + .globl vacall_receiver + .type vacall_receiver, @function +vacall_receiver: +.LFB0 = . + .cfi_startproc + addi.d $sp,$sp,-272 + .cfi_def_cfa_offset 272 + st.d $ra,$sp,248 + st.d $fp,$sp,240 + la.global $t0,vacall_function + .cfi_offset 1, -24 + .cfi_offset 22, -32 + addi.d $fp,$sp,256 + .cfi_def_cfa 22, 16 + addi.d $t1,$fp,16 + ldptr.d $t0,$t0,0 + st.d $a0,$fp,-184 + st.d $a7,$fp,8 + st.d $a1,$fp,-176 + st.d $a2,$fp,-168 + st.d $a3,$fp,-160 + st.d $a4,$fp,-152 + st.d $a5,$fp,-144 + st.d $a6,$fp,-136 + st.d $a7,$fp,-128 + fst.s $f0,$fp,-116 + fst.s $f1,$fp,-112 + fst.s $f2,$fp,-108 + fst.s $f3,$fp,-104 + fst.s $f4,$fp,-100 + fst.s $f5,$fp,-96 + fst.s $f6,$fp,-92 + fst.s $f7,$fp,-88 + fst.d $f0,$fp,-80 + fst.d $f1,$fp,-72 + fst.d $f2,$fp,-64 + fst.d $f3,$fp,-56 + fst.d $f4,$fp,-48 + fst.d $f5,$fp,-40 + fst.d $f6,$fp,-32 + fst.d $f7,$fp,-24 + st.d $t1,$fp,-224 + st.w $zero,$fp,-248 + st.d $zero,$fp,-216 + st.w $zero,$fp,-208 + addi.d $a0,$fp,-248 + st.w $zero,$fp,-192 + st.w $zero,$fp,-120 + jirl $ra,$t0,0 + ldptr.w $t0,$fp,-208 + beqz $t0,.L1 + addi.w $t1,$r0,15 # 0xf + bgtu $t0,$t1,.L1 + slli.d $t0,$t0,3 + la.local $t1,.L4 + ldx.d $t0,$t1,$t0 + jr $t0 + .section .rodata + .align 3 + .align 2 +.L4: + .dword .L1 + .dword .L15 + .dword .L15 + .dword .L14 + .dword .L13 + .dword .L12 + .dword .L11 + .dword .L10 + .dword .L5 + .dword .L5 + .dword .L5 + .dword .L5 + .dword .L7 + .dword .L6 + .dword .L5 + .dword .L3 + .text +.L5: + ld.d $a0,$fp,-240 +.L1: + ld.d $ra,$sp,248 + .cfi_remember_state + .cfi_restore 1 + ld.d $fp,$sp,240 + .cfi_restore 22 + addi.d $sp,$sp,272 + .cfi_def_cfa 3, 0 + jr $ra +.L15: + .cfi_restore_state + ld.b $a0,$fp,-240 + b .L1 +.L10: + ld.wu $a0,$fp,-240 + b .L1 +.L14: + ld.bu $a0,$fp,-240 + b .L1 +.L13: + ld.h $a0,$fp,-240 + b .L1 +.L12: + ld.hu $a0,$fp,-240 + b .L1 +.L11: + ldptr.w $a0,$fp,-240 + b .L1 +.L6: + fld.d $f0,$fp,-240 + b .L1 +.L7: + fld.s $f0,$fp,-240 + b .L1 +.L3: + ldptr.w $t0,$fp,-248 + andi $t0,$t0,1024 + beqz $t0,.L1 + ld.d $t1,$fp,-200 + addi.w $t0,$r0,15 # 0xf + addi.d $t2,$t1,-1 + bgtu $t2,$t0,.L1 + ld.d $t2,$fp,-216 + addi.w $t3,$r0,-8 # 0xfffffffffffffff8 + addi.w $t0,$r0,8 # 0x8 + andi $t4,$t2,7 + add.d $t5,$t1,$t4 + and $t2,$t2,$t3 + ldptr.d $t7,$t2,0 + slli.w $t3,$t5,3 + slli.w $t6,$t4,3 + bgtu $t1,$t0,.L17 + bgtu $t5,$t0,.L18 + addi.w $t3,$t3,-1 + addi.w $a0,$r0,2 # 0x2 + sll.d $a0,$a0,$t3 + addi.d $a0,$a0,-1 + and $a0,$a0,$t7 + sra.d $a0,$a0,$t6 + b .L1 +.L17: + addi.w $t1,$r0,16 # 0x10 + ld.d $t8,$t2,8 + sra.d $t7,$t7,$t6 + sub.d $t0,$t0,$t4 + bgtu $t5,$t1,.L19 + addi.w $t3,$t3,-65 + addi.w $a1,$r0,2 # 0x2 + sll.d $a1,$a1,$t3 + addi.d $a1,$a1,-1 + and $a1,$a1,$t8 + slli.w $t0,$t0,2 + sll.d $a0,$a1,$t0 + sll.d $a0,$a0,$t0 + or $a0,$a0,$t7 + sra.d $a1,$a1,$t6 + b .L1 +.L18: + ld.d $t2,$t2,8 + addi.w $t3,$t3,-65 + addi.w $t1,$r0,2 # 0x2 + sll.d $t1,$t1,$t3 + addi.d $t1,$t1,-1 + sub.d $t0,$t0,$t4 + and $t1,$t1,$t2 + slli.w $t0,$t0,3 + sll.d $t0,$t1,$t0 + sra.d $t7,$t7,$t6 + or $a0,$t0,$t7 + b .L1 +.L19: + ld.d $t2,$t2,16 + addi.w $t3,$t3,-129 + addi.w $t1,$r0,2 # 0x2 + sll.d $t1,$t1,$t3 + addi.d $t1,$t1,-1 + slli.w $t0,$t0,3 + and $t1,$t1,$t2 + sll.d $a0,$t8,$t0 + sll.d $t0,$t1,$t0 + sra.d $t8,$t8,$t6 + or $a0,$a0,$t7 + or $a1,$t0,$t8 + b .L1 + .cfi_endproc +.LFE0: + .size vacall_receiver, .-vacall_receiver + .ident "GCC: (GNU) 12.0.1 20220317 (experimental)" + .section .note.GNU-stack,"",@progbits diff --git a/vacall/vacall-loongarch64-macro.S b/vacall/vacall-loongarch64-macro.S new file mode 100644 index 0000000..0699ab6 --- /dev/null +++ b/vacall/vacall-loongarch64-macro.S @@ -0,0 +1,193 @@ + .file "vacall-loongarch64.c" + .text + .align 2 + .globl vacall_receiver + .type vacall_receiver, @function +vacall_receiver: +.LFB0 = . + .cfi_startproc + addi.d $sp,$sp,-272 + .cfi_def_cfa_offset 272 + st.d $ra,$sp,248 + st.d $fp,$sp,240 + la.global $t0,vacall_function + .cfi_offset 1, -24 + .cfi_offset 22, -32 + addi.d $fp,$sp,256 + .cfi_def_cfa 22, 16 + addi.d $t1,$fp,16 + ldptr.d $t0,$t0,0 + st.d $a0,$fp,-184 + st.d $a7,$fp,8 + st.d $a1,$fp,-176 + st.d $a2,$fp,-168 + st.d $a3,$fp,-160 + st.d $a4,$fp,-152 + st.d $a5,$fp,-144 + st.d $a6,$fp,-136 + st.d $a7,$fp,-128 + fst.s $f0,$fp,-116 + fst.s $f1,$fp,-112 + fst.s $f2,$fp,-108 + fst.s $f3,$fp,-104 + fst.s $f4,$fp,-100 + fst.s $f5,$fp,-96 + fst.s $f6,$fp,-92 + fst.s $f7,$fp,-88 + fst.d $f0,$fp,-80 + fst.d $f1,$fp,-72 + fst.d $f2,$fp,-64 + fst.d $f3,$fp,-56 + fst.d $f4,$fp,-48 + fst.d $f5,$fp,-40 + fst.d $f6,$fp,-32 + fst.d $f7,$fp,-24 + st.d $t1,$fp,-224 + st.w $zero,$fp,-248 + st.d $zero,$fp,-216 + st.w $zero,$fp,-208 + addi.d $a0,$fp,-248 + st.w $zero,$fp,-192 + st.w $zero,$fp,-120 + jirl $ra,$t0,0 + ldptr.w $t0,$fp,-208 + beqz $t0,.L1 + addi.w $t1,$r0,15 # 0xf + bgtu $t0,$t1,.L1 + slli.d $t0,$t0,3 + la.local $t1,.L4 + ldx.d $t0,$t1,$t0 + jr $t0 + .section .rodata + .align 3 + .align 2 +.L4: + .dword .L1 + .dword .L15 + .dword .L15 + .dword .L14 + .dword .L13 + .dword .L12 + .dword .L11 + .dword .L10 + .dword .L5 + .dword .L5 + .dword .L5 + .dword .L5 + .dword .L7 + .dword .L6 + .dword .L5 + .dword .L3 + .text +.L5: + ld.d $a0,$fp,-240 +.L1: + ld.d $ra,$sp,248 + .cfi_remember_state + .cfi_restore 1 + ld.d $fp,$sp,240 + .cfi_restore 22 + addi.d $sp,$sp,272 + .cfi_def_cfa 3, 0 + jr $ra +.L15: + .cfi_restore_state + ld.b $a0,$fp,-240 + b .L1 +.L10: + ld.wu $a0,$fp,-240 + b .L1 +.L14: + ld.bu $a0,$fp,-240 + b .L1 +.L13: + ld.h $a0,$fp,-240 + b .L1 +.L12: + ld.hu $a0,$fp,-240 + b .L1 +.L11: + ldptr.w $a0,$fp,-240 + b .L1 +.L6: + fld.d $f0,$fp,-240 + b .L1 +.L7: + fld.s $f0,$fp,-240 + b .L1 +.L3: + ldptr.w $t0,$fp,-248 + andi $t0,$t0,1024 + beqz $t0,.L1 + ld.d $t1,$fp,-200 + addi.w $t0,$r0,15 # 0xf + addi.d $t2,$t1,-1 + bgtu $t2,$t0,.L1 + ld.d $t2,$fp,-216 + addi.w $t3,$r0,-8 # 0xfffffffffffffff8 + addi.w $t0,$r0,8 # 0x8 + andi $t4,$t2,7 + add.d $t5,$t1,$t4 + and $t2,$t2,$t3 + ldptr.d $t7,$t2,0 + slli.w $t3,$t5,3 + slli.w $t6,$t4,3 + bgtu $t1,$t0,.L17 + bgtu $t5,$t0,.L18 + addi.w $t3,$t3,-1 + addi.w $a0,$r0,2 # 0x2 + sll.d $a0,$a0,$t3 + addi.d $a0,$a0,-1 + and $a0,$a0,$t7 + sra.d $a0,$a0,$t6 + b .L1 +.L17: + addi.w $t1,$r0,16 # 0x10 + ld.d $t8,$t2,8 + sra.d $t7,$t7,$t6 + sub.d $t0,$t0,$t4 + bgtu $t5,$t1,.L19 + addi.w $t3,$t3,-65 + addi.w $a1,$r0,2 # 0x2 + sll.d $a1,$a1,$t3 + addi.d $a1,$a1,-1 + and $a1,$a1,$t8 + slli.w $t0,$t0,2 + sll.d $a0,$a1,$t0 + sll.d $a0,$a0,$t0 + or $a0,$a0,$t7 + sra.d $a1,$a1,$t6 + b .L1 +.L18: + ld.d $t2,$t2,8 + addi.w $t3,$t3,-65 + addi.w $t1,$r0,2 # 0x2 + sll.d $t1,$t1,$t3 + addi.d $t1,$t1,-1 + sub.d $t0,$t0,$t4 + and $t1,$t1,$t2 + slli.w $t0,$t0,3 + sll.d $t0,$t1,$t0 + sra.d $t7,$t7,$t6 + or $a0,$t0,$t7 + b .L1 +.L19: + ld.d $t2,$t2,16 + addi.w $t3,$t3,-129 + addi.w $t1,$r0,2 # 0x2 + sll.d $t1,$t1,$t3 + addi.d $t1,$t1,-1 + slli.w $t0,$t0,3 + and $t1,$t1,$t2 + sll.d $a0,$t8,$t0 + sll.d $t0,$t1,$t0 + sra.d $t8,$t8,$t6 + or $a0,$a0,$t7 + or $a1,$t0,$t8 + b .L1 + .cfi_endproc +.LFE0: + .size vacall_receiver, .-vacall_receiver +#if defined __linux__ || defined __FreeBSD__ || defined __FreeBSD_kernel__ || defined __DragonFly__ + .section .note.GNU-stack,"",@progbits +#endif diff --git a/vacall/vacall-loongarch64.c b/vacall/vacall-loongarch64.c new file mode 100644 index 0000000..d5cfa7f --- /dev/null +++ b/vacall/vacall-loongarch64.c @@ -0,0 +1,238 @@ +/* vacall function for LoongArch 64-bit CPU */ + +/* + * Copyright 1995-2022 Bruno Haible + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "vacall-internal.h" + +#ifdef REENTRANT +#define vacall_receiver callback_receiver +register struct { void (*vacall_function) (void*,va_alist); void* arg; } + * env __asm__("t8"); +#endif + +register __varword iarg1 __asm__("a0"); +register __varword iarg2 __asm__("a1"); +register __varword iarg3 __asm__("a2"); +register __varword iarg4 __asm__("a3"); +register __varword iarg5 __asm__("a4"); +register __varword iarg6 __asm__("a5"); +register __varword iarg7 __asm__("a6"); +register __varword iarg8 __asm__("a7"); + +register float farg1 __asm__("f0"); +register float farg2 __asm__("f1"); +register float farg3 __asm__("f2"); +register float farg4 __asm__("f3"); +register float farg5 __asm__("f4"); +register float farg6 __asm__("f5"); +register float farg7 __asm__("f6"); +register float farg8 __asm__("f7"); + +register double darg1 __asm__("f0"); +register double darg2 __asm__("f1"); +register double darg3 __asm__("f2"); +register double darg4 __asm__("f3"); +register double darg5 __asm__("f4"); +register double darg6 __asm__("f5"); +register double darg7 __asm__("f6"); +register double darg8 __asm__("f7"); + +register __varword iret __asm__("a0"); +register __varword iret2 __asm__("a1"); +register float fret __asm__("f0"); +register double dret __asm__("f0"); + +/* The ABI requires that the first 8 general-purpose argument words are + being passed in registers, even if these words belong to structs that are + at most 2 words large. No room is allocated for these register words on + the stack by the caller, but the callee allocates room for them - at the + right place in the stack frame, that is, above the retaddr - if and only + if they are part of a struct that extends to the stack and the address of + this struct is taken. */ +struct gpargsequence { + __vaword word8; /* a7 */ + __vaword firststackword; +}; + +#ifdef REENTRANT +static +#endif +void /* the return type is variable, not void! */ +vacall_receiver (__vaword word1, __vaword word2, __vaword word3, __vaword word4, + __vaword word5, __vaword word6, __vaword word7, + struct gpargsequence gpargs) +{ + __va_alist list; + /* Move the arguments passed in registers to temp storage. */ + list.iarg[0] = iarg1; + list.iarg[1] = iarg2; + list.iarg[2] = iarg3; + list.iarg[3] = iarg4; + list.iarg[4] = iarg5; + list.iarg[5] = iarg6; + list.iarg[6] = iarg7; + list.iarg[7] = iarg8; /* = gpargs.word8 */ + list.farg[0] = farg1; + list.farg[1] = farg2; + list.farg[2] = farg3; + list.farg[3] = farg4; + list.farg[4] = farg5; + list.farg[5] = farg6; + list.farg[6] = farg7; + list.farg[7] = farg8; + list.darg[0] = darg1; + list.darg[1] = darg2; + list.darg[2] = darg3; + list.darg[3] = darg4; + list.darg[4] = darg5; + list.darg[5] = darg6; + list.darg[6] = darg7; + list.darg[7] = darg8; + /* Prepare the va_alist. */ + list.flags = 0; + list.aptr = (long)&gpargs + sizeof(__vaword); + list.raddr = (void*)0; + list.rtype = __VAvoid; + list.ianum = 0; + list.fanum = 0; + /* Call vacall_function. The macros do all the rest. */ +#ifndef REENTRANT + (*vacall_function) (&list); +#else /* REENTRANT */ + (*env->vacall_function) (env->arg,&list); +#endif + /* Put return value into proper register. */ + if (list.rtype == __VAvoid) { + } else + if (list.rtype == __VAchar) { + iret = list.tmp._char; + } else + if (list.rtype == __VAschar) { + iret = list.tmp._schar; + } else + if (list.rtype == __VAuchar) { + iret = list.tmp._uchar; + } else + if (list.rtype == __VAshort) { + iret = list.tmp._short; + } else + if (list.rtype == __VAushort) { + iret = list.tmp._ushort; + } else + if (list.rtype == __VAint) { + iret = list.tmp._int; + } else + if (list.rtype == __VAuint) { + iret = list.tmp._uint; + } else + if (list.rtype == __VAlong || list.rtype == __VAlonglong) { + iret = list.tmp._long; + } else + if (list.rtype == __VAulong || list.rtype == __VAulonglong) { + iret = list.tmp._ulong; + } else + if (list.rtype == __VAfloat) { + fret = list.tmp._float; + } else + if (list.rtype == __VAdouble) { + dret = list.tmp._double; + } else + if (list.rtype == __VAvoidp) { + iret = (long)list.tmp._ptr; + } else + if (list.rtype == __VAstruct) { + /* normal struct return convention */ + if (list.flags & __VA_REGISTER_STRUCT_RETURN) { + /* Return structs of size <= 16 in registers. */ + if (list.rsize > 0 && list.rsize <= 16) { + #if 0 /* Unoptimized */ + iret = (__varword)((unsigned char *) list.raddr)[0]; + if (list.rsize >= 2) + iret |= (__varword)((unsigned char *) list.raddr)[1] << 8; + if (list.rsize >= 3) + iret |= (__varword)((unsigned char *) list.raddr)[2] << 16; + if (list.rsize >= 4) + iret |= (__varword)((unsigned char *) list.raddr)[3] << 24; + if (list.rsize >= 5) + iret |= (__varword)((unsigned char *) list.raddr)[4] << 32; + if (list.rsize >= 6) + iret |= (__varword)((unsigned char *) list.raddr)[5] << 40; + if (list.rsize >= 7) + iret |= (__varword)((unsigned char *) list.raddr)[6] << 48; + if (list.rsize >= 8) + iret |= (__varword)((unsigned char *) list.raddr)[7] << 56; + if (list.rsize >= 9) { + iret2 = (__varword)((unsigned char *) list.raddr)[8]; + if (list.rsize >= 10) + iret2 |= (__varword)((unsigned char *) list.raddr)[9] << 8; + if (list.rsize >= 11) + iret2 |= (__varword)((unsigned char *) list.raddr)[10] << 16; + if (list.rsize >= 12) + iret2 |= (__varword)((unsigned char *) list.raddr)[11] << 24; + if (list.rsize >= 13) + iret2 |= (__varword)((unsigned char *) list.raddr)[12] << 32; + if (list.rsize >= 14) + iret2 |= (__varword)((unsigned char *) list.raddr)[13] << 40; + if (list.rsize >= 15) + iret2 |= (__varword)((unsigned char *) list.raddr)[14] << 48; + if (list.rsize >= 16) + iret2 |= (__varword)((unsigned char *) list.raddr)[15] << 56; + } + #else /* Optimized: fewer conditional jumps, fewer memory accesses */ + uintptr_t count = list.rsize; /* > 0, ≤ 2*sizeof(__varword) */ + __varword* wordaddr = (__varword*)((uintptr_t)list.raddr & ~(uintptr_t)(sizeof(__varword)-1)); + uintptr_t start_offset = (uintptr_t)list.raddr & (uintptr_t)(sizeof(__varword)-1); /* ≥ 0, < sizeof(__varword) */ + uintptr_t end_offset = start_offset + count; /* > 0, < 3*sizeof(__varword) */ + if (count <= sizeof(__varword)) { + /* Assign iret. */ + if (end_offset <= sizeof(__varword)) { + /* 0 < end_offset ≤ sizeof(__varword) */ + __varword mask0 = ((__varword)2 << (end_offset*8-1)) - 1; + iret = (wordaddr[0] & mask0) >> (start_offset*8); + } else { + /* sizeof(__varword) < end_offset < 2*sizeof(__varword), start_offset > 0 */ + __varword mask1 = ((__varword)2 << (end_offset*8-sizeof(__varword)*8-1)) - 1; + iret = (wordaddr[0] >> (start_offset*8)) | ((wordaddr[1] & mask1) << (sizeof(__varword)*8-start_offset*8)); + } + } else { + /* Assign iret, iret2. */ + if (end_offset <= 2*sizeof(__varword)) { + /* sizeof(__varword) < end_offset ≤ 2*sizeof(__varword) */ + __varword mask1 = ((__varword)2 << (end_offset*8-sizeof(__varword)*8-1)) - 1; + iret = (wordaddr[0] >> (start_offset*8)) | ((wordaddr[1] & mask1) << (sizeof(__varword)*4-start_offset*4) << (sizeof(__varword)*4-start_offset*4)); + iret2 = (wordaddr[1] & mask1) >> (start_offset*8); + } else { + /* 2*sizeof(__varword) < end_offset < 3*sizeof(__varword), start_offset > 0 */ + __varword mask2 = ((__varword)2 << (end_offset*8-2*sizeof(__varword)*8-1)) - 1; + iret = (wordaddr[0] >> (start_offset*8)) | (wordaddr[1] << (sizeof(__varword)*8-start_offset*8)); + iret2 = (wordaddr[1] >> (start_offset*8)) | ((wordaddr[2] & mask2) << (sizeof(__varword)*8-start_offset*8)); + } + } + #endif + } + } + } +} + +#ifdef REENTRANT +__vacall_r_t +callback_get_receiver (void) +{ + return (__vacall_r_t)(void*)&callback_receiver; +} +#endif diff --git a/vacall/vacall.h b/vacall/vacall.h index 9d14d4a..a467df7 100644 --- a/vacall/vacall.h +++ b/vacall/vacall.h @@ -1,5 +1,5 @@ /* - * Copyright 1995-2021 Bruno Haible + * Copyright 1995-2022 Bruno Haible * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -136,7 +136,7 @@ enum __VA_alist_flags #if defined(__sparc__) && !defined(__sparc64__) && defined(__sun) && (defined(__SUNPRO_C) || defined(__SUNPRO_CC)) /* SUNWspro cc or CC */ __VA_SUNPROCC_STRUCT_RETURN, #else -#if (defined(__i386__) && (defined(_WIN32) || defined(__CYGWIN__) || (defined(__MACH__) && defined(__APPLE__)) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__))) || defined(__m68k__) || defined(__mipsn32__) || defined(__mips64__) || defined(__sparc64__) || defined(__hppa__) || defined(__hppa64__) || defined(__arm__) || defined(__armhf__) || defined(__arm64__) || defined(__powerpc64_elfv2__) || defined(__ia64__) || defined(__x86_64__) || defined(__riscv32__) || defined(__riscv64__) +#if (defined(__i386__) && (defined(_WIN32) || defined(__CYGWIN__) || (defined(__MACH__) && defined(__APPLE__)) || defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__))) || defined(__m68k__) || defined(__mipsn32__) || defined(__mips64__) || defined(__sparc64__) || defined(__hppa__) || defined(__hppa64__) || defined(__arm__) || defined(__armhf__) || defined(__arm64__) || defined(__powerpc64_elfv2__) || defined(__ia64__) || defined(__x86_64__) || defined(__riscv32__) || defined(__riscv64__) || defined(__loongarch64) __VA_SMALL_STRUCT_RETURN | #endif #if defined(__GNUC__) && !((defined(__mipsn32__) || defined(__mips64__)) && ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ > 3))) @@ -253,7 +253,7 @@ enum __VA_alist_flags #endif /* These are for internal use only */ -#if defined(__i386__) || defined(__m68k__) || defined(__mipsn32__) || defined(__mips64__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm__) || defined(__armhf__) || defined(__arm64__) || defined(__powerpc__) || defined(__powerpc64__) || defined(__ia64__) || defined(__x86_64__) || (defined(__s390__) && !defined(__s390x__)) || defined(__riscv64__) +#if defined(__i386__) || defined(__m68k__) || defined(__mipsn32__) || defined(__mips64__) || defined(__sparc64__) || defined(__alpha__) || defined(__hppa64__) || defined(__arm__) || defined(__armhf__) || defined(__arm64__) || defined(__powerpc__) || defined(__powerpc64__) || defined(__ia64__) || defined(__x86_64__) || (defined(__s390__) && !defined(__s390x__)) || defined(__riscv64__) || defined(__loongarch64) __VA_REGISTER_STRUCT_RETURN = 1<<10, #endif #if defined(__mipsn32__) || defined(__mips64__) -- 2.39.1