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