comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:3e629dc19168
1 /*
2
3 Package: dyncall
4 Library: dyncall
5 File: dyncall/dyncall_call_sparc.S
6 Description: Call kernel for sparc processor architecture.
7 License:
8
9 Copyright (c) 2011-2015 Daniel Adler <dadler@uni-goettingen.de>
10
11 Permission to use, copy, modify, and distribute this software for any
12 purpose with or without fee is hereby granted, provided that the above
13 copyright notice and this permission notice appear in all copies.
14
15 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
16 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
18 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
21 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23 */
24
25
26
27
28 /* ---------------------------------------------------------------------------
29
30 call kernel for sparc 32-bit
31 ----------------------------
32 tested on linux/debian [gcc54.fsffrance.org - thanx to the farm!]
33
34 new C Interface:
35 void dcCall_sparc (DCCallVM* callvm, DCpointer target);
36 %i0 %1
37
38 we need to do that, due to the special property of sparc, its 'register windows'
39 that propagate input registers..
40 otherwise, we would have a 'void' return-value layer which results in failure
41 to propagate back return values.
42 instead of implementing 'dummy'-C return-values, we call directly.
43
44 in sparc, this is simply a leaf-function layer using %o3.
45
46 old C Interface:
47 void dcCall_sparc (DCpointer target, DCsize size, DCpointer data);
48 %i0 , %i1 , %i2
49
50
51 Input:
52 i0 callvm
53 i1 target
54
55 old Input:
56 i0 target
57 i1 size
58 i2 data
59
60 Description:
61 We need to raise a dynamic stack frame.
62 Therefore we need to compute the stack size in the context of the caller as a leaf note (using o3 in addition).
63 Then we raise the frame.
64
65 sparc:
66 - big endian
67
68 sparc V8:
69 - integer/pointer: 32 32-bit integers.
70 - float: 8 quad precision, 16 double precision, 32 single precision.
71
72 sparc V9:
73 - integer/pointer: 32 64-bit integers.
74
75 plan9:
76 - completely different scheme - similar to mips/plan9.
77 - registers are named r0 .. r31
78 r1 stack pointer
79 r2 static base register
80 .. to be continued..
81
82 Stack Layout 32-Bit Model:
83 - sp+92 seventh argument
84 - sp+68 first argument
85 - sp+64
86 - 16 registers save area (in/local).
87
88 XX: should be 8 byte aligned (min stack frame size is 96).
89 ...
90 92: on stack argument 6
91 88: input argument 5 spill
92 ...
93 68: input argument 0 spill
94 64: struct/union pointer return value
95 0: 16 registers save area
96
97 Stack Layout 64-Bit Model:
98 XX: should be 16 byte aligned (min stack frame size is 172).
99 168: on stack argument 6
100 136: input argument 0 spill
101 128: struct/union poiner return value
102 0: 16 registers save area
103
104
105
106 Register Usage:
107 %sp or %o6: stack pointer, always 8 (or 16?)-byte aligned.
108 %fp or %i6: frame pointer.
109 %i0 and %o0: integer and pointer return values.
110 %i7 and %o7: return address. (caller puts return address to %o7, callee uses %i7)
111 %f0 and %f1: return value (float).
112 %i0..%i5: input argument registers
113 %o0..%o5: output argument registers
114 %g0: always zero, writes to it have no effect.
115
116 Register Mappings:
117 r0-7 -> globals
118 r8-15 -> outs
119 r16-r23 -> locals
120 r24-r31 -> ins
121
122 */
123
124 #if defined __arch64__
125 #define REGSIZE 8
126 #error invalid arch
127 #else
128 #define REGSIZE 4
129 #endif
130
131 #define ALIGN 16
132 CALLVM_size = 12
133 CALLVM_dataoff = 16
134 .global dcCall_sparc
135 dcCall_sparc:
136
137 /* Basic Prolog: supports up to 6 arguments. */
138
139 /* new C interface */
140 /* o0-1: callvm,target */
141
142 or %o0, %g0, %o3 /* %o3: callvm */
143 or %o1, %g0, %o0 /* %o0: target */
144 ld [%o3+CALLVM_size], %o1 /* %o1: size */
145 add %o3, CALLVM_dataoff, %o2 /* %o2: data */
146 /*o0-2:target,size,data*/
147
148 /*leaf functions: may use the first six output registers.*/
149 /*o3-5:free to use */
150
151 /* Compute a matiching stack size (approximate): o3 = align(92+o1,16) */
152
153 add %o1, (16+1+6)*REGSIZE+ALIGN-1, %o3
154 and %o3, -ALIGN, %o3
155 neg %o3
156
157 /* Prolog. */
158 save %sp, %o3, %sp /* min stack size (16+1+6)*sizeof(ptr)=92 paddded to 8-byte alignment => min frame size of 96 bytes. */
159
160 /* Load output registers. */
161
162 ld [%i2 ],%o0
163 ld [%i2+REGSIZE*1 ],%o1
164 ld [%i2+REGSIZE*2 ],%o2
165 ld [%i2+REGSIZE*3 ],%o3
166 ld [%i2+REGSIZE*4 ],%o4
167 ld [%i2+REGSIZE*5 ],%o5
168
169 /* Copy on stack? */
170 sub %i1, REGSIZE*6, %i1 /* i1 = decrement copy size by 6 regs (=6 regs x 4 bytes = 24 bytes total). */
171 cmp %i1, 0
172 ble .do_call
173 nop
174
175 /* Copy loop: */
176 add %i2, REGSIZE*6, %i2 /* i2 = address of 7th word of args buffer. */
177 or %g0, %g0, %l0 /* l0 = offset initialized to 0. */
178 add %sp, (16+1+6)*REGSIZE, %l2 /* l2 = argument area on stack space (7th word). (64+4+6*4 = byte offset 92). */
179 .next:
180 ld [%i2+%l0],%l1 /* Read from arg buffer(%i2) to %l1. */
181 st %l1, [%l2+%l0] /* Write %l1 to stack space(%l2). */
182 add %l0, REGSIZE, %l0 /* Increment offset. */
183 sub %i1, REGSIZE, %i1 /* Decrement copy size. */
184 cmp %i1, 0
185 bgt .next
186 nop
187 .do_call:
188 call %i0 /* Call target. */
189 nop
190 or %o0, %g0, %i0
191 or %o1, %g0, %i1
192 jmpl %i7 + 8, %g0
193 restore