1*b58afc8dSThomas Weißschuh /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 2*b58afc8dSThomas Weißschuh /* 3*b58afc8dSThomas Weißschuh * Alpha specific definitions for NOLIBC 4*b58afc8dSThomas Weißschuh * Copyright (C) 2025 Thomas Weißschuh <linux@weissschuh.net> 5*b58afc8dSThomas Weißschuh */ 6*b58afc8dSThomas Weißschuh 7*b58afc8dSThomas Weißschuh #ifndef _NOLIBC_ARCH_ALPHA_H 8*b58afc8dSThomas Weißschuh #define _NOLIBC_ARCH_ALPHA_H 9*b58afc8dSThomas Weißschuh 10*b58afc8dSThomas Weißschuh #include "compiler.h" 11*b58afc8dSThomas Weißschuh #include "crt.h" 12*b58afc8dSThomas Weißschuh 13*b58afc8dSThomas Weißschuh /* 14*b58afc8dSThomas Weißschuh * Syscalls for Alpha: 15*b58afc8dSThomas Weißschuh * - registers are 64-bit 16*b58afc8dSThomas Weißschuh * - syscall number is passed in $0/v0 17*b58afc8dSThomas Weißschuh * - the system call is performed by calling callsys 18*b58afc8dSThomas Weißschuh * - syscall return comes in $0/v0, error flag in $19/a3 19*b58afc8dSThomas Weißschuh * - arguments are passed in $16/a0 to $21/a5 20*b58afc8dSThomas Weißschuh * - GCC does not support symbol register names 21*b58afc8dSThomas Weißschuh */ 22*b58afc8dSThomas Weißschuh 23*b58afc8dSThomas Weißschuh #define _NOLIBC_SYSCALL_CLOBBERLIST \ 24*b58afc8dSThomas Weißschuh "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", \ 25*b58afc8dSThomas Weißschuh "$22", "$23", "$24", "$25", "$27", "$28", "memory", "cc" 26*b58afc8dSThomas Weißschuh 27*b58afc8dSThomas Weißschuh #define __nolibc_syscall0(num) \ 28*b58afc8dSThomas Weißschuh ({ \ 29*b58afc8dSThomas Weißschuh register long _num __asm__ ("$0") = (num); \ 30*b58afc8dSThomas Weißschuh register long _err __asm__ ("$19"); \ 31*b58afc8dSThomas Weißschuh \ 32*b58afc8dSThomas Weißschuh __asm__ volatile ( \ 33*b58afc8dSThomas Weißschuh "callsys" \ 34*b58afc8dSThomas Weißschuh : "+r"(_num), "=r"(_err) \ 35*b58afc8dSThomas Weißschuh : \ 36*b58afc8dSThomas Weißschuh : _NOLIBC_SYSCALL_CLOBBERLIST, \ 37*b58afc8dSThomas Weißschuh "$16", "$17", "$18", "$20", "$21" \ 38*b58afc8dSThomas Weißschuh ); \ 39*b58afc8dSThomas Weißschuh _err ? -_num : _num; \ 40*b58afc8dSThomas Weißschuh }) 41*b58afc8dSThomas Weißschuh 42*b58afc8dSThomas Weißschuh #define __nolibc_syscall1(num, arg1) \ 43*b58afc8dSThomas Weißschuh ({ \ 44*b58afc8dSThomas Weißschuh register long _num __asm__ ("$0") = (num); \ 45*b58afc8dSThomas Weißschuh register long _err __asm__ ("$19"); \ 46*b58afc8dSThomas Weißschuh register long _arg1 __asm__ ("$16") = (long)(arg1); \ 47*b58afc8dSThomas Weißschuh \ 48*b58afc8dSThomas Weißschuh __asm__ volatile ( \ 49*b58afc8dSThomas Weißschuh "callsys" \ 50*b58afc8dSThomas Weißschuh : "+r"(_num), "=r"(_err) \ 51*b58afc8dSThomas Weißschuh : "r"(_arg1) \ 52*b58afc8dSThomas Weißschuh : _NOLIBC_SYSCALL_CLOBBERLIST, "$17", "$18", "$20", "$21" \ 53*b58afc8dSThomas Weißschuh ); \ 54*b58afc8dSThomas Weißschuh _err ? -_num : _num; \ 55*b58afc8dSThomas Weißschuh }) 56*b58afc8dSThomas Weißschuh 57*b58afc8dSThomas Weißschuh #define __nolibc_syscall2(num, arg1, arg2) \ 58*b58afc8dSThomas Weißschuh ({ \ 59*b58afc8dSThomas Weißschuh register long _num __asm__ ("$0") = (num); \ 60*b58afc8dSThomas Weißschuh register long _err __asm__ ("$19"); \ 61*b58afc8dSThomas Weißschuh register long _arg1 __asm__ ("$16") = (long)(arg1); \ 62*b58afc8dSThomas Weißschuh register long _arg2 __asm__ ("$17") = (long)(arg2); \ 63*b58afc8dSThomas Weißschuh \ 64*b58afc8dSThomas Weißschuh __asm__ volatile ( \ 65*b58afc8dSThomas Weißschuh "callsys" \ 66*b58afc8dSThomas Weißschuh : "+r"(_num), "=r"(_err) \ 67*b58afc8dSThomas Weißschuh : "r"(_arg1), "r"(_arg2) \ 68*b58afc8dSThomas Weißschuh : _NOLIBC_SYSCALL_CLOBBERLIST, "$18", "$20", "$21" \ 69*b58afc8dSThomas Weißschuh ); \ 70*b58afc8dSThomas Weißschuh _err ? -_num : _num; \ 71*b58afc8dSThomas Weißschuh }) 72*b58afc8dSThomas Weißschuh 73*b58afc8dSThomas Weißschuh #define __nolibc_syscall3(num, arg1, arg2, arg3) \ 74*b58afc8dSThomas Weißschuh ({ \ 75*b58afc8dSThomas Weißschuh register long _num __asm__ ("$0") = (num); \ 76*b58afc8dSThomas Weißschuh register long _err __asm__ ("$19"); \ 77*b58afc8dSThomas Weißschuh register long _arg1 __asm__ ("$16") = (long)(arg1); \ 78*b58afc8dSThomas Weißschuh register long _arg2 __asm__ ("$17") = (long)(arg2); \ 79*b58afc8dSThomas Weißschuh register long _arg3 __asm__ ("$18") = (long)(arg3); \ 80*b58afc8dSThomas Weißschuh \ 81*b58afc8dSThomas Weißschuh __asm__ volatile ( \ 82*b58afc8dSThomas Weißschuh "callsys" \ 83*b58afc8dSThomas Weißschuh : "+r"(_num), "=r"(_err) \ 84*b58afc8dSThomas Weißschuh : "r"(_arg1), "r"(_arg2), "r"(_arg3) \ 85*b58afc8dSThomas Weißschuh : _NOLIBC_SYSCALL_CLOBBERLIST, "$20", "$21" \ 86*b58afc8dSThomas Weißschuh ); \ 87*b58afc8dSThomas Weißschuh _err ? -_num : _num; \ 88*b58afc8dSThomas Weißschuh }) 89*b58afc8dSThomas Weißschuh 90*b58afc8dSThomas Weißschuh #define __nolibc_syscall4(num, arg1, arg2, arg3, arg4) \ 91*b58afc8dSThomas Weißschuh ({ \ 92*b58afc8dSThomas Weißschuh register long _num __asm__ ("$0") = (num); \ 93*b58afc8dSThomas Weißschuh register long _arg1 __asm__ ("$16") = (long)(arg1); \ 94*b58afc8dSThomas Weißschuh register long _arg2 __asm__ ("$17") = (long)(arg2); \ 95*b58afc8dSThomas Weißschuh register long _arg3 __asm__ ("$18") = (long)(arg3); \ 96*b58afc8dSThomas Weißschuh register long _arg4 __asm__ ("$19") = (long)(arg4); \ 97*b58afc8dSThomas Weißschuh \ 98*b58afc8dSThomas Weißschuh __asm__ volatile ( \ 99*b58afc8dSThomas Weißschuh "callsys" \ 100*b58afc8dSThomas Weißschuh : "+r"(_num), "+r"(_arg4) \ 101*b58afc8dSThomas Weißschuh : "r"(_arg1), "r"(_arg2), "r"(_arg3) \ 102*b58afc8dSThomas Weißschuh : _NOLIBC_SYSCALL_CLOBBERLIST, "$20", "$21" \ 103*b58afc8dSThomas Weißschuh ); \ 104*b58afc8dSThomas Weißschuh _arg4 ? -_num : _num; \ 105*b58afc8dSThomas Weißschuh }) 106*b58afc8dSThomas Weißschuh 107*b58afc8dSThomas Weißschuh #define __nolibc_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ 108*b58afc8dSThomas Weißschuh ({ \ 109*b58afc8dSThomas Weißschuh register long _num __asm__ ("$0") = (num); \ 110*b58afc8dSThomas Weißschuh register long _arg1 __asm__ ("$16") = (long)(arg1); \ 111*b58afc8dSThomas Weißschuh register long _arg2 __asm__ ("$17") = (long)(arg2); \ 112*b58afc8dSThomas Weißschuh register long _arg3 __asm__ ("$18") = (long)(arg3); \ 113*b58afc8dSThomas Weißschuh register long _arg4 __asm__ ("$19") = (long)(arg4); \ 114*b58afc8dSThomas Weißschuh register long _arg5 __asm__ ("$20") = (long)(arg5); \ 115*b58afc8dSThomas Weißschuh \ 116*b58afc8dSThomas Weißschuh __asm__ volatile ( \ 117*b58afc8dSThomas Weißschuh "callsys" \ 118*b58afc8dSThomas Weißschuh : "+r"(_num), "+r"(_arg4) \ 119*b58afc8dSThomas Weißschuh : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg5) \ 120*b58afc8dSThomas Weißschuh : _NOLIBC_SYSCALL_CLOBBERLIST, "$21" \ 121*b58afc8dSThomas Weißschuh ); \ 122*b58afc8dSThomas Weißschuh _arg4 ? -_num : _num; \ 123*b58afc8dSThomas Weißschuh }) 124*b58afc8dSThomas Weißschuh 125*b58afc8dSThomas Weißschuh #define __nolibc_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \ 126*b58afc8dSThomas Weißschuh ({ \ 127*b58afc8dSThomas Weißschuh register long _num __asm__ ("$0") = (num); \ 128*b58afc8dSThomas Weißschuh register long _arg1 __asm__ ("$16") = (long)(arg1); \ 129*b58afc8dSThomas Weißschuh register long _arg2 __asm__ ("$17") = (long)(arg2); \ 130*b58afc8dSThomas Weißschuh register long _arg3 __asm__ ("$18") = (long)(arg3); \ 131*b58afc8dSThomas Weißschuh register long _arg4 __asm__ ("$19") = (long)(arg4); \ 132*b58afc8dSThomas Weißschuh register long _arg5 __asm__ ("$20") = (long)(arg5); \ 133*b58afc8dSThomas Weißschuh register long _arg6 __asm__ ("$21") = (long)(arg6); \ 134*b58afc8dSThomas Weißschuh \ 135*b58afc8dSThomas Weißschuh __asm__ volatile ( \ 136*b58afc8dSThomas Weißschuh "callsys" \ 137*b58afc8dSThomas Weißschuh : "+r"(_num), "+r"(_arg4) \ 138*b58afc8dSThomas Weißschuh : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg5), \ 139*b58afc8dSThomas Weißschuh "r"(_arg6) \ 140*b58afc8dSThomas Weißschuh : _NOLIBC_SYSCALL_CLOBBERLIST \ 141*b58afc8dSThomas Weißschuh ); \ 142*b58afc8dSThomas Weißschuh _arg4 ? -_num : _num; \ 143*b58afc8dSThomas Weißschuh }) 144*b58afc8dSThomas Weißschuh 145*b58afc8dSThomas Weißschuh /* startup code */ 146*b58afc8dSThomas Weißschuh void __attribute__((weak, noreturn)) __nolibc_entrypoint __nolibc_no_stack_protector 147*b58afc8dSThomas Weißschuh _start(void) 148*b58afc8dSThomas Weißschuh { 149*b58afc8dSThomas Weißschuh __asm__ volatile ( 150*b58afc8dSThomas Weißschuh "br $gp, 0f\n" /* setup $gp, so that 'lda' works */ 151*b58afc8dSThomas Weißschuh "0: ldgp $gp, 0($gp)\n" 152*b58afc8dSThomas Weißschuh "lda $27, _start_c\n" /* setup current function address for _start_c */ 153*b58afc8dSThomas Weißschuh "mov $sp, $16\n" /* save argc pointer to $16, as arg1 of _start_c */ 154*b58afc8dSThomas Weißschuh "br _start_c\n" /* transfer to c runtime */ 155*b58afc8dSThomas Weißschuh ); 156*b58afc8dSThomas Weißschuh __nolibc_entrypoint_epilogue(); 157*b58afc8dSThomas Weißschuh } 158*b58afc8dSThomas Weißschuh 159*b58afc8dSThomas Weißschuh #endif /* _NOLIBC_ARCH_ALPHA_H */ 160