Mercurial > hg > truffle
annotate src/cpu/sparc/vm/args.cc @ 1661:01b172b8cd7c
Merge
author | never |
---|---|
date | Fri, 16 Jul 2010 08:29:42 -0700 |
parents | c18cbe5936b8 |
children |
rev | line source |
---|---|
0 | 1 /* |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
2 * Copyright (c) 2002, 2006, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
0
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 #include <stdio.h> | |
26 #include <string.h> | |
27 | |
28 static const int R_O0_num = 1000; | |
29 static const int R_I0_num = 2000; | |
30 static const int R_F0_num = 3000; | |
31 static const int R_F1_num = R_F0_num + 1; | |
32 static const int R_F2_num = R_F0_num + 2; | |
33 static const int STACK_num= 4000; | |
34 | |
35 static bool LP64 = false; | |
36 static bool LONGS_IN_ONE_ENTRY = false; | |
37 | |
38 static const int Op_RegI = 'I'; | |
39 static const int Op_RegP = 'P'; | |
40 static const int Op_RegF = 'F'; | |
41 static const int Op_RegD = 'D'; | |
42 static const int Op_RegL = 'L'; | |
43 static const int SPARC_ARGS_IN_REGS_NUM=6; | |
44 | |
45 static void print_reg( int reg ) { | |
46 if( reg == 0 ) | |
47 printf("__"); // halve's | |
48 else if( reg >= STACK_num && reg < STACK_num+100 ) | |
49 printf("S%d_",reg - STACK_num); | |
50 else if( reg >= R_F0_num && reg < R_F0_num+100 ) | |
51 printf("F%d_",reg - R_F0_num); | |
52 else if( reg >= R_O0_num && reg < R_O0_num+100 ) { | |
53 if( LONGS_IN_ONE_ENTRY ) { | |
54 reg -= R_O0_num; | |
55 printf("O%d",reg>>1); | |
56 printf(reg&1 ? "H" : "L"); | |
57 } else | |
58 printf("O%d_",reg - R_O0_num); | |
59 } else | |
60 printf("Wretched: %d\n", reg); | |
61 } | |
62 | |
63 static void print_convention( int *sig, const char *s, int length ) { | |
64 // Print it out | |
65 for( int i = 0; i < length; i++) { | |
66 if( sig[i] == 0 ) continue; // do not print 'halves' | |
67 print_reg( sig[i] & 0xFFFF ); | |
68 int reg = sig[i] >> 16; | |
69 if( reg ) { | |
70 printf(":"); | |
71 print_reg( reg ); | |
72 } else { | |
73 printf(" "); | |
74 } | |
75 printf(" "); | |
76 } | |
77 printf("\n"); | |
78 } | |
79 | |
80 static int INT_SCALE( int x ) { | |
81 return LONGS_IN_ONE_ENTRY ? (x<<1) : x; | |
82 } | |
83 | |
84 static void java_convention( int *sig, const char *s, int length ) { | |
85 if( LP64 && !LONGS_IN_ONE_ENTRY ) { | |
86 printf("LP64 and 2-reg longs not supported\n"); | |
87 return; | |
88 } | |
89 for( int i = 0; i < length; i++ ) | |
90 sig[i] = s[i]; // Reset sig array | |
91 bool is_outgoing = true; | |
92 | |
93 int int_base = (is_outgoing ? R_O0_num : R_I0_num); | |
94 | |
95 // Convention is to pack the first 6 int/oop args into the first 6 | |
96 // registers (I0-I5), extras spill to the stack. Then pack the first | |
97 // 32 float args into F0-F31, extras spill to the stack. Then pad | |
98 // all register sets to align. Then put longs and doubles into the | |
99 // same registers as they fit, else spill to the stack. | |
100 int int_reg_max = SPARC_ARGS_IN_REGS_NUM; | |
101 int flt_reg_max = 32; | |
102 | |
103 // Count int/oop and float args. See how many stack slots we'll need | |
104 // and where the longs & doubles will go. | |
105 int int_reg_cnt = 0; | |
106 int flt_reg_cnt = 0; | |
107 int stk_reg_pairs = 0; | |
108 for( int i = 0; i < length; i++) { | |
109 switch( sig[i] ) { | |
110 case Op_RegL: // Longs-in-1-reg compete with int args | |
111 if( LONGS_IN_ONE_ENTRY ) { | |
112 if( int_reg_cnt < int_reg_max ) int_reg_cnt++; | |
113 } | |
114 break; | |
115 case Op_RegP: | |
116 if( int_reg_cnt < int_reg_max ) int_reg_cnt++; | |
117 else if( !LP64 ) stk_reg_pairs++; | |
118 break; | |
119 case Op_RegI: | |
120 if( int_reg_cnt < int_reg_max ) int_reg_cnt++; | |
121 else stk_reg_pairs++; | |
122 break; | |
123 case Op_RegF: | |
124 if( flt_reg_cnt < flt_reg_max ) flt_reg_cnt++; | |
125 else stk_reg_pairs++; | |
126 break; | |
127 } | |
128 } | |
129 | |
130 // This is where the longs/doubles start on the stack. | |
131 stk_reg_pairs = (stk_reg_pairs+1) & ~1; // Round | |
132 | |
133 int int_reg_pairs = (int_reg_cnt+1) & ~1; // 32-bit 2-reg longs only | |
134 int flt_reg_pairs = (flt_reg_cnt+1) & ~1; | |
135 | |
136 int stk_reg = 0; | |
137 int int_reg = 0; | |
138 int flt_reg = 0; | |
139 | |
140 // Now do the signature layout | |
141 for( int i = 0; i < length; i++) { | |
142 int tmp = sig[i]; | |
143 if( tmp == Op_RegP ) | |
144 tmp = LP64 ? Op_RegL : Op_RegI; // Treat ptrs and ints or long accordingly | |
145 switch( tmp ) { | |
146 case Op_RegI: | |
147 // case Op_RegP: | |
148 if( int_reg < int_reg_max) tmp = INT_SCALE(int_reg++) + int_base; | |
149 else tmp = STACK_num + stk_reg++; | |
150 sig[i] = tmp; | |
151 break; | |
152 | |
153 case Op_RegL: | |
154 if( sig[i] != Op_RegP && sig[i+1] != 'h' ) { printf("expecting (h)alf, found %c\n", sig[i+1]); return; } | |
155 // case Op_RegP: | |
156 if( LONGS_IN_ONE_ENTRY ) { | |
157 if( int_reg < int_reg_max ) { | |
158 tmp = INT_SCALE(int_reg++) + int_base; | |
159 } else { | |
160 tmp = STACK_num + stk_reg_pairs; | |
161 stk_reg_pairs += 2; | |
162 } | |
163 } else { | |
164 if( int_reg_pairs < int_reg_max ) { | |
165 tmp = int_reg_pairs + int_base; | |
166 int_reg_pairs += 2; | |
167 } else { | |
168 tmp = STACK_num + stk_reg_pairs; | |
169 stk_reg_pairs += 2; | |
170 } | |
171 } | |
172 sig[i] = tmp | (tmp+1)<<16; // Smear to pair | |
173 break; | |
174 | |
175 case Op_RegF: | |
176 sig[i] = (flt_reg < flt_reg_max) ? (R_F0_num + flt_reg++) : STACK_num + stk_reg++; | |
177 break; | |
178 case Op_RegD: | |
179 if( sig[i+1] != 'h' ) { printf("expecting (h)alf, found %c\n", sig[i+1]); return; } | |
180 if( flt_reg_pairs < flt_reg_max ) { | |
181 tmp = R_F0_num + flt_reg_pairs; | |
182 flt_reg_pairs += 2; | |
183 } else { | |
184 tmp = STACK_num + stk_reg_pairs; | |
185 stk_reg_pairs += 2; | |
186 } | |
187 sig[i] = tmp | (tmp+1)<<16; // Smear to pair | |
188 break; | |
189 case 'h': sig[i] = 0; break; | |
190 default: | |
191 printf("Bad character: %c\n", sig[i] ); | |
192 return; | |
193 } | |
194 } | |
195 | |
196 printf("java "); | |
197 printf(LP64 ? "LP64 " : "LP32 "); | |
198 printf(LONGS_IN_ONE_ENTRY ? "long1: " : "long2: "); | |
199 print_convention(sig,s,length); | |
200 } | |
201 | |
202 static int int_stk_helper( int i ) { | |
203 if( i < 6 ) return R_O0_num + (LONGS_IN_ONE_ENTRY ? i<<1 : i); | |
204 else return STACK_num + (LP64 ? i<<1 : i); | |
205 } | |
206 | |
207 static void native_convention( int *sig, const char *s, int length ) { | |
208 if( LP64 && !LONGS_IN_ONE_ENTRY ) { | |
209 printf("LP64 and 2-reg longs not supported\n"); | |
210 return; | |
211 } | |
212 for( int i = 0; i < length; i++ ) | |
213 sig[i] = s[i]; // Reset sig array | |
214 | |
215 // The native convention is V8 if !LP64, which means the V8 convention is | |
216 // used both with and without LONGS_IN_ONE_ENTRY, an unfortunate split. The | |
217 // same actual machine registers are used, but they are named differently in | |
218 // the LONGS_IN_ONE_ENTRY mode. The LP64 convention is the V9 convention | |
219 // which is slightly more sane. | |
220 | |
221 if( LP64 ) { | |
222 // V9 convention: All things "as-if" on double-wide stack slots. | |
223 // Hoist any int/ptr/long's in the first 6 to int regs. | |
224 // Hoist any flt/dbl's in the first 16 dbl regs. | |
225 int j = 0; // Count of actual args, not HALVES | |
226 for( int i=0; i<length; i++, j++ ) { | |
227 int tmp; | |
228 switch( sig[i] ) { | |
229 case Op_RegI: | |
230 sig[i] = int_stk_helper( j ); | |
231 break; | |
232 case Op_RegL: | |
233 if( sig[i+1] != 'h' ) { printf("expecting (h)alf, found %c\n", sig[i+1]); return; } | |
234 case Op_RegP: | |
235 tmp = int_stk_helper( j ); | |
236 sig[i] = tmp | ((tmp+1) << 16); // Smear to pair | |
237 break; | |
238 case Op_RegF: // V9ism: floats go in ODD registers | |
239 sig[i] = ((j < 16) ? R_F1_num : (STACK_num + 1)) + (j<<1); | |
240 break; | |
241 case Op_RegD: // V9ism: doubles go in EVEN/ODD regs | |
242 tmp = ((j < 16) ? R_F0_num : STACK_num) + (j<<1); | |
243 sig[i] = tmp | ((tmp+1) << 16); // Smear to pair | |
244 break; | |
245 case 'h': sig[i] = 0; j--; break; // Do not count HALVES | |
246 default: | |
247 printf("Bad character: %c\n", sig[i] ); | |
248 return; | |
249 } | |
250 } | |
251 | |
252 } else { | |
253 // V8 convention: first 6 things in O-regs, rest on stack. | |
254 // Alignment is willy-nilly. | |
255 for( int i=0; i<length; i++ ) { | |
256 int tmp; | |
257 switch( sig[i] ) { | |
258 case Op_RegI: | |
259 case Op_RegP: | |
260 case Op_RegF: | |
261 sig[i] = int_stk_helper( i ); | |
262 break; | |
263 case Op_RegL: | |
264 case Op_RegD: | |
265 if( sig[i+1] != 'h' ) { printf("expecting (h)alf, found %c\n", sig[i+1]); return; } | |
266 tmp = int_stk_helper( i ); | |
267 sig[i] = tmp | (int_stk_helper( i+1 ) << 16); | |
268 break; | |
269 case 'h': sig[i] = 0; break; | |
270 default: | |
271 printf("Bad character: %c\n", sig[i] ); | |
272 return; | |
273 } | |
274 } | |
275 } | |
276 | |
277 printf("natv "); | |
278 printf(LP64 ? "LP64 " : "LP32 "); | |
279 printf(LONGS_IN_ONE_ENTRY ? "long1: " : "long2: "); | |
280 print_convention(sig,s,length); | |
281 } | |
282 | |
283 int main( int argc, char **argv ) { | |
284 | |
285 if( argc != 2 ) { | |
286 printf("Usage: args IPFLhDh... (Java argument string)\n"); | |
287 printf("Returns argument layout\n"); | |
288 return -1; | |
289 } | |
290 | |
291 const char *s = argv[1]; | |
292 int length = strlen(s); | |
293 int sig[1000]; | |
294 | |
295 LP64 = false; LONGS_IN_ONE_ENTRY = false; | |
296 java_convention( sig, s, length ); | |
297 LP64 = false; LONGS_IN_ONE_ENTRY = true; | |
298 java_convention( sig, s, length ); | |
299 LP64 = true ; LONGS_IN_ONE_ENTRY = true; | |
300 java_convention( sig, s, length ); | |
301 | |
302 LP64 = false; LONGS_IN_ONE_ENTRY = false; | |
303 native_convention( sig, s, length ); | |
304 LP64 = false; LONGS_IN_ONE_ENTRY = true; | |
305 native_convention( sig, s, length ); | |
306 LP64 = true ; LONGS_IN_ONE_ENTRY = true; | |
307 native_convention( sig, s, length ); | |
308 } | |
309 |