Mercurial > hg > CbC > old > device
annotate mc-code-powerpc.c @ 382:832e1f6bba82
ARM wrote all code. Check compile error.
author | kono |
---|---|
date | Mon, 19 Jul 2004 16:30:11 +0900 (2004-07-19) |
parents | 91849fdeea60 |
children | 5b76a2bc1177 |
rev | line source |
---|---|
326 | 1 /* Micro-C Code Generation Part for Power PC (Mac OS X) */ |
89 | 2 /* $Id$ */ |
3 | |
327 | 4 #include <stdio.h> |
89 | 5 #include "mc.h" |
327 | 6 #include "mc-parse.h" |
93 | 7 #include "mc-code.h" |
89 | 8 #include "mc-codegen.h" |
9 | |
173 | 10 char *l_include_path[] = { |
11 "/usr/include/", | |
12 0 | |
13 }; | |
14 | |
324 | 15 // __builtin_expect(a,t) branch prediction |
16 | |
327 | 17 static |
18 char *init_src0 = "\ | |
313 | 19 #define __ppc__ 1\n\ |
20 #define __BIG_ENDIAN__ 1\n\ | |
21 #define __STDC__ 1\n\ | |
22 #define __builtin_va_list int\n\ | |
23 #define __builtin_va_start(ap,arg) ap=(((int)(&arg))+sizeof(arg))\n\ | |
24 #define __builtin_va_arg(ap,type) (*((type *)ap)++)\n\ | |
25 #define alloca __builtin_alloca\n\ | |
324 | 26 #define __builtin_expect(a,t) a\n\ |
313 | 27 "; |
28 | |
89 | 29 #define TEXT_EMIT_MODE 0 |
30 #define DATA_EMIT_MODE 1 | |
31 #define RODATA_EMIT_MODE 2 | |
32 | |
93 | 33 static void data_mode(char *name); |
263 | 34 static void text_mode(); |
221 | 35 static void ld_indexx(int byte, int n, int xreg,int reg,int sign); |
93 | 36 static void local_table(void); |
221 | 37 static void shift(char *op, int creg,int reg); |
119 | 38 static int struct_push(int e4,int t,int arg); |
93 | 39 |
341 | 40 |
221 | 41 static int creg; |
42 | |
89 | 43 static int output_mode = TEXT_EMIT_MODE; |
340 | 44 int data_alignment = 0; |
89 | 45 |
46 static int code_disp_label; | |
111 | 47 static int code_setup; |
116 | 48 static int r1_offset_label; |
49 static int lvar_offset_label; | |
313 | 50 static int max_func_arg_label; |
116 | 51 |
52 static int reg_save; | |
53 static int freg_save; | |
54 | |
205 | 55 static int freg,ireg,lreg; |
147 | 56 |
238 | 57 int code_lassop_p = 1; |
58 | |
245 | 59 #define SIZE_OF_INT 4 |
60 #define SIZE_OF_SHORT 2 | |
61 #define SIZE_OF_FLOAT 4 | |
62 #define SIZE_OF_DOUBLE 8 | |
63 #define SIZE_OF_LONGLONG 8 | |
64 #define ENDIAN 1 | |
65 | |
205 | 66 static int reg_sp; /* REGister Stack-Pointer */ |
67 static int reg_stack[MAX_MAX]; /* �ºݤΥ쥸�������ΰ� */ | |
138 | 68 |
69 /* floating point registers */ | |
70 | |
205 | 71 static int freg_sp; /* floating point REGister Stack-Pointer */ |
72 static int freg_stack[MAX_MAX]; /* �ºݤΥ쥸�������ΰ� */ | |
89 | 73 |
206 | 74 static int lreg_sp; /* longlong REGister Stack-Pointer */ |
75 static int lreg_stack[MAX_MAX]; /* �ºݤΥ쥸�������ΰ� */ | |
76 | |
119 | 77 #define REG_fp 1 |
78 #define REG_sp 30 | |
79 #define REG_VAR_BASE 29 | |
130 | 80 #define REG_VAR_MIN 18 |
119 | 81 #define MIN_TMP_REG 3 |
130 | 82 #define MAX_TMP_REG 11 |
119 | 83 |
84 #define PTRC_REG 3 | |
85 | |
86 #define FREG_VAR_BASE 31 | |
130 | 87 #define FREG_VAR_MIN 20 |
119 | 88 #define MIN_TMP_FREG 1 |
130 | 89 #define MAX_TMP_FREG 14 |
119 | 90 |
91 int MAX_REGISTER=30; /* PowerPC�Υ쥸������10�ĤޤǻȤ�*/ | |
122 | 92 int MAX_FREGISTER=31; |
119 | 93 #define REAL_MAX_REGISTER 32 /* PowerPC�Υ쥸������32�Ȥ�������*/ |
94 #define REAL_MAX_FREGISTER 32 /* PowerPC�Υ쥸������32�Ȥ�������*/ | |
207 | 95 #define REAL_MAX_LREGISTER 16 |
119 | 96 |
145 | 97 #define FREG_OFFSET REAL_MAX_REGISTER |
207 | 98 #define LREG_OFFSET (REAL_MAX_REGISTER+REAL_MAX_FREGISTER) |
99 | |
100 #define RET_REGISTER 3 | |
101 #define RET_FREGISTER (1+FREG_OFFSET) | |
222 | 102 #define RET_LREGISTER_H 3 /* high word */ |
207 | 103 #define RET_LREGISTER_L 4 /* low word */ |
104 #define RET_LREGISTER LREG_OFFSET | |
145 | 105 |
122 | 106 int MAX_INPUT_REGISTER_VAR = 11-MIN_TMP_REG; |
107 int MAX_CODE_INPUT_REGISTER_VAR = 11-MIN_TMP_REG; | |
108 int MAX_INPUT_DREGISTER_VAR = 14-MIN_TMP_FREG; | |
138 | 109 int MAX_INPUT_FREGISTER_VAR = 14-MIN_TMP_FREG; |
122 | 110 int MAX_CODE_INPUT_DREGISTER_VAR = 14-MIN_TMP_FREG; |
138 | 111 int MAX_CODE_INPUT_FREGISTER_VAR = 14-MIN_TMP_FREG; |
119 | 112 |
207 | 113 static int powerpc_regs[REAL_MAX_REGISTER+REAL_MAX_FREGISTER+ |
114 REAL_MAX_LREGISTER]; | |
115 static int regv_h0[REAL_MAX_LREGISTER]; | |
116 static int regv_l0[REAL_MAX_LREGISTER]; | |
211 | 117 #define regv_h(i) regv_h0[(i)-LREG_OFFSET] |
118 #define regv_l(i) regv_l0[(i)-LREG_OFFSET] | |
205 | 119 |
120 static int *regs = powerpc_regs; | |
119 | 121 |
207 | 122 #define CREG_REGISTER (MAX_TMP_REG) |
123 #define FREG_FREGISTER (MAX_TMP_FREG+FREG_OFFSET) | |
124 #define LREG_LREGISTER (MAX_TMP_REG+LREG_OFFSET) | |
206 | 125 |
126 | |
119 | 127 static int max_reg_var, max_freg_var; |
128 | |
129 static char *reg_name[] = { | |
130 "r0","r1","r2","r3","r4","r5","r6","r7","r8","r9", | |
131 "r10","r11","r12","r13","r14","r15","r16","r17","r18","r19", | |
132 "r20","r21","r22","r23","r24","r25","r26","r27","r28","r29", | |
145 | 133 "r30","r31", |
119 | 134 "f0","f1","f2","f3","f4","f5","f6","f7","f8","f9", |
135 "f10","f11","f12","f13","f14","f15","f16","f17","f18","f19", | |
136 "f20","f21","f22","f23","f24","f25","f26","f27","f28","f29", | |
137 "f30","f31" | |
138 }; | |
139 | |
260 | 140 #define round4(i) ((i+(SIZE_OF_INT-1))&~(SIZE_OF_INT-1)) |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
141 |
207 | 142 #define register_name(i) reg_name[i] |
143 #define fregister_name(i) reg_name[i] | |
144 #define lregister_name_low(i) reg_name[regv_l(i)] | |
210 | 145 #define lregister_name_high(i) reg_name[regv_h(i)] |
207 | 146 |
221 | 147 char *r(i) { return register_name(i); } |
148 char *f(i) { return fregister_name(i); } | |
149 char *ll(i) { return lregister_name_low(i); } | |
150 char *lh(i) { return lregister_name_high(i); } | |
151 | |
207 | 152 #define is_int_reg(i) (0<=i&&i<REAL_MAX_REGISTER) |
153 #define is_float_reg(i) (REAL_MAX_REGISTER<=i&&i<REAL_MAX_FREGISTER+REAL_MAX_REGISTER) | |
154 #define is_longlong_reg(i) (LREG_OFFSET<=i&&i<LREG_OFFSET+REAL_MAX_LREGISTER) | |
147 | 155 |
221 | 156 #define use_int(reg) if (reg==USE_CREG) reg=use_int0() |
157 static | |
158 int use_int0() { | |
159 int i = creg; | |
233 | 160 if (!i||!ireg||!is_int_reg(i)) { |
338 | 161 if (lreg) { if (regs[lreg]) free_register(lreg); lreg = 0; } |
205 | 162 if (!ireg) ireg = get_register(); |
222 | 163 // else if (ireg!=i) free_register(i); |
206 | 164 i = ireg; |
205 | 165 } |
207 | 166 if (!regs[i]) regs[i]=USING_REG; |
221 | 167 creg = i; |
147 | 168 return i; |
169 } | |
170 | |
222 | 171 #if LONGLONG_CODE |
172 #define use_longlong(reg) if (reg==USE_CREG) reg=use_longlong0() | |
173 | |
174 static | |
175 int use_longlong0() { | |
176 int i = creg; | |
177 if (!is_longlong_reg(i)) { | |
178 if (ireg) { free_register(ireg); ireg=0; } | |
226 | 179 if (!lreg||!regs[lreg]) lreg = get_lregister(); |
222 | 180 // else if (lreg!=i) free_register(i); |
181 i = lreg; | |
182 } | |
183 if (!regv_l(i)) regv_l(i) = get_register(); | |
184 if (!regv_h(i)) regv_h(i) = get_register(); | |
185 if (!regs[i]) regs[i]=USING_REG; | |
186 if (!regs[regv_l(i)]) regs[regv_l(i)]=USING_REG; | |
187 if (!regs[regv_h(i)]) regs[regv_h(i)]=USING_REG; | |
188 creg = i; | |
189 return i; | |
190 } | |
191 #endif | |
192 | |
193 | |
221 | 194 #if FLOAT_CODE |
195 #define use_float(d,reg) if (reg==USE_CREG) reg=d?use_double0():use_float0() | |
196 static | |
197 int use_float0() { | |
198 int i = creg; | |
207 | 199 if (!is_float_reg(i)) { |
200 if (lreg) { free_register(lreg); lreg = 0; } | |
201 if (!freg) freg = get_dregister(0); | |
208 | 202 else if (freg!=i) free_register(i); |
207 | 203 i = freg; |
204 } | |
205 if (!regs[i]) regs[i]=USING_REG; | |
221 | 206 creg = i; |
147 | 207 return i; |
208 } | |
221 | 209 static |
210 int use_double0() { | |
211 int i = creg; | |
207 | 212 if (!is_float_reg(i)) { |
213 if (lreg) { free_register(lreg); lreg = 0; } | |
214 if (!freg) freg = get_dregister(1); | |
208 | 215 else if (freg!=i) free_register(i); |
207 | 216 i = freg; |
217 } | |
218 if (!regs[i]) regs[i]=USING_REG; | |
221 | 219 creg = i; |
147 | 220 return i; |
221 } | |
221 | 222 #endif |
223 | |
195 | 224 |
225 #if FLOAT_CODE | |
119 | 226 static |
348 | 227 NMTBL float_zero = {"_float_zero",0,STATIC,FLOAT,0}; |
119 | 228 static |
348 | 229 NMTBL float_one = {"_float_one",0,STATIC,FLOAT,0}; |
119 | 230 |
231 | |
232 static char * fload(int d); | |
233 static int code_d1(double d); | |
234 static int code_d2(double d); | |
195 | 235 #endif |
206 | 236 #if LONGLONG_CODE |
237 static int code_l1(long long ll); | |
238 static int code_l2(long long ll); | |
239 #endif | |
195 | 240 |
119 | 241 static void code_save_stacks(); |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
242 static void code_save_input_registers(int dots); |
207 | 243 static void set_ireg(int,int); |
119 | 244 static void set_freg(int,int); |
195 | 245 static void set_lreg(int,int); |
287 | 246 static void jcond(int l, char cond); |
119 | 247 |
153 | 248 static int max_func_args; |
249 static int my_func_args; | |
119 | 250 #define ARG_LVAR_OFFSET 0x10000000 |
251 | |
126 | 252 /* |
89 | 253 |
97 | 254 r0 return value etc. |
255 r3-r10 input register | |
326 | 256 r22-r29 saved register variable (input register for code segment) |
89 | 257 r30 stack pointer |
258 r31 0 | |
259 r1 frame pointer | |
97 | 260 |
261 f0 return value etc. | |
262 f1-r8 input register | |
263 f24-f31 saved register variable | |
116 | 264 |
202 | 265 function call stack frame |
375 | 266 <-------r1_offset------------------------------> |
267 <------------lvar_offset0------> | |
268 <--lvar_offset--> | |
116 | 269 r+ +------------+---+---------------+----------+--------------+----+ - |
122 | 270 callee arg xx register save local caller arg xx |
245 | 271 reg_save disp max_func_args*SIZE_OF_INT |
119 | 272 lvar>0 lvar<0 lvar>0x1000 0000 |
127 | 273 |
274 code segment stack frame | |
275 | |
276 * goto��ƤӽФ����ؿ���r1 ! r1(goto����r1) | |
128 | 277 # * r30 <---r1_offset---------> r1 |
127 | 278 r+ +----------+--+----------+----------------+-----------+----------+----+ |
279 cousin arg xx reg save !callee arg !code local caller arg xx | |
280 r20-r29 lvar>0 lvar<0 lvar>0x1000 000 | |
281 f20-f31 <-my_func_args--><--disp-----><-max_func_arg-> | |
245 | 282 *SIZE_OF_INT *SIZE_OF_INT |
127 | 283 |
89 | 284 */ |
122 | 285 int arg_offset = 24; int arg_offset1 = 24; int disp_offset = -12; |
230 | 286 // #define func_disp_offset 60 |
287 #define func_disp_offset 68 | |
122 | 288 #define r1_offset func_disp_offset+12 |
121 | 289 int code_disp_offset = 0; int jump_offset = 0; |
290 #define CODE_LVAR l+code_disp_offset | |
129 | 291 #define CODE_CALLER_ARG (l-ARG_LVAR_OFFSET)+arg_offset1 |
121 | 292 #define FUNC_LVAR l+disp_offset |
293 #define CALLER_ARG (l-ARG_LVAR_OFFSET)+arg_offset1 | |
294 #define CALLEE_ARG l+arg_offset | |
89 | 295 |
116 | 296 void |
297 code_offset_set() | |
298 { | |
126 | 299 #if 0 |
121 | 300 int l; |
126 | 301 #endif |
245 | 302 int lvar_offsetv = -disp+max_func_args*SIZE_OF_INT+func_disp_offset; |
375 | 303 // int r1_offsetv = -disp+max_func_args*SIZE_OF_INT-reg_save+r1_offset; |
304 int r1_offsetv = lvar_offsetv-reg_save+12; | |
305 printf(".set L_%d,%d\n",lvar_offset_label,r1_offsetv-lvar_offsetv); | |
121 | 306 printf(".set L_%d,%d\n",r1_offset_label,r1_offsetv); |
313 | 307 if (max_func_arg_label) { |
308 printf(".set L_%d,%d\n",max_func_arg_label,max_func_args*SIZE_OF_INT+24); | |
309 max_func_arg_label = 0; | |
310 } | |
311 | |
375 | 312 printf("# reg_save %d\n",reg_save); |
126 | 313 #if 0 |
121 | 314 printf("# function %s\n",fnptr->nm); |
315 l = ARG_LVAR_OFFSET; | |
316 printf("# offset call0\t%d\n",CALLER_ARG); | |
245 | 317 l = ARG_LVAR_OFFSET+max_func_args*SIZE_OF_INT; |
318 printf("# offset calln\t%d %d\n",CALLER_ARG,max_func_args*SIZE_OF_INT); | |
121 | 319 l = disp; |
122 | 320 printf("# offset lvarn\t%d %d\n",FUNC_LVAR+lvar_offsetv,disp); |
121 | 321 l = 0; |
322 printf("# offset lvar0\t%d\n",FUNC_LVAR+lvar_offsetv); | |
323 l = -reg_save; | |
324 printf("# offset regs\t%d\n",FUNC_LVAR+lvar_offsetv); | |
325 printf("# offset r1off\t%d\n",r1_offsetv); | |
326 l = 0; | |
327 printf("# offset carg0\t%d\n",CALLEE_ARG+r1_offsetv); | |
328 l = my_func_args; | |
122 | 329 printf("# offset cargn\t%d %d\n",CALLEE_ARG+r1_offsetv,my_func_args); |
126 | 330 #endif |
116 | 331 } |
111 | 332 |
375 | 333 static int large_offset_reg; |
119 | 334 |
335 static void | |
375 | 336 lvar(int l) |
116 | 337 { |
375 | 338 char *rn; |
339 if (!large_offset_reg) { | |
340 if (fnptr->sc==CODE) { | |
341 if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ | |
342 printf("lo16(%d)(r1)\n",CODE_CALLER_ARG); | |
343 } else | |
344 printf("lo16(%d)(r30)\n",CODE_LVAR); | |
345 } else if (l<0) { /* local variable */ | |
346 printf("lo16(%d)(r30)\n",FUNC_LVAR); | |
347 } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ | |
348 printf("lo16(%d)(r1)\n",CALLER_ARG); | |
349 } else { /* callee's arguments */ | |
350 printf("lo16(%d+L_%d)(r30)\n",CALLEE_ARG,lvar_offset_label); | |
351 } | |
352 } else { | |
353 rn = register_name(large_offset_reg); | |
354 if (fnptr->sc==CODE) { | |
355 if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ | |
356 printf("lo16(%d)(%s)\n",CODE_CALLER_ARG,rn); | |
357 } else | |
358 printf("lo16(%d)(%s)\n",CODE_LVAR,rn); | |
359 } else if (l<0) { /* local variable */ | |
360 printf("lo16(%d)(%s)\n",FUNC_LVAR,rn); | |
361 } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ | |
362 printf("lo16(%d)(%s)\n",CALLER_ARG,rn); | |
363 } else { /* callee's arguments */ | |
364 printf("lo16(%d+L_%d)(%s)\n",CALLEE_ARG,lvar_offset_label,rn); | |
365 } | |
366 free_register(large_offset_reg); | |
116 | 367 } |
368 } | |
111 | 369 |
119 | 370 /* if size of local variables / input variables is more then 64k, |
371 lo16 does not work. We have to use ha16 also. But we can't know | |
372 the exact size in one path compile. We may safely use lvar16ha | |
326 | 373 if disp or max_func_args > 32k. Of course this is redundant for |
119 | 374 smaller offset. But who cares who use very large local variables? |
375 */ | |
96 | 376 |
375 | 377 #define LARGE_OFFSET(l) (l<-32000||l>32000) |
95 | 378 |
119 | 379 static void |
375 | 380 lvar_intro(int l) |
119 | 381 { |
375 | 382 char *rn; |
383 large_offset_reg=0; | |
119 | 384 if (fnptr->sc==CODE) { |
375 | 385 if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ |
386 if (LARGE_OFFSET(CODE_CALLER_ARG)) { | |
387 rn=register_name(large_offset_reg=get_register()); | |
388 printf("\taddis %s,r1,ha16(%d)\n",rn,CODE_CALLER_ARG); | |
389 } | |
390 } else { | |
391 if (LARGE_OFFSET(CODE_LVAR)) { | |
392 rn=register_name(large_offset_reg=get_register()); | |
393 printf("\taddis %s,r30,ha16(%d)\n",rn,CODE_LVAR); | |
394 } | |
395 } | |
119 | 396 } else if (l<0) { /* local variable */ |
375 | 397 if (LARGE_OFFSET(FUNC_LVAR)) { |
398 rn=register_name(large_offset_reg=get_register()); | |
399 printf("\taddis %s,r30,ha16(%d)\n",rn,FUNC_LVAR); | |
400 } | |
125 | 401 } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ |
375 | 402 if (LARGE_OFFSET(CALLER_ARG)) { |
403 rn=register_name(large_offset_reg=get_register()); | |
404 printf("\taddis %s,r1,ha16(%d)\n",rn,CALLER_ARG); | |
405 } | |
119 | 406 } else { /* callee's arguments */ |
375 | 407 if (LARGE_OFFSET(CALLEE_ARG)) { |
408 rn=register_name(large_offset_reg=get_register()); | |
409 printf("\taddis %s,r30,lo16(%d+L_%d)\n", | |
410 rn,CALLEE_ARG,lvar_offset_label); | |
411 } | |
119 | 412 } |
413 } | |
89 | 414 |
415 | |
119 | 416 void |
221 | 417 code_lvar(int e2,int reg) { |
418 use_int(reg); | |
119 | 419 lvar_intro(e2); |
221 | 420 printf("\tla %s,",register_name(reg)); |
119 | 421 lvar(e2); |
422 } | |
95 | 423 |
89 | 424 void |
425 code_init(void) | |
426 { | |
327 | 427 /* called only once */ |
428 | |
429 init_src = init_src0; | |
430 size_of_int = SIZE_OF_INT; | |
431 size_of_short = SIZE_OF_SHORT; | |
432 size_of_float = SIZE_OF_FLOAT; | |
433 size_of_double = SIZE_OF_DOUBLE; | |
434 size_of_longlong = SIZE_OF_LONGLONG; | |
435 endian = ENDIAN; | |
436 | |
207 | 437 regv_l(RET_LREGISTER) = RET_LREGISTER_L; |
438 regv_h(RET_LREGISTER) = RET_LREGISTER_H; | |
89 | 439 } |
440 | |
327 | 441 extern void |
442 emit_reinit() | |
443 { | |
444 /* called for each file */ | |
328 | 445 /* heap is initialized here, setup ptr cache free list */ |
446 init_ptr_cache(); | |
327 | 447 } |
448 | |
89 | 449 void |
450 gexpr_code_init(void){ | |
96 | 451 } |
452 | |
147 | 453 void |
454 code_gexpr(int e){ | |
207 | 455 // if (is_int_reg(creg) && creg!=ireg) error(-1); |
147 | 456 } |
457 | |
89 | 458 |
109 | 459 void |
137 | 460 code_arg_register(NMTBL *fnptr) |
109 | 461 { |
137 | 462 int args = fnptr->dsp; |
463 NMTBL *n; | |
464 int reg_var = 0; | |
465 int freg_var = 0; | |
466 int type; | |
467 int reg; | |
207 | 468 int i; |
137 | 469 int is_code0 = is_code(fnptr); |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
470 int dots; |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
471 |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
472 function_type(fnptr->ty,&dots); |
137 | 473 while (args) { |
474 /* process in reverse order */ | |
475 n = (NMTBL*)caddr(args); | |
476 type = n->ty; | |
477 if (scalar(type)) { | |
478 if ((reg = get_input_register_var(reg_var,n,is_code0))) { | |
479 n->sc = REGISTER; | |
207 | 480 n->dsp = cadr(reg); |
481 regs[n->dsp]= INPUT_REG; | |
137 | 482 reg_var++; |
245 | 483 cadddr(args)=SIZE_OF_INT; |
137 | 484 } |
138 | 485 } else if (type==FLOAT) { |
486 if ((reg = get_input_dregister_var(freg_var,n,is_code0,0))) { | |
487 n->sc = DREGISTER; | |
207 | 488 n->dsp = cadr(reg); |
489 regs[n->dsp]= INPUT_REG; | |
138 | 490 freg_var++; |
205 | 491 cadddr(args)=size(type); |
138 | 492 } |
493 } else if (type==DOUBLE) { | |
494 if ((reg = get_input_dregister_var(freg_var,n,is_code0,1))) { | |
137 | 495 n->sc = DREGISTER; |
207 | 496 n->dsp = cadr(reg); |
497 regs[n->dsp]= INPUT_REG; | |
137 | 498 freg_var++; |
205 | 499 cadddr(args)=size(type); |
500 } | |
501 } else if (type==LONGLONG||type==ULONGLONG) { | |
502 if ((reg = get_input_lregister_var(reg_var,n,is_code0))) { | |
503 n->sc = LREGISTER; | |
207 | 504 n->dsp = cadr(reg); |
505 regs[i=n->dsp]= INPUT_REG; | |
506 regs[regv_l(i)]= INPUT_REG; | |
507 regs[regv_h(i)]= INPUT_REG; | |
205 | 508 reg_var+=2; |
509 cadddr(args)=size(type); | |
137 | 510 } |
511 } | |
512 args = cadr(args); | |
513 } | |
126 | 514 if (is_function(fnptr)) |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
515 code_save_input_registers(dots); |
109 | 516 } |
517 | |
208 | 518 |
89 | 519 int |
210 | 520 get_register(void) |
89 | 521 { /* �Ȥ��Ƥ��ʤ��쥸������Ĵ�٤� */ |
219 | 522 int i,j,reg; |
96 | 523 for(i=MAX_TMP_REG;i>MIN_TMP_REG;i--) { |
102 | 524 if (regs[i]) continue; /* �Ȥ��Ƥ��� */ |
525 regs[i]=USING_REG; /* ���Υ쥸������Ȥ����Ȥ������ */ | |
207 | 526 return i; /* ���ξ���ɽ���ֹ���֤� */ |
102 | 527 } |
135 | 528 /* PTR_CACHE ��Ĥ֤� */ |
341 | 529 if ((i=last_ptr_cache())) { |
530 clear_ptr_cache_reg(i); | |
96 | 531 regs[i]=USING_REG; /* ���Υ쥸������Ȥ����Ȥ������ */ |
207 | 532 return i; /* ���ξ���ɽ���ֹ���֤� */ |
96 | 533 } |
534 /* search register stack */ | |
535 for(i=0;i<reg_sp;i++) { | |
120 | 536 if ((reg=reg_stack[i])>=0) { |
96 | 537 code_assign_lvar( |
245 | 538 (j=new_lvar(SIZE_OF_INT)),reg,0); |
219 | 539 reg_stack[i]= j-REG_LVAR_OFFSET; |
120 | 540 return reg; |
89 | 541 } |
542 } | |
206 | 543 #if LONGLONG_CODE |
544 /* search register stack */ | |
545 for(i=0;i<lreg_sp;i++) { | |
546 if ((reg=lreg_stack[i])>=0) { | |
219 | 547 code_lassign_lvar( |
245 | 548 (j=new_lvar(SIZE_OF_LONGLONG)),reg); |
219 | 549 lreg_stack[i]= j-REG_LVAR_OFFSET; |
206 | 550 free_register(reg); |
551 return get_register(); | |
552 } | |
553 } | |
554 #endif | |
130 | 555 for(i=0;i<REG_VAR_BASE-REG_VAR_MIN;i++) { |
556 reg =REG_VAR_BASE-i; | |
557 if (! regs[reg]) { /* �Ȥ��Ƥ��ʤ��ʤ� */ | |
558 regs[reg]=USING_REG; /* ���Υ쥸������Ȥ����Ȥ������ */ | |
559 if (i>max_reg_var) max_reg_var=i; | |
207 | 560 return reg; /* ���ξ���ɽ���ֹ���֤� */ |
130 | 561 } |
562 } | |
96 | 563 /* �����Ƥ����꤬�ʤ��ʤ顢���顼 (���ä���ï���ȤäƤ��?) */ |
136
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
135
diff
changeset
|
564 error(HPERR); return creg; |
89 | 565 } |
566 | |
210 | 567 #if 0 |
208 | 568 int |
569 get_register(void) | |
570 { | |
571 int i = get_register0(); | |
572 printf("# get_register %d\n",i); | |
573 return i; | |
574 } | |
210 | 575 #endif |
208 | 576 |
93 | 577 int |
578 pop_register(void) | |
579 { /* �쥸���������ͤ���Ф� */ | |
580 return reg_stack[--reg_sp]; | |
581 } | |
582 | |
195 | 583 #if FLOAT_CODE |
96 | 584 int |
210 | 585 get_dregister(int d) |
96 | 586 { /* �Ȥ��Ƥ��ʤ��쥸������Ĵ�٤� */ |
103 | 587 int i,reg; |
145 | 588 for(i=MAX_TMP_FREG+FREG_OFFSET;i>MIN_TMP_FREG+FREG_OFFSET;i--) { |
589 if (regs[i]) continue; /* �Ȥ��Ƥ��� */ | |
590 regs[i]=USING_REG; /* ���Υ쥸������Ȥ����Ȥ������ */ | |
207 | 591 return i; /* ���ξ���ɽ���ֹ���֤� */ |
102 | 592 } |
96 | 593 /* search register stack */ |
594 for(i=0;i<freg_sp;i++) { | |
103 | 595 if ((reg=freg_stack[i])>=0) { |
96 | 596 code_dassign_lvar( |
245 | 597 (freg_stack[i]=new_lvar(SIZE_OF_DOUBLE)),reg,1); |
96 | 598 freg_stack[i]= freg_stack[i]-REG_LVAR_OFFSET; |
120 | 599 return reg; |
96 | 600 } |
601 } | |
130 | 602 for(i=0;i<FREG_VAR_BASE-REG_VAR_MIN;i++) { |
145 | 603 reg =FREG_VAR_BASE-i+FREG_OFFSET; |
604 if (! regs[reg]) { /* �Ȥ��Ƥ��ʤ��ʤ� */ | |
605 regs[reg]=USING_REG; /* ���Υ쥸������Ȥ����Ȥ������ */ | |
130 | 606 if (i>max_freg_var) max_freg_var=i; |
207 | 607 return reg; /* ���ξ���ɽ���ֹ���֤� */ |
130 | 608 } |
609 } | |
96 | 610 /* �����Ƥ����꤬�ʤ��ʤ顢���顼 (���ä���ï���ȤäƤ��?) */ |
98 | 611 error(REG_ERR); return freg; |
96 | 612 } |
613 | |
210 | 614 #if 0 |
208 | 615 int |
616 get_dregister(int d) | |
617 { | |
618 int i = get_dregister0(d); | |
619 printf("# get_dregister %d\n",i); | |
620 return i; | |
621 } | |
210 | 622 #endif |
208 | 623 |
96 | 624 int |
97 | 625 pop_fregister(void) |
96 | 626 { /* �쥸���������ͤ���Ф� */ |
627 return freg_stack[--freg_sp]; | |
628 } | |
195 | 629 #endif |
630 | |
631 int | |
207 | 632 get_lregister0() |
633 { | |
634 int i; | |
635 for(i=LREG_OFFSET+1;i<REAL_MAX_LREGISTER+LREG_OFFSET;i++) { | |
636 if (regs[i]==0) { | |
210 | 637 // printf("# get_lregister %d\n",i); |
207 | 638 return i; |
639 } | |
640 } | |
641 return -1; | |
642 } | |
643 | |
644 int | |
205 | 645 get_lregister() |
646 { | |
207 | 647 int h,l,i; |
648 i = get_lregister0(); | |
649 if (i==-1) return -1; | |
220 | 650 h = get_register(); |
651 if (h==-1) return -1; | |
652 regv_h(i) = h; | |
653 l = get_register(); | |
654 if (l==-1) { free_register(h); return -1; } | |
655 regv_l(i) = l; | |
656 regs[i]=USING_REG; | |
657 return i; | |
205 | 658 } |
659 | |
660 int | |
195 | 661 get_lregister_var(NMTBL *n) |
662 { | |
207 | 663 int i,j,ll; |
206 | 664 int max_reg_var_save=max_reg_var; |
207 | 665 ll = get_lregister0(); |
255 | 666 if (ll==-1) goto not_found; |
207 | 667 if (regs[ll]==0) { |
668 for(i=0;i<REG_VAR_BASE-REG_VAR_MIN;i++) { | |
669 if (! regs[REG_VAR_BASE-i]) { /* �Ȥ��Ƥ��ʤ��ʤ� */ | |
670 /* ���Υ쥸������Ȥ����Ȥ������ */ | |
671 regs[REG_VAR_BASE-i]=USING_REG; | |
672 if (i>max_reg_var) max_reg_var=i; | |
673 for(j=0;j<REG_VAR_BASE-REG_VAR_MIN;j++) { | |
674 if (! regs[REG_VAR_BASE-j]) { | |
675 /* �Ȥ��Ƥ��ʤ��ʤ� */ | |
676 /* ���Υ쥸������Ȥ����Ȥ������ */ | |
677 regs[REG_VAR_BASE-j]=USING_REG; | |
678 if (j>max_reg_var) max_reg_var=j; | |
679 /* ���ξ���ɽ���ֹ���֤� */ | |
228 | 680 regs[ll]=USING_REG; |
207 | 681 regv_l(ll) = REG_VAR_BASE-j; |
682 regv_h(ll) = REG_VAR_BASE-i; | |
683 return list3(LREGISTER,ll,(int)n); | |
684 } | |
206 | 685 } |
207 | 686 /* �ҤȤĤ����ʤ��ä� */ |
687 regs[REG_VAR_BASE-i]=0; | |
688 max_reg_var=max_reg_var_save; | |
689 goto not_found; | |
206 | 690 } |
691 } | |
692 } | |
207 | 693 not_found: |
245 | 694 return list2(LVAR,new_lvar(SIZE_OF_LONGLONG)); |
195 | 695 } |
96 | 696 |
93 | 697 void |
698 emit_pop_free(int xreg) | |
699 { | |
103 | 700 if (xreg>=0) |
701 free_register(xreg); | |
93 | 702 } |
703 | |
211 | 704 void |
705 | |
89 | 706 free_register(int i) { /* ����ʤ��ʤä��쥸�������� */ |
210 | 707 // printf("# free_register %d\n",i); |
207 | 708 regs[i]=0; |
709 if (is_longlong_reg(i)) { | |
710 regs[regv_l(i)]=0; | |
711 regs[regv_h(i)]=0; | |
226 | 712 //regv_l(i)=0; |
713 //regv_h(i)=0; | |
206 | 714 } |
96 | 715 } |
716 | |
341 | 717 extern void |
718 use_ptr_cache(int r) | |
719 { | |
720 regs[r]=PTRC_REG; | |
721 } | |
722 | |
89 | 723 int |
138 | 724 get_input_dregister_var(int i,NMTBL *n,int is_code,int d) |
99 | 725 { |
126 | 726 if (is_code) { |
148 | 727 if(!(i<FREG_VAR_BASE-FREG_VAR_MIN)) return 0; |
728 i = FREG_VAR_BASE-i+FREG_OFFSET; | |
126 | 729 } else { |
135 | 730 if (i<0||i>=MAX_INPUT_DREGISTER_VAR) return 0; |
145 | 731 i = i+MIN_TMP_FREG+FREG_OFFSET; |
126 | 732 } |
207 | 733 return list3(DREGISTER,i,(int)n); |
205 | 734 } |
735 | |
736 int | |
737 get_input_lregister_var(int i,NMTBL *n,int is_code) | |
738 { | |
207 | 739 int ll; |
740 ll = get_lregister0(); | |
741 if (i!=-1) { | |
742 if (is_code) { | |
227 | 743 if(!(i<REG_VAR_BASE-REG_VAR_MIN)) return 0; |
207 | 744 i = REG_VAR_BASE-i; |
745 } else { | |
227 | 746 if (i<0||i>=MAX_INPUT_REGISTER_VAR) return 0; |
207 | 747 i = i+MIN_TMP_REG; |
748 } | |
222 | 749 regv_h(ll)=i; |
750 regv_l(ll)=i+1; | |
207 | 751 } else { error(-1); ll=LREG_OFFSET+2; } |
752 return list3(LREGISTER,ll,(int)n); | |
99 | 753 } |
754 | |
755 int | |
126 | 756 get_input_register_var(int i,NMTBL *n,int is_code) |
99 | 757 { |
126 | 758 if (is_code) { |
131 | 759 if(!(i<REG_VAR_BASE-REG_VAR_MIN)) return 0; |
126 | 760 i = REG_VAR_BASE-i; |
761 } else { | |
135 | 762 if (i<0||i>=MAX_INPUT_REGISTER_VAR) return 0; |
763 i = i+MIN_TMP_REG; | |
764 } | |
207 | 765 return list3(REGISTER,i,(int)n); |
135 | 766 } |
767 | |
145 | 768 /* double register case? */ |
769 | |
135 | 770 int |
771 get_input_register_var_1(int i,NMTBL *n,int is_code) | |
772 { | |
773 if (is_code) { | |
774 if(!(i<REG_VAR_BASE-REG_VAR_MIN)) return 0; | |
775 i = REG_VAR_BASE-i; | |
776 } else { | |
777 if (i<0||i>=MAX_INPUT_REGISTER_VAR+1) return 0; | |
126 | 778 i = i+MIN_TMP_REG; |
779 } | |
207 | 780 return list3(REGISTER,i,(int)n); |
99 | 781 } |
782 | |
783 int | |
137 | 784 free_register_count(int d) |
103 | 785 { |
786 int i,count,fcount; | |
787 fcount = count = 0; | |
788 for(i=0;i<MAX_REGISTER;i++) { | |
205 | 789 if (! regs[i]) count++; |
103 | 790 } |
791 for(i=0;i<MAX_FREGISTER;i++) { | |
205 | 792 if (! regs[i+FREG_OFFSET]) fcount++; |
103 | 793 } |
137 | 794 printf("# free reg %d freg %d\n",count,fcount); |
795 return d?fcount:count; | |
103 | 796 } |
797 | |
205 | 798 #if 0 |
799 static int | |
89 | 800 register_full(void) |
801 { | |
802 int i; | |
803 for(i=0;i<MAX_REGISTER;i++) { | |
804 if (! regs[i]) { | |
805 return 0; | |
806 } | |
807 } | |
808 return 1; | |
809 } | |
205 | 810 #endif |
89 | 811 |
812 void | |
813 free_all_register(void) | |
814 { | |
815 int i; | |
210 | 816 // printf("# free_all register\n"); |
206 | 817 #if LONGLONG_CODE |
226 | 818 for(i=0;i<REAL_MAX_LREGISTER;i++) { |
819 regs[i+LREG_OFFSET]=0; | |
820 regv_l(i+LREG_OFFSET) = 0; | |
821 regv_h(i+LREG_OFFSET) = 0; | |
822 } | |
206 | 823 lreg = 0; |
222 | 824 // set_lreg(LREG_LREGISTER,0); |
206 | 825 #endif |
205 | 826 for(i=0;i<MAX_REGISTER;i++) { regs[i]=0; } |
827 for(i=0;i<MAX_FREGISTER;i++) { regs[i+FREG_OFFSET]=0; } | |
195 | 828 #if FLOAT_CODE |
138 | 829 freg = get_dregister(1); |
195 | 830 set_freg(FREG_FREGISTER,0); |
831 #endif | |
832 ireg = creg = get_register(); | |
207 | 833 set_ireg(CREG_REGISTER,0); |
89 | 834 return; |
835 } | |
836 | |
345 | 837 extern int |
838 code_register_overlap(int s,int t) | |
839 { | |
840 switch(car(s)) { | |
841 case REGISTER: | |
842 switch(car(t)) { | |
843 case DREGISTER: case FREGISTER: break; | |
844 case REGISTER: | |
845 if(cadr(s)==cadr(t)) return 1; | |
846 break; | |
847 case LREGISTER: | |
848 if(cadr(s)==regv_l(cadr(t))) return 1; | |
849 if(cadr(s)==regv_h(cadr(t))) return 1; | |
850 break; | |
851 } | |
852 break; | |
853 case DREGISTER: | |
854 case FREGISTER: | |
855 switch(car(t)) { | |
856 case REGISTER: case LREGISTER: break; | |
857 case DREGISTER: case FREGISTER: | |
858 if(cadr(s)==cadr(t)) return 1; | |
859 break; | |
860 } | |
861 break; | |
862 case LREGISTER: | |
863 switch(car(t)) { | |
864 case DREGISTER: case FREGISTER: break; | |
865 case REGISTER: | |
866 if(cadr(t)==regv_l(cadr(s))) return 1; | |
867 if(cadr(t)==regv_h(cadr(s))) return 1; | |
868 break; | |
869 case LREGISTER: | |
870 if(regv_l(cadr(t))==regv_l(cadr(s))) return 1; | |
871 if(regv_l(cadr(t))==regv_h(cadr(s))) return 1; | |
872 if(regv_h(cadr(t))==regv_l(cadr(s))) return 1; | |
873 if(regv_h(cadr(t))==regv_h(cadr(s))) return 1; | |
874 break; | |
875 } | |
876 break; | |
877 } | |
878 return 0; | |
879 } | |
880 | |
89 | 881 void |
882 register_usage(char *s) | |
883 { | |
207 | 884 #if 1 |
273 | 885 int i,j; |
886 #endif | |
887 #define USAGE_MAX 4 | |
888 if (chk) return; | |
889 if (!lsrc) return; | |
890 printf("# %d: %s:",lineno,s); | |
891 if (ireg) printf(" creg=%s",register_name(ireg)); | |
892 if (freg) printf(" freg=%s",fregister_name(freg)); | |
893 if (lreg) printf(" lreg=%s,%s",lregister_name_high(lreg), | |
894 lregister_name_low(lreg)); | |
895 #if 1 | |
896 for(j=0,i=0;i<MAX_REGISTER;i++) if (regs[i]) j++; | |
897 if (j>USAGE_MAX) { | |
898 printf("\n# regs:"); | |
899 for(i=0;i<MAX_REGISTER;i++) { printf("%d",regs[i]); } | |
900 } | |
901 if (reg_sp>0) { | |
902 printf(" stack "); | |
903 for(i=reg_sp;i>0;i--) { | |
904 if(reg_stack[i-1]>=0) { | |
905 printf(" %s",register_name(reg_stack[i-1])); | |
906 } else | |
907 printf(",%d",reg_stack[i-1]); | |
908 } | |
909 } | |
910 for(j=0,i=0;i<MAX_FREGISTER;i++) if (regs[i+FREG_OFFSET]) j++; | |
911 if (j>USAGE_MAX) { | |
912 printf("\n# freg:"); | |
913 for(i=0;i<MAX_FREGISTER;i++) { printf("%d",regs[i+FREG_OFFSET]); } | |
914 } | |
915 if (freg_sp>0) { | |
916 printf(" fstack "); | |
917 for(i=freg_sp;i>0;i--) { | |
918 if(freg_stack[i-1]>=0) { | |
919 printf(" %s",fregister_name(freg_stack[i-1])); | |
920 } else | |
921 printf(",%d",freg_stack[i-1]); | |
922 } | |
923 } | |
924 | |
925 for(j=0,i=0;i<REAL_MAX_LREGISTER;i++) if (regs[i+LREG_OFFSET]) j++; | |
926 if (j>USAGE_MAX) { | |
927 printf("\n# lreg:"); | |
928 for(i=0;i<REAL_MAX_LREGISTER;i++) { printf("%d",regs[i+LREG_OFFSET]); } | |
929 } | |
930 if (lreg_sp>0) { | |
931 printf(" lstack "); | |
932 for(i=lreg_sp;i>0;i--) { | |
933 if(lreg_stack[i-1]>=0) { | |
934 printf(" %s",lregister_name_high(lreg_stack[i-1])); | |
935 printf(",%s",lregister_name_low(lreg_stack[i-1])); | |
936 } else | |
937 printf(",%d",lreg_stack[i-1]); | |
938 } | |
939 } | |
940 #endif | |
941 printf("\n"); | |
942 } | |
943 | |
944 #if 0 | |
945 void | |
946 register_usage(char *s) | |
947 { | |
948 #if 1 | |
89 | 949 int i; |
126 | 950 #endif |
89 | 951 if (chk) return; |
109 | 952 if (!lsrc) return; |
89 | 953 printf("# %d: %s:",lineno,s); |
206 | 954 if (ireg) printf(" creg=%s",register_name(ireg)); |
955 if (freg) printf(" freg=%s",fregister_name(freg)); | |
956 if (lreg) printf(" lreg=%s,%s",lregister_name_high(lreg), | |
957 lregister_name_low(lreg)); | |
207 | 958 #if 1 |
126 | 959 printf("\n# regs:"); |
210 | 960 for(i=0;i<MAX_REGISTER;i++) { printf("%d",regs[i]); } |
207 | 961 printf(" stack "); |
962 for(i=reg_sp;i>0;i--) { | |
963 if(reg_stack[i-1]>=0) | |
964 printf(" %s",register_name(reg_stack[i])); | |
965 } | |
101 | 966 printf("\n# freg:"); |
210 | 967 for(i=0;i<MAX_FREGISTER;i++) { printf("%d",regs[i+FREG_OFFSET]); } |
207 | 968 printf(" stack "); |
969 for(i=freg_sp;i>0;i--) { | |
970 if(freg_stack[i-1]>=0) | |
971 printf(" %s",fregister_name(freg_stack[i])); | |
972 } | |
973 printf("\n# lreg:"); | |
210 | 974 for(i=0;i<REAL_MAX_LREGISTER;i++) { printf("%d",regs[i+LREG_OFFSET]); } |
207 | 975 printf(" stack "); |
976 for(i=lreg_sp;i>0;i--) { | |
977 if(lreg_stack[i-1]>=0) | |
978 printf(" %s",lregister_name_high(lreg_stack[i])); | |
979 printf(",%s",lregister_name_low(lreg_stack[i])); | |
89 | 980 } |
981 #endif | |
982 printf("\n"); | |
983 } | |
273 | 984 #endif |
89 | 985 |
211 | 986 void |
987 | |
89 | 988 gexpr_init(void) |
989 { | |
990 while(reg_sp > 0) { | |
292 | 991 error(-1); |
89 | 992 free_register(reg_stack[--reg_sp]); |
993 } | |
148 | 994 while(freg_sp > 0) { |
292 | 995 error(-1); |
148 | 996 free_register(freg_stack[--freg_sp]); |
997 } | |
206 | 998 while(lreg_sp > 0) { |
292 | 999 error(-1); |
206 | 1000 free_register(lreg_stack[--lreg_sp]); |
1001 } | |
221 | 1002 use_int0(); |
89 | 1003 text_mode(); |
1004 gexpr_code_init(); | |
1005 register_usage("gexpr_init"); | |
1006 } | |
1007 | |
1008 | |
211 | 1009 void |
1010 | |
89 | 1011 emit_init(void) |
1012 { | |
327 | 1013 /* called before each declaration */ |
1014 | |
89 | 1015 free_all_register(); |
110 | 1016 max_reg_var=-1; max_freg_var=-1; |
89 | 1017 reg_sp = 0; |
123 | 1018 freg_sp = 0; |
89 | 1019 text_mode(); |
1020 } | |
1021 | |
97 | 1022 |
89 | 1023 int |
105 | 1024 get_register_var(NMTBL *n) |
89 | 1025 { |
1026 int i; | |
99 | 1027 for(i=0;i<REG_VAR_BASE-REG_VAR_MIN;i++) { |
137 | 1028 if (! regs[REG_VAR_BASE-i]) { /* �Ȥ��Ƥ��ʤ��ʤ� */ |
1029 /* ���Υ쥸������Ȥ����Ȥ������ */ | |
1030 regs[REG_VAR_BASE-i]=USING_REG; | |
97 | 1031 if (i>max_reg_var) max_reg_var=i; |
122 | 1032 /* ���ξ���ɽ���ֹ���֤� */ |
207 | 1033 return list3(REGISTER,REG_VAR_BASE-i,(int)n); |
137 | 1034 } |
96 | 1035 } |
245 | 1036 return list2(LVAR,new_lvar(SIZE_OF_INT)); |
96 | 1037 } |
1038 | |
1039 int | |
138 | 1040 get_dregister_var(NMTBL *n,int d) |
96 | 1041 { |
1042 int i; | |
148 | 1043 for(i=0;i<FREG_VAR_BASE-FREG_VAR_MIN;i++) { |
145 | 1044 if (! regs[FREG_VAR_BASE-i+FREG_OFFSET]) { /* �Ȥ��Ƥ��ʤ��ʤ� */ |
1045 regs[FREG_VAR_BASE-i+FREG_OFFSET]=USING_REG; /*���Υ쥸������Ȥ����Ȥ������*/ | |
97 | 1046 if (i>max_freg_var) max_freg_var=i; |
122 | 1047 /* ���ξ���ɽ���ֹ���֤� */ |
206 | 1048 return list3(DREGISTER, |
207 | 1049 FREG_VAR_BASE-i+FREG_OFFSET,(int)n); |
89 | 1050 } |
1051 } | |
245 | 1052 return list2(LVAR,new_lvar(SIZE_OF_DOUBLE)); |
89 | 1053 } |
1054 | |
211 | 1055 void |
1056 | |
107 | 1057 emit_push() |
89 | 1058 { |
1059 int new_reg; | |
221 | 1060 if (!is_int_reg(creg)) error(-1); |
102 | 1061 if (reg_sp>MAX_MAX) error(-1); |
221 | 1062 new_reg = get_register(); /* ���Ф˼��� */ |
97 | 1063 reg_stack[reg_sp++] = creg; /* push ���뤫���˥쥸������Ȥ� */ |
147 | 1064 ireg = creg = new_reg; |
89 | 1065 } |
1066 | |
1067 int | |
93 | 1068 emit_pop(int type) |
89 | 1069 { |
112 | 1070 int xreg,reg; |
97 | 1071 xreg=pop_register(); |
1072 if (xreg<= -REG_LVAR_OFFSET) { | |
112 | 1073 reg = get_register(); |
119 | 1074 code_rlvar(REG_LVAR_OFFSET+xreg,reg); |
117 | 1075 free_lvar(REG_LVAR_OFFSET+xreg); |
112 | 1076 xreg = reg; |
97 | 1077 } |
89 | 1078 return xreg; |
1079 } | |
1080 | |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
1081 static int code_base; |
89 | 1082 |
341 | 1083 extern void |
1084 code_ptr_cache_def(int r,NMTBL *nptr) | |
89 | 1085 { |
341 | 1086 char *rrn = register_name(r); |
109 | 1087 if (nptr->sc==STATIC) { |
1088 printf("\taddis %s,r31,ha16(_%s-L_%d)\n", | |
1089 rrn,nptr->nm,code_base); | |
1090 printf("\tla %s,lo16(_%s-L_%d)(%s)\n", | |
1091 rrn,nptr->nm,code_base,rrn); | |
1092 } else { | |
1093 printf("\taddis %s,r31,ha16(L_%s$non_lazy_ptr-L_%d)\n", | |
1094 rrn,nptr->nm,code_base); | |
1095 printf("\tlwz %s,lo16(L_%s$non_lazy_ptr-L_%d)(%s)\n", | |
1096 rrn,nptr->nm,code_base,rrn); | |
1097 } | |
89 | 1098 } |
1099 | |
245 | 1100 static char *cload(int sz) { return sz==1?"lbz":sz==SIZE_OF_SHORT?"lhz":"lwz"; } |
1101 static char *cstore(int sz) { return sz==1?"stb":sz==SIZE_OF_SHORT?"sth":"stw"; } | |
230 | 1102 |
1103 static void | |
1104 cext(int sign,int sz,int reg) | |
1105 { | |
1106 char *crn = register_name(reg); | |
1107 if (sign) { | |
1108 if (sz==1) | |
1109 printf("\textsb %s,%s\n",crn,crn); | |
245 | 1110 else if (sz==SIZE_OF_SHORT) |
230 | 1111 printf("\textsh %s,%s\n",crn,crn); |
1112 } else { | |
1113 if (sz==1) | |
1114 printf("\trlwinm %s,%s,0,0xff\n",crn,crn); | |
245 | 1115 else if (sz==SIZE_OF_SHORT) |
230 | 1116 printf("\trlwinm %s,%s,0,0xffff\n",crn,crn); |
1117 } | |
1118 } | |
1119 | |
168 | 1120 |
89 | 1121 void |
92 | 1122 code_label(int labelno) |
1123 { | |
1124 clear_ptr_cache(); | |
102 | 1125 printf("L_%d:\n",labelno); |
92 | 1126 } |
1127 | |
367 | 1128 static void |
1129 code_add(int reg,int offset,int r) | |
1130 { | |
1131 char *crn = register_name(reg); | |
1132 char *rrn = register_name(r); | |
1133 if (offset==0) { | |
1134 if(r!=reg) | |
1135 printf("\tmr %s,%s\n",crn,rrn); | |
375 | 1136 } else if (LARGE_OFFSET(offset)) { |
367 | 1137 printf("\tla %s,ha16(%d)(%s)\n",crn,offset,rrn); |
1138 printf("\taddi %s,%s,lo16(%d)\n",crn,crn,offset); | |
1139 } else | |
1140 printf("\taddi %s,%s,%d\n",crn,rrn,offset); | |
1141 } | |
1142 | |
1143 static void | |
1144 code_ld(char *ld,int reg,int offset,int r) | |
1145 { | |
1146 char *crn = register_name(reg); | |
1147 char *rrn = register_name(r); | |
375 | 1148 if (LARGE_OFFSET(offset)) { |
367 | 1149 printf("\tla %s,ha16(%d)(%s)\n",crn,offset,rrn); |
1150 printf("\t%s %s,%s,lo16(%d)\n",ld,crn,crn,offset); | |
1151 } else | |
1152 printf("\t%s %s,%d(%s)\n",ld,crn,offset,rrn); | |
1153 } | |
1154 | |
1155 static void | |
1156 code_ldf(char *ld,char *crn,int offset,int r) | |
1157 { | |
1158 char *rrn = register_name(r); | |
1159 int reg; | |
1160 char *lrn; | |
1161 if (offset<-32768||32767<offset) { | |
1162 lrn = register_name(reg = get_register()); | |
1163 printf("\tla %s,ha16(%d)(%s)\n",lrn,offset,rrn); | |
1164 printf("\t%s %s,%s,lo16(%d)\n",ld,crn,lrn,offset); | |
1165 free_register(reg); | |
1166 } else | |
1167 printf("\t%s %s,%d(%s)\n",ld,crn,offset,rrn); | |
1168 } | |
1169 | |
92 | 1170 void |
221 | 1171 code_gvar(int e1,int reg) { |
1172 use_int(reg); | |
367 | 1173 code_add(reg,cadr(e1),get_ptr_cache((NMTBL*)caddr(e1))); |
89 | 1174 return; |
1175 } | |
1176 | |
1177 void | |
221 | 1178 code_rgvar(int e1,int reg) { |
1179 use_int(reg); | |
367 | 1180 code_ld("lwz",reg,cadr(e1),get_ptr_cache((NMTBL*)caddr(e1))); |
89 | 1181 } |
1182 | |
1183 void | |
221 | 1184 code_crgvar(int e1,int reg,int sign,int sz){ |
1185 use_int(reg); | |
367 | 1186 code_ld(cload(sz),reg,cadr(e1),get_ptr_cache((NMTBL*)caddr(e1))); |
230 | 1187 cext(sign,sz,reg); |
89 | 1188 } |
1189 | |
165 | 1190 |
1191 | |
89 | 1192 void |
221 | 1193 code_register(int e2,int reg) { |
1194 use_int(reg); | |
1195 if (reg!=e2) | |
1196 printf("\tmr %s,%s\n",register_name(reg),register_name(e2)); | |
89 | 1197 } |
1198 | |
353 | 1199 extern void |
1200 code_i2c(int reg) | |
1201 { | |
1202 use_int(reg); | |
1203 cext(1,1,reg); | |
1204 } | |
1205 | |
1206 extern void | |
1207 code_i2s(int reg) | |
1208 { | |
1209 use_int(reg); | |
1210 cext(1,SIZE_OF_SHORT,reg); | |
1211 } | |
1212 | |
1213 extern void | |
1214 code_u2uc(int reg) | |
1215 { | |
1216 use_int(reg); | |
1217 cext(0,1,reg); | |
1218 } | |
1219 | |
1220 extern void | |
1221 code_u2us(int reg) | |
1222 { | |
1223 use_int(reg); | |
1224 cext(0,SIZE_OF_SHORT,reg); | |
1225 } | |
89 | 1226 |
1227 void | |
95 | 1228 code_rlvar(int e2,int reg) { |
221 | 1229 use_int(reg); |
119 | 1230 lvar_intro(e2); |
1231 printf("\tlwz %s,",register_name(reg)); | |
1232 lvar(e2); | |
89 | 1233 } |
1234 | |
1235 void | |
165 | 1236 code_crlvar(int e2,int reg,int sign,int sz) { |
221 | 1237 use_int(reg); |
119 | 1238 lvar_intro(e2); |
165 | 1239 printf("\t%s %s,",cload(sz),register_name(reg)); |
119 | 1240 lvar(e2); |
230 | 1241 cext(sign,sz,reg); |
89 | 1242 } |
1243 | |
1244 void | |
221 | 1245 code_fname(NMTBL *n,int reg) { |
89 | 1246 int r; |
221 | 1247 use_int(reg); |
109 | 1248 r = get_ptr_cache(n); |
221 | 1249 if(r!=reg) |
1250 printf("\tmr %s,%s\n",register_name(reg),register_name(r)); | |
89 | 1251 return; |
1252 } | |
1253 | |
363 | 1254 void |
1255 code_label_value(int label,int reg) { | |
1256 char *crn; | |
1257 use_int(reg); | |
1258 crn = register_name(reg); | |
1259 printf("\taddis %s,r31,ha16(L_%d-L_%d)\n",crn,label,code_base); | |
1260 printf("\tla %s,lo16(L_%d-L_%d)(%s)\n",crn,label,code_base,crn); | |
1261 return; | |
1262 } | |
89 | 1263 |
1264 void | |
221 | 1265 code_const(int e2,int reg) { |
1266 char *crn; | |
1267 use_int(reg); | |
1268 crn = register_name(reg); | |
371 | 1269 // printf("# 0x%08x\n",e2); |
89 | 1270 if (-32768<e2&&e2<32768) |
1271 printf("\tli %s,%d\n",crn,e2); | |
1272 else { | |
1273 printf("\tlis %s,ha16(%d)\n",crn,e2); | |
1274 printf("\taddi %s,%s,lo16(%d)\n",crn,crn,e2); | |
1275 } | |
1276 } | |
1277 | |
1278 | |
1279 void | |
107 | 1280 code_neg(int creg) { |
221 | 1281 use_int(creg); |
93 | 1282 printf("\tneg %s,%s\n", register_name(creg), register_name(creg)); |
89 | 1283 } |
1284 | |
1285 | |
1286 void | |
107 | 1287 code_not(int creg) { |
221 | 1288 use_int(creg); |
89 | 1289 printf("\tnor %s,%s,%s\n", |
1290 register_name(creg), register_name(creg),register_name(creg)); | |
1291 } | |
1292 | |
1293 | |
1294 void | |
107 | 1295 code_lnot(int creg) { |
221 | 1296 use_int(creg); |
89 | 1297 printf("\tsubfic r0,%s,0\n", register_name(creg)); |
1298 printf("\tadde %s,r0,%s\n", register_name(creg),register_name(creg)); | |
1299 } | |
1300 | |
1301 void | |
168 | 1302 code_preinc(int e1,int e2,int dir,int sign,int sz,int reg) { |
89 | 1303 char *xrn,*drn; |
1304 if (car(e2)==REGISTER) { | |
221 | 1305 use_int(reg); |
95 | 1306 printf("\taddi %s,%s,%d\n", |
168 | 1307 register_name(cadr(e2)),register_name(cadr(e2)), dir); |
273 | 1308 if (cadr(e2)!=reg) |
1309 printf("\tmr %s,%s\n",register_name(reg),register_name(cadr(e2))); | |
89 | 1310 return; |
1311 } | |
1312 g_expr(e2); | |
221 | 1313 if (!is_int_reg(creg)) error(-1); |
89 | 1314 xrn = register_name(creg); |
221 | 1315 if (reg==USE_CREG) { |
231 | 1316 reg=get_register(); if (!reg) error(-1); |
1317 drn = register_name(reg); | |
1318 set_ireg(reg,0); | |
221 | 1319 } else { |
1320 drn = register_name(reg); | |
1321 } | |
168 | 1322 printf("\t%s %s,0(%s)\n",cload(sz),drn,xrn); |
231 | 1323 if (use) cext(sign,sz,reg); |
168 | 1324 printf("\taddi %s,%s,%d\n",drn,drn,dir); |
1325 printf("\t%s %s,0(%s)\n",cstore(sz),drn,xrn); | |
89 | 1326 } |
1327 | |
1328 | |
1329 void | |
168 | 1330 code_postinc(int e1,int e2,int dir,int sign,int sz,int reg) { |
89 | 1331 char *xrn,*crn,*nrn; |
231 | 1332 int nreg; |
89 | 1333 if (car(e2)==REGISTER) { |
221 | 1334 use_int(reg); |
107 | 1335 printf("\tmr %s,%s\n",register_name(reg),register_name(cadr(e2))); |
89 | 1336 printf("\taddi %s,%s,%d\n", |
168 | 1337 register_name(cadr(e2)),register_name(cadr(e2)),dir); |
89 | 1338 return; |
1339 } | |
1340 g_expr(e2); | |
221 | 1341 if (!is_int_reg(creg)) error(-1); |
89 | 1342 crn = register_name(creg); |
1343 nreg=get_register(); if (!nreg) error(-1); | |
1344 nrn = register_name(nreg); | |
221 | 1345 if (reg==USE_CREG) { |
231 | 1346 reg=get_register(); if (!reg) error(-1); |
1347 xrn = register_name(reg); | |
1348 set_ireg(reg,0); | |
221 | 1349 } else { |
1350 xrn = register_name(reg); | |
1351 } | |
168 | 1352 printf("\t%s %s,0(%s)\n",cload(sz),xrn,crn); |
230 | 1353 if (use) cext(sign,sz,reg); |
168 | 1354 printf("\taddi %s,%s,%d\n",nrn,xrn,dir); |
1355 printf("\t%s %s,0(%s)\n",cstore(sz),nrn,crn); | |
89 | 1356 free_register(nreg); |
1357 } | |
1358 | |
1359 | |
1360 void | |
107 | 1361 code_return(int creg) { |
221 | 1362 char *crn; |
1363 use_int(creg); | |
1364 crn = register_name(creg); | |
102 | 1365 printf("\taddis %s,r31,ha16(L_%d-L_%d)\n",crn,retcont,code_base); |
1366 printf("\tla %s,lo16(L_%d-L_%d)(%s)\n",crn,retcont,code_base,crn); | |
89 | 1367 } |
1368 | |
128 | 1369 #define R1SAVE 1 |
89 | 1370 |
1371 void | |
107 | 1372 code_environment(int creg) { |
126 | 1373 /* save frame pointer */ |
221 | 1374 use_int(creg); |
128 | 1375 #if R1SAVE |
1376 printf("\tlwz %s,0(r1)\n",register_name(creg)); | |
1377 #else | |
1378 int l = 0; | |
1379 printf("\tla %s,",register_name(creg)); | |
1380 printf("lo16(%d+L_%d)(r30)\n",FUNC_LVAR,lvar_offset_label); | |
1381 #endif | |
89 | 1382 } |
1383 | |
288 | 1384 static int rexpr_bool(int e1,int reg); |
1385 | |
1386 #if FLOAT_CODE | |
1387 static int drexpr_bool(int e1,int reg); | |
1388 #endif | |
1389 | |
1390 #if LONGLONG_CODE | |
1391 static int lrexpr_bool(int e1,int reg) | |
1392 { | |
1393 return 0; | |
1394 } | |
1395 #endif | |
1396 | |
1397 | |
1398 | |
89 | 1399 void |
221 | 1400 code_bool(int e1,int reg) { |
89 | 1401 char *xrn; |
1402 int e2,e3; | |
288 | 1403 |
1404 if (rexpr_bool(e1,reg)) return; | |
1405 #if FLOAT_CODE | |
1406 else if (drexpr_bool(e1,reg)) return; | |
1407 #endif | |
1408 #if LONGLONG_CODE | |
1409 else if (lrexpr_bool(e1,reg)) return; | |
1410 #endif | |
1411 | |
89 | 1412 b_expr(e1,1,e2=fwdlabel(),1); /* including > < ... */ |
289 | 1413 if (use) { |
1414 use_int(reg); | |
1415 xrn = register_name(reg); | |
1416 printf("\tli %s,0\n",xrn); | |
1417 jmp(e3=fwdlabel()); | |
1418 fwddef(e2); | |
1419 printf("\tli %s,1\n",xrn); | |
1420 fwddef(e3); | |
1421 } else { | |
1422 fwddef(e2); | |
1423 } | |
89 | 1424 } |
1425 | |
1426 char * | |
1427 code_gt(int cond) { | |
113 | 1428 return (cond?"gt":"le"); |
89 | 1429 } |
1430 | |
1431 char * | |
1432 code_ugt(int cond) { | |
113 | 1433 return (cond?"gt":"le"); |
89 | 1434 } |
1435 | |
1436 char * | |
1437 code_ge(int cond) { | |
113 | 1438 return (cond?"ge":"lt"); |
89 | 1439 } |
1440 | |
1441 char * | |
1442 code_uge(int cond) { | |
113 | 1443 return (cond?"ge":"lt"); |
89 | 1444 } |
1445 | |
1446 char * | |
1447 code_eq(int cond) { | |
113 | 1448 return (cond?"eq":"ne"); |
89 | 1449 } |
1450 | |
280 | 1451 static int cmpflag = 0; |
1452 | |
1453 static void | |
1454 inc_cmpflag() | |
1455 { | |
291 | 1456 cmpflag = (cmpflag+1)%8; |
280 | 1457 } |
1458 | |
89 | 1459 void |
287 | 1460 code_cmp_crgvar(int e1,int reg,int sz,int label,int cond) { |
89 | 1461 int r; |
221 | 1462 use_int(reg); |
367 | 1463 code_ld(cload(sz),reg,cadr(e1),get_ptr_cache((NMTBL*)caddr(e1))); |
230 | 1464 cext(0,sz,r); |
291 | 1465 inc_cmpflag(); |
367 | 1466 printf("\tcmpwi cr%d,%s,0\n",cmpflag,register_name(reg)); |
287 | 1467 jcond(label,cond); |
89 | 1468 } |
1469 | |
1470 | |
1471 void | |
287 | 1472 code_cmp_crlvar(int e2,int reg, int sz,int label,int cond) { |
221 | 1473 char *crn; |
1474 use_int(reg); | |
1475 crn = register_name(reg); | |
119 | 1476 lvar_intro(e2); |
167 | 1477 printf("\t%s %s,",cload(sz),crn); |
160 | 1478 lvar(e2); |
230 | 1479 cext(0,sz,reg); |
287 | 1480 code_cmp_register(reg,label,cond); |
160 | 1481 } |
1482 | |
89 | 1483 |
1484 void | |
287 | 1485 code_cmp_rgvar(int e1,int reg,int label,int cond) { |
221 | 1486 use_int(reg); |
367 | 1487 code_ld("lwz",reg,cadr(e1),get_ptr_cache((NMTBL*)caddr(e1))); |
287 | 1488 code_cmp_register(reg,label,cond); |
89 | 1489 } |
1490 | |
1491 | |
1492 void | |
287 | 1493 code_cmp_rlvar(int e2,int reg,int label,int cond) { |
221 | 1494 char *crn; |
1495 use_int(reg); | |
1496 crn = register_name(reg); | |
119 | 1497 lvar_intro(e2); |
1498 printf("\tlwz %s,",crn); | |
1499 lvar(e2); | |
287 | 1500 code_cmp_register(reg,label,cond); |
89 | 1501 } |
1502 | |
1503 | |
1504 void | |
287 | 1505 code_cmp_register(int e2,int label,int cond) { |
221 | 1506 use_int(e2); |
291 | 1507 inc_cmpflag(); |
280 | 1508 printf("\tcmpwi cr%d,%s,0\n",cmpflag,register_name(e2)); |
287 | 1509 jcond(label,cond); |
89 | 1510 } |
1511 | |
1512 | |
1513 void | |
107 | 1514 code_string(int e1,int creg) |
89 | 1515 { |
95 | 1516 int lb; |
319 | 1517 char *crn; |
221 | 1518 |
1519 use_int(creg); | |
1520 crn = register_name(creg); | |
319 | 1521 lb = emit_string_label(); |
1522 ascii((char *)cadr(e1)); | |
89 | 1523 if (output_mode==TEXT_EMIT_MODE) { |
1524 printf(".text\n"); | |
1525 } else { | |
1526 text_mode(); | |
1527 } | |
102 | 1528 printf("\taddis %s,r31,ha16(L_%d-L_%d)\n",crn,lb,code_base); |
1529 printf("\tla %s,lo16(L_%d-L_%d)(%s)\n",crn,lb,code_base,crn); | |
89 | 1530 } |
1531 | |
1532 #define MAX_COPY_LEN 20 | |
1533 | |
211 | 1534 void |
1535 | |
89 | 1536 emit_copy(int from,int to,int length,int offset,int value,int det) |
1537 { | |
221 | 1538 char *frn; |
1539 char *trn; | |
89 | 1540 char *drn; |
1541 int fix = 0; | |
125 | 1542 char *memmove = "memmove"; |
95 | 1543 int dreg = get_register(); if (!dreg) error(-1); |
221 | 1544 |
89 | 1545 drn = register_name(dreg); |
221 | 1546 use_int(from); |
1547 use_int(to); | |
1548 frn = register_name(from); | |
1549 trn = register_name(to); | |
89 | 1550 |
1551 /* length <0 means upward direction copy */ | |
1552 switch (length) { | |
1553 case 0: break; | |
1554 case 1: case -1: | |
1555 printf("\tlbz %s,%d(%s)\n",drn,offset,frn); | |
1556 printf("\tstb %s,%d(%s)\n",drn,offset,trn); | |
1557 break; | |
1558 case 2: case -2: | |
1559 printf("\tlhz %s,%d(%s)\n",drn,offset,frn); | |
1560 printf("\tsth %s,%d(%s)\n",drn,offset,trn); | |
1561 break; | |
1562 case 4: case -4: | |
1563 printf("\tlwz %s,%d(%s)\n",drn,offset,frn); | |
1564 printf("\tstw %s,%d(%s)\n",drn,offset,trn); | |
1565 break; | |
1566 default: | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1567 if (length <0) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1568 if (length > -MAX_COPY_LEN) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1569 for(;length<=-4;length+=4,offset-=4) |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1570 emit_copy(from,to,-4,offset-4,0,det); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1571 for(;length<=-2;length+=2,offset-=2) |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1572 emit_copy(from,to,-2,offset-2,0,det); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1573 if(length<0) |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1574 emit_copy(from,to,length,offset-1,0,det); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1575 break; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1576 } |
89 | 1577 } else if (length <=MAX_COPY_LEN) { |
1578 for(;length>=4;length-=4,offset+=4) | |
1579 emit_copy(from,to,4,offset,0,det); | |
1580 for(;length>=2;length-=2,offset+=2) | |
1581 emit_copy(from,to,2,offset,0,det); | |
1582 if(length>0) | |
1583 emit_copy(from,to,length,offset,0,det); | |
1584 break; | |
1585 } | |
125 | 1586 clear_ptr_cache(); |
1587 code_save_stacks(); | |
1588 printf("\tli r5,%d\n",length); | |
1589 printf("\tmr r4,%s\n",frn); | |
1590 printf("\tmr r3,%s\n",trn); | |
1591 /* overrap must be allowed */ | |
1592 printf("\tbl L_%s$stub\n",memmove); | |
1593 extern_define(memmove,0,FUNCTION,1); | |
1594 fix=0; | |
207 | 1595 set_ireg(RET_REGISTER,0); |
125 | 1596 if (creg!=to) { |
1597 free_register(to); to = creg; | |
89 | 1598 } |
125 | 1599 break; |
89 | 1600 } |
1601 if (value) { | |
1602 /* creg must point top of the destination data */ | |
1603 /* this code is necessary for the value of assignment or function call */ | |
1604 /* otherwise we don't need this */ | |
1605 if (fix) printf("\taddi %s,%s,%d\n",trn,trn,fix); | |
1606 if(creg!=to) { | |
221 | 1607 free_register(creg); creg=to; ireg=to; |
89 | 1608 } |
1609 } | |
1610 free_register(dreg); | |
1611 } | |
1612 | |
1613 int | |
119 | 1614 struct_push(int e4,int t,int arg) |
89 | 1615 { |
95 | 1616 int length,count; |
119 | 1617 int dreg,sreg; char *drn,*crn,*srn; |
89 | 1618 g_expr(e4); |
221 | 1619 if (!is_int_reg(creg)) error(-1); |
89 | 1620 length=size(t); |
245 | 1621 if(length%SIZE_OF_INT) { |
1622 length += SIZE_OF_INT - (length%SIZE_OF_INT); | |
89 | 1623 } |
95 | 1624 dreg = get_register(); if (!dreg) error(-1); |
89 | 1625 drn = register_name(dreg); |
119 | 1626 crn = register_name(creg); |
125 | 1627 if (length<MAX_COPY_LEN) { |
1628 sreg = get_register(); if (!sreg) error(-1); | |
1629 srn = register_name(sreg); | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1630 code_lvar(cadr(arg),dreg); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1631 for(count=0;count<length;count+=SIZE_OF_INT) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1632 printf("\tlwz %s,%d(%s)\n",srn,count,crn); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1633 printf("\tstwu %s,%d(%s)\n",srn,count,drn); |
89 | 1634 } |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1635 free_register(sreg); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1636 free_register(dreg); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1637 return length/SIZE_OF_INT; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1638 } else { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1639 code_lvar(cadr(arg),dreg); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1640 /* downward direction copy */ |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1641 emit_copy(creg,dreg,length,0,0,1); |
89 | 1642 } |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1643 free_register(dreg); |
245 | 1644 return length/SIZE_OF_INT; |
89 | 1645 } |
1646 | |
104 | 1647 void |
207 | 1648 set_ireg(int reg,int mode) |
104 | 1649 { |
207 | 1650 if (!is_int_reg(reg)) error(-1); |
104 | 1651 if (reg!=creg) { |
111 | 1652 clear_ptr_cache_reg(reg); |
208 | 1653 if (ireg && reg!=ireg ) { |
1654 free_register(ireg); | |
1655 if (mode) { | |
1656 printf("\tmr %s,%s\n",register_name(reg),register_name(ireg)); | |
1657 } | |
206 | 1658 } |
104 | 1659 free_register(creg); |
208 | 1660 regs[reg]=USING_REG; |
104 | 1661 } |
206 | 1662 creg = ireg = reg; |
104 | 1663 } |
1664 | |
1665 void | |
1666 set_freg(int reg,int mode) | |
1667 { | |
207 | 1668 if (!is_float_reg(reg)) error(-1); |
147 | 1669 if (reg!=creg) { |
222 | 1670 if (freg && reg!=freg) { |
208 | 1671 free_register(freg); |
1672 if (mode) { | |
1673 printf("\tfmr %s,%s\n",fregister_name(reg),fregister_name(freg)); | |
1674 } | |
147 | 1675 } |
222 | 1676 // if (creg!=ireg) free_register(creg); |
208 | 1677 regs[reg]=USING_REG; |
104 | 1678 } |
206 | 1679 creg = freg = reg; |
195 | 1680 } |
1681 | |
1682 void | |
1683 set_lreg(int reg,int mode) | |
1684 { | |
222 | 1685 if (reg==RET_LREGISTER) { |
1686 regv_l(reg) = RET_LREGISTER_L; | |
1687 regv_h(reg) = RET_LREGISTER_H; | |
1688 } | |
207 | 1689 if (!is_longlong_reg(reg)) error(-1); |
206 | 1690 if (reg!=creg) { |
222 | 1691 if (lreg && reg!=lreg) { |
208 | 1692 if (mode) { |
1693 printf("\tmr %s,%s\n", | |
1694 lregister_name_low(reg),lregister_name_low(lreg)); | |
1695 printf("\tmr %s,%s\n", | |
1696 lregister_name_high(reg),lregister_name_high(lreg)); | |
1697 } | |
226 | 1698 free_register(lreg); |
206 | 1699 } |
226 | 1700 free_register(creg); |
207 | 1701 regs[reg]=USING_REG; |
222 | 1702 clear_ptr_cache_reg(regv_l(reg)); |
207 | 1703 regs[regv_l(reg)]=USING_REG; |
222 | 1704 clear_ptr_cache_reg(regv_h(reg)); |
207 | 1705 regs[regv_h(reg)]=USING_REG; |
206 | 1706 } |
219 | 1707 creg = lreg = reg; |
104 | 1708 } |
1709 | |
1710 void | |
217 | 1711 set_lreg_operand(int reg,int mode) |
216 | 1712 { |
326 | 1713 // save_stack,clear_ptr_cache is assumed |
217 | 1714 if (!is_longlong_reg(reg)) { error(-1); return; } |
1715 if (mode) { | |
255 | 1716 if (regv_l(reg)!=3) |
1717 printf("\tmr r3,%s\n", lregister_name_high(reg)); | |
1718 if (regv_l(reg)!=4) | |
1719 printf("\tmr r4,%s\n", lregister_name_low(reg)); | |
1720 } | |
1721 } | |
1722 | |
1723 void | |
1724 set_lreg_operand1(int reg,int mode) | |
1725 { | |
326 | 1726 // save_stack,clear_ptr_cache is assumed |
255 | 1727 if (!is_longlong_reg(reg)) { error(-1); return; } |
1728 if (mode) { | |
217 | 1729 if (regv_l(reg)!=5) |
228 | 1730 printf("\tmr r5,%s\n", lregister_name_high(reg)); |
217 | 1731 if (regv_l(reg)!=6) |
228 | 1732 printf("\tmr r6,%s\n", lregister_name_low(reg)); |
217 | 1733 } |
216 | 1734 } |
1735 | |
1736 void | |
207 | 1737 use_reg(int arg) |
104 | 1738 { |
210 | 1739 // printf("# use reg %d\n",arg); |
208 | 1740 if (arg<0||arg> REAL_MAX_REGISTER+REAL_MAX_FREGISTER+ REAL_MAX_LREGISTER) |
1741 error(-1); | |
223 | 1742 clear_ptr_cache_reg(arg); |
207 | 1743 regs[arg]=USING_REG; |
1744 if (is_longlong_reg(arg)) { | |
228 | 1745 clear_ptr_cache_reg(regv_l(arg)); |
207 | 1746 regs[regv_l(arg)]=USING_REG; |
228 | 1747 clear_ptr_cache_reg(regv_h(arg)); |
207 | 1748 regs[regv_h(arg)]=USING_REG; |
206 | 1749 } |
104 | 1750 } |
1751 | |
105 | 1752 void |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
1753 code_save_input_registers(int dots) |
105 | 1754 { |
119 | 1755 int args; |
1756 NMTBL *n; | |
1757 int reg; | |
1758 int tag; | |
1759 int lvar; | |
1760 int t; | |
1761 /* fnptr->dsp=list4(type,fnptr->dsp,(int)n,0); */ | |
1762 int reg_offset = 0; | |
1763 int offset = 0; | |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
1764 int reg_var = 0; |
119 | 1765 |
1766 for(args = fnptr->dsp;args;args = cadr(args)) { | |
1767 n = (NMTBL *)caddr(args); | |
1768 tag = n->sc; | |
1769 reg = n->dsp; | |
1770 if (!n||n==&null_nptr) error(REG_ERR); | |
1771 if (tag==REGISTER) { | |
1772 /* regs[reg]==INPUT_REG case should be considered */ | |
1773 n->dsp = offset; | |
245 | 1774 offset+=SIZE_OF_INT; |
119 | 1775 t = INT; |
1776 reg += reg_offset; /* for duplicated floating point argument */ | |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
1777 reg_var++; |
119 | 1778 } else if (tag==DREGISTER) { |
145 | 1779 /* regs[reg]==INPUT_REG case should be considered */ |
119 | 1780 n->dsp = offset; |
120 | 1781 t = n->ty; |
245 | 1782 if(t==FLOAT) { offset+=SIZE_OF_FLOAT; reg_offset+=1; } |
1783 else if(t==DOUBLE) { offset+=SIZE_OF_DOUBLE; reg_offset+=2; } | |
120 | 1784 else error(-1); |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
1785 reg_var += 2; |
206 | 1786 } else if (tag==LREGISTER) { |
1787 /* regs[reg]==INPUT_REG case should be considered */ | |
1788 n->dsp = offset; | |
1789 t = n->ty; | |
245 | 1790 offset+=SIZE_OF_LONGLONG; reg_offset+=2; |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
1791 reg_var += 2; |
122 | 1792 } else { |
1793 offset += size(n->ty); | |
119 | 1794 continue; |
122 | 1795 } |
119 | 1796 n->sc = LVAR; |
1797 lvar = list2(LVAR,n->dsp); | |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
1798 g_expr_u(assign_expr0( |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
1799 list2(LVAR,n->dsp),list3(tag,reg,(int)n),n->ty,t)); |
206 | 1800 if (tag==REGISTER||tag==DREGISTER||tag==FREGISTER||tag==LREGISTER) { |
119 | 1801 free_register(reg); |
1802 } | |
1803 } | |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
1804 if (dots) { |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
1805 while ((reg = get_input_register_var(reg_var,0,0))) { |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
1806 g_expr_u(assign_expr0( |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
1807 list2(LVAR,offset),reg,INT,INT)); |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
1808 offset+=SIZE_OF_INT; |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
1809 reg_var++; |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
1810 } |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
1811 } |
121 | 1812 my_func_args = offset; |
105 | 1813 } |
1814 | |
228 | 1815 static int |
1816 not_simple_p(int e3) | |
223 | 1817 { |
255 | 1818 return e3==FUNCTION||e3==CONV||e3==RSTRUCT||e3==STASS|| |
1819 e3==LLSHIFT||e3==LULSHIFT||e3==LRSHIFT||e3==LURSHIFT|| | |
313 | 1820 e3==LDIV||e3==LUDIV||e3==LMOD||e3==LUMOD||e3==LASSOP||e3==ALLOCA; |
223 | 1821 } |
1822 | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1823 static int |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1824 simple_arg(int e3) |
108 | 1825 { |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1826 return !contains_p(e3,not_simple_p); |
108 | 1827 } |
1828 | |
119 | 1829 int |
1830 caller_arg_offset_v(int arg) | |
1831 { | |
245 | 1832 return ARG_LVAR_OFFSET+arg*SIZE_OF_INT; |
119 | 1833 } |
111 | 1834 |
233 | 1835 void |
1836 use_input_reg(int reg,int mode) | |
1837 { | |
1838 if (is_int_reg(reg)) { | |
1839 if (ireg&® == ireg) { | |
1840 if (creg==ireg) creg = 0; | |
1841 ireg = 0; | |
1842 } | |
1843 if (lreg) { | |
1844 if (regv_l(lreg)==reg) { | |
1845 regs[lreg]=0; | |
1846 if (regv_h(lreg)>reg&®s[regv_h(lreg)]==USING_REG) { | |
1847 free_register(regv_h(lreg)); | |
1848 } | |
1849 if (creg==lreg) creg = 0; | |
1850 lreg = 0; | |
1851 } else if (regv_h(lreg)==reg) { | |
1852 regs[lreg]=0; | |
1853 if (regv_h(lreg)>reg&®s[regv_l(lreg)]==USING_REG) { | |
1854 free_register(regv_l(lreg)); | |
1855 } | |
1856 if (creg==lreg) creg = 0; | |
1857 lreg = 0; | |
1858 } | |
1859 } | |
1860 } else if (is_longlong_reg(reg)) { | |
1861 use_input_reg(regv_h(reg),0); | |
1862 use_input_reg(regv_l(reg),0); | |
1863 } else if (is_float_reg(reg)) { | |
1864 if (freg&® == freg) { | |
1865 if (creg==freg) creg = 0; | |
1866 freg = 0; | |
1867 } | |
1868 } | |
1869 if (mode) use_reg(reg); | |
1870 } | |
1871 | |
271 | 1872 static int |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1873 compute_complex_arg(int e3,int reg_arg_list,int arg) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1874 int t=caddr(e3); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1875 int e4 = car(e3); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1876 reg_arg_list = list2(arg,reg_arg_list); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1877 g_expr_u(assign_expr0(arg,e4,t,t)); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1878 if (car(arg)==REGISTER||car(arg)==DREGISTER|| |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1879 car(arg)==FREGISTER||car(arg)==LREGISTER) |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1880 use_input_reg(cadr(arg),1); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1881 car(e3) = arg; |
271 | 1882 return reg_arg_list; |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1883 } |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1884 |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1885 static void |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1886 increment_function_arg(int e3,int *pnargs,int *preg_arg,int *pfreg_arg) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1887 int nargs=0,reg_arg=0,freg_arg=0; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1888 int t=caddr(e3); |
331 | 1889 if (t>=0&&(car(t)==BIT_FIELD)) { |
1890 t = cadr(t); | |
1891 } | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1892 if(scalar(t)) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1893 nargs ++ ; reg_arg++; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1894 } else if (t==LONGLONG||t==ULONGLONG) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1895 nargs ++ ; reg_arg++; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1896 nargs ++ ; reg_arg++; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1897 } else if (t==DOUBLE||t==FLOAT) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1898 if (*preg_arg<MAX_INPUT_REGISTER_VAR) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1899 reg_arg += 2; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1900 } |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1901 freg_arg++; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1902 nargs += size(t)/SIZE_OF_INT; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1903 } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1904 nargs += round4(size(t))/SIZE_OF_INT; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1905 } else { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1906 error(TYERR); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1907 nargs ++ ; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1908 } |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1909 *pnargs += nargs; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1910 *preg_arg += reg_arg; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1911 *pfreg_arg += freg_arg; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1912 } |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1913 |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1914 #define AS_SAVE 1 |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1915 #define AS_ARG 0 |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1916 |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1917 static int |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1918 get_input_arg(int t,int mode,int nargs,int reg_arg,int freg_arg) |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1919 { |
331 | 1920 if (t>=0&&(car(t)==BIT_FIELD)) { |
1921 t = cadr(t); | |
1922 } | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1923 if(scalar(t)) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1924 if (mode==AS_SAVE) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1925 return get_register_var(0); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1926 } else if (reg_arg>=MAX_INPUT_REGISTER_VAR) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1927 return list2(LVAR,caller_arg_offset_v(nargs)); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1928 } else |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1929 return get_input_register_var(reg_arg,0,0); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1930 } else if (t==LONGLONG||t==ULONGLONG) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1931 if (mode==AS_SAVE) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1932 return get_lregister_var(0); |
259 | 1933 } else if (reg_arg+1>=MAX_INPUT_REGISTER_VAR) { |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1934 return list2(LVAR,caller_arg_offset_v(nargs)); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1935 } else |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1936 return get_input_lregister_var(reg_arg,0,0); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1937 } else if (t==FLOAT) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1938 if (mode==AS_SAVE) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1939 return get_dregister_var(0,0); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1940 } else if (freg_arg>=MAX_INPUT_DREGISTER_VAR) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1941 return list2(LVAR,caller_arg_offset_v(nargs)); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1942 } else |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1943 return get_input_dregister_var(freg_arg,0,0,0); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1944 } else if (t==DOUBLE) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1945 if (mode==AS_SAVE) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1946 return get_dregister_var(0,1); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1947 } else if (freg_arg>=MAX_INPUT_DREGISTER_VAR) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1948 return list2(LVAR,caller_arg_offset_v(nargs)); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1949 } else |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1950 return get_input_dregister_var(freg_arg,0,0,1); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1951 } else if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1952 if (mode==AS_SAVE) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1953 return get_register_var(0); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1954 } else |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1955 return list2(LVAR,caller_arg_offset_v(nargs)); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1956 } else { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1957 error(-1); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1958 return get_register_var(0); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1959 } |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1960 } |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1961 |
108 | 1962 int |
89 | 1963 function(int e1) |
1964 { | |
119 | 1965 int e2,e3,e4,e5,nargs,t,r0,r1; |
104 | 1966 int arg,reg_arg,freg_arg,arg_assign; |
136
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
135
diff
changeset
|
1967 int dots; |
111 | 1968 int reg_arg_list=0,ret_type,special_lvar; |
127 | 1969 NMTBL *fn = 0; |
108 | 1970 int jmp = 0; |
1971 char *jrn; | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1972 int complex_; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1973 int pnargs,preg_arg,pfreg_arg; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
1974 int stargs; |
95 | 1975 |
111 | 1976 special_lvar = -1; |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
1977 #if 0 |
136
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
135
diff
changeset
|
1978 ret_type = cadr(cadddr(e1)); |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
135
diff
changeset
|
1979 if (ret_type==CHAR) ret_type=INT; |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
135
diff
changeset
|
1980 |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
135
diff
changeset
|
1981 /* check argments type is DOTS? */ |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
135
diff
changeset
|
1982 t = caddr(cadddr(e1)); |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
135
diff
changeset
|
1983 if (t==0 || t==DOTS) dots = 1; |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
135
diff
changeset
|
1984 else { |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
135
diff
changeset
|
1985 dots = 0; |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
135
diff
changeset
|
1986 for(t = caddr(cadddr(e1));t;t = cadr(t)) { |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
135
diff
changeset
|
1987 if (car(t)==DOTS) dots = 1; |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
135
diff
changeset
|
1988 } |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
135
diff
changeset
|
1989 } |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
1990 #else |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
1991 ret_type = function_type(cadddr(e1),&dots); |
313 | 1992 if (caddr(cadddr(e1))==0) dots=1; |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
304
diff
changeset
|
1993 #endif |
108 | 1994 |
285 | 1995 arg_assign = 0; |
108 | 1996 e2 = cadr(e1); |
1997 if (car(e2) == FNAME) { | |
1998 fn=(NMTBL *)cadr(e2); | |
1999 } else { | |
285 | 2000 #if 0 |
108 | 2001 jmp = get_register_var(0); |
2002 if (car(jmp)!=REGISTER) error(-1); | |
2003 reg_arg_list = list2(jmp,reg_arg_list); | |
116 | 2004 g_expr(e2); |
221 | 2005 if (!is_int_reg(creg)) error(-1); |
116 | 2006 code_register(creg,cadr(jmp)); |
2007 /* g_expr(assign_expr0(jmp,e2,INT,INT)); functions are lvalue */ | |
285 | 2008 #else |
2009 if (car(e2)==INDIRECT) e2=cadr(e2); // (*func)(i) case | |
2010 jmp = get_register_var(0); | |
2011 if (car(jmp)!=REGISTER) error(-1); | |
2012 reg_arg_list = list2(jmp,reg_arg_list); | |
2013 if (!simple_arg(e2)) { | |
2014 g_expr_u(assign_expr0(jmp,e2,INT,INT)); | |
2015 } else | |
2016 arg_assign = list2(assign_expr0(jmp,e2,INT,INT),arg_assign); | |
2017 #endif | |
108 | 2018 } |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2019 /* first we execute complex argument to avoid interaction with |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2020 input variables */ |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2021 stargs = 0; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2022 complex_ = 0; |
259 | 2023 nargs = reg_arg = freg_arg = 0; |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2024 for (e3 = e1 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2025 t=caddr(e3); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2026 if ((e5= !simple_arg(car(e3)))) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2027 if (complex_) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2028 arg = get_input_arg(caddr(complex_),AS_SAVE, |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2029 pnargs,preg_arg,pfreg_arg); |
271 | 2030 reg_arg_list = compute_complex_arg(complex_,reg_arg_list,arg); |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2031 } |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2032 pnargs=nargs;preg_arg=reg_arg;pfreg_arg=freg_arg; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2033 complex_ = e3; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2034 } |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2035 if (t>=0&&(car(t)==STRUCT||car(t)==UNION)) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2036 // The struct should be pushed after complex arguments. |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2037 if (e5) { // compute address only, complex_ is me now. Clear it. |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2038 complex_ = 0; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2039 e4 = car(e3); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2040 if (car(e4)!=RSTRUCT) error(-1); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2041 if (!simple_arg(cadr(e4))) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2042 // Calculate complex struct address here. |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2043 // If simple, leave it. |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2044 arg = get_register_var(0); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2045 g_expr_u(assign_expr0(arg,list2(ADDRESS,car(e3)),INT,INT)); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2046 car(e3)=arg; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2047 reg_arg_list = list2(arg,reg_arg_list); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2048 if (car(arg)==REGISTER) use_input_reg(cadr(arg),1); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2049 } |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2050 } |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2051 stargs = list4(e3,stargs,nargs,reg_arg); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2052 } |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2053 increment_function_arg(e3,&nargs,®_arg,&freg_arg); |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2054 } |
108 | 2055 |
99 | 2056 /* now all input register vars are free */ |
108 | 2057 code_save_stacks(); |
222 | 2058 // set_lreg(LREG_LREGISTER,0); |
221 | 2059 set_freg(FREG_FREGISTER,0); |
207 | 2060 set_ireg(CREG_REGISTER,0); |
108 | 2061 |
268 | 2062 // Struct arguments need emit_copy. it destructs 3 input registers. |
326 | 2063 // But it returns no value on a register. So calculate it here. |
268 | 2064 // We cannot do this in the previous loop, because the copied struct may be |
326 | 2065 // override by other complex arguments. But before this we have to check |
268 | 2066 // complex_. |
2067 | |
2068 if (stargs) { | |
2069 if (complex_) { | |
2070 arg = get_input_arg(caddr(complex_),AS_SAVE, | |
2071 pnargs,preg_arg,pfreg_arg); | |
271 | 2072 reg_arg_list = compute_complex_arg(complex_,reg_arg_list,arg); |
268 | 2073 } |
2074 for(stargs=reverse0(stargs);stargs;stargs = cadr(stargs)) { | |
2075 e3 = car(stargs); | |
2076 e4 = car(e3); | |
2077 t = caddr(e3); | |
2078 arg = get_input_arg(t,AS_ARG,caddr(stargs),cadddr(stargs),0); | |
2079 struct_push(e4,t,arg); | |
2080 car(e3)=0; // done | |
2081 } | |
2082 } else { | |
2083 // last complex argument can use input register | |
2084 if (complex_) { | |
2085 arg = get_input_arg(caddr(complex_),AS_ARG,pnargs,preg_arg,pfreg_arg); | |
271 | 2086 reg_arg_list = compute_complex_arg(complex_,reg_arg_list,arg); |
268 | 2087 } |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2088 } |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2089 |
285 | 2090 nargs = reg_arg = freg_arg = 0; |
268 | 2091 // calc stack arguments first, it may requires extra registers, |
2092 // and we can still use input registers now. | |
259 | 2093 for (e3 = e1; e3; |
2094 increment_function_arg(e3,&nargs,®_arg,&freg_arg), | |
2095 e3 = cadr(e3)) { | |
2096 if (!(e4=car(e3))) continue; | |
2097 t=caddr(e3); | |
2098 arg = get_input_arg(t,AS_ARG,nargs,reg_arg,freg_arg); | |
2099 if (car(arg)!=LVAR) continue; | |
2100 g_expr_u(assign_expr0(arg,e4,t,t)); | |
2101 if (t==LONGLONG||t==ULONGLONG) { | |
2102 if (reg_arg+1==MAX_INPUT_REGISTER_VAR) { | |
2103 // half register, half memory case | |
2104 arg_assign = list2( | |
2105 assign_expr0(r0=get_input_register_var(reg_arg,0,0), | |
2106 arg,INT,INT), | |
2107 arg_assign); | |
2108 use_input_reg(cadr(r0),1); | |
2109 } | |
2110 } | |
2111 car(e3)=0; // done | |
2112 } | |
2113 nargs = reg_arg = freg_arg = 0; | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2114 for (e3 = e1; e3; |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2115 increment_function_arg(e3,&nargs,®_arg,&freg_arg), |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2116 e3 = cadr(e3)) { |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2117 if (!(e4=car(e3))) continue; |
89 | 2118 t=caddr(e3); |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2119 arg = get_input_arg(t,AS_ARG,nargs,reg_arg,freg_arg); |
89 | 2120 if(scalar(t)) { |
99 | 2121 reg_arg_list = list2(arg,reg_arg_list); |
233 | 2122 /* protect from input register free */ |
2123 if (car(arg)==REGISTER) | |
2124 use_input_reg(cadr(arg),1); | |
99 | 2125 g_expr_u(assign_expr0(arg,e4,t,t)); |
202 | 2126 } else if (t==LONGLONG||t==ULONGLONG) { |
259 | 2127 if (reg_arg+1==MAX_INPUT_REGISTER_VAR) { |
227 | 2128 // half register, half memory case |
2129 // put whole long long anyway | |
2130 arg_assign = list2( | |
232 | 2131 assign_expr0(r0=get_input_register_var(reg_arg,0,0), |
227 | 2132 arg,INT,INT), |
2133 arg_assign); | |
233 | 2134 use_input_reg(cadr(r0),1); |
206 | 2135 } else { |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2136 if (car(arg)==LREGISTER) |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
257
diff
changeset
|
2137 use_input_reg(cadr(arg),1); |
206 | 2138 } |
2139 reg_arg_list = list2(arg,reg_arg_list); | |
2140 g_expr_u(assign_expr0(arg,e4,t,t)); | |
89 | 2141 } else if (t==DOUBLE||t==FLOAT) { |
137 | 2142 if (reg_arg<MAX_INPUT_REGISTER_VAR) { |
119 | 2143 /* sigh... |
326 | 2144 printf requires floating value in integer registers |
119 | 2145 */ |
137 | 2146 if (dots) { |
2147 if (car(e4)==DRLVAR) { | |
2148 special_lvar = cadr(e4); | |
2149 e5 = list2(LVAR,special_lvar); | |
2150 } else { | |
245 | 2151 special_lvar = new_lvar(SIZE_OF_DOUBLE); |
137 | 2152 g_expr(assign_expr0( |
2153 (e5=list2(LVAR,special_lvar)),e4,DOUBLE,t)); | |
2154 reg_arg_list = list2(e5,reg_arg_list); | |
2155 e4 = list2(DREGISTER,freg); | |
2156 /* freg should not change until XXX */ | |
2157 } | |
2158 r0=get_input_register_var(reg_arg,0,0); | |
2159 r1 = reg_arg+1+MIN_TMP_REG; | |
206 | 2160 if (regs[r1]==PTRC_REG) |
2161 clear_ptr_cache_reg(list2(REGISTER,r1)); | |
137 | 2162 /* else if (regs[r1]) error(-1); */ |
2163 r1=get_input_register_var_1(reg_arg+1,0,0); | |
233 | 2164 use_input_reg(cadr(r0),1); /* protect from input register free */ |
2165 use_input_reg(cadr(r1),1); /* protect from input register free */ | |
137 | 2166 reg_arg_list = list2(r0,reg_arg_list); |
2167 reg_arg_list = list2(r1,reg_arg_list); | |
2168 arg_assign = list2( assign_expr0(r0,e5,INT,INT), arg_assign); | |
2169 arg_assign = list2( assign_expr0(r1, | |
245 | 2170 list2(LVAR,special_lvar+SIZE_OF_INT), |
137 | 2171 INT,INT), arg_assign); |
111 | 2172 } |
2173 } | |
136
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
135
diff
changeset
|
2174 if (dots && freg_arg>=4 && freg_arg<MAX_INPUT_DREGISTER_VAR) { |
119 | 2175 /* oh my god! |
326 | 2176 it requires integer register and floating register and |
119 | 2177 stack value. You are crazy. |
2178 */ | |
2179 arg_assign = list2( | |
2180 assign_expr0(list2(LVAR,caller_arg_offset_v(nargs)), | |
138 | 2181 get_input_dregister_var(freg_arg,0,0,1),t,t), |
119 | 2182 arg_assign); |
2183 } | |
233 | 2184 reg_arg_list = list2(arg,reg_arg_list); |
208 | 2185 if (car(arg)==DREGISTER) |
233 | 2186 use_input_reg(cadr(arg),1); /* protect from input register free */ |
118 | 2187 g_expr_u(assign_expr0(arg,e4,t,t)); /* XXX */ |
89 | 2188 } |
259 | 2189 // structs are finished |
89 | 2190 } |
116 | 2191 if (max_func_args<nargs) max_func_args=nargs; |
104 | 2192 for(;arg_assign;arg_assign=cadr(arg_assign)) { |
2193 g_expr_u(car(arg_assign)); | |
2194 } | |
96 | 2195 clear_ptr_cache(); |
89 | 2196 if (car(e2) == FNAME) { |
108 | 2197 printf("\tbl\tL_%s$stub\n",fn->nm); |
89 | 2198 } else { |
108 | 2199 jrn = register_name(cadr(jmp)); |
89 | 2200 printf("\tmtctr %s\n",jrn); |
2201 printf("\tbctrl\n"); | |
2202 } | |
99 | 2203 for(;reg_arg_list;reg_arg_list=cadr(reg_arg_list)) { |
108 | 2204 arg = car(reg_arg_list); |
206 | 2205 if (car(arg)==REGISTER||car(arg)==DREGISTER||car(arg)==FREGISTER |
2206 ||car(arg)==LREGISTER) | |
147 | 2207 free_register(cadr(arg)); |
119 | 2208 else if (car(arg)==LVAR&&cadr(arg)<0) free_lvar(cadr(arg)); |
99 | 2209 } |
105 | 2210 if (ret_type==DOUBLE||ret_type==FLOAT) { |
104 | 2211 set_freg(RET_FREGISTER,0); |
206 | 2212 } else if (ret_type==ULONGLONG||ret_type==LONGLONG) { |
2213 set_lreg(RET_LREGISTER,0); | |
207 | 2214 use_reg(RET_LREGISTER); |
105 | 2215 } else if (ret_type==VOID) { |
96 | 2216 } else { |
207 | 2217 set_ireg(RET_REGISTER,0); |
96 | 2218 } |
105 | 2219 return ret_type; |
89 | 2220 } |
2221 | |
2222 void | |
313 | 2223 code_alloca(int e1,int reg) |
2224 { | |
2225 char *crn,*grn; | |
2226 int g; | |
2227 | |
2228 g_expr(list3(BAND,list3(ADD,e1,list2(CONST,30)),list2(CONST,~15))); | |
2229 use_int(reg); | |
2230 g = get_register(); | |
2231 crn = register_name(reg); | |
2232 grn = register_name(g); | |
2233 // printf("\trlwinm r0,%s,0,0,27\n",crn); | |
2234 printf("\tlwz %s,0(r1)\n",grn); | |
2235 printf("\tneg %s,%s\n",crn,crn); | |
2236 printf("\tstwux %s,r1,%s\n",grn,crn); | |
2237 // printf("\tstw %s,0(r1)\n",grn); | |
2238 if (!max_func_arg_label) max_func_arg_label = fwdlabel(); | |
2239 printf("\taddis r1,r1,ha16(L_%d)\n",max_func_arg_label); | |
2240 printf("\taddi %s,r1,lo16(L_%d)\n",crn,max_func_arg_label); | |
2241 free_register(g); | |
2242 } | |
2243 | |
2244 void | |
89 | 2245 code_frame_pointer(int e3) { |
221 | 2246 use_int(e3); |
128 | 2247 #if R1SAVE |
2248 printf("\tmr r1,%s\n",register_name(e3)); | |
2249 #else | |
126 | 2250 printf("\tmr r30,%s\n",register_name(e3)); |
128 | 2251 #endif |
89 | 2252 } |
2253 | |
2254 | |
2255 void | |
2256 code_fix_frame_pointer(int disp_offset) { | |
128 | 2257 int l = 0; |
2258 printf("\tla r30,"); | |
375 | 2259 printf("lo16(%d)(r30)\n",FUNC_LVAR); |
89 | 2260 } |
2261 | |
2262 void | |
2263 code_jmp(char *s) { | |
128 | 2264 max_reg_var = REG_VAR_BASE-REG_VAR_MIN; |
2265 max_freg_var = FREG_VAR_BASE-FREG_VAR_MIN; | |
89 | 2266 printf("\tb L_%s$stub\n",s); |
283 | 2267 control=0; |
89 | 2268 } |
2269 | |
2270 | |
2271 void | |
2272 code_indirect_jmp(int e2) { | |
128 | 2273 max_reg_var = REG_VAR_BASE-REG_VAR_MIN; |
2274 max_freg_var = FREG_VAR_BASE-FREG_VAR_MIN; | |
221 | 2275 use_int(e2); |
89 | 2276 printf("\tmtctr %s\n",register_name(e2)); |
2277 printf("\tbctr\n"); | |
283 | 2278 control=0; |
89 | 2279 } |
2280 | |
355 | 2281 void |
2282 code_rindirect(int e1, int reg,int offset, int sign,int sz) | |
196 | 2283 { |
221 | 2284 char *crn,*rrn; |
196 | 2285 g_expr(e1); |
221 | 2286 if (!is_int_reg(creg)) error(-1); |
196 | 2287 crn=register_name(creg); |
221 | 2288 use_int(reg); |
2289 rrn=register_name(reg); | |
375 | 2290 if (LARGE_OFFSET(offset)) { |
2291 printf("\taddis %s,%s,ha16(%d)\n",crn,crn,offset); | |
2292 } | |
2293 printf("\t%s %s,lo16(%d)(%s)\n",cload(sz),rrn,offset,crn); | |
355 | 2294 cext(sign,sz,reg); |
89 | 2295 } |
2296 | |
196 | 2297 #if FLOAT_CODE |
2298 int | |
221 | 2299 code_drindirect(int e1, int reg,int offset, int d) |
196 | 2300 { |
2301 char *crn; | |
2302 g_expr(e1); | |
221 | 2303 if (!is_int_reg(creg)) error(-1); |
196 | 2304 crn=register_name(creg); |
221 | 2305 use_float(d,reg); |
375 | 2306 if (LARGE_OFFSET(offset)) { |
2307 printf("\taddis %s,%s,ha16(%d)\n",crn,crn,offset); | |
2308 } | |
2309 printf("\t%s %s,lo16(%d)(%s)\n",fload(d), | |
221 | 2310 fregister_name(reg),offset,crn); |
375 | 2311 |
206 | 2312 return d?DOUBLE:FLOAT; |
196 | 2313 } |
2314 #endif | |
2315 | |
269 | 2316 static void |
2317 lload(int creg,int reg,int offset) | |
2318 { | |
2319 char *crn = register_name(creg); | |
375 | 2320 if (LARGE_OFFSET(offset)) { |
2321 printf("\taddis %s,%s,ha16(%d)\n",crn,crn,offset); | |
2322 } | |
269 | 2323 if (creg!=regv_h(reg)) { |
375 | 2324 printf("\tlwz %s,lo16(%d)(%s)\n",lregister_name_high(reg),offset,crn); |
2325 printf("\tlwz %s,lo16(%d)(%s)\n",lregister_name_low(reg),offset+SIZE_OF_INT,crn); | |
269 | 2326 } else { |
375 | 2327 printf("\tlwz %s,lo16(%d)(%s)\n",lregister_name_low(reg),offset+SIZE_OF_INT,crn); |
2328 printf("\tlwz %s,lo16(%d)(%s)\n",lregister_name_high(reg),offset,crn); | |
269 | 2329 } |
2330 } | |
2331 | |
196 | 2332 #if LONGLONG_CODE |
2333 int | |
221 | 2334 code_lrindirect(int e1, int reg, int offset, int us) |
196 | 2335 { |
2336 char *crn; | |
222 | 2337 int creg0; |
2338 | |
196 | 2339 g_expr(e1); |
221 | 2340 if (!is_int_reg(creg)) error(-1); |
222 | 2341 crn=register_name(creg0=creg); |
221 | 2342 use_longlong(reg); |
269 | 2343 lload(creg0,reg,offset); |
206 | 2344 return us?ULONGLONG:LONGLONG; |
196 | 2345 } |
2346 #endif | |
2347 | |
89 | 2348 void |
103 | 2349 code_assign_gvar(int e2,int creg,int byte) { |
221 | 2350 use_int(creg); |
367 | 2351 code_ldf(cstore(byte),register_name(creg),cadr(e2), |
2352 get_ptr_cache((NMTBL*)caddr(e2))); | |
89 | 2353 } |
2354 | |
2355 void | |
103 | 2356 code_assign_lvar(int e2,int creg,int byte) { |
90 | 2357 char *crn; |
221 | 2358 use_int(creg); |
90 | 2359 crn=register_name(creg); |
119 | 2360 lvar_intro(e2); |
367 | 2361 printf("\t%s %s,",cstore(byte),crn); |
165 | 2362 lvar(e2); |
89 | 2363 } |
2364 | |
2365 void | |
111 | 2366 code_assign_register(int e2,int byte,int creg) { |
221 | 2367 use_int(creg); |
104 | 2368 if (e2!=creg) |
2369 printf("\tmr %s,%s\n",register_name(e2),register_name(creg)); | |
89 | 2370 } |
2371 | |
2372 void | |
118 | 2373 code_assign(int e2,int byte,int creg) { |
233 | 2374 char *drn; |
221 | 2375 char *crn; |
233 | 2376 use_int(e2); |
2377 drn=register_name(e2); | |
221 | 2378 use_int(creg); |
2379 crn=register_name(creg); | |
95 | 2380 |
367 | 2381 printf("\t%s %s,0(%s)\n",cstore(byte),crn,drn); |
89 | 2382 } |
2383 | |
2384 | |
2385 void | |
221 | 2386 code_register_assop(int e2,int reg, int op,int byte) { |
2387 // reg <= reg(e2) op=reg | |
2388 use_int(reg); | |
2389 tosop(op,e2,reg); | |
89 | 2390 } |
2391 | |
2392 void | |
221 | 2393 code_assop(int op,int creg, int byte,int sign) { |
90 | 2394 char *xrn,*crn,*drn; |
89 | 2395 int xreg; |
90 | 2396 int edx = get_register(); if(!edx) error(-1); |
221 | 2397 // (*creg) op = pop() |
2398 | |
2399 use_int(creg); | |
93 | 2400 xrn = register_name(xreg = emit_pop(0)); /* pop e3 value */ |
285 | 2401 #if 1 |
2402 set_ireg(edx,0); | |
2403 ld_indexx(byte,0,creg,ireg,sign); | |
338 | 2404 use_reg(creg); // to clear ptr cache |
285 | 2405 tosop(op,ireg,xreg); |
2406 crn = register_name(ireg); | |
2407 drn = register_name(creg); | |
2408 if (byte==1) { | |
2409 printf("\tstb %s,0(%s)\n",crn,drn); | |
2410 } else if (byte==SIZE_OF_SHORT) { | |
2411 printf("\tsth %s,0(%s)\n",crn,drn); | |
2412 } else { | |
2413 printf("\tstw %s,0(%s)\n",crn,drn); | |
2414 } | |
2415 free_register(creg); | |
2416 emit_pop_free(xreg); | |
2417 #else | |
113 | 2418 printf("# assop\n\tmr %s,%s\n",register_name(edx),register_name(creg)); |
221 | 2419 ld_indexx(byte,0,edx,creg,sign); |
2420 tosop(op,creg,xreg); | |
90 | 2421 crn = register_name(creg); |
2422 drn = register_name(edx); | |
165 | 2423 if (byte==1) { |
108 | 2424 printf("\tstb %s,0(%s)\n",crn,drn); |
245 | 2425 } else if (byte==SIZE_OF_SHORT) { |
165 | 2426 printf("\tsth %s,0(%s)\n",crn,drn); |
90 | 2427 } else { |
108 | 2428 printf("\tstw %s,0(%s)\n",crn,drn); |
90 | 2429 } |
2430 free_register(edx); | |
89 | 2431 emit_pop_free(xreg); |
285 | 2432 #endif |
89 | 2433 } |
2434 | |
2435 void | |
221 | 2436 tosop(int op,int creg,int oreg) |
89 | 2437 { |
221 | 2438 int dx = -1; |
252 | 2439 int ox = -1; |
95 | 2440 char *orn,*crn,*drn; |
221 | 2441 // creg = creg op oreg |
2442 | |
2443 use_int(creg); | |
103 | 2444 if(oreg==-1) { |
2445 error(-1); | |
2446 } else if (oreg<= -REG_LVAR_OFFSET) { | |
252 | 2447 ox = get_register(); if (ox<0) error(-1); |
2448 code_rlvar(oreg+REG_LVAR_OFFSET,ox); | |
2449 oreg = ox; | |
103 | 2450 } |
2451 | |
89 | 2452 switch(op) { |
2453 case LSHIFT: | |
2454 case ULSHIFT: | |
221 | 2455 shift("slw",creg,oreg); |
252 | 2456 if(ox!=-1) free_register(ox); |
89 | 2457 return; |
2458 case RSHIFT: | |
221 | 2459 shift("sraw",creg,oreg); |
252 | 2460 if(ox!=-1) free_register(ox); |
89 | 2461 return; |
2462 case URSHIFT: | |
221 | 2463 shift("srw",creg,oreg); |
252 | 2464 if(ox!=-1) free_register(ox); |
89 | 2465 return; |
2466 } | |
93 | 2467 orn = register_name(oreg); |
89 | 2468 crn = register_name(creg); |
2469 switch(op) { | |
2470 case ADD: | |
114 | 2471 printf("\tadd %s,%s,%s\n",crn,crn,orn); |
89 | 2472 break; |
2473 case SUB: | |
114 | 2474 printf("\tsub %s,%s,%s\n",crn,crn,orn); |
89 | 2475 break; |
112 | 2476 case CMP: |
291 | 2477 inc_cmpflag(); |
280 | 2478 printf("\tcmpw cr%d,%s,%s\n",cmpflag,crn,orn); |
2479 break; | |
2480 case UCMP: | |
291 | 2481 inc_cmpflag(); |
280 | 2482 printf("\tcmplw cr%d,%s,%s\n",cmpflag,crn,orn); |
112 | 2483 break; |
89 | 2484 case BAND: |
114 | 2485 printf("\tand %s,%s,%s\n",crn,crn,orn); |
89 | 2486 break; |
2487 case EOR: | |
114 | 2488 printf("\txor %s,%s,%s\n",crn,crn,orn); |
89 | 2489 break; |
2490 case BOR: | |
114 | 2491 printf("\tor %s,%s,%s\n",crn,crn,orn); |
89 | 2492 break; |
2493 case MUL: | |
116 | 2494 printf("\tmullw %s,%s,%s\n",crn,crn,orn); |
2495 break; | |
89 | 2496 case UMUL: |
114 | 2497 printf("\tmullw %s,%s,%s\n",crn,crn,orn); |
89 | 2498 break; |
2499 case DIV: | |
114 | 2500 printf("\tdivw %s,%s,%s\n",crn,crn,orn); |
90 | 2501 break; |
89 | 2502 case UDIV: |
114 | 2503 printf("\tdivwu %s,%s,%s\n",crn,crn,orn); |
89 | 2504 break; |
2505 case MOD: | |
90 | 2506 dx=get_register(); |
95 | 2507 drn = register_name(dx); |
116 | 2508 printf("\tdivw %s,%s,%s\n",drn,crn,orn); |
2509 printf("\tmullw %s,%s,%s\n",drn,drn,orn); | |
2510 printf("\tsubf %s,%s,%s\n",crn,drn,crn); | |
90 | 2511 break; |
89 | 2512 case UMOD: |
90 | 2513 dx=get_register(); |
95 | 2514 drn = register_name(dx); |
114 | 2515 printf("\tdivwu %s,%s,%s\n",drn,crn,orn); |
116 | 2516 printf("\tmullw %s,%s,%s\n",drn,drn,orn); |
2517 printf("\tsubf %s,%s,%s\n",crn,drn,crn); | |
89 | 2518 break; |
112 | 2519 default: |
2520 error(-1); | |
89 | 2521 } |
221 | 2522 if(dx!=-1) free_register(dx); |
252 | 2523 if(ox!=-1) free_register(ox); |
89 | 2524 } |
2525 | |
189 | 2526 int |
2527 code_const_op_p(int op,int v) | |
2528 { | |
240 | 2529 if (car(v)!=CONST) return 0; |
366 | 2530 if (op==DIV||op==UDIV) return ilog(v); |
2531 if (op==BAND||op==MOD||op==UMOD) return 0; | |
240 | 2532 v = cadr(v); |
214 | 2533 return (-32766<v&&v<32767); |
189 | 2534 } |
2535 | |
211 | 2536 void |
221 | 2537 oprtc(int op,int creg, int v) |
189 | 2538 { |
221 | 2539 char *crn; |
366 | 2540 int l; |
221 | 2541 use_int(creg); |
2542 crn = register_name(creg); | |
240 | 2543 v = cadr(v); |
221 | 2544 |
189 | 2545 switch(op) { |
2546 case LSHIFT: | |
2547 case ULSHIFT: | |
2548 printf("\tslwi %s,%s,%d\n",crn,crn,v); | |
2549 return; | |
366 | 2550 case DIV: |
2551 v = ilog(v); | |
189 | 2552 case RSHIFT: |
2553 printf("\tsrawi %s,%s,%d\n",crn,crn,v); | |
2554 return; | |
366 | 2555 case UDIV: |
2556 v = ilog(v); | |
189 | 2557 case URSHIFT: |
2558 printf("\tsrwi %s,%s,%d\n",crn,crn,v); | |
2559 return; | |
2560 case ADD: | |
2561 printf("\taddi %s,%s,lo16(%d)\n",crn,crn,v); | |
2562 break; | |
2563 case SUB: | |
221 | 2564 printf("\taddi %s,%s,lo16(-%d)\n",crn,crn,v); |
189 | 2565 break; |
2566 case CMP: | |
291 | 2567 inc_cmpflag(); |
280 | 2568 printf("\tcmpwi cr%d,%s,lo16(%d)\n",cmpflag,crn,v); |
189 | 2569 break; |
354 | 2570 case UCMP: |
2571 inc_cmpflag(); | |
2572 printf("\tcmplwi cr%d,%s,lo16(%d)\n",cmpflag,crn,v); | |
2573 break; | |
189 | 2574 case EOR: |
2575 printf("\txori %s,%s,lo16(%d)\n",crn,crn,v); | |
2576 break; | |
2577 case BOR: | |
2578 printf("\tori %s,%s,lo16(%d)\n",crn,crn,v); | |
2579 break; | |
2580 case MUL: | |
2581 case UMUL: | |
366 | 2582 if ((l=ilog(v))) { |
2583 printf("\tslwi %s,%s,%d\n",crn,crn,l); | |
2584 } else | |
2585 printf("\tmulli %s,%s,lo16(%d)\n",crn,crn,v); | |
189 | 2586 break; |
2587 default: | |
2588 error(-1); | |
2589 } | |
2590 } | |
89 | 2591 |
2592 void | |
221 | 2593 shift(char *op, int creg, int reg) |
89 | 2594 { |
221 | 2595 char *crn; |
93 | 2596 char *rrn = register_name(reg); |
221 | 2597 use_int(creg); |
2598 crn = register_name(creg); | |
186 | 2599 printf("\t%s %s,%s,%s\n",op,crn,crn,rrn); |
89 | 2600 } |
2601 | |
2602 void | |
221 | 2603 ld_indexx(int byte, int n, int xreg,int creg, int sign) |
89 | 2604 { |
221 | 2605 char *crn; |
2606 use_int(creg); | |
2607 crn = register_name(creg); | |
246 | 2608 printf("\t%s %s,%d(%s)\n",cload(byte),register_name(creg),n, |
90 | 2609 register_name(xreg)); |
246 | 2610 cext(sign,byte,creg); |
89 | 2611 } |
2612 | |
95 | 2613 int |
2614 code_csvalue() | |
2615 { | |
2616 return creg; | |
2617 } | |
2618 | |
89 | 2619 void |
287 | 2620 code_cmpdimm(int e, int csreg,int label,int cond) |
89 | 2621 { |
366 | 2622 int reg; |
89 | 2623 /* used in dosiwtch() */ |
2624 if(chk) return; | |
291 | 2625 inc_cmpflag(); |
2626 if (-32767<e&&e<32767) { | |
2627 printf("\tcmpwi cr%d,%s,%d\n",cmpflag,register_name(csreg),e); | |
2628 jcond(label,cond); | |
2629 } else { | |
366 | 2630 reg = get_register(); |
2631 code_const(list2(CONST,e),reg); | |
2632 printf("\tcmpw cr%d,%s,%s\n",cmpflag,register_name(csreg),register_name(reg)); | |
2633 jcond(label,cond); | |
2634 free_register(reg); | |
291 | 2635 } |
89 | 2636 } |
2637 | |
2638 void | |
2639 code_opening(char *filename) | |
2640 { | |
2641 printf("\t.file \"%s\"\n",filename); | |
108 | 2642 /* printf("\t.version\t\"01.01\"\n"); */ |
89 | 2643 /* printf("gcc2_compiled.:\n"); */ |
2644 printf(".text\n"); | |
2645 } | |
2646 | |
288 | 2647 #define CRBITSIZ 4 |
2648 | |
2649 static int | |
2650 rexpr_bool(int e1,int reg) | |
2651 { | |
2652 int t,flag=-1,eq=-1,neg=-1; | |
2653 char *rn; | |
2654 switch(car(e1)) { | |
2655 case GT: t=INT; flag = 2; break; | |
2656 case UGT: t=0; flag = 2; break; | |
2657 case GE: t=INT; flag = 2; eq=3; break; | |
2658 case UGE: t=0; flag = 2; eq=3; break; | |
2659 case LT: t=INT; flag = 1; break; | |
2660 case ULT: t=0; flag = 1; break; | |
2661 case LE: t=INT; flag = 1; eq=3; break; | |
2662 case ULE: t=0; flag = 1; eq=3; break; | |
2663 case EQ: t=INT; flag = 3; break; | |
289 | 2664 case NEQ: t=INT; flag = 3; neg=3; break; |
288 | 2665 default: return 0; |
2666 } | |
2667 g_expr(list3((t==INT?CMP:UCMP),cadr(e1),caddr(e1))); | |
2668 use_int(reg); | |
2669 rn = register_name(reg); | |
289 | 2670 t = CRBITSIZ*cmpflag; |
288 | 2671 if (eq>0) { |
289 | 2672 printf("\tcror %d,%d,%d\n",t+flag-1,t+eq-1,t+flag-1); |
2673 } | |
2674 if (neg>0) { | |
2675 neg = t+neg-1, | |
2676 printf("\tcrnor %d,%d,%d\n",neg,neg,neg); | |
288 | 2677 } |
2678 printf("\tmfcr %s\n",rn); | |
289 | 2679 printf("\trlwinm %s,%s,%d,1\n",rn,rn,t+flag); |
288 | 2680 return 1; |
2681 } | |
2682 | |
89 | 2683 void |
280 | 2684 rexpr(int e1, int l1, int cond,int t) |
89 | 2685 { |
280 | 2686 char *s; |
2687 switch(car(e1)) { | |
2688 case GT: s=code_gt(cond); break; | |
2689 case UGT: s=code_ugt(cond); break; | |
2690 case GE: s=code_ge(cond); break; | |
2691 case UGE: s=code_uge(cond); break; | |
2692 case LT: s=code_ge(!cond); break; | |
2693 case ULT: s=code_uge(!cond);break; | |
2694 case LE: s=code_gt(!cond); break; | |
2695 case ULE: s=code_ugt(!cond);break; | |
2696 case EQ: s=code_eq(cond); break; | |
2697 case NEQ: s=code_eq(!cond); break; | |
2698 default: error(-1); | |
2699 } | |
2700 g_expr(list3((t==INT?CMP:UCMP),cadr(e1),caddr(e1))); | |
2701 printf("\tb%s cr%d,L_%d\n",s,cmpflag,l1); | |
89 | 2702 } |
2703 | |
287 | 2704 static void |
89 | 2705 jcond(int l, char cond) |
2706 { | |
2707 if (chk) return; | |
297 | 2708 if (cond==LT) { |
2709 printf("\tb%s cr%d,L_%d\n",code_ge(0),cmpflag,l); | |
2710 } else if (cond==1||cond==0) { | |
2711 printf("\tb%s cr%d,L_%d\n",cond?"ne":"eq",cmpflag,l); | |
2712 } else error(-1); | |
89 | 2713 } |
2714 | |
2715 void | |
2716 jmp(int l) | |
2717 { | |
2718 control=0; | |
2719 if (chk) return; | |
102 | 2720 printf("\tb\tL_%d\n",l); |
89 | 2721 } |
2722 | |
327 | 2723 extern void |
89 | 2724 gen_comment(char *s) |
2725 { | |
2726 if (chk) return; | |
307 | 2727 printf("## %s",s); |
89 | 2728 } |
2729 | |
2730 void | |
2731 code_enter(char *name) | |
2732 { | |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2733 if (output_mode!=TEXT_EMIT_MODE) |
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2734 text_mode(); |
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2735 else |
108 | 2736 printf("\t.align 2\n"); |
89 | 2737 if (stmode!=STATIC) |
102 | 2738 printf(".globl _%s\n",name); |
126 | 2739 #ifdef DOT_SIZE |
89 | 2740 printf("\t.type\t%s,@function\n",name); |
126 | 2741 #endif |
101 | 2742 printf("_%s:\n",name); |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2743 code_disp_label=fwdlabel(); |
128 | 2744 printf("\tla r1,lo16(L_%d)(r30)\n",code_disp_label); |
126 | 2745 printf("\tbcl 20,31,L_%d\n",code_base = fwdlabel()); |
2746 fwddef(code_base); | |
2747 printf("\tmflr r31\n"); | |
119 | 2748 max_func_args = 0; |
89 | 2749 } |
2750 | |
2751 | |
2752 void | |
2753 code_enter1(int args) | |
2754 { | |
222 | 2755 // set_lreg(LREG_LREGISTER,0); |
207 | 2756 set_ireg(CREG_REGISTER,0); |
106 | 2757 set_freg(FREG_FREGISTER,0); |
89 | 2758 } |
2759 | |
2760 void | |
2761 code_leave(char *name) | |
2762 { | |
128 | 2763 int r1_offsetv; |
245 | 2764 disp&= -SIZE_OF_INT; |
2765 r1_offsetv = -disp+max_func_args*SIZE_OF_INT+code_disp_offset; | |
128 | 2766 |
2767 printf(".set L_%d,%d\n",code_disp_label,-r1_offsetv); | |
89 | 2768 local_table(); |
208 | 2769 // free_all_register(); |
89 | 2770 } |
2771 | |
2772 void | |
2773 enter(char *name) | |
2774 { | |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2775 if (output_mode!=TEXT_EMIT_MODE) |
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2776 text_mode(); |
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2777 else |
108 | 2778 printf("\t.align 2\n"); |
89 | 2779 if (stmode!=STATIC) |
101 | 2780 printf(".globl _%s\n",name); |
108 | 2781 /* |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2782 printf("\t.type\t%s,@function\n",name); |
108 | 2783 */ |
101 | 2784 printf("_%s:\n",name); |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2785 code_setup=fwdlabel(); |
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2786 printf("\tmflr r0\n"); |
102 | 2787 printf("\tbl L_%d\n",code_setup); |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2788 code_base=fwdlabel(); |
111 | 2789 fwddef(code_base); |
116 | 2790 r1_offset_label = fwdlabel(); |
2791 lvar_offset_label = fwdlabel(); | |
375 | 2792 #if 0 |
2793 printf("\taddi r30,r1,lo16(-L_%d)\n",lvar_offset_label); | |
116 | 2794 printf("\tstwu r1,lo16(-L_%d)(r1)\n",r1_offset_label); |
375 | 2795 // printf("\tmr r30,r1\n"); |
2796 #else | |
2797 printf("\taddi r30,r1,lo16(-L_%d)\n",lvar_offset_label); | |
2798 printf("\tlis r31,ha16(-L_%d)\n",r1_offset_label); | |
2799 printf("\taddi r31,r31,lo16(-L_%d)\n",r1_offset_label); | |
2800 printf("\tstwux r1,r1,r31\n"); | |
2801 #endif | |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2802 printf("\tmflr r31\n"); |
116 | 2803 max_func_args = 0; |
89 | 2804 } |
2805 | |
2806 void | |
2807 enter1() | |
2808 { | |
182 | 2809 text_mode(); |
208 | 2810 // set_lreg(LREG_LREGISTER,0); |
207 | 2811 set_ireg(CREG_REGISTER,0); |
106 | 2812 set_freg(FREG_FREGISTER,0); |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2813 } |
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2814 |
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2815 int |
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2816 reg_save_offset() |
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2817 { |
108 | 2818 return -( |
245 | 2819 (REAL_MAX_REGISTER-(REG_VAR_BASE-max_reg_var))*SIZE_OF_INT+ |
2820 (REAL_MAX_FREGISTER-(FREG_VAR_BASE-max_freg_var))*SIZE_OF_DOUBLE | |
108 | 2821 ); |
89 | 2822 } |
2823 | |
2824 void | |
2825 leave(int control, char *name) | |
2826 { | |
130 | 2827 int retcont1=0,sz; |
128 | 2828 |
2829 if (max_freg_var>=0 && max_freg_var<=3) max_freg_var=3; | |
2830 reg_save = reg_save_offset(); | |
111 | 2831 |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2832 if (control) { |
108 | 2833 code_set_return_register(1); |
89 | 2834 } |
126 | 2835 if (retcont) { |
2836 if (control) jmp(retlabel); | |
128 | 2837 retcont1 = fwdlabel(); |
126 | 2838 fwddef(retcont); |
2839 if (cadr(fnptr->ty)==FLOAT||cadr(fnptr->ty)==DOUBLE) { | |
2840 printf("\tfmr f1,f31\n"); | |
128 | 2841 } else if (cadr(fnptr->ty)>0&&( |
2842 car(cadr(fnptr->ty))==STRUCT || | |
2843 car(cadr(fnptr->ty))==UNION)) { | |
2844 sz = size(cadr(fnptr->ty)); | |
2845 printf("\tli r7,%d\n",sz); | |
2846 printf("\tsubl r6,r7,r30\n"); | |
245 | 2847 printf("\tlwz r3,lo16(%d)(r30)\n",(my_func_args-1)*SIZE_OF_INT); |
128 | 2848 emit_copy(6,3,sz,0,1,1); |
126 | 2849 } else if (cadr(fnptr->ty)!=VOID) { |
2850 printf("\tmr r3,r29\n"); | |
2851 } | |
128 | 2852 #if !R1SAVE |
2853 printf("\tla r1,lo16(%d)(r30)\n", | |
245 | 2854 -reg_save+my_func_args*SIZE_OF_INT); |
128 | 2855 #endif |
2856 printf("\tb L_%d\n",retcont1); | |
126 | 2857 } |
89 | 2858 fwddef(retlabel); |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2859 printf("\tlwz r1,0(r1)\n"); |
128 | 2860 if (retcont) { |
2861 fwddef(retcont1); | |
2862 } | |
110 | 2863 if (max_freg_var>=0) { |
2864 printf("\tlmw r%d,%d(r1)\n", | |
111 | 2865 REG_VAR_BASE-max_reg_var,reg_save); |
2866 freg_save = 72-(REAL_MAX_FREGISTER-(FREG_VAR_BASE-max_freg_var))*4; | |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2867 printf("\tb restFP+%d ; restore f%d-f31\n", |
111 | 2868 freg_save, |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2869 FREG_VAR_BASE-max_freg_var); |
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2870 } else { |
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2871 printf("\tlwz r0,8(r1)\n"); |
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2872 printf("\tmtlr r0\n"); |
110 | 2873 printf("\tlmw r%d,%d(r1)\n", |
116 | 2874 REG_VAR_BASE-max_reg_var,reg_save); |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2875 printf("\tblr\n"); |
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2876 } |
89 | 2877 |
245 | 2878 disp &= -SIZE_OF_INT; |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2879 fwddef(code_setup); |
110 | 2880 printf("\tstmw r%d,%d(r1)\n", |
116 | 2881 REG_VAR_BASE-max_reg_var,reg_save); |
110 | 2882 printf("\tstw r0,8(r1)\n"); |
2883 if (max_freg_var>=0) | |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2884 printf("\tb saveFP+%d ; save f%d-f31\n", |
111 | 2885 freg_save, |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2886 FREG_VAR_BASE-max_freg_var); |
110 | 2887 else { |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2888 printf("\tblr\n"); |
110 | 2889 } |
100
a9e6f2a2946f
Wrote all code for PowerPC and no compile error. Let's fix all bugs...
kono
parents:
99
diff
changeset
|
2890 |
116 | 2891 code_offset_set(); |
89 | 2892 local_table(); |
2893 labelno++; | |
208 | 2894 // free_all_register(); |
89 | 2895 } |
2896 | |
2897 | |
2898 void | |
107 | 2899 code_set_return_register(int mode) { |
111 | 2900 if (cadr(fnptr->ty)==DOUBLE||cadr(fnptr->ty)==FLOAT) { |
107 | 2901 set_freg(RET_FREGISTER,mode); |
206 | 2902 } else if (cadr(fnptr->ty)==LONGLONG||cadr(fnptr->ty)==ULONGLONG) { |
2903 set_lreg(RET_LREGISTER,mode); | |
147 | 2904 } else if (cadr(fnptr->ty)==VOID) { |
103 | 2905 } else { |
207 | 2906 set_ireg(RET_REGISTER,mode); |
103 | 2907 } |
89 | 2908 } |
2909 | |
187 | 2910 int |
2911 code_get_fixed_creg(int reg,int type) { | |
2912 return creg; | |
2913 } | |
2914 | |
89 | 2915 void |
187 | 2916 code_set_fixed_creg(int reg,int mode,int type) { |
108 | 2917 if (type==FLOAT||type==DOUBLE) { |
187 | 2918 set_freg(reg,mode); |
206 | 2919 } else if (type==LONGLONG||type==ULONGLONG) { |
195 | 2920 set_lreg(reg,mode); |
210 | 2921 // use_reg(reg); |
108 | 2922 } else { |
207 | 2923 set_ireg(reg,mode); |
108 | 2924 } |
107 | 2925 } |
2926 | |
2927 void | |
89 | 2928 gen_gdecl(char *n, int gpc) |
2929 { | |
102 | 2930 /* |
89 | 2931 if (stmode!=STATIC) |
99 | 2932 printf(".globl _%s\n",n); |
102 | 2933 */ |
89 | 2934 } |
2935 | |
340 | 2936 extern void |
2937 ascii(char *s) | |
2938 { | |
2939 printf("\t.ascii \""); | |
2940 while(*s) { | |
2941 if (*s=='\n') | |
2942 printf("%cn",92); | |
2943 else if (*s<' ') | |
2944 printf("%c%03o",92,*s); | |
2945 else if (*s=='\\') | |
2946 printf("\\\\"); | |
2947 else if (*s==34) | |
2948 printf("%c%c",92,34); | |
2949 else | |
2950 printf("%c",*s); | |
2951 s++; | |
2952 } | |
2953 printf("\\0%c\n\t.align 2\n",34); | |
2954 } | |
2955 | |
2956 extern int | |
2957 emit_string_label() { | |
2958 int lb; | |
2959 | |
2960 printf(".data\t\n.cstring\n\t.align 2\n"); | |
2961 lb=fwdlabel(); | |
2962 printf("L_%d:\n",lb); | |
2963 output_mode = RODATA_EMIT_MODE; | |
2964 return lb; | |
2965 } | |
2966 | |
2967 extern void | |
89 | 2968 align(int t) |
2969 { | |
2970 if (t!=CHAR) { | |
2971 if (data_alignment & 1) | |
2972 printf("\t.align 2\n"); | |
2973 data_alignment = 0; | |
2974 } | |
2975 } | |
2976 | |
340 | 2977 extern void |
2978 emit_global(char *name,int t) | |
2979 { | |
2980 printf(".globl\t_%s\n",name); | |
2981 data_mode(name); | |
2982 align(t); | |
2983 printf("_%s:\n",name); | |
2984 } | |
2985 | |
2986 extern void | |
2987 emit_space(int sp) | |
2988 { | |
2989 data_mode(0); | |
2990 printf("\t.space\t%d\n",sp); | |
2991 } | |
2992 | |
2993 extern void | |
2994 emit_char(int d) | |
89 | 2995 { |
340 | 2996 data_mode(0); |
2997 printf("\t.byte %d\n",d); | |
2998 } | |
2999 | |
3000 extern void | |
3001 emit_short(int d) | |
3002 { | |
3003 data_mode(0); | |
3004 printf("\t.short %d\n",d); | |
3005 } | |
3006 | |
3007 extern void | |
3008 emit_int(int d) | |
3009 { | |
3010 data_mode(0); | |
3011 printf("\t.long %d\n",d); | |
3012 } | |
3013 | |
3014 extern void | |
3015 emit_longlong(int e) | |
3016 { | |
206 | 3017 #if LONGLONG_CODE |
341 | 3018 long long d = lcadr(e); |
340 | 3019 data_mode(0); |
3020 printf("\t.long\t0x%x,0x%x\n",code_l2(d),code_l1(d)); | |
195 | 3021 #endif |
340 | 3022 } |
3023 | |
3024 extern void | |
3025 emit_double(int e) | |
3026 { | |
195 | 3027 #if FLOAT_CODE |
341 | 3028 double d = dcadr(e); |
340 | 3029 data_mode(0); |
3030 printf("\t.long\t0x%x,0x%x\n",code_d2(d),code_d1(d)); | |
339 | 3031 #endif |
340 | 3032 } |
3033 | |
3034 extern void | |
3035 emit_float(int e) | |
3036 { | |
3037 #if FLOAT_CODE | |
341 | 3038 float f = dcadr(e); |
340 | 3039 data_mode(0); |
3040 printf("\t.long\t0x%x\n",*(int *)&f); | |
3041 #endif | |
3042 } | |
3043 | |
3044 extern void | |
367 | 3045 emit_address(char *s,int offset) |
340 | 3046 { |
3047 data_mode(0); | |
367 | 3048 if (offset) |
3049 printf("\t.long _%s+%d\n",s,offset); | |
3050 else | |
3051 printf("\t.long _%s\n",s); | |
340 | 3052 } |
3053 | |
3054 extern void | |
3055 emit_label(int labelno) | |
3056 { | |
3057 data_mode(0); | |
3058 printf("\t.long L_%d\n",labelno); | |
3059 } | |
3060 | |
3061 extern void | |
89 | 3062 emit_data_closing(NMTBL *n) |
3063 { | |
126 | 3064 #ifdef DOT_SIZE |
89 | 3065 int lb; |
126 | 3066 #endif |
89 | 3067 if (chk) return; |
3068 if (mode==GDECL) { | |
3069 data_mode(0); | |
126 | 3070 #ifdef DOT_SIZE |
89 | 3071 lb=fwdlabel(); |
102 | 3072 printf("L_%d:\n",lb); |
3073 printf("\t.size\t%s,L_%d-%s\n",n->nm,lb,n->nm); | |
126 | 3074 #endif |
89 | 3075 } |
3076 } | |
3077 | |
3078 void | |
3079 global_table(void) | |
3080 { | |
3081 NMTBL *n; | |
98 | 3082 int init; char *extrn; |
89 | 3083 init=0; |
350 | 3084 for(n = global_list;n!=&null_nptr;n = n->next) { |
109 | 3085 if ((n->sc == GVAR) && n->dsp != -1) { |
89 | 3086 /* n->dsp = -1 means initialized global */ |
3087 if (init==0) { | |
3088 data_mode(0); | |
3089 init=1; | |
3090 } | |
97 | 3091 printf(".comm _%s,%d\n",n->nm,size(n->ty)); |
109 | 3092 } else if ((n->sc==STATIC) && n->dsp != -1) { |
3093 /* n->dsp = -1 means initialized global */ | |
3094 if (init==0) { | |
3095 data_mode(0); | |
3096 init=1; | |
3097 } | |
3098 printf(".lcomm _%s,%d\n",n->nm,size(n->ty)); | |
97 | 3099 } |
3100 } | |
350 | 3101 for(n = global_list;n!=&null_nptr;n = n->next) { |
103 | 3102 if (is_code(n)||is_function(n)) { |
97 | 3103 extrn = n->nm; |
103 | 3104 if (n->sc==EXTRN1) { |
3105 data_mode(0); | |
3106 printf(".picsymbol_stub\n"); | |
97 | 3107 printf("L_%s$stub:\n",extrn); |
3108 printf("\t.indirect_symbol _%s\n",extrn); | |
3109 printf("\tmflr r0\n"); | |
3110 printf("\tbcl 20,31,L0$_%s\n",extrn); | |
3111 printf("L0$_%s:\n",extrn); | |
3112 printf("\tmflr r11\n"); | |
3113 printf("\taddis r11,r11,ha16(L_%s$lazy_ptr-L0$_%s)\n",extrn,extrn); | |
3114 printf("\tmtlr r0\n"); | |
3115 printf("\tlwz r12,lo16(L_%s$lazy_ptr-L0$_%s)(r11)\n",extrn,extrn); | |
3116 printf("\tmtctr r12\n"); | |
3117 printf("\taddi r11,r11,lo16(L_%s$lazy_ptr-L0$_%s)\n",extrn,extrn); | |
3118 printf("\tbctr\n"); | |
3119 printf(".data\n"); | |
3120 printf(".lazy_symbol_pointer\n"); | |
3121 printf("L_%s$lazy_ptr:\n",extrn); | |
3122 printf("\t.indirect_symbol _%s\n",extrn); | |
3123 printf("\t.long dyld_stub_binding_helper\n"); | |
103 | 3124 } else if (n->sc==FUNCTION||n->sc==CODE) { |
3125 text_mode(); | |
3126 printf("\t.set L_%s$stub,_%s\n",extrn,extrn); | |
109 | 3127 data_mode(0); |
111 | 3128 printf("L_%s$non_lazy_ptr:\n\t.long\t_%s\n",extrn,extrn); |
108 | 3129 } |
97 | 3130 } |
3131 } | |
109 | 3132 init=0; |
350 | 3133 for(n = global_list;n!=&null_nptr;n = n->next) { |
109 | 3134 if (n->sc == GVAR) { |
3135 if (init==0) { | |
119 | 3136 printf(".data\n"); |
109 | 3137 init=1; |
3138 } | |
116 | 3139 printf("L_%s$non_lazy_ptr:\n\t.long\t_%s\n",n->nm,n->nm); |
109 | 3140 } |
3141 } | |
97 | 3142 init = 0; |
350 | 3143 for(n = global_list;n!=&null_nptr;n = n->next) { |
116 | 3144 if (is_code(n)||is_function(n)) continue; |
109 | 3145 if (n->sc==EXTRN1) { |
97 | 3146 if(init==0) { |
119 | 3147 printf(".data\n"); |
97 | 3148 printf(".non_lazy_symbol_pointer\n"); |
3149 init=1; | |
3150 } | |
3151 printf("L_%s$non_lazy_ptr:\n",n->nm); | |
3152 printf("\t.indirect_symbol _%s\n",n->nm); | |
3153 printf("\t.long\t0\n"); | |
89 | 3154 } |
3155 } | |
3156 } | |
3157 | |
3158 void | |
3159 local_table(void) | |
3160 { | |
3161 NMTBL *n; | |
3162 int init; | |
3163 init=0; | |
3164 /* static local variables */ | |
350 | 3165 for(n = local_static_list;n!=&null_nptr;n = n->next) { |
89 | 3166 if (n->sc == GVAR) { |
3167 if (init==0) { | |
3168 data_mode(0); | |
3169 init=1; | |
3170 } | |
156 | 3171 if (n->dsp != -1) /* initialized static */ |
3172 printf(".lcomm _%s,%d\n",n->nm,size(n->ty)); | |
3173 printf("L_%s$non_lazy_ptr:\n\t.long\t_%s\n",n->nm,n->nm); | |
89 | 3174 } |
3175 } | |
3176 } | |
3177 | |
3178 void | |
3179 text_mode(void) | |
3180 { | |
3181 if (output_mode!=TEXT_EMIT_MODE) { | |
3182 printf(".text\n"); | |
3183 printf("\t.align 2\n"); | |
3184 output_mode = TEXT_EMIT_MODE; | |
3185 } | |
3186 } | |
3187 | |
3188 void | |
3189 data_mode(char *name) | |
3190 { | |
3191 if (output_mode!=DATA_EMIT_MODE) { | |
3192 printf(".data\n"); | |
3193 output_mode = DATA_EMIT_MODE; | |
3194 } | |
108 | 3195 /* |
89 | 3196 if (name) |
3197 printf("\t.type\t%s,@object\n",name); | |
108 | 3198 */ |
89 | 3199 } |
3200 | |
195 | 3201 #if FLOAT_CODE |
3202 | |
89 | 3203 /* floating point */ |
3204 | |
96 | 3205 static int float_one_lib_used=0; |
3206 static char *float_one_lib[] = { | |
3207 ".data", | |
108 | 3208 /* ".literal8", */ |
96 | 3209 " .align 3", |
3210 "__float_one:", | |
3211 " .long 1065353216", | |
3212 ".text", | |
109 | 3213 /* ".set L__float_one$non_lazy_ptr,__float_one", */ |
96 | 3214 0 |
3215 }; | |
97 | 3216 static int float_zero_lib_used=0; |
3217 static char *float_zero_lib[] = { | |
3218 ".data", | |
108 | 3219 /* ".literal8", */ |
97 | 3220 " .align 3", |
3221 "__float_zero:", | |
3222 " .long 0", | |
3223 ".text", | |
109 | 3224 /* ".set L__float_zero$non_lazy_ptr,__float_zero", */ |
97 | 3225 0 |
3226 }; | |
3227 | |
89 | 3228 char * |
3229 fstore(int d) | |
3230 { | |
90 | 3231 return (d?"stfd":"stfs"); |
89 | 3232 } |
3233 | |
3234 char * | |
3235 fload(int d) | |
3236 { | |
90 | 3237 return d?"lfd":"lfs"; |
89 | 3238 } |
3239 | |
95 | 3240 void |
287 | 3241 code_cmp_dregister(int e2,int d,int label,int cond) |
95 | 3242 { |
99 | 3243 char *frn,*rrn,*grn; |
3244 int greg,r; | |
138 | 3245 grn = register_name(greg = get_dregister(d)); |
221 | 3246 use_float(d,e2); |
132 | 3247 frn = register_name(e2); |
99 | 3248 float_zero_lib_used=1; |
109 | 3249 r = get_ptr_cache(&float_zero); |
99 | 3250 rrn = register_name(r); |
108 | 3251 printf("\tlfs %s,0(%s)\n",grn,rrn); |
291 | 3252 inc_cmpflag(); |
280 | 3253 printf("\tfcmpu cr%d,%s,%s\n",cmpflag,grn,frn); |
147 | 3254 free_register(greg); |
287 | 3255 jcond(label,cond); |
99 | 3256 return; |
95 | 3257 } |
3258 | |
3259 void | |
138 | 3260 code_dregister(int e2,int freg,int d) |
95 | 3261 { |
221 | 3262 use_float(d,freg); |
147 | 3263 if (freg!=e2) { |
3264 if (is_int_reg(e2)) error(-1); | |
108 | 3265 printf("\tfmr %s,%s\n",fregister_name(freg),fregister_name(e2)); |
147 | 3266 } |
95 | 3267 } |
3268 | |
211 | 3269 void |
3270 code_dassign_gvar(int e2,int freg,int d) | |
89 | 3271 { |
221 | 3272 use_float(d,freg); |
367 | 3273 code_ldf(fstore(d),fregister_name(freg),cadr(e2), |
3274 get_ptr_cache((NMTBL*)caddr(e2))); | |
89 | 3275 } |
3276 | |
211 | 3277 void |
3278 code_dassign_lvar(int e2,int freg,int d) | |
89 | 3279 { |
221 | 3280 use_float(d,freg); |
119 | 3281 lvar_intro(e2); |
3282 printf("\t%s %s,",fstore(d),fregister_name(freg)); | |
3283 lvar(e2); | |
89 | 3284 } |
3285 | |
211 | 3286 void |
3287 code_dassign(int e2,int freg,int d) | |
89 | 3288 { |
221 | 3289 use_float(d,freg); |
108 | 3290 printf("\t%s %s,0(%s)\n",fstore(d),fregister_name(freg),register_name(e2)); |
89 | 3291 } |
3292 | |
111 | 3293 void |
138 | 3294 code_dassign_dregister(int e2,int d,int freg) { |
221 | 3295 use_float(d,freg); |
147 | 3296 if (e2!=freg) { |
111 | 3297 printf("\tfmr %s,%s\n",fregister_name(e2),fregister_name(freg)); |
147 | 3298 } |
111 | 3299 } |
3300 | |
89 | 3301 static double d0 = 1.0; |
3302 | |
3303 int | |
3304 code_d1(double d) | |
3305 { | |
3306 int *i = (int *)&d0; int *j = (int *)&d; | |
99 | 3307 return (i[1] == 0x3ff00000)?j[0]:j[1]; |
89 | 3308 } |
3309 | |
3310 int | |
3311 code_d2(double d) | |
3312 { | |
3313 int *i = (int *)&d0; int *j = (int *)&d; | |
99 | 3314 return (i[1] == 0x3ff00000)?j[1]:j[0]; |
89 | 3315 } |
3316 | |
133 | 3317 int |
3318 code_f(double d) | |
3319 { | |
3320 float f = d; | |
3321 int *j = (int *)&f; | |
3322 return *j; | |
3323 } | |
3324 | |
211 | 3325 void |
3326 | |
138 | 3327 code_dconst(int e2,int freg,int d) |
89 | 3328 { |
3329 int lb; | |
138 | 3330 double value = dcadr(e2); |
90 | 3331 int r; |
97 | 3332 char *rrn,*frn; |
221 | 3333 |
3334 use_float(d,freg); | |
97 | 3335 frn = fregister_name(freg); |
138 | 3336 if (value==0.0) { |
97 | 3337 float_zero_lib_used=1; |
109 | 3338 r = get_ptr_cache(&float_zero); |
98 | 3339 rrn = register_name(r); |
108 | 3340 printf("\tlfs %s,0(%s)\n",frn,rrn); |
97 | 3341 return; |
89 | 3342 } |
138 | 3343 if (value==1.0) { |
97 | 3344 float_one_lib_used=1; |
109 | 3345 r = get_ptr_cache(&float_one); |
98 | 3346 rrn = register_name(r); |
108 | 3347 printf("\tlfs %s,0(%s)\n",frn,rrn); |
97 | 3348 return; |
89 | 3349 } |
97 | 3350 rrn = register_name((r=get_register())); |
230 | 3351 use_reg(r); // to clear ptr cache |
108 | 3352 printf(" \t.data\n\t.align 3\n"); |
89 | 3353 lb=fwdlabel(); |
102 | 3354 printf("L_%d:\n",lb); |
138 | 3355 if (d) { |
3356 printf("\t.long\t0x%x,0x%x\n",code_d2(value),code_d1(value)); | |
133 | 3357 } else { |
138 | 3358 printf("\t.long\t0x%x\n",code_f(value)); |
133 | 3359 } |
89 | 3360 if (output_mode==TEXT_EMIT_MODE) { |
3361 printf(".text\n"); | |
3362 } else { | |
3363 text_mode(); | |
3364 } | |
102 | 3365 printf("\taddis %s,r31,ha16(L_%d-L_%d)\n",rrn,lb,code_base); |
3366 printf("\tla %s,lo16(L_%d-L_%d)(%s)\n",rrn,lb,code_base,rrn); | |
138 | 3367 if (d) { |
133 | 3368 printf("\tlfd %s,0(%s)\n",frn,rrn); |
3369 } else { | |
3370 printf("\tlfs %s,0(%s)\n",frn,rrn); | |
3371 } | |
90 | 3372 free_register(r); |
89 | 3373 } |
3374 | |
133 | 3375 |
211 | 3376 void |
3377 code_dneg(int freg,int d) | |
89 | 3378 { |
221 | 3379 char *frn; |
3380 use_float(d,freg); | |
3381 frn = fregister_name(freg); | |
95 | 3382 printf("\tfneg %s,%s\n",frn,frn); |
89 | 3383 } |
3384 | |
211 | 3385 void |
221 | 3386 code_d2i() |
89 | 3387 { |
147 | 3388 char *frn; |
3389 char *crn; | |
245 | 3390 int e2 = new_lvar(SIZE_OF_DOUBLE); |
147 | 3391 |
221 | 3392 use_double0(); |
3393 frn = fregister_name(freg); | |
3394 use_int0(); | |
147 | 3395 crn = register_name(creg); |
3396 | |
119 | 3397 free_lvar(e2); |
93 | 3398 printf("\tfctiwz %s,%s\n",frn,frn); |
119 | 3399 lvar_intro(e2); |
3400 printf("\tstfd %s,",frn); lvar(e2); | |
245 | 3401 lvar_intro(e2+SIZE_OF_DOUBLE-SIZE_OF_INT); |
3402 printf("\tlwz %s,",crn); lvar(e2+SIZE_OF_DOUBLE-SIZE_OF_INT); | |
89 | 3403 } |
3404 | |
91 | 3405 static int i2d_lib_used=0; |
3406 static char *i2d_lib[] = { | |
3407 ".data", | |
108 | 3408 /* ".literal8", */ |
91 | 3409 " .align 3", |
3410 "__i2dLC0:", | |
3411 " .long 1127219200", | |
3412 " .long -2147483648", | |
3413 ".text", | |
3414 " .align 2", | |
111 | 3415 "i2d_:", |
91 | 3416 " mflr r0", |
3417 " bcl 20,31,__i2dL1$pb", | |
3418 "__i2dL1$pb:", | |
3419 " mflr r10", | |
3420 " mtlr r0", | |
3421 " xoris r3,r3,0x8000", | |
375 | 3422 " stw r3,-28(r1)", |
91 | 3423 " lis r0,0x4330", |
375 | 3424 " stw r0,-32(r1)", |
3425 " lfd f0,-32(r1)", | |
91 | 3426 " addis r9,r10,ha16(__i2dLC0-__i2dL1$pb)", |
3427 " lfd f1,lo16(__i2dLC0-__i2dL1$pb)(r9)", | |
3428 " fsub f1,f0,f1", | |
3429 " blr", | |
3430 0 | |
3431 }; | |
3432 | |
211 | 3433 void |
221 | 3434 code_i2d() |
89 | 3435 { |
95 | 3436 i2d_lib_used = 1; |
113 | 3437 clear_ptr_cache(); |
3438 code_save_stacks(); | |
207 | 3439 set_ireg(RET_REGISTER,1); |
91 | 3440 printf("\tbl i2d_\n"); |
104 | 3441 set_freg(RET_FREGISTER,0); |
89 | 3442 } |
3443 | |
91 | 3444 static int d2u_lib_used=0; |
3445 static char *d2u_lib[] = { | |
108 | 3446 /* ".literal8", */ |
91 | 3447 " .align 3", |
3448 "__d2uLC0:", | |
3449 " .long 1105199104", | |
3450 " .long 0", | |
3451 ".text", | |
3452 " .align 2", | |
111 | 3453 "d2u_:", |
91 | 3454 " mflr r0", |
3455 " bcl 20,31,__d2uL1$pb", | |
3456 "__d2uL1$pb:", | |
3457 " mflr r10", | |
3458 " mtlr r0", | |
3459 " addis r9,r10,ha16(__d2uLC0-__d2uL1$pb)", | |
3460 " lfd f0,lo16(__d2uLC0-__d2uL1$pb)(r9)", | |
3461 " fcmpu cr0,f1,f0", | |
3462 " cror 2,1,2", | |
3463 " beq- cr0,__d2uL2", | |
3464 " fctiwz f0,f1", | |
375 | 3465 " stfd f0,-32(r1)", |
3466 " lwz r3,-28(r1)", | |
91 | 3467 " blr", |
3468 "__d2uL2:", | |
3469 " addis r9,r10,ha16(__d2uLC0-__d2uL1$pb)", | |
3470 " lfd f0,lo16(__d2uLC0-__d2uL1$pb)(r9)", | |
3471 " fsub f0,f1,f0", | |
3472 " fctiwz f0,f0", | |
375 | 3473 " stfd f0,-24(r1)", |
3474 " lwz r3,-20(r1)", | |
91 | 3475 " xoris r3,r3,0x8000", |
3476 " blr", | |
3477 0 | |
3478 }; | |
3479 | |
211 | 3480 void |
221 | 3481 code_d2u() |
89 | 3482 { |
113 | 3483 code_save_stacks(); |
3484 clear_ptr_cache(); | |
91 | 3485 d2u_lib_used=1; |
104 | 3486 set_freg(RET_FREGISTER,1); |
111 | 3487 printf("\tbl d2u_\n"); |
207 | 3488 set_ireg(RET_REGISTER,0); |
91 | 3489 } |
90 | 3490 |
91 | 3491 static int u2d_lib_used=0; |
3492 static char *u2d_lib[] = { | |
3493 ".data", | |
108 | 3494 /* ".literal8", */ |
91 | 3495 " .align 3", |
3496 "__u2dLC1:", | |
3497 " .long 1127219200", | |
3498 " .long 0", | |
3499 ".text", | |
3500 " .align 2", | |
111 | 3501 "u2d_:", |
91 | 3502 " mflr r0", |
3503 " bcl 20,31,__u2dL2$pb", | |
3504 "__u2dL2$pb:", | |
3505 " mflr r10", | |
3506 " mtlr r0", | |
375 | 3507 " stw r3,-28(r1)", |
91 | 3508 " lis r0,0x4330", |
375 | 3509 " stw r0,-32(r1)", |
3510 " lfd f0,-32(r1)", | |
91 | 3511 " addis r9,r10,ha16(__u2dLC1-__u2dL2$pb)", |
3512 " lfd f1,lo16(__u2dLC1-__u2dL2$pb)(r9)", | |
3513 " fsub f1,f0,f1", | |
3514 " blr", | |
3515 0 | |
3516 }; | |
89 | 3517 |
211 | 3518 void |
221 | 3519 code_u2d() |
89 | 3520 { |
113 | 3521 code_save_stacks(); |
3522 clear_ptr_cache(); | |
147 | 3523 u2d_lib_used = 1; |
207 | 3524 set_ireg(RET_REGISTER,1); |
111 | 3525 printf("\tbl u2d_\n"); |
228 | 3526 set_freg(RET_FREGISTER,0); |
89 | 3527 } |
3528 | |
211 | 3529 void |
221 | 3530 code_d2f() { } |
211 | 3531 void |
221 | 3532 code_f2d() { } |
211 | 3533 void |
221 | 3534 code_f2i() { code_d2i(); } |
211 | 3535 void |
221 | 3536 code_f2u() { code_d2u(); } |
211 | 3537 void |
221 | 3538 code_i2f() { code_i2d(); } |
211 | 3539 void |
221 | 3540 code_u2f() { code_u2d(); } |
211 | 3541 |
3542 void | |
3543 code_drgvar(int e2,int d,int freg) | |
89 | 3544 { |
221 | 3545 use_float(d,freg); |
367 | 3546 code_ldf(fload(d),fregister_name(freg),cadr(e2), |
3547 get_ptr_cache((NMTBL*)caddr(e2))); | |
89 | 3548 } |
3549 | |
3550 | |
211 | 3551 void |
3552 code_drlvar(int e2,int d,int freg) | |
89 | 3553 { |
221 | 3554 use_float(d,freg); |
119 | 3555 lvar_intro(e2); |
3556 printf("\t%s %s,",fload(d),fregister_name(freg)); lvar(e2); | |
89 | 3557 } |
3558 | |
211 | 3559 void |
287 | 3560 code_cmp_drgvar(int e2,int reg,int d,int label,int cond) |
89 | 3561 { |
221 | 3562 char *frn; |
138 | 3563 int g=get_dregister(d); |
97 | 3564 char *grn=fregister_name(g); |
221 | 3565 |
3566 use_float(d,reg); | |
3567 frn=fregister_name(reg); | |
3568 | |
367 | 3569 code_ldf(fload(1),grn,cadr(e2), |
3570 get_ptr_cache((NMTBL*)caddr(e2))); | |
291 | 3571 inc_cmpflag(); |
280 | 3572 printf("\tfcmpu cr%d,%s,%s\n",cmpflag,frn,grn); |
147 | 3573 free_register(g); |
287 | 3574 jcond(label,cond); |
89 | 3575 } |
3576 | |
211 | 3577 void |
287 | 3578 code_cmp_drlvar(int e2,int reg,int d,int label,int cond) |
89 | 3579 { |
221 | 3580 char *frn; |
138 | 3581 int g=get_dregister(d); |
97 | 3582 char *grn=fregister_name(g); |
108 | 3583 |
221 | 3584 use_float(d,reg); |
3585 frn=fregister_name(reg); | |
3586 | |
119 | 3587 lvar_intro(e2); |
3588 printf("\t%s %s,",fload(1),grn); lvar(e2); | |
291 | 3589 inc_cmpflag(); |
280 | 3590 printf("\tfcmpu cr%d,%s,%s\n",cmpflag,frn,grn); |
147 | 3591 free_register(g); |
287 | 3592 jcond(label,cond); |
89 | 3593 } |
3594 | |
211 | 3595 void |
273 | 3596 dtosop(int op,int reg,int oreg) |
89 | 3597 { |
127 | 3598 char *opn=""; |
221 | 3599 char *frn; |
273 | 3600 char *grn; |
3601 int ox = -1; | |
221 | 3602 |
3603 use_float(1,reg); | |
273 | 3604 if(oreg==-1) { |
3605 error(-1); | |
3606 } else if (oreg<= -REG_LVAR_OFFSET) { | |
3607 ox = get_dregister(1); if (ox<0) error(-1); | |
3608 use_reg(ox); | |
3609 code_drlvar(oreg+REG_LVAR_OFFSET,1,ox); | |
3610 oreg = ox; | |
3611 } | |
3612 grn=fregister_name(oreg); | |
221 | 3613 frn=fregister_name(reg); |
89 | 3614 switch(op) { |
133 | 3615 case FADD: |
91 | 3616 case DADD: opn="fadd"; break; |
133 | 3617 case FSUB: |
101 | 3618 case DSUB: opn="fsub"; break; |
133 | 3619 case FDIV: |
101 | 3620 case DDIV: opn="fdiv"; break; |
133 | 3621 case FMUL: |
101 | 3622 case DMUL: opn="fmul"; break; |
133 | 3623 case FCMP: |
91 | 3624 case DCMP: |
291 | 3625 inc_cmpflag(); |
288 | 3626 printf("\tfcmpu cr%d,%s,%s\n",cmpflag,frn,grn); |
273 | 3627 if (ox!=-1) free_register(ox); |
101 | 3628 return; |
133 | 3629 case FCMPGE: |
91 | 3630 case DCMPGE: |
291 | 3631 inc_cmpflag(); |
288 | 3632 printf("\tfcmpu cr%d,%s,%s\n",cmpflag,frn,grn); |
273 | 3633 if (ox!=-1) free_register(ox); |
101 | 3634 return; |
133 | 3635 default: |
3636 error(-1); return; | |
89 | 3637 } |
91 | 3638 printf("\t%s %s,%s,%s\n",opn,frn,frn,grn); |
273 | 3639 if (ox!=-1) free_register(ox); |
89 | 3640 } |
3641 | |
3642 void | |
221 | 3643 code_dassop(int op,int reg,int d) { |
91 | 3644 /* we have lvalue in creg, applied floating value is in freg */ |
221 | 3645 // (*creg) op = pop() |
138 | 3646 int xreg=emit_dpop(d); |
221 | 3647 char *crn; |
209 | 3648 char *frn; |
221 | 3649 |
3650 crn=register_name(ireg); | |
3651 use_float(d,reg); | |
3652 frn =fregister_name(reg); | |
209 | 3653 |
108 | 3654 printf("\t%s %s,0(%s)\n",fload(d),frn,crn); |
221 | 3655 dtosop(op,reg,xreg); |
108 | 3656 printf("\t%s %s,0(%s)\n",fstore(d),frn,crn); |
138 | 3657 emit_dpop_free(xreg,d); |
89 | 3658 } |
3659 | |
219 | 3660 void |
3661 code_register_dassop(int reg,int op,int d) { | |
221 | 3662 // reg op= dpop() |
219 | 3663 int xreg=emit_dpop(d); |
221 | 3664 dtosop(op,reg,xreg); |
3665 emit_dpop_free(xreg,d); | |
219 | 3666 } |
91 | 3667 |
273 | 3668 static int |
3669 code_dload_1(int d) | |
3670 { | |
3671 int r,g; | |
3672 char *drn,*grn; | |
3673 // load 1 | |
3674 float_one_lib_used=1; | |
3675 r = get_ptr_cache(&float_one); | |
3676 drn=register_name(r); | |
3677 grn=fregister_name(g=get_dregister(d)); | |
3678 printf("\tlfs %s,0(%s)\n",grn,drn); | |
3679 return g; | |
3680 } | |
3681 | |
89 | 3682 void |
107 | 3683 code_dpreinc(int e1,int e2,int d,int reg) { |
273 | 3684 char *frn,*crn,*grn; |
91 | 3685 int g; |
3686 | |
144 | 3687 if (car(e2)==DREGISTER||car(e2)==FREGISTER) { |
221 | 3688 crn=register_name(cadr(e2)); |
273 | 3689 grn = fregister_name(g = code_dload_1(d)); |
3690 if (reg==USE_CREG) { | |
3691 reg=get_dregister(d); if (!reg) error(-1); | |
3692 set_freg(reg,0); | |
3693 } | |
3694 frn=fregister_name(reg); | |
3695 printf("\t%s %s,%s,%s\n",(caddr(e1)>0)?"fadd":"fsub",crn,crn,grn); | |
3696 if (use && reg!=cadr(e2)) | |
3697 printf("\tfmr %s,%s\n",frn,crn); | |
221 | 3698 } else { |
3699 g_expr(e2); | |
3700 if (!is_int_reg(creg)) error(-1); | |
3701 crn=register_name(ireg); | |
273 | 3702 if (reg==USE_CREG) { |
3703 reg=get_dregister(d); if (!reg) error(-1); | |
3704 set_freg(reg,0); | |
3705 } | |
3706 frn=fregister_name(reg); | |
3707 grn = fregister_name(g = code_dload_1(d)); | |
221 | 3708 printf("\t%s %s,0(%s)\n",fload(d),frn,crn); |
3709 printf("\t%s %s,%s,%s\n",(caddr(e1)>0)?"fadd":"fsub",frn,frn,grn); | |
3710 printf("\t%s %s,0(%s)\n",fstore(d),frn,crn); | |
3711 } | |
147 | 3712 free_register(g); |
89 | 3713 } |
3714 | |
3715 void | |
107 | 3716 code_dpostinc(int e1,int e2,int d,int reg) { |
273 | 3717 char *frn,*crn,*grn; |
91 | 3718 int g; |
3719 | |
144 | 3720 if (car(e2)==DREGISTER||car(e2)==FREGISTER) { |
221 | 3721 crn=register_name(cadr(e2)); |
273 | 3722 grn = fregister_name(g = code_dload_1(d)); |
3723 if (reg==USE_CREG) { | |
3724 reg=get_dregister(d); if (!reg) error(-1); | |
3725 set_freg(reg,0); | |
3726 } | |
3727 frn=fregister_name(reg); | |
3728 if (use && reg!=cadr(e2)) | |
3729 printf("\tfmr %s,%s\n",frn,crn); | |
3730 printf("\t%s %s,%s,%s\n",(caddr(e1)>0)?"fadd":"fsub",crn,crn,grn); | |
221 | 3731 } else { |
3732 g_expr(e2); | |
3733 if (!is_int_reg(creg)) error(-1); | |
273 | 3734 crn=register_name(ireg); |
3735 if (reg==USE_CREG) { | |
3736 reg=get_dregister(d); if (!reg) error(-1); | |
3737 set_freg(reg,0); | |
3738 } | |
3739 frn=fregister_name(reg); | |
3740 grn = fregister_name(g = code_dload_1(d)); | |
221 | 3741 printf("\t%s %s,0(%s)\n",fload(d),frn,crn); |
3742 printf("\t%s %s,%s,%s\n",(caddr(e1)>0)?"fadd":"fsub",grn,frn,grn); | |
3743 printf("\t%s %s,0(%s)\n",fstore(d),grn,crn); | |
3744 } | |
147 | 3745 free_register(g); |
89 | 3746 } |
3747 | |
288 | 3748 static int |
3749 drexpr_bool(int e1,int reg) | |
3750 { | |
289 | 3751 int flag=-1,eq=-1,neg=-1,t; |
288 | 3752 char *rn; |
3753 switch(car(e1)) { | |
3754 case DOP+GT: case FOP+GT: flag = 2; break; | |
3755 case DOP+GE: case FOP+GE: flag = 2; eq=3; break; | |
3756 case DOP+LT: case FOP+LT: flag = 1; break; | |
3757 case DOP+LE: case FOP+LE: flag = 1; eq=3; break; | |
3758 case DOP+EQ: case FOP+EQ: flag = 3; break; | |
289 | 3759 case DOP+NEQ: case FOP+NEQ: flag = 3; neg=3; break; |
288 | 3760 default: return 0; |
3761 } | |
3762 g_expr(list3(DCMP,cadr(e1),caddr(e1))); | |
3763 use_int(reg); | |
3764 rn = register_name(reg); | |
289 | 3765 t = CRBITSIZ*cmpflag; |
288 | 3766 if (eq>0) { |
289 | 3767 printf("\tcror %d,%d,%d\n",t+flag-1,t+eq-1,t+flag-1); |
3768 } | |
3769 if (neg>0) { | |
3770 neg = t+neg-1, | |
3771 printf("\tcrnor %d,%d,%d\n",neg,neg,neg); | |
288 | 3772 } |
3773 printf("\tmfcr %s\n",rn); | |
289 | 3774 printf("\trlwinm %s,%s,%d,1\n",rn,rn,t+flag); |
288 | 3775 return 1; |
3776 } | |
3777 | |
89 | 3778 void |
229 | 3779 drexpr(int e1, int e2,int l1, int op,int cond) |
3780 { | |
231 | 3781 if (!cond) { |
229 | 3782 switch(op) { |
3783 case FOP+GT: | |
232 | 3784 drexpr(e2,e1,l1,FOP+GE,1); return; |
229 | 3785 case FOP+GE: |
232 | 3786 drexpr(e2,e1,l1,FOP+GT,1); return; |
229 | 3787 case FOP+EQ: |
3788 op=FOP+NEQ; break; | |
3789 case FOP+NEQ: | |
3790 op=FOP+EQ; break; | |
3791 case DOP+GT: | |
232 | 3792 drexpr(e2,e1,l1,DOP+GE,1); return; |
229 | 3793 case DOP+GE: |
232 | 3794 drexpr(e2,e1,l1,DOP+GT,1); return; |
229 | 3795 case DOP+EQ: |
3796 op=DOP+NEQ; break; | |
3797 case DOP+NEQ: | |
3798 op=DOP+EQ; break; | |
3799 } | |
3800 } | |
234 | 3801 g_expr(list3(DCMP, e1,e2)); |
89 | 3802 switch(op) { |
288 | 3803 case DOP+GT: case FOP+GT: |
3804 printf("\tbgt\tcr%d,L_%d\n",cmpflag,l1); | |
3805 break; | |
3806 case DOP+GE: case FOP+GE: | |
3807 printf("\tbge\tcr%d,L_%d\n",cmpflag,l1); | |
229 | 3808 break; |
288 | 3809 case DOP+EQ: case FOP+EQ: |
3810 printf("\tbeq\tcr%d,L_%d\n",cmpflag,l1); | |
89 | 3811 break; |
288 | 3812 case DOP+NEQ: case FOP+NEQ: |
3813 printf("\tbne\tcr%d,L_%d\n",cmpflag,l1); | |
89 | 3814 break; |
3815 } | |
3816 } | |
3817 | |
138 | 3818 int emit_dpop(int d) |
89 | 3819 { |
114 | 3820 int xreg,reg; |
97 | 3821 xreg=pop_fregister(); |
3822 if (xreg<= -REG_LVAR_OFFSET) { | |
138 | 3823 reg = get_dregister(d); |
119 | 3824 code_drlvar(REG_LVAR_OFFSET+xreg,1,reg); |
117 | 3825 free_lvar(REG_LVAR_OFFSET+xreg); |
205 | 3826 xreg=reg; |
96 | 3827 } |
3828 return xreg; | |
89 | 3829 } |
3830 | |
211 | 3831 void |
3832 emit_dpop_free(int e1,int d) | |
89 | 3833 { |
147 | 3834 free_register(e1); |
89 | 3835 } |
3836 | |
211 | 3837 void |
3838 emit_dpush(int d) | |
89 | 3839 { |
97 | 3840 int new_reg; |
221 | 3841 if (!is_float_reg(creg)) error(-1); |
102 | 3842 if (freg_sp>MAX_MAX) error(-1); |
221 | 3843 new_reg = get_dregister(1); /* ���Ф˼��� */ |
97 | 3844 freg_stack[freg_sp++] = freg; /* push ���뤫���˥쥸������Ȥ� */ |
147 | 3845 creg = freg = new_reg; |
89 | 3846 } |
3847 | |
195 | 3848 #endif |
3849 | |
3850 #if LONGLONG_CODE | |
3851 | |
3852 | |
3853 /* 64bit int part */ | |
219 | 3854 static void |
273 | 3855 lmove(int to,int from) // to = from |
219 | 3856 { |
227 | 3857 int tmp; |
3858 if (regv_h(to)==regv_l(from)&&(regv_l(to)==regv_h(from))) { | |
3859 tmp = get_register(); | |
228 | 3860 printf("\tmr %s,%s\n",register_name(tmp),lregister_name_low(from)); |
227 | 3861 printf("\tmr %s,%s\n",lregister_name_high(to),lregister_name_high(from)); |
3862 printf("\tmr %s,%s\n",lregister_name_low(to),register_name(tmp)); | |
3863 free_register(tmp); | |
3864 } else if (regv_h(to)==regv_l(from)) { | |
226 | 3865 printf("\tmr %s,%s\n",lregister_name_low(to),lregister_name_low(from)); |
3866 printf("\tmr %s,%s\n",lregister_name_high(to),lregister_name_high(from)); | |
3867 } else { | |
3868 printf("\tmr %s,%s\n",lregister_name_high(to),lregister_name_high(from)); | |
3869 printf("\tmr %s,%s\n",lregister_name_low(to),lregister_name_low(from)); | |
3870 } | |
219 | 3871 } |
195 | 3872 |
211 | 3873 static void |
280 | 3874 pcond(char *s,int cmpflag,int l1) |
3875 { | |
3876 printf("\tb%s cr%d,L_%d\n",s,cmpflag,l1); | |
3877 } | |
3878 | |
3879 static int | |
3880 lcmp(int op,int cond) | |
210 | 3881 { |
280 | 3882 if (op==LOP+UGT||op==LOP+UGE) { |
3883 return UCMP; | |
3884 } else if (op==LOP+LE||op==LOP+GE) { | |
3885 return CMP; | |
3886 } else { | |
3887 return CMP; | |
3888 } | |
210 | 3889 } |
3890 | |
3891 void | |
229 | 3892 lrexpr(int e1, int e2,int l1, int op,int cond) |
195 | 3893 { |
221 | 3894 int reg; |
210 | 3895 int e3; |
280 | 3896 int l2; |
3897 int op1,cr0,cr1; | |
3898 | |
210 | 3899 g_expr(e1); |
3900 emit_lpush(); | |
3901 g_expr(e2); | |
3902 e3 = emit_lpop(); | |
221 | 3903 if (!is_longlong_reg(creg)) error(-1); |
3904 reg = lreg; | |
280 | 3905 op1 = lcmp(op,cond); |
3906 tosop(op1,regv_h(e3),regv_h(reg)); | |
3907 cr0 = cmpflag; | |
291 | 3908 tosop(op1,regv_l(e3),regv_l(reg)); |
280 | 3909 cr1 = cmpflag; |
3910 | |
3911 l2 = fwdlabel(); | |
3912 // cond==0 jump on false condtion ( if(x) => rexpr(.. cond=0 ...) ) | |
210 | 3913 switch(op) { |
3914 case LOP+GT: | |
3915 case LOP+GE: | |
280 | 3916 pcond(code_gt(1),cr0,cond?l1:l2); |
3917 pcond(code_eq(0),cr0,cond?l2:l1); | |
3918 break; | |
3919 case LOP+UGT: | |
3920 case LOP+UGE: | |
3921 pcond(code_ugt(1),cr0,cond?l1:l2); | |
3922 pcond(code_eq(0), cr0,cond?l2:l1); | |
3923 break; | |
210 | 3924 case LOP+EQ: |
280 | 3925 pcond(code_eq(0),cr0,(cond?l2:l1)); |
3926 pcond(code_eq(cond),cr1,l1); | |
3927 break; | |
210 | 3928 case LOP+NEQ: |
280 | 3929 pcond(code_eq(0),cr0,(cond?l1:l2)); |
3930 pcond(code_eq(!cond),cr1,l1); | |
3931 break; | |
210 | 3932 default: |
3933 error(-1); | |
3934 } | |
3935 switch(op) { | |
280 | 3936 case LOP+GT: pcond(code_gt(cond), cr1,l1); break; |
3937 case LOP+GE: pcond(code_ge(cond), cr1,l1); break; | |
3938 case LOP+UGT: pcond(code_ugt(cond), cr1,l1); break; | |
3939 case LOP+UGE: pcond(code_uge(cond), cr1,l1); break; | |
3940 } | |
3941 fwddef(l2); | |
3942 emit_lpop_free(e3); | |
3943 } | |
195 | 3944 |
211 | 3945 int |
3946 emit_lpop() | |
195 | 3947 { |
210 | 3948 int xreg,reg; |
237 | 3949 xreg=lreg_stack[--lreg_sp]; |
210 | 3950 if (xreg<= -REG_LVAR_OFFSET) { |
3951 reg = get_lregister(); | |
3952 code_lrlvar(REG_LVAR_OFFSET+xreg,reg); | |
3953 free_lvar(REG_LVAR_OFFSET+xreg); | |
3954 xreg = reg; | |
3955 } | |
3956 return xreg; | |
195 | 3957 } |
3958 | |
211 | 3959 void |
3960 code_lregister(int e2,int reg) | |
195 | 3961 { |
221 | 3962 use_longlong(reg); |
3963 if (reg!=e2) { | |
3964 lmove(reg,e2); | |
211 | 3965 } |
195 | 3966 } |
3967 | |
211 | 3968 void |
287 | 3969 code_cmp_lregister(int reg,int label,int cond) |
195 | 3970 { |
221 | 3971 use_longlong(reg); |
211 | 3972 printf("\tor %s,%s,%s\n", |
3973 lregister_name_low(reg), | |
3974 lregister_name_low(reg), | |
3975 lregister_name_high(reg)); | |
291 | 3976 inc_cmpflag(); |
280 | 3977 printf("\tcmpwi cr%d,%s,0\n",cmpflag,lregister_name_low(reg)); |
287 | 3978 jcond(label,cond); |
195 | 3979 } |
3980 | |
211 | 3981 void |
287 | 3982 code_cmp_lrgvar(int e1,int creg,int label,int cond) |
195 | 3983 { |
221 | 3984 use_longlong(creg); |
211 | 3985 code_lrgvar(e1,creg); |
287 | 3986 code_cmp_lregister(creg,label,cond); |
211 | 3987 } |
3988 | |
3989 void | |
287 | 3990 code_cmp_lrlvar(int e1,int creg,int label,int cond) |
211 | 3991 { |
221 | 3992 use_longlong(creg); |
211 | 3993 code_lrlvar(e1,creg); |
287 | 3994 code_cmp_lregister(creg,label,cond); |
195 | 3995 } |
3996 | |
211 | 3997 void |
3998 code_lassign(int e2,int creg) | |
195 | 3999 { |
211 | 4000 char *drn = register_name(e2); |
221 | 4001 char *crn_h; |
4002 char *crn_l; | |
4003 | |
4004 use_longlong(creg); | |
4005 crn_h = lregister_name_high(creg); | |
4006 crn_l = lregister_name_low(creg); | |
211 | 4007 |
271 | 4008 printf("\tstw %s,0(%s)\n",crn_h,drn); |
4009 printf("\tstw %s,%d(%s)\n",crn_l,SIZE_OF_INT,drn); | |
195 | 4010 } |
4011 | |
211 | 4012 void |
4013 code_lassign_gvar(int e2,int creg) | |
195 | 4014 { |
211 | 4015 int r; |
367 | 4016 use_longlong(creg); |
4017 r = get_ptr_cache((NMTBL*)caddr(e2)); | |
4018 code_ldf(cstore(0),lregister_name_high(creg),cadr(e2),r); | |
4019 code_ldf(cstore(0),lregister_name_low(creg),cadr(e2)+SIZE_OF_INT,r); | |
195 | 4020 } |
4021 | |
211 | 4022 void |
4023 code_lassign_lvar(int e2,int creg) | |
195 | 4024 { |
221 | 4025 char *crn_h; |
4026 char *crn_l; | |
4027 | |
4028 use_longlong(creg); | |
4029 crn_h = lregister_name_high(creg); | |
4030 crn_l = lregister_name_low(creg); | |
211 | 4031 lvar_intro(e2); |
4032 printf("\tstw %s,",crn_h);lvar(e2); | |
245 | 4033 printf("\tstw %s,",crn_l);lvar(e2+SIZE_OF_INT); |
195 | 4034 } |
4035 | |
211 | 4036 void |
4037 code_lassign_lregister(int e2,int reg) | |
195 | 4038 { |
221 | 4039 use_longlong(reg); |
219 | 4040 if (e2!=reg) { |
4041 lmove(e2,reg); | |
211 | 4042 } |
195 | 4043 } |
4044 | |
207 | 4045 static long long ll0 = 1LL; |
206 | 4046 |
4047 static int | |
4048 code_l1(long long d) | |
4049 { | |
207 | 4050 int *i = (int *)&ll0; int *j = (int *)&d; |
206 | 4051 return (i[1] == 1)?j[1]:j[0]; |
4052 } | |
4053 | |
4054 static int | |
4055 code_l2(long long d) | |
4056 { | |
207 | 4057 int *i = (int *)&ll0; int *j = (int *)&d; |
206 | 4058 return (i[1] == 1)?j[0]:j[1]; |
4059 } | |
4060 | |
211 | 4061 void |
4062 code_lconst(int e1,int creg) | |
4063 { | |
221 | 4064 use_longlong(creg); |
211 | 4065 code_const(code_l1(lcadr(e1)),regv_l(creg)); |
4066 code_const(code_l2(lcadr(e1)),regv_h(creg)); | |
4067 } | |
4068 | |
4069 void | |
4070 code_lneg(int creg) | |
195 | 4071 { |
221 | 4072 use_longlong(creg); |
211 | 4073 printf("\tsubfic %s,%s,0\n", |
4074 lregister_name_low(creg),lregister_name_low(creg)); | |
221 | 4075 printf("\tsubfze %s,%s\n", |
211 | 4076 lregister_name_high(creg),lregister_name_high(creg)); |
195 | 4077 } |
4078 | |
211 | 4079 void |
221 | 4080 code_lrgvar(int e1,int creg) |
211 | 4081 { |
4082 int r; | |
221 | 4083 char *crn_h; |
4084 char *crn_l; | |
4085 use_longlong(creg); | |
4086 crn_h = lregister_name_high(creg); | |
4087 crn_l = lregister_name_low(creg); | |
367 | 4088 r = get_ptr_cache((NMTBL*)caddr(e1)); |
4089 code_ldf(cload(0),crn_h,cadr(e1),r); | |
4090 code_ldf(cload(0),crn_l,cadr(e1)+SIZE_OF_INT,r); | |
211 | 4091 } |
4092 | |
4093 void | |
4094 code_lrlvar(int e1,int creg) | |
195 | 4095 { |
221 | 4096 char *crn_h; |
4097 char *crn_l; | |
4098 use_longlong(creg); | |
4099 crn_h = lregister_name_high(creg); | |
4100 crn_l = lregister_name_low(creg); | |
211 | 4101 lvar_intro(e1); |
4102 printf("\tlwz %s,",crn_h); lvar(e1); | |
245 | 4103 printf("\tlwz %s,",crn_l); lvar(e1+SIZE_OF_INT); |
195 | 4104 } |
4105 | |
221 | 4106 #if 0 |
216 | 4107 static int lumod_lib_used=0; |
217 | 4108 static char *lumod_lib[] = { |
216 | 4109 }; |
4110 | |
4111 static int lmod_lib_used=0; | |
217 | 4112 static char *lmod_lib[] = { |
216 | 4113 }; |
4114 | |
4115 static int ludiv_lib_used=0; | |
217 | 4116 static char *ludiv_lib[] = { |
216 | 4117 }; |
4118 | |
4119 static int ldiv_lib_used=0; | |
217 | 4120 static char *ldiv_lib[] = { |
216 | 4121 }; |
221 | 4122 #endif |
216 | 4123 |
4124 static int lsrd_lib_used=0; | |
217 | 4125 static char *lsrd_lib[] = { |
4126 ".text", | |
4127 " .align 2", | |
4128 "lsrd__:", | |
4129 " mr. r5,r5", | |
4130 " beqlr", | |
4131 " subfic r2,r5,32", | |
4132 " stw r3,-32(r1)", | |
4133 " stw r4,-28(r1)", | |
4134 " cmpwi cr7,r2,0", | |
4135 " bgt+ cr7,L__lsrd1", | |
4136 " neg r0,r2", | |
4137 " lwz r2,-32(r1)", | |
4138 " li r9,0", | |
4139 " srw r2,r2,r0", | |
4140 " stw r9,-48(r1)", | |
4141 " b L__lsrd2", | |
4142 "L__lsrd1: lwz r0,-32(r1)", | |
4143 " slw r9,r0,r2", | |
4144 " lwz r2,-28(r1)", | |
4145 " srw r0,r0,r5", | |
4146 " srw r2,r2,r5", | |
4147 " stw r0,-48(r1)", | |
4148 " or r2,r2,r9", | |
4149 "L__lsrd2: stw r2,-44(r1)", | |
4150 " lwz r3,-48(r1)", | |
4151 " lwz r4,-44(r1)", | |
4152 " blr", | |
219 | 4153 0 |
217 | 4154 }; |
4155 | |
4156 static int asld_lib_used=0; | |
4157 static char *asld_lib[] = { | |
4158 ".text", | |
4159 " .align 2", | |
4160 "asld__:", | |
4161 " mr. r5,r5", | |
4162 " beqlr", | |
4163 " subfic r2,r5,32", | |
4164 " stw r3,-32(r1)", | |
4165 " stw r4,-28(r1)", | |
4166 " cmpwi cr7,r2,0", | |
4167 " bgt+ cr7,L__asld1", | |
4168 " neg r0,r2", | |
4169 " lwz r2,-28(r1)", | |
4170 " li r9,0", | |
4171 " slw r2,r2,r0", | |
4172 " stw r9,-44(r1)", | |
4173 " b L__asld2", | |
4174 "L__asld1: lwz r0,-28(r1)", | |
4175 " srw r9,r0,r2", | |
4176 " lwz r2,-32(r1)", | |
4177 " slw r0,r0,r5", | |
4178 " slw r2,r2,r5", | |
4179 " stw r0,-44(r1)", | |
4180 " or r2,r2,r9", | |
4181 "L__asld2: stw r2,-48(r1)", | |
4182 " lwz r3,-48(r1)", | |
4183 " lwz r4,-44(r1)", | |
4184 " blr", | |
219 | 4185 0 |
216 | 4186 }; |
4187 | |
4188 static int asrd_lib_used=0; | |
217 | 4189 static char *asrd_lib[] = { |
4190 ".text", | |
4191 " .align 2", | |
4192 "asrd__:", | |
4193 " mr. r5,r5", | |
4194 " beqlr", | |
4195 " subfic r2,r5,32", | |
4196 " stw r3,-32(r1)", | |
4197 " stw r4,-28(r1)", | |
4198 " cmpwi cr7,r2,0", | |
4199 " bgt+ cr7,L__asrd1", | |
4200 " lwz r0,-32(r1)", | |
4201 " neg r2,r2", | |
4202 " sraw r2,r0,r2", | |
4203 " srawi r0,r0,31", | |
4204 " b L__asrd2", | |
4205 "L__asrd1: lwz r0,-32(r1)", | |
4206 " slw r9,r0,r2", | |
4207 " lwz r2,-28(r1)", | |
4208 " sraw r0,r0,r5", | |
4209 " srw r2,r2,r5", | |
4210 " or r2,r2,r9", | |
4211 "L__asrd2: stw r0,-48(r1)", | |
4212 " stw r2,-44(r1)", | |
4213 " lwz r3,-48(r1)", | |
4214 " lwz r4,-44(r1)", | |
4215 " blr", | |
219 | 4216 0 |
216 | 4217 }; |
4218 | |
217 | 4219 static void |
4220 extern_conv(char *conv) | |
4221 { | |
4222 code_save_stacks(); | |
4223 clear_ptr_cache(); | |
4224 extern_define(conv,0,FUNCTION,1); | |
4225 printf("\tbl L_%s$stub\n",conv); | |
4226 } | |
4227 | |
216 | 4228 #if FLOAT_CODE |
218 | 4229 #if 0 |
217 | 4230 static int d2ll_lib_used=0; |
4231 static char *d2ll_lib[] = { | |
216 | 4232 }; |
4233 | |
4234 static int d2ull_lib_used=0; | |
217 | 4235 static char *d2ull_lib[] = { |
216 | 4236 }; |
4237 | |
4238 static int f2ll_lib_used=0; | |
217 | 4239 static char *f2ll_lib[] = { |
216 | 4240 }; |
4241 | |
4242 static int f2ull_lib_used=0; | |
217 | 4243 static char *f2ull_lib[] = { |
216 | 4244 }; |
4245 | |
4246 static int ll2d_lib_used=0; | |
217 | 4247 static char *ll2d_lib[] = { |
216 | 4248 }; |
4249 | |
4250 static int ll2f_lib_used=0; | |
217 | 4251 static char *ll2f_lib[] = { |
216 | 4252 }; |
218 | 4253 #endif |
216 | 4254 |
4255 #endif | |
4256 | |
4257 static void | |
255 | 4258 code_asld_lib(int reg,int oreg) |
211 | 4259 { |
4260 code_save_stacks(); | |
4261 clear_ptr_cache(); | |
4262 asld_lib_used = 1; | |
255 | 4263 set_lreg_operand(reg,1); |
4264 set_lreg(RET_LREGISTER,0); | |
228 | 4265 if (regv_l(oreg)!=5) { |
4266 printf("\tmr r5,%s\n", lregister_name_low(oreg)); | |
4267 } | |
221 | 4268 printf("\tbl asld__\n"); |
195 | 4269 } |
4270 | |
216 | 4271 static void |
255 | 4272 code_asrd_lib(int reg,int oreg) // ___ashrdi3$stub |
216 | 4273 { |
4274 code_save_stacks(); | |
4275 clear_ptr_cache(); | |
4276 asrd_lib_used = 1; | |
255 | 4277 set_lreg_operand(reg,1); |
4278 set_lreg(RET_LREGISTER,0); | |
228 | 4279 if (regv_l(oreg)!=5) { |
4280 printf("\tmr r5,%s\n", lregister_name_low(oreg)); | |
4281 } | |
221 | 4282 printf("\tbl asrd__\n"); |
216 | 4283 } |
4284 | |
4285 static void | |
255 | 4286 code_lsrd_lib(int reg,int oreg) // ___lshrdi3$stub |
216 | 4287 { |
4288 code_save_stacks(); | |
4289 clear_ptr_cache(); | |
4290 lsrd_lib_used = 1; | |
255 | 4291 set_lreg_operand(reg,1); |
4292 set_lreg(RET_LREGISTER,0); | |
231 | 4293 if (regv_l(oreg)!=5) { |
4294 printf("\tmr r5,%s\n", lregister_name_low(oreg)); | |
4295 } | |
221 | 4296 printf("\tbl lsrd__\n"); |
216 | 4297 } |
4298 | |
4299 static void | |
255 | 4300 code_ldiv_lib(int reg,int oreg) // ___divdi3$stub |
216 | 4301 { |
223 | 4302 code_save_stacks(); |
4303 clear_ptr_cache(); | |
255 | 4304 set_lreg_operand(reg,1); |
4305 set_lreg(RET_LREGISTER,0); | |
4306 set_lreg_operand1(oreg,1); | |
217 | 4307 extern_conv("__divdi3"); |
216 | 4308 } |
4309 | |
4310 static void | |
255 | 4311 code_ludiv_lib(int reg,int oreg) // ___udivdi3$stub |
216 | 4312 { |
223 | 4313 code_save_stacks(); |
4314 clear_ptr_cache(); | |
255 | 4315 set_lreg_operand(reg,1); |
4316 set_lreg(RET_LREGISTER,0); | |
4317 set_lreg_operand1(oreg,1); | |
217 | 4318 extern_conv("__udivdi3"); |
216 | 4319 } |
4320 | |
4321 static void | |
255 | 4322 code_lmod_lib(int reg,int oreg) // ___moddi3$stub |
216 | 4323 { |
223 | 4324 code_save_stacks(); |
4325 clear_ptr_cache(); | |
255 | 4326 set_lreg_operand(reg,1); |
4327 set_lreg(RET_LREGISTER,0); | |
4328 set_lreg_operand1(oreg,1); | |
217 | 4329 extern_conv("__moddi3"); |
216 | 4330 } |
4331 | |
4332 static void | |
255 | 4333 code_lumod_lib(int reg,int oreg) // ___umoddi3$stub |
216 | 4334 { |
223 | 4335 code_save_stacks(); |
4336 clear_ptr_cache(); | |
255 | 4337 set_lreg(RET_LREGISTER,0); |
4338 set_lreg_operand(reg,1); | |
4339 set_lreg_operand1(oreg,1); | |
217 | 4340 extern_conv("__umoddi3"); |
216 | 4341 } |
4342 | |
221 | 4343 #define check_lreg(reg) if (reg!=lreg) { lmove(reg,lreg); } |
4344 | |
211 | 4345 void |
221 | 4346 ltosop(int op,int reg,int oreg) |
195 | 4347 { |
221 | 4348 int dx = -1; |
252 | 4349 int ox = -1; |
211 | 4350 char *orn_h,*crn_h,*drn_h; |
4351 char *orn_l,*crn_l,*drn_l; | |
221 | 4352 // creg = creg op oreg |
4353 | |
4354 use_longlong(reg); | |
211 | 4355 if(oreg==-1) { |
4356 error(-1); | |
4357 } else if (oreg<= -REG_LVAR_OFFSET) { | |
252 | 4358 ox = get_lregister(); if (ox<0) error(-1); |
4359 use_reg(ox); | |
273 | 4360 code_lrlvar(oreg+REG_LVAR_OFFSET,ox); |
252 | 4361 oreg = ox; |
211 | 4362 } |
4363 | |
4364 switch(op) { | |
4365 case LLSHIFT: | |
4366 case LULSHIFT: | |
255 | 4367 code_asld_lib(reg,oreg); // ___ashldi3$stub |
221 | 4368 check_lreg(reg); |
252 | 4369 if(ox!=-1) free_register(ox); |
211 | 4370 return; |
4371 case LRSHIFT: | |
255 | 4372 code_asrd_lib(reg,oreg); // ___ashrdi3$stub |
221 | 4373 check_lreg(reg); |
252 | 4374 if(ox!=-1) free_register(ox); |
211 | 4375 return; |
4376 case LURSHIFT: | |
255 | 4377 code_lsrd_lib(reg,oreg); // ___lshrdi3$stub |
221 | 4378 check_lreg(reg); |
252 | 4379 if(ox!=-1) free_register(ox); |
211 | 4380 return; |
4381 } | |
4382 orn_h = lregister_name_high(oreg); | |
4383 orn_l = lregister_name_low(oreg); | |
221 | 4384 crn_h = lregister_name_high(reg); |
4385 crn_l = lregister_name_low(reg); | |
211 | 4386 switch(op) { |
219 | 4387 case LADD: |
211 | 4388 printf("\taddc %s,%s,%s\n",crn_l,crn_l,orn_l); |
4389 printf("\tadde %s,%s,%s\n",crn_h,crn_h,orn_h); | |
4390 break; | |
219 | 4391 case LSUB: |
228 | 4392 printf("\tsubfc %s,%s,%s\n",crn_l,orn_l,crn_l); |
4393 printf("\tsubfe %s,%s,%s\n",crn_h,orn_h,crn_h); | |
211 | 4394 break; |
4395 case LCMP: | |
4396 error(-1); | |
4397 break; | |
219 | 4398 case LBAND: |
211 | 4399 printf("\tand %s,%s,%s\n",crn_l,crn_l,orn_l); |
4400 printf("\tand %s,%s,%s\n",crn_h,crn_h,orn_h); | |
4401 break; | |
219 | 4402 case LEOR: |
211 | 4403 printf("\txor %s,%s,%s\n",crn_l,crn_l,orn_l); |
4404 printf("\txor %s,%s,%s\n",crn_h,crn_h,orn_h); | |
4405 break; | |
219 | 4406 case LBOR: |
211 | 4407 printf("\tor %s,%s,%s\n",crn_l,crn_l,orn_l); |
4408 printf("\tor %s,%s,%s\n",crn_h,crn_h,orn_h); | |
4409 break; | |
219 | 4410 case LMUL: |
4411 case LUMUL: | |
273 | 4412 // code_save_stacks(); |
4413 // clear_ptr_cache(); | |
211 | 4414 dx=get_lregister(); |
223 | 4415 use_reg(dx); |
211 | 4416 drn_l = lregister_name_low(dx); |
4417 drn_h = lregister_name_high(dx); | |
4418 /* | |
4419 drn_l = l32( crn_l * orn_l); | |
4420 drn_h = h32( crn_l * orn_l); | |
4421 orn_l = l32( crn_h * orn_l); | |
4422 drn_h = drn_h + orn_l; | |
4423 crn_l = l32( crn_l * orn_h); | |
4424 crn_h = drn_h + crn_l; | |
4425 crn_l = drn_l; | |
4426 */ | |
4427 printf("\tmulhwu %s,%s,%s\n",drn_h,crn_l,orn_l); | |
228 | 4428 printf("\tmullw %s,%s,%s\n", drn_l,crn_l,orn_l); |
4429 printf("\tmullw %s,%s,%s\n", orn_l,crn_h,orn_l); | |
4430 printf("\tadd %s,%s,%s\n", drn_h,drn_h,orn_l); | |
4431 printf("\tmullw %s,%s,%s\n", crn_l,orn_h,crn_l); | |
4432 printf("\tadd %s,%s,%s\n", crn_h,drn_h,crn_l); | |
4433 printf("\tmr %s,%s\n", crn_l,drn_l); | |
211 | 4434 break; |
219 | 4435 case LDIV: |
255 | 4436 code_ldiv_lib(reg,oreg); // ___divdi3$stub |
221 | 4437 check_lreg(reg); |
211 | 4438 break; |
219 | 4439 case LUDIV: |
255 | 4440 code_ludiv_lib(reg,oreg); // ___udivdi3$stub |
221 | 4441 check_lreg(reg); |
211 | 4442 break; |
219 | 4443 case LMOD: |
255 | 4444 code_lmod_lib(reg,oreg); // ___moddi3$stub |
221 | 4445 check_lreg(reg); |
211 | 4446 break; |
219 | 4447 case LUMOD: |
255 | 4448 code_lumod_lib(reg,oreg); // ___umoddi3$stub |
221 | 4449 check_lreg(reg); |
211 | 4450 break; |
4451 default: | |
4452 error(-1); | |
4453 } | |
252 | 4454 if(ox!=-1) free_register(dx); |
221 | 4455 if(dx!=-1) free_register(dx); |
195 | 4456 } |
4457 | |
216 | 4458 int |
4459 code_lconst_op_p(int op,int e) | |
214 | 4460 { |
215 | 4461 int v; |
4462 if (car(e)==LCONST) { | |
222 | 4463 if (!(-32766<lcadr(e)&&lcadr(e)<32767)) return 0; |
287 | 4464 v = lcadr(e); |
215 | 4465 } else if (car(e)==CONST) { |
222 | 4466 if (!(-32766<cadr(e)&&cadr(e)<32767)) return 0; |
287 | 4467 v = cadr(e); |
222 | 4468 } else return 0; |
215 | 4469 |
214 | 4470 switch(op) { |
231 | 4471 case LLSHIFT: |
4472 case LULSHIFT: | |
4473 case LRSHIFT: | |
4474 case LURSHIFT: | |
215 | 4475 return (0<v&&v<31); |
219 | 4476 case LADD: |
4477 case LSUB: | |
215 | 4478 return 1; |
219 | 4479 case LBOR: |
215 | 4480 return (v>0); |
214 | 4481 default: |
4482 return 0; | |
4483 } | |
4484 } | |
4485 | |
216 | 4486 void |
221 | 4487 loprtc(int op,int creg,int e) |
213 | 4488 { |
221 | 4489 char *crn_h; |
4490 char *crn_l; | |
215 | 4491 char *grn; |
214 | 4492 int v; |
215 | 4493 int greg; |
4494 | |
221 | 4495 use_longlong(creg); |
4496 crn_h = lregister_name_high(creg); | |
4497 crn_l = lregister_name_low(creg); | |
4498 | |
222 | 4499 if (car(e)==LCONST) v = lcadr(e); |
4500 else if (car(e)==CONST) v = cadr(e); | |
213 | 4501 |
4502 switch(op) { | |
219 | 4503 case LLSHIFT: |
4504 case LULSHIFT: | |
215 | 4505 greg = get_register(); |
223 | 4506 use_reg(greg); |
215 | 4507 grn = register_name(greg); |
231 | 4508 printf("\tsrwi %s,%s,%d\n",grn,crn_l,32-v); |
4509 printf("\tslwi %s,%s,%d\n",crn_h,crn_h,v); | |
4510 printf("\tor %s,%s,%s\n",crn_h,grn,crn_h); | |
215 | 4511 printf("\tslwi %s,%s,%d\n",crn_l,crn_l,v); |
4512 free_register(greg); | |
213 | 4513 return; |
219 | 4514 case LRSHIFT: |
215 | 4515 greg = get_register(); |
223 | 4516 use_reg(greg); |
215 | 4517 grn = register_name(greg); |
4518 printf("\tsrwi %s,%s,%d\n",grn,crn_l,v); | |
231 | 4519 printf("\tinsrwi %s,%s,%d,0\n",grn,crn_h,v); |
215 | 4520 printf("\tsrawi %s,%s,%d\n",crn_h,crn_h,v); |
4521 printf("\tmr %s,%s\n",crn_l,grn); | |
4522 free_register(greg); | |
213 | 4523 return; |
219 | 4524 case LURSHIFT: |
215 | 4525 greg = get_register(); |
223 | 4526 use_reg(greg); |
215 | 4527 grn = register_name(greg); |
231 | 4528 printf("\tslwi %s,%s,%d\n",grn,crn_h,32-v); |
215 | 4529 printf("\tsrwi %s,%s,%d\n",crn_l,crn_l,v); |
231 | 4530 printf("\tor %s,%s,%s\n",crn_l,grn,crn_l); |
4531 printf("\tsrwi %s,%s,%d\n",crn_h,crn_h,v); | |
215 | 4532 free_register(greg); |
4533 return; | |
231 | 4534 case LSUB: |
4535 v = -v; | |
219 | 4536 case LADD: |
231 | 4537 printf("\taddic %s,%s,%d\n",crn_l,crn_l,v); |
4538 if (v<0) | |
4539 printf("\taddme %s,%s\n",crn_h,crn_h); | |
4540 else | |
4541 printf("\taddze %s,%s\n",crn_h,crn_h); | |
213 | 4542 break; |
219 | 4543 case LBOR: |
215 | 4544 printf("\tori %s,%s,lo16(%d)\n",crn_l,crn_l,v); |
213 | 4545 break; |
4546 default: | |
4547 error(-1); | |
4548 } | |
4549 } | |
4550 | |
4551 | |
211 | 4552 void |
4553 emit_lpop_free(int xreg) | |
195 | 4554 { |
211 | 4555 if (xreg>=0) |
4556 free_register(xreg); | |
195 | 4557 } |
4558 | |
211 | 4559 void |
4560 emit_lpush() | |
4561 { | |
4562 int new_reg; | |
212 | 4563 if (!is_longlong_reg(creg)) error(-1); |
211 | 4564 if (lreg_sp>MAX_MAX) error(-1); |
221 | 4565 new_reg = get_lregister(); /* ���Ф˼���(?) */ |
211 | 4566 lreg_stack[lreg_sp++] = creg; /* push ���뤫���˥쥸������Ȥ� */ |
4567 lreg = creg = new_reg; | |
4568 } | |
4569 | |
4570 void | |
239 | 4571 code_i2ll(int reg) |
195 | 4572 { |
215 | 4573 char *crn,*crn_h,*crn_l; |
239 | 4574 int reg0; |
4575 crn = register_name(reg0 = ireg); | |
4576 use_longlong(reg); | |
221 | 4577 crn_h = lregister_name_high(lreg); |
4578 crn_l = lregister_name_low(lreg); | |
239 | 4579 if (reg0!=regv_l(lreg)) |
215 | 4580 printf("\tmr %s,%s\n",crn_l,crn); |
4581 printf("\tsrawi %s,%s,31\n",crn_h,crn_l); | |
195 | 4582 } |
4583 | |
211 | 4584 void |
239 | 4585 code_i2ull(int reg) |
195 | 4586 { |
239 | 4587 code_i2ll(reg); |
195 | 4588 } |
4589 | |
211 | 4590 void |
239 | 4591 code_u2ll(int reg) |
195 | 4592 { |
215 | 4593 char *crn,*crn_h,*crn_l; |
239 | 4594 int reg0; |
4595 crn = register_name(reg0 = ireg); | |
4596 use_longlong(reg); | |
221 | 4597 crn_h = lregister_name_high(lreg); |
4598 crn_l = lregister_name_low(lreg); | |
239 | 4599 if (reg0!=regv_l(lreg)) |
215 | 4600 printf("\tmr %s,%s\n",crn_l,crn); |
4601 printf("\tli %s,0\n",crn_h); | |
195 | 4602 } |
4603 | |
211 | 4604 void |
4605 code_u2ull(int creg) | |
195 | 4606 { |
215 | 4607 code_u2ll(creg); |
195 | 4608 } |
4609 | |
211 | 4610 void |
239 | 4611 code_ll2i(int reg) |
195 | 4612 { |
219 | 4613 char *crn_l; |
239 | 4614 int reg0; |
4615 crn_l = lregister_name_low(reg0=lreg); | |
4616 use_int(reg); | |
4617 if (ireg!=regv_l(reg0)) | |
221 | 4618 printf("\tmr %s,%s\n",register_name(ireg),crn_l); |
195 | 4619 } |
4620 | |
211 | 4621 void |
4622 code_ll2u(int creg) | |
195 | 4623 { |
215 | 4624 code_ll2i(creg); |
195 | 4625 } |
4626 | |
211 | 4627 void |
4628 code_ull2i(int creg) | |
195 | 4629 { |
215 | 4630 code_ll2i(creg); |
195 | 4631 } |
4632 | |
211 | 4633 void |
4634 code_ull2u(int creg) | |
195 | 4635 { |
215 | 4636 code_ll2i(creg); |
195 | 4637 } |
4638 | |
4639 #if FLOAT_CODE | |
216 | 4640 |
211 | 4641 void |
239 | 4642 code_d2ll(int reg) |
195 | 4643 { |
215 | 4644 // fixdfdi$stub |
218 | 4645 set_freg(RET_FREGISTER,1); |
221 | 4646 extern_conv("__fixdfdi"); |
216 | 4647 set_lreg(RET_LREGISTER,0); |
239 | 4648 if (reg!=USE_CREG&®!=RET_LREGISTER) |
4649 use_longlong(reg); | |
195 | 4650 } |
4651 | |
211 | 4652 void |
239 | 4653 code_d2ull(int reg) |
195 | 4654 { |
218 | 4655 set_freg(RET_FREGISTER,1); |
221 | 4656 extern_conv("__fixunsdfdi"); |
216 | 4657 set_lreg(RET_LREGISTER,0); |
239 | 4658 if (reg!=USE_CREG&®!=RET_LREGISTER) |
4659 use_longlong(reg); | |
195 | 4660 } |
4661 | |
211 | 4662 void |
239 | 4663 code_f2ll(int reg) |
195 | 4664 { |
218 | 4665 set_freg(RET_FREGISTER,1); |
221 | 4666 extern_conv("__fixdfdi"); |
216 | 4667 set_lreg(RET_LREGISTER,0); |
239 | 4668 if (reg!=USE_CREG&®!=RET_LREGISTER) |
4669 use_longlong(reg); | |
195 | 4670 } |
4671 | |
211 | 4672 void |
239 | 4673 code_f2ull(int reg) |
195 | 4674 { |
218 | 4675 set_freg(RET_FREGISTER,1); |
221 | 4676 extern_conv("__fixsfdi"); |
216 | 4677 set_lreg(RET_LREGISTER,0); |
239 | 4678 if (reg!=USE_CREG&®!=RET_LREGISTER) |
4679 use_longlong(reg); | |
195 | 4680 } |
4681 | |
211 | 4682 void |
239 | 4683 code_ll2d(int reg) |
195 | 4684 { |
216 | 4685 set_lreg(RET_LREGISTER,1); |
221 | 4686 extern_conv("__floatdidf"); |
218 | 4687 set_freg(RET_FREGISTER,0); |
239 | 4688 if (reg!=USE_CREG&®!=RET_FREGISTER) |
4689 use_float(1,reg); | |
195 | 4690 } |
4691 | |
217 | 4692 |
211 | 4693 void |
239 | 4694 code_ll2f(int reg) |
195 | 4695 { |
216 | 4696 set_lreg(RET_LREGISTER,1); |
221 | 4697 extern_conv("__floatdisf"); |
218 | 4698 set_freg(RET_FREGISTER,0); |
239 | 4699 if (reg!=USE_CREG&®!=RET_FREGISTER) |
4700 use_float(0,reg); | |
195 | 4701 } |
4702 | |
211 | 4703 void |
4704 code_ull2d(int creg) | |
195 | 4705 { |
215 | 4706 code_ll2d(creg); |
195 | 4707 } |
4708 | |
211 | 4709 void |
4710 code_ull2f(int creg) | |
195 | 4711 { |
215 | 4712 code_ll2f(creg); |
195 | 4713 } |
4714 | |
4715 #endif | |
4716 | |
273 | 4717 static void |
4718 ladd(int creg,int reg,int dir) // creg=reg+dir | |
221 | 4719 { |
273 | 4720 printf("\taddic %s,%s,%d\n", |
4721 lregister_name_low(creg),lregister_name_low(reg), dir); | |
4722 printf("\tadd%s %s,%s\n", dir>0?"ze":"me", | |
4723 lregister_name_high(creg),lregister_name_high(reg)); | |
221 | 4724 } |
195 | 4725 |
211 | 4726 void |
4727 code_lpreinc(int e1,int e2,int reg) | |
195 | 4728 { |
222 | 4729 int dreg,xreg; |
211 | 4730 int dir=caddr(e1); |
4731 if (car(e2)==LREGISTER) { | |
221 | 4732 use_longlong(reg); |
273 | 4733 ladd(cadr(e2),cadr(e2),dir); |
4734 if (reg!=cadr(e2)) { | |
4735 lmove(reg,cadr(e2)); | |
211 | 4736 } |
4737 return; | |
4738 } | |
4739 g_expr(e2); | |
221 | 4740 if(!is_int_reg(creg)) error(-1); |
222 | 4741 emit_push(); |
221 | 4742 if (reg==USE_CREG) { |
4743 dreg=get_lregister(); if (!dreg) error(-1); | |
4744 set_lreg(dreg,0); // free old lreg==creg | |
4745 } else { | |
269 | 4746 dreg = reg; |
221 | 4747 } |
222 | 4748 xreg = emit_pop(0); |
269 | 4749 lload(xreg,dreg,0); |
273 | 4750 ladd(dreg,dreg,dir); |
269 | 4751 code_lassign(xreg,dreg); |
222 | 4752 emit_pop_free(xreg); |
195 | 4753 } |
4754 | |
211 | 4755 void |
4756 code_lpostinc(int e1,int e2,int reg) | |
195 | 4757 { |
222 | 4758 int dreg,nreg,xreg; |
211 | 4759 int dir=caddr(e1); |
4760 if (car(e2)==LREGISTER) { | |
221 | 4761 use_longlong(reg); |
273 | 4762 if (reg!=cadr(e2)) |
4763 lmove(reg,cadr(e2)); | |
4764 ladd(cadr(e2),cadr(e2),dir); | |
211 | 4765 return; |
4766 } | |
4767 g_expr(e2); | |
221 | 4768 if(!is_int_reg(creg)) error(-1); |
222 | 4769 emit_push(); |
221 | 4770 nreg=get_lregister(); if (!nreg) error(-1); |
4771 if (reg==USE_CREG) { | |
4772 dreg=get_lregister(); if (!dreg) error(-1); | |
4773 set_lreg(dreg,0); // free old lreg==creg | |
4774 } else { | |
269 | 4775 dreg = reg; |
221 | 4776 } |
222 | 4777 xreg = emit_pop(0); |
269 | 4778 lload(xreg,dreg,0); |
273 | 4779 ladd(nreg,dreg,dir); |
269 | 4780 code_lassign(xreg,nreg); |
222 | 4781 emit_pop_free(xreg); |
211 | 4782 free_register(nreg); |
195 | 4783 } |
4784 | |
211 | 4785 void |
221 | 4786 code_lassop(int op,int reg) |
195 | 4787 { |
211 | 4788 int xreg; |
4789 int edx,edx0=-1; | |
221 | 4790 |
4791 // (*creg) op = pop() | |
211 | 4792 xreg = emit_lpop(0); /* pop e3 value */ |
4793 if (!is_int_reg(creg)) error(-1); | |
221 | 4794 edx = ireg; |
223 | 4795 emit_push(); |
221 | 4796 use_longlong(reg); |
4797 if (regv_l(lreg)==edx || regv_h(lreg)==edx) { | |
285 | 4798 // this can't happen |
211 | 4799 edx0 = get_register(); if(!edx0) error(-1); |
4800 printf("# lassop\n\tmr %s,%s\n",register_name(edx0),register_name(edx)); | |
4801 edx = edx0; | |
4802 } | |
269 | 4803 lload(edx0=edx,reg,0); |
221 | 4804 ltosop(op,reg,xreg); |
269 | 4805 use_reg(reg); |
223 | 4806 edx = emit_pop(0); |
269 | 4807 code_lassign(edx,reg); |
4808 if (edx0!=-1) | |
4809 free_register(edx0); | |
4810 emit_pop_free(edx); | |
211 | 4811 emit_lpop_free(xreg); |
195 | 4812 } |
4813 | |
219 | 4814 void |
4815 code_register_lassop(int reg,int op) { | |
221 | 4816 // reg op = pop() |
219 | 4817 int xreg=emit_lpop(); |
221 | 4818 ltosop(op,reg,xreg); |
4819 emit_lpop_free(xreg); | |
219 | 4820 } |
4821 | |
195 | 4822 |
4823 #endif | |
4824 | |
95 | 4825 void |
4826 code_save_stacks() | |
4827 { | |
103 | 4828 int i,reg; |
101 | 4829 for(i=0;i<reg_sp;i++) { |
103 | 4830 if ((reg=reg_stack[i])>=0) { |
101 | 4831 code_assign_lvar( |
245 | 4832 (reg_stack[i]=new_lvar(SIZE_OF_INT)),reg,0); |
101 | 4833 reg_stack[i]= reg_stack[i]-REG_LVAR_OFFSET; |
368 | 4834 free_register(reg); |
101 | 4835 } |
4836 } | |
195 | 4837 #if FLOAT_CODE |
101 | 4838 for(i=0;i<freg_sp;i++) { |
103 | 4839 if ((reg=freg_stack[i])>=0) { |
101 | 4840 code_dassign_lvar( |
245 | 4841 (freg_stack[i]=new_lvar(SIZE_OF_DOUBLE)),reg,1); |
101 | 4842 freg_stack[i]= freg_stack[i]-REG_LVAR_OFFSET; |
368 | 4843 free_register(reg); |
101 | 4844 } |
4845 } | |
195 | 4846 #endif |
212 | 4847 #if LONGLONG_CODE |
4848 for(i=0;i<lreg_sp;i++) { | |
4849 if ((reg=lreg_stack[i])>=0) { | |
223 | 4850 code_lassign_lvar( |
245 | 4851 (lreg_stack[i]=new_lvar(SIZE_OF_LONGLONG)),reg); |
212 | 4852 lreg_stack[i]= lreg_stack[i]-REG_LVAR_OFFSET; |
368 | 4853 free_register(reg); |
212 | 4854 } |
4855 } | |
4856 #endif | |
96 | 4857 } |
4858 | |
4859 void | |
4860 emit_lib(char *p[]) | |
95 | 4861 { |
98 | 4862 while(*p) { |
4863 printf("%s\n",*p++); | |
96 | 4864 } |
4865 } | |
4866 | |
4867 void | |
4868 code_closing() | |
4869 { | |
195 | 4870 #if FLOAT_CODE |
96 | 4871 if (d2u_lib_used) emit_lib(d2u_lib); |
4872 if (u2d_lib_used) emit_lib(u2d_lib); | |
4873 if (float_one_lib_used) emit_lib(float_one_lib); | |
98 | 4874 if (float_zero_lib_used) emit_lib(float_zero_lib); |
96 | 4875 if (i2d_lib_used) emit_lib(i2d_lib); |
195 | 4876 #endif |
213 | 4877 #if LONGLONG_CODE |
218 | 4878 if (asld_lib_used) emit_lib(asld_lib); |
221 | 4879 if (lsrd_lib_used) emit_lib(lsrd_lib); |
4880 if (asrd_lib_used) emit_lib(asrd_lib); | |
4881 #if 0 | |
216 | 4882 if (lumod_lib_used) emit_lib(lumod_lib); |
4883 if (lmod_lib_used) emit_lib(lmod_lib); | |
4884 if (ludiv_lib_used) emit_lib(ludiv_lib); | |
4885 if (ldiv_lib_used) emit_lib(ldiv_lib); | |
221 | 4886 #endif |
213 | 4887 #if FLOAT_CODE |
218 | 4888 #if 0 |
216 | 4889 if (dl2ll_lib_used) emit_lib(dl2ll_lib); |
4890 if (d2ull_lib_used) emit_lib(d2ull_lib); | |
4891 if (f2ll_lib_used) emit_lib(f2ll_lib); | |
4892 if (f2ull_lib_used) emit_lib(f2ull_lib); | |
4893 if (ll2d_lib_used) emit_lib(ll2d_lib); | |
4894 if (ll2f_lib_used) emit_lib(ll2f_lib); | |
213 | 4895 #endif |
4896 #endif | |
218 | 4897 #endif |
97 | 4898 global_table(); |
108 | 4899 /* printf("\t.ident \"Micro-C compiled\"\n"); */ |
95 | 4900 } |
4901 | |
300 | 4902 #if CASE_CODE |
4903 | |
4904 int | |
382 | 4905 code_table_jump_p(int delta) { return 1; } |
300 | 4906 |
4907 void | |
302 | 4908 code_table_jump(int l,int csvalue,int delta,int max,int min,int dlabel) |
300 | 4909 { |
302 | 4910 int t,s,u=-1; |
4911 char *crn = register_name(csvalue); // can be t,s,u | |
300 | 4912 char *trn = register_name(t=get_register()); |
4913 char *srn = register_name(s=get_register()); | |
302 | 4914 char *urn; |
300 | 4915 |
4916 inc_cmpflag(); | |
4917 if (min>32767||min<-32765) { | |
302 | 4918 if (t==csvalue) { |
4919 code_const(min,s); | |
4920 printf("\tsub\t%s,%s,%s\n",trn,crn,srn); | |
4921 } else { | |
4922 code_const(min,t); | |
4923 printf("\tsub\t%s,%s,%s\n",trn,crn,trn); | |
4924 } | |
300 | 4925 } else { |
4926 printf("\taddi\t%s,%s,lo16(%d)\n",trn,crn,-min); | |
4927 } | |
302 | 4928 printf("\tcmplwi cr%d,%s,%d\n",cmpflag,trn,max-min); |
4929 printf("\tbgt-\tcr%d,L_%d\n",cmpflag,dlabel); | |
300 | 4930 inc_cmpflag(); |
4931 switch(delta) { | |
4932 case 1: printf("\tslwi %s,%s,2\n",trn,trn); break; | |
302 | 4933 case 2: |
4934 printf("\tli %s,1\n",srn); | |
4935 printf("\tand %s,%s,%s\n",srn,srn,trn); | |
4936 printf("\tcmplwi cr%d,%s,0\n",cmpflag,srn); | |
4937 printf("\tbne\tcr%d,L_%d\n",cmpflag,dlabel); | |
4938 printf("\tslwi %s,%s,1\n",trn,trn); | |
4939 break; | |
4940 case 4: | |
4941 printf("\tli %s,3\n",srn); | |
4942 printf("\tand %s,%s,%s\n",srn,srn,trn); | |
4943 printf("\tcmplwi cr%d,%s,0\n",cmpflag,srn); | |
4944 printf("\tbne\tcr%d,L_%d\n",cmpflag,dlabel); | |
4945 break; | |
300 | 4946 default: |
302 | 4947 urn = register_name(u=get_register()); |
4948 printf("\tli %s,%d\n",srn,delta); | |
4949 printf("\tdivwu %s,%s,%s\n",urn,trn,srn); | |
4950 printf("\tmullw %s,%s,%s\n",srn,urn,srn); | |
4951 printf("\tsubf %s,%s,%s\n",srn,trn,srn); | |
4952 printf("\tcmplwi cr%d,%s,0\n",cmpflag,srn); | |
4953 printf("\tbne\tcr%d,L_%d\n",cmpflag,dlabel); | |
4954 printf("\tslwi %s,%s,2\n",trn,urn); | |
300 | 4955 } |
4956 printf("\taddis %s,r31,ha16(L_%d-L_%d)\n", | |
4957 srn,l,code_base); | |
4958 printf("\tla %s,lo16(L_%d-L_%d)(%s)\n", | |
4959 srn,l,code_base,srn); | |
4960 printf("\tadd %s,%s,%s\n",trn,srn,trn); | |
4961 printf("\tlwz r0,0(%s)\n",trn); | |
4962 printf("\tadd r0,r0,%s\n",srn); | |
4963 printf("\tmtctr r0\n"); | |
4964 printf("\tbctr\n"); | |
4965 | |
4966 free_register(s); | |
4967 free_register(t); | |
302 | 4968 if (u!=-1) free_register(u); |
300 | 4969 } |
4970 | |
4971 void | |
4972 code_table_open(int l) | |
4973 { | |
4974 printf("\t.p2align 2\n"); | |
4975 fwddef(l); | |
4976 } | |
4977 | |
4978 void | |
4979 code_table_value(int label,int table_top) | |
4980 { | |
4981 printf("\t.long L_%d-L_%d\n",label,table_top); | |
4982 } | |
4983 | |
4984 void | |
4985 code_table_close() | |
4986 { | |
4987 } | |
4988 | |
4989 #endif | |
4990 | |
316 | 4991 #if ASM_CODE |
4992 | |
318 | 4993 /* |
320 | 4994 print an operand |
318 | 4995 */ |
4996 | |
4997 static void | |
320 | 4998 emit_asm_operand(int rstr) |
318 | 4999 { |
5000 if (car(rstr)==REGISTER) { | |
5001 printf("%s",register_name(cadr(rstr))); | |
5002 } else if (car(rstr)==CONST) { | |
5003 printf("%d",cadr(rstr)); | |
319 | 5004 } else if (car(rstr)==FNAME) { |
5005 printf("%s",(char*)cadr(rstr)); | |
318 | 5006 } else if (car(rstr)==STRING) { |
319 | 5007 printf("L_%d",cadr(rstr)); |
318 | 5008 } else { |
5009 error(-1); | |
5010 } | |
5011 } | |
5012 | |
320 | 5013 /* |
5014 prepare asm operands | |
5015 | |
5016 char *constraints sgtring | |
326 | 5017 int oeprand expr |
320 | 5018 int mode (ASM_INPUT,ASM_OUTPUT) |
5019 int replacement list | |
5020 int output operands count | |
5021 int output operands replacement list | |
5022 | |
5023 retrun replacement list | |
5024 list3( operands, next, clobber ) | |
5025 0 can be shared in input/output | |
5026 1 can't be used in input | |
5027 */ | |
5028 | |
327 | 5029 extern int |
5030 code_asm_operand(char *p,int e1,int mode,int repl,int n,int repl0) | |
318 | 5031 { |
5032 int r; | |
5033 int c; | |
5034 int val; | |
5035 int clobber = 0; | |
5036 | |
5037 printf("# constraint %s\n",p); | |
5038 if (*p=='=') { | |
5039 // output register | |
5040 p++; | |
5041 } | |
5042 if (*p=='&') { | |
5043 // earlyclobber | |
5044 p++; | |
5045 clobber = 1; | |
5046 } | |
5047 c = *p; | |
5048 if (c=='r') { | |
5049 if (mode==ASM_INPUT) { | |
5050 for(;repl0;repl0 = cadr(repl0)) { | |
5051 if (car(car(repl0))==REGISTER && caddr(repl0)==0) { | |
5052 r = cadr(car(repl0)); | |
5053 caddr(repl0) = ASM_USED; | |
5054 break; | |
5055 } | |
5056 } | |
5057 r = get_register(); | |
5058 } else { | |
5059 r = get_register(); | |
5060 } | |
5061 repl = list3(list2(REGISTER,r),repl,clobber); | |
5062 } else if (c=='m') { | |
319 | 5063 repl = list3(list2(0,0),repl,clobber); |
318 | 5064 } else if (c=='i') { |
368 | 5065 if (car(e1)==GVAR) { |
5066 e1=list3(FNAME,(int)(((NMTBL *)caddr(e1))->nm),0); | |
5067 } else if (car(e1)==FNAME) { | |
319 | 5068 e1=list3(FNAME,(int)(((NMTBL *)cadr(e1))->nm),0); |
5069 } else if (car(e1)==STRING) { | |
5070 val = emit_string_label(); | |
5071 ascii((char*)cadr(e1)); | |
5072 e1=list3(STRING,val,0); | |
5073 } else if (car(e1)==CONST) { | |
5074 } else error(-1); | |
318 | 5075 repl = list3(e1,repl,clobber); |
5076 } else if (digit(c)) { | |
5077 val = 0; | |
5078 do { val = val*10 + c-'0'; } while (digit(c=*p++)); | |
5079 if (val>MAX_ASM_REG) error(-1); // too large register | |
5080 if (n-val<0) error(-1); | |
5081 repl = list3(car(nth(n-val-1,repl0)),repl,clobber); | |
5082 } else error(-1); | |
5083 return repl; | |
5084 } | |
5085 | |
320 | 5086 void |
327 | 5087 code_free_asm_operand(int repl) |
318 | 5088 { |
5089 for(;repl;repl=cadr(repl)) { | |
5090 if (car(car(repl))==REGISTER) | |
5091 free_register(cadr(car(repl))); | |
5092 } | |
5093 } | |
5094 | |
320 | 5095 |
5096 extern void | |
327 | 5097 code_asm(char *asm_str,int repl) |
316 | 5098 { |
320 | 5099 int c,i,rstr,val; |
318 | 5100 char *p; |
320 | 5101 int reg[MAX_ASM_REG]; |
5102 | |
5103 text_mode(); | |
5104 c = *asm_str; | |
5105 if (c!='\t'&&c!=' ') printf("\t"); | |
5106 for(i=0;repl && i<MAX_ASM_REG;i++) { | |
5107 reg[i] = car(repl); | |
5108 repl = cadr(repl); | |
5109 } | |
5110 p = asm_str; | |
5111 while((c = *p++)) { | |
5112 if (c=='%') { | |
5113 c = *p++; | |
5114 if (!c) { break; | |
5115 } else if (c=='%') { | |
5116 printf("%%"); continue; | |
5117 } else if (!digit(c)) { | |
5118 printf("%%%c",c); continue; | |
5119 } | |
5120 val = 0; | |
5121 do { val = val*10 + c-'0'; } while (digit(c=*p++)) ; | |
5122 p--; | |
5123 if (val>MAX_ASM_REG) error(-1); // too large register | |
5124 rstr = reg[val]; | |
5125 emit_asm_operand(rstr); | |
5126 } else { | |
5127 printf("%c",c); | |
318 | 5128 } |
5129 } | |
320 | 5130 printf("\n"); |
316 | 5131 } |
5132 | |
5133 #endif | |
5134 | |
5135 | |
329 | 5136 #if BIT_FIELD_CODE |
5137 | |
5138 /* bit field alignment calcuration */ | |
5139 | |
5140 static void | |
5141 set_bitsz(int type,int *psign,int *pbitsz,int *palign,int *pl) | |
5142 { | |
5143 int sign=0,bitsz; | |
331 | 5144 int align,l=0; |
329 | 5145 switch(cadr(type)) { |
5146 case INT: sign=1; bitsz=32; align=4;break; | |
5147 case UNSIGNED: bitsz=32; align=4;break; | |
335 | 5148 case CHAR: sign=1; bitsz= 8; align=1;break; |
5149 case UCHAR: bitsz= 8; align=1;break; | |
329 | 5150 case SHORT: sign=1; bitsz=16; align=2;break; |
5151 case USHORT: sign=1; bitsz=16; align=2;break; | |
5152 case LONGLONG: sign=1; bitsz=64; align=4;l=1; break; | |
5153 case ULONGLONG: bitsz=64; align=4;l=1; break; | |
5154 default: error(-1); | |
5155 } | |
5156 *psign = sign; | |
5157 *pbitsz = bitsz; | |
5158 *palign = align; | |
5159 *pl = l; | |
5160 } | |
5161 | |
5162 /* | |
5163 bit field alignment calcuration | |
5164 this is architecture depenedent | |
5165 */ | |
5166 | |
5167 extern int | |
5168 code_bit_field_disp(int type,int *poffset,int *bfd,int *sz) | |
5169 { | |
331 | 5170 int sign,bitsz,align; |
329 | 5171 int i; |
5172 int bitpos = *bfd; | |
5173 int offset = *poffset; | |
5174 int l; | |
5175 int bitsize = cadddr(type); | |
331 | 5176 set_bitsz(type,&sign,&bitsz,&align,&l); |
329 | 5177 |
5178 if (bitsize>bitsz) { error(BTERR); bitsize = i; } | |
5179 | |
5180 /* bfd means previous bit field bit offset */ | |
5181 if (bitpos) { | |
5182 /* previous field is bit field and spaces may remain */ | |
5183 /* calc previsous offset */ | |
5184 | |
5185 i= offset-(bitpos+7)/8; | |
5186 | |
335 | 5187 for(l = bitpos;l>0;l -= 8,i++) { |
336 | 5188 if ((i & (align-1))==0 && l+bitsize <= bitsz) { |
335 | 5189 /* alignment is correct and space remains */ |
5190 *poffset=offset=i; | |
5191 i = l+bitsize; | |
5192 *bfd = i; | |
5193 *sz = (i+7)/8; | |
336 | 5194 // printf("# bitpos=%d bitsize=%d bitsz=%d offset=%d\n",l,bitsize,bitsz,*poffset); |
335 | 5195 return l; |
5196 } | |
5197 } | |
329 | 5198 } |
5199 | |
5200 /* first bit-field */ | |
5201 | |
5202 if ((i=(offset & (align-1)))) { | |
335 | 5203 *poffset = (offset += (align-i)); |
329 | 5204 } |
5205 bitpos = 0; | |
5206 *bfd = bitsize; | |
5207 *sz = (bitsize+7)/8; | |
5208 | |
336 | 5209 // printf("# bitpos=%d bitsize=%d bitsz=%d offset=%d\n",bitpos,bitsize,bitsz,*poffset); |
329 | 5210 return bitpos; |
5211 } | |
5212 | |
5213 /* bit field value */ | |
5214 | |
5215 /* reg contains container value, result should be in reg */ | |
5216 extern void | |
331 | 5217 code_bit_field(int type,int bitpos,int reg) |
329 | 5218 { |
331 | 5219 int sign,bitsz,l,align; |
329 | 5220 int bitsize = cadddr(type); |
5221 int i; | |
331 | 5222 set_bitsz(type,&sign,&bitsz,&align,&l); |
336 | 5223 // printf("# %d: bitpos=%d bitsize=%d bitsz=%d\n",lineno,bitpos,bitsize,bitsz); |
329 | 5224 /* this implementation returns -1 for int i:1; */ |
5225 if (l==1) { | |
5226 use_longlong(reg); | |
5227 /* shift left */ | |
331 | 5228 if (bitpos) |
335 | 5229 loprtc(LLSHIFT,reg,list2(CONST,bitpos)); |
329 | 5230 /* shift right */ |
5231 if ((i=bitsz-bitsize)) | |
335 | 5232 loprtc(sign?LRSHIFT:LURSHIFT,reg,list2(CONST,i)); |
329 | 5233 } else { |
5234 use_int(reg); | |
5235 /* shift left */ | |
336 | 5236 if ((i=bitpos+(32-bitsz))) |
5237 oprtc(LSHIFT,reg,list2(CONST,i)); | |
329 | 5238 /* shift right */ |
336 | 5239 if ((i=bitsz-bitsize+(32-bitsz))) |
335 | 5240 oprtc(sign?RSHIFT:URSHIFT,reg,list2(CONST,i)); |
329 | 5241 } |
5242 } | |
5243 | |
5244 /* bit field replacement */ | |
5245 | |
330 | 5246 static void |
331 | 5247 make_mask_and_or(int mask,int tmp,char *trn,char *crn,char *lrn) |
330 | 5248 { |
336 | 5249 // printf("# mask 0x%08x ~0x%08x\n",mask,~mask); |
330 | 5250 code_const(~mask,tmp); |
5251 printf("\tor %s,%s,%s\n",trn,crn,trn); | |
5252 /* do conjunction */ | |
5253 printf("\tand %s,%s,%s\n",lrn,trn,lrn); | |
5254 /* make or-mask */ | |
5255 code_const(mask,tmp); | |
5256 printf("\tand %s,%s,%s\n",trn,crn,trn); | |
5257 /* do disjunction */ | |
336 | 5258 printf("\tor %s,%s,%s\n",crn,trn,lrn); |
330 | 5259 } |
5260 | |
329 | 5261 extern void |
331 | 5262 code_bit_replace(int value,int lvalue,int type,int bitpos) |
329 | 5263 { |
331 | 5264 int sign,bitsz,l,align; |
329 | 5265 int bitsize = cadddr(type); |
330 | 5266 int mask = 0; |
5267 int tmp = -1; | |
331 | 5268 int i; |
330 | 5269 char *crn,*lrn,*trn; |
331 | 5270 set_bitsz(type,&sign,&bitsz,&align,&l); |
336 | 5271 // printf("# %d: bitpos=%d bitsize=%d bitsz=%d\n",lineno,bitpos,bitsize,bitsz); |
329 | 5272 if (l) { |
330 | 5273 use_longlong(value); |
5274 crn = lregister_name_low(value); | |
5275 lrn = lregister_name_low(lvalue); | |
329 | 5276 /* shift left */ |
330 | 5277 if ((i=bitsz-bitsize-bitpos)) |
335 | 5278 loprtc(LLSHIFT,value,list2(CONST,i)); |
330 | 5279 trn = register_name(tmp = get_register()); |
336 | 5280 if (bitpos+bitsize>=32) { |
330 | 5281 /* make and-mask lower */ |
336 | 5282 mask = make_mask(bitpos>=32?bitpos-32:0,bitpos+bitsize-32-1); |
330 | 5283 make_mask_and_or(mask,tmp,trn,crn,lrn); |
5284 } | |
5285 crn = lregister_name_high(value); | |
5286 lrn = lregister_name_high(lvalue); | |
5287 if (bitpos<32) { | |
5288 /* make and-mask upper */ | |
336 | 5289 mask = make_mask(bitpos,bitpos+bitsize>=32?31:bitpos+bitsize-1); |
330 | 5290 make_mask_and_or(mask,tmp,trn,crn,lrn); |
5291 } | |
329 | 5292 } else { |
330 | 5293 use_int(value); |
5294 crn = register_name(value); | |
5295 lrn = register_name(lvalue); | |
5296 /* shift left */ | |
5297 if ((i=bitsz-bitsize-bitpos)) | |
335 | 5298 oprtc(LSHIFT,value,list2(CONST,i)); |
330 | 5299 trn = register_name(tmp = get_register()); |
329 | 5300 /* make and-mask */ |
336 | 5301 mask = make_mask(bitpos+(32-bitsz),bitpos+bitsize-1+(32-bitsz)); |
330 | 5302 make_mask_and_or(mask,tmp,trn,crn,lrn); |
329 | 5303 } |
330 | 5304 if (tmp!=-1) free_register(tmp); |
329 | 5305 } |
5306 | |
365 | 5307 static void |
5308 make_mask_and_or_const(int mask,char *crn,int c) | |
5309 { | |
5310 char *trn; | |
5311 int tmp = -1; | |
5312 // printf("# mask 0x%08x ~0x%08x\n",mask,~mask); | |
5313 if ((~mask|c)!=-1) { | |
5314 trn = register_name(tmp=get_register()); | |
5315 code_const((~mask|c),tmp); | |
5316 /* do conjunction */ | |
5317 printf("\tand %s,%s,%s\n",crn,trn,crn); | |
5318 } | |
5319 /* make or-mask */ | |
5320 c = mask&c; | |
5321 if (c!=0) { | |
5322 /* do disjunction */ | |
5323 if (!((mask&c)&0xffff0000)) { | |
5324 printf("\tori %s,%s,lo16(%d)\n",crn,crn,c); | |
5325 } else { | |
5326 trn = register_name(tmp=get_register()); | |
5327 code_const(c,tmp); | |
5328 printf("\tor %s,%s,%s\n",crn,trn,crn); | |
5329 } | |
5330 } | |
5331 if (tmp!=-1) free_register(tmp); | |
5332 } | |
5333 | |
5334 extern void | |
5335 code_bit_replace_const(int value,int lvalue,int type,int bitpos) | |
5336 { | |
5337 int sign,bitsz,l,align; | |
5338 int bitsize = cadddr(type); | |
5339 int mask = 0; | |
5340 int i; | |
5341 int c; | |
5342 #if LONGLONG_CODE | |
5343 long long lc; | |
5344 #endif | |
5345 char *crn; | |
5346 set_bitsz(type,&sign,&bitsz,&align,&l); | |
5347 // printf("# %d: bitpos=%d bitsize=%d bitsz=%d\n",lineno,bitpos,bitsize,bitsz); | |
5348 if (l) { | |
5349 #if LONGLONG_CODE | |
5350 use_longlong(lvalue); | |
5351 crn = lregister_name_low(lvalue); | |
5352 /* shift left */ | |
5353 lc = lcadr(value); | |
5354 if ((i=bitsz-bitsize-bitpos)) | |
5355 lc <<= i; | |
5356 if (bitpos+bitsize>=32) { | |
5357 /* make and-mask lower */ | |
5358 mask = make_mask(bitpos>=32?bitpos-32:0,bitpos+bitsize-32-1); | |
5359 make_mask_and_or_const(mask,crn,(int)lc); | |
5360 } | |
5361 crn = lregister_name_high(lvalue); | |
5362 if (bitpos<32) { | |
5363 /* make and-mask upper */ | |
5364 mask = make_mask(bitpos,bitpos+bitsize>=32?31:bitpos+bitsize-1); | |
5365 make_mask_and_or_const(mask,crn,(int)(lc>>32)); | |
5366 } | |
5367 #endif | |
5368 } else { | |
5369 use_int(lvalue); | |
5370 crn = register_name(lvalue); | |
5371 /* shift left */ | |
5372 c = cadr(value); | |
5373 if ((i=bitsz-bitsize-bitpos)) | |
5374 c <<= i; | |
5375 /* make and-mask */ | |
5376 mask = make_mask(bitpos+(32-bitsz),bitpos+bitsize-1+(32-bitsz)); | |
5377 make_mask_and_or_const(mask,crn,c); | |
5378 } | |
5379 } | |
5380 | |
329 | 5381 #endif |
5382 | |
89 | 5383 /* end */ |