1/* ----------------------------------------------------------------------- 2 sysv.S - Copyright (c) 2003, 2004, 2006, 2008 Kaz Kojima 3 4 SuperH SHmedia Foreign Function Interface 5 6 Permission is hereby granted, free of charge, to any person obtaining 7 a copy of this software and associated documentation files (the 8 ``Software''), to deal in the Software without restriction, including 9 without limitation the rights to use, copy, modify, merge, publish, 10 distribute, sublicense, and/or sell copies of the Software, and to 11 permit persons to whom the Software is furnished to do so, subject to 12 the following conditions: 13 14 The above copyright notice and this permission notice shall be included 15 in all copies or substantial portions of the Software. 16 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#ifdef HAVE_MACHINE_ASM_H 32#include <machine/asm.h> 33#else 34/* XXX these lose for some platforms, I'm sure. */ 35#define CNAME(x) x 36#define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x): 37#endif 38 39#ifdef __LITTLE_ENDIAN__ 40#define OFS_FLT 0 41#else 42#define OFS_FLT 4 43#endif 44 45 .section .text..SHmedia32,"ax" 46 47 # r2: ffi_prep_args 48 # r3: &ecif 49 # r4: bytes 50 # r5: flags 51 # r6: flags2 52 # r7: rvalue 53 # r8: fn 54 55 # This assumes we are using gas. 56 .align 5 57ENTRY(ffi_call_SYSV) 58 # Save registers 59.LFB1: 60 addi.l r15, -48, r15 61.LCFI0: 62 st.q r15, 40, r32 63 st.q r15, 32, r31 64 st.q r15, 24, r30 65 st.q r15, 16, r29 66 st.q r15, 8, r28 67 st.l r15, 4, r18 68 st.l r15, 0, r14 69.LCFI1: 70 add.l r15, r63, r14 71.LCFI2: 72# add r4, r63, r28 73 add r5, r63, r29 74 add r6, r63, r30 75 add r7, r63, r31 76 add r8, r63, r32 77 78 addi r4, (64 + 7), r4 79 andi r4, ~7, r4 80 sub.l r15, r4, r15 81 82 ptabs/l r2, tr0 83 add r15, r63, r2 84 blink tr0, r18 85 86 addi r15, 64, r22 87 movi 0, r0 88 movi 0, r1 89 movi -1, r23 90 91 pt/l 1f, tr1 92 bnei/l r29, FFI_TYPE_STRUCT, tr1 93 ld.l r15, 0, r19 94 addi r15, 8, r15 95 addi r0, 1, r0 961: 97 98.L_pass: 99 andi r30, 3, r20 100 shlri r30, 2, r30 101 102 pt/l .L_call_it, tr0 103 pt/l .L_pass_i, tr1 104 pt/l .L_pass_f, tr2 105 106 beqi/l r20, FFI_TYPE_VOID, tr0 107 beqi/l r20, FFI_TYPE_INT, tr1 108 beqi/l r20, FFI_TYPE_FLOAT, tr2 109 110.L_pass_d: 111 addi r0, 1, r0 112 pt/l 3f, tr0 113 movi 12, r20 114 bge/l r1, r20, tr0 115 116 pt/l .L_pop_d, tr1 117 pt/l 2f, tr0 118 blink tr1, r63 1192: 120 addi.l r15, 8, r15 1213: 122 pt/l .L_pass, tr0 123 addi r1, 2, r1 124 blink tr0, r63 125 126.L_pop_d: 127 pt/l .L_pop_d_tbl, tr1 128 gettr tr1, r20 129 shlli r1, 2, r21 130 add r20, r21, r20 131 ptabs/l r20, tr1 132 blink tr1, r63 133 134.L_pop_d_tbl: 135 fld.d r15, 0, dr0 136 blink tr0, r63 137 fld.d r15, 0, dr2 138 blink tr0, r63 139 fld.d r15, 0, dr4 140 blink tr0, r63 141 fld.d r15, 0, dr6 142 blink tr0, r63 143 fld.d r15, 0, dr8 144 blink tr0, r63 145 fld.d r15, 0, dr10 146 blink tr0, r63 147 148.L_pass_f: 149 addi r0, 1, r0 150 pt/l 3f, tr0 151 movi 12, r20 152 bge/l r1, r20, tr0 153 154 pt/l .L_pop_f, tr1 155 pt/l 2f, tr0 156 blink tr1, r63 1572: 158 addi.l r15, 8, r15 1593: 160 pt/l .L_pass, tr0 161 blink tr0, r63 162 163.L_pop_f: 164 pt/l .L_pop_f_tbl, tr1 165 pt/l 5f, tr2 166 gettr tr1, r20 167 bge/l r23, r63, tr2 168 add r1, r63, r23 169 shlli r1, 3, r21 170 addi r1, 2, r1 171 add r20, r21, r20 172 ptabs/l r20, tr1 173 blink tr1, r63 1745: 175 addi r23, 1, r21 176 movi -1, r23 177 shlli r21, 3, r21 178 add r20, r21, r20 179 ptabs/l r20, tr1 180 blink tr1, r63 181 182.L_pop_f_tbl: 183 fld.s r15, OFS_FLT, fr0 184 blink tr0, r63 185 fld.s r15, OFS_FLT, fr1 186 blink tr0, r63 187 fld.s r15, OFS_FLT, fr2 188 blink tr0, r63 189 fld.s r15, OFS_FLT, fr3 190 blink tr0, r63 191 fld.s r15, OFS_FLT, fr4 192 blink tr0, r63 193 fld.s r15, OFS_FLT, fr5 194 blink tr0, r63 195 fld.s r15, OFS_FLT, fr6 196 blink tr0, r63 197 fld.s r15, OFS_FLT, fr7 198 blink tr0, r63 199 fld.s r15, OFS_FLT, fr8 200 blink tr0, r63 201 fld.s r15, OFS_FLT, fr9 202 blink tr0, r63 203 fld.s r15, OFS_FLT, fr10 204 blink tr0, r63 205 fld.s r15, OFS_FLT, fr11 206 blink tr0, r63 207 208.L_pass_i: 209 pt/l 3f, tr0 210 movi 8, r20 211 bge/l r0, r20, tr0 212 213 pt/l .L_pop_i, tr1 214 pt/l 2f, tr0 215 blink tr1, r63 2162: 217 addi.l r15, 8, r15 2183: 219 pt/l .L_pass, tr0 220 addi r0, 1, r0 221 blink tr0, r63 222 223.L_pop_i: 224 pt/l .L_pop_i_tbl, tr1 225 gettr tr1, r20 226 shlli r0, 3, r21 227 add r20, r21, r20 228 ptabs/l r20, tr1 229 blink tr1, r63 230 231.L_pop_i_tbl: 232 ld.q r15, 0, r2 233 blink tr0, r63 234 ld.q r15, 0, r3 235 blink tr0, r63 236 ld.q r15, 0, r4 237 blink tr0, r63 238 ld.q r15, 0, r5 239 blink tr0, r63 240 ld.q r15, 0, r6 241 blink tr0, r63 242 ld.q r15, 0, r7 243 blink tr0, r63 244 ld.q r15, 0, r8 245 blink tr0, r63 246 ld.q r15, 0, r9 247 blink tr0, r63 248 249.L_call_it: 250 # call function 251 pt/l 1f, tr1 252 bnei/l r29, FFI_TYPE_STRUCT, tr1 253 add r19, r63, r2 2541: 255 add r22, r63, r15 256 ptabs/l r32, tr0 257 blink tr0, r18 258 259 pt/l .L_ret_i, tr0 260 pt/l .L_ret_ll, tr1 261 pt/l .L_ret_d, tr2 262 pt/l .L_ret_f, tr3 263 pt/l .L_epilogue, tr4 264 265 beqi/l r29, FFI_TYPE_INT, tr0 266 beqi/l r29, FFI_TYPE_UINT32, tr0 267 beqi/l r29, FFI_TYPE_SINT64, tr1 268 beqi/l r29, FFI_TYPE_UINT64, tr1 269 beqi/l r29, FFI_TYPE_DOUBLE, tr2 270 beqi/l r29, FFI_TYPE_FLOAT, tr3 271 272 pt/l .L_ret_q, tr0 273 pt/l .L_ret_h, tr1 274 275 beqi/l r29, FFI_TYPE_UINT8, tr0 276 beqi/l r29, FFI_TYPE_UINT16, tr1 277 blink tr4, r63 278 279.L_ret_d: 280 fst.d r31, 0, dr0 281 blink tr4, r63 282 283.L_ret_ll: 284 st.q r31, 0, r2 285 blink tr4, r63 286 287.L_ret_f: 288 fst.s r31, OFS_FLT, fr0 289 blink tr4, r63 290 291.L_ret_q: 292 st.b r31, 0, r2 293 blink tr4, r63 294 295.L_ret_h: 296 st.w r31, 0, r2 297 blink tr4, r63 298 299.L_ret_i: 300 st.l r31, 0, r2 301 # Fall 302 303.L_epilogue: 304 # Remove the space we pushed for the args 305 add r14, r63, r15 306 307 ld.l r15, 0, r14 308 ld.l r15, 4, r18 309 ld.q r15, 8, r28 310 ld.q r15, 16, r29 311 ld.q r15, 24, r30 312 ld.q r15, 32, r31 313 ld.q r15, 40, r32 314 addi.l r15, 48, r15 315 ptabs r18, tr0 316 blink tr0, r63 317 318.LFE1: 319.ffi_call_SYSV_end: 320 .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV) 321 322 .align 5 323ENTRY(ffi_closure_SYSV) 324.LFB2: 325 addi.l r15, -136, r15 326.LCFI3: 327 st.l r15, 12, r18 328 st.l r15, 8, r14 329 st.l r15, 4, r12 330.LCFI4: 331 add r15, r63, r14 332.LCFI5: 333 /* Stack layout: 334 ... 335 64 bytes (register parameters) 336 48 bytes (floating register parameters) 337 8 bytes (result) 338 4 bytes (r18) 339 4 bytes (r14) 340 4 bytes (r12) 341 4 bytes (for align) 342 <- new stack pointer 343 */ 344 fst.d r14, 24, dr0 345 fst.d r14, 32, dr2 346 fst.d r14, 40, dr4 347 fst.d r14, 48, dr6 348 fst.d r14, 56, dr8 349 fst.d r14, 64, dr10 350 st.q r14, 72, r2 351 st.q r14, 80, r3 352 st.q r14, 88, r4 353 st.q r14, 96, r5 354 st.q r14, 104, r6 355 st.q r14, 112, r7 356 st.q r14, 120, r8 357 st.q r14, 128, r9 358 359 add r1, r63, r2 360 addi r14, 16, r3 361 addi r14, 72, r4 362 addi r14, 24, r5 363 addi r14, 136, r6 364#ifdef PIC 365 movi (((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) >> 16) & 65535), r12 366 shori ((datalabel _GLOBAL_OFFSET_TABLE_-(.LPCS0-.)) & 65535), r12 367.LPCS0: ptrel/u r12, tr0 368 movi ((ffi_closure_helper_SYSV@GOTPLT) & 65535), r1 369 gettr tr0, r12 370 ldx.l r1, r12, r1 371 ptabs r1, tr0 372#else 373 pt/l ffi_closure_helper_SYSV, tr0 374#endif 375 blink tr0, r18 376 377 shlli r2, 1, r1 378 movi (((datalabel .L_table) >> 16) & 65535), r2 379 shori ((datalabel .L_table) & 65535), r2 380 ldx.w r2, r1, r1 381 add r1, r2, r1 382 pt/l .L_case_v, tr1 383 ptabs r1, tr0 384 blink tr0, r63 385 386 .align 2 387.L_table: 388 .word .L_case_v - datalabel .L_table /* FFI_TYPE_VOID */ 389 .word .L_case_i - datalabel .L_table /* FFI_TYPE_INT */ 390 .word .L_case_f - datalabel .L_table /* FFI_TYPE_FLOAT */ 391 .word .L_case_d - datalabel .L_table /* FFI_TYPE_DOUBLE */ 392 .word .L_case_d - datalabel .L_table /* FFI_TYPE_LONGDOUBLE */ 393 .word .L_case_uq - datalabel .L_table /* FFI_TYPE_UINT8 */ 394 .word .L_case_q - datalabel .L_table /* FFI_TYPE_SINT8 */ 395 .word .L_case_uh - datalabel .L_table /* FFI_TYPE_UINT16 */ 396 .word .L_case_h - datalabel .L_table /* FFI_TYPE_SINT16 */ 397 .word .L_case_i - datalabel .L_table /* FFI_TYPE_UINT32 */ 398 .word .L_case_i - datalabel .L_table /* FFI_TYPE_SINT32 */ 399 .word .L_case_ll - datalabel .L_table /* FFI_TYPE_UINT64 */ 400 .word .L_case_ll - datalabel .L_table /* FFI_TYPE_SINT64 */ 401 .word .L_case_v - datalabel .L_table /* FFI_TYPE_STRUCT */ 402 .word .L_case_i - datalabel .L_table /* FFI_TYPE_POINTER */ 403 404 .align 2 405.L_case_d: 406 fld.d r14, 16, dr0 407 blink tr1, r63 408.L_case_f: 409 fld.s r14, 16, fr0 410 blink tr1, r63 411.L_case_ll: 412 ld.q r14, 16, r2 413 blink tr1, r63 414.L_case_i: 415 ld.l r14, 16, r2 416 blink tr1, r63 417.L_case_q: 418 ld.b r14, 16, r2 419 blink tr1, r63 420.L_case_uq: 421 ld.ub r14, 16, r2 422 blink tr1, r63 423.L_case_h: 424 ld.w r14, 16, r2 425 blink tr1, r63 426.L_case_uh: 427 ld.uw r14, 16, r2 428 blink tr1, r63 429.L_case_v: 430 add.l r14, r63, r15 431 ld.l r15, 4, r12 432 ld.l r15, 8, r14 433 ld.l r15, 12, r18 434 addi.l r15, 136, r15 435 ptabs r18, tr0 436 blink tr0, r63 437 438.LFE2: 439.ffi_closure_SYSV_end: 440 .size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV) 441 442#if defined __ELF__ && defined __linux__ 443 .section .note.GNU-stack,"",@progbits 444#endif 445 446 .section ".eh_frame","aw",@progbits 447__FRAME_BEGIN__: 448 .4byte .LECIE1-.LSCIE1 /* Length of Common Information Entry */ 449.LSCIE1: 450 .4byte 0x0 /* CIE Identifier Tag */ 451 .byte 0x1 /* CIE Version */ 452#ifdef PIC 453 .ascii "zR\0" /* CIE Augmentation */ 454#else 455 .byte 0x0 /* CIE Augmentation */ 456#endif 457 .uleb128 0x1 /* CIE Code Alignment Factor */ 458 .sleb128 -4 /* CIE Data Alignment Factor */ 459 .byte 0x12 /* CIE RA Column */ 460#ifdef PIC 461 .uleb128 0x1 /* Augmentation size */ 462 .byte 0x10 /* FDE Encoding (pcrel) */ 463#endif 464 .byte 0xc /* DW_CFA_def_cfa */ 465 .uleb128 0xf 466 .uleb128 0x0 467 .align 2 468.LECIE1: 469.LSFDE1: 470 .4byte datalabel .LEFDE1-datalabel .LASFDE1 /* FDE Length */ 471.LASFDE1: 472 .4byte datalabel .LASFDE1-datalabel __FRAME_BEGIN__ 473#ifdef PIC 474 .4byte .LFB1-. /* FDE initial location */ 475#else 476 .4byte .LFB1 /* FDE initial location */ 477#endif 478 .4byte datalabel .LFE1-datalabel .LFB1 /* FDE address range */ 479#ifdef PIC 480 .uleb128 0x0 /* Augmentation size */ 481#endif 482 .byte 0x4 /* DW_CFA_advance_loc4 */ 483 .4byte datalabel .LCFI0-datalabel .LFB1 484 .byte 0xe /* DW_CFA_def_cfa_offset */ 485 .uleb128 0x30 486 .byte 0x4 /* DW_CFA_advance_loc4 */ 487 .4byte datalabel .LCFI1-datalabel .LCFI0 488 .byte 0x8e /* DW_CFA_offset, column 0xe */ 489 .uleb128 0xc 490 .byte 0x92 /* DW_CFA_offset, column 0x12 */ 491 .uleb128 0xb 492 .byte 0x9c /* DW_CFA_offset, column 0x1c */ 493 .uleb128 0xa 494 .byte 0x9d /* DW_CFA_offset, column 0x1d */ 495 .uleb128 0x8 496 .byte 0x9e /* DW_CFA_offset, column 0x1e */ 497 .uleb128 0x6 498 .byte 0x9f /* DW_CFA_offset, column 0x1f */ 499 .uleb128 0x4 500 .byte 0xa0 /* DW_CFA_offset, column 0x20 */ 501 .uleb128 0x2 502 .byte 0x4 /* DW_CFA_advance_loc4 */ 503 .4byte datalabel .LCFI2-datalabel .LCFI1 504 .byte 0xd /* DW_CFA_def_cfa_register */ 505 .uleb128 0xe 506 .align 2 507.LEFDE1: 508 509.LSFDE3: 510 .4byte datalabel .LEFDE3-datalabel .LASFDE3 /* FDE Length */ 511.LASFDE3: 512 .4byte datalabel .LASFDE3-datalabel __FRAME_BEGIN__ 513#ifdef PIC 514 .4byte .LFB2-. /* FDE initial location */ 515#else 516 .4byte .LFB2 /* FDE initial location */ 517#endif 518 .4byte datalabel .LFE2-datalabel .LFB2 /* FDE address range */ 519#ifdef PIC 520 .uleb128 0x0 /* Augmentation size */ 521#endif 522 .byte 0x4 /* DW_CFA_advance_loc4 */ 523 .4byte datalabel .LCFI3-datalabel .LFB2 524 .byte 0xe /* DW_CFA_def_cfa_offset */ 525 .uleb128 0x88 526 .byte 0x4 /* DW_CFA_advance_loc4 */ 527 .4byte datalabel .LCFI4-datalabel .LCFI3 528 .byte 0x8c /* DW_CFA_offset, column 0xc */ 529 .uleb128 0x21 530 .byte 0x8e /* DW_CFA_offset, column 0xe */ 531 .uleb128 0x20 532 .byte 0x92 /* DW_CFA_offset, column 0x12 */ 533 .uleb128 0x1f 534 .byte 0x4 /* DW_CFA_advance_loc4 */ 535 .4byte datalabel .LCFI5-datalabel .LCFI4 536 .byte 0xd /* DW_CFA_def_cfa_register */ 537 .uleb128 0xe 538 .align 2 539.LEFDE3: 540