Home | History | Annotate | Download | only in pa
      1 /* -----------------------------------------------------------------------
      2    hpux32.S - Copyright (c) 2006 Free Software Foundation, Inc.
      3 	                (c) 2008 Red Hat, Inc.
      4    based on src/pa/linux.S
      5 
      6    HP-UX PA Foreign Function Interface
      7 
      8    Permission is hereby granted, free of charge, to any person obtaining
      9    a copy of this software and associated documentation files (the
     10    ``Software''), to deal in the Software without restriction, including
     11    without limitation the rights to use, copy, modify, merge, publish,
     12    distribute, sublicense, and/or sell copies of the Software, and to
     13    permit persons to whom the Software is furnished to do so, subject to
     14    the following conditions:
     15 
     16    The above copyright notice and this permission notice shall be included
     17    in all copies or substantial portions of the Software.
     18 
     19    THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
     20    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     21    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     22    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
     23    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     24    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     25    OTHER DEALINGS IN THE SOFTWARE.
     26    ----------------------------------------------------------------------- */
     27 
     28 #define LIBFFI_ASM
     29 #include <fficonfig.h>
     30 #include <ffi.h>
     31 
     32 	.LEVEL 1.1
     33 	.SPACE	$PRIVATE$
     34 	.IMPORT	$global$,DATA
     35 	.IMPORT	$$dyncall,MILLICODE
     36 	.SUBSPA	$DATA$
     37 	.align	4
     38 
     39 	/* void ffi_call_pa32(void (*)(char *, extended_cif *),
     40 			       extended_cif *ecif,
     41 			       unsigned bytes,
     42 			       unsigned flags,
     43 			       unsigned *rvalue,
     44 			       void (*fn)(void));
     45 	 */
     46 
     47 	.export	ffi_call_pa32,ENTRY,PRIV_LEV=3
     48 	.import	ffi_prep_args_pa32,CODE
     49 
     50 	.SPACE	$TEXT$
     51 	.SUBSPA $CODE$
     52 	.align	4
     53 
     54 L$FB1
     55 ffi_call_pa32
     56 	.proc
     57 	.callinfo	FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=4
     58 	.entry
     59 	stw	%rp, -20(%sp)
     60 	copy	%r3, %r1
     61 L$CFI11
     62 	copy	%sp, %r3
     63 L$CFI12
     64 
     65 	/* Setup the stack for calling prep_args...
     66 	   We want the stack to look like this:
     67 
     68 	   [ Previous stack                            ] <- %r3
     69 
     70 	   [ 64-bytes register save area               ] <- %r4
     71 
     72 	   [ Stack space for actual call, passed as    ] <- %arg0
     73 	   [     arg0 to ffi_prep_args_pa32           ]
     74 
     75 	   [ Stack for calling prep_args               ] <- %sp
     76 	 */
     77 
     78 	stwm	%r1, 64(%sp)
     79 	stw	%r4, 12(%r3)
     80 L$CFI13
     81 	copy	%sp, %r4
     82 
     83 	addl	%arg2, %r4, %arg0	; arg stack
     84 	stw	%arg3, -48(%r3)		; save flags we need it later
     85 
     86 	/* Call prep_args:
     87 	   %arg0(stack) -- set up above
     88 	   %arg1(ecif)  -- same as incoming param
     89 	   %arg2(bytes) -- same as incoming param */
     90 	bl	ffi_prep_args_pa32,%r2
     91 	ldo	64(%arg0), %sp
     92 	ldo	-64(%sp), %sp
     93 
     94 	/* now %sp should point where %arg0 was pointing.  */
     95 
     96 	/* Load the arguments that should be passed in registers
     97 	   The fp args are loaded by the prep_args function.  */
     98 	ldw	-36(%sp), %arg0
     99 	ldw	-40(%sp), %arg1
    100 	ldw	-44(%sp), %arg2
    101 	ldw	-48(%sp), %arg3
    102 
    103 	/* in case the function is going to return a structure
    104 	   we need to give it a place to put the result.  */
    105 	ldw	-52(%r3), %ret0		; %ret0 <- rvalue
    106 	ldw	-56(%r3), %r22		; %r22 <- function to call
    107 	bl	$$dyncall, %r31		; Call the user function
    108 	copy	%r31, %rp
    109 
    110 	/* Prepare to store the result; we need to recover flags and rvalue.  */
    111 	ldw	-48(%r3), %r21		; r21 <- flags
    112 	ldw	-52(%r3), %r20		; r20 <- rvalue
    113 
    114 	/* Store the result according to the return type.  The most
    115 	   likely types should come first.  */
    116 
    117 L$checkint
    118 	comib,<>,n FFI_TYPE_INT, %r21, L$checkint8
    119 	b	L$done
    120 	stw	%ret0, 0(%r20)
    121 
    122 L$checkint8
    123 	comib,<>,n FFI_TYPE_UINT8, %r21, L$checkint16
    124 	b	L$done
    125 	stb	%ret0, 0(%r20)
    126 
    127 L$checkint16
    128 	comib,<>,n FFI_TYPE_UINT16, %r21, L$checkdbl
    129 	b	L$done
    130 	sth	%ret0, 0(%r20)
    131 
    132 L$checkdbl
    133 	comib,<>,n FFI_TYPE_DOUBLE, %r21, L$checkfloat
    134 	b	L$done
    135 	fstd	%fr4,0(%r20)
    136 
    137 L$checkfloat
    138 	comib,<>,n FFI_TYPE_FLOAT, %r21, L$checkll
    139 	b	L$done
    140 	fstw	%fr4L,0(%r20)
    141 
    142 L$checkll
    143 	comib,<>,n FFI_TYPE_UINT64, %r21, L$checksmst2
    144 	stw	%ret0, 0(%r20)
    145 	b	L$done
    146 	stw	%ret1, 4(%r20)
    147 
    148 L$checksmst2
    149 	comib,<>,n FFI_TYPE_SMALL_STRUCT2, %r21, L$checksmst3
    150 	/* 2-byte structs are returned in ret0 as ????xxyy.  */
    151 	extru	%ret0, 23, 8, %r22
    152 	stbs,ma	%r22, 1(%r20)
    153 	b	L$done
    154 	stb	%ret0, 0(%r20)
    155 
    156 L$checksmst3
    157 	comib,<>,n FFI_TYPE_SMALL_STRUCT3, %r21, L$checksmst4
    158 	/* 3-byte structs are returned in ret0 as ??xxyyzz.  */
    159 	extru	%ret0, 15, 8, %r22
    160 	stbs,ma	%r22, 1(%r20)
    161 	extru	%ret0, 23, 8, %r22
    162 	stbs,ma	%r22, 1(%r20)
    163 	b	L$done
    164 	stb	%ret0, 0(%r20)
    165 
    166 L$checksmst4
    167 	comib,<>,n FFI_TYPE_SMALL_STRUCT4, %r21, L$checksmst5
    168 	/* 4-byte structs are returned in ret0 as wwxxyyzz.  */
    169 	extru	%ret0, 7, 8, %r22
    170 	stbs,ma	%r22, 1(%r20)
    171 	extru	%ret0, 15, 8, %r22
    172 	stbs,ma	%r22, 1(%r20)
    173 	extru	%ret0, 23, 8, %r22
    174 	stbs,ma	%r22, 1(%r20)
    175 	b	L$done
    176 	stb	%ret0, 0(%r20)
    177 
    178 L$checksmst5
    179 	comib,<>,n FFI_TYPE_SMALL_STRUCT5, %r21, L$checksmst6
    180 	/* 5 byte values are returned right justified:
    181 	      ret0     ret1
    182 	   5: ??????aa bbccddee */
    183 	stbs,ma	%ret0, 1(%r20)
    184 	extru	%ret1, 7, 8, %r22
    185 	stbs,ma	%r22, 1(%r20)
    186 	extru	%ret1, 15, 8, %r22
    187 	stbs,ma	%r22, 1(%r20)
    188 	extru	%ret1, 23, 8, %r22
    189 	stbs,ma	%r22, 1(%r20)
    190 	b	L$done
    191 	stb	%ret1, 0(%r20)
    192 
    193 L$checksmst6
    194 	comib,<>,n FFI_TYPE_SMALL_STRUCT6, %r21, L$checksmst7
    195 	/* 6 byte values are returned right justified:
    196 	      ret0     ret1
    197 	   6: ????aabb ccddeeff */
    198 	extru	%ret0, 23, 8, %r22
    199 	stbs,ma	%r22, 1(%r20)
    200 	stbs,ma	%ret0, 1(%r20)
    201 	extru	%ret1, 7, 8, %r22
    202 	stbs,ma	%r22, 1(%r20)
    203 	extru	%ret1, 15, 8, %r22
    204 	stbs,ma	%r22, 1(%r20)
    205 	extru	%ret1, 23, 8, %r22
    206 	stbs,ma	%r22, 1(%r20)
    207 	b	L$done
    208 	stb	%ret1, 0(%r20)
    209 
    210 L$checksmst7
    211 	comib,<>,n FFI_TYPE_SMALL_STRUCT7, %r21, L$checksmst8
    212 	/* 7 byte values are returned right justified:
    213 	      ret0     ret1
    214 	   7: ??aabbcc ddeeffgg */
    215 	extru	%ret0, 15, 8, %r22
    216 	stbs,ma	%r22, 1(%r20)
    217 	extru	%ret0, 23, 8, %r22
    218 	stbs,ma	%r22, 1(%r20)
    219 	stbs,ma	%ret0, 1(%r20)
    220 	extru	%ret1, 7, 8, %r22
    221 	stbs,ma	%r22, 1(%r20)
    222 	extru	%ret1, 15, 8, %r22
    223 	stbs,ma	%r22, 1(%r20)
    224 	extru	%ret1, 23, 8, %r22
    225 	stbs,ma	%r22, 1(%r20)
    226 	b	L$done
    227 	stb	%ret1, 0(%r20)
    228 
    229 L$checksmst8
    230 	comib,<>,n FFI_TYPE_SMALL_STRUCT8, %r21, L$done
    231 	/* 8 byte values are returned right justified:
    232 	      ret0     ret1
    233 	   8: aabbccdd eeffgghh */
    234 	extru	%ret0, 7, 8, %r22
    235 	stbs,ma	%r22, 1(%r20)
    236 	extru	%ret0, 15, 8, %r22
    237 	stbs,ma	%r22, 1(%r20)
    238 	extru	%ret0, 23, 8, %r22
    239 	stbs,ma	%r22, 1(%r20)
    240 	stbs,ma	%ret0, 1(%r20)
    241 	extru	%ret1, 7, 8, %r22
    242 	stbs,ma	%r22, 1(%r20)
    243 	extru	%ret1, 15, 8, %r22
    244 	stbs,ma	%r22, 1(%r20)
    245 	extru	%ret1, 23, 8, %r22
    246 	stbs,ma	%r22, 1(%r20)
    247 	stb	%ret1, 0(%r20)
    248 
    249 L$done
    250 	/* all done, return */
    251 	copy	%r4, %sp	; pop arg stack
    252 	ldw	12(%r3), %r4
    253 	ldwm	-64(%sp), %r3	; .. and pop stack
    254 	ldw	-20(%sp), %rp
    255 	bv	%r0(%rp)
    256 	nop
    257 	.exit
    258 	.procend
    259 L$FE1
    260 
    261 	/* void ffi_closure_pa32(void);
    262 	   Called with closure argument in %r21 */
    263 
    264 	.SPACE $TEXT$
    265 	.SUBSPA $CODE$
    266 	.export ffi_closure_pa32,ENTRY,PRIV_LEV=3,RTNVAL=GR
    267 	.import ffi_closure_inner_pa32,CODE
    268 	.align 4
    269 L$FB2
    270 ffi_closure_pa32
    271 	.proc
    272 	.callinfo FRAME=64,CALLS,SAVE_RP,SAVE_SP,ENTRY_GR=3
    273 	.entry
    274 
    275 	stw	%rp, -20(%sp)
    276 	copy	%r3, %r1
    277 L$CFI21
    278 	copy	%sp, %r3
    279 L$CFI22
    280 	stwm	%r1, 64(%sp)
    281 
    282 	/* Put arguments onto the stack and call ffi_closure_inner.  */
    283 	stw	%arg0, -36(%r3)
    284 	stw	%arg1, -40(%r3)
    285 	stw	%arg2, -44(%r3)
    286 	stw	%arg3, -48(%r3)
    287 
    288 	copy	%r21, %arg0
    289 	bl	ffi_closure_inner_pa32, %r2
    290 	copy    %r3, %arg1
    291 	ldwm	-64(%sp), %r3
    292 	ldw	-20(%sp), %rp
    293 	ldw	-36(%sp), %ret0
    294 	bv	%r0(%rp)
    295 	ldw	-40(%sp), %ret1
    296 	.exit
    297 	.procend
    298 L$FE2:
    299 
    300 	.SPACE $PRIVATE$
    301 	.SUBSPA $DATA$
    302 
    303 	.align 4
    304 	.EXPORT _GLOBAL__F_ffi_call_pa32,DATA
    305 _GLOBAL__F_ffi_call_pa32
    306 L$frame1:
    307 	.word   L$ECIE1-L$SCIE1 ;# Length of Common Information Entry
    308 L$SCIE1:
    309 	.word   0x0     ;# CIE Identifier Tag
    310 	.byte   0x1     ;# CIE Version
    311 	.ascii "\0"     ;# CIE Augmentation
    312 	.uleb128 0x1    ;# CIE Code Alignment Factor
    313 	.sleb128 4      ;# CIE Data Alignment Factor
    314 	.byte   0x2     ;# CIE RA Column
    315 	.byte   0xc     ;# DW_CFA_def_cfa
    316 	.uleb128 0x1e
    317 	.uleb128 0x0
    318 	.align 4
    319 L$ECIE1:
    320 L$SFDE1:
    321 	.word   L$EFDE1-L$ASFDE1        ;# FDE Length
    322 L$ASFDE1:
    323 	.word   L$ASFDE1-L$frame1       ;# FDE CIE offset
    324 	.word   L$FB1   ;# FDE initial location
    325 	.word   L$FE1-L$FB1     ;# FDE address range
    326 
    327 	.byte   0x4     ;# DW_CFA_advance_loc4
    328 	.word   L$CFI11-L$FB1
    329 	.byte	0x83	;# DW_CFA_offset, column 0x3
    330 	.uleb128 0x0
    331 	.byte   0x11    ;# DW_CFA_offset_extended_sf; save r2 at [r30-20]
    332 	.uleb128 0x2
    333 	.sleb128 -5
    334 
    335 	.byte   0x4     ;# DW_CFA_advance_loc4
    336 	.word   L$CFI12-L$CFI11
    337 	.byte   0xd     ;# DW_CFA_def_cfa_register = r3
    338 	.uleb128 0x3
    339 
    340 	.byte   0x4     ;# DW_CFA_advance_loc4
    341 	.word   L$CFI13-L$CFI12
    342 	.byte	0x84	;# DW_CFA_offset, column 0x4
    343 	.uleb128 0x3
    344 
    345 	.align 4
    346 L$EFDE1:
    347 
    348 L$SFDE2:
    349 	.word   L$EFDE2-L$ASFDE2        ;# FDE Length
    350 L$ASFDE2:
    351 	.word   L$ASFDE2-L$frame1       ;# FDE CIE offset
    352 	.word   L$FB2   ;# FDE initial location
    353 	.word   L$FE2-L$FB2     ;# FDE address range
    354 	.byte   0x4     ;# DW_CFA_advance_loc4
    355 	.word   L$CFI21-L$FB2
    356 	.byte   0x83    ;# DW_CFA_offset, column 0x3
    357 	.uleb128 0x0
    358 	.byte   0x11    ;# DW_CFA_offset_extended_sf
    359 	.uleb128 0x2
    360 	.sleb128 -5
    361 
    362 	.byte   0x4     ;# DW_CFA_advance_loc4
    363 	.word   L$CFI22-L$CFI21
    364 	.byte   0xd     ;# DW_CFA_def_cfa_register = r3
    365 	.uleb128 0x3
    366 
    367 	.align 4
    368 L$EFDE2:
    369