Mercurial > hg > CbC > old > device
annotate mc-code-mips.c @ 181:4beb7f079055
new file
author | kono |
---|---|
date | Sun, 30 Nov 2003 18:38:43 +0900 |
parents | 3b33c7daae95 |
children | f53d70110377 |
rev | line source |
---|---|
131 | 1 /* Micro-C Code Generatation Part for MIPS (PS2Linux) */ |
130 | 2 /* $Id$ */ |
3 | |
4 #define EXTERN extern | |
5 #include "mc.h" | |
6 #include "mc-code.h" | |
7 #include "mc-codegen.h" | |
8 | |
173 | 9 char *l_include_path[] = { |
10 "/usr/include/", | |
11 0 | |
12 }; | |
13 | |
130 | 14 #define TEXT_EMIT_MODE 0 |
15 #define DATA_EMIT_MODE 1 | |
16 #define RODATA_EMIT_MODE 2 | |
17 | |
18 static void data_mode(char *name); | |
163 | 19 static void ld_indexx(int byte, int n, int xreg,int sign); |
130 | 20 static void local_table(void); |
21 static void shift(char *op, int reg); | |
22 static int struct_push(int e4,int t,int arg); | |
23 | |
24 static int output_mode = TEXT_EMIT_MODE; | |
25 static int data_alignment = 0; | |
26 | |
27 static int code_disp_label; | |
152 | 28 static int disp_label; |
130 | 29 static int r1_offset_label; |
30 static int lvar_offset_label; | |
152 | 31 static int cprestore_label; |
130 | 32 |
33 static int reg_save; | |
34 static int freg_save; | |
35 | |
149 | 36 static int freg,ireg,dreg; |
148 | 37 |
38 /* mips requires two registers for compare */ | |
39 static int cmpreg = -1; | |
40 | |
130 | 41 int size_of_int = 4; |
42 int size_of_float = 4; | |
43 int size_of_double = 8; | |
44 int size_of_longlong = 8; | |
45 int endian = 1; | |
46 | |
148 | 47 int reg_sp; /* REGister Stack-Pointer */ |
48 int reg_stack[MAX_MAX]; /* 実際のレジスタの領域 */ | |
49 | |
50 /* floating point registers */ | |
51 | |
52 int freg_sp; /* floating point REGister Stack-Pointer */ | |
53 int freg_stack[MAX_MAX]; /* 実際のレジスタの領域 */ | |
54 | |
55 /* double floating point registers */ | |
56 | |
57 int dreg_sp; /* floating point REGister Stack-Pointer */ | |
58 int dreg_stack[MAX_MAX]; /* 実際のレジスタの領域 */ | |
130 | 59 |
60 #define REG_fp 1 | |
61 #define REG_sp 30 | |
62 #define REG_VAR_BASE 29 | |
131 | 63 #define REG_VAR_MIN 18 |
64 #define MIN_TMP_REG 4 | |
65 #define MAX_TMP_REG 11 | |
130 | 66 |
149 | 67 #define DREG_VAR_BASE 29 |
68 #define DREG_VAR_MIN 18 | |
69 #define MIN_TMP_DREG 4 | |
152 | 70 #define MAX_TMP_DREG 17 |
149 | 71 |
130 | 72 #define PTRC_REG 3 |
73 | |
74 #define FREG_VAR_BASE 31 | |
131 | 75 #define FREG_VAR_MIN 20 |
130 | 76 #define MIN_TMP_FREG 1 |
131 | 77 #define MAX_TMP_FREG 14 |
130 | 78 |
79 #define RET_REGISTER 3 | |
148 | 80 #define RET_FREGISTER (1+FREG_OFFSET) |
81 #define RET_DREGISTER (1+DREG_OFFSET) | |
130 | 82 |
148 | 83 int MAX_REGISTER=30; /* PowerPCのレジスタを10個まで使う*/ |
130 | 84 int MAX_FREGISTER=31; |
148 | 85 int MAX_DREGISTER=16; |
86 #define REAL_MAX_REGISTER 32 /* PowerPCのレジスタが32ということ*/ | |
87 #define REAL_MAX_FREGISTER 32 /* PowerPCのFレジスタが32ということ*/ | |
88 #define REAL_MAX_DREGISTER 31 /* PowerPCのDレジスタ番号が31ということ*/ | |
89 | |
90 #define FREG_OFFSET REAL_MAX_REGISTER | |
91 #define DREG_OFFSET (REAL_MAX_REGISTER+REAL_MAX_FREGISTER ) | |
130 | 92 |
131 | 93 int MAX_INPUT_REGISTER_VAR = 7-MIN_TMP_REG; |
94 int MAX_CODE_INPUT_REGISTER_VAR = 7-MIN_TMP_REG; | |
130 | 95 int MAX_INPUT_DREGISTER_VAR = 14-MIN_TMP_FREG; |
148 | 96 int MAX_INPUT_FREGISTER_VAR = 14-MIN_TMP_FREG; |
130 | 97 int MAX_CODE_INPUT_DREGISTER_VAR = 14-MIN_TMP_FREG; |
148 | 98 int MAX_CODE_INPUT_FREGISTER_VAR = 14-MIN_TMP_FREG; |
130 | 99 |
100 #define CREG_REGISTER MAX_TMP_REG | |
148 | 101 #define FREG_FREGISTER (MAX_TMP_FREG+FREG_OFFSET) |
149 | 102 #define DREG_DREGISTER (2+DREG_OFFSET) |
145 | 103 |
149 | 104 int powerpc_regs[REAL_MAX_REGISTER+REAL_MAX_FREGISTER+REAL_MAX_DREGISTER]; |
105 int powerpc_regv[REAL_MAX_REGISTER+REAL_MAX_FREGISTER+REAL_MAX_DREGISTER]; | |
138 | 106 |
151 | 107 int dreg_pair0[REAL_MAX_DREGISTER] = { |
148 | 108 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30 |
109 }; | |
151 | 110 int dreg_pair1[REAL_MAX_DREGISTER] = { |
148 | 111 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 |
112 }; | |
130 | 113 |
148 | 114 int *regv = powerpc_regv; |
115 int *regs = powerpc_regs; | |
130 | 116 |
117 static int max_reg_var, max_freg_var; | |
148 | 118 static int cond_reg=-1,cond_freg=-1,cond_dreg=-1; |
130 | 119 |
120 static char *reg_name[] = { | |
131 | 121 "$0","$1","$2","$3","$4","$5","$6","$7","$8","$9", |
122 "$10","$11","$12","$13","$14","$15","$16","$17","$18","$19", | |
123 "$20","$21","$22","$23","$24","$25","$26","$27","$28","$29", | |
148 | 124 "$30","$31", |
131 | 125 "$f0","$f1","$f2","$f3","$f4","$f5","$f6","$f7","$f8","$f9", |
126 "$f10","$f11","$f12","$f13","$f14","$f15","$f16","$f17","$f18","$f19", | |
127 "$f20","$f21","$f22","$f23","$f24","$f25","$f26","$f27","$f28","$f29", | |
128 "$f30","$f31" | |
130 | 129 }; |
130 | |
148 | 131 |
132 #define register_name(i) reg_name0(i) | |
133 #define fregister_name(i) reg_name0(i) | |
149 | 134 #define dregister_name0(i) reg_name1(i,dreg_pair0) |
135 #define dregister_name1(i) reg_name1(i,dreg_pair1) | |
148 | 136 |
149 | 137 static char * |
148 | 138 reg_name0(int i) |
139 { | |
140 if (i<=REAL_MAX_REGISTER+REAL_MAX_FREGISTER) | |
141 return reg_name[i]; | |
149 | 142 else { |
148 | 143 error(-1); |
149 | 144 return reg_name[0]; |
145 } | |
148 | 146 } |
147 | |
149 | 148 static char * |
151 | 149 reg_name1(int i,int *d) |
149 | 150 { |
151 if (i<=REAL_MAX_REGISTER+REAL_MAX_FREGISTER) { | |
152 error(-1); | |
153 return reg_name[0]; | |
154 } else | |
155 return reg_name[d[i-DREG_OFFSET]]; | |
156 } | |
157 | |
158 | |
148 | 159 #define is_int_reg(i) (0<=i&&i<REAL_MAX_REGISTER) |
160 #define is_float_reg(i) (REAL_MAX_REGISTER<=i&&i<REAL_MAX_FREGISTER+REAL_MAX_REGISTER) | |
149 | 161 #define is_double_reg(i) (REAL_MAX_REGISTER+REAL_MAX_FREGISTER<=i&&i<REAL_MAX_FREGISTER+REAL_MAX_REGISTER+REAL_MAX_DREGISTER) |
148 | 162 |
130 | 163 |
148 | 164 int use_int(int i) { |
165 if (!is_int_reg(i)) i = ireg; | |
166 if (!regs[i]) regs[i]=1; | |
167 return i; | |
168 } | |
169 | |
170 int use_float(int i) { | |
171 if (!is_float_reg(i)) i = freg; | |
172 if (!regs[i]) regs[i]=1; | |
173 return i; | |
174 } | |
175 | |
176 int use_double(int i) { | |
177 if (!is_double_reg(i)) i = dreg; | |
178 if (!regs[i]) regs[i]=1; | |
179 return i; | |
180 } | |
130 | 181 |
149 | 182 static int code_d1(double d); |
183 static int code_d2(double d); | |
184 | |
130 | 185 static void code_save_stacks(); |
186 static void code_save_input_registers(); | |
187 static void set_creg(int,int); | |
188 static void set_freg(int,int); | |
148 | 189 static void set_dreg(int,int); |
130 | 190 |
136
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
191 static int mask_label; |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
192 static int mask1_label; |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
193 static int fmask_label; |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
194 static int fmask1_label; |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
195 |
131 | 196 static FILE *asi; |
148 | 197 |
153 | 198 static int max_func_args; |
199 static int max_func_iargs; | |
200 static int my_func_args; | |
130 | 201 #define ARG_LVAR_OFFSET 0x10000000 |
202 | |
131 | 203 #define DOT_SIZE 1 |
204 | |
130 | 205 /* |
206 | |
152 | 207 Reorder is automatically done in assembler. |
208 delayed slot done within .set noreorder. | |
209 | |
130 | 210 r0 return value etc. |
152 | 211 $2,$3 return value. (dpcmp return value on $2) |
212 $0 special register | |
213 $4-$7 input register | |
130 | 214 r22-r29 saved register variable (input register for code segement) |
152 | 215 $31 stack pointer |
216 $fp frame pointer | |
130 | 217 |
152 | 218 $f0 return value etc. |
219 $f14,$f12 input register | |
220 $f20-$f31 saved register variable | |
130 | 221 |
222 function call stack frame | |
223 <------r1_offset------------------------------> | |
224 <------------lvar_offset-------> | |
225 r+ +------------+---+---------------+----------+--------------+----+ - | |
226 callee arg xx register save local caller arg xx | |
227 reg_save disp max_func_args*size_of_int | |
228 lvar>0 lvar<0 lvar>0x1000 0000 | |
229 | |
230 code segment stack frame | |
231 | |
232 * gotoを呼び出した関数のr1 ! r1(goto前のr1) | |
233 # * r30 <---r1_offset---------> r1 | |
234 r+ +----------+--+----------+----------------+-----------+----------+----+ | |
235 cousin arg xx reg save !callee arg !code local caller arg xx | |
236 r20-r29 lvar>0 lvar<0 lvar>0x1000 000 | |
237 f20-f31 <-my_func_args--><--disp-----><-max_func_arg-> | |
238 *size_of_int *size_of_int | |
239 | |
240 */ | |
241 int arg_offset = 24; int arg_offset1 = 24; int disp_offset = -12; | |
242 #define func_disp_offset 60 | |
243 #define r1_offset func_disp_offset+12 | |
244 int code_disp_offset = 0; int jump_offset = 0; | |
245 #define CODE_LVAR l+code_disp_offset | |
246 #define CODE_CALLER_ARG (l-ARG_LVAR_OFFSET)+arg_offset1 | |
247 #define FUNC_LVAR l+disp_offset | |
248 #define CALLER_ARG (l-ARG_LVAR_OFFSET)+arg_offset1 | |
249 #define CALLEE_ARG l+arg_offset | |
250 | |
251 void | |
252 code_offset_set() | |
253 { | |
254 #if 0 | |
255 int l; | |
256 #endif | |
257 int lvar_offsetv = -disp+max_func_args*size_of_int+func_disp_offset; | |
258 int r1_offsetv = -disp+max_func_args*size_of_int-reg_save+r1_offset; | |
153 | 259 printf("L_%d = %d\n",lvar_offset_label,lvar_offsetv); |
260 printf("L_%d = %d\n",r1_offset_label,r1_offsetv); | |
130 | 261 #if 0 |
262 printf("# function %s\n",fnptr->nm); | |
263 l = ARG_LVAR_OFFSET; | |
264 printf("# offset call0\t%d\n",CALLER_ARG); | |
265 l = ARG_LVAR_OFFSET+max_func_args*size_of_int; | |
266 printf("# offset calln\t%d %d\n",CALLER_ARG,max_func_args*size_of_int); | |
267 l = disp; | |
268 printf("# offset lvarn\t%d %d\n",FUNC_LVAR+lvar_offsetv,disp); | |
269 l = 0; | |
270 printf("# offset lvar0\t%d\n",FUNC_LVAR+lvar_offsetv); | |
271 l = -reg_save; | |
272 printf("# offset regs\t%d\n",FUNC_LVAR+lvar_offsetv); | |
273 printf("# offset r1off\t%d\n",r1_offsetv); | |
274 l = 0; | |
275 printf("# offset carg0\t%d\n",CALLEE_ARG+r1_offsetv); | |
276 l = my_func_args; | |
277 printf("# offset cargn\t%d %d\n",CALLEE_ARG+r1_offsetv,my_func_args); | |
278 #endif | |
279 } | |
280 | |
281 static void | |
131 | 282 lvar(int l) |
130 | 283 { |
284 if (fnptr->sc==CODE) { | |
148 | 285 if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ |
286 printf("%d($fp)\n",CODE_CALLER_ARG); | |
287 } else | |
288 printf("%d($fp)\n",CODE_LVAR); | |
130 | 289 } else if (l<0) { /* local variable */ |
148 | 290 printf("%d+L_%d($fp)\n",FUNC_LVAR,lvar_offset_label); |
130 | 291 } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ |
148 | 292 printf("%d($fp)\n",CALLER_ARG); |
130 | 293 } else { /* callee's arguments */ |
148 | 294 printf("%d+L_%d($fp)\n",CALLEE_ARG,r1_offset_label); |
130 | 295 } |
296 } | |
297 | |
298 static void | |
131 | 299 lvar_address(int l,int creg) |
130 | 300 { |
301 if (fnptr->sc==CODE) { | |
148 | 302 if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ |
303 printf("\taddu\t%s,$fp,%d\n",register_name(creg),CODE_CALLER_ARG); | |
304 } else | |
305 printf("\taddu\t%s,$fp,%d\n",register_name(creg),CODE_LVAR); | |
130 | 306 } else if (l<0) { /* local variable */ |
148 | 307 printf("\taddu\t%s,$fp,%d+L_%d\n",register_name(creg),FUNC_LVAR,lvar_offset_label); |
130 | 308 } else if (l>=ARG_LVAR_OFFSET) { /* caller's arguments */ |
148 | 309 printf("\taddu\t%s,$fp,%d\n",register_name(creg),CALLER_ARG); |
130 | 310 } else { /* callee's arguments */ |
148 | 311 printf("\taddu\t%s,$fp,%d+L_%d\n",register_name(creg),CALLEE_ARG,r1_offset_label); |
130 | 312 } |
313 } | |
314 | |
315 void | |
316 code_lvar(int e2,int creg) { | |
131 | 317 lvar_address(e2,creg); |
130 | 318 regv[creg]=1; |
319 } | |
320 | |
321 void | |
322 code_init(void) | |
323 { | |
131 | 324 /* this is called once program call */ |
130 | 325 } |
326 | |
327 void | |
328 gexpr_code_init(void){ | |
329 regv[creg]=0; | |
148 | 330 regv[freg]=0; |
130 | 331 } |
332 | |
137 | 333 void |
148 | 334 code_gexpr(int e){ |
335 if (is_int_reg(creg) && creg!=ireg) error(-1); | |
336 } | |
337 | |
338 | |
339 void | |
137 | 340 code_arg_register(NMTBL *fnptr) |
341 { | |
342 int args = fnptr->dsp; | |
343 NMTBL *n; | |
344 int reg_var = 0; | |
345 int freg_var = 0; | |
346 int type; | |
347 int reg; | |
348 int is_code0 = is_code(fnptr); | |
130 | 349 |
137 | 350 while (args) { |
351 /* process in reverse order */ | |
352 n = (NMTBL*)caddr(args); | |
353 type = n->ty; | |
354 if (scalar(type)) { | |
355 if ((reg = get_input_register_var(reg_var,n,is_code0))) { | |
356 n->sc = REGISTER; | |
357 n->dsp = cadr(reg); | |
358 regv[n->dsp]= 1; | |
359 regs[n->dsp]= INPUT_REG; | |
360 reg_var++; | |
361 cadddr(args)=size_of_int; /* why we need this? */ | |
362 } | |
363 } else if (type==FLOAT) { | |
138 | 364 if ((reg = get_input_dregister_var(freg_var,n,is_code0,0))) { |
141 | 365 n->sc = FREGISTER; |
137 | 366 n->dsp = cadr(reg); |
148 | 367 regv[n->dsp]= 1; |
368 regs[n->dsp]= INPUT_REG; | |
369 freg_var++; | |
137 | 370 cadddr(args)=size(type); /* why we need this? */ |
371 } | |
372 } else if (type==DOUBLE) { | |
141 | 373 if ((reg = get_input_dregister_var(reg_var,n,is_code0,1))) { |
137 | 374 n->sc = DREGISTER; |
375 n->dsp = cadr(reg); | |
148 | 376 regv[n->dsp]= 1; |
377 regs[n->dsp]= INPUT_REG; | |
141 | 378 reg_var+=2; |
137 | 379 cadddr(args)=size(type); /* why we need this? */ |
380 } | |
381 } | |
382 args = cadr(args); | |
383 } | |
130 | 384 if (is_function(fnptr)) |
148 | 385 code_save_input_registers(); |
130 | 386 } |
387 | |
388 int | |
389 get_register(void) | |
390 { /* 使われていないレジスタを調べる */ | |
391 int i,reg; | |
392 for(i=MAX_TMP_REG;i>MIN_TMP_REG;i--) { | |
393 if (regs[i]) continue; /* 使われている */ | |
394 regs[i]=USING_REG; /* そのレジスタを使うことを宣言し */ | |
395 return i; /* その場所を表す番号を返す */ | |
396 } | |
397 /* search register stack */ | |
398 for(i=0;i<reg_sp;i++) { | |
399 if ((reg=reg_stack[i])>=0) { | |
400 code_assign_lvar( | |
401 (reg_stack[i]=new_lvar(size_of_int)),reg,0); | |
402 reg_stack[i]= reg_stack[i]-REG_LVAR_OFFSET; | |
403 return reg; | |
404 } | |
405 } | |
148 | 406 /* search dregister stack */ |
407 for(i=0;i<dreg_sp;i++) { | |
408 if ((reg=dreg_stack[i])>=0) { | |
409 code_dassign_lvar( | |
410 (dreg_stack[i]=new_lvar(size_of_double)),reg,1); | |
411 dreg_stack[i]= dreg_stack[i]-REG_LVAR_OFFSET; | |
149 | 412 free_register(reg); |
148 | 413 return get_register(); /* 今度は必ずある */ |
414 } | |
415 } | |
131 | 416 for(i=0;i<REG_VAR_BASE-REG_VAR_MIN;i++) { |
417 reg =REG_VAR_BASE-i; | |
418 if (! regs[reg]) { /* 使われていないなら */ | |
419 regs[reg]=USING_REG; /* そのレジスタを使うことを宣言し */ | |
420 regv[reg]=0; | |
421 if (i>max_reg_var) max_reg_var=i; | |
422 return reg; | |
423 } | |
424 } | |
130 | 425 /* 空いている場所がないなら、エラー (いったい誰が使ってるの?) */ |
148 | 426 error(HPERR); return creg; |
130 | 427 } |
428 | |
429 int | |
430 pop_register(void) | |
431 { /* レジスタから値を取り出す */ | |
432 return reg_stack[--reg_sp]; | |
433 } | |
434 | |
148 | 435 static int |
436 get_dregister1() { | |
149 | 437 int i; |
151 | 438 for(i=MAX_TMP_DREG+DREG_OFFSET;i>MIN_TMP_DREG+DREG_OFFSET;i--) { |
148 | 439 if (regs[i]) continue; /* 使われている */ |
440 if (regs[dreg_pair0[i-DREG_OFFSET]]) continue; | |
441 if (regs[dreg_pair1[i-DREG_OFFSET]]) continue; | |
442 regs[dreg_pair0[i-DREG_OFFSET]]=USING_REG; | |
443 regs[dreg_pair1[i-DREG_OFFSET]]=USING_REG; | |
444 regs[i]=USING_REG; /* そのレジスタを使うことを宣言し */ | |
445 return i; /* その場所を表す番号を返す */ | |
446 } | |
447 return -1; | |
448 } | |
449 | |
450 static int | |
451 get_dregister0() | |
452 { | |
149 | 453 int reg,i; |
148 | 454 /* とりあえず、空き int register pair を探す */ |
455 if ((i=get_dregister1())!=-1) { | |
456 return i; | |
457 } | |
458 /* search dregister stack */ | |
459 for(i=0;i<dreg_sp;i++) { | |
460 if ((reg=dreg_stack[i])>=0) { | |
461 code_dassign_lvar( | |
462 (dreg_stack[i]=new_lvar(size_of_double)),reg,1); | |
463 dreg_stack[i]= dreg_stack[i]-REG_LVAR_OFFSET; | |
152 | 464 return reg; |
148 | 465 } |
466 } | |
467 /* clear integer register stack */ | |
468 for(i=0;i<reg_sp;i++) { | |
469 if ((reg=reg_stack[i])>=0) { | |
470 code_assign_lvar( | |
471 (reg_stack[i]=new_lvar(size_of_int)),reg,0); | |
472 reg_stack[i]= reg_stack[i]-REG_LVAR_OFFSET; | |
473 free_register(reg); | |
474 } | |
475 } | |
476 if ((i=get_dregister1())!=-1) { | |
477 return i; | |
478 } | |
479 | |
480 error(REG_ERR); return dreg; | |
481 } | |
482 | |
483 static int | |
484 get_fregister0() | |
130 | 485 { /* 使われていないレジスタを調べる */ |
148 | 486 int i,reg; |
487 for(i=MAX_TMP_FREG+FREG_OFFSET;i>MIN_TMP_FREG+FREG_OFFSET;i--) { | |
488 if (regs[i]) continue; /* 使われている */ | |
489 regs[i]=USING_REG; /* そのレジスタを使うことを宣言し */ | |
130 | 490 return i; /* その場所を表す番号を返す */ |
491 } | |
492 /* search register stack */ | |
493 for(i=0;i<freg_sp;i++) { | |
494 if ((reg=freg_stack[i])>=0) { | |
495 code_dassign_lvar( | |
153 | 496 (freg_stack[i]=new_lvar(size_of_float)),reg,0); |
130 | 497 freg_stack[i]= freg_stack[i]-REG_LVAR_OFFSET; |
498 return reg; | |
499 } | |
500 } | |
131 | 501 for(i=0;i<FREG_VAR_BASE-REG_VAR_MIN;i++) { |
148 | 502 reg =FREG_VAR_BASE-i+FREG_OFFSET; |
503 if (! regs[reg]) { /* 使われていないなら */ | |
504 regs[reg]=USING_REG; /* そのレジスタを使うことを宣言し */ | |
505 regv[reg]=0; | |
131 | 506 if (i>max_freg_var) max_freg_var=i; |
507 return reg; | |
508 } | |
509 } | |
130 | 510 /* 空いている場所がないなら、エラー (いったい誰が使ってるの?) */ |
511 error(REG_ERR); return freg; | |
512 } | |
513 | |
148 | 514 int |
515 get_dregister(int d) | |
149 | 516 { |
148 | 517 if (d) { |
518 return get_dregister0(); | |
519 } else { | |
520 return get_fregister0(); | |
521 } | |
522 } | |
523 | |
130 | 524 int |
525 pop_fregister(void) | |
526 { /* レジスタから値を取り出す */ | |
527 return freg_stack[--freg_sp]; | |
528 } | |
529 | |
148 | 530 int |
531 pop_dregister(void) | |
532 { /* レジスタから値を取り出す */ | |
533 return dreg_stack[--dreg_sp]; | |
534 } | |
535 | |
130 | 536 void |
537 emit_pop_free(int xreg) | |
538 { | |
539 if (xreg>=0) | |
540 free_register(xreg); | |
541 } | |
542 | |
543 void | |
544 free_register(int i) { /* いらなくなったレジスタを開放 */ | |
148 | 545 int i0,i1; |
546 if (i<0||MAX_FREGISTER+FREG_OFFSET+REAL_MAX_DREGISTER<i) error(-1); | |
547 if (is_double_reg(i)) { | |
548 i0 = dreg_pair0[i-DREG_OFFSET]; | |
549 regv[i0]=regs[i0]=0; | |
550 i1 = dreg_pair1[i-DREG_OFFSET]; | |
551 regv[i1]=regs[i1]=0; | |
552 } | |
130 | 553 regv[i]=regs[i]=0; |
554 } | |
555 | |
556 int | |
138 | 557 get_input_dregister_var(int i,NMTBL *n,int is_code,int d) |
130 | 558 { |
148 | 559 if (d) { |
560 if (is_code) { | |
561 if(!(i<DREG_VAR_BASE-DREG_VAR_MIN)) return 0; | |
562 i = DREG_VAR_BASE-i+DREG_OFFSET; | |
141 | 563 } else { |
148 | 564 if (i<0||i>=MAX_INPUT_DREGISTER_VAR) return 0; |
565 i = i+MIN_TMP_DREG+DREG_OFFSET; | |
141 | 566 } |
148 | 567 return list3(DREGISTER,i,(int)n); |
141 | 568 } else { |
148 | 569 if (is_code) { |
570 if(!(i<FREG_VAR_BASE-FREG_VAR_MIN)) return 0; | |
571 i = FREG_VAR_BASE-i+FREG_OFFSET; | |
141 | 572 } else { |
148 | 573 if (i<0||i>=MAX_INPUT_FREGISTER_VAR) return 0; |
574 i = i+MIN_TMP_FREG+FREG_OFFSET; | |
141 | 575 } |
148 | 576 return list3(FREGISTER,i,(int)n); |
141 | 577 } |
130 | 578 } |
579 | |
580 int | |
581 get_input_register_var(int i,NMTBL *n,int is_code) | |
582 { | |
583 if (is_code) { | |
131 | 584 if(!(i<REG_VAR_BASE-REG_VAR_MIN)) return 0; |
130 | 585 i = REG_VAR_BASE-i; |
586 } else { | |
148 | 587 if (i<0||i>=MAX_INPUT_REGISTER_VAR) return 0; |
588 i = i+MIN_TMP_REG; | |
589 } | |
590 return list3(REGISTER,i,(int)n); | |
591 } | |
592 | |
593 /* double register case? */ | |
594 | |
595 int | |
596 get_input_register_var_1(int i,NMTBL *n,int is_code) | |
597 { | |
598 if (is_code) { | |
599 if(!(i<REG_VAR_BASE-REG_VAR_MIN)) return 0; | |
600 i = REG_VAR_BASE-i; | |
601 } else { | |
602 if (i<0||i>=MAX_INPUT_REGISTER_VAR+1) return 0; | |
130 | 603 i = i+MIN_TMP_REG; |
604 } | |
605 return list3(REGISTER,i,(int)n); | |
606 } | |
607 | |
608 int | |
137 | 609 free_register_count(int d) |
130 | 610 { |
611 int i,count,fcount; | |
612 fcount = count = 0; | |
613 for(i=0;i<MAX_REGISTER;i++) { | |
614 if (! regs[i] && ! regv[i]) count++; | |
615 } | |
616 for(i=0;i<MAX_FREGISTER;i++) { | |
148 | 617 if (! regs[i+FREG_OFFSET] && ! regv[i+FREG_OFFSET]) fcount++; |
130 | 618 } |
148 | 619 printf("# free reg %d freg %d\n",count,fcount); |
137 | 620 return d?fcount:count; |
130 | 621 } |
622 | |
623 int | |
624 register_full(void) | |
625 { | |
626 int i; | |
627 for(i=0;i<MAX_REGISTER;i++) { | |
628 if (! regs[i]) { | |
629 return 0; | |
630 } | |
631 } | |
632 return 1; | |
633 } | |
634 | |
635 void | |
636 free_all_register(void) | |
637 { | |
638 int i; | |
639 for(i=0;i<MAX_REGISTER;i++) { regs[i]=0; regv[i]=0; } | |
148 | 640 for(i=0;i<MAX_FREGISTER;i++) { regs[i+FREG_OFFSET]=0; regv[i+FREG_OFFSET]=0; } |
641 for(i=0;i<MAX_DREGISTER;i++) { regs[i+DREG_OFFSET]=0; regv[i+DREG_OFFSET]=0; } | |
130 | 642 creg = get_register(); |
138 | 643 freg = get_dregister(0); |
150 | 644 dreg = DREG_DREGISTER; |
130 | 645 set_creg(CREG_REGISTER,0); |
646 set_freg(FREG_FREGISTER,0); | |
148 | 647 set_dreg(DREG_DREGISTER,0); |
130 | 648 return; |
649 } | |
650 | |
651 void | |
652 register_usage(char *s) | |
653 { | |
654 #if 0 | |
655 int i; | |
656 #endif | |
657 if (chk) return; | |
658 if (!lsrc) return; | |
659 printf("# %d: %s:",lineno,s); | |
150 | 660 printf(" creg=%s ireg=%s freg=%s dreg=%s", |
661 is_int_reg(creg)?register_name(creg): | |
662 is_float_reg(creg)?fregister_name(creg): | |
663 is_double_reg(creg)?dregister_name0(creg):"bad", | |
664 register_name(ireg),fregister_name(freg),dregister_name0(dreg)); | |
130 | 665 #if 0 |
666 printf("\n# regs:"); | |
667 for(i=0;i<MAX_REGISTER;i++) { printf("%d",regv[i]); } | |
668 printf(":"); | |
669 for(i=0;i<MAX_REGISTER;i++) { printf("%d",regs[i]); } | |
670 printf("\n# freg:"); | |
148 | 671 for(i=0;i<MAX_FREGISTER;i++) { printf("%d",regs[i+FREG_OFFSET]); } |
130 | 672 for(i=reg_sp;i>=0;i--) { |
673 if(reg_stack[i]>=0) | |
148 | 674 printf(" %s",register_name(reg_stack[i])); |
130 | 675 } |
676 #endif | |
677 printf("\n"); | |
678 } | |
679 | |
680 void | |
681 gexpr_init(void) | |
682 { | |
683 while(reg_sp > 0) { | |
684 free_register(reg_stack[--reg_sp]); | |
685 } | |
148 | 686 while(freg_sp > 0) { |
687 free_register(freg_stack[--freg_sp]); | |
688 } | |
689 while(dreg_sp > 0) { | |
690 free_register(dreg_stack[--dreg_sp]); | |
691 } | |
130 | 692 if (cond_freg!=-1) { |
148 | 693 if(car(cond_freg)==FREGISTER) free_register(cadr(cond_freg)); |
130 | 694 cond_freg=-1; |
695 } | |
148 | 696 if (cond_dreg!=-1) { |
697 if(car(cond_dreg)==DREGISTER) free_register(cadr(cond_dreg)); | |
698 cond_dreg=-1; | |
699 } | |
130 | 700 if (cond_reg!=-1) { |
701 if(car(cond_reg)==REGISTER) free_register(cadr(cond_reg)); | |
702 cond_reg=-1; | |
703 } | |
148 | 704 cmpreg = -1; |
130 | 705 text_mode(); |
706 gexpr_code_init(); | |
707 register_usage("gexpr_init"); | |
708 } | |
709 | |
710 | |
711 void | |
712 emit_init(void) | |
713 { | |
714 free_all_register(); | |
715 max_reg_var=-1; max_freg_var=-1; | |
716 reg_sp = 0; | |
717 freg_sp = 0; | |
148 | 718 dreg_sp = 0; |
130 | 719 text_mode(); |
720 } | |
721 | |
722 int | |
723 register_var(int r) { | |
724 return r; | |
725 } | |
726 | |
727 | |
728 int | |
729 get_register_var(NMTBL *n) | |
730 { | |
731 int i; | |
732 for(i=0;i<REG_VAR_BASE-REG_VAR_MIN;i++) { | |
148 | 733 if (! regs[REG_VAR_BASE-i]) { /* 使われていないなら */ |
734 /* そのレジスタを使うことを宣言し */ | |
735 regs[REG_VAR_BASE-i]=USING_REG; | |
736 regv[REG_VAR_BASE-i]=0; | |
130 | 737 if (i>max_reg_var) max_reg_var=i; |
738 /* その場所を表す番号を返す */ | |
739 return list3(REGISTER,REG_VAR_BASE-i,(int)n); | |
148 | 740 } |
130 | 741 } |
742 return list2(LVAR,new_lvar(size_of_int)); | |
743 } | |
744 | |
745 int | |
746 fregister_var(int r) { | |
747 return r; | |
748 } | |
749 | |
750 int | |
138 | 751 get_dregister_var(NMTBL *n,int d) |
130 | 752 { |
148 | 753 int i,j; |
754 if (d) { | |
755 for(i=0;i<DREG_VAR_BASE-DREG_VAR_MIN;i++) { | |
149 | 756 if (! regs[j=(DREG_VAR_BASE-i+DREG_OFFSET)]) { /* 使われていないなら */ |
148 | 757 if (regs[dreg_pair0[j]] || regs[dreg_pair1[j]]) continue; |
758 regs[DREG_VAR_BASE-i+DREG_OFFSET]=USING_REG; /*そのレジスタを使うことを宣言し*/ | |
759 regv[DREG_VAR_BASE-i+DREG_OFFSET]=0; | |
760 regs[dreg_pair0[j]] = regs[dreg_pair1[j]] = USING_REG; | |
761 regv[dreg_pair0[j]] = regv[dreg_pair1[j]] = 0; | |
149 | 762 if (dreg_pair1[j]>max_reg_var) max_reg_var=dreg_pair1[j]; |
148 | 763 /* その場所を表す番号を返す */ |
764 return list3(DREGISTER,DREG_VAR_BASE-i+DREG_OFFSET,(int)n); | |
765 } | |
766 } | |
767 return list2(LVAR,new_lvar(size_of_double)); | |
768 } else { | |
769 for(i=0;i<FREG_VAR_BASE-FREG_VAR_MIN;i++) { | |
770 if (! regs[FREG_VAR_BASE-i+FREG_OFFSET]) { /* 使われていないなら */ | |
771 regs[FREG_VAR_BASE-i+FREG_OFFSET]=USING_REG; /*そのレジスタを使うことを宣言し*/ | |
772 regv[FREG_VAR_BASE-i+FREG_OFFSET]=0; | |
773 if (i>max_freg_var) max_freg_var=i; | |
774 /* その場所を表す番号を返す */ | |
775 return list3(FREGISTER,FREG_VAR_BASE-i+FREG_OFFSET,(int)n); | |
776 } | |
777 } | |
778 return list2(LVAR,new_lvar(size_of_float)); | |
130 | 779 } |
780 } | |
781 | |
782 void | |
783 emit_push() | |
784 { | |
785 int new_reg; | |
786 if (reg_sp>MAX_MAX) error(-1); | |
787 new_reg = get_register(); | |
788 reg_stack[reg_sp++] = creg; /* push するかわりにレジスタを使う */ | |
148 | 789 ireg = creg = new_reg; |
130 | 790 regv[creg]=1; |
791 } | |
792 | |
793 int | |
794 emit_pop(int type) | |
795 { | |
796 int xreg,reg; | |
797 xreg=pop_register(); | |
798 if (xreg<= -REG_LVAR_OFFSET) { | |
799 reg = get_register(); | |
800 code_rlvar(REG_LVAR_OFFSET+xreg,reg); | |
801 free_lvar(REG_LVAR_OFFSET+xreg); | |
802 xreg = reg; | |
148 | 803 regv[creg]=1; |
130 | 804 } |
805 return xreg; | |
806 } | |
807 | |
808 void | |
809 code_label(int labelno) | |
810 { | |
811 printf("L_%d:\n",labelno); | |
812 } | |
813 | |
814 void | |
815 code_gvar(int e1,int creg) { | |
136
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
816 printf("\tla %s,%s\n",register_name(creg),((NMTBL*)cadr(e1))->nm); |
130 | 817 regv[creg]=1; |
818 } | |
819 | |
820 void | |
821 code_rgvar(int e1,int creg) { | |
136
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
822 printf("\tlw %s,%s\n",register_name(creg),((NMTBL*)cadr(e1))->nm); |
130 | 823 regv[creg]=1; |
824 } | |
167 | 825 char *cload(int sign,int sz) { return sz==1?(sign?"lbu":"lb"):(sz==size_of_short?(sign?"lhu":"lh"):"lw");} |
168 | 826 char *cstore(int sz) { return sz==1?"sb":(sz==size_of_short)?"sh":"sw";} |
130 | 827 void |
167 | 828 code_crgvar(int e1,int creg,int sign,int sz){ |
829 printf("\t%s %s,%s\n",cload(sign,sz),register_name(creg),((NMTBL*)cadr(e1))->nm); | |
130 | 830 regv[creg]=1; |
831 } | |
832 | |
833 | |
834 void | |
835 code_register(int e2,int creg) { | |
836 if (creg!=e2) | |
148 | 837 printf("\tmove %s,%s\n",register_name(creg),register_name(e2)); |
130 | 838 regv[creg]=1; |
839 } | |
840 | |
841 | |
842 void | |
843 code_rlvar(int e2,int reg) { | |
131 | 844 printf("\tlw %s,",register_name(reg)); |
130 | 845 lvar(e2); |
846 regv[creg]=1; | |
847 } | |
848 | |
849 | |
850 void | |
167 | 851 code_crlvar(int e2,int reg,int sign,int sz) { |
852 printf("\t%s %s,",cload(sign,sz),register_name(reg)); | |
130 | 853 lvar(e2); |
854 regv[reg]=1; | |
855 } | |
856 | |
857 | |
858 void | |
859 code_fname(NMTBL *n,int creg) { | |
136
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
860 printf("\tla %s,%s\n",register_name(creg),n->nm); |
130 | 861 regv[creg]=1; |
862 } | |
863 | |
864 | |
865 void | |
866 code_const(int e2,int creg) { | |
131 | 867 printf("\tli %s,%d\n",register_name(creg),e2); |
130 | 868 regv[creg]=1; |
869 } | |
870 | |
871 | |
872 void | |
873 code_neg(int creg) { | |
131 | 874 printf("\tsubu %s,$0,%s\n", register_name(creg), register_name(creg)); |
130 | 875 } |
876 | |
877 | |
878 void | |
879 code_not(int creg) { | |
880 printf("\tnor %s,%s,%s\n", | |
148 | 881 register_name(creg), register_name(creg),register_name(creg)); |
130 | 882 } |
883 | |
884 | |
885 void | |
886 code_lnot(int creg) { | |
131 | 887 /* if non zero 1 else 0 */ |
888 int dreg = get_register(); | |
889 printf("\txori %s,%s,0x0\n", | |
148 | 890 register_name(dreg),register_name(creg)); |
131 | 891 printf("\tsltu %s,%s,1\n", |
148 | 892 register_name(creg),register_name(dreg)); |
131 | 893 free_register(dreg); |
130 | 894 } |
895 | |
896 void | |
168 | 897 code_preinc(int e1,int e2,int dir,int sign,int sz,int reg) { |
130 | 898 char *xrn,*drn; |
899 int i,dreg; | |
900 if (car(e2)==REGISTER) { | |
148 | 901 printf("\taddu %s,%s,%d\n", |
168 | 902 register_name(cadr(e2)),register_name(cadr(e2)), dir); |
148 | 903 if (cadr(reg)!=e2) |
904 printf("\tmove %s,%s\n",register_name(cadr(reg)),register_name(e2)); | |
905 regv[reg]=1; | |
906 return; | |
130 | 907 } |
908 g_expr(e2); | |
909 xrn = register_name(creg); | |
910 dreg=get_register(); if (!dreg) error(-1); | |
911 drn = register_name(dreg); | |
168 | 912 printf("\t%s %s,0(%s)\n",cload(sign,sz),drn,xrn); |
913 printf("\taddu %s,%s,%d\n",drn,drn,dir); | |
914 printf("\t%s %s,0(%s)\n",cstore(sz),drn,xrn); | |
130 | 915 i=creg;creg=dreg;dreg=i; |
150 | 916 regv[creg]=1; ireg=creg; |
130 | 917 free_register(dreg); |
918 } | |
919 | |
920 | |
921 void | |
168 | 922 code_postinc(int e1,int e2,int dir,int sign,int sz,int reg) { |
130 | 923 char *xrn,*crn,*nrn; |
924 int dreg,nreg,i; | |
925 if (car(e2)==REGISTER) { | |
148 | 926 printf("\tmove %s,%s\n",register_name(reg),register_name(cadr(e2))); |
927 printf("\taddu %s,%s,%d\n", | |
168 | 928 register_name(cadr(e2)),register_name(cadr(e2)),dir); |
148 | 929 regv[reg]=1; |
930 return; | |
130 | 931 } |
932 g_expr(e2); | |
933 crn = register_name(creg); | |
934 dreg=get_register(); if (!dreg) error(-1); | |
935 xrn = register_name(dreg); | |
936 nreg=get_register(); if (!nreg) error(-1); | |
937 nrn = register_name(nreg); | |
168 | 938 printf("\t%s %s,0(%s)\n",cload(sign,sz),xrn,crn); |
939 printf("\taddu %s,%s,%d\n",nrn,xrn,dir); | |
940 printf("\t%s %s,0(%s)\n",cstore(sz),nrn,crn); | |
941 i=creg;creg=dreg;dreg=i; | |
130 | 942 free_register(nreg); |
943 free_register(dreg); | |
150 | 944 regv[creg]=1; ireg=creg; |
130 | 945 } |
946 | |
947 | |
948 | |
949 void | |
950 code_return(int creg) { | |
951 char *crn = register_name(creg); | |
131 | 952 printf("\tla %s,L_%d\n",crn,retcont); |
130 | 953 } |
954 | |
955 #define R1SAVE 1 | |
956 | |
957 void | |
958 code_environment(int creg) { | |
959 /* save frame pointer */ | |
960 #if R1SAVE | |
131 | 961 printf("\tlw %s,0($fp)\n",register_name(creg)); |
130 | 962 #else |
963 int l = 0; | |
131 | 964 printf("\taddu %s,",register_name(creg)); |
965 printf("$fp,%d+L_%d\n",FUNC_LVAR,lvar_offset_label); | |
130 | 966 #endif |
967 } | |
968 | |
969 void | |
970 code_bool(int e1) { | |
971 char *xrn; | |
972 int e2,e3; | |
973 b_expr(e1,1,e2=fwdlabel(),1); /* including > < ... */ | |
150 | 974 creg = use_int(creg); |
130 | 975 xrn = register_name(creg); |
976 printf("\tli %s,0\n",xrn); | |
977 jmp(e3=fwdlabel()); | |
978 fwddef(e2); | |
979 printf("\tli %s,1\n",xrn); | |
980 fwddef(e3); | |
981 } | |
982 | |
983 char * | |
984 code_gt(int cond) { | |
152 | 985 return (cond?"\tslt %s,%s,%s\n\tbeq %s,$0,L_%d\n": |
986 "\tslt %s,%s,%s\n\tbne %s,$0,L_%d\n"); | |
130 | 987 } |
988 | |
989 char * | |
990 code_ugt(int cond) { | |
152 | 991 return (cond?"\tsltu %s,%s,%s\n\tbeq %s,$0,L_%d\n": |
992 "\tsltu %s,%s,%s\n\tbne %s,$0,L_%d\n"); | |
130 | 993 } |
994 | |
995 char * | |
996 code_ge(int cond) { | |
152 | 997 return (cond?"\tslt %s,%s,%s\n\txori %s,%s,0x1\n\tbeq %s,$0,L_%d\n": |
998 "\tslt %s,%s,%s\n\txori %s,%s,0x1\n\tbne %s,$0,L_%d\n"); | |
130 | 999 } |
1000 | |
1001 char * | |
1002 code_uge(int cond) { | |
152 | 1003 return (cond?"\tsltu %s,%s,%s\n\txori %s,%s,0x1\n\tbeq %s,$0,L_%d\n": |
1004 "\tsltu %s,%s,%s\n\txori %s,%s,0x1\n\tbne %s,$0,L_%d\n"); | |
130 | 1005 } |
1006 | |
1007 char * | |
1008 code_eq(int cond) { | |
152 | 1009 return (cond?"\tbeq %s,%s,L_%d\n":"\tbne %s,%s,L_%d\n"); |
130 | 1010 } |
1011 | |
1012 void | |
167 | 1013 code_cmp_crgvar(int e1,int sz) { |
148 | 1014 if (cmpreg==-1) cmpreg = get_register(); |
167 | 1015 code_crgvar(cadr(e1),cmpreg,1,sz); |
148 | 1016 regv[cmpreg]=1; |
130 | 1017 } |
1018 | |
1019 | |
1020 void | |
167 | 1021 code_cmp_crlvar(int e2,int sz) { |
148 | 1022 if (cmpreg==-1) cmpreg = get_register(); |
167 | 1023 code_crlvar(e2,cmpreg,1,sz); |
148 | 1024 regv[cmpreg]=1; |
130 | 1025 } |
1026 | |
1027 | |
1028 void | |
1029 code_cmp_rgvar(int e1) { | |
148 | 1030 if (cmpreg==-1) cmpreg = get_register(); |
1031 code_rgvar(e1,cmpreg); | |
1032 regv[cmpreg]=1; | |
130 | 1033 } |
1034 | |
1035 | |
1036 void | |
1037 code_cmp_rlvar(int e2) { | |
148 | 1038 if (cmpreg==-1) cmpreg = get_register(); |
149 | 1039 code_rlvar(e2,cmpreg); |
148 | 1040 regv[cmpreg]=1; |
130 | 1041 } |
1042 | |
1043 | |
1044 void | |
1045 code_cmp_register(int e2) { | |
148 | 1046 cmpreg = e2; |
1047 /* prevent cmpreg freeing */ | |
1048 regv[cmpreg]=2; | |
130 | 1049 } |
1050 | |
1051 | |
1052 void | |
1053 ascii(char *s) | |
1054 { | |
1055 printf("\t.ascii \""); | |
1056 while(*s) { | |
1057 if (*s=='\n') | |
1058 printf("%cn",92); | |
1059 else if (*s<' ') | |
1060 printf("%c%03o",92,*s); | |
1061 else if (*s=='\\') | |
1062 printf("\\\\"); | |
1063 else if (*s==34) | |
1064 printf("%c%c",92,34); | |
1065 else | |
1066 printf("%c",*s); | |
1067 s++; | |
1068 } | |
148 | 1069 printf("\\0%c\n\t.align 2\n",34); |
130 | 1070 } |
1071 | |
1072 void | |
1073 code_string(int e1,int creg) | |
1074 { | |
1075 char *s,*crn; | |
1076 int lb; | |
1077 crn=register_name(creg); | |
1078 | |
1079 s=(char *)cadr(e1); | |
131 | 1080 printf("\t.rdata\n\t.align 2\n"); |
130 | 1081 lb=fwdlabel(); |
1082 printf("L_%d:\n",lb); | |
1083 ascii(s); | |
1084 if (output_mode==TEXT_EMIT_MODE) { | |
148 | 1085 printf(".text\n"); |
130 | 1086 } else { |
148 | 1087 text_mode(); |
130 | 1088 } |
131 | 1089 printf("\tla %s,L_%d\n",crn,lb); |
130 | 1090 } |
1091 | |
1092 #define MAX_COPY_LEN 20 | |
1093 | |
1094 void | |
1095 emit_copy(int from,int to,int length,int offset,int value,int det) | |
1096 { | |
1097 char *frn = register_name(from); | |
1098 char *trn = register_name(to); | |
1099 char *drn; | |
1100 int fix = 0; | |
1101 char *memmove = "memmove"; | |
1102 int dreg = get_register(); if (!dreg) error(-1); | |
1103 drn = register_name(dreg); | |
1104 | |
1105 /* length <0 means upward direction copy */ | |
1106 switch (length) { | |
148 | 1107 case 0: break; |
130 | 1108 case 1: case -1: |
148 | 1109 printf("\tlb %s,%d(%s)\n",drn,offset,frn); |
1110 printf("\tsb %s,%d(%s)\n",drn,offset,trn); | |
1111 break; | |
130 | 1112 case 2: case -2: |
148 | 1113 printf("\tlh %s,%d(%s)\n",drn,offset,frn); |
1114 printf("\tsh %s,%d(%s)\n",drn,offset,trn); | |
1115 break; | |
130 | 1116 case 4: case -4: |
148 | 1117 printf("\tlw %s,%d(%s)\n",drn,offset,frn); |
1118 printf("\tsw %s,%d(%s)\n",drn,offset,trn); | |
1119 break; | |
130 | 1120 default: |
148 | 1121 if (-MAX_COPY_LEN<length && length <0) { |
1122 for(;length<=4;length+=4,offset-=4) | |
1123 emit_copy(from,to,4,offset,0,det); | |
1124 for(;length<=2;length+=2,offset-=2) | |
1125 emit_copy(from,to,2,offset,0,det); | |
1126 if(length>0) | |
1127 emit_copy(from,to,length,offset,0,det); | |
1128 break; | |
1129 } else if (length <=MAX_COPY_LEN) { | |
1130 for(;length>=4;length-=4,offset+=4) | |
1131 emit_copy(from,to,4,offset,0,det); | |
1132 for(;length>=2;length-=2,offset+=2) | |
1133 emit_copy(from,to,2,offset,0,det); | |
1134 if(length>0) | |
1135 emit_copy(from,to,length,offset,0,det); | |
1136 break; | |
1137 } | |
1138 code_save_stacks(); | |
1139 printf("\tli $6,%d\n",length); | |
1140 printf("\tmr $5,%s\n",frn); | |
1141 printf("\tmr $4,%s\n",trn); | |
130 | 1142 /* overrap must be allowed */ |
148 | 1143 printf("\tbl L_%s$stub\n",memmove); |
130 | 1144 fix=0; |
148 | 1145 set_creg(RET_REGISTER,0); |
1146 if (creg!=to) { | |
1147 free_register(to); to = creg; | |
1148 } | |
1149 break; | |
130 | 1150 } |
149 | 1151 if (value) { |
130 | 1152 /* creg must point top of the destination data */ |
1153 /* this code is necessary for the value of assignment or function call */ | |
1154 /* otherwise we don't need this */ | |
148 | 1155 if (fix) printf("\taddi %s,%s,%d\n",trn,trn,fix); |
1156 if(creg!=to) { | |
1157 free_register(creg); creg=to; | |
1158 } | |
130 | 1159 } |
1160 free_register(dreg); | |
1161 regv[from]=regv[to]=regv[dreg]=0; | |
1162 regv[creg]=1; | |
1163 } | |
1164 | |
1165 int | |
1166 struct_push(int e4,int t,int arg) | |
1167 { | |
1168 int length,count; | |
1169 int dreg,sreg; char *drn,*crn,*srn; | |
1170 g_expr(e4); | |
1171 length=size(t); | |
1172 if(length%size_of_int) { | |
1173 length += size_of_int - (length%size_of_int); | |
1174 } | |
1175 dreg = get_register(); if (!dreg) error(-1); | |
1176 drn = register_name(dreg); | |
1177 crn = register_name(creg); | |
1178 if (length<MAX_COPY_LEN) { | |
1179 sreg = get_register(); if (!sreg) error(-1); | |
1180 srn = register_name(sreg); | |
1181 code_lvar(cadr(arg),sreg); | |
1182 for(count=0;length<MAX_COPY_LEN;count++,length-=size_of_int) { | |
1183 if (length==0) { | |
1184 free_register(sreg); | |
1185 free_register(dreg); | |
1186 return count; | |
1187 } else { | |
148 | 1188 printf("\tlw %s,%d(%s)\n",drn,length-size_of_int,crn); |
1189 printf("\tsw %s,%d(%s)\n",drn,length-size_of_int,srn); | |
130 | 1190 } |
1191 } | |
1192 } | |
1193 code_lvar(cadr(arg),dreg); | |
1194 /* downward direction copy */ | |
1195 emit_copy(creg,dreg,length,0,0,1); | |
1196 if (dreg) free_register(dreg); | |
1197 return length/size_of_int; | |
1198 } | |
1199 | |
1200 void | |
1201 set_creg(int reg,int mode) | |
1202 { | |
148 | 1203 if (!is_int_reg(reg)) error(-1); |
130 | 1204 if (reg!=creg) { |
148 | 1205 if (reg!=ireg && mode) |
150 | 1206 printf("\tmove %s,%s\n",register_name(reg),register_name(ireg)); |
130 | 1207 free_register(creg); |
148 | 1208 creg = ireg = reg; |
130 | 1209 regs[creg]=1; |
1210 } | |
1211 } | |
1212 | |
1213 void | |
1214 set_freg(int reg,int mode) | |
1215 { | |
148 | 1216 if (!is_float_reg(reg)) error(-1); |
1217 if (reg!=creg) { | |
1218 if (reg!=freg && mode) { | |
1219 printf("\tfmove %s,%s\n",fregister_name(reg),fregister_name(freg)); | |
1220 } | |
1221 free_register(creg); | |
1222 creg = freg = reg; | |
1223 regs[freg]=1; | |
130 | 1224 } |
1225 } | |
1226 | |
149 | 1227 static void |
1228 move_dreg(int reg,int dreg) | |
1229 { | |
1230 if (reg!=dreg) { | |
1231 printf("\tmove %s,%s\n",dregister_name0(reg), | |
1232 dregister_name0(dreg)); | |
1233 printf("\tmove %s,%s\n",dregister_name1(reg), | |
1234 dregister_name1(dreg)); | |
1235 } | |
1236 } | |
1237 | |
130 | 1238 void |
148 | 1239 set_dreg(int reg,int mode) |
1240 { | |
1241 if (!is_double_reg(reg)) error(-1); | |
1242 if (reg!=creg) { | |
149 | 1243 if (mode) { |
1244 move_dreg(reg,dreg); | |
148 | 1245 } |
1246 free_register(creg); | |
1247 creg = dreg = reg; | |
1248 regs[dreg]=1; | |
152 | 1249 regs[dreg_pair0[dreg-DREG_OFFSET]]=1; |
1250 regs[dreg_pair1[dreg-DREG_OFFSET]]=1; | |
148 | 1251 } |
1252 } | |
1253 | |
1254 | |
1255 void | |
130 | 1256 use_var(int arg) |
1257 { | |
1258 if (car(arg)==REGISTER) | |
1259 regs[cadr(arg)]=USING_REG; | |
148 | 1260 else if (car(arg)==FREGISTER) |
1261 regs[cadr(arg)]=USING_REG; | |
130 | 1262 else if (car(arg)==DREGISTER) |
148 | 1263 regs[cadr(arg)]=USING_REG; |
130 | 1264 } |
1265 | |
1266 void | |
1267 code_save_input_registers() | |
1268 { | |
1269 int args; | |
1270 NMTBL *n; | |
1271 int reg; | |
1272 int tag; | |
1273 int lvar; | |
1274 int t; | |
1275 /* fnptr->dsp=list4(type,fnptr->dsp,(int)n,0); */ | |
1276 int reg_offset = 0; | |
1277 int offset = 0; | |
1278 | |
1279 for(args = fnptr->dsp;args;args = cadr(args)) { | |
1280 n = (NMTBL *)caddr(args); | |
1281 tag = n->sc; | |
1282 reg = n->dsp; | |
1283 if (!n||n==&null_nptr) error(REG_ERR); | |
1284 if (tag==REGISTER) { | |
1285 /* regs[reg]==INPUT_REG case should be considered */ | |
1286 n->dsp = offset; | |
1287 offset+=size_of_int; | |
1288 t = INT; | |
1289 reg += reg_offset; /* for duplicated floating point argument */ | |
148 | 1290 } else if (tag==FREGISTER) { |
1291 /* fregs[reg]==INPUT_REG case should be considered */ | |
1292 n->dsp = offset; | |
1293 t = n->ty; | |
1294 if(t==FLOAT) { offset+=size_of_float; reg_offset+=1; } | |
1295 else if(t==DOUBLE) { offset+=size_of_double; reg_offset+=2; } | |
1296 else error(-1); | |
1297 } else if (tag==DREGISTER) { | |
1298 /* fregs[reg]==INPUT_REG case should be considered */ | |
1299 n->dsp = offset; | |
1300 t = n->ty; | |
1301 if(t==FLOAT) { offset+=size_of_float; reg_offset+=1; } | |
1302 else if(t==DOUBLE) { offset+=size_of_double; reg_offset+=2; } | |
1303 else error(-1); | |
130 | 1304 } else { |
1305 offset += size(n->ty); | |
1306 continue; | |
1307 } | |
1308 n->sc = LVAR; | |
1309 lvar = list2(LVAR,n->dsp); | |
1310 g_expr_u(assign_expr0(list2(LVAR,n->dsp),list3(tag,reg,(int)n),n->ty,t)); | |
148 | 1311 if (tag==REGISTER||tag==DREGISTER||tag==FREGISTER) { |
130 | 1312 free_register(reg); |
1313 } | |
1314 } | |
1315 my_func_args = offset; | |
1316 } | |
1317 | |
1318 int | |
1319 simple_args(int e3) | |
1320 { | |
1321 return | |
1322 !contains_in_list(e3,FUNCTION) && | |
1323 !contains_in_list(e3,CONV) && | |
1324 !contains_in_list(e3,RSTRUCT) && | |
164 | 1325 !contains_in_list(e3,STASS) |
130 | 1326 ; |
1327 } | |
1328 | |
1329 int | |
1330 caller_arg_offset_v(int arg) | |
1331 { | |
1332 return ARG_LVAR_OFFSET+arg*size_of_int; | |
1333 } | |
1334 | |
1335 int | |
1336 function(int e1) | |
1337 { | |
150 | 1338 int e2,e3,e4,nargs,t; |
130 | 1339 int arg,reg_arg,freg_arg,arg_assign; |
148 | 1340 int dots; |
130 | 1341 int reg_arg_list=0,ret_type,special_lvar; |
1342 NMTBL *fn = 0; | |
1343 int jmp = 0; | |
1344 char *jrn; | |
153 | 1345 int iargs=0; |
130 | 1346 |
1347 special_lvar = -1; | |
148 | 1348 ret_type = cadr(cadddr(e1)); |
1349 if (ret_type==CHAR) ret_type=INT; | |
1350 | |
1351 /* check argments type is DOTS? */ | |
1352 t = caddr(cadddr(e1)); | |
1353 if (t==0 || t==DOTS) dots = 1; | |
1354 else { | |
1355 dots = 0; | |
1356 for(t = caddr(cadddr(e1));t;t = cadr(t)) { | |
1357 if (car(t)==DOTS) dots = 1; | |
1358 } | |
1359 } | |
130 | 1360 |
1361 e2 = cadr(e1); | |
1362 if (car(e2) == FNAME) { | |
1363 fn=(NMTBL *)cadr(e2); | |
1364 } else { | |
1365 jmp = get_register_var(0); | |
1366 if (car(jmp)!=REGISTER) error(-1); | |
1367 reg_arg_list = list2(jmp,reg_arg_list); | |
1368 g_expr(e2); | |
1369 code_register(creg,cadr(jmp)); | |
1370 /* g_expr(assign_expr0(jmp,e2,INT,INT)); functions are lvalue */ | |
1371 } | |
1372 | |
1373 /* now all input register vars are free */ | |
1374 code_save_stacks(); | |
1375 set_creg(CREG_REGISTER,0); | |
1376 set_freg(FREG_FREGISTER,0); | |
148 | 1377 set_dreg(DREG_DREGISTER,0); |
130 | 1378 |
1379 nargs = reg_arg = freg_arg = arg_assign = 0; | |
1380 for (e3 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) { | |
1381 t=caddr(e3); | |
1382 e4 = car(e3); | |
1383 if(scalar(t)) { | |
1384 if (reg_arg>=MAX_INPUT_REGISTER_VAR) { | |
1385 arg = list2(LVAR,caller_arg_offset_v(nargs)); | |
1386 } else if (!simple_args(e3) && cadr(e3)) { | |
1387 arg = get_register_var(0); | |
1388 arg_assign = list2( | |
148 | 1389 assign_expr0(get_input_register_var(reg_arg,0,0), |
1390 arg,t,t), | |
130 | 1391 arg_assign); |
1392 } else { | |
1393 arg = get_input_register_var(reg_arg,0,0); | |
1394 } | |
1395 use_var(arg); /* protect from input register free */ | |
1396 reg_arg_list = list2(arg,reg_arg_list); | |
1397 g_expr_u(assign_expr0(arg,e4,t,t)); | |
153 | 1398 nargs ++ ; reg_arg++; iargs += size_of_int; |
130 | 1399 continue; |
1400 } else if (t==DOUBLE||t==FLOAT) { | |
1401 if (freg_arg>=MAX_INPUT_DREGISTER_VAR) { | |
1402 arg = list2(LVAR,caller_arg_offset_v(nargs)); | |
148 | 1403 } else if (!simple_args(e3) && cadr(e3)) { |
138 | 1404 arg = get_dregister_var(0,1); |
130 | 1405 arg_assign = list2( |
148 | 1406 assign_expr0(get_input_dregister_var(freg_arg,0,0,1), |
1407 arg,t,t), | |
130 | 1408 arg_assign); |
1409 } else { | |
138 | 1410 arg = get_input_dregister_var(freg_arg,0,0,1); |
130 | 1411 } |
1412 use_var(arg); /* protect from input register free */ | |
1413 reg_arg_list = list2(arg,reg_arg_list); | |
1414 g_expr_u(assign_expr0(arg,e4,t,t)); /* XXX */ | |
1415 freg_arg++; | |
1416 nargs += size(t)/size_of_int; | |
153 | 1417 if (t==DOUBLE) iargs += size(t); |
130 | 1418 continue; |
1419 } else if (car(t)==STRUCT||car(t)==UNION) { | |
1420 arg = list2(LVAR,caller_arg_offset_v(nargs)); | |
1421 nargs += struct_push(e4,t,arg); | |
153 | 1422 iargs += ((size(t)+3)/size_of_int)*size_of_int; |
130 | 1423 continue; |
1424 } else { | |
1425 error(TYERR); | |
1426 } | |
1427 ++nargs; | |
1428 } | |
1429 if (max_func_args<nargs) max_func_args=nargs; | |
153 | 1430 if (max_func_iargs<iargs) max_func_iargs=iargs; |
130 | 1431 for(;arg_assign;arg_assign=cadr(arg_assign)) { |
1432 g_expr_u(car(arg_assign)); | |
1433 } | |
1434 if (car(e2) == FNAME) { | |
1435 printf("\tbl\tL_%s$stub\n",fn->nm); | |
1436 } else { | |
1437 jrn = register_name(cadr(jmp)); | |
131 | 1438 printf("\tj %s\n",jrn); |
130 | 1439 } |
1440 for(;reg_arg_list;reg_arg_list=cadr(reg_arg_list)) { | |
1441 arg = car(reg_arg_list); | |
148 | 1442 if (car(arg)==REGISTER||car(arg)==DREGISTER||car(arg)==FREGISTER) |
1443 free_register(cadr(arg)); | |
130 | 1444 else if (car(arg)==LVAR&&cadr(arg)<0) free_lvar(cadr(arg)); |
1445 } | |
148 | 1446 if (ret_type==DOUBLE) { |
1447 set_dreg(RET_DREGISTER,0); | |
1448 regv[dreg]=1; regv[creg]=0; | |
1449 } else if (ret_type==FLOAT) { | |
130 | 1450 set_freg(RET_FREGISTER,0); |
148 | 1451 regv[freg]=1; regv[creg]=0; |
130 | 1452 } else if (ret_type==VOID) { |
148 | 1453 regv[freg]=0; regv[creg]=0; |
130 | 1454 } else { |
1455 set_creg(RET_REGISTER,0); | |
148 | 1456 regv[freg]=0; regv[creg]=1; |
130 | 1457 } |
1458 return ret_type; | |
1459 } | |
1460 | |
1461 void | |
1462 code_frame_pointer(int e3) { | |
1463 #if R1SAVE | |
131 | 1464 printf("\tmove $fp,%s\n",register_name(e3)); |
130 | 1465 #else |
131 | 1466 printf("\tmove $fp,%s\n",register_name(e3)); |
130 | 1467 #endif |
1468 } | |
1469 | |
1470 | |
1471 void | |
1472 code_fix_frame_pointer(int disp_offset) { | |
1473 int l = 0; | |
131 | 1474 printf("\tla $fp,"); |
1475 printf("%d+L_%d($sp)\n",FUNC_LVAR,lvar_offset_label); | |
130 | 1476 } |
1477 | |
1478 void | |
1479 code_jmp(char *s) { | |
1480 max_reg_var = REG_VAR_BASE-REG_VAR_MIN; | |
1481 max_freg_var = FREG_VAR_BASE-FREG_VAR_MIN; | |
131 | 1482 printf("\tj L_%s\n",s); |
130 | 1483 } |
1484 | |
1485 | |
1486 void | |
1487 code_indirect_jmp(int e2) { | |
1488 max_reg_var = REG_VAR_BASE-REG_VAR_MIN; | |
1489 max_freg_var = FREG_VAR_BASE-FREG_VAR_MIN; | |
131 | 1490 printf("\tj %s\n",register_name(e2)); |
130 | 1491 } |
1492 | |
1493 int | |
1494 rindirect(int e1) /* *(p +5 ) */ | |
1495 { | |
1496 char *crn; | |
1497 int e2,e3,e4,offset; | |
1498 | |
1499 offset=0; | |
1500 e3 = cadr(e2 = cadr(e1)); | |
1501 if (car(e2)==ADD) { | |
1502 e4=caddr(e2); | |
1503 if (car(e4)==CONST) { | |
1504 offset=cadr(e4); | |
1505 e2=e3; | |
1506 } | |
1507 } | |
1508 g_expr(e2); | |
1509 crn=register_name(creg); | |
1510 switch (car(e1)) { | |
149 | 1511 case FRINDIRECT: |
1512 printf("\tl.s %s,%d(%s)\n", fregister_name(freg),offset,crn); | |
148 | 1513 regv[creg]=0; regv[freg]=1; |
149 | 1514 creg = freg; |
1515 return FLOAT; | |
1516 case DRINDIRECT: | |
1517 printf("\tlw %s,%d(%s)\n", | |
1518 dregister_name0(dreg),offset,crn); | |
1519 printf("\tlw %s,%d(%s)\n", | |
1520 dregister_name1(dreg),offset+size_of_int,crn); | |
1521 regv[creg]=0; regv[dreg]=1; | |
1522 creg = dreg; | |
148 | 1523 return DOUBLE; |
130 | 1524 case CRINDIRECT: |
148 | 1525 printf("\tlb %s,%d(%s)\n",crn,offset,crn); |
1526 return CHAR; | |
163 | 1527 case CURINDIRECT: |
1528 printf("\tlbu %s,%d(%s)\n",crn,offset,crn); | |
1529 return UCHAR; | |
167 | 1530 case SRINDIRECT: |
1531 printf("\tlh %s,%d(%s)\n",crn,offset,crn); | |
1532 return SHORT; | |
1533 case SURINDIRECT: | |
1534 printf("\tlhu %s,%d(%s)\n",crn,offset,crn); | |
1535 return USHORT; | |
130 | 1536 case RINDIRECT: |
148 | 1537 printf("\tlw %s,%d(%s)\n",crn,offset,crn); |
1538 return INT; | |
130 | 1539 } |
1540 error(-1); return INT; | |
1541 } | |
1542 | |
1543 void | |
1544 code_assign_gvar(int e2,int creg,int byte) { | |
151 | 1545 char *crn,*name; |
136
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
1546 |
151 | 1547 name = ((NMTBL*)cadr(e2))->nm; |
130 | 1548 crn=register_name(creg); |
167 | 1549 if (byte==1) { |
151 | 1550 printf("\tsb %s,%s\n",crn,name); |
167 | 1551 } if (byte==size_of_short) { |
1552 printf("\tsh %s,%s\n",crn,name); | |
130 | 1553 } else { |
151 | 1554 printf("\tsw %s,%s\n",crn,name); |
130 | 1555 } |
1556 } | |
1557 | |
1558 void | |
1559 code_assign_lvar(int e2,int creg,int byte) { | |
1560 char *crn; | |
1561 crn=register_name(creg); | |
167 | 1562 if (byte==1) { |
1563 printf("\tsb %s,",crn); | |
1564 } else if (byte==size_of_short) { | |
1565 printf("\tsh %s,",crn); | |
130 | 1566 } else { |
167 | 1567 printf("\tsw %s,",crn); |
130 | 1568 } |
167 | 1569 lvar(e2); |
130 | 1570 } |
1571 | |
1572 void | |
1573 code_assign_register(int e2,int byte,int creg) { | |
1574 if (e2!=creg) | |
148 | 1575 printf("\tmove %s,%s\n",register_name(e2),register_name(creg)); |
130 | 1576 } |
1577 | |
1578 void | |
1579 code_assign(int e2,int byte,int creg) { | |
1580 char *drn=register_name(e2); | |
1581 char *crn=register_name(creg); | |
1582 | |
167 | 1583 if (byte==1) { |
148 | 1584 printf("\tsb %s,0(%s)\n",crn,drn); |
167 | 1585 } else if (byte==size_of_short) { |
1586 printf("\tsh %s,0(%s)\n",crn,drn); | |
130 | 1587 } else { |
148 | 1588 printf("\tsw %s,0(%s)\n",crn,drn); |
130 | 1589 } |
148 | 1590 regv[creg]=1; |
130 | 1591 } |
1592 | |
1593 | |
1594 void | |
1595 code_register_assop(int e2,int op,int byte) { | |
1596 int reg; | |
1597 int xreg = creg; | |
1598 creg = reg = e2; | |
1599 tosop(op,xreg); | |
1600 creg = xreg; | |
1601 if (creg!=reg) | |
148 | 1602 printf("\tmove %s,%s\n",register_name(creg),register_name(reg)); |
1603 regv[creg]=1; | |
130 | 1604 } |
1605 | |
1606 | |
1607 void | |
163 | 1608 code_assop(int op,int byte,int sign) { |
130 | 1609 char *xrn,*crn,*drn; |
1610 int xreg; | |
1611 int edx = get_register(); if(!edx) error(-1); | |
1612 xrn = register_name(xreg = emit_pop(0)); /* pop e3 value */ | |
1613 regv[xreg]=regs[xreg]=1; | |
1614 printf("# assop\n\tmr %s,%s\n",register_name(edx),register_name(creg)); | |
1615 regv[edx]=1; | |
163 | 1616 ld_indexx(byte,0,edx,sign); |
130 | 1617 tosop(op,xreg); |
1618 crn = register_name(creg); | |
1619 drn = register_name(edx); | |
168 | 1620 printf("\t%s %s,0(%s)\n",cstore(byte),crn,drn); |
130 | 1621 free_register(edx); |
1622 emit_pop_free(xreg); | |
148 | 1623 regv[creg]=1; |
130 | 1624 } |
1625 | |
1626 | |
1627 void | |
1628 tosop(int op,int oreg) | |
1629 { | |
1630 int dx; | |
149 | 1631 char *orn,*crn; |
130 | 1632 |
1633 if(oreg==-1) { | |
1634 error(-1); | |
1635 } else if (oreg<= -REG_LVAR_OFFSET) { | |
1636 dx = get_register(); if (dx<0) error(-1); | |
1637 code_rlvar(oreg+REG_LVAR_OFFSET,dx); | |
1638 oreg = dx; | |
1639 regv[oreg]=1; | |
1640 } | |
1641 | |
1642 switch(op) { | |
1643 case LSHIFT: | |
1644 case ULSHIFT: | |
131 | 1645 shift("sll",oreg); |
148 | 1646 regv[creg]=1; |
130 | 1647 return; |
1648 case RSHIFT: | |
131 | 1649 shift("srl",oreg); |
148 | 1650 regv[creg]=1; |
130 | 1651 return; |
1652 case URSHIFT: | |
131 | 1653 shift("sra",oreg); |
148 | 1654 regv[creg]=1; |
130 | 1655 return; |
1656 } | |
1657 orn = register_name(oreg); | |
1658 crn = register_name(creg); | |
1659 switch(op) { | |
1660 case ADD: | |
131 | 1661 printf("\taddu %s,%s,%s\n",crn,crn,orn); |
130 | 1662 break; |
1663 case SUB: | |
131 | 1664 printf("\tsubu %s,%s,%s\n",crn,crn,orn); |
130 | 1665 break; |
1666 case CMP: | |
131 | 1667 printf("\tslt %s,%s\n",crn,orn); |
130 | 1668 break; |
1669 case BAND: | |
1670 printf("\tand %s,%s,%s\n",crn,crn,orn); | |
1671 break; | |
1672 case EOR: | |
1673 printf("\txor %s,%s,%s\n",crn,crn,orn); | |
1674 break; | |
1675 case BOR: | |
1676 printf("\tor %s,%s,%s\n",crn,crn,orn); | |
1677 break; | |
1678 case MUL: | |
131 | 1679 printf("\tmult %s,%s,%s\n",crn,crn,orn); |
130 | 1680 break; |
1681 case UMUL: | |
131 | 1682 printf("\tmultu %s,%s,%s\n",crn,crn,orn); |
130 | 1683 break; |
148 | 1684 case DIV: |
1685 printf("\tdivw %s,%s,%s\n",crn,crn,orn); | |
1686 break; | |
149 | 1687 case UDIV: case MOD: case UMOD: |
148 | 1688 printf("\t%s $0,%s,%s\n",(op==UDIV||op==UMOD)?"divu":"div",crn,orn); |
1689 printf("\t%s %s\n",(op==MOD||op==UMOD)?"mflo":"mfhi",crn); | |
1690 printf("\t.set noreorder\n"); | |
1691 printf("\tbeql %s,$0,1f\n",orn); | |
1692 printf("\tbreak 7\n"); | |
1693 printf("1:\n"); | |
1694 printf("\t.set reorder\n"); | |
1695 break; | |
130 | 1696 default: |
1697 error(-1); | |
1698 } | |
1699 if(oreg!=creg) free_register(oreg); | |
148 | 1700 regv[creg]=1; |
130 | 1701 } |
1702 | |
1703 | |
1704 void | |
1705 shift(char *op, int reg) | |
1706 { | |
1707 char *crn = register_name(creg); | |
1708 char *rrn = register_name(reg); | |
1709 printf("\t%s %s,%s,%s\n",op,crn,rrn,crn); | |
1710 } | |
1711 | |
1712 void | |
163 | 1713 ld_indexx(int byte, int n, int xreg,int sign) |
130 | 1714 { |
1715 char *crn = register_name(creg); | |
168 | 1716 printf("\t%s %s,%d(%s)\n",cload(sign,byte),crn,n, |
1717 register_name(xreg)); | |
130 | 1718 } |
1719 | |
1720 int | |
1721 code_csvalue() | |
1722 { | |
1723 return creg; | |
1724 } | |
1725 | |
1726 void | |
1727 code_cmpdimm(int e, int csreg) | |
1728 { | |
1729 /* used in dosiwtch() */ | |
1730 if(chk) return; | |
150 | 1731 creg = use_int(creg); |
131 | 1732 printf("\tli %s,%d\n",register_name(creg),e); |
148 | 1733 cmpreg = csreg; |
1734 regv[cmpreg]=2; /* prevent from freeing */ | |
130 | 1735 } |
1736 | |
1737 void | |
136
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
1738 code_opening(char *s) |
130 | 1739 { |
131 | 1740 /* this is called once per month */ |
1741 char *p=cheapp; | |
1742 | |
136
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
1743 printf("\t.file \"%s\"\n",s); |
130 | 1744 /* printf("\t.version\t\"01.01\"\n"); */ |
1745 /* printf("gcc2_compiled.:\n"); */ | |
131 | 1746 printf("\t.abicalls\n"); |
1747 printf("\t.text\n"); | |
1748 | |
1749 if (asi) { | |
148 | 1750 fclose(asi); |
1751 asi = 0; | |
131 | 1752 } |
1753 while ((*cheapp++ = *s++)) { | |
1754 if (*s=='.') { | |
1755 *cheapp++=*s++; *cheapp++='i'; | |
148 | 1756 *cheapp++=0; |
131 | 1757 break; |
1758 } | |
1759 } | |
1760 asi = fopen(p,"w"); | |
136
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
1761 printf(".include \"%s\"\n",p); |
131 | 1762 if (!asi) error(-1); |
130 | 1763 } |
1764 | |
1765 void | |
1766 rexpr(int e1, int l1, char *s,int t) | |
1767 { | |
132 | 1768 char *crn,*drn; |
148 | 1769 if (cmpreg>=0) { free_register(cmpreg); cmpreg = -1; } |
132 | 1770 |
1771 g_expr(cadr(e1)); | |
1772 emit_push(); | |
1773 g_expr(caddr(e1)); | |
150 | 1774 cmpreg = emit_pop(0); |
132 | 1775 crn = register_name(creg); |
148 | 1776 drn = register_name(cmpreg); |
132 | 1777 |
1778 if (s[1] == 's') { | |
148 | 1779 if (s[16]=='x') { |
1780 /* slt $2,$2,$3; xroi $2,$2,0x1; beq $2,$0,L1 */ | |
1781 printf(s,crn,drn,drn,crn,crn,crn,l1); | |
1782 } else { | |
1783 /* slt $2,$2,$3; beq $2,$0,L1 */ | |
1784 printf(s,crn,drn,drn,crn,l1); | |
1785 } | |
132 | 1786 } else { |
148 | 1787 /* beq $2,$3,L1 */ |
1788 printf(s,crn,drn,l1); | |
132 | 1789 } |
148 | 1790 free_register(cmpreg) ; cmpreg = -1; |
130 | 1791 } |
1792 | |
1793 void | |
1794 jcond(int l, char cond) | |
131 | 1795 { |
130 | 1796 if (chk) return; |
148 | 1797 if (cmpreg==-1) error(-1); |
150 | 1798 printf("\tb%s %s,%s,L_%d\n", |
1799 cond?"ne":"eq", | |
1800 register_name(creg),register_name(cmpreg), | |
1801 l); | |
148 | 1802 if (regv[cmpreg]==1) { |
1803 free_register(cmpreg); cmpreg = -1; | |
132 | 1804 } |
131 | 1805 regv[creg]=0; |
130 | 1806 } |
1807 | |
1808 void | |
1809 jmp(int l) | |
1810 { | |
1811 control=0; | |
1812 if (chk) return; | |
131 | 1813 printf("\tj\tL_%d\n",l); |
130 | 1814 } |
1815 | |
1816 void | |
1817 gen_comment(char *s) | |
1818 { | |
1819 if (chk) return; | |
1820 printf("## %s",s); | |
1821 } | |
1822 | |
1823 void | |
1824 code_enter(char *name) | |
1825 { | |
1826 if (output_mode!=TEXT_EMIT_MODE) | |
1827 text_mode(); | |
1828 else | |
132 | 1829 printf("\t.align 3\n"); |
153 | 1830 /* if (stmode!=STATIC) |
1831 printf(".globl _%s\n",name); */ | |
132 | 1832 printf(".ent %s\n",name); |
130 | 1833 printf("_%s:\n",name); |
1834 code_disp_label=fwdlabel(); | |
132 | 1835 |
1836 printf("\t.set noreorder\n"); | |
1837 printf("\t.cpload $25\n"); | |
1838 printf("\t.set reorder\n"); | |
1839 printf("\tsubu $sp,$sp,L_%d\n",code_disp_label); | |
153 | 1840 printf("\t.cprestore L_%d\n",cprestore_label); |
148 | 1841 |
130 | 1842 max_func_args = 0; |
153 | 1843 max_func_iargs = 0; |
130 | 1844 } |
1845 | |
1846 | |
1847 void | |
1848 code_enter1(int args) | |
1849 { | |
1850 set_creg(CREG_REGISTER,0); | |
1851 set_freg(FREG_FREGISTER,0); | |
148 | 1852 set_dreg(DREG_DREGISTER,0); |
130 | 1853 } |
1854 | |
1855 void | |
1856 code_leave(char *name) | |
1857 { | |
1858 int r1_offsetv; | |
1859 disp&= -size_of_int; | |
1860 r1_offsetv = -disp+max_func_args*size_of_int+code_disp_offset; | |
1861 | |
132 | 1862 fprintf(asi,"L_%d=%d\n",code_disp_label,-r1_offsetv); |
148 | 1863 |
130 | 1864 local_table(); |
1865 free_all_register(); | |
1866 } | |
1867 | |
1868 void | |
1869 enter(char *name) | |
1870 { | |
1871 if (output_mode!=TEXT_EMIT_MODE) | |
1872 text_mode(); | |
1873 else | |
1874 printf("\t.align 2\n"); | |
153 | 1875 /* if (stmode!=STATIC) |
1876 printf(".globl _%s\n",name); */ | |
132 | 1877 printf(".ent %s\n",name); |
130 | 1878 printf("_%s:\n",name); |
132 | 1879 |
130 | 1880 r1_offset_label = fwdlabel(); |
1881 lvar_offset_label = fwdlabel(); | |
152 | 1882 disp_label = fwdlabel(); |
132 | 1883 mask_label = fwdlabel(); |
1884 mask1_label = fwdlabel(); | |
1885 fmask_label = fwdlabel(); | |
1886 fmask1_label = fwdlabel(); | |
152 | 1887 cprestore_label = fwdlabel(); |
132 | 1888 |
1889 printf("\t.frame $fp,L_%d,$31\n",r1_offset_label); | |
1890 printf("\t.mask L_%d,L_%d\n",mask_label,mask1_label); | |
1891 printf("\t.fmask L_%d,L_%d\n",fmask_label,fmask1_label); | |
1892 | |
1893 printf("\t.set noreorder\n"); | |
1894 printf("\t.cpload $25\n"); | |
1895 printf("\t.set reorder\n"); | |
152 | 1896 printf("\tsubu $sp,$sp,L_%d\n",disp_label); |
153 | 1897 printf("\t.cprestore L_%d\n",cprestore_label); |
130 | 1898 max_func_args = 0; |
153 | 1899 max_func_iargs = 0; |
148 | 1900 |
130 | 1901 } |
1902 | |
1903 void | |
1904 enter1() | |
1905 { | |
1906 set_creg(CREG_REGISTER,0); | |
1907 set_freg(FREG_FREGISTER,0); | |
148 | 1908 set_dreg(DREG_DREGISTER,0); |
130 | 1909 } |
1910 | |
153 | 1911 static unsigned int |
1912 code_mask_label() | |
130 | 1913 { |
153 | 1914 int i; |
1915 unsigned int mask=0; | |
1916 for(i=0;i<32;i++) { | |
1917 if (i==28||i==31||(REG_VAR_MIN<=i&&i<=REG_VAR_MIN+max_reg_var)) { | |
1918 mask |= (1<<i); | |
1919 } | |
1920 } | |
1921 return mask; | |
130 | 1922 } |
1923 | |
153 | 1924 static unsigned int |
1925 code_fmask_label() | |
1926 { | |
1927 int i; | |
1928 unsigned int mask=0; | |
1929 for(i=0;i<32;i++) { | |
1930 if (FREG_VAR_MIN<=i&&i<=FREG_VAR_MIN+max_freg_var) { | |
1931 mask |= (1<<i); | |
1932 } | |
1933 } | |
1934 return mask; | |
1935 } | |
1936 | |
1937 | |
130 | 1938 void |
1939 leave(int control, char *name) | |
1940 { | |
131 | 1941 int retcont1=0,sz; |
152 | 1942 int r1_offsetv; |
130 | 1943 |
1944 if (max_freg_var>=0 && max_freg_var<=3) max_freg_var=3; | |
153 | 1945 reg_save = |
1946 (REAL_MAX_REGISTER-(REG_VAR_BASE-max_reg_var))*size_of_int; | |
1947 freg_save = | |
1948 (REAL_MAX_FREGISTER-(FREG_VAR_BASE-max_freg_var))*size_of_float; | |
130 | 1949 |
1950 if (control) { | |
1951 code_set_return_register(1); | |
1952 } | |
1953 if (retcont) { | |
152 | 1954 /* return from CbC segement */ |
130 | 1955 if (control) jmp(retlabel); |
1956 retcont1 = fwdlabel(); | |
1957 fwddef(retcont); | |
152 | 1958 if (cadr(fnptr->ty)==FLOAT) { |
1959 if (freg!=RET_FREGISTER) | |
1960 printf("\tmov.s %s,%s\n",register_name(RET_FREGISTER), | |
1961 register_name(freg)); | |
1962 } else if (cadr(fnptr->ty)==DOUBLE) { | |
1963 move_dreg(RET_DREGISTER,dreg); | |
130 | 1964 } else if (cadr(fnptr->ty)>0&&( |
1965 car(cadr(fnptr->ty))==STRUCT || | |
1966 car(cadr(fnptr->ty))==UNION)) { | |
1967 sz = size(cadr(fnptr->ty)); | |
152 | 1968 printf("\tli $4,%d\n",sz); |
1969 printf("\tsubl $5,$4,$fp\n"); | |
1970 printf("\tlw $3,(%d)($fp)\n",(my_func_args-1)*size_of_int); | |
130 | 1971 emit_copy(6,3,sz,0,1,1); |
1972 } else if (cadr(fnptr->ty)!=VOID) { | |
152 | 1973 if (creg!=RET_REGISTER) |
1974 printf("\tmove $3,%s\n",register_name(creg)); | |
130 | 1975 } |
152 | 1976 printf("\tj L_%d\n",retcont1); |
130 | 1977 } |
1978 fwddef(retlabel); | |
1979 if (retcont) { | |
1980 fwddef(retcont1); | |
1981 } | |
1982 if (max_freg_var>=0) { | |
1983 } else { | |
1984 } | |
152 | 1985 fprintf(asi,"L_%d=%d\n",r1_offset_label,0); |
1986 fprintf(asi,"L_%d=%d\n",lvar_offset_label,0); | |
153 | 1987 fprintf(asi,"L_%d=0x%x\n",mask_label,code_mask_label()); |
152 | 1988 fprintf(asi,"L_%d=%d\n",mask1_label,0); |
153 | 1989 fprintf(asi,"L_%d=0x%x\n",fmask_label ,code_fmask_label()); |
152 | 1990 fprintf(asi,"L_%d=%d\n",fmask1_label,0); |
153 | 1991 fprintf(asi,"L_%d=%d\n",cprestore_label ,max_func_iargs); |
130 | 1992 |
1993 disp &= -size_of_int; | |
152 | 1994 r1_offsetv = 0; |
1995 | |
1996 printf("\tmove $sp,$fp\n"); | |
1997 printf("\tlw $31,%d($sp)\n",-disp); | |
1998 printf("\tlw $fp,%d($sp)\n",-disp-4); | |
1999 printf("\taddu $sp,$sp,%d\n",r1_offsetv); | |
2000 printf("\tj $31\n"); | |
2001 printf("\t.end print\n"); | |
2002 | |
2003 fprintf(asi,"L_%d=%d\n",disp_label,-r1_offsetv); | |
130 | 2004 |
2005 code_offset_set(); | |
2006 local_table(); | |
2007 labelno++; | |
2008 free_all_register(); | |
2009 } | |
2010 | |
2011 | |
2012 void | |
2013 code_set_return_register(int mode) { | |
148 | 2014 if (cadr(fnptr->ty)==DOUBLE) { |
2015 set_dreg(RET_DREGISTER,mode); | |
2016 } else if (cadr(fnptr->ty)==FLOAT) { | |
130 | 2017 set_freg(RET_FREGISTER,mode); |
148 | 2018 } else if (cadr(fnptr->ty)==VOID) { |
130 | 2019 } else { |
2020 set_creg(RET_REGISTER,mode); | |
2021 } | |
2022 } | |
2023 | |
2024 void | |
2025 code_set_fixed_creg(int mode,int type) { | |
148 | 2026 if (type==FLOAT) { |
130 | 2027 if (cond_freg== -1) { |
148 | 2028 cond_freg = get_dregister_var(0,0); |
2029 if(car(cond_freg)!=FREGISTER) error(-1); | |
130 | 2030 } |
2031 set_freg(cadr(cond_freg),mode); | |
148 | 2032 } else if (type==DOUBLE) { |
2033 if (cond_dreg== -1) { | |
2034 cond_dreg = get_dregister_var(0,1); | |
2035 if(car(cond_dreg)!=DREGISTER) error(-1); | |
2036 } | |
2037 set_dreg(cadr(cond_dreg),mode); | |
130 | 2038 } else { |
2039 if (cond_reg== -1) { | |
2040 cond_reg = get_register_var(0); | |
2041 if(car(cond_reg)!=REGISTER) error(-1); | |
2042 } | |
2043 set_creg(cadr(cond_reg),mode); | |
2044 } | |
2045 } | |
2046 | |
2047 void | |
2048 gen_gdecl(char *n, int gpc) | |
2049 { | |
2050 if (stmode!=STATIC) | |
153 | 2051 printf("\t.globl _%s\n",n); |
130 | 2052 } |
2053 | |
2054 void | |
2055 align(int t) | |
2056 { | |
2057 if (t!=CHAR) { | |
2058 if (data_alignment & 1) | |
2059 printf("\t.align 2\n"); | |
2060 data_alignment = 0; | |
2061 } | |
2062 } | |
2063 | |
2064 void | |
2065 emit_data(int e, int t, NMTBL *n) | |
2066 { | |
2067 int l; | |
2068 double d; | |
2069 float f; | |
2070 char *name; | |
2071 name = n->nm; | |
156 | 2072 if(mode!=GDECL&&mode!=STADECL) { |
130 | 2073 error(-1); return; |
2074 } | |
2075 if (chk) return; | |
2076 if (n->dsp != -1) { | |
2077 n->dsp = -1; /* initiallized flag */ | |
153 | 2078 /* printf(".globl\t_%s\n",name); */ |
130 | 2079 data_mode(name); |
2080 align(t); | |
2081 printf("_%s:\n",name); | |
2082 } else { | |
2083 data_mode(0); | |
2084 } | |
2085 if(car(e)==CONST) { | |
168 | 2086 if (t==CHAR||t==UCHAR) { |
130 | 2087 printf("\t.byte %d\n",cadr(e)); |
2088 if (data_alignment>0) | |
2089 data_alignment++; | |
2090 gpc += 1; | |
168 | 2091 } else if (t==SHORT||t==USHORT) { |
2092 printf("\t.short %d\n",cadr(e)); | |
130 | 2093 if (data_alignment>0) data_alignment++; |
2094 gpc += 2; | |
2095 } else { | |
148 | 2096 printf("\t.word %d\n",cadr(e)); |
130 | 2097 gpc += size_of_int; |
2098 } | |
2099 } else if(t==DOUBLE) { | |
148 | 2100 d = dcadr(e); |
153 | 2101 printf("\t.word\t0x%x\n\t.word\t0x%x\n",code_d1(d),code_d2(d)); |
130 | 2102 } else if(t==FLOAT) { |
148 | 2103 f = dcadr(e); |
2104 printf("\t.word\t0x%x\n",*(int *)&f); | |
130 | 2105 } else if(t!=CHAR) { |
2106 gpc += size_of_int; | |
148 | 2107 if(car(e)==ADDRESS&&car(cadr(e))==GVAR) { |
2108 printf("\t.word _%s\n",((NMTBL *)cadr(cadr(e)))->nm); | |
2109 } else if(car(e)==FNAME) { | |
2110 printf("\t.word _%s\n",((NMTBL *)cadr(e))->nm); | |
2111 } else if(car(e)==GVAR) { | |
2112 printf("\t.word _%s\n",((NMTBL *)cadr(e))->nm); | |
2113 } else if(car(e)==STRING) { | |
2114 if (car(n->ty)!=ARRAY || cadr(n->ty)!=CHAR) { | |
2115 l = fwdlabel(); | |
2116 printf("\t.word L_%d\n",l); | |
2117 printf(".rdata\n\t.align 2\n"); | |
2118 printf("L_%d:\n",l); | |
2119 output_mode = RODATA_EMIT_MODE; | |
2120 } | |
2121 ascii((char *)cadr(e)); | |
130 | 2122 } else error(TYERR); |
168 | 2123 } else error(TYERR); |
130 | 2124 } |
2125 | |
2126 void | |
2127 emit_data_closing(NMTBL *n) | |
2128 { | |
2129 #ifdef DOT_SIZE | |
2130 int lb; | |
2131 #endif | |
2132 if (chk) return; | |
2133 if (mode==GDECL) { | |
2134 data_mode(0); | |
2135 #ifdef DOT_SIZE | |
2136 lb=fwdlabel(); | |
2137 printf("L_%d:\n",lb); | |
2138 printf("\t.size\t%s,L_%d-%s\n",n->nm,lb,n->nm); | |
2139 #endif | |
2140 } | |
2141 } | |
2142 | |
149 | 2143 void |
130 | 2144 global_table(void) |
2145 { | |
2146 NMTBL *n; | |
131 | 2147 int init; |
130 | 2148 init=0; |
2149 for(n=ntable;n < &ntable[GSYMS];n++) { | |
148 | 2150 if ((n->sc == GVAR) && n->dsp != -1) { |
2151 /* n->dsp = -1 means initialized global */ | |
2152 if (init==0) { | |
2153 data_mode(0); | |
2154 init=1; | |
2155 } | |
2156 printf(".comm _%s,%d\n",n->nm,size(n->ty)); | |
2157 } else if ((n->sc==STATIC) && n->dsp != -1) { | |
2158 /* n->dsp = -1 means initialized global */ | |
2159 if (init==0) { | |
2160 data_mode(0); | |
2161 init=1; | |
2162 } | |
2163 printf(".lcomm _%s,%d\n",n->nm,size(n->ty)); | |
2164 } | |
130 | 2165 } |
2166 } | |
2167 | |
2168 void | |
2169 local_table(void) | |
2170 { | |
2171 NMTBL *n; | |
2172 int init; | |
2173 init=0; | |
2174 /* static local variables */ | |
2175 for(n=ntable+GSYMS;n < &ntable[GSYMS+LSYMS];n++) { | |
2176 if (n->sc == GVAR) { | |
2177 if (init==0) { | |
2178 data_mode(0); | |
2179 init=1; | |
2180 } | |
156 | 2181 if (n->dsp!=-1) /* n->dsp = -1 means initialized global */ |
130 | 2182 printf(".lcomm _%s,%d\n",n->nm,size(n->ty)); |
2183 } | |
2184 } | |
2185 } | |
2186 | |
2187 void | |
2188 text_mode(void) | |
2189 { | |
2190 if (output_mode!=TEXT_EMIT_MODE) { | |
2191 printf(".text\n"); | |
2192 printf("\t.align 2\n"); | |
2193 output_mode = TEXT_EMIT_MODE; | |
2194 } | |
2195 } | |
2196 | |
2197 void | |
2198 data_mode(char *name) | |
2199 { | |
2200 if (output_mode!=DATA_EMIT_MODE) { | |
2201 printf(".data\n"); | |
2202 output_mode = DATA_EMIT_MODE; | |
2203 } | |
2204 if (name) | |
2205 printf("\t.type\t%s,@object\n",name); | |
2206 } | |
2207 | |
2208 char * | |
2209 fstore(int d) | |
2210 { | |
148 | 2211 return (d?"stfd":"stfs"); |
130 | 2212 } |
2213 | |
2214 char * | |
2215 fload(int d) | |
2216 { | |
148 | 2217 return d?"lfd":"lfs"; |
130 | 2218 } |
2219 | |
153 | 2220 static |
2221 void code_dpfunc(char *f) | |
2222 { | |
2223 if (max_func_iargs<16) max_func_iargs=16; | |
2224 printf("\tjal %s\n",f); | |
2225 } | |
2226 | |
130 | 2227 void |
138 | 2228 code_cmp_dregister(int e2,int d) |
130 | 2229 { |
149 | 2230 char *frn,*grn; |
2231 int greg; | |
2232 | |
2233 if (d) { | |
2234 printf("\tli.d $6,%g\n",0.0); | |
2235 code_save_stacks(); | |
2236 move_dreg(4+DREG_OFFSET,freg); | |
153 | 2237 code_dpfunc("dpcmp"); |
2238 if (max_func_iargs<16) max_func_iargs=16; | |
149 | 2239 set_dreg(RET_DREGISTER,0); |
2240 return; | |
2241 } else { | |
2242 grn = register_name(greg = get_dregister(d)); | |
2243 frn = register_name(e2); | |
2244 printf("\tli.s %s,%g\n",grn,0.0); | |
2245 printf("\tc.eq.s %s,%s\n",grn,frn); | |
2246 free_register(greg); | |
2247 return; | |
2248 } | |
130 | 2249 } |
2250 | |
2251 void | |
138 | 2252 code_dregister(int e2,int freg,int d) |
130 | 2253 { |
141 | 2254 if (freg!=e2) { |
149 | 2255 if (d) { |
2256 if (!is_double_reg(e2)) error(-1); | |
2257 move_dreg(freg,e2); | |
2258 } else { | |
2259 if (!is_float_reg(e2)) error(-1); | |
2260 printf("\tfmr %s,%s\n",fregister_name(freg),fregister_name(e2)); | |
2261 } | |
141 | 2262 } |
148 | 2263 regv[freg]=1; |
130 | 2264 } |
2265 | |
2266 void code_dassign_gvar(int e2,int freg,int d) | |
2267 { | |
149 | 2268 NMTBL *n = (NMTBL*)cadr(e2); |
2269 if (d) { | |
2270 if (!is_double_reg(freg)) error(-1); | |
2271 printf("\tsw %s,0(%s)\n",dregister_name0(freg),n->nm); | |
2272 printf("\tsw %s,0(%s)\n",dregister_name1(freg),n->nm); | |
2273 } else { | |
2274 printf("\ts.s %s,0(%s)\n",fregister_name(freg),n->nm); | |
2275 } | |
148 | 2276 regv[freg]=1; |
130 | 2277 } |
2278 | |
2279 void code_dassign_lvar(int e2,int freg,int d) | |
2280 { | |
149 | 2281 if (d) { |
2282 if (!is_double_reg(freg)) error(-1); | |
2283 printf("\tsw %s,",dregister_name0(freg)); | |
2284 lvar(e2); | |
2285 printf("\tsw %s,",dregister_name1(freg)); | |
2286 e2 += size_of_double/2; | |
2287 } else { | |
2288 printf("\ts.s %s,",fregister_name(freg)); | |
2289 } | |
130 | 2290 lvar(e2); |
148 | 2291 regv[freg]=1; |
130 | 2292 } |
2293 | |
2294 void code_dassign(int e2,int freg,int d) | |
2295 { | |
149 | 2296 if (d) { |
2297 if (!is_double_reg(freg)) error(-1); | |
2298 printf("\tsw %s,0(%s)\n",dregister_name0(freg),register_name(e2)); | |
2299 printf("\tsw %s,4(%s)\n",dregister_name1(freg),register_name(e2)); | |
2300 } else { | |
2301 printf("\ts.s %s,0(%s)\n",fregister_name(freg),register_name(e2)); | |
2302 } | |
148 | 2303 regv[freg]=1; |
130 | 2304 } |
2305 | |
2306 void | |
138 | 2307 code_dassign_dregister(int e2,int d,int freg) { |
149 | 2308 /* これってさ、code_dregister と同じ? */ |
141 | 2309 if (e2!=freg) { |
149 | 2310 if (d) { |
2311 if (!is_double_reg(freg)) error(-1); | |
2312 move_dreg(freg,e2); | |
2313 } else { | |
2314 printf("\tmov.s %s,%s\n",fregister_name(e2),fregister_name(freg)); | |
2315 } | |
141 | 2316 } |
149 | 2317 |
130 | 2318 } |
2319 | |
136
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2320 static double d0 = 1.0; |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2321 |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2322 int |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2323 code_d1(double d) |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2324 { |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2325 int *i = (int *)&d0; int *j = (int *)&d; |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2326 return (i[1] == 0x3ff00000)?j[0]:j[1]; |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2327 } |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2328 |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2329 int |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2330 code_d2(double d) |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2331 { |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2332 int *i = (int *)&d0; int *j = (int *)&d; |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2333 return (i[1] == 0x3ff00000)?j[1]:j[0]; |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2334 } |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2335 |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2336 int |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2337 code_f(double d) |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2338 { |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2339 float f = d; |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2340 int *j = (int *)&f; |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2341 return *j; |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2342 } |
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2343 |
148 | 2344 void |
2345 code_dconst(int e2,int freg,int d) | |
130 | 2346 { |
138 | 2347 double value = dcadr(e2); |
149 | 2348 char *frn; |
2349 if (d) { | |
2350 printf("\tli.d %s,%g\n",dregister_name0(freg),value); | |
2351 } else { | |
2352 frn = fregister_name(freg); | |
2353 printf("\tli.s %s,%g\n",frn,value); | |
148 | 2354 } |
2355 regv[freg]=1; | |
130 | 2356 } |
2357 | |
136
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2358 |
138 | 2359 void code_dneg(int freg,int d) |
130 | 2360 { |
149 | 2361 char *frn; |
2362 if (d) { | |
2363 code_save_stacks(); | |
2364 move_dreg(4+DREG_OFFSET,freg); | |
153 | 2365 code_dpfunc("dpneg"); |
149 | 2366 set_dreg(RET_DREGISTER,0); |
2367 } else { | |
2368 frn = fregister_name(freg); | |
2369 printf("\tfneg %s,%s\n",frn,frn); | |
2370 } | |
130 | 2371 } |
2372 | |
148 | 2373 void code_d2i(int freg0) |
130 | 2374 { |
149 | 2375 code_save_stacks(); |
2376 set_dreg(RET_DREGISTER,1); | |
153 | 2377 code_dpfunc("dptoli"); |
149 | 2378 set_creg(RET_REGISTER,0); |
2379 regv[freg]=0; | |
148 | 2380 regv[creg]=1; |
130 | 2381 } |
2382 | |
148 | 2383 void code_i2d(int creg0) |
2384 { | |
141 | 2385 code_save_stacks(); |
148 | 2386 set_creg(RET_REGISTER,1); |
153 | 2387 code_dpfunc("litodp"); |
150 | 2388 set_dreg(RET_DREGISTER,0); |
148 | 2389 regv[freg]=1; |
149 | 2390 regv[creg]=0; |
141 | 2391 } |
136
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2392 |
148 | 2393 void code_d2u(int freg0) |
2394 { | |
141 | 2395 code_save_stacks(); |
149 | 2396 set_dreg(RET_DREGISTER,1); |
153 | 2397 code_dpfunc("dptoul"); |
148 | 2398 set_creg(RET_REGISTER,0); |
2399 regv[freg]=1; | |
141 | 2400 } |
2401 | |
148 | 2402 void code_u2d(int creg0) |
2403 { | |
2404 code_save_stacks(); | |
2405 set_creg(RET_REGISTER,1); | |
153 | 2406 code_dpfunc("ultodp"); |
149 | 2407 set_dreg(RET_DREGISTER,0); |
148 | 2408 regv[freg]=1; |
141 | 2409 } |
2410 | |
149 | 2411 void code_d2f(int freg) { |
2412 code_save_stacks(); | |
2413 set_dreg(RET_DREGISTER,1); | |
153 | 2414 code_dpfunc("dptofp"); |
149 | 2415 set_freg(RET_FREGISTER,0); |
2416 } | |
2417 | |
2418 void code_f2d(int freg) { | |
2419 code_save_stacks(); | |
2420 set_freg(RET_FREGISTER,1); | |
153 | 2421 code_dpfunc("fptodp"); |
149 | 2422 set_dreg(RET_DREGISTER,0); |
2423 } | |
2424 | |
2425 void code_f2i(int freg) { | |
2426 printf("\ttrunc.w.s %s,%s,%s\n",register_name(freg), | |
2427 register_name(freg),register_name(ireg)); | |
2428 creg = ireg; | |
2429 } | |
2430 | |
2431 void code_f2u(int freg) { | |
2432 printf("\ttrunc.w.s %s,%s,%s\n",register_name(freg), | |
2433 register_name(freg),register_name(ireg)); | |
2434 creg = ireg; | |
2435 } | |
2436 | |
2437 void code_i2f(int creg0) { | |
2438 printf("\tcvt.s.w %s,%s\n",register_name(freg),register_name(freg)); | |
2439 creg = freg; | |
2440 } | |
2441 | |
2442 void code_u2f(int creg0) { | |
2443 printf("\tcvt.s.w %s,%s\n",register_name(freg),register_name(freg)); | |
2444 creg = freg; | |
2445 } | |
136
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2446 |
130 | 2447 void code_drgvar(int e2,int d,int freg) |
2448 { | |
151 | 2449 char *name = ((NMTBL*)cadr(e2))->nm; |
149 | 2450 if (d) { |
151 | 2451 printf("\tlw %s,%s\n",dregister_name0(freg),name); |
2452 printf("\tlw %s,%s\n",dregister_name1(freg),name); | |
149 | 2453 } else { |
151 | 2454 printf("\tl.s %s,%s\n",fregister_name(freg),name); |
149 | 2455 } |
148 | 2456 regv[freg]=1; |
130 | 2457 } |
2458 | |
2459 | |
2460 void code_drlvar(int e2,int d,int freg) | |
2461 { | |
149 | 2462 if (d) { |
152 | 2463 printf("\tlw %s,",dregister_name0(freg)); lvar(e2); |
2464 printf("\tlw %s,",dregister_name1(freg)); lvar(e2+size_of_double/2); | |
149 | 2465 } else { |
2466 printf("\tl.s %s,",fregister_name(freg)); lvar(e2); | |
2467 } | |
148 | 2468 regv[freg]=1; |
130 | 2469 } |
2470 | |
138 | 2471 void code_cmp_drgvar(int e2,int d) |
130 | 2472 { |
149 | 2473 char *frn; |
2474 int g; | |
2475 if (d) { | |
2476 code_save_stacks(); | |
2477 set_dreg(RET_DREGISTER,1); | |
2478 code_drgvar(e2,d,RET_DREGISTER+2); | |
153 | 2479 code_dpfunc("dcmp"); |
149 | 2480 regv[dreg]=0; |
2481 } else { | |
2482 frn=fregister_name(freg); | |
2483 g=get_dregister(d); | |
2484 code_drgvar(e2,d,g); | |
2485 printf("\tfc.eq.s %s,%s\n",frn,fregister_name(g)); | |
2486 free_register(g); | |
2487 regv[freg]=0; | |
2488 } | |
130 | 2489 } |
2490 | |
138 | 2491 void code_cmp_drlvar(int e2,int d) |
130 | 2492 { |
2493 char *frn=fregister_name(freg); | |
149 | 2494 int g; |
2495 if (d) { | |
2496 code_save_stacks(); | |
2497 set_dreg(RET_DREGISTER,1); | |
2498 code_drgvar(e2,d,RET_DREGISTER+2); | |
153 | 2499 code_dpfunc("dcmp"); |
149 | 2500 regv[dreg]=0; |
2501 } else { | |
2502 g=get_dregister(d); | |
2503 code_drlvar(e2,d,g); | |
2504 printf("\tc.eq.s %s,%s\n",frn,fregister_name(g)); | |
2505 free_register(g); | |
2506 regv[freg]=0; | |
2507 } | |
2508 } | |
130 | 2509 |
149 | 2510 static void |
2511 dtosop0(char *opn,int e1,int d,int cmp) | |
2512 { | |
2513 char *frn; | |
2514 char *grn; | |
2515 if (d) { | |
2516 code_save_stacks(); | |
2517 set_dreg(RET_DREGISTER,1); | |
2518 move_dreg(RET_DREGISTER+2,e1); | |
153 | 2519 code_dpfunc(opn); |
149 | 2520 } else { |
2521 frn=fregister_name(freg); | |
2522 grn=fregister_name(e1); | |
2523 if (cmp) { | |
2524 printf("\t%s %s,%s\n",opn,frn,grn); | |
2525 } else { | |
2526 printf("\t%s %s,%s,%s\n",opn,frn,frn,grn); | |
2527 } | |
2528 } | |
2529 free_register(e1); | |
141 | 2530 } |
2531 | |
149 | 2532 |
130 | 2533 void dtosop(int op,int e1) |
2534 { | |
148 | 2535 regv[freg]=1; |
130 | 2536 switch(op) { |
149 | 2537 case FADD: dtosop0("fadd",e1,0,0); return; |
2538 case DADD: dtosop0("dpadd",e1,1,0); return; | |
2539 case FSUB: dtosop0("fadd",e1,0,0); return; | |
2540 case DSUB: dtosop0("dpsub",e1,1,0); return; | |
2541 case FDIV: dtosop0("fadd",e1,0,0); return; | |
2542 case DDIV: dtosop0("dpdiv",e1,1,0); return; | |
2543 case FMUL: dtosop0("fadd",e1,0,0); return; | |
2544 case DMUL: dtosop0("dpmul",e1,1,0); return; | |
141 | 2545 case DCMPGE: |
149 | 2546 case DCMP: dtosop0("dpcmp",e1,1,1); return; |
2547 case FCMPGE: dtosop0("c.le.s",e1,0,1); return; | |
2548 case FCMP: dtosop0("c.eq.s",e1,0,1); return; | |
136
069960078249
remove redundant funcall argument for prototyped code in PowerPC case.
kono
parents:
133
diff
changeset
|
2549 default: |
149 | 2550 error(-1); return; |
130 | 2551 } |
2552 } | |
2553 | |
2554 void | |
2555 code_dassop(int op,int d) { | |
2556 /* we have lvalue in creg, applied floating value is in freg */ | |
149 | 2557 char *frn; |
2558 int xreg; | |
130 | 2559 char *crn=register_name(creg); |
2560 | |
149 | 2561 if (d) { |
2562 xreg=emit_dpop(d); | |
2563 printf("\tlw %s,0(%s)\n",dregister_name0(freg),crn); | |
2564 printf("\tlw %s,%d(%s)\n",dregister_name1(freg),size_of_int,crn); | |
2565 dtosop(op,xreg); | |
2566 printf("\tsw %s,0(%s)\n",dregister_name0(freg),crn); | |
2567 printf("\tsw %s,%d(%s)\n",dregister_name1(freg),size_of_int,crn); | |
2568 emit_dpop_free(xreg,d); | |
2569 creg = dreg; | |
2570 } else { | |
2571 xreg=emit_dpop(d); | |
2572 frn=fregister_name(freg); | |
2573 crn=register_name(creg); | |
2574 | |
2575 printf("\tl.s %s,0(%s)\n",frn,crn); | |
2576 dtosop(op,xreg); | |
2577 printf("\ts.s %s,0(%s)\n",frn,crn); | |
2578 emit_dpop_free(xreg,d); | |
2579 creg = freg; | |
2580 } | |
2581 regv[creg]=1; | |
130 | 2582 } |
2583 | |
2584 | |
2585 void | |
2586 code_dpreinc(int e1,int e2,int d,int reg) { | |
2587 char *frn; | |
2588 char *crn; | |
2589 int g; | |
149 | 2590 char *grn; |
130 | 2591 |
2592 g_expr(e2); | |
2593 | |
149 | 2594 if (d) { |
2595 crn=register_name(creg); | |
2596 frn=fregister_name(freg); | |
130 | 2597 |
149 | 2598 code_save_stacks(); |
2599 set_dreg(RET_DREGISTER,0); | |
2600 printf("\tlw $4,0(%s)\n",crn); | |
2601 printf("\tlw $5,%d(%s)\n",size_of_int,crn); | |
2602 printf("\tli.d $6,1.0\n"); | |
2603 if (caddr(e1)>0) | |
153 | 2604 code_dpfunc("dpadd"); |
149 | 2605 else |
153 | 2606 code_dpfunc("dpsub"); |
149 | 2607 printf("\tsw $2,0(%s)\n",crn); |
2608 printf("\tsw $3,%d(%s)\n",size_of_int,crn); | |
2609 creg = dreg; | |
2610 } else { | |
2611 crn=register_name(creg); | |
2612 frn=fregister_name(freg); | |
2613 grn=fregister_name(g=get_dregister(d)); | |
2614 | |
2615 printf("\tl.s %s,0(%s)\n",frn,crn); | |
2616 printf("\tli.s %s,1.0\n",grn); | |
2617 if (caddr(e1)>0) | |
2618 printf("\tfadd %s,%s,%s\n",frn,frn,grn); | |
2619 else | |
2620 printf("\tfsub %s,%s,%s\n",frn,frn,grn); | |
2621 printf("\ts.s %s,0(%s)\n",frn,crn); | |
2622 free_register(g); | |
2623 creg = freg; | |
2624 } | |
2625 regv[creg]=1; | |
130 | 2626 } |
2627 | |
2628 void | |
2629 code_dpostinc(int e1,int e2,int d,int reg) { | |
2630 char *frn; | |
2631 char *crn; | |
2632 int g; | |
149 | 2633 char *grn; |
130 | 2634 |
2635 g_expr(e2); | |
2636 | |
149 | 2637 if (d) { |
2638 crn=register_name(creg); | |
2639 g = get_dregister(d); | |
2640 set_dreg(RET_DREGISTER,0); | |
2641 printf("\tlw $4,0(%s)\n",crn); | |
2642 printf("\tlw $5,%d(%s)\n",size_of_int,crn); | |
2643 move_dreg(g,4+DREG_OFFSET); | |
2644 printf("\tli.d $6,1.0\n"); | |
2645 if (caddr(e1)>0) | |
153 | 2646 code_dpfunc("dpadd"); |
149 | 2647 else |
153 | 2648 code_dpfunc("dpsub"); |
149 | 2649 set_dreg(RET_DREGISTER,0); |
2650 printf("\tsw $2,0(%s)\n",crn); | |
2651 printf("\tsw $3,%d(%s)\n",size_of_int,crn); | |
152 | 2652 free_register(dreg); |
149 | 2653 set_dreg(g,0); |
2654 creg = g; | |
2655 } else { | |
2656 crn=register_name(creg); | |
2657 frn=fregister_name(freg); | |
2658 grn=fregister_name(g=get_dregister(d)); | |
130 | 2659 |
149 | 2660 printf("\tl.s %s,0(%s)\n",frn,crn); |
2661 printf("\tli.s %s,1.0\n",grn); | |
2662 if (caddr(e1)>0) | |
2663 printf("\tfadd %s,%s,%s\n",frn,frn,grn); | |
2664 else | |
2665 printf("\tfsub %s,%s,%s\n",frn,frn,grn); | |
2666 printf("\ts.s %s,0(%s)\n",grn,crn); | |
2667 free_register(g); | |
2668 creg = freg; | |
2669 } | |
2670 regv[creg]=1; | |
2671 | |
130 | 2672 } |
2673 | |
2674 void | |
2675 drexpr(int e1, int e2,int l1, int op) | |
2676 { | |
149 | 2677 g_expr(list3(((op==FOP+EQ||op==FOP+NEQ)?DCMP:FCMPGE),e1,e2)); |
130 | 2678 switch(op) { |
149 | 2679 case DOP+GE: |
2680 printf("\tbgez\tL_%d\n",l1); | |
2681 break; | |
2682 case DOP+GT: | |
2683 printf("\tbltz\tL_%d\n",l1); | |
2684 break; | |
2685 case DOP+EQ: | |
2686 printf("\tbeq\tL_%d\n",l1); | |
2687 break; | |
2688 case DOP+NEQ: | |
2689 printf("\tbne\tL_%d\n",l1); | |
2690 break; | |
2691 case FOP+GE: | |
2692 printf("\tbc1tl\tL_%d\n",l1); | |
2693 break; | |
2694 case FOP+GT: | |
2695 printf("\tbc1tl\tL_%d\n",l1); | |
2696 break; | |
2697 case FOP+EQ: | |
2698 printf("\tbc1f\tL_%d\n",l1); | |
2699 break; | |
2700 case FOP+NEQ: | |
2701 printf("\tbc1f\tL_%d\n",l1); | |
2702 break; | |
130 | 2703 } |
2704 } | |
2705 | |
138 | 2706 int emit_dpop(int d) |
130 | 2707 { |
2708 int xreg,reg; | |
151 | 2709 if (d) |
2710 xreg=pop_dregister(); | |
2711 else | |
2712 xreg=pop_fregister(); | |
130 | 2713 if (xreg<= -REG_LVAR_OFFSET) { |
138 | 2714 reg = get_dregister(d); |
149 | 2715 code_drlvar(REG_LVAR_OFFSET+xreg,d,reg); |
130 | 2716 free_lvar(REG_LVAR_OFFSET+xreg); |
148 | 2717 regv[reg]=1; xreg=reg; |
130 | 2718 } |
2719 return xreg; | |
2720 } | |
2721 | |
138 | 2722 void emit_dpop_free(int e1,int d) |
130 | 2723 { |
148 | 2724 free_register(e1); |
130 | 2725 } |
2726 | |
133 | 2727 void emit_dpush(int d) |
130 | 2728 { |
2729 int new_reg; | |
2730 if (freg_sp>MAX_MAX) error(-1); | |
149 | 2731 new_reg = get_dregister(d); |
151 | 2732 if (d) { |
2733 dreg_stack[dreg_sp++] = dreg; /* push するかわりにレジスタを使う */ | |
2734 creg = dreg = new_reg; | |
2735 regv[dreg]=1; | |
2736 } else { | |
2737 freg_stack[freg_sp++] = freg; /* push するかわりにレジスタを使う */ | |
2738 creg = freg = new_reg; | |
2739 regv[freg]=1; | |
2740 } | |
130 | 2741 } |
2742 | |
2743 void | |
2744 code_save_stacks() | |
2745 { | |
2746 int i,reg; | |
2747 for(i=0;i<reg_sp;i++) { | |
2748 if ((reg=reg_stack[i])>=0) { | |
2749 code_assign_lvar( | |
2750 (reg_stack[i]=new_lvar(size_of_int)),reg,0); | |
2751 reg_stack[i]= reg_stack[i]-REG_LVAR_OFFSET; | |
2752 } | |
2753 } | |
149 | 2754 for(i=0;i<dreg_sp;i++) { |
2755 if ((reg=dreg_stack[i])>=0) { | |
2756 code_dassign_lvar( | |
2757 (dreg_stack[i]=new_lvar(size_of_double)),reg,1); | |
2758 dreg_stack[i]= dreg_stack[i]-REG_LVAR_OFFSET; | |
2759 } | |
2760 } | |
130 | 2761 for(i=0;i<freg_sp;i++) { |
2762 if ((reg=freg_stack[i])>=0) { | |
2763 code_dassign_lvar( | |
149 | 2764 (freg_stack[i]=new_lvar(size_of_float)),reg,0); |
130 | 2765 freg_stack[i]= freg_stack[i]-REG_LVAR_OFFSET; |
2766 } | |
2767 } | |
2768 } | |
2769 | |
2770 void | |
2771 emit_lib(char *p[]) | |
2772 { | |
2773 while(*p) { | |
2774 printf("%s\n",*p++); | |
2775 } | |
2776 } | |
2777 | |
2778 void | |
2779 code_closing() | |
2780 { | |
2781 global_table(); | |
2782 /* printf("\t.ident \"Micro-C compiled\"\n"); */ | |
149 | 2783 fclose(asi); |
130 | 2784 } |
2785 | |
2786 /* end */ | |
2787 |