Home | History | Annotate | Download | only in m68k
      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 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 
     59 CALLFUNC(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 #else
     76 	bsr.l	CALLFUNC(ffi_prep_args@PLTPC)
     77 #endif
     78 	addq.l	#8,%sp
     79 
     80 	| Pass pointer to struct value, if any
     81 #ifdef __MINT__
     82 	move.l	%d0,%a1
     83 #else
     84 	move.l	%a0,%a1
     85 #endif
     86 
     87 	| Call the function
     88 	move.l	24(%fp),%a0
     89 	jsr	(%a0)
     90 
     91 	| Remove the space we pushed for the args
     92 	add.l	12(%fp),%sp
     93 
     94 	| Load the pointer to storage for the return value
     95 	move.l	20(%fp),%a1
     96 
     97 	| Load the return type code
     98 	move.l	16(%fp),%d2
     99 
    100 	| If the return value pointer is NULL, assume no return value.
    101 	| NOTE: On the mc68000, tst on an address register is not supported.
    102 #if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__)
    103 	cmp.w	#0, %a1
    104 #else
    105 	tst.l	%a1
    106 #endif
    107 	jbeq	noretval
    108 
    109 	btst	#0,%d2
    110 	jbeq	retlongint
    111 	move.l	%d0,(%a1)
    112 	jbra	epilogue
    113 
    114 retlongint:
    115 	btst	#1,%d2
    116 	jbeq	retfloat
    117 	move.l	%d0,(%a1)
    118 	move.l	%d1,4(%a1)
    119 	jbra	epilogue
    120 
    121 retfloat:
    122 	btst	#2,%d2
    123 	jbeq	retdouble
    124 #if defined(__MC68881__) || defined(__HAVE_68881__)
    125 	fmove.s	%fp0,(%a1)
    126 #else
    127 	move.l	%d0,(%a1)
    128 #endif
    129 	jbra	epilogue
    130 
    131 retdouble:
    132 	btst	#3,%d2
    133 	jbeq	retlongdouble
    134 #if defined(__MC68881__) || defined(__HAVE_68881__)
    135 	fmove.d	%fp0,(%a1)
    136 #else
    137 	move.l	%d0,(%a1)+
    138 	move.l	%d1,(%a1)
    139 #endif
    140 	jbra	epilogue
    141 
    142 retlongdouble:
    143 	btst	#4,%d2
    144 	jbeq	retpointer
    145 #if defined(__MC68881__) || defined(__HAVE_68881__)
    146 	fmove.x	%fp0,(%a1)
    147 #else
    148 	move.l	%d0,(%a1)+
    149 	move.l	%d1,(%a1)+
    150 	move.l	%d2,(%a1)
    151 #endif
    152 	jbra	epilogue
    153 
    154 retpointer:
    155 	btst	#5,%d2
    156 	jbeq	retstruct1
    157 #ifdef __MINT__
    158 	move.l	%d0,(%a1)
    159 #else
    160 	move.l	%a0,(%a1)
    161 #endif
    162 	jbra	epilogue
    163 
    164 retstruct1:
    165 	btst	#6,%d2
    166 	jbeq	retstruct2
    167 	move.b	%d0,(%a1)
    168 	jbra	epilogue
    169 
    170 retstruct2:
    171 	btst	#7,%d2
    172 	jbeq	retsint8
    173 	move.w	%d0,(%a1)
    174 	jbra	epilogue
    175 
    176 retsint8:
    177 	btst	#8,%d2
    178 	jbeq	retsint16
    179 	| NOTE: On the mc68000, extb is not supported. 8->16, then 16->32.
    180 #if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__)
    181 	ext.w	%d0
    182 	ext.l	%d0
    183 #else
    184 	extb.l	%d0
    185 #endif
    186 	move.l	%d0,(%a1)
    187 	jbra	epilogue
    188 
    189 retsint16:
    190 	btst	#9,%d2
    191 	jbeq	noretval
    192 	ext.l	%d0
    193 	move.l	%d0,(%a1)
    194 
    195 noretval:
    196 epilogue:
    197 	move.l	(%sp)+,%d2
    198 	unlk	%fp
    199 	rts
    200 	CFI_ENDPROC()
    201 	.size	CALLFUNC(ffi_call_SYSV),.-CALLFUNC(ffi_call_SYSV)
    202 
    203 	.globl	CALLFUNC(ffi_closure_SYSV)
    204 	.type	CALLFUNC(ffi_closure_SYSV), @function
    205 	.align	4
    206 
    207 CALLFUNC(ffi_closure_SYSV):
    208 	CFI_STARTPROC()
    209 	link	%fp,#-12
    210 	CFI_OFFSET(14,-8)
    211 	CFI_DEF_CFA(14,8)
    212 	move.l	%sp,-12(%fp)
    213 	pea	8(%fp)
    214 	pea	-12(%fp)
    215 	move.l	%a0,-(%sp)
    216 #if !defined __PIC__
    217 	jsr	CALLFUNC(ffi_closure_SYSV_inner)
    218 #else
    219 	bsr.l	CALLFUNC(ffi_closure_SYSV_inner@PLTPC)
    220 #endif
    221 
    222 	lsr.l	#1,%d0
    223 	jne	1f
    224 	jcc	.Lcls_epilogue
    225 	| CIF_FLAGS_INT
    226 	move.l	-12(%fp),%d0
    227 .Lcls_epilogue:
    228 	| no CIF_FLAGS_*
    229 	unlk	%fp
    230 	rts
    231 1:
    232 	lea	-12(%fp),%a0
    233 	lsr.l	#2,%d0
    234 	jne	1f
    235 	jcs	.Lcls_ret_float
    236 	| CIF_FLAGS_DINT
    237 	move.l	(%a0)+,%d0
    238 	move.l	(%a0),%d1
    239 	jra	.Lcls_epilogue
    240 .Lcls_ret_float:
    241 #if defined(__MC68881__) || defined(__HAVE_68881__)
    242 	fmove.s	(%a0),%fp0
    243 #else
    244 	move.l	(%a0),%d0
    245 #endif
    246 	jra	.Lcls_epilogue
    247 1:
    248 	lsr.l	#2,%d0
    249 	jne	1f
    250 	jcs	.Lcls_ret_ldouble
    251 	| CIF_FLAGS_DOUBLE
    252 #if defined(__MC68881__) || defined(__HAVE_68881__)
    253 	fmove.d	(%a0),%fp0
    254 #else
    255 	move.l	(%a0)+,%d0
    256 	move.l	(%a0),%d1
    257 #endif
    258 	jra	.Lcls_epilogue
    259 .Lcls_ret_ldouble:
    260 #if defined(__MC68881__) || defined(__HAVE_68881__)
    261 	fmove.x	(%a0),%fp0
    262 #else
    263 	move.l	(%a0)+,%d0
    264 	move.l	(%a0)+,%d1
    265 	move.l	(%a0),%d2
    266 #endif
    267 	jra	.Lcls_epilogue
    268 1:
    269 	lsr.l	#2,%d0
    270 	jne	1f
    271 	jcs	.Lcls_ret_struct1
    272 	| CIF_FLAGS_POINTER
    273 	move.l	(%a0),%a0
    274 	move.l	%a0,%d0
    275 	jra	.Lcls_epilogue
    276 .Lcls_ret_struct1:
    277 	move.b	(%a0),%d0
    278 	jra	.Lcls_epilogue
    279 1:
    280 	lsr.l	#2,%d0
    281 	jne	1f
    282 	jcs	.Lcls_ret_sint8
    283 	| CIF_FLAGS_STRUCT2
    284 	move.w	(%a0),%d0
    285 	jra	.Lcls_epilogue
    286 .Lcls_ret_sint8:
    287 	move.l	(%a0),%d0
    288 	| NOTE: On the mc68000, extb is not supported. 8->16, then 16->32.
    289 #if !defined(__mc68020__) && !defined(__mc68030__) && !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcoldfire__)
    290 	ext.w	%d0
    291 	ext.l	%d0
    292 #else
    293 	extb.l	%d0
    294 #endif
    295 	jra	.Lcls_epilogue
    296 1:
    297 	| CIF_FLAGS_SINT16
    298 	move.l	(%a0),%d0
    299 	ext.l	%d0
    300 	jra	.Lcls_epilogue
    301 	CFI_ENDPROC()
    302 
    303 	.size	CALLFUNC(ffi_closure_SYSV),.-CALLFUNC(ffi_closure_SYSV)
    304 
    305 	.globl	CALLFUNC(ffi_closure_struct_SYSV)
    306 	.type	CALLFUNC(ffi_closure_struct_SYSV), @function
    307 	.align	4
    308 
    309 CALLFUNC(ffi_closure_struct_SYSV):
    310 	CFI_STARTPROC()
    311 	link	%fp,#0
    312 	CFI_OFFSET(14,-8)
    313 	CFI_DEF_CFA(14,8)
    314 	move.l	%sp,-12(%fp)
    315 	pea	8(%fp)
    316 	move.l	%a1,-(%sp)
    317 	move.l	%a0,-(%sp)
    318 #if !defined __PIC__
    319 	jsr	CALLFUNC(ffi_closure_SYSV_inner)
    320 #else
    321 	bsr.l	CALLFUNC(ffi_closure_SYSV_inner@PLTPC)
    322 #endif
    323 	unlk	%fp
    324 	rts
    325 	CFI_ENDPROC()
    326 	.size	CALLFUNC(ffi_closure_struct_SYSV),.-CALLFUNC(ffi_closure_struct_SYSV)
    327 
    328 #if defined __ELF__ && defined __linux__
    329 	.section	.note.GNU-stack,"",@progbits
    330 #endif
    331