1 /* ----------------------------------------------------------------------- 2 v9.S - Copyright (c) 2000, 2003, 2004, 2008 Red Hat, Inc. 3 4 SPARC 64-bit 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, 18 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 24 DEALINGS IN THE SOFTWARE. 25 ----------------------------------------------------------------------- */ 26 27 #define LIBFFI_ASM 28 #include <fficonfig.h> 29 #include <ffi.h> 30 31 #ifdef SPARC64 32 /* Only compile this in for 64bit builds, because otherwise the object file 33 will have inproper architecture due to used instructions. */ 34 35 #define STACKFRAME 128 /* Minimum stack framesize for SPARC */ 36 #define STACK_BIAS 2047 37 #define ARGS (128) /* Offset of register area in frame */ 38 39 .text 40 .align 8 41 .globl ffi_call_v9 42 .globl _ffi_call_v9 43 44 ffi_call_v9: 45 _ffi_call_v9: 46 .LLFB1: 47 save %sp, -STACKFRAME, %sp 48 .LLCFI0: 49 50 sub %sp, %i2, %sp ! alloca() space in stack for frame to set up 51 add %sp, STACKFRAME+STACK_BIAS, %l0 ! %l0 has start of 52 ! frame to set up 53 54 mov %l0, %o0 ! call routine to set up frame 55 call %i0 56 mov %i1, %o1 ! (delay) 57 brz,pt %o0, 1f 58 ldx [%l0+ARGS], %o0 ! call foreign function 59 60 ldd [%l0+ARGS], %f0 61 ldd [%l0+ARGS+8], %f2 62 ldd [%l0+ARGS+16], %f4 63 ldd [%l0+ARGS+24], %f6 64 ldd [%l0+ARGS+32], %f8 65 ldd [%l0+ARGS+40], %f10 66 ldd [%l0+ARGS+48], %f12 67 ldd [%l0+ARGS+56], %f14 68 ldd [%l0+ARGS+64], %f16 69 ldd [%l0+ARGS+72], %f18 70 ldd [%l0+ARGS+80], %f20 71 ldd [%l0+ARGS+88], %f22 72 ldd [%l0+ARGS+96], %f24 73 ldd [%l0+ARGS+104], %f26 74 ldd [%l0+ARGS+112], %f28 75 ldd [%l0+ARGS+120], %f30 76 77 1: ldx [%l0+ARGS+8], %o1 78 ldx [%l0+ARGS+16], %o2 79 ldx [%l0+ARGS+24], %o3 80 ldx [%l0+ARGS+32], %o4 81 ldx [%l0+ARGS+40], %o5 82 call %i5 83 sub %l0, STACK_BIAS, %sp ! (delay) switch to frame 84 85 ! If the return value pointer is NULL, assume no return value. 86 brz,pn %i4, done 87 nop 88 89 cmp %i3, FFI_TYPE_INT 90 be,a,pt %icc, done 91 stx %o0, [%i4+0] ! (delay) 92 93 cmp %i3, FFI_TYPE_FLOAT 94 be,a,pn %icc, done 95 st %f0, [%i4+0] ! (delay) 96 97 cmp %i3, FFI_TYPE_DOUBLE 98 be,a,pn %icc, done 99 std %f0, [%i4+0] ! (delay) 100 101 cmp %i3, FFI_TYPE_STRUCT 102 be,pn %icc, dostruct 103 104 cmp %i3, FFI_TYPE_LONGDOUBLE 105 bne,pt %icc, done 106 nop 107 std %f0, [%i4+0] 108 std %f2, [%i4+8] 109 110 done: ret 111 restore 112 113 dostruct: 114 /* This will not work correctly for unions. */ 115 stx %o0, [%i4+0] 116 stx %o1, [%i4+8] 117 stx %o2, [%i4+16] 118 stx %o3, [%i4+24] 119 std %f0, [%i4+32] 120 std %f2, [%i4+40] 121 std %f4, [%i4+48] 122 std %f6, [%i4+56] 123 ret 124 restore 125 .LLFE1: 126 127 .ffi_call_v9_end: 128 .size ffi_call_v9,.ffi_call_v9_end-ffi_call_v9 129 130 131 #undef STACKFRAME 132 #define STACKFRAME 336 /* 16*8 register window + 133 6*8 args backing store + 134 20*8 locals */ 135 #define FP %fp+STACK_BIAS 136 137 /* ffi_closure_v9(...) 138 139 Receives the closure argument in %g1. */ 140 141 .text 142 .align 8 143 .globl ffi_closure_v9 144 145 ffi_closure_v9: 146 .LLFB2: 147 save %sp, -STACKFRAME, %sp 148 .LLCFI1: 149 150 ! Store all of the potential argument registers in va_list format. 151 stx %i0, [FP+128+0] 152 stx %i1, [FP+128+8] 153 stx %i2, [FP+128+16] 154 stx %i3, [FP+128+24] 155 stx %i4, [FP+128+32] 156 stx %i5, [FP+128+40] 157 158 ! Store possible floating point argument registers too. 159 std %f0, [FP-128] 160 std %f2, [FP-120] 161 std %f4, [FP-112] 162 std %f6, [FP-104] 163 std %f8, [FP-96] 164 std %f10, [FP-88] 165 std %f12, [FP-80] 166 std %f14, [FP-72] 167 std %f16, [FP-64] 168 std %f18, [FP-56] 169 std %f20, [FP-48] 170 std %f22, [FP-40] 171 std %f24, [FP-32] 172 std %f26, [FP-24] 173 std %f28, [FP-16] 174 std %f30, [FP-8] 175 176 ! Call ffi_closure_sparc_inner to do the bulk of the work. 177 mov %g1, %o0 178 add %fp, STACK_BIAS-160, %o1 179 add %fp, STACK_BIAS+128, %o2 180 call ffi_closure_sparc_inner_v9 181 add %fp, STACK_BIAS-128, %o3 182 183 ! Load up the return value in the proper type. 184 ! See ffi_prep_cif_machdep for the list of cases. 185 cmp %o0, FFI_TYPE_VOID 186 be,pn %icc, done1 187 188 cmp %o0, FFI_TYPE_INT 189 be,pn %icc, integer 190 191 cmp %o0, FFI_TYPE_FLOAT 192 be,a,pn %icc, done1 193 ld [FP-160], %f0 194 195 cmp %o0, FFI_TYPE_DOUBLE 196 be,a,pn %icc, done1 197 ldd [FP-160], %f0 198 199 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE 200 cmp %o0, FFI_TYPE_LONGDOUBLE 201 be,a,pn %icc, longdouble1 202 ldd [FP-160], %f0 203 #endif 204 205 ! FFI_TYPE_STRUCT 206 ldx [FP-152], %i1 207 ldx [FP-144], %i2 208 ldx [FP-136], %i3 209 ldd [FP-160], %f0 210 ldd [FP-152], %f2 211 ldd [FP-144], %f4 212 ldd [FP-136], %f6 213 214 integer: 215 ldx [FP-160], %i0 216 217 done1: 218 ret 219 restore 220 221 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE 222 longdouble1: 223 ldd [FP-152], %f2 224 ret 225 restore 226 #endif 227 .LLFE2: 228 229 .ffi_closure_v9_end: 230 .size ffi_closure_v9,.ffi_closure_v9_end-ffi_closure_v9 231 232 #ifdef HAVE_RO_EH_FRAME 233 .section ".eh_frame",#alloc 234 #else 235 .section ".eh_frame",#alloc,#write 236 #endif 237 .LLframe1: 238 .uaword .LLECIE1-.LLSCIE1 ! Length of Common Information Entry 239 .LLSCIE1: 240 .uaword 0x0 ! CIE Identifier Tag 241 .byte 0x1 ! CIE Version 242 .ascii "zR\0" ! CIE Augmentation 243 .byte 0x1 ! uleb128 0x1; CIE Code Alignment Factor 244 .byte 0x78 ! sleb128 -8; CIE Data Alignment Factor 245 .byte 0xf ! CIE RA Column 246 .byte 0x1 ! uleb128 0x1; Augmentation size 247 #ifdef HAVE_AS_SPARC_UA_PCREL 248 .byte 0x1b ! FDE Encoding (pcrel sdata4) 249 #else 250 .byte 0x50 ! FDE Encoding (aligned absolute) 251 #endif 252 .byte 0xc ! DW_CFA_def_cfa 253 .byte 0xe ! uleb128 0xe 254 .byte 0xff,0xf ! uleb128 0x7ff 255 .align 8 256 .LLECIE1: 257 .LLSFDE1: 258 .uaword .LLEFDE1-.LLASFDE1 ! FDE Length 259 .LLASFDE1: 260 .uaword .LLASFDE1-.LLframe1 ! FDE CIE offset 261 #ifdef HAVE_AS_SPARC_UA_PCREL 262 .uaword %r_disp32(.LLFB1) 263 .uaword .LLFE1-.LLFB1 ! FDE address range 264 #else 265 .align 8 266 .xword .LLFB1 267 .uaxword .LLFE1-.LLFB1 ! FDE address range 268 #endif 269 .byte 0x0 ! uleb128 0x0; Augmentation size 270 .byte 0x4 ! DW_CFA_advance_loc4 271 .uaword .LLCFI0-.LLFB1 272 .byte 0xd ! DW_CFA_def_cfa_register 273 .byte 0x1e ! uleb128 0x1e 274 .byte 0x2d ! DW_CFA_GNU_window_save 275 .byte 0x9 ! DW_CFA_register 276 .byte 0xf ! uleb128 0xf 277 .byte 0x1f ! uleb128 0x1f 278 .align 8 279 .LLEFDE1: 280 .LLSFDE2: 281 .uaword .LLEFDE2-.LLASFDE2 ! FDE Length 282 .LLASFDE2: 283 .uaword .LLASFDE2-.LLframe1 ! FDE CIE offset 284 #ifdef HAVE_AS_SPARC_UA_PCREL 285 .uaword %r_disp32(.LLFB2) 286 .uaword .LLFE2-.LLFB2 ! FDE address range 287 #else 288 .align 8 289 .xword .LLFB2 290 .uaxword .LLFE2-.LLFB2 ! FDE address range 291 #endif 292 .byte 0x0 ! uleb128 0x0; Augmentation size 293 .byte 0x4 ! DW_CFA_advance_loc4 294 .uaword .LLCFI1-.LLFB2 295 .byte 0xd ! DW_CFA_def_cfa_register 296 .byte 0x1e ! uleb128 0x1e 297 .byte 0x2d ! DW_CFA_GNU_window_save 298 .byte 0x9 ! DW_CFA_register 299 .byte 0xf ! uleb128 0xf 300 .byte 0x1f ! uleb128 0x1f 301 .align 8 302 .LLEFDE2: 303 #endif 304 305 #ifdef __linux__ 306 .section .note.GNU-stack,"",@progbits 307 #endif 308