1 /* Assembler macros for SH. 2 Copyright (C) 1999, 2000, 2005 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 #include <common/sysdep.h> 20 21 #include <features.h> 22 23 #ifdef __ASSEMBLER__ 24 25 /* Syntactic details of assembler. */ 26 27 #define LOCAL(X) .L_##X 28 #define ALIGNARG(log2) log2 29 /* For ELF we need the `.type' directive to make shared libs work right. */ 30 #define ASM_TYPE_DIRECTIVE(name,typearg) .type name,@##typearg; 31 #define ASM_SIZE_DIRECTIVE(name) .size name,.-name 32 33 #ifdef SHARED 34 #define PLTJMP(_x) _x##@PLT 35 #else 36 #define PLTJMP(_x) _x 37 #endif 38 39 /* Define an entry point visible from C. */ 40 #define ENTRY(name) \ 41 .globl C_SYMBOL_NAME(name); \ 42 ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),function) \ 43 .align ALIGNARG(5); \ 44 C_LABEL(name) \ 45 cfi_startproc; 46 47 #undef END 48 #define END(name) \ 49 cfi_endproc; \ 50 ASM_SIZE_DIRECTIVE(C_SYMBOL_NAME(name)) 51 52 #ifdef __UCLIBC_UNDERSCORES__ 53 /* Since C identifiers are not normally prefixed with an underscore 54 on this system, the asm identifier `syscall_error' intrudes on the 55 C name space. Make sure we use an innocuous name. */ 56 #define syscall_error __syscall_error 57 #define mcount _mcount 58 #endif 59 60 /* For Linux we can use the system call table in the header file 61 /usr/include/asm/unistd.h 62 of the kernel. But these symbols do not follow the SYS_* syntax 63 so we have to redefine the `SYS_ify' macro here. */ 64 #undef SYS_ify 65 #define SYS_ify(syscall_name) (__NR_##syscall_name) 66 67 #define ret rts ; nop 68 /* The sh move insn is s, d. */ 69 #define MOVE(x,y) mov x , y 70 71 /* Linux uses a negative return value to indicate syscall errors, 72 unlike most Unices, which use the condition codes' carry flag. 73 74 Since version 2.1 the return value of a system call might be 75 negative even if the call succeeded. E.g., the `lseek' system call 76 might return a large offset. Therefore we must not anymore test 77 for < 0, but test for a real error by making sure the value in R0 78 is a real error number. Linus said he will make sure the no syscall 79 returns a value in -1 .. -4095 as a valid result so we can savely 80 test with -4095. */ 81 82 #define _IMM1 #-1 83 #define _IMM12 #-12 84 #undef PSEUDO 85 #define PSEUDO(name, syscall_name, args) \ 86 .text; \ 87 ENTRY (name); \ 88 DO_CALL (syscall_name, args); \ 89 mov r0,r1; \ 90 mov _IMM12,r2; \ 91 shad r2,r1; \ 92 not r1,r1; \ 93 tst r1,r1; \ 94 bf .Lpseudo_end; \ 95 SYSCALL_ERROR_HANDLER; \ 96 .Lpseudo_end: 97 98 #undef PSEUDO_END 99 #define PSEUDO_END(name) \ 100 END (name) 101 102 #undef PSEUDO_NOERRNO 103 #define PSEUDO_NOERRNO(name, syscall_name, args) \ 104 .text; \ 105 ENTRY (name); \ 106 DO_CALL (syscall_name, args) 107 108 #undef PSEUDO_END_NOERRNO 109 #define PSEUDO_END_NOERRNO(name) \ 110 END (name) 111 112 #define ret_NOERRNO ret 113 114 #define PSEUDO_ERRVAL(name, syscall_name, args) \ 115 .text; \ 116 ENTRY (name); \ 117 DO_CALL (syscall_name, args); 118 119 #undef PSEUDO_END_ERRVAL 120 #define PSEUDO_END_ERRVAL(name) \ 121 END (name) 122 123 #ifndef __PIC__ 124 # define SYSCALL_ERROR_HANDLER \ 125 mov.l 0f,r1; \ 126 jmp @r1; \ 127 mov r0,r4; \ 128 .align 2; \ 129 0: .long __syscall_error 130 131 #include <libc/sysdeps/linux/sh/syscall_error.S> 132 #else 133 # if defined _LIBC_REENTRANT 134 135 # if defined USE___THREAD 136 137 # define SYSCALL_ERROR_ERRNO errno 138 # define SYSCALL_ERROR_HANDLER \ 139 neg r0,r1; \ 140 mov r12,r2; \ 141 mov.l 0f,r12; \ 142 mova 0f,r0; \ 143 add r0,r12; \ 144 mov.l 1f,r0; \ 145 stc gbr, r4; \ 146 mov.l @(r0,r12),r0; \ 147 bra .Lskip; \ 148 add r4,r0; \ 149 .align 2; \ 150 1: .long SYSCALL_ERROR_ERRNO@GOTTPOFF; \ 151 .Lskip: \ 152 mov r2,r12; \ 153 mov.l r1,@r0; \ 154 bra .Lpseudo_end; \ 155 mov _IMM1,r0; \ 156 .align 2; \ 157 0: .long _GLOBAL_OFFSET_TABLE_ 158 # else 159 160 # define SYSCALL_ERROR_HANDLER \ 161 neg r0,r1; \ 162 mov.l r14,@-r15; \ 163 mov.l r12,@-r15; \ 164 mov.l r1,@-r15; \ 165 mov.l 0f,r12; \ 166 mova 0f,r0; \ 167 add r0,r12; \ 168 sts.l pr,@-r15; \ 169 mov r15,r14; \ 170 mov.l 1f,r1; \ 171 bsrf r1; \ 172 nop; \ 173 2: mov r14,r15; \ 174 lds.l @r15+,pr; \ 175 mov.l @r15+,r1; \ 176 mov.l r1,@r0; \ 177 mov.l @r15+,r12; \ 178 mov.l @r15+,r14; \ 179 bra .Lpseudo_end; \ 180 mov _IMM1,r0; \ 181 .align 2; \ 182 0: .long _GLOBAL_OFFSET_TABLE_; \ 183 1: .long PLTJMP(C_SYMBOL_NAME(__errno_location))-(2b-.) 184 /* A quick note: it is assumed that the call to `__errno_location' does 185 not modify the stack! */ 186 # endif 187 # else 188 189 /* Store (-r0) into errno through the GOT. */ 190 # define SYSCALL_ERROR_HANDLER \ 191 neg r0,r1; \ 192 mov r12,r2; \ 193 mov.l 0f,r12; \ 194 mova 0f,r0; \ 195 add r0,r12; \ 196 mov.l 1f,r0; \ 197 mov.l @(r0,r12),r0; \ 198 mov r2,r12; \ 199 mov.l r1,@r0; \ 200 bra .Lpseudo_end; \ 201 mov _IMM1,r0; \ 202 .align 2; \ 203 0: .long _GLOBAL_OFFSET_TABLE_; \ 204 1: .long errno@GOT 205 # endif /* _LIBC_REENTRANT */ 206 #endif /* __PIC__ */ 207 208 # ifdef __SH4__ 209 # define SYSCALL_INST_PAD \ 210 or r0,r0; or r0,r0; or r0,r0; or r0,r0; or r0,r0 211 # else 212 # define SYSCALL_INST_PAD 213 # endif 214 215 #define SYSCALL_INST0 trapa #0x10 216 #define SYSCALL_INST1 trapa #0x11 217 #define SYSCALL_INST2 trapa #0x12 218 #define SYSCALL_INST3 trapa #0x13 219 #define SYSCALL_INST4 trapa #0x14 220 #define SYSCALL_INST5 mov.l @(0,r15),r0; trapa #0x15 221 #define SYSCALL_INST6 mov.l @(0,r15),r0; mov.l @(4,r15),r1; trapa #0x16 222 223 #undef DO_CALL 224 #define DO_CALL(syscall_name, args) \ 225 mov.l 1f,r3; \ 226 SYSCALL_INST##args; \ 227 SYSCALL_INST_PAD; \ 228 bra 2f; \ 229 nop; \ 230 .align 2; \ 231 1: .long SYS_ify (syscall_name); \ 232 2: 233 #endif /* __ASSEMBLER__ */ 234