Home | History | Annotate | Download | only in sh64
      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
     57 ENTRY(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
     96 1:
     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
    119 2:
    120 	addi.l	r15, 8, r15
    121 3:
    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
    157 2:
    158 	addi.l	r15, 8, r15
    159 3:
    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
    174 5:
    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
    216 2:
    217 	addi.l	r15, 8, r15
    218 3:
    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
    254 1:
    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
    323 ENTRY(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