1*d4fe68aeSThomas Weißschuh /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 2*d4fe68aeSThomas Weißschuh /* 3*d4fe68aeSThomas Weißschuh * parisc/hppa (32-bit) specific definitions for NOLIBC 4*d4fe68aeSThomas Weißschuh * Copyright (C) 2026 Thomas Weißschuh <linux@weissschuh.net> 5*d4fe68aeSThomas Weißschuh */ 6*d4fe68aeSThomas Weißschuh 7*d4fe68aeSThomas Weißschuh #ifndef _NOLIBC_ARCH_PARISC_H 8*d4fe68aeSThomas Weißschuh #define _NOLIBC_ARCH_PARISC_H 9*d4fe68aeSThomas Weißschuh 10*d4fe68aeSThomas Weißschuh #if defined(__LP64__) 11*d4fe68aeSThomas Weißschuh #error 64-bit not supported 12*d4fe68aeSThomas Weißschuh #endif 13*d4fe68aeSThomas Weißschuh 14*d4fe68aeSThomas Weißschuh #include "compiler.h" 15*d4fe68aeSThomas Weißschuh #include "crt.h" 16*d4fe68aeSThomas Weißschuh 17*d4fe68aeSThomas Weißschuh /* Syscalls for parisc : 18*d4fe68aeSThomas Weißschuh * - syscall number is passed in r20 19*d4fe68aeSThomas Weißschuh * - arguments are in r26 to r21 20*d4fe68aeSThomas Weißschuh * - the system call is performed by calling "ble 0x100(%sr2, %r0)", 21*d4fe68aeSThomas Weißschuh * the instruction after that is in the delay slot and executed before 22*d4fe68aeSThomas Weißschuh * the jump to 0x100 actually happens, use it to load the syscall number 23*d4fe68aeSThomas Weißschuh * - syscall return comes in r28 24*d4fe68aeSThomas Weißschuh * - the arguments are cast to long and assigned into the target 25*d4fe68aeSThomas Weißschuh * registers which are then simply passed as registers to the asm code, 26*d4fe68aeSThomas Weißschuh * so that we don't have to experience issues with register constraints. 27*d4fe68aeSThomas Weißschuh */ 28*d4fe68aeSThomas Weißschuh 29*d4fe68aeSThomas Weißschuh #define _NOLIBC_SYSCALL_CLOBBERLIST \ 30*d4fe68aeSThomas Weißschuh "memory", "%r1", "%r2", "%r4", "%r20", "%r29", "%r31" 31*d4fe68aeSThomas Weißschuh 32*d4fe68aeSThomas Weißschuh #define __nolibc_syscall0(num) \ 33*d4fe68aeSThomas Weißschuh ({ \ 34*d4fe68aeSThomas Weißschuh register long _ret __asm__ ("r28"); \ 35*d4fe68aeSThomas Weißschuh \ 36*d4fe68aeSThomas Weißschuh __asm__ volatile ( \ 37*d4fe68aeSThomas Weißschuh "ble 0x100(%%sr2, %%r0)\n\t" \ 38*d4fe68aeSThomas Weißschuh "copy %1, %%r20\n\t" \ 39*d4fe68aeSThomas Weißschuh : "=r"(_ret) \ 40*d4fe68aeSThomas Weißschuh : "r"(num) \ 41*d4fe68aeSThomas Weißschuh : _NOLIBC_SYSCALL_CLOBBERLIST, \ 42*d4fe68aeSThomas Weißschuh "%r21", "%r22", "%r23", "%r24", "%r25", "%r26" \ 43*d4fe68aeSThomas Weißschuh ); \ 44*d4fe68aeSThomas Weißschuh _ret; \ 45*d4fe68aeSThomas Weißschuh }) 46*d4fe68aeSThomas Weißschuh 47*d4fe68aeSThomas Weißschuh #define __nolibc_syscall1(num, arg1) \ 48*d4fe68aeSThomas Weißschuh ({ \ 49*d4fe68aeSThomas Weißschuh register long _ret __asm__ ("r28"); \ 50*d4fe68aeSThomas Weißschuh register long _arg1 __asm__ ("r26") = (long)(arg1); \ 51*d4fe68aeSThomas Weißschuh \ 52*d4fe68aeSThomas Weißschuh __asm__ volatile ( \ 53*d4fe68aeSThomas Weißschuh "ble 0x100(%%sr2, %%r0)\n\t" \ 54*d4fe68aeSThomas Weißschuh "copy %2, %%r20\n\t" \ 55*d4fe68aeSThomas Weißschuh : "=r"(_ret), \ 56*d4fe68aeSThomas Weißschuh "+r"(_arg1) \ 57*d4fe68aeSThomas Weißschuh : "r"(num) \ 58*d4fe68aeSThomas Weißschuh : _NOLIBC_SYSCALL_CLOBBERLIST, \ 59*d4fe68aeSThomas Weißschuh "%r21", "%r22", "%r23", "%r24", "%r25" \ 60*d4fe68aeSThomas Weißschuh ); \ 61*d4fe68aeSThomas Weißschuh _ret; \ 62*d4fe68aeSThomas Weißschuh }) 63*d4fe68aeSThomas Weißschuh 64*d4fe68aeSThomas Weißschuh #define __nolibc_syscall2(num, arg1, arg2) \ 65*d4fe68aeSThomas Weißschuh ({ \ 66*d4fe68aeSThomas Weißschuh register long _ret __asm__ ("r28"); \ 67*d4fe68aeSThomas Weißschuh register long _arg1 __asm__ ("r26") = (long)(arg1); \ 68*d4fe68aeSThomas Weißschuh register long _arg2 __asm__ ("r25") = (long)(arg2); \ 69*d4fe68aeSThomas Weißschuh \ 70*d4fe68aeSThomas Weißschuh __asm__ volatile ( \ 71*d4fe68aeSThomas Weißschuh "ble 0x100(%%sr2, %%r0)\n\t" \ 72*d4fe68aeSThomas Weißschuh "copy %3, %%r20\n\t" \ 73*d4fe68aeSThomas Weißschuh : "=r"(_ret), \ 74*d4fe68aeSThomas Weißschuh "+r"(_arg1), "+r"(_arg2) \ 75*d4fe68aeSThomas Weißschuh : "r"(num) \ 76*d4fe68aeSThomas Weißschuh : _NOLIBC_SYSCALL_CLOBBERLIST, \ 77*d4fe68aeSThomas Weißschuh "%r21", "%r22", "%r23", "%r24" \ 78*d4fe68aeSThomas Weißschuh ); \ 79*d4fe68aeSThomas Weißschuh _ret; \ 80*d4fe68aeSThomas Weißschuh }) 81*d4fe68aeSThomas Weißschuh 82*d4fe68aeSThomas Weißschuh #define __nolibc_syscall3(num, arg1, arg2, arg3) \ 83*d4fe68aeSThomas Weißschuh ({ \ 84*d4fe68aeSThomas Weißschuh register long _ret __asm__ ("r28"); \ 85*d4fe68aeSThomas Weißschuh register long _arg1 __asm__ ("r26") = (long)(arg1); \ 86*d4fe68aeSThomas Weißschuh register long _arg2 __asm__ ("r25") = (long)(arg2); \ 87*d4fe68aeSThomas Weißschuh register long _arg3 __asm__ ("r24") = (long)(arg3); \ 88*d4fe68aeSThomas Weißschuh \ 89*d4fe68aeSThomas Weißschuh __asm__ volatile ( \ 90*d4fe68aeSThomas Weißschuh "ble 0x100(%%sr2, %%r0)\n\t" \ 91*d4fe68aeSThomas Weißschuh "copy %4, %%r20\n\t" \ 92*d4fe68aeSThomas Weißschuh : "=r"(_ret), \ 93*d4fe68aeSThomas Weißschuh "+r"(_arg1), "+r"(_arg2), "+r"(_arg3) \ 94*d4fe68aeSThomas Weißschuh : "r"(num) \ 95*d4fe68aeSThomas Weißschuh : _NOLIBC_SYSCALL_CLOBBERLIST, \ 96*d4fe68aeSThomas Weißschuh "%r21", "%r22", "%r23" \ 97*d4fe68aeSThomas Weißschuh ); \ 98*d4fe68aeSThomas Weißschuh _ret; \ 99*d4fe68aeSThomas Weißschuh }) 100*d4fe68aeSThomas Weißschuh 101*d4fe68aeSThomas Weißschuh #define __nolibc_syscall4(num, arg1, arg2, arg3, arg4) \ 102*d4fe68aeSThomas Weißschuh ({ \ 103*d4fe68aeSThomas Weißschuh register long _ret __asm__ ("r28"); \ 104*d4fe68aeSThomas Weißschuh register long _arg1 __asm__ ("r26") = (long)(arg1); \ 105*d4fe68aeSThomas Weißschuh register long _arg2 __asm__ ("r25") = (long)(arg2); \ 106*d4fe68aeSThomas Weißschuh register long _arg3 __asm__ ("r24") = (long)(arg3); \ 107*d4fe68aeSThomas Weißschuh register long _arg4 __asm__ ("r23") = (long)(arg4); \ 108*d4fe68aeSThomas Weißschuh \ 109*d4fe68aeSThomas Weißschuh __asm__ volatile ( \ 110*d4fe68aeSThomas Weißschuh "ble 0x100(%%sr2, %%r0)\n\t" \ 111*d4fe68aeSThomas Weißschuh "copy %5, %%r20\n\t" \ 112*d4fe68aeSThomas Weißschuh : "=r"(_ret), \ 113*d4fe68aeSThomas Weißschuh "+r"(_arg1), "+r"(_arg2), "+r"(_arg3), "+r"(_arg4) \ 114*d4fe68aeSThomas Weißschuh : "r"(num) \ 115*d4fe68aeSThomas Weißschuh : _NOLIBC_SYSCALL_CLOBBERLIST, \ 116*d4fe68aeSThomas Weißschuh "%r21", "%r22" \ 117*d4fe68aeSThomas Weißschuh ); \ 118*d4fe68aeSThomas Weißschuh _ret; \ 119*d4fe68aeSThomas Weißschuh }) 120*d4fe68aeSThomas Weißschuh 121*d4fe68aeSThomas Weißschuh #define __nolibc_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ 122*d4fe68aeSThomas Weißschuh ({ \ 123*d4fe68aeSThomas Weißschuh register long _ret __asm__ ("r28"); \ 124*d4fe68aeSThomas Weißschuh register long _arg1 __asm__ ("r26") = (long)(arg1); \ 125*d4fe68aeSThomas Weißschuh register long _arg2 __asm__ ("r25") = (long)(arg2); \ 126*d4fe68aeSThomas Weißschuh register long _arg3 __asm__ ("r24") = (long)(arg3); \ 127*d4fe68aeSThomas Weißschuh register long _arg4 __asm__ ("r23") = (long)(arg4); \ 128*d4fe68aeSThomas Weißschuh register long _arg5 __asm__ ("r22") = (long)(arg5); \ 129*d4fe68aeSThomas Weißschuh \ 130*d4fe68aeSThomas Weißschuh __asm__ volatile ( \ 131*d4fe68aeSThomas Weißschuh "ble 0x100(%%sr2, %%r0)\n\t" \ 132*d4fe68aeSThomas Weißschuh "copy %6, %%r20\n\t" \ 133*d4fe68aeSThomas Weißschuh : "=r"(_ret), \ 134*d4fe68aeSThomas Weißschuh "+r"(_arg1), "+r"(_arg2), "+r"(_arg3), "+r"(_arg4), \ 135*d4fe68aeSThomas Weißschuh "+r"(_arg5) \ 136*d4fe68aeSThomas Weißschuh : "r"(num) \ 137*d4fe68aeSThomas Weißschuh : _NOLIBC_SYSCALL_CLOBBERLIST, \ 138*d4fe68aeSThomas Weißschuh "%r21" \ 139*d4fe68aeSThomas Weißschuh ); \ 140*d4fe68aeSThomas Weißschuh _ret; \ 141*d4fe68aeSThomas Weißschuh }) 142*d4fe68aeSThomas Weißschuh 143*d4fe68aeSThomas Weißschuh #define __nolibc_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \ 144*d4fe68aeSThomas Weißschuh ({ \ 145*d4fe68aeSThomas Weißschuh register long _ret __asm__ ("r28"); \ 146*d4fe68aeSThomas Weißschuh register long _arg1 __asm__ ("r26") = (long)(arg1); \ 147*d4fe68aeSThomas Weißschuh register long _arg2 __asm__ ("r25") = (long)(arg2); \ 148*d4fe68aeSThomas Weißschuh register long _arg3 __asm__ ("r24") = (long)(arg3); \ 149*d4fe68aeSThomas Weißschuh register long _arg4 __asm__ ("r23") = (long)(arg4); \ 150*d4fe68aeSThomas Weißschuh register long _arg5 __asm__ ("r22") = (long)(arg5); \ 151*d4fe68aeSThomas Weißschuh register long _arg6 __asm__ ("r21") = (long)(arg6); \ 152*d4fe68aeSThomas Weißschuh \ 153*d4fe68aeSThomas Weißschuh __asm__ volatile ( \ 154*d4fe68aeSThomas Weißschuh "ble 0x100(%%sr2, %%r0)\n\t" \ 155*d4fe68aeSThomas Weißschuh "copy %7, %%r20\n\t" \ 156*d4fe68aeSThomas Weißschuh : "=r"(_ret), \ 157*d4fe68aeSThomas Weißschuh "+r"(_arg1), "+r"(_arg2), "+r"(_arg3), "+r"(_arg4), \ 158*d4fe68aeSThomas Weißschuh "+r"(_arg5), "+r"(_arg6) \ 159*d4fe68aeSThomas Weißschuh : "r"(num) \ 160*d4fe68aeSThomas Weißschuh : _NOLIBC_SYSCALL_CLOBBERLIST \ 161*d4fe68aeSThomas Weißschuh ); \ 162*d4fe68aeSThomas Weißschuh _ret; \ 163*d4fe68aeSThomas Weißschuh }) 164*d4fe68aeSThomas Weißschuh 165*d4fe68aeSThomas Weißschuh #ifndef NOLIBC_NO_RUNTIME 166*d4fe68aeSThomas Weißschuh /* startup code */ 167*d4fe68aeSThomas Weißschuh void __attribute__((weak, noreturn)) __nolibc_entrypoint __nolibc_no_stack_protector _start(void) 168*d4fe68aeSThomas Weißschuh { 169*d4fe68aeSThomas Weißschuh __asm__ volatile ( 170*d4fe68aeSThomas Weißschuh ".import $global$\n" /* Set up the dp register */ 171*d4fe68aeSThomas Weißschuh "ldil L%$global$, %dp\n" 172*d4fe68aeSThomas Weißschuh "ldo R%$global$(%r27), %dp\n" 173*d4fe68aeSThomas Weißschuh 174*d4fe68aeSThomas Weißschuh "b _start_c\n" /* Call _start_c, the load below is executed first */ 175*d4fe68aeSThomas Weißschuh 176*d4fe68aeSThomas Weißschuh "ldo -4(%r24), %r26\n" /* The sp register is special on parisc. 177*d4fe68aeSThomas Weißschuh * r24 points to argv. Subtract 4 to get &argc. 178*d4fe68aeSThomas Weißschuh * Pass that as first argument to _start_c. 179*d4fe68aeSThomas Weißschuh */ 180*d4fe68aeSThomas Weißschuh ); 181*d4fe68aeSThomas Weißschuh __nolibc_entrypoint_epilogue(); 182*d4fe68aeSThomas Weißschuh } 183*d4fe68aeSThomas Weißschuh #endif /* NOLIBC_NO_RUNTIME */ 184*d4fe68aeSThomas Weißschuh 185*d4fe68aeSThomas Weißschuh #endif /* _NOLIBC_ARCH_PARISC_H */ 186