1 /* ----------------------------------------------------------------------- 2 v8.S - Copyright (c) 1996, 1997, 2003, 2004, 2008 Red Hat, Inc. 3 4 SPARC 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 #define STACKFRAME 96 /* Minimum stack framesize for SPARC */ 32 #define ARGS (64+4) /* Offset of register area in frame */ 33 34 .text 35 .align 8 36 .globl ffi_call_v8 37 .globl _ffi_call_v8 38 39 ffi_call_v8: 40 _ffi_call_v8: 41 .LLFB1: 42 save %sp, -STACKFRAME, %sp 43 .LLCFI0: 44 45 sub %sp, %i2, %sp ! alloca() space in stack for frame to set up 46 add %sp, STACKFRAME, %l0 ! %l0 has start of 47 ! frame to set up 48 49 mov %l0, %o0 ! call routine to set up frame 50 call %i0 51 mov %i1, %o1 ! (delay) 52 53 ld [%l0+ARGS], %o0 ! call foreign function 54 ld [%l0+ARGS+4], %o1 55 ld [%l0+ARGS+8], %o2 56 ld [%l0+ARGS+12], %o3 57 ld [%l0+ARGS+16], %o4 58 ld [%l0+ARGS+20], %o5 59 call %i5 60 mov %l0, %sp ! (delay) switch to frame 61 nop ! STRUCT returning functions skip 12 instead of 8 bytes 62 63 ! If the return value pointer is NULL, assume no return value. 64 tst %i4 65 bz done 66 nop 67 68 cmp %i3, FFI_TYPE_INT 69 be,a done 70 st %o0, [%i4] ! (delay) 71 72 cmp %i3, FFI_TYPE_FLOAT 73 be,a done 74 st %f0, [%i4+0] ! (delay) 75 76 cmp %i3, FFI_TYPE_SINT64 77 be longlong 78 79 cmp %i3, FFI_TYPE_DOUBLE 80 bne done 81 nop 82 st %f0, [%i4+0] 83 st %f1, [%i4+4] 84 85 done: 86 ret 87 restore 88 89 longlong: 90 st %o0, [%i4+0] 91 st %o1, [%i4+4] 92 ret 93 restore 94 .LLFE1: 95 96 .ffi_call_v8_end: 97 .size ffi_call_v8,.ffi_call_v8_end-ffi_call_v8 98 99 100 #undef STACKFRAME 101 #define STACKFRAME 104 /* 16*4 register window + 102 1*4 struct return + 103 6*4 args backing store + 104 3*4 locals */ 105 106 /* ffi_closure_v8(...) 107 108 Receives the closure argument in %g2. */ 109 110 .text 111 .align 8 112 .globl ffi_closure_v8 113 114 ffi_closure_v8: 115 #ifdef HAVE_AS_REGISTER_PSEUDO_OP 116 .register %g2, #scratch 117 #endif 118 .LLFB2: 119 ! Reserve frame space for all arguments in case 120 ! we need to align them on a 8-byte boundary. 121 ld [%g2+FFI_TRAMPOLINE_SIZE], %g1 122 ld [%g1+4], %g1 123 sll %g1, 3, %g1 124 add %g1, STACKFRAME, %g1 125 ! %g1 == STACKFRAME + 8*nargs 126 neg %g1 127 save %sp, %g1, %sp 128 .LLCFI1: 129 130 ! Store all of the potential argument registers in va_list format. 131 st %i0, [%fp+68+0] 132 st %i1, [%fp+68+4] 133 st %i2, [%fp+68+8] 134 st %i3, [%fp+68+12] 135 st %i4, [%fp+68+16] 136 st %i5, [%fp+68+20] 137 138 ! Call ffi_closure_sparc_inner to do the bulk of the work. 139 mov %g2, %o0 140 add %fp, -8, %o1 141 add %fp, 64, %o2 142 call ffi_closure_sparc_inner_v8 143 add %fp, -16, %o3 144 145 ! Load up the return value in the proper type. 146 ! See ffi_prep_cif_machdep for the list of cases. 147 cmp %o0, FFI_TYPE_VOID 148 be done1 149 150 cmp %o0, FFI_TYPE_INT 151 be integer 152 153 cmp %o0, FFI_TYPE_FLOAT 154 be,a done1 155 ld [%fp-8], %f0 156 157 cmp %o0, FFI_TYPE_DOUBLE 158 be,a done1 159 ldd [%fp-8], %f0 160 161 #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE 162 cmp %o0, FFI_TYPE_LONGDOUBLE 163 be done2 164 #endif 165 166 cmp %o0, FFI_TYPE_STRUCT 167 be done2 168 169 ! FFI_TYPE_SINT64 170 ! FFI_TYPE_UINT64 171 ld [%fp-4], %i1 172 173 integer: 174 ld [%fp-8], %i0 175 176 done1: 177 jmp %i7+8 178 restore 179 done2: 180 ! Skip 'unimp'. 181 jmp %i7+12 182 restore 183 .LLFE2: 184 185 .ffi_closure_v8_end: 186 .size ffi_closure_v8,.ffi_closure_v8_end-ffi_closure_v8 187 188 #ifdef SPARC64 189 #define WS 8 190 #define nword xword 191 #define uanword uaxword 192 #else 193 #define WS 4 194 #define nword long 195 #define uanword uaword 196 #endif 197 198 #ifdef HAVE_RO_EH_FRAME 199 .section ".eh_frame",#alloc 200 #else 201 .section ".eh_frame",#alloc,#write 202 #endif 203 .LLframe1: 204 .uaword .LLECIE1-.LLSCIE1 ! Length of Common Information Entry 205 .LLSCIE1: 206 .uaword 0x0 ! CIE Identifier Tag 207 .byte 0x1 ! CIE Version 208 .ascii "zR\0" ! CIE Augmentation 209 .byte 0x1 ! uleb128 0x1; CIE Code Alignment Factor 210 .byte 0x80-WS ! sleb128 -WS; CIE Data Alignment Factor 211 .byte 0xf ! CIE RA Column 212 .byte 0x1 ! uleb128 0x1; Augmentation size 213 #ifdef HAVE_AS_SPARC_UA_PCREL 214 .byte 0x1b ! FDE Encoding (pcrel sdata4) 215 #else 216 .byte 0x50 ! FDE Encoding (aligned absolute) 217 #endif 218 .byte 0xc ! DW_CFA_def_cfa 219 .byte 0xe ! uleb128 0xe 220 .byte 0x0 ! uleb128 0x0 221 .align WS 222 .LLECIE1: 223 .LLSFDE1: 224 .uaword .LLEFDE1-.LLASFDE1 ! FDE Length 225 .LLASFDE1: 226 .uaword .LLASFDE1-.LLframe1 ! FDE CIE offset 227 #ifdef HAVE_AS_SPARC_UA_PCREL 228 .uaword %r_disp32(.LLFB1) 229 .uaword .LLFE1-.LLFB1 ! FDE address range 230 #else 231 .align WS 232 .nword .LLFB1 233 .uanword .LLFE1-.LLFB1 ! FDE address range 234 #endif 235 .byte 0x0 ! uleb128 0x0; Augmentation size 236 .byte 0x4 ! DW_CFA_advance_loc4 237 .uaword .LLCFI0-.LLFB1 238 .byte 0xd ! DW_CFA_def_cfa_register 239 .byte 0x1e ! uleb128 0x1e 240 .byte 0x2d ! DW_CFA_GNU_window_save 241 .byte 0x9 ! DW_CFA_register 242 .byte 0xf ! uleb128 0xf 243 .byte 0x1f ! uleb128 0x1f 244 .align WS 245 .LLEFDE1: 246 .LLSFDE2: 247 .uaword .LLEFDE2-.LLASFDE2 ! FDE Length 248 .LLASFDE2: 249 .uaword .LLASFDE2-.LLframe1 ! FDE CIE offset 250 #ifdef HAVE_AS_SPARC_UA_PCREL 251 .uaword %r_disp32(.LLFB2) 252 .uaword .LLFE2-.LLFB2 ! FDE address range 253 #else 254 .align WS 255 .nword .LLFB2 256 .uanword .LLFE2-.LLFB2 ! FDE address range 257 #endif 258 .byte 0x0 ! uleb128 0x0; Augmentation size 259 .byte 0x4 ! DW_CFA_advance_loc4 260 .uaword .LLCFI1-.LLFB2 261 .byte 0xd ! DW_CFA_def_cfa_register 262 .byte 0x1e ! uleb128 0x1e 263 .byte 0x2d ! DW_CFA_GNU_window_save 264 .byte 0x9 ! DW_CFA_register 265 .byte 0xf ! uleb128 0xf 266 .byte 0x1f ! uleb128 0x1f 267 .align WS 268 .LLEFDE2: 269 270 #if defined __ELF__ && defined __linux__ 271 .section .note.GNU-stack,"",@progbits 272 #endif 273