Mercurial > pub > dyncall > dyncall
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 |