1 /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 2 /* 3 * SuperH specific definitions for NOLIBC 4 * Copyright (C) 2025 Thomas Weißschuh <linux@weissschuh.net> 5 */ 6 7 #ifndef _NOLIBC_ARCH_SH_H 8 #define _NOLIBC_ARCH_SH_H 9 10 #include "compiler.h" 11 #include "crt.h" 12 13 /* 14 * Syscalls for SuperH: 15 * - registers are 32bit wide 16 * - syscall number is passed in r3 17 * - arguments are in r4, r5, r6, r7, r0, r1, r2 18 * - the system call is performed by calling trapa #31 19 * - syscall return value is in r0 20 */ 21 22 #define my_syscall0(num) \ 23 ({ \ 24 register long _num __asm__ ("r3") = (num); \ 25 register long _ret __asm__ ("r0"); \ 26 \ 27 __asm__ volatile ( \ 28 "trapa #31" \ 29 : "=r"(_ret) \ 30 : "r"(_num) \ 31 : "memory", "cc" \ 32 ); \ 33 _ret; \ 34 }) 35 36 #define my_syscall1(num, arg1) \ 37 ({ \ 38 register long _num __asm__ ("r3") = (num); \ 39 register long _ret __asm__ ("r0"); \ 40 register long _arg1 __asm__ ("r4") = (long)(arg1); \ 41 \ 42 __asm__ volatile ( \ 43 "trapa #31" \ 44 : "=r"(_ret) \ 45 : "r"(_num), "r"(_arg1) \ 46 : "memory", "cc" \ 47 ); \ 48 _ret; \ 49 }) 50 51 #define my_syscall2(num, arg1, arg2) \ 52 ({ \ 53 register long _num __asm__ ("r3") = (num); \ 54 register long _ret __asm__ ("r0"); \ 55 register long _arg1 __asm__ ("r4") = (long)(arg1); \ 56 register long _arg2 __asm__ ("r5") = (long)(arg2); \ 57 \ 58 __asm__ volatile ( \ 59 "trapa #31" \ 60 : "=r"(_ret) \ 61 : "r"(_num), "r"(_arg1), "r"(_arg2) \ 62 : "memory", "cc" \ 63 ); \ 64 _ret; \ 65 }) 66 67 #define my_syscall3(num, arg1, arg2, arg3) \ 68 ({ \ 69 register long _num __asm__ ("r3") = (num); \ 70 register long _ret __asm__ ("r0"); \ 71 register long _arg1 __asm__ ("r4") = (long)(arg1); \ 72 register long _arg2 __asm__ ("r5") = (long)(arg2); \ 73 register long _arg3 __asm__ ("r6") = (long)(arg3); \ 74 \ 75 __asm__ volatile ( \ 76 "trapa #31" \ 77 : "=r"(_ret) \ 78 : "r"(_num), "r"(_arg1), "r"(_arg2), "r"(_arg3) \ 79 : "memory", "cc" \ 80 ); \ 81 _ret; \ 82 }) 83 84 #define my_syscall4(num, arg1, arg2, arg3, arg4) \ 85 ({ \ 86 register long _num __asm__ ("r3") = (num); \ 87 register long _ret __asm__ ("r0"); \ 88 register long _arg1 __asm__ ("r4") = (long)(arg1); \ 89 register long _arg2 __asm__ ("r5") = (long)(arg2); \ 90 register long _arg3 __asm__ ("r6") = (long)(arg3); \ 91 register long _arg4 __asm__ ("r7") = (long)(arg4); \ 92 \ 93 __asm__ volatile ( \ 94 "trapa #31" \ 95 : "=r"(_ret) \ 96 : "r"(_num), "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4) \ 97 : "memory", "cc" \ 98 ); \ 99 _ret; \ 100 }) 101 102 #define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \ 103 ({ \ 104 register long _num __asm__ ("r3") = (num); \ 105 register long _ret __asm__ ("r0"); \ 106 register long _arg1 __asm__ ("r4") = (long)(arg1); \ 107 register long _arg2 __asm__ ("r5") = (long)(arg2); \ 108 register long _arg3 __asm__ ("r6") = (long)(arg3); \ 109 register long _arg4 __asm__ ("r7") = (long)(arg4); \ 110 register long _arg5 __asm__ ("r0") = (long)(arg5); \ 111 \ 112 __asm__ volatile ( \ 113 "trapa #31" \ 114 : "=r"(_ret) \ 115 : "r"(_num), "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ 116 "r"(_arg5) \ 117 : "memory", "cc" \ 118 ); \ 119 _ret; \ 120 }) 121 122 #define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \ 123 ({ \ 124 register long _num __asm__ ("r3") = (num); \ 125 register long _ret __asm__ ("r0"); \ 126 register long _arg1 __asm__ ("r4") = (long)(arg1); \ 127 register long _arg2 __asm__ ("r5") = (long)(arg2); \ 128 register long _arg3 __asm__ ("r6") = (long)(arg3); \ 129 register long _arg4 __asm__ ("r7") = (long)(arg4); \ 130 register long _arg5 __asm__ ("r0") = (long)(arg5); \ 131 register long _arg6 __asm__ ("r1") = (long)(arg6); \ 132 \ 133 __asm__ volatile ( \ 134 "trapa #31" \ 135 : "=r"(_ret) \ 136 : "r"(_num), "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \ 137 "r"(_arg5), "r"(_arg6) \ 138 : "memory", "cc" \ 139 ); \ 140 _ret; \ 141 }) 142 143 /* startup code */ 144 void _start_wrapper(void); 145 void __attribute__((weak,noreturn)) __nolibc_entrypoint __no_stack_protector _start_wrapper(void) 146 { 147 __asm__ volatile ( 148 ".global _start\n" /* The C function will have a prologue, */ 149 ".type _start, @function\n" /* corrupting "sp" */ 150 ".weak _start\n" 151 "_start:\n" 152 153 "mov sp, r4\n" /* save argc pointer to r4, as arg1 of _start_c */ 154 "bsr _start_c\n" /* transfer to c runtime */ 155 "nop\n" /* delay slot */ 156 157 ".size _start, .-_start\n" 158 ); 159 __nolibc_entrypoint_epilogue(); 160 } 161 162 #endif /* _NOLIBC_ARCH_SH_H */ 163