github.com/prattmic/llgo-embedded@v0.0.0-20150820070356-41cfecea0e1e/third_party/gofrontend/libffi/src/sparc/v8.S (about) 1 /* ----------------------------------------------------------------------- 2 v8.S - Copyright (c) 2013 The Written Word, Inc. 3 Copyright (c) 1996, 1997, 2003, 2004, 2008 Red Hat, Inc. 4 5 SPARC Foreign Function Interface 6 7 Permission is hereby granted, free of charge, to any person obtaining 8 a copy of this software and associated documentation files (the 9 ``Software''), to deal in the Software without restriction, including 10 without limitation the rights to use, copy, modify, merge, publish, 11 distribute, sublicense, and/or sell copies of the Software, and to 12 permit persons to whom the Software is furnished to do so, subject to 13 the following conditions: 14 15 The above copyright notice and this permission notice shall be included 16 in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 DEALINGS IN THE SOFTWARE. 26 ----------------------------------------------------------------------- */ 27 28 #define LIBFFI_ASM 29 #include <fficonfig.h> 30 #include <ffi.h> 31 #include <ffi_cfi.h> 32 #include "internal.h" 33 34 #ifndef SPARC64 35 36 #define C2(X, Y) X ## Y 37 #define C1(X, Y) C2(X, Y) 38 39 #ifdef __USER_LABEL_PREFIX__ 40 # define C(Y) C1(__USER_LABEL_PREFIX__, Y) 41 #else 42 # define C(Y) Y 43 #endif 44 #define L(Y) C1(.L, Y) 45 46 .text 47 48 #ifndef __GNUC__ 49 .align 8 50 .globl C(ffi_flush_icache) 51 .type C(ffi_flush_icache),@function 52 FFI_HIDDEN(C(ffi_flush_icache)) 53 54 C(ffi_flush_icache): 55 cfi_startproc 56 1: iflush %o0 57 iflush %o+8 58 nop 59 nop 60 nop 61 nop 62 nop 63 retl 64 nop 65 cfi_endproc 66 .size C(ffi_flush_icache), . - C(ffi_flush_icache) 67 #endif 68 69 .macro E index 70 .align 16 71 .org 2b + \index * 16 72 .endm 73 74 .align 8 75 .globl C(ffi_call_v8) 76 .type C(ffi_call_v8),@function 77 FFI_HIDDEN(C(ffi_call_v8)) 78 79 C(ffi_call_v8): 80 cfi_startproc 81 ! Allocate a stack frame sized by ffi_call. 82 save %sp, %o4, %sp 83 cfi_def_cfa_register(%fp) 84 cfi_window_save 85 86 mov %i0, %o0 ! copy cif 87 add %sp, 64+32, %o1 ! load args area 88 mov %i2, %o2 ! copy rvalue 89 call C(ffi_prep_args_v8) 90 mov %i3, %o3 ! copy avalue 91 92 add %sp, 32, %sp ! deallocate prep frame 93 and %o0, SPARC_FLAG_RET_MASK, %l0 ! save return type 94 srl %o0, SPARC_SIZEMASK_SHIFT, %l1 ! save return size 95 ld [%sp+64+4], %o0 ! load all argument registers 96 ld [%sp+64+8], %o1 97 ld [%sp+64+12], %o2 98 ld [%sp+64+16], %o3 99 cmp %l0, SPARC_RET_STRUCT ! struct return needs an unimp 4 100 ld [%sp+64+20], %o4 101 be 8f 102 ld [%sp+64+24], %o5 103 104 ! Call foreign function 105 call %i1 106 mov %i5, %g2 ! load static chain 107 108 0: call 1f ! load pc in %o7 109 sll %l0, 4, %l0 110 1: add %o7, %l0, %o7 ! o7 = 0b + ret_type*16 111 jmp %o7+(2f-0b) 112 nop 113 114 ! Note that each entry is 4 insns, enforced by the E macro. 115 .align 16 116 2: 117 E SPARC_RET_VOID 118 ret 119 restore 120 E SPARC_RET_STRUCT 121 unimp 122 E SPARC_RET_UINT8 123 and %o0, 0xff, %o0 124 st %o0, [%i2] 125 ret 126 restore 127 E SPARC_RET_SINT8 128 sll %o0, 24, %o0 129 b 7f 130 sra %o0, 24, %o0 131 E SPARC_RET_UINT16 132 sll %o0, 16, %o0 133 b 7f 134 srl %o0, 16, %o0 135 E SPARC_RET_SINT16 136 sll %o0, 16, %o0 137 b 7f 138 sra %o0, 16, %o0 139 E SPARC_RET_UINT32 140 7: st %o0, [%i2] 141 ret 142 restore 143 E SP_V8_RET_CPLX16 144 sth %o0, [%i2+2] 145 b 9f 146 srl %o0, 16, %o0 147 E SPARC_RET_INT64 148 st %o0, [%i2] 149 st %o1, [%i2+4] 150 ret 151 restore 152 E SPARC_RET_INT128 153 std %o0, [%i2] 154 std %o2, [%i2+8] 155 ret 156 restore 157 E SPARC_RET_F_8 158 st %f7, [%i2+7*4] 159 nop 160 st %f6, [%i2+6*4] 161 nop 162 E SPARC_RET_F_6 163 st %f5, [%i2+5*4] 164 nop 165 st %f4, [%i2+4*4] 166 nop 167 E SPARC_RET_F_4 168 st %f3, [%i2+3*4] 169 nop 170 st %f2, [%i2+2*4] 171 nop 172 E SPARC_RET_F_2 173 st %f1, [%i2+4] 174 st %f0, [%i2] 175 ret 176 restore 177 E SP_V8_RET_CPLX8 178 stb %o0, [%i2+1] 179 b 10f 180 srl %o0, 8, %o0 181 E SPARC_RET_F_1 182 st %f0, [%i2] 183 ret 184 restore 185 186 .align 8 187 9: sth %o0, [%i2] 188 ret 189 restore 190 .align 8 191 10: stb %o0, [%i2] 192 ret 193 restore 194 195 ! Struct returning functions expect and skip the unimp here. 196 ! To make it worse, conforming callees examine the unimp and 197 ! make sure the low 12 bits of the unimp match the size of 198 ! the struct being returned. 199 .align 8 200 8: call 1f ! load pc in %o7 201 sll %l1, 2, %l0 ! size * 4 202 1: sll %l1, 4, %l1 ! size * 16 203 add %l0, %l1, %l0 ! size * 20 204 add %o7, %l0, %o7 ! o7 = 0b + size*20 205 jmp %o7+(2f-8b) 206 mov %i5, %g2 ! load static chain 207 2: 208 .rept 0x1000 209 call %i1 210 nop 211 unimp (. - 2b) / 20 212 ret 213 restore 214 .endr 215 216 cfi_endproc 217 .size C(ffi_call_v8),. - C(ffi_call_v8) 218 219 220 /* 16*4 register window + 1*4 struct return + 6*4 args backing store 221 + 8*4 return storage + 1*4 alignment. */ 222 #define STACKFRAME (16*4 + 4 + 6*4 + 8*4 + 4) 223 224 /* ffi_closure_v8(...) 225 226 Receives the closure argument in %g2. */ 227 228 #ifdef HAVE_AS_REGISTER_PSEUDO_OP 229 .register %g2, #scratch 230 #endif 231 232 .align 8 233 .globl C(ffi_go_closure_v8) 234 .type C(ffi_go_closure_v8),@function 235 FFI_HIDDEN(C(ffi_go_closure_v8)) 236 237 C(ffi_go_closure_v8): 238 cfi_startproc 239 save %sp, -STACKFRAME, %sp 240 cfi_def_cfa_register(%fp) 241 cfi_window_save 242 243 ld [%g2+4], %o0 ! load cif 244 ld [%g2+8], %o1 ! load fun 245 b 0f 246 mov %g2, %o2 ! load user_data 247 cfi_endproc 248 .size C(ffi_go_closure_v8), . - C(ffi_go_closure_v8) 249 250 .align 8 251 .globl C(ffi_closure_v8) 252 .type C(ffi_closure_v8),@function 253 FFI_HIDDEN(C(ffi_closure_v8)) 254 255 C(ffi_closure_v8): 256 cfi_startproc 257 save %sp, -STACKFRAME, %sp 258 cfi_def_cfa_register(%fp) 259 cfi_window_save 260 261 ld [%g2+FFI_TRAMPOLINE_SIZE], %o0 ! load cif 262 ld [%g2+FFI_TRAMPOLINE_SIZE+4], %o1 ! load fun 263 ld [%g2+FFI_TRAMPOLINE_SIZE+8], %o2 ! load user_data 264 0: 265 ! Store all of the potential argument registers in va_list format. 266 st %i0, [%fp+68+0] 267 st %i1, [%fp+68+4] 268 st %i2, [%fp+68+8] 269 st %i3, [%fp+68+12] 270 st %i4, [%fp+68+16] 271 st %i5, [%fp+68+20] 272 273 ! Call ffi_closure_sparc_inner to do the bulk of the work. 274 add %fp, -8*4, %o3 275 call ffi_closure_sparc_inner_v8 276 add %fp, 64, %o4 277 278 0: call 1f 279 and %o0, SPARC_FLAG_RET_MASK, %o0 280 1: sll %o0, 4, %o0 ! o0 = o0 * 16 281 add %o7, %o0, %o7 ! o7 = 0b + o0*16 282 jmp %o7+(2f-0b) 283 add %fp, -8*4, %i2 284 285 ! Note that each entry is 4 insns, enforced by the E macro. 286 .align 16 287 2: 288 E SPARC_RET_VOID 289 ret 290 restore 291 E SPARC_RET_STRUCT 292 ld [%i2], %i0 293 jmp %i7+12 294 restore 295 E SPARC_RET_UINT8 296 ldub [%i2+3], %i0 297 ret 298 restore 299 E SPARC_RET_SINT8 300 ldsb [%i2+3], %i0 301 ret 302 restore 303 E SPARC_RET_UINT16 304 lduh [%i2+2], %i0 305 ret 306 restore 307 E SPARC_RET_SINT16 308 ldsh [%i2+2], %i0 309 ret 310 restore 311 E SPARC_RET_UINT32 312 ld [%i2], %i0 313 ret 314 restore 315 E SP_V8_RET_CPLX16 316 ld [%i2], %i0 317 ret 318 restore 319 E SPARC_RET_INT64 320 ldd [%i2], %i0 321 ret 322 restore 323 E SPARC_RET_INT128 324 ldd [%i2], %i0 325 ldd [%i2+8], %i2 326 ret 327 restore 328 E SPARC_RET_F_8 329 ld [%i2+7*4], %f7 330 nop 331 ld [%i2+6*4], %f6 332 nop 333 E SPARC_RET_F_6 334 ld [%i2+5*4], %f5 335 nop 336 ld [%i2+4*4], %f4 337 nop 338 E SPARC_RET_F_4 339 ld [%i2+3*4], %f3 340 nop 341 ld [%i2+2*4], %f2 342 nop 343 E SPARC_RET_F_2 344 ldd [%i2], %f0 345 ret 346 restore 347 E SP_V8_RET_CPLX8 348 lduh [%i2], %i0 349 ret 350 restore 351 E SPARC_RET_F_1 352 ld [%i2], %f0 353 ret 354 restore 355 356 cfi_endproc 357 .size C(ffi_closure_v8), . - C(ffi_closure_v8) 358 #endif /* !SPARC64 */ 359 #if defined __ELF__ && defined __linux__ 360 .section .note.GNU-stack,"",@progbits 361 #endif