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