diff dyncall/dyncall_call_sparc.S @ 0:3e629dc19168

initial from svn dyncall-1745
author Daniel Adler
date Thu, 19 Mar 2015 22:24:28 +0100
parents
children 3729a99ef03c
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dyncall/dyncall_call_sparc.S	Thu Mar 19 22:24:28 2015 +0100
@@ -0,0 +1,193 @@
+/*
+
+ Package: dyncall
+ Library: dyncall
+ File: dyncall/dyncall_call_sparc.S
+ Description: Call kernel for sparc processor architecture.
+ License:
+
+   Copyright (c) 2011-2015 Daniel Adler <dadler@uni-goettingen.de>
+
+   Permission to use, copy, modify, and distribute this software for any
+   purpose with or without fee is hereby granted, provided that the above
+   copyright notice and this permission notice appear in all copies.
+
+   THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+   WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+   MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+   ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+*/
+
+
+
+
+/* --------------------------------------------------------------------------- 
+
+call kernel for sparc 32-bit
+----------------------------
+tested on linux/debian [gcc54.fsffrance.org - thanx to the farm!] 
+
+new C Interface:
+  void dcCall_sparc (DCCallVM* callvm, DCpointer target);
+                     %i0               %1 
+
+we need to do that, due to the special property of sparc, its 'register windows'
+that propagate input registers..
+otherwise, we would have a 'void' return-value layer which results in failure
+to propagate back return values.
+instead of implementing 'dummy'-C return-values, we call directly.
+
+in sparc, this is simply a leaf-function layer using %o3.
+
+old C Interface:
+  void dcCall_sparc (DCpointer target, DCsize size, DCpointer data);
+		     %i0             , %i1        , %i2
+
+
+Input:
+  i0   callvm
+  i1   target
+
+old Input:
+  i0   target
+  i1   size
+  i2   data
+
+Description:
+We need to raise a dynamic stack frame.
+Therefore we need to compute the stack size in the context of the caller as a leaf note (using o3 in addition).
+Then we raise the frame.
+
+sparc:
+- big endian
+
+sparc V8:
+- integer/pointer: 32 32-bit integers.
+- float: 8 quad precision, 16 double precision, 32 single precision.
+
+sparc V9:
+- integer/pointer: 32 64-bit integers.
+
+plan9:
+- completely different scheme - similar to mips/plan9.
+- registers are named r0 .. r31
+  r1 stack pointer
+  r2 static base register
+  .. to be continued..
+
+Stack Layout 32-Bit Model:
+- sp+92 seventh argument
+- sp+68 first argument
+- sp+64 
+- 16 registers save area (in/local).
+
+	XX: should be 8 byte aligned (min stack frame size is 96).
+	            ...
+	92: on stack argument 6
+	88: input argument 5 spill
+	            ...
+	68: input argument 0 spill
+	64: struct/union pointer return value
+	 0: 16 registers save area
+
+Stack Layout 64-Bit Model:
+        XX: should be 16 byte aligned (min stack frame size is 172).
+       168: on stack argument 6
+       136: input argument 0 spill
+       128: struct/union poiner return value
+	 0: 16 registers save area
+
+
+
+Register Usage:
+%sp or  %o6: stack pointer, always 8 (or 16?)-byte aligned.
+%fp or  %i6: frame pointer.
+%i0 and %o0: integer and pointer return values.
+%i7 and %o7: return address. (caller puts return address to %o7, callee uses %i7)
+%f0 and %f1: return value (float).
+%i0..%i5:    input argument registers 
+%o0..%o5:    output argument registers
+%g0:         always zero, writes to it have no effect.
+
+Register Mappings:
+r0-7    -> globals
+r8-15   -> outs
+r16-r23 -> locals
+r24-r31 -> ins
+
+*/
+
+#if defined __arch64__
+#define REGSIZE 8
+#error invalid arch
+#else
+#define REGSIZE 4
+#endif
+
+#define ALIGN   16
+CALLVM_size    = 12
+CALLVM_dataoff = 16
+.global dcCall_sparc
+dcCall_sparc:
+
+/* Basic Prolog: supports up to 6 arguments. */
+
+	/* new C interface */
+	/* o0-1: callvm,target */
+	
+	or   %o0, %g0, %o3	       /* %o3: callvm */
+	or   %o1, %g0, %o0	       /* %o0: target */
+	ld  [%o3+CALLVM_size], %o1     /* %o1: size */
+	add  %o3, CALLVM_dataoff, %o2  /* %o2: data */
+	/*o0-2:target,size,data*/
+
+	/*leaf functions: may use the first six output registers.*/
+	/*o3-5:free to use */
+
+	/* Compute a matiching stack size (approximate): o3 = align(92+o1,16) */
+
+	add     %o1, (16+1+6)*REGSIZE+ALIGN-1, %o3
+	and     %o3,   -ALIGN, %o3
+	neg     %o3
+	
+	/* Prolog. */
+	save	%sp, %o3, %sp	/* min stack size (16+1+6)*sizeof(ptr)=92 paddded to 8-byte alignment => min frame size of 96 bytes. */
+	
+	/* Load output registers. */
+
+	ld	[%i2           ],%o0
+	ld	[%i2+REGSIZE*1 ],%o1
+	ld	[%i2+REGSIZE*2 ],%o2
+	ld	[%i2+REGSIZE*3 ],%o3
+	ld	[%i2+REGSIZE*4 ],%o4
+	ld	[%i2+REGSIZE*5 ],%o5
+
+	/* Copy on stack? */
+	sub	%i1,  REGSIZE*6, %i1   		/* i1 = decrement copy size by 6 regs (=6 regs x 4 bytes = 24 bytes total). */
+	cmp %i1, 0
+    ble .do_call
+	nop
+
+	/* Copy loop: */
+	add     %i2,  REGSIZE*6, %i2	/* i2 = address of 7th word of args buffer. */
+	or      %g0, %g0, %l0			/* l0 = offset initialized to 0. */
+	add     %sp,  (16+1+6)*REGSIZE, %l2	/* l2 = argument area on stack space (7th word). (64+4+6*4 = byte offset 92). */
+.next:
+	ld      [%i2+%l0],%l1			/* Read from arg buffer(%i2) to %l1. */
+	st      %l1, [%l2+%l0]			/* Write %l1 to stack space(%l2). */
+	add     %l0, REGSIZE, %l0		/* Increment offset. */
+	sub     %i1, REGSIZE, %i1		/* Decrement copy size. */
+	cmp     %i1, 0
+	bgt     .next
+	nop
+.do_call:
+	call    %i0						/* Call target. */
+	nop
+    	or     %o0, %g0, %i0
+    	or     %o1, %g0, %i1
+	jmpl	%i7 + 8, %g0
+	restore