1 /* Assembler macros for ARM. 2 Copyright (C) 1997, 1998, 2003 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 The GNU C Library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; if not, see 17 <http://www.gnu.org/licenses/>. */ 18 19 #ifndef _LINUX_ARM_SYSDEP_H 20 #define _LINUX_ARM_SYSDEP_H 1 21 22 #include <common/sysdep.h> 23 #include <bits/arm_bx.h> 24 #include <sys/syscall.h> 25 /* For Linux we can use the system call table in the header file 26 /usr/include/asm/unistd.h 27 of the kernel. But these symbols do not follow the SYS_* syntax 28 so we have to redefine the `SYS_ify' macro here. */ 29 #undef SYS_ify 30 #define SWI_BASE (0x900000) 31 #define SYS_ify(syscall_name) (__NR_##syscall_name) 32 33 #ifdef __ASSEMBLER__ 34 35 /* Syntactic details of assembler. */ 36 37 #define ALIGNARG(log2) log2 38 /* For ELF we need the `.type' directive to make shared libs work right. */ 39 #define ASM_TYPE_DIRECTIVE(name,typearg) .type name,%##typearg; 40 #define ASM_SIZE_DIRECTIVE(name) .size name,.-name 41 42 /* In ELF C symbols are asm symbols. */ 43 #undef NO_UNDERSCORES 44 #define NO_UNDERSCORES 45 46 #define PLTJMP(_x) _x##(PLT) 47 48 /* APCS-32 doesn't preserve the condition codes across function call. */ 49 #ifdef __APCS_32__ 50 #define LOADREGS(cond, base, reglist...)\ 51 ldm##cond base,reglist 52 #define RETINSTR(cond, reg) \ 53 BXC(cond, reg) 54 #define DO_RET(_reg) \ 55 BX(_reg) 56 #else /* APCS-26 */ 57 #define LOADREGS(cond, base, reglist...) \ 58 ldm##cond base,reglist^ 59 #define RETINSTR(cond, reg) \ 60 mov##cond##s pc, reg 61 #define DO_RET(_reg) \ 62 movs pc, _reg 63 #endif 64 65 /* Define an entry point visible from C. */ 66 #define ENTRY(name) \ 67 .globl C_SYMBOL_NAME(name); \ 68 ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),function) \ 69 .align ALIGNARG(4); \ 70 name##: 71 72 #undef END 73 #define END(name) \ 74 ASM_SIZE_DIRECTIVE(name) 75 76 #ifdef NO_UNDERSCORES 77 /* Since C identifiers are not normally prefixed with an underscore 78 on this system, the asm identifier `syscall_error' intrudes on the 79 C name space. Make sure we use an innocuous name. */ 80 #define syscall_error __syscall_error 81 #define mcount _mcount 82 #endif 83 /* Linux uses a negative return value to indicate syscall errors, 84 unlike most Unices, which use the condition codes' carry flag. 85 86 Since version 2.1 the return value of a system call might be 87 negative even if the call succeeded. E.g., the `lseek' system call 88 might return a large offset. Therefore we must not anymore test 89 for < 0, but test for a real error by making sure the value in R0 90 is a real error number. Linus said he will make sure the no syscall 91 returns a value in -1 .. -4095 as a valid result so we can safely 92 test with -4095. */ 93 94 #undef PSEUDO 95 #define PSEUDO(name, syscall_name, args) \ 96 .text; \ 97 ENTRY (name); \ 98 DO_CALL (syscall_name, args); \ 99 cmn r0, $4096; 100 101 #define PSEUDO_RET \ 102 RETINSTR(cc, lr); \ 103 b PLTJMP(SYSCALL_ERROR) 104 #undef ret 105 #define ret PSEUDO_RET 106 107 #undef PSEUDO_END 108 #define PSEUDO_END(name) \ 109 SYSCALL_ERROR_HANDLER \ 110 END (name) 111 112 #undef PSEUDO_NOERRNO 113 #define PSEUDO_NOERRNO(name, syscall_name, args) \ 114 .text; \ 115 ENTRY (name); \ 116 DO_CALL (syscall_name, args); 117 118 #define PSEUDO_RET_NOERRNO \ 119 DO_RET (lr); 120 121 #undef ret_NOERRNO 122 #define ret_NOERRNO PSEUDO_RET_NOERRNO 123 124 #undef PSEUDO_END_NOERRNO 125 #define PSEUDO_END_NOERRNO(name) \ 126 END (name) 127 128 /* The function has to return the error code. */ 129 #undef PSEUDO_ERRVAL 130 #define PSEUDO_ERRVAL(name, syscall_name, args) \ 131 .text; \ 132 ENTRY (name) \ 133 DO_CALL (syscall_name, args); \ 134 rsb r0, r0, #0 135 136 #undef PSEUDO_END_ERRVAL 137 #define PSEUDO_END_ERRVAL(name) \ 138 END (name) 139 140 #if defined NOT_IN_libc 141 # define SYSCALL_ERROR __local_syscall_error 142 # define SYSCALL_ERROR_HANDLER \ 143 __local_syscall_error: \ 144 str lr, [sp, #-4]!; \ 145 str r0, [sp, #-4]!; \ 146 bl PLTJMP(C_SYMBOL_NAME(__errno_location)); \ 147 ldr r1, [sp], #4; \ 148 rsb r1, r1, #0; \ 149 str r1, [r0]; \ 150 mvn r0, #0; \ 151 ldr pc, [sp], #4; 152 #else 153 # define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */ 154 # define SYSCALL_ERROR __syscall_error 155 #endif 156 157 /* Linux takes system call args in registers: 158 syscall number in the SWI instruction 159 arg 1 r0 160 arg 2 r1 161 arg 3 r2 162 arg 4 r3 163 arg 5 r4 (this is different from the APCS convention) 164 arg 6 r5 165 arg 7 r6 166 167 The compiler is going to form a call by coming here, through PSEUDO, with 168 arguments 169 syscall number in the DO_CALL macro 170 arg 1 r0 171 arg 2 r1 172 arg 3 r2 173 arg 4 r3 174 arg 5 [sp] 175 arg 6 [sp+4] 176 arg 7 [sp+8] 177 178 We need to shuffle values between R4..R6 and the stack so that the 179 caller's v1..v3 and stack frame are not corrupted, and the kernel 180 sees the right arguments. 181 182 */ 183 #if __ARM_ARCH > 6 || defined (__ARM_ARCH_6K__) || defined (__ARM_ARCH_6ZK__) 184 # define ARCH_HAS_HARD_TP 185 #endif 186 187 # ifdef __thumb2__ 188 # define NEGOFF_ADJ_BASE(R, OFF) add R, R, $OFF 189 # define NEGOFF_ADJ_BASE2(D, S, OFF) add D, S, $OFF 190 # define NEGOFF_OFF1(R, OFF) [R] 191 # define NEGOFF_OFF2(R, OFFA, OFFB) [R, $((OFFA) - (OFFB))] 192 # else 193 # define NEGOFF_ADJ_BASE(R, OFF) 194 # define NEGOFF_ADJ_BASE2(D, S, OFF) mov D, S 195 # define NEGOFF_OFF1(R, OFF) [R, $OFF] 196 # define NEGOFF_OFF2(R, OFFA, OFFB) [R, $OFFA] 197 # endif 198 199 # ifdef ARCH_HAS_HARD_TP 200 /* If the cpu has cp15 available, use it. */ 201 # define GET_TLS(TMP) mrc p15, 0, r0, c13, c0, 3 202 # else 203 /* At this generic level we have no tricks to pull. Call the ABI routine. */ 204 # define GET_TLS(TMP) \ 205 push { r1, r2, r3, lr }; \ 206 cfi_remember_state; \ 207 cfi_adjust_cfa_offset (16); \ 208 cfi_rel_offset (r1, 0); \ 209 cfi_rel_offset (r2, 4); \ 210 cfi_rel_offset (r3, 8); \ 211 cfi_rel_offset (lr, 12); \ 212 bl __aeabi_read_tp; \ 213 pop { r1, r2, r3, lr }; \ 214 cfi_restore_state 215 # endif /* ARCH_HAS_HARD_TP */ 216 217 218 219 220 #undef DO_CALL 221 #if defined(__ARM_EABI__) 222 #define DO_CALL(syscall_name, args) \ 223 DOARGS_##args \ 224 mov ip, r7; \ 225 ldr r7, =SYS_ify (syscall_name); \ 226 swi 0x0; \ 227 mov r7, ip; \ 228 UNDOARGS_##args 229 #else 230 #define DO_CALL(syscall_name, args) \ 231 DOARGS_##args \ 232 swi SYS_ify (syscall_name); \ 233 UNDOARGS_##args 234 #endif 235 236 #define DOARGS_0 /* nothing */ 237 #define DOARGS_1 /* nothing */ 238 #define DOARGS_2 /* nothing */ 239 #define DOARGS_3 /* nothing */ 240 #define DOARGS_4 /* nothing */ 241 #define DOARGS_5 str r4, [sp, $-4]!; ldr r4, [sp, $4]; 242 #define DOARGS_6 mov ip, sp; stmfd sp!, {r4, r5}; ldmia ip, {r4, r5}; 243 #define DOARGS_7 mov ip, sp; stmfd sp!, {r4, r5, r6}; ldmia ip, {r4, r5, r6}; 244 245 #define UNDOARGS_0 /* nothing */ 246 #define UNDOARGS_1 /* nothing */ 247 #define UNDOARGS_2 /* nothing */ 248 #define UNDOARGS_3 /* nothing */ 249 #define UNDOARGS_4 /* nothing */ 250 #define UNDOARGS_5 ldr r4, [sp], $4; 251 #define UNDOARGS_6 ldmfd sp!, {r4, r5}; 252 #define UNDOARGS_7 ldmfd sp!, {r4, r5, r6}; 253 254 #endif /* __ASSEMBLER__ */ 255 #endif /* linux/arm/sysdep.h */ 256