1/* ----------------------------------------------------------------------- 2 3 sysv.S - Copyright (c) 2012 Alan Hourihane 4 Copyright (c) 1998, 2012 Andreas Schwab 5 Copyright (c) 2008 Red Hat, Inc. 6 Copyright (c) 2012, 2016 Thorsten Glaser 7 8 m68k Foreign Function Interface 9 10 Permission is hereby granted, free of charge, to any person obtaining 11 a copy of this software and associated documentation files (the 12 ``Software''), to deal in the Software without restriction, including 13 without limitation the rights to use, copy, modify, merge, publish, 14 distribute, sublicense, and/or sell copies of the Software, and to 15 permit persons to whom the Software is furnished to do so, subject to 16 the following conditions: 17 18 The above copyright notice and this permission notice shall be included 19 in all copies or substantial portions of the Software. 20 21 THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, 22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 24 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 25 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 26 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28 DEALINGS IN THE SOFTWARE. 29 ----------------------------------------------------------------------- */ 30 31#define LIBFFI_ASM 32#include <fficonfig.h> 33#include <ffi.h> 34 35#ifdef HAVE_AS_CFI_PSEUDO_OP 36#define CFI_STARTPROC() .cfi_startproc 37#define CFI_OFFSET(reg,off) .cfi_offset reg,off 38#define CFI_DEF_CFA(reg,off) .cfi_def_cfa reg,off 39#define CFI_ENDPROC() .cfi_endproc 40#else 41#define CFI_STARTPROC() 42#define CFI_OFFSET(reg,off) 43#define CFI_DEF_CFA(reg,off) 44#define CFI_ENDPROC() 45#endif 46 47#ifdef __MINT__ 48#define CALLFUNC(funcname) _ ## funcname 49#else 50#define CALLFUNC(funcname) funcname 51#endif 52 53 .text 54 55 .globl CALLFUNC(ffi_call_SYSV) 56 .type CALLFUNC(ffi_call_SYSV),@function 57 .align 4 58 59CALLFUNC(ffi_call_SYSV): 60 CFI_STARTPROC() 61 link %fp,#0 62 CFI_OFFSET(14,-8) 63 CFI_DEF_CFA(14,8) 64 move.l %d2,-(%sp) 65 CFI_OFFSET(2,-12) 66 67 | Make room for all of the new args. 68 sub.l 12(%fp),%sp 69 70 | Call ffi_prep_args 71 move.l 8(%fp),-(%sp) 72 pea 4(%sp) 73#if !defined __PIC__ 74 jsr CALLFUNC(ffi_prep_args) 75#elif defined(__uClinux__) && defined(__ID_SHARED_LIBRARY__) 76 move.l _current_shared_library_a5_offset_(%a5),%a0 77 move.l CALLFUNC(ffi_prep_args@GOT)(%a0),%a0 78 jsr (%a0) 79#elif defined(__mcoldfire__) && !defined(__mcfisab__) && !defined(__mcfisac__) 80 move.l #_GLOBAL_OFFSET_TABLE_@GOTPC,%a0 81 lea (-6,%pc,%a0),%a0 82 move.l CALLFUNC(ffi_prep_args@GOT)(%a0),%a0 83 jsr (%a0) 84#else 85 bsr.l CALLFUNC(ffi_prep_args@PLTPC) 86#endif 87 addq.l #8,%sp 88 89 | Pass pointer to struct value, if any 90#ifdef __MINT__ 91 move.l %d0,%a1 92#else 93 move.l %a0,%a1 94#endif 95 96 | Call the function 97 move.l 24(%fp),%a0 98 jsr (%a0) 99 100 | Remove the space we pushed for the args 101 add.l 12(%fp),%sp 102 103 | Load the pointer to storage for the return value 104 move.l 20(%fp),%a1 105 106 | Load the return type code 107 move.l 16(%fp),%d2 108 109 | If the return value pointer is NULL, assume no return value. 110 | NOTE: On the mc68000, tst on an address register is not supported. 111#if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__) 112 cmp.w #0, %a1 113#else 114 tst.l %a1 115#endif 116 jbeq noretval 117 118 btst #0,%d2 119 jbeq retlongint 120 move.l %d0,(%a1) 121 jbra epilogue 122 123retlongint: 124 btst #1,%d2 125 jbeq retfloat 126 move.l %d0,(%a1) 127 move.l %d1,4(%a1) 128 jbra epilogue 129 130retfloat: 131 btst #2,%d2 132 jbeq retdouble 133#if defined(__MC68881__) || defined(__HAVE_68881__) 134 fmove.s %fp0,(%a1) 135#else 136 move.l %d0,(%a1) 137#endif 138 jbra epilogue 139 140retdouble: 141 btst #3,%d2 142 jbeq retlongdouble 143#if defined(__MC68881__) || defined(__HAVE_68881__) 144 fmove.d %fp0,(%a1) 145#else 146 move.l %d0,(%a1)+ 147 move.l %d1,(%a1) 148#endif 149 jbra epilogue 150 151retlongdouble: 152 btst #4,%d2 153 jbeq retpointer 154#if defined(__MC68881__) || defined(__HAVE_68881__) 155 fmove.x %fp0,(%a1) 156#else 157 move.l %d0,(%a1)+ 158 move.l %d1,(%a1)+ 159 move.l %d2,(%a1) 160#endif 161 jbra epilogue 162 163retpointer: 164 btst #5,%d2 165 jbeq retstruct1 166#ifdef __MINT__ 167 move.l %d0,(%a1) 168#else 169 move.l %a0,(%a1) 170#endif 171 jbra epilogue 172 173retstruct1: 174 btst #6,%d2 175 jbeq retstruct2 176 move.b %d0,(%a1) 177 jbra epilogue 178 179retstruct2: 180 btst #7,%d2 181 jbeq retsint8 182 move.w %d0,(%a1) 183 jbra epilogue 184 185retsint8: 186 btst #8,%d2 187 jbeq retsint16 188 | NOTE: On the mc68000, extb is not supported. 8->16, then 16->32. 189#if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__) 190 ext.w %d0 191 ext.l %d0 192#else 193 extb.l %d0 194#endif 195 move.l %d0,(%a1) 196 jbra epilogue 197 198retsint16: 199 btst #9,%d2 200 jbeq noretval 201 ext.l %d0 202 move.l %d0,(%a1) 203 204noretval: 205epilogue: 206 move.l (%sp)+,%d2 207 unlk %fp 208 rts 209 CFI_ENDPROC() 210 .size CALLFUNC(ffi_call_SYSV),.-CALLFUNC(ffi_call_SYSV) 211 212 .globl CALLFUNC(ffi_closure_SYSV) 213 .type CALLFUNC(ffi_closure_SYSV), @function 214 .align 4 215 216CALLFUNC(ffi_closure_SYSV): 217 CFI_STARTPROC() 218 link %fp,#-12 219 CFI_OFFSET(14,-8) 220 CFI_DEF_CFA(14,8) 221 move.l %sp,-12(%fp) 222 pea 8(%fp) 223 pea -12(%fp) 224 move.l %a0,-(%sp) 225#if !defined __PIC__ 226 jsr CALLFUNC(ffi_closure_SYSV_inner) 227#elif defined(__uClinux__) && defined(__ID_SHARED_LIBRARY__) 228 move.l _current_shared_library_a5_offset_(%a5),%a0 229 move.l CALLFUNC(ffi_closure_SYSV_inner@GOT)(%a0),%a0 230 jsr (%a0) 231#elif defined(__mcoldfire__) && !defined(__mcfisab__) && !defined(__mcfisac__) 232 move.l #_GLOBAL_OFFSET_TABLE_@GOTPC,%a0 233 lea (-6,%pc,%a0),%a0 234 move.l CALLFUNC(ffi_closure_SYSV_inner@GOT)(%a0),%a0 235 jsr (%a0) 236#else 237 bsr.l CALLFUNC(ffi_closure_SYSV_inner@PLTPC) 238#endif 239 240 lsr.l #1,%d0 241 jne 1f 242 jcc .Lcls_epilogue 243 | CIF_FLAGS_INT 244 move.l -12(%fp),%d0 245.Lcls_epilogue: 246 | no CIF_FLAGS_* 247 unlk %fp 248 rts 2491: 250 lea -12(%fp),%a0 251 lsr.l #2,%d0 252 jne 1f 253 jcs .Lcls_ret_float 254 | CIF_FLAGS_DINT 255 move.l (%a0)+,%d0 256 move.l (%a0),%d1 257 jra .Lcls_epilogue 258.Lcls_ret_float: 259#if defined(__MC68881__) || defined(__HAVE_68881__) 260 fmove.s (%a0),%fp0 261#else 262 move.l (%a0),%d0 263#endif 264 jra .Lcls_epilogue 2651: 266 lsr.l #2,%d0 267 jne 1f 268 jcs .Lcls_ret_ldouble 269 | CIF_FLAGS_DOUBLE 270#if defined(__MC68881__) || defined(__HAVE_68881__) 271 fmove.d (%a0),%fp0 272#else 273 move.l (%a0)+,%d0 274 move.l (%a0),%d1 275#endif 276 jra .Lcls_epilogue 277.Lcls_ret_ldouble: 278#if defined(__MC68881__) || defined(__HAVE_68881__) 279 fmove.x (%a0),%fp0 280#else 281 move.l (%a0)+,%d0 282 move.l (%a0)+,%d1 283 move.l (%a0),%d2 284#endif 285 jra .Lcls_epilogue 2861: 287 lsr.l #2,%d0 288 jne 1f 289 jcs .Lcls_ret_struct1 290 | CIF_FLAGS_POINTER 291 move.l (%a0),%a0 292 move.l %a0,%d0 293 jra .Lcls_epilogue 294.Lcls_ret_struct1: 295 move.b (%a0),%d0 296 jra .Lcls_epilogue 2971: 298 lsr.l #2,%d0 299 jne 1f 300 jcs .Lcls_ret_sint8 301 | CIF_FLAGS_STRUCT2 302 move.w (%a0),%d0 303 jra .Lcls_epilogue 304.Lcls_ret_sint8: 305 move.l (%a0),%d0 306 | NOTE: On the mc68000, extb is not supported. 8->16, then 16->32. 307#if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__) 308 ext.w %d0 309 ext.l %d0 310#else 311 extb.l %d0 312#endif 313 jra .Lcls_epilogue 3141: 315 | CIF_FLAGS_SINT16 316 move.l (%a0),%d0 317 ext.l %d0 318 jra .Lcls_epilogue 319 CFI_ENDPROC() 320 321 .size CALLFUNC(ffi_closure_SYSV),.-CALLFUNC(ffi_closure_SYSV) 322 323 .globl CALLFUNC(ffi_closure_struct_SYSV) 324 .type CALLFUNC(ffi_closure_struct_SYSV), @function 325 .align 4 326 327CALLFUNC(ffi_closure_struct_SYSV): 328 CFI_STARTPROC() 329 link %fp,#0 330 CFI_OFFSET(14,-8) 331 CFI_DEF_CFA(14,8) 332 move.l %sp,-12(%fp) 333 pea 8(%fp) 334 move.l %a1,-(%sp) 335 move.l %a0,-(%sp) 336#if !defined __PIC__ 337 jsr CALLFUNC(ffi_closure_SYSV_inner) 338#elif defined(__uClinux__) && defined(__ID_SHARED_LIBRARY__) 339 move.l _current_shared_library_a5_offset_(%a5),%a0 340 move.l CALLFUNC(ffi_closure_SYSV_inner@GOT)(%a0),%a0 341 jsr (%a0) 342#elif defined(__mcoldfire__) && !defined(__mcfisab__) && !defined(__mcfisac__) 343 move.l #_GLOBAL_OFFSET_TABLE_@GOTPC,%a0 344 lea (-6,%pc,%a0),%a0 345 move.l CALLFUNC(ffi_closure_SYSV_inner@GOT)(%a0),%a0 346 jsr (%a0) 347#else 348 bsr.l CALLFUNC(ffi_closure_SYSV_inner@PLTPC) 349#endif 350 unlk %fp 351 rts 352 CFI_ENDPROC() 353 .size CALLFUNC(ffi_closure_struct_SYSV),.-CALLFUNC(ffi_closure_struct_SYSV) 354 355#if defined __ELF__ && defined __linux__ 356 .section .note.GNU-stack,"",@progbits 357#endif 358