1/* ----------------------------------------------------------------------- 2 linux.S - (c) 2003-2004 Randolph Chung <tausq@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: 48ffi_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: 261ffi_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#ifdef __PIC__ 301 .ascii "zR\0" ;# CIE Augmentation: 'z' - data, 'R' - DW_EH_PE_... data 302#else 303 .ascii "\0" ;# CIE Augmentation 304#endif 305 .uleb128 0x1 ;# CIE Code Alignment Factor 306 .sleb128 4 ;# CIE Data Alignment Factor 307 .byte 0x2 ;# CIE RA Column 308#ifdef __PIC__ 309 .uleb128 0x1 ;# Augmentation size 310 .byte 0x1b ;# FDE Encoding (DW_EH_PE_pcrel|DW_EH_PE_sdata4) 311#endif 312 .byte 0xc ;# DW_CFA_def_cfa 313 .uleb128 0x1e 314 .uleb128 0x0 315 .align 4 316.LECIE1: 317.LSFDE1: 318 .word .LEFDE1-.LASFDE1 ;# FDE Length 319.LASFDE1: 320 .word .LASFDE1-.Lframe1 ;# FDE CIE offset 321#ifdef __PIC__ 322 .word .LFB1-. ;# FDE initial location 323#else 324 .word .LFB1 ;# FDE initial location 325#endif 326 .word .LFE1-.LFB1 ;# FDE address range 327#ifdef __PIC__ 328 .uleb128 0x0 ;# Augmentation size: no data 329#endif 330 .byte 0x4 ;# DW_CFA_advance_loc4 331 .word .LCFI11-.LFB1 332 .byte 0x83 ;# DW_CFA_offset, column 0x3 333 .uleb128 0x0 334 .byte 0x11 ;# DW_CFA_offset_extended_sf; save r2 at [r30-20] 335 .uleb128 0x2 336 .sleb128 -5 337 338 .byte 0x4 ;# DW_CFA_advance_loc4 339 .word .LCFI12-.LCFI11 340 .byte 0xd ;# DW_CFA_def_cfa_register = r3 341 .uleb128 0x3 342 343 .byte 0x4 ;# DW_CFA_advance_loc4 344 .word .LCFI13-.LCFI12 345 .byte 0x84 ;# DW_CFA_offset, column 0x4 346 .uleb128 0x3 347 348 .align 4 349.LEFDE1: 350 351.LSFDE2: 352 .word .LEFDE2-.LASFDE2 ;# FDE Length 353.LASFDE2: 354 .word .LASFDE2-.Lframe1 ;# FDE CIE offset 355#ifdef __PIC__ 356 .word .LFB2-. ;# FDE initial location 357#else 358 .word .LFB2 ;# FDE initial location 359#endif 360 .word .LFE2-.LFB2 ;# FDE address range 361#ifdef __PIC__ 362 .uleb128 0x0 ;# Augmentation size: no data 363#endif 364 .byte 0x4 ;# DW_CFA_advance_loc4 365 .word .LCFI21-.LFB2 366 .byte 0x83 ;# DW_CFA_offset, column 0x3 367 .uleb128 0x0 368 .byte 0x11 ;# DW_CFA_offset_extended_sf 369 .uleb128 0x2 370 .sleb128 -5 371 372 .byte 0x4 ;# DW_CFA_advance_loc4 373 .word .LCFI22-.LCFI21 374 .byte 0xd ;# DW_CFA_def_cfa_register = r3 375 .uleb128 0x3 376 377 .align 4 378.LEFDE2: 379