Home | History | Annotate | Download | only in ia64
      1 /* -----------------------------------------------------------------------
      2    unix.S - Copyright (c) 1998, 2008 Red Hat, Inc.
      3             Copyright (c) 2000 Hewlett Packard Company
      4 
      5    IA64/unix Foreign Function Interface
      6 
      7    Primary author: Hans Boehm, HP Labs
      8 
      9    Loosely modeled on Cygnus code for other platforms.
     10 
     11    Permission is hereby granted, free of charge, to any person obtaining
     12    a copy of this software and associated documentation files (the
     13    ``Software''), to deal in the Software without restriction, including
     14    without limitation the rights to use, copy, modify, merge, publish,
     15    distribute, sublicense, and/or sell copies of the Software, and to
     16    permit persons to whom the Software is furnished to do so, subject to
     17    the following conditions:
     18 
     19    The above copyright notice and this permission notice shall be included
     20    in all copies or substantial portions of the Software.
     21 
     22    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
     23    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     24    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     25    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
     26    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
     27    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     28    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     29    DEALINGS IN THE SOFTWARE.
     30    ----------------------------------------------------------------------- */
     31 
     32 #define LIBFFI_ASM
     33 #include <fficonfig.h>
     34 #include <ffi.h>
     35 #include "ia64_flags.h"
     36 
     37 	.pred.safe_across_calls p1-p5,p16-p63
     38 .text
     39 
     40 /* int ffi_call_unix (struct ia64_args *stack, PTR64 rvalue,
     41 		      void (*fn)(void), int flags);
     42  */
     43 
     44         .align 16
     45         .global	ffi_call_unix
     46         .proc	ffi_call_unix
     47 ffi_call_unix:
     48 	.prologue
     49 	/* Bit o trickiness.  We actually share a stack frame with ffi_call.
     50 	   Rely on the fact that ffi_call uses a vframe and don't bother
     51 	   tracking one here at all.  */
     52 	.fframe	0
     53 	.save	ar.pfs, r36 // loc0
     54 	alloc   loc0 = ar.pfs, 4, 3, 8, 0
     55 	.save	rp, loc1
     56 	mov 	loc1 = b0
     57 	.body
     58 	add	r16 = 16, in0
     59 	mov	loc2 = gp
     60 	mov	r8 = in1
     61 	;;
     62 
     63 	/* Load up all of the argument registers.  */
     64 	ldf.fill f8 = [in0], 32
     65 	ldf.fill f9 = [r16], 32
     66 	;;
     67 	ldf.fill f10 = [in0], 32
     68 	ldf.fill f11 = [r16], 32
     69 	;;
     70 	ldf.fill f12 = [in0], 32
     71 	ldf.fill f13 = [r16], 32
     72 	;;
     73 	ldf.fill f14 = [in0], 32
     74 	ldf.fill f15 = [r16], 24
     75 	;;
     76 	ld8	out0 = [in0], 16
     77 	ld8	out1 = [r16], 16
     78 	;;
     79 	ld8	out2 = [in0], 16
     80 	ld8	out3 = [r16], 16
     81 	;;
     82 	ld8	out4 = [in0], 16
     83 	ld8	out5 = [r16], 16
     84 	;;
     85 	ld8	out6 = [in0]
     86 	ld8	out7 = [r16]
     87 	;;
     88 
     89 	/* Deallocate the register save area from the stack frame.  */
     90 	mov	sp = in0
     91 
     92 	/* Call the target function.  */
     93 	ld8	r16 = [in2], 8
     94 	;;
     95 	ld8	gp = [in2]
     96 	mov	b6 = r16
     97 	br.call.sptk.many b0 = b6
     98 	;;
     99 
    100 	/* Dispatch to handle return value.  */
    101 	mov	gp = loc2
    102 	zxt1	r16 = in3
    103 	;;
    104 	mov	ar.pfs = loc0
    105 	addl	r18 = @ltoffx(.Lst_table), gp
    106 	;;
    107 	ld8.mov	r18 = [r18], .Lst_table
    108 	mov	b0 = loc1
    109 	;;
    110 	shladd	r18 = r16, 3, r18
    111 	;;
    112 	ld8	r17 = [r18]
    113 	shr	in3 = in3, 8
    114 	;;
    115 	add	r17 = r17, r18
    116 	;;
    117 	mov	b6 = r17
    118 	br	b6
    119 	;;
    120 
    121 .Lst_void:
    122 	br.ret.sptk.many b0
    123 	;;
    124 .Lst_uint8:
    125 	zxt1	r8 = r8
    126 	;;
    127 	st8	[in1] = r8
    128 	br.ret.sptk.many b0
    129 	;;
    130 .Lst_sint8:
    131 	sxt1	r8 = r8
    132 	;;
    133 	st8	[in1] = r8
    134 	br.ret.sptk.many b0
    135 	;;
    136 .Lst_uint16:
    137 	zxt2	r8 = r8
    138 	;;
    139 	st8	[in1] = r8
    140 	br.ret.sptk.many b0
    141 	;;
    142 .Lst_sint16:
    143 	sxt2	r8 = r8
    144 	;;
    145 	st8	[in1] = r8
    146 	br.ret.sptk.many b0
    147 	;;
    148 .Lst_uint32:
    149 	zxt4	r8 = r8
    150 	;;
    151 	st8	[in1] = r8
    152 	br.ret.sptk.many b0
    153 	;;
    154 .Lst_sint32:
    155 	sxt4	r8 = r8
    156 	;;
    157 	st8	[in1] = r8
    158 	br.ret.sptk.many b0
    159 	;;
    160 .Lst_int64:
    161 	st8	[in1] = r8
    162 	br.ret.sptk.many b0
    163 	;;
    164 .Lst_float:
    165 	stfs	[in1] = f8
    166 	br.ret.sptk.many b0
    167 	;;
    168 .Lst_double:
    169 	stfd	[in1] = f8
    170 	br.ret.sptk.many b0
    171 	;;
    172 .Lst_ldouble:
    173 	stfe	[in1] = f8
    174 	br.ret.sptk.many b0
    175 	;;
    176 
    177 .Lst_small_struct:
    178 	add	sp = -16, sp
    179 	cmp.lt	p6, p0 = 8, in3
    180 	cmp.lt	p7, p0 = 16, in3
    181 	cmp.lt	p8, p0 = 24, in3
    182 	;;
    183 	add	r16 = 8, sp
    184 	add	r17 = 16, sp
    185 	add	r18 = 24, sp
    186 	;;
    187 	st8	[sp] = r8
    188 (p6)	st8	[r16] = r9
    189 	mov	out0 = in1
    190 (p7)	st8	[r17] = r10
    191 (p8)	st8	[r18] = r11
    192 	mov	out1 = sp
    193 	mov	out2 = in3
    194 	br.call.sptk.many b0 = memcpy#
    195 	;;
    196 	mov	ar.pfs = loc0
    197 	mov	b0 = loc1
    198 	mov	gp = loc2
    199 	br.ret.sptk.many b0
    200 
    201 .Lst_hfa_float:
    202 	add	r16 = 4, in1
    203 	cmp.lt	p6, p0 = 4, in3
    204 	;;
    205 	stfs	[in1] = f8, 8
    206 (p6)	stfs	[r16] = f9, 8
    207 	cmp.lt	p7, p0 = 8, in3
    208 	cmp.lt	p8, p0 = 12, in3
    209 	;;
    210 (p7)	stfs	[in1] = f10, 8
    211 (p8)	stfs	[r16] = f11, 8
    212 	cmp.lt	p9, p0 = 16, in3
    213 	cmp.lt	p10, p0 = 20, in3
    214 	;;
    215 (p9)	stfs	[in1] = f12, 8
    216 (p10)	stfs	[r16] = f13, 8
    217 	cmp.lt	p6, p0 = 24, in3
    218 	cmp.lt	p7, p0 = 28, in3
    219 	;;
    220 (p6)	stfs	[in1] = f14
    221 (p7)	stfs	[r16] = f15
    222 	br.ret.sptk.many b0
    223 	;;
    224 
    225 .Lst_hfa_double:
    226 	add	r16 = 8, in1
    227 	cmp.lt	p6, p0 = 8, in3
    228 	;;
    229 	stfd	[in1] = f8, 16
    230 (p6)	stfd	[r16] = f9, 16
    231 	cmp.lt	p7, p0 = 16, in3
    232 	cmp.lt	p8, p0 = 24, in3
    233 	;;
    234 (p7)	stfd	[in1] = f10, 16
    235 (p8)	stfd	[r16] = f11, 16
    236 	cmp.lt	p9, p0 = 32, in3
    237 	cmp.lt	p10, p0 = 40, in3
    238 	;;
    239 (p9)	stfd	[in1] = f12, 16
    240 (p10)	stfd	[r16] = f13, 16
    241 	cmp.lt	p6, p0 = 48, in3
    242 	cmp.lt	p7, p0 = 56, in3
    243 	;;
    244 (p6)	stfd	[in1] = f14
    245 (p7)	stfd	[r16] = f15
    246 	br.ret.sptk.many b0
    247 	;;
    248 
    249 .Lst_hfa_ldouble:
    250 	add	r16 = 16, in1
    251 	cmp.lt	p6, p0 = 16, in3
    252 	;;
    253 	stfe	[in1] = f8, 32
    254 (p6)	stfe	[r16] = f9, 32
    255 	cmp.lt	p7, p0 = 32, in3
    256 	cmp.lt	p8, p0 = 48, in3
    257 	;;
    258 (p7)	stfe	[in1] = f10, 32
    259 (p8)	stfe	[r16] = f11, 32
    260 	cmp.lt	p9, p0 = 64, in3
    261 	cmp.lt	p10, p0 = 80, in3
    262 	;;
    263 (p9)	stfe	[in1] = f12, 32
    264 (p10)	stfe	[r16] = f13, 32
    265 	cmp.lt	p6, p0 = 96, in3
    266 	cmp.lt	p7, p0 = 112, in3
    267 	;;
    268 (p6)	stfe	[in1] = f14
    269 (p7)	stfe	[r16] = f15
    270 	br.ret.sptk.many b0
    271 	;;
    272 
    273         .endp ffi_call_unix
    274 
    275         .align 16
    276         .global ffi_closure_unix
    277         .proc ffi_closure_unix
    278 
    279 #define FRAME_SIZE	(8*16 + 8*8 + 8*16)
    280 
    281 ffi_closure_unix:
    282 	.prologue
    283 	.save	ar.pfs, r40 // loc0
    284 	alloc   loc0 = ar.pfs, 8, 4, 4, 0
    285 	.fframe	FRAME_SIZE
    286 	add	r12 = -FRAME_SIZE, r12
    287 	.save	rp, loc1
    288 	mov	loc1 = b0
    289 	.save	ar.unat, loc2
    290 	mov	loc2 = ar.unat
    291 	.body
    292 
    293 	/* Retrieve closure pointer and real gp.  */
    294 #ifdef _ILP32
    295 	addp4	out0 = 0, gp
    296 	addp4	gp = 16, gp
    297 #else
    298 	mov	out0 = gp
    299 	add	gp = 16, gp
    300 #endif
    301 	;;
    302 	ld8	gp = [gp]
    303 
    304 	/* Spill all of the possible argument registers.  */
    305 	add	r16 = 16 + 8*16, sp
    306 	add	r17 = 16 + 8*16 + 16, sp
    307 	;;
    308 	stf.spill [r16] = f8, 32
    309 	stf.spill [r17] = f9, 32
    310 	mov	loc3 = gp
    311 	;;
    312 	stf.spill [r16] = f10, 32
    313 	stf.spill [r17] = f11, 32
    314 	;;
    315 	stf.spill [r16] = f12, 32
    316 	stf.spill [r17] = f13, 32
    317 	;;
    318 	stf.spill [r16] = f14, 32
    319 	stf.spill [r17] = f15, 24
    320 	;;
    321 	.mem.offset 0, 0
    322 	st8.spill [r16] = in0, 16
    323 	.mem.offset 8, 0
    324 	st8.spill [r17] = in1, 16
    325 	add	out1 = 16 + 8*16, sp
    326 	;;
    327 	.mem.offset 0, 0
    328 	st8.spill [r16] = in2, 16
    329 	.mem.offset 8, 0
    330 	st8.spill [r17] = in3, 16
    331 	add	out2 = 16, sp
    332 	;;
    333 	.mem.offset 0, 0
    334 	st8.spill [r16] = in4, 16
    335 	.mem.offset 8, 0
    336 	st8.spill [r17] = in5, 16
    337 	mov	out3 = r8
    338 	;;
    339 	.mem.offset 0, 0
    340 	st8.spill [r16] = in6
    341 	.mem.offset 8, 0
    342 	st8.spill [r17] = in7
    343 
    344 	/* Invoke ffi_closure_unix_inner for the hard work.  */
    345 	br.call.sptk.many b0 = ffi_closure_unix_inner
    346 	;;
    347 
    348 	/* Dispatch to handle return value.  */
    349 	mov	gp = loc3
    350 	zxt1	r16 = r8
    351 	;;
    352 	addl	r18 = @ltoffx(.Lld_table), gp
    353 	mov	ar.pfs = loc0
    354 	;;
    355 	ld8.mov	r18 = [r18], .Lld_table
    356 	mov	b0 = loc1
    357 	;;
    358 	shladd	r18 = r16, 3, r18
    359 	mov	ar.unat = loc2
    360 	;;
    361 	ld8	r17 = [r18]
    362 	shr	r8 = r8, 8
    363 	;;
    364 	add	r17 = r17, r18
    365 	add	r16 = 16, sp
    366 	;;
    367 	mov	b6 = r17
    368 	br	b6
    369 	;;
    370 	.label_state 1
    371 
    372 .Lld_void:
    373 	.restore sp
    374 	add	sp = FRAME_SIZE, sp
    375 	br.ret.sptk.many b0
    376 	;;
    377 .Lld_int:
    378 	.body
    379 	.copy_state 1
    380 	ld8	r8 = [r16]
    381 	.restore sp
    382 	add	sp = FRAME_SIZE, sp
    383 	br.ret.sptk.many b0
    384 	;;
    385 .Lld_float:
    386 	.body
    387 	.copy_state 1
    388 	ldfs	f8 = [r16]
    389 	.restore sp
    390 	add	sp = FRAME_SIZE, sp
    391 	br.ret.sptk.many b0
    392 	;;
    393 .Lld_double:
    394 	.body
    395 	.copy_state 1
    396 	ldfd	f8 = [r16]
    397 	.restore sp
    398 	add	sp = FRAME_SIZE, sp
    399 	br.ret.sptk.many b0
    400 	;;
    401 .Lld_ldouble:
    402 	.body
    403 	.copy_state 1
    404 	ldfe	f8 = [r16]
    405 	.restore sp
    406 	add	sp = FRAME_SIZE, sp
    407 	br.ret.sptk.many b0
    408 	;;
    409 
    410 .Lld_small_struct:
    411 	.body
    412 	.copy_state 1
    413 	add	r17 = 8, r16
    414 	cmp.lt	p6, p0 = 8, r8
    415 	cmp.lt	p7, p0 = 16, r8
    416 	cmp.lt	p8, p0 = 24, r8
    417 	;;
    418 	ld8	r8 = [r16], 16
    419 (p6)	ld8	r9 = [r17], 16
    420 	;;
    421 (p7)	ld8	r10 = [r16]
    422 (p8)	ld8	r11 = [r17]
    423 	.restore sp
    424 	add	sp = FRAME_SIZE, sp
    425 	br.ret.sptk.many b0
    426 	;;
    427 
    428 .Lld_hfa_float:
    429 	.body
    430 	.copy_state 1
    431 	add	r17 = 4, r16
    432 	cmp.lt	p6, p0 = 4, r8
    433 	;;
    434 	ldfs	f8 = [r16], 8
    435 (p6)	ldfs	f9 = [r17], 8
    436 	cmp.lt	p7, p0 = 8, r8
    437 	cmp.lt	p8, p0 = 12, r8
    438 	;;
    439 (p7)	ldfs	f10 = [r16], 8
    440 (p8)	ldfs	f11 = [r17], 8
    441 	cmp.lt	p9, p0 = 16, r8
    442 	cmp.lt	p10, p0 = 20, r8
    443 	;;
    444 (p9)	ldfs	f12 = [r16], 8
    445 (p10)	ldfs	f13 = [r17], 8
    446 	cmp.lt	p6, p0 = 24, r8
    447 	cmp.lt	p7, p0 = 28, r8
    448 	;;
    449 (p6)	ldfs	f14 = [r16]
    450 (p7)	ldfs	f15 = [r17]
    451 	.restore sp
    452 	add	sp = FRAME_SIZE, sp
    453 	br.ret.sptk.many b0
    454 	;;
    455 
    456 .Lld_hfa_double:
    457 	.body
    458 	.copy_state 1
    459 	add	r17 = 8, r16
    460 	cmp.lt	p6, p0 = 8, r8
    461 	;;
    462 	ldfd	f8 = [r16], 16
    463 (p6)	ldfd	f9 = [r17], 16
    464 	cmp.lt	p7, p0 = 16, r8
    465 	cmp.lt	p8, p0 = 24, r8
    466 	;;
    467 (p7)	ldfd	f10 = [r16], 16
    468 (p8)	ldfd	f11 = [r17], 16
    469 	cmp.lt	p9, p0 = 32, r8
    470 	cmp.lt	p10, p0 = 40, r8
    471 	;;
    472 (p9)	ldfd	f12 = [r16], 16
    473 (p10)	ldfd	f13 = [r17], 16
    474 	cmp.lt	p6, p0 = 48, r8
    475 	cmp.lt	p7, p0 = 56, r8
    476 	;;
    477 (p6)	ldfd	f14 = [r16]
    478 (p7)	ldfd	f15 = [r17]
    479 	.restore sp
    480 	add	sp = FRAME_SIZE, sp
    481 	br.ret.sptk.many b0
    482 	;;
    483 
    484 .Lld_hfa_ldouble:
    485 	.body
    486 	.copy_state 1
    487 	add	r17 = 16, r16
    488 	cmp.lt	p6, p0 = 16, r8
    489 	;;
    490 	ldfe	f8 = [r16], 32
    491 (p6)	ldfe	f9 = [r17], 32
    492 	cmp.lt	p7, p0 = 32, r8
    493 	cmp.lt	p8, p0 = 48, r8
    494 	;;
    495 (p7)	ldfe	f10 = [r16], 32
    496 (p8)	ldfe	f11 = [r17], 32
    497 	cmp.lt	p9, p0 = 64, r8
    498 	cmp.lt	p10, p0 = 80, r8
    499 	;;
    500 (p9)	ldfe	f12 = [r16], 32
    501 (p10)	ldfe	f13 = [r17], 32
    502 	cmp.lt	p6, p0 = 96, r8
    503 	cmp.lt	p7, p0 = 112, r8
    504 	;;
    505 (p6)	ldfe	f14 = [r16]
    506 (p7)	ldfe	f15 = [r17]
    507 	.restore sp
    508 	add	sp = FRAME_SIZE, sp
    509 	br.ret.sptk.many b0
    510 	;;
    511 
    512 	.endp	ffi_closure_unix
    513 
    514 	.section .rodata
    515 	.align	8
    516 .Lst_table:
    517 	data8	@pcrel(.Lst_void)		// FFI_TYPE_VOID
    518 	data8	@pcrel(.Lst_sint32)		// FFI_TYPE_INT
    519 	data8	@pcrel(.Lst_float)		// FFI_TYPE_FLOAT
    520 	data8	@pcrel(.Lst_double)		// FFI_TYPE_DOUBLE
    521 	data8	@pcrel(.Lst_ldouble)		// FFI_TYPE_LONGDOUBLE
    522 	data8	@pcrel(.Lst_uint8)		// FFI_TYPE_UINT8
    523 	data8	@pcrel(.Lst_sint8)		// FFI_TYPE_SINT8
    524 	data8	@pcrel(.Lst_uint16)		// FFI_TYPE_UINT16
    525 	data8	@pcrel(.Lst_sint16)		// FFI_TYPE_SINT16
    526 	data8	@pcrel(.Lst_uint32)		// FFI_TYPE_UINT32
    527 	data8	@pcrel(.Lst_sint32)		// FFI_TYPE_SINT32
    528 	data8	@pcrel(.Lst_int64)		// FFI_TYPE_UINT64
    529 	data8	@pcrel(.Lst_int64)		// FFI_TYPE_SINT64
    530 	data8	@pcrel(.Lst_void)		// FFI_TYPE_STRUCT
    531 	data8	@pcrel(.Lst_int64)		// FFI_TYPE_POINTER
    532 	data8 	@pcrel(.Lst_small_struct)	// FFI_IA64_TYPE_SMALL_STRUCT
    533 	data8	@pcrel(.Lst_hfa_float)		// FFI_IA64_TYPE_HFA_FLOAT
    534 	data8	@pcrel(.Lst_hfa_double)		// FFI_IA64_TYPE_HFA_DOUBLE
    535 	data8	@pcrel(.Lst_hfa_ldouble)	// FFI_IA64_TYPE_HFA_LDOUBLE
    536 
    537 .Lld_table:
    538 	data8	@pcrel(.Lld_void)		// FFI_TYPE_VOID
    539 	data8	@pcrel(.Lld_int)		// FFI_TYPE_INT
    540 	data8	@pcrel(.Lld_float)		// FFI_TYPE_FLOAT
    541 	data8	@pcrel(.Lld_double)		// FFI_TYPE_DOUBLE
    542 	data8	@pcrel(.Lld_ldouble)		// FFI_TYPE_LONGDOUBLE
    543 	data8	@pcrel(.Lld_int)		// FFI_TYPE_UINT8
    544 	data8	@pcrel(.Lld_int)		// FFI_TYPE_SINT8
    545 	data8	@pcrel(.Lld_int)		// FFI_TYPE_UINT16
    546 	data8	@pcrel(.Lld_int)		// FFI_TYPE_SINT16
    547 	data8	@pcrel(.Lld_int)		// FFI_TYPE_UINT32
    548 	data8	@pcrel(.Lld_int)		// FFI_TYPE_SINT32
    549 	data8	@pcrel(.Lld_int)		// FFI_TYPE_UINT64
    550 	data8	@pcrel(.Lld_int)		// FFI_TYPE_SINT64
    551 	data8	@pcrel(.Lld_void)		// FFI_TYPE_STRUCT
    552 	data8	@pcrel(.Lld_int)		// FFI_TYPE_POINTER
    553 	data8 	@pcrel(.Lld_small_struct)	// FFI_IA64_TYPE_SMALL_STRUCT
    554 	data8	@pcrel(.Lld_hfa_float)		// FFI_IA64_TYPE_HFA_FLOAT
    555 	data8	@pcrel(.Lld_hfa_double)		// FFI_IA64_TYPE_HFA_DOUBLE
    556 	data8	@pcrel(.Lld_hfa_ldouble)	// FFI_IA64_TYPE_HFA_LDOUBLE
    557 
    558 #if defined __ELF__ && defined __linux__
    559 	.section	.note.GNU-stack,"",@progbits
    560 #endif
    561