0
|
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
|