$OpenBSD: patch-src_m68k_sysv_S,v 1.2 2013/07/15 19:01:56 miod Exp $

Match the calling convention used by NetBSD and OpenBSD on m68k/ELF, which
differs from Linux/ELF: structs are always passed on the stack, functions
returning structs receive the struct pointer in %a0 instead of %a1.

Add an OpenBSD-specific function to flush the instruction cache after
building closure trampolines.

--- src/m68k/sysv.S.orig	Tue Dec 29 15:22:26 2009
+++ src/m68k/sysv.S	Mon Jul 15 18:54:57 2013
@@ -68,12 +68,21 @@ ffi_call_SYSV:
 #endif
 	addq.l	#8,%sp	
 
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+	| Pointer to struct value, if any, is in %a0, as expected by the
+	| called function.
+
+	| Call the function
+	move.l	24(%fp),%a1
+	jsr	(%a1)
+#else
 	| Pass pointer to struct value, if any
 	move.l	%a0,%a1
 
 	| Call the function
 	move.l	24(%fp),%a0
 	jsr	(%a0)
+#endif
 
 	| Remove the space we pushed for the args
 	add.l	12(%fp),%sp
@@ -132,9 +141,23 @@ retstruct1:
 
 retstruct2:
 	btst	#7,%d2
-	jbeq	noretval
+	jbeq	retsint8
 	move.w	%d0,(%a1)
+	jbra	epilogue
 
+retsint8:
+	btst	#8,%d2
+	jbeq	retsint16
+	extb.l	%d0
+	move.l	%d0,(%a1)
+	jbra	epilogue
+
+retsint16:
+	btst	#9,%d2
+	jbeq	noretval
+	ext.l	%d0
+	move.l	%d0,(%a1)
+
 noretval:
 epilogue:
 	move.l	(%sp)+,%d2
@@ -191,7 +214,7 @@ ffi_closure_SYSV:
 	jra	.Lcls_epilogue
 1:
 	lsr.l	#2,%d0
-	jne	.Lcls_ret_struct2
+	jne	1f
 	jcs	.Lcls_ret_struct1
 	move.l	(%a0),%a0
 	move.l	%a0,%d0
@@ -199,9 +222,20 @@ ffi_closure_SYSV:
 .Lcls_ret_struct1:
 	move.b	(%a0),%d0
 	jra	.Lcls_epilogue
-.Lcls_ret_struct2:
+1:
+	lsr.l	#2,%d0
+	jne	1f
+	jcs	.Lcls_ret_sint8
 	move.w	(%a0),%d0
 	jra	.Lcls_epilogue
+.Lcls_ret_sint8:
+	move.l	(%a0),%d0
+	extb.l	%d0
+	jra	.Lcls_epilogue
+1:
+	move.l	(%a0),%d0
+	ext.l	%d0
+	jra	.Lcls_epilogue
 	CFI_ENDPROC()
 
 	.size	ffi_closure_SYSV,.-ffi_closure_SYSV
@@ -217,8 +251,13 @@ ffi_closure_struct_SYSV:
 	CFI_DEF_CFA(14,8)
 	move.l	%sp,-12(%fp)
 	pea	8(%fp)
-	move.l	%a1,-(%sp)
-	move.l	%a0,-(%sp)
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+	move.l	%a0,-(%sp)	/* struct return address */
+	move.l	%a1,-(%sp)	/* closure */
+#else
+	move.l	%a1,-(%sp)	/* struct return address */
+	move.l	%a0,-(%sp)	/* closure */
+#endif
 #if !defined __PIC__
 	jsr	ffi_closure_SYSV_inner
 #else
@@ -228,6 +267,20 @@ ffi_closure_struct_SYSV:
 	rts
 	CFI_ENDPROC()
 	.size	ffi_closure_struct_SYSV,.-ffi_closure_struct_SYSV
+
+#ifdef __OpenBSD__
+	.globl	ffi_sync_icache
+	.type	ffi_sync_icache, @function
+	.align	4
+
+ffi_sync_icache:
+	movl	%sp@(8), %d1		| length
+	movl	%sp@(4), %a1		| address
+	movl	#0x80000004, %d0	| CC_EXTPURGE | CC_IPURGE
+	trap	#12
+	rts
+	.size	ffi_sync_icache,.-ffi_sync_icache
+#endif
 
 #if defined __ELF__ && defined __linux__
 	.section	.note.GNU-stack,"",@progbits
