Mercurial > hg > CbC > old > device
annotate mc-codegen.c @ 330:fa4c7b15d7ed
bit field all code written
author | kono |
---|---|
date | Wed, 23 Jun 2004 17:12:33 +0900 |
parents | 4c8f8ef8c0cf |
children | f25aa4f03198 |
rev | line source |
---|---|
326 | 1 /* Micro-C Generic Code Generation Part */ |
61 | 2 /* $Id$ */ |
3 | |
327 | 4 #include <stdio.h> |
61 | 5 #include "mc.h" |
327 | 6 #include "mc-parse.h" |
61 | 7 #include "mc-codegen.h" |
8 #include "mc-code.h" | |
9 | |
83 | 10 int use; /* generated value will be used */ |
327 | 11 char *init_src; |
12 int size_of_int; | |
13 int size_of_short; | |
14 int size_of_float; | |
15 int size_of_double; | |
16 int size_of_longlong; | |
17 int bit_of_byte; | |
18 int endian; | |
81 | 19 |
327 | 20 static void assign(int e1); |
21 static void gen_asm(int asm0,int in,int out,int opt,int e); | |
22 static void compatible(int t1, int t2); | |
23 static int contains(int e,int type); | |
24 static int contains_in_list(int e,int type); | |
25 static int contains_in_list_p(int e,int (*p)(int)); | |
26 static void iassop(int e1); | |
105 | 27 static int is_same_type(int e1,int e2); |
28 static void jump(int e1, int env); | |
29 static void machinop(int e1); | |
327 | 30 static int register_to_lvar(int e); |
31 static void remove0(int *parent,int e) ; | |
105 | 32 static void sassign(int e1); |
61 | 33 |
195 | 34 #if FLOAT_CODE |
35 | |
36 /* floating point */ | |
37 | |
38 static void dassop(int e1); | |
39 static void dmachinop(int e1,int d); | |
40 static void dassign(int e1); | |
41 | |
42 #endif | |
43 #if LONGLONG_CODE | |
44 static void lassop(int e1); | |
45 static void lmachinop(int e1); | |
46 static void lassign(int e1); | |
47 #endif | |
48 | |
329 | 49 #if BIT_FIELD_CODE |
50 static int bit_field(int e1,int t); | |
51 static int bassign(int e1,int e2,int t); | |
52 static int bassop(int e1,int e2,int op,int t); | |
53 #endif | |
54 | |
195 | 55 |
327 | 56 extern void |
102 | 57 codegen_init() |
58 { | |
327 | 59 /* called only once */ |
102 | 60 code_init(); |
61 } | |
62 | |
327 | 63 extern void |
64 codegen_reinit() | |
65 { | |
66 /* called for each file */ | |
67 emit_reinit(); | |
68 } | |
69 | |
70 extern void | |
71 codegen_decl_init() | |
72 { | |
73 /* called before each declaration */ | |
74 emit_init(); | |
75 init_free_lvar_list(); | |
76 } | |
77 | |
78 extern void | |
137 | 79 arg_register(NMTBL *fnptr) |
80 { | |
81 code_arg_register(fnptr); | |
82 } | |
83 | |
327 | 84 extern int |
83 | 85 gexpr(int e1,int use0) |
61 | 86 { |
94 | 87 if (chk) return INT; |
61 | 88 gexpr_init(); |
83 | 89 use = use0; |
61 | 90 #if 0 |
91 if(lineno==2862) { | |
94 | 92 return g_expr0(e1); /*break here*/ |
61 | 93 } |
94 #endif | |
94 | 95 return g_expr0(e1); |
61 | 96 } |
97 | |
327 | 98 /* gexpr for value unused */ |
99 | |
100 extern int | |
83 | 101 g_expr_u(int e1) |
102 { | |
94 | 103 int t; |
83 | 104 int suse = use; use=0; |
94 | 105 t=g_expr0(e1); |
147 | 106 code_gexpr(e1); |
107 | |
83 | 108 use=suse; |
94 | 109 return t; |
83 | 110 } |
111 | |
327 | 112 /* gexpr for value used */ |
113 | |
114 extern int | |
61 | 115 g_expr(int e1) |
116 { | |
94 | 117 int t; |
83 | 118 int suse = use; use=1; |
94 | 119 t=g_expr0(e1); |
147 | 120 code_gexpr(e1); |
121 | |
83 | 122 use=suse; |
94 | 123 return t; |
83 | 124 } |
125 | |
327 | 126 /* gexpr for used flag untouched */ |
127 | |
128 extern int | |
83 | 129 g_expr0(int e1) |
130 { | |
191 | 131 int e2,e3,t,d,t1; |
61 | 132 NMTBL *n; |
133 | |
147 | 134 code_gexpr(e1); |
135 | |
61 | 136 e2 = cadr(e1); |
137 switch (car(e1)){ | |
138 case GVAR: | |
221 | 139 code_gvar(e1,USE_CREG); |
94 | 140 return ADDRESS; |
61 | 141 case RGVAR: |
221 | 142 code_rgvar(e1,USE_CREG); |
94 | 143 return INT; |
61 | 144 case CRGVAR: |
221 | 145 code_crgvar(e1,USE_CREG,1,1); |
94 | 146 return CHAR; |
162 | 147 case CURGVAR: |
221 | 148 code_crgvar(e1,USE_CREG,0,1); |
165 | 149 return UCHAR; |
150 case SRGVAR: | |
221 | 151 code_crgvar(e1,USE_CREG,1,size_of_short); |
165 | 152 return CHAR; |
153 case SURGVAR: | |
221 | 154 code_crgvar(e1,USE_CREG,0,size_of_short); |
162 | 155 return UCHAR; |
61 | 156 case LVAR: |
221 | 157 code_lvar(e2,USE_CREG); |
94 | 158 return ADDRESS; |
61 | 159 case REGISTER: |
221 | 160 code_register(e2,USE_CREG); |
94 | 161 return INT; |
195 | 162 #if FLOAT_CODE |
94 | 163 case DREGISTER: |
221 | 164 code_dregister(e2,USE_CREG,1); |
94 | 165 return DOUBLE; |
137 | 166 case FREGISTER: |
221 | 167 code_dregister(e2,USE_CREG,0); |
137 | 168 return FLOAT; |
195 | 169 #endif |
219 | 170 #if LONGLONG_CODE |
171 case LREGISTER: | |
221 | 172 code_lregister(e2,USE_CREG); |
219 | 173 return LONGLONG; |
174 #endif | |
61 | 175 case RLVAR: |
221 | 176 code_rlvar(e2,USE_CREG); |
94 | 177 return INT; |
61 | 178 case CRLVAR: |
221 | 179 code_crlvar(e2,USE_CREG,1,1); |
94 | 180 return CHAR; |
162 | 181 case CURLVAR: |
221 | 182 code_crlvar(e2,USE_CREG,0,1); |
165 | 183 return UCHAR; |
184 case SRLVAR: | |
221 | 185 code_crlvar(e2,USE_CREG,1,size_of_short); |
165 | 186 return CHAR; |
187 case SURLVAR: | |
221 | 188 code_crlvar(e2,USE_CREG,0,size_of_short); |
162 | 189 return UCHAR; |
195 | 190 #if FLOAT_CODE |
81 | 191 case FRLVAR: |
221 | 192 code_drlvar(e2,0,USE_CREG); |
94 | 193 return FLOAT; |
81 | 194 case FRGVAR: |
221 | 195 code_drgvar(e1,0,USE_CREG); |
94 | 196 return FLOAT; |
81 | 197 case DRLVAR: |
221 | 198 code_drlvar(e2,1,USE_CREG); |
94 | 199 return DOUBLE; |
81 | 200 case DRGVAR: |
221 | 201 code_drgvar(e1,1,USE_CREG); |
94 | 202 return DOUBLE; |
195 | 203 #endif |
202 | 204 #if LONGLONG_CODE |
205 case LRLVAR: | |
221 | 206 code_lrlvar(e2,USE_CREG); |
202 | 207 return LONGLONG; |
208 case LRGVAR: | |
221 | 209 code_lrgvar(e1,USE_CREG); |
202 | 210 return LONGLONG; |
211 case LURLVAR: | |
221 | 212 code_lrlvar(e2,USE_CREG); |
202 | 213 return ULONGLONG; |
214 case LURGVAR: | |
221 | 215 code_lrgvar(e1,USE_CREG); |
202 | 216 return ULONGLONG; |
217 #endif | |
61 | 218 case FNAME: |
221 | 219 code_fname((NMTBL *)(e2),USE_CREG); |
94 | 220 return ADDRESS; |
61 | 221 case CONST: /* ÂåÆþ¤¹¤ëÃͤ¬0¤Ç¤âÆÃÊ̤ʽèÍý¤Ï¤·¤Ê¤¤ */ |
221 | 222 code_const(e2,USE_CREG); |
94 | 223 return INT; |
195 | 224 #if FLOAT_CODE |
81 | 225 case DCONST: |
221 | 226 code_dconst(e1,USE_CREG,1); |
94 | 227 return DOUBLE; |
133 | 228 case FCONST: |
221 | 229 code_dconst(e1,USE_CREG,0); |
133 | 230 return FLOAT; |
195 | 231 #endif |
206 | 232 #if LONGLONG_CODE |
202 | 233 case LCONST: |
221 | 234 code_lconst(e1,USE_CREG); |
202 | 235 return LONGLONG; |
236 #endif | |
61 | 237 case STRING: |
221 | 238 code_string(e1,USE_CREG); |
94 | 239 return ADDRESS; |
61 | 240 case FUNCTION: |
94 | 241 t = function(e1); |
242 return t; | |
61 | 243 case CODE: |
244 jump(e2,caddr(e1)); | |
94 | 245 return VOID; |
61 | 246 case INDIRECT: |
94 | 247 return g_expr0(e2); |
196 | 248 case RINDIRECT: |
245 | 249 return code_rindirect(e2,USE_CREG,caddr(e1),1); |
196 | 250 case URINDIRECT: |
245 | 251 return code_rindirect(e2,USE_CREG,caddr(e1),0); |
196 | 252 case CRINDIRECT: |
245 | 253 return code_crindirect(e2,USE_CREG,caddr(e1),1); |
196 | 254 case CURINDIRECT: |
245 | 255 return code_crindirect(e2,USE_CREG,caddr(e1),0); |
196 | 256 case SRINDIRECT: |
245 | 257 return code_srindirect(e2,USE_CREG,caddr(e1),1); |
258 case SURINDIRECT: | |
221 | 259 return code_srindirect(e2,USE_CREG,caddr(e1),0); |
195 | 260 #if FLOAT_CODE |
197 | 261 case FRINDIRECT: |
221 | 262 return code_drindirect(e2,USE_CREG,caddr(e1),0); |
196 | 263 case DRINDIRECT: |
221 | 264 return code_drindirect(e2,USE_CREG,caddr(e1),1); |
195 | 265 #endif |
196 | 266 #if LONGLONG_CODE |
267 case LRINDIRECT: | |
221 | 268 return code_lrindirect(e2,USE_CREG,caddr(e1),0); |
196 | 269 case LURINDIRECT: |
221 | 270 return code_lrindirect(e2,USE_CREG,caddr(e1),1); |
196 | 271 #endif |
61 | 272 case ADDRESS: |
138 | 273 if (car(e2)==REGISTER||car(e2)==DREGISTER||car(e2)==FREGISTER) |
274 return register_to_lvar(e2); /* too late? */ | |
105 | 275 else |
276 return g_expr0(e2); | |
61 | 277 case MINUS: /* ¥ì¥¸¥¹¥¿¤ËÂФ·¡¢negl¤ò¼Â¹Ô¤¹¤ì¤Ð¼Â¸½²Äǽ */ |
221 | 278 g_expr0(e2); code_neg(USE_CREG); |
94 | 279 return INT; |
212 | 280 #if LONGLONG_CODE |
281 case LMINUS: | |
221 | 282 g_expr0(e2); code_lneg(USE_CREG); |
212 | 283 return LONGLONG; |
284 #endif | |
195 | 285 #if FLOAT_CODE |
81 | 286 case DMINUS: |
221 | 287 g_expr0(e2); code_dneg(USE_CREG,1); |
94 | 288 return DOUBLE; |
133 | 289 case FMINUS: |
221 | 290 g_expr0(e2); code_dneg(USE_CREG,0); |
133 | 291 return FLOAT; |
195 | 292 #endif |
108 | 293 case CONV: |
294 g_expr0(e2); | |
295 switch(caddr(e1)) { | |
195 | 296 #if FLOAT_CODE |
221 | 297 case I2D: code_i2d(USE_CREG); return DOUBLE; |
298 case D2I: code_d2i(USE_CREG); return INT; | |
299 case U2D: code_u2d(USE_CREG); return DOUBLE; | |
300 case F2U: code_f2u(USE_CREG); return UNSIGNED; | |
301 case I2F: code_i2f(USE_CREG); return FLOAT; | |
302 case F2I: code_f2i(USE_CREG); return INT; | |
303 case U2F: code_u2f(USE_CREG); return FLOAT; | |
304 case D2U: code_d2u(USE_CREG); return UNSIGNED; | |
305 case D2F: code_d2f(USE_CREG); return FLOAT; | |
306 case F2D: code_f2d(USE_CREG); return DOUBLE; | |
195 | 307 #endif |
308 #if LONGLONG_CODE | |
221 | 309 case I2LL: code_i2ll(USE_CREG); return LONGLONG; |
310 case I2ULL: code_i2ull(USE_CREG); return ULONGLONG; | |
311 case U2LL: code_u2ll(USE_CREG); return LONGLONG; | |
312 case U2ULL: code_u2ull(USE_CREG); return ULONGLONG; | |
313 case LL2I: code_ll2i(USE_CREG); return INT; | |
314 case LL2U: code_ll2u(USE_CREG); return UNSIGNED; | |
315 case ULL2I: code_ull2i(USE_CREG); return INT; | |
316 case ULL2U: code_ull2u(USE_CREG); return UNSIGNED; | |
195 | 317 #if FLOAT_CODE |
221 | 318 case D2LL: code_d2ll(USE_CREG); return LONGLONG; |
319 case D2ULL: code_d2ull(USE_CREG); return ULONGLONG; | |
320 case F2LL: code_f2ll(USE_CREG); return LONGLONG; | |
321 case F2ULL: code_f2ull(USE_CREG); return ULONGLONG; | |
322 case LL2D: code_ll2d(USE_CREG); return DOUBLE; | |
323 case LL2F: code_ll2f(USE_CREG); return FLOAT; | |
324 case ULL2D: code_ull2d(USE_CREG); return DOUBLE; | |
325 case ULL2F: code_ull2f(USE_CREG); return FLOAT; | |
195 | 326 #endif |
327 #endif | |
328 | |
108 | 329 default: |
330 error(-1); return INT; | |
331 } | |
61 | 332 case BNOT: /* ~ */ |
221 | 333 g_expr0(e2); code_not(USE_CREG); |
94 | 334 return INT; |
61 | 335 case LNOT: /* ! */ |
221 | 336 g_expr0(e2); code_lnot(USE_CREG); |
94 | 337 return INT; |
61 | 338 case PREINC: |
221 | 339 code_preinc(e1,e2,caddr(e1),1,cadddr(e1),USE_CREG); |
168 | 340 return INT; |
341 case UPREINC: | |
221 | 342 code_preinc(e1,e2,caddr(e1),0,cadddr(e1),USE_CREG); |
94 | 343 return INT; |
61 | 344 case POSTINC: |
221 | 345 code_postinc(e1,e2,caddr(e1),1,cadddr(e1),USE_CREG); |
168 | 346 return INT; |
347 case UPOSTINC: | |
221 | 348 code_postinc(e1,e2,caddr(e1),0,cadddr(e1),USE_CREG); |
94 | 349 return INT; |
195 | 350 #if FLOAT_CODE |
147 | 351 case DPREINC: /* ++d */ |
221 | 352 code_dpreinc(e1,e2,1,USE_CREG); |
94 | 353 return DOUBLE; |
147 | 354 case DPOSTINC: /* d++ */ |
221 | 355 code_dpostinc(e1,e2,1,USE_CREG); |
94 | 356 return DOUBLE; |
147 | 357 case FPREINC: /* ++f */ |
221 | 358 code_dpreinc(e1,e2,0,USE_CREG); |
94 | 359 return FLOAT; |
147 | 360 case FPOSTINC: /* f++ */ |
221 | 361 code_dpostinc(e1,e2,0,USE_CREG); |
94 | 362 return FLOAT; |
195 | 363 #endif |
364 #if LONGLONG_CODE | |
365 case LPREINC: /* ++d */ | |
221 | 366 code_lpreinc(e1,e2,USE_CREG); |
219 | 367 return LONGLONG; |
195 | 368 case LPOSTINC: /* d++ */ |
221 | 369 code_lpostinc(e1,e2,USE_CREG); |
219 | 370 return LONGLONG; |
371 case LUPREINC: /* ++d */ | |
221 | 372 code_lpreinc(e1,e2,USE_CREG); |
219 | 373 return ULONGLONG; |
374 case LUPOSTINC: /* d++ */ | |
221 | 375 code_lpostinc(e1,e2,USE_CREG); |
219 | 376 return ULONGLONG; |
195 | 377 #endif |
61 | 378 case MUL: case UMUL: |
379 case DIV: case UDIV: | |
380 case MOD: case UMOD: | |
381 case LSHIFT: case ULSHIFT: case RSHIFT: case URSHIFT: | |
246 | 382 case ADD: case SUB: case BAND: case EOR: case BOR: case CMP: case CMPGE: |
278 | 383 case UCMP: case CMPEQ: case CMPNEQ: case UCMPGE: |
61 | 384 machinop(e1); |
94 | 385 return INT; |
195 | 386 #if FLOAT_CODE |
81 | 387 case DMUL: case DDIV: |
388 case DADD: case DSUB: | |
250 | 389 case DCMP: case DCMPGE: case DCMPEQ: case DCMPNEQ: |
133 | 390 dmachinop(e1,1); |
94 | 391 return DOUBLE; |
133 | 392 case FMUL: case FDIV: |
393 case FADD: case FSUB: | |
250 | 394 case FCMP: case FCMPGE: case FCMPEQ: case FCMPNEQ: |
133 | 395 dmachinop(e1,0); |
396 return FLOAT; | |
195 | 397 #endif |
398 #if LONGLONG_CODE | |
399 case LMUL: case LUMUL: | |
400 case LDIV: case LUDIV: | |
401 case LMOD: case LUMOD: | |
402 case LLSHIFT: case LULSHIFT: case LRSHIFT: case LURSHIFT: | |
403 case LADD: case LSUB: case LBAND: case LEOR: case LBOR: case LCMP: | |
404 lmachinop(e1); | |
405 return INT; | |
406 #endif | |
222 | 407 case LCOND: |
408 case DCOND: | |
409 case FCOND: | |
195 | 410 case COND: /* a?0:1 should consider non-brach instruction */ |
411 d = (car(e1)==LCOND?LONGLONG: | |
412 car(e1)==COND?INT:car(e1)==DCOND?DOUBLE:FLOAT); | |
108 | 413 e2=fwdlabel(); |
414 b_expr(cadr(e1),0,e2,0); | |
187 | 415 g_expr0(caddr(e1)); |
221 | 416 t = code_get_fixed_creg(USE_CREG,d); |
108 | 417 jmp(e3=fwdlabel()); |
418 fwddef(e2); | |
191 | 419 t1=g_expr0(cadddr(e1)); |
187 | 420 code_set_fixed_creg(t,1,d); |
61 | 421 fwddef(e3); |
191 | 422 return t1; |
164 | 423 case STASS: |
61 | 424 sassign(e1); |
94 | 425 return RSTRUCT; |
165 | 426 case ASS: case CASS: case SASS: |
61 | 427 assign(e1); |
94 | 428 return INT; |
162 | 429 case ASSOP: case CASSOP: case CUASSOP: |
327 | 430 iassop(e1); |
94 | 431 return INT; |
195 | 432 #if FLOAT_CODE |
433 case FASS: case DASS: | |
434 dassign(e1); | |
435 return DOUBLE; | |
81 | 436 case DASSOP: case FASSOP: |
437 dassop(e1); | |
94 | 438 return DOUBLE; |
195 | 439 #endif |
440 #if LONGLONG_CODE | |
441 case LASS: | |
442 lassign(e1); | |
443 return LONGLONG; | |
444 case LASSOP: case LUASSOP: | |
445 lassop(e1); | |
446 return LONGLONG ; | |
447 #endif | |
61 | 448 case RSTRUCT: |
83 | 449 g_expr0(e2); |
94 | 450 return RSTRUCT; |
313 | 451 case ALLOCA: |
452 code_alloca(e2,USE_CREG); | |
453 return list2(POINTER,CHAR); | |
61 | 454 case COMMA: |
83 | 455 g_expr_u(e2); |
94 | 456 return g_expr0(caddr(e1)); |
61 | 457 case RETURN: |
458 n = (NMTBL *)e2; | |
459 if (retcont==0) | |
460 retcont=fwdlabel(); | |
221 | 461 code_return(USE_CREG); |
94 | 462 return VOID; |
61 | 463 case ENVIRONMENT: |
221 | 464 code_environment(USE_CREG); |
94 | 465 return ADDRESS; |
329 | 466 #if BIT_FIELD_CODE |
467 case RBIT_FIELD: | |
468 return bit_field(e2,caddr(e1) /* type */); | |
469 case BASS: | |
470 return bassign(e2,caddr(e1),cadr(cadddr(e1))/* type */); | |
471 case BASSOP: | |
472 return bassop(e2,caddr(e1),car(cadddr(e1)),/* op */ | |
473 cadr(cadddr(e1))/* type */); | |
474 case BFD_REPL: | |
475 return bit_field_repl(e2,caddr(e1),cadddr(e1) /* type */); | |
476 #endif | |
316 | 477 #if ASM_CODE |
478 case ASM: | |
327 | 479 gen_asm(car(e2),cadr(e2),caddr(e2),cadddr(e2),caddr(e1)); |
316 | 480 /* asm in (str) out (str) opt(str) expr */ |
481 return VOID; | |
482 #endif | |
61 | 483 default: |
221 | 484 code_bool(e1,USE_CREG); /* type? */ |
94 | 485 return INT; |
61 | 486 } |
487 } | |
488 | |
94 | 489 #define dual_ops(op) \ |
490 (op==GT|| op==UGT|| op==GE|| op==UGE|| op==LT|| \ | |
491 op==ULT|| op==LE|| op==ULE|| \ | |
492 op==DOP+GT|| op==DOP+GE|| op==DOP+LT|| op==DOP+LE || \ | |
135 | 493 op==FOP+GT|| op==FOP+GE|| op==FOP+LT|| op==FOP+LE || \ |
494 op==FOP+EQ|| op==FOP+NEQ || \ | |
495 op==EQ|| op==NEQ|| op==DOP+EQ|| op==DOP+NEQ) | |
94 | 496 |
327 | 497 static int |
94 | 498 rop_dual(op) |
499 { | |
232 | 500 // x op y => y dual(op) x |
195 | 501 switch(op) { |
502 case GT: return LT; | |
503 case UGT: return ULT; | |
504 case GE: return LE; | |
505 case UGE: return ULE; | |
506 case LT: return GT; | |
507 case ULT: return UGT; | |
508 case LE: return GE; | |
509 case ULE: return UGE; | |
510 case DOP+GT: return DOP+LT; | |
511 case DOP+GE: return DOP+LE; | |
512 case DOP+LT: return DOP+GT; | |
513 case DOP+LE: return DOP+GE; | |
514 case FOP+GT: return FOP+LT; | |
515 case FOP+GE: return FOP+LE; | |
516 case FOP+LT: return FOP+GT; | |
517 case FOP+LE: return FOP+GE; | |
518 | |
519 case LOP+GT: return LOP+LT; | |
520 case LOP+GE: return LOP+LE; | |
521 case LOP+LT: return LOP+GT; | |
522 case LOP+LE: return LOP+GE; | |
523 case LOP+UGT: return FOP+ULT; | |
524 case LOP+UGE: return FOP+ULE; | |
525 case LOP+ULT: return FOP+UGT; | |
526 case LOP+ULE: return FOP+UGE; | |
527 } | |
94 | 528 return op; |
529 } | |
530 | |
327 | 531 /* bexpr for value unused */ |
532 | |
533 extern void | |
289 | 534 bexpr_u(int e1, char cond, int l1) |
61 | 535 { |
94 | 536 int op = car(e1); |
66 | 537 if (chk) return; |
292 | 538 // gexpr_init(); |
94 | 539 if (dual_ops(op) && (car(caddr(e1))==CONST||(car(caddr(e1))==DCONST))) |
540 b_expr(list3(rop_dual(op),caddr(e1),cadr(e1)),cond,l1,0); | |
541 else | |
542 b_expr(e1,cond,l1,0); | |
61 | 543 } |
544 | |
327 | 545 /* bexpr for value used */ |
546 | |
547 extern void | |
289 | 548 bexpr(int e1, char cond, int l1) |
549 { | |
550 int uses = use; use=1; | |
551 bexpr_u(e1, cond, l1); | |
552 use = uses; | |
553 } | |
554 | |
327 | 555 /* branch expression generator */ |
556 /* if (cond?e1:!e1) goto l1 */ | |
557 /* 1 or 0 is return for code_bool */ | |
558 | |
559 extern void | |
61 | 560 b_expr(int e1, char cond, int l1,int err) |
561 { | |
94 | 562 int e2,l2,t; |
132 | 563 if (!control) return; |
127 | 564 l2 = 0; |
61 | 565 e2=cadr(e1); |
566 switch(car(e1)) { | |
567 case LNOT: | |
568 b_expr(e2,!cond,l1,0); | |
569 return; | |
280 | 570 case GT: case GE: case LT: case LE: |
571 case EQ: case NEQ: | |
572 rexpr(e1,l1,cond,INT); | |
61 | 573 return; |
280 | 574 case UGT: case UGE: case ULT: case ULE: |
575 rexpr(e1,l1,cond,UNSIGNED); | |
61 | 576 return; |
195 | 577 #if FLOAT_CODE |
82 | 578 case DOP+GT: |
194 | 579 case DOP+GE: |
580 case DOP+EQ: | |
581 case DOP+NEQ: | |
582 case FOP+GT: | |
583 case FOP+GE: | |
584 case FOP+EQ: | |
585 case FOP+NEQ: | |
229 | 586 drexpr(cadr(e1),caddr(e1),l1,car(e1),cond); |
82 | 587 return; |
194 | 588 case FOP+LT: |
231 | 589 case FOP+LE: |
82 | 590 case DOP+LT: |
591 case DOP+LE: | |
232 | 592 drexpr(caddr(e1),cadr(e1),l1,rop_dual(car(e1)),cond); |
82 | 593 return; |
195 | 594 #endif |
595 #if LONGLONG_CODE | |
596 case LOP+GT: | |
597 case LOP+GE: | |
598 case LOP+EQ: | |
599 case LOP+NEQ: | |
210 | 600 case LOP+UGT: |
601 case LOP+UGE: | |
231 | 602 lrexpr(cadr(e1),caddr(e1),l1,car(e1),cond); |
210 | 603 return; |
232 | 604 case LOP+LT: |
605 case LOP+LE: | |
210 | 606 case LOP+ULT: |
607 case LOP+ULE: | |
232 | 608 lrexpr(caddr(e1),cadr(e1),l1,rop_dual(car(e1)),cond); |
210 | 609 return; |
195 | 610 #endif |
61 | 611 case LAND: |
289 | 612 bexpr(e2,0,cond?(l2=fwdlabel()):l1); |
613 bexpr_u(caddr(e1),cond,l1); | |
61 | 614 if(cond) fwddef(l2); |
615 return; | |
616 case LOR: | |
289 | 617 bexpr(e2,1,cond?l1:(l2=fwdlabel())); |
618 bexpr_u(caddr(e1),cond,l1); | |
61 | 619 if(!cond) fwddef(l2); |
620 return; | |
167 | 621 case CRGVAR: case CURGVAR: |
287 | 622 code_cmp_crgvar(e1,USE_CREG,1,l1,cond); |
61 | 623 return; |
167 | 624 case SRGVAR: case SURGVAR: |
287 | 625 code_cmp_crgvar(e1,USE_CREG,size_of_short,l1,cond); |
167 | 626 return; |
627 case CRLVAR: case CURLVAR: | |
287 | 628 code_cmp_crlvar(e2,USE_CREG,1,l1,cond); |
167 | 629 return; |
630 case SRLVAR: case SURLVAR: | |
287 | 631 code_cmp_crlvar(e2,USE_CREG,size_of_short,l1,cond); |
61 | 632 return; |
633 case RGVAR: | |
287 | 634 code_cmp_rgvar(e1,USE_CREG,l1,cond); |
61 | 635 return; |
636 case RLVAR: | |
287 | 637 code_cmp_rlvar(e2,USE_CREG,l1,cond); |
61 | 638 return; |
195 | 639 #if FLOATC_DOE |
81 | 640 case DRLVAR: |
287 | 641 code_cmp_drlvar(e2,USE_CREG,1,l1,cond); |
138 | 642 return; |
643 case FRLVAR: | |
287 | 644 code_cmp_drlvar(e2,USE_CREG,0,l1,cond); |
81 | 645 return; |
646 case DRGVAR: | |
287 | 647 code_cmp_drgvar(e2,USE_CREG,1,l1,cond); |
138 | 648 return; |
649 case FRGVAR: | |
287 | 650 code_cmp_drgvar(e2,USE_CREG,0,l1,cond); |
81 | 651 return; |
138 | 652 case FREGISTER: |
287 | 653 code_cmp_dregister(e2,0,l1,cond); |
138 | 654 return; |
94 | 655 case DREGISTER: |
287 | 656 code_cmp_dregister(e2,1,l1,cond); |
94 | 657 return; |
81 | 658 case DCONST: |
138 | 659 case FCONST: |
132 | 660 if(control&&((dcadr(e2)!=0.0)^cond)) jmp(l1); |
81 | 661 return; |
195 | 662 #endif |
663 #if LONGLONG_DOE | |
664 case LRLVAR: | |
287 | 665 code_cmp_lrlvar(e2,1,l1,cond); |
195 | 666 return; |
667 case LRGVAR: | |
287 | 668 code_cmp_lrgvar(e2,1,l1,cond); |
195 | 669 return; |
670 case LREGISTER: | |
287 | 671 code_cmp_lregister(e2,1,l1,cond); |
195 | 672 return; |
673 case LCONST: | |
674 if(control&&((lcadr(e2)!=0)^cond)) jmp(l1); | |
675 return; | |
676 #endif | |
677 case REGISTER: | |
287 | 678 code_cmp_register(e2,l1,cond); |
195 | 679 return; |
680 case CONST: | |
681 if(control&&((cond&&e2)||(!cond&&!e2))) jmp(l1); | |
682 return; | |
61 | 683 default: |
684 if(err) { | |
81 | 685 error(-1); return; /* recursive g_expr/b_expr */ |
94 | 686 } |
687 t=g_expr(e1); | |
289 | 688 if (!use) return; |
195 | 689 if (0) ; |
690 #if FLOAT_CODE | |
691 else if(t==FLOAT) | |
287 | 692 code_cmp_dregister(USE_CREG,0,l1,cond); |
138 | 693 else if(t==DOUBLE) |
287 | 694 code_cmp_dregister(USE_CREG,1,l1,cond); |
195 | 695 #endif |
696 #if LONGLONG_CODE | |
697 else if(t==LONGLONG||t==ULONGLONG) | |
287 | 698 code_cmp_lregister(USE_CREG,l1,cond); |
195 | 699 #endif |
94 | 700 else |
287 | 701 code_cmp_register(USE_CREG,l1,cond); |
61 | 702 return; |
703 } | |
704 } | |
705 | |
327 | 706 extern int |
126 | 707 is_code(NMTBL *fnptr) |
708 { | |
709 int type = fnptr->ty; | |
710 return type==CODE|| (type>0 && car(type)==CODE); | |
711 } | |
712 | |
327 | 713 extern int |
126 | 714 is_function(NMTBL *fnptr) |
715 { | |
716 int type = fnptr->ty; | |
717 return type==FUNCTION || (type>0 && car(type)==FUNCTION); | |
718 } | |
719 | |
327 | 720 extern int |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
721 function_type(int e1,int *dots) |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
722 { |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
723 int ret_type,t; |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
724 ret_type = cadr(e1); |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
725 if (ret_type==CHAR) ret_type=INT; |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
726 |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
727 /* check argments type is DOTS? */ |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
728 t = caddr(e1); |
313 | 729 if (/* t==0 || */ t==DOTS) *dots = 1; |
305
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
730 else { |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
731 *dots = 0; |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
732 for(;t;t = cadr(t)) { |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
733 if (car(t)==DOTS) *dots = 1; |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
734 } |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
735 } |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
736 |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
737 return ret_type; |
117baacd1ed0
stdarg powerpc passed except long long (macro problem)
kono
parents:
297
diff
changeset
|
738 } |
61 | 739 |
105 | 740 static int |
741 register_to_lvar(int e) | |
742 { | |
743 error(REG_ERR); | |
744 return 0; | |
745 #if 0 | |
746 ÅÓÃæ¤Ç¥ì¥¸¥¹¥¿¤«¤éLVAR¤ËÊѹ¹¤·¤Æ¤â¡¢´Ö¤Ë¹ç¤ï¤Ê¤¤¡£ | |
747 | |
748 NMTBL *n = (NMTBL*)caddr(e); | |
749 int reg = cadr(e); | |
750 int tag = car(e); | |
751 int lvar; | |
752 int t; | |
753 if (!n||n==&null_nptr) error(REG_ERR); | |
754 if (tag==REGISTER) { | |
755 n->dsp = new_lvar(size_of_int); | |
756 t = INT; | |
757 } else if (tag==DREGISTER) { | |
758 n->dsp = new_lvar(size_of_double); | |
759 t = DOUBLE; | |
138 | 760 } else if (tag==FREGISTER) { |
761 n->dsp = new_lvar(size_of_float); | |
762 t = DOUBLE; | |
195 | 763 } else if (tag==LREGISTER) { |
764 n->dsp = new_lvar(size_of_longlong); | |
765 t = LONGLONG; | |
105 | 766 } else error(-1); |
767 n->sc = LVAR; | |
768 lvar = list2(LVAR,n->dsp); | |
769 g_expr_u(assign_expr0(list2(LVAR,n->dsp),list3(tag,reg,(int)n),t,t)); | |
195 | 770 if (tag==REGISTER||tag==DREGISTER||tag==FREGISTER||tag==LREGISTER) { |
105 | 771 free_register(reg); |
772 return g_expr0(lvar); | |
773 #endif | |
774 } | |
775 | |
277 | 776 // parallel assignment of registers. |
777 // | |
778 // target = list3(target_regnum,next,source_regnum); | |
779 | |
327 | 780 extern void |
277 | 781 parallel_rassign(int assigns) |
782 { | |
783 int free,tmp,tmp_target,remains,t0,t2,src; | |
784 tmp = 0; | |
785 for(;;) { | |
786 remains = 0; | |
787 // find free target | |
788 for(free=assigns;free;free=cadr(free)) { | |
789 if (!caddr(free)) continue; // already done | |
790 remains++; | |
791 t0 = car(free); // target register | |
792 // check target is free | |
793 for(src=assigns;src;src=cadr(src)) { | |
794 if ((t2=caddr(src)) && t0==t2) break; // target is in source | |
795 } | |
796 if (src==0) { | |
797 break; // free is a free target | |
798 } | |
799 } | |
800 if (remains==0) { | |
801 if (tmp) { | |
802 code_rlvar(tmp,tmp_target); | |
803 } | |
804 return; | |
805 } | |
806 if (free) { // free target | |
807 if (t0!=caddr(free)) | |
808 code_assign_register(t0,0,caddr(free)); | |
809 } else { // no free target | |
810 for(free=assigns;free;free=cadr(free)) { | |
811 if (caddr(free)) break; // not yet done | |
812 } | |
813 if (!free) error(-1); | |
814 tmp = new_lvar(size_of_int); | |
815 tmp_target = car(free); | |
816 code_assign_lvar(tmp,caddr(free),0); | |
817 } | |
818 caddr(free)=0; // mark it done | |
819 } | |
820 } | |
821 | |
61 | 822 /* goto arguments list */ |
823 /* target list4(list2(tag,disp),cdr,ty,source_expr) */ | |
824 /* source expr=listn(tag,...) */ | |
825 /* source (after) list2(tag,disp) */ | |
826 /* source list list3(e,cdr,sz) */ | |
827 | |
284 | 828 #define DEBUG_PARALLEL_ASSIGN 0 |
61 | 829 |
327 | 830 static int |
61 | 831 overrap(int t,int sz,int source) |
832 { | |
833 int s,s0,s1; | |
834 int t0=cadr(t); | |
835 int t1=t0+sz; | |
836 for(;source;source=cadr(source)) { | |
837 s=car(source); s0=cadr(s); | |
838 if(car(s)==REGISTER && car(t)==REGISTER) { | |
839 if(s0==t0) return s; | |
840 } else if (is_same_type(s,t)) { | |
841 s1=s0+caddr(source); | |
842 #if DEBUG_PARALLEL_ASSIGN>1 | |
843 printf("# ovedrrap source %d t0 %d t1 %d\n",car(car(t)),t0,t1); | |
844 printf("# ovedrrap target %d s0 %d s1 %d\n",car(car(source)),s0,s1); | |
845 printf("# ovedrrap equal = %d\n",((t0<=s0&&s0<t1)||(t0<s1&&s1<=t1))); | |
846 #endif | |
847 if((t0<=s0&&s0<t1)||(t0<s1&&s1<=t1)) return s; | |
848 } | |
849 } | |
850 return 0; | |
851 } | |
852 | |
327 | 853 static void |
61 | 854 remove_target(int *target,int t,int *use) |
855 { | |
856 int use0=*use; | |
147 | 857 int reg; |
61 | 858 while(use0) { |
859 if (car(use0)==t) { | |
147 | 860 reg = car(caddr(use0)); |
861 if (reg==REGISTER||reg==FREGISTER||reg==DREGISTER) | |
99 | 862 free_register(cadr(caddr(use0))); |
61 | 863 break; |
864 } | |
865 use0 = cadr(use0); | |
866 } | |
867 remove0(target,t); | |
868 } | |
869 | |
327 | 870 static void |
61 | 871 save_target(int t,int s,int *target,int *use,int sz,int ty) |
872 { | |
873 int e1; | |
874 /*¿·¤·¤¤¥ì¥¸¥¹¥¿(or ¥¹¥¿¥Ã¥¯)¤ò¼èÆÀ¤¹¤ë*/ | |
875 if (sz==size_of_int && (e1=get_register())!=-1) { | |
105 | 876 e1=list3(REGISTER,e1,0); |
61 | 877 *use=list3(t,*use,e1); |
99 | 878 g_expr_u(assign_expr0(e1,s,ty,ty)); |
879 *target = append4(*target,t,ty,e1); | |
195 | 880 #if FLOAT_CODE |
138 | 881 } else if (sz==size_of_double && (e1=get_dregister(1))!=-1) { |
105 | 882 e1=list3(DREGISTER,e1,0); |
99 | 883 *use=list3(t,*use,e1); |
83 | 884 g_expr_u(assign_expr0(e1,s,ty,ty)); |
61 | 885 *target = append4(*target,t,ty,e1); |
138 | 886 } else if (sz==size_of_float && (e1=get_dregister(0))!=-1) { |
887 e1=list3(FREGISTER,e1,0); | |
888 *use=list3(t,*use,e1); | |
889 g_expr_u(assign_expr0(e1,s,ty,ty)); | |
890 *target = append4(*target,t,ty,e1); | |
195 | 891 #endif |
205 | 892 #if LONGLONG_CODE |
893 } else if (sz==size_of_longlong && (e1=get_lregister())!=-1) { | |
894 e1=list3(LREGISTER,e1,0); | |
895 *use=list3(t,*use,e1); | |
896 g_expr_u(assign_expr0(e1,s,ty,ty)); | |
897 *target = append4(*target,t,ty,e1); | |
898 #endif | |
61 | 899 } else { |
94 | 900 g_expr_u(assign_expr0((e1=list2(LVAR,new_lvar(sz))),s,ty,ty)); |
61 | 901 *target = append4(*target,t,ty,e1); |
117 | 902 *use=list3(t,*use,e1); |
61 | 903 } |
904 } | |
905 | |
327 | 906 static int |
61 | 907 circular_dependency(int t,int s,int *target,int *source) |
908 { | |
909 int target0=*target; | |
910 int t1,sz,ty,s1; | |
911 while(target0) { | |
912 if (cadddr(target0)==s) { | |
913 t1=car(target0); | |
914 s=cadddr(target0); | |
915 sz=size(ty=caddr(target0)); | |
916 if(t==t1) { | |
917 #if DEBUG_PARALLEL_ASSIGN | |
918 printf("# circular dependency %d ty %d+%d sz %d\n",car(t1),ty,cadr(t1),sz); | |
919 #endif | |
920 return 1; | |
921 } | |
922 if ((s1=overrap(t1,sz,*source))) { | |
923 /* another overrap start over */ | |
924 return circular_dependency(t,s1,target,source); | |
925 } | |
926 } | |
927 target0=cadr(target0); | |
928 } | |
929 return 0; | |
930 } | |
931 | |
327 | 932 static void |
61 | 933 parallel_assign(int *target,int *source,int *processing,int *use) |
934 { | |
935 int t,s,sz,ty,target0,s1; | |
936 while(*target) { | |
937 target0=*target; | |
938 while(target0) { | |
939 t=car(target0); s=cadddr(target0); | |
940 sz=size(ty=caddr(target0)); | |
941 if(car(t)==car(s) && cadr(t)==cadr(s)) { | |
942 /*½ñ¤¹þ¤ßÀ褬¼«Ê¬¼«¿È*/ | |
943 #if DEBUG_PARALLEL_ASSIGN | |
944 printf("# remove same %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz); | |
945 #endif | |
946 remove_target(target,t,use); | |
947 /* Ç˲õ¤µ¤ì¤Æ¤Ïº¤¤ë¤Î¤Ç¡¢source list¤«¤é¤Ï½ü¤«¤Ê¤¤ */ | |
948 } else if (!(s1=overrap(t,sz,*source))) { | |
949 /* ½Å¤Ê¤Ã¤Æ¤Ê¤¤¤Î¤Ç°Â¿´¤·¤Æ½ñ¤¹þ¤á¤ë */ | |
950 #if DEBUG_PARALLEL_ASSIGN | |
951 printf("# normal assign %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz); | |
952 #endif | |
83 | 953 g_expr_u(assign_expr0(t,s,ty,ty)); |
61 | 954 remove_target(target,t,use); remove0(source,s); |
955 } else { | |
956 if(circular_dependency(t,s1,target,source)) { | |
957 #if DEBUG_PARALLEL_ASSIGN | |
958 printf("# saving %d ty %d+%d sz %d\n",car(t),ty,cadr(t),sz); | |
959 #endif | |
960 remove_target(target,t,use); remove0(source,s); | |
961 save_target(t,s,target,use,sz,ty); | |
962 } | |
963 } | |
964 target0=cadr(target0); | |
965 } | |
966 } | |
967 } | |
968 | |
327 | 969 static void |
61 | 970 remove0(int *parent,int e) |
971 { | |
972 int list; | |
973 while ((list=*parent)) { | |
974 if (car(list)==e) { | |
975 *parent= cadr(list); return; | |
976 } else { | |
977 parent=&cadr(list); | |
978 } | |
979 } | |
980 } | |
981 | |
105 | 982 /* |
327 | 983 static void |
61 | 984 remove0_all(int *parent,int e) |
985 { | |
986 int list; | |
987 while ((list=*parent)) { | |
988 if (car(list)==e) { | |
989 *parent= cadr(list); | |
990 } else { | |
991 parent=&cadr(list); | |
992 } | |
993 } | |
994 } | |
105 | 995 */ |
61 | 996 |
327 | 997 static int |
61 | 998 is_simple(int e1) |
999 { | |
1000 return ( | |
99 | 1001 e1==CONST || e1==FNAME || e1==LVAR || e1==REGISTER ||e1==DREGISTER || |
195 | 1002 e1==FREGISTER || e1==LREGISTER || |
81 | 1003 e1==GVAR || e1==RGVAR || e1==RLVAR || e1==CRLVAR || e1==CRGVAR || |
195 | 1004 e1==DRLVAR || e1==FRLVAR || e1==LRLVAR || |
165 | 1005 e1==CURLVAR || e1==SURLVAR || e1==CURGVAR || e1==SURGVAR |
61 | 1006 ); |
1007 } | |
1008 | |
327 | 1009 static int |
61 | 1010 is_same_type(int e1,int e2) |
1011 { | |
1012 int ce1=car(e1); | |
1013 int ce2=car(e2); | |
1014 return ( | |
81 | 1015 (ce1==LVAR && (ce2==RLVAR||ce2==CRLVAR||ce2==FRLVAR||ce2==DRLVAR)) |
165 | 1016 || (ce1==LVAR && (ce2==SRLVAR||ce2==SURLVAR||ce2==CURLVAR)) |
81 | 1017 || (ce2==LVAR && (ce1==RLVAR||ce1==CRLVAR||ce1==FRLVAR||ce1==DRLVAR)) |
165 | 1018 || (ce2==LVAR && (ce1==SRLVAR||ce1==SURLVAR||ce1==CURLVAR)) |
195 | 1019 || (ce2==LVAR && (ce1==LRLVAR)) |
81 | 1020 || (ce1==GVAR && (ce2==RGVAR||ce2==CRGVAR||ce2==FRGVAR||ce2==DRGVAR)) |
165 | 1021 || (ce1==GVAR && (ce2==SRGVAR||ce2==SURGVAR||ce2==CURGVAR)) |
81 | 1022 || (ce2==GVAR && (ce1==RGVAR||ce1==CRGVAR||ce1==FRGVAR||ce1==DRGVAR)) |
165 | 1023 || (ce2==GVAR && (ce1==SRGVAR||ce1==SURGVAR||ce1==CURGVAR)) |
195 | 1024 || (ce2==GVAR && (ce1==LRGVAR)) |
61 | 1025 ); |
1026 } | |
1027 | |
327 | 1028 static int |
61 | 1029 is_memory(int e1) |
1030 { | |
1031 int ce1=car(e1); | |
1032 return ( | |
195 | 1033 ce1==LVAR ||ce1==RLVAR||ce1==CRLVAR || ce1==DRLVAR || ce1==LRLVAR || |
1034 ce1==GVAR ||ce1==RGVAR||ce1==CRGVAR || ce1==DRGVAR || ce1==LRGVAR || | |
1035 ce1==FRLVAR || ce1==FRGVAR || | |
165 | 1036 ce1==CURGVAR ||ce1==SURGVAR||ce1==SRGVAR || |
219 | 1037 ce1==REGISTER|| ce1==DREGISTER || ce1==FREGISTER || |
1038 ce1==LREGISTER | |
61 | 1039 ); |
1040 } | |
1041 | |
98 | 1042 |
327 | 1043 static void |
61 | 1044 jump(int e1, int env) |
1045 { | |
99 | 1046 int e2,e3,e4,sz,arg_size,ty,regs,fregs; |
147 | 1047 int t0,s0,r,reg; |
127 | 1048 NMTBL *code0 = 0; |
61 | 1049 int target = 0; |
1050 int source = 0; | |
1051 int processing = 0; | |
1052 int use = 0; | |
1053 | |
1054 /* ¤Þ¤º¡¢¥µ¥¤¥º¤ò·×»»¤·¤Ê¤¬¤é¡¢·è¤Þ¤Ã¤¿·Á¤ËÍ¡£ */ | |
1055 | |
99 | 1056 arg_size = 0; regs = 0; |
1057 fregs = 0; | |
61 | 1058 for (e3 = reverse0(caddr(e1)); e3; e3 = cadr(e3)) { |
1059 e2 = car(e3); sz = size(ty=caddr(e3)); | |
138 | 1060 if (scalar(ty) && (r = get_input_register_var(regs,0,1))) { |
1061 target=list4(r,target,ty,e2); regs++; | |
1062 } else if (ty==FLOAT && (r = get_input_dregister_var(fregs,0,1,0))) { | |
1063 target=list4(r, target,ty,e2); fregs++; | |
1064 } else if (ty==DOUBLE && (r = get_input_dregister_var(fregs,0,1,1))) { | |
1065 target=list4(r, target,ty,e2); fregs++; | |
61 | 1066 } else { |
1067 target=list4(list2(LVAR,0), target,ty,e2); | |
1068 } | |
128 | 1069 /* keep arg space for register variables */ |
1070 arg_size += sz; | |
61 | 1071 #if DEBUG_PARALLEL_ASSIGN |
1072 printf("# target %d ty %d+%d sz %d\n",car(car(target)),ty,cadr(car(target)),sz); | |
1073 #endif | |
1074 } | |
1075 | |
1076 /* disp ¤òÈô¤ÓÀè»÷¹ç¤ï¤»¤Æ½¤Àµ */ | |
98 | 1077 if (is_code(fnptr)) { |
61 | 1078 if (-arg_size<disp) disp = -arg_size; |
1079 } else { | |
1080 if (disp_offset-arg_size<disp) disp = disp_offset-arg_size; | |
1081 } | |
1082 | |
1083 /* Ê£»¨¤Ê¼°¤òÁ°¤â¤Ã¤Æ·×»»¤·¤Æ¤ª¤¯ */ | |
1084 /* ɬÍפʤé¶É½êÊÑ¿ô¤òÍѤ¤¤ë¡£ */ | |
1085 /* ¶É½êÊÑ¿ô¤Ø¤Î¥ª¥Õ¥»¥Ã¥È¤ò³Ð¤¨¤Æ¤ª¤¯ */ | |
1086 | |
1087 for (e2 = target; e2; e2 = cadr(e2)) { | |
1088 t0=car(e2); s0=cadddr(e2); | |
1089 sz=size(ty=caddr(e2)); | |
1090 if(car(t0)==LVAR) { | |
1091 /* ¤³¤³¤Ç¡¢½ñ¹þÀ襢¥É¥ì¥¹¤ò·è¤á¤ë */ | |
1092 cadr(t0)=-arg_size; | |
1093 } | |
128 | 1094 arg_size-=sz; |
61 | 1095 if (!is_simple(car(s0))) { |
94 | 1096 g_expr_u(assign_expr0((e4=list2(LVAR,new_lvar(sz))),s0,ty,ty)); |
117 | 1097 use=list3(ty,use,e1); |
61 | 1098 cadddr(e2)=e4; |
1099 s0=e4; | |
1100 } else if (is_same_type(t0,s0)) { | |
1101 if(cadr(t0)==cadr(s0)) { | |
1102 #if DEBUG_PARALLEL_ASSIGN | |
1103 printf("# remove same memory %d ty %d+%d sz %d\n",car(t0),ty,cadr(t0),sz); | |
1104 #endif | |
269 | 1105 /* we should check size also (but currently useless) */ |
61 | 1106 remove0(&target,t0); |
1107 /* still we have source to avoid overwrite */ | |
1108 } | |
1109 } | |
1110 if(is_memory(s0)) { | |
1111 source=list3(s0,source,sz); | |
1112 #if DEBUG_PARALLEL_ASSIGN | |
1113 printf("# source %d ty %d+%d sz %d\n",car(car(source)),ty,cadr(car(source)),sz); | |
1114 #endif | |
1115 } | |
1116 } | |
1117 | |
1118 /* compute jump address */ | |
1119 e2 = cadr(e1); | |
1120 if (car(e2) == FNAME) { | |
1121 code0=(NMTBL *)cadr(e2); | |
98 | 1122 if (!is_code(code0)) { |
61 | 1123 error(TYERR); return; |
1124 } | |
1125 } else { /* indirect */ | |
1126 g_expr(e2); | |
1127 emit_push(); | |
1128 } | |
1129 if (env) { | |
1130 g_expr(env); | |
1131 emit_push(); | |
1132 } | |
1133 | |
1134 /* ÊÂÎóÂåÆþ¤ò¼Â¹Ô */ | |
1135 parallel_assign(&target,&source,&processing,&use); | |
1136 while (use) { | |
147 | 1137 reg = car(caddr(use)); |
195 | 1138 if (reg==REGISTER||reg==FREGISTER||reg==DREGISTER||reg==LREGISTER) |
99 | 1139 free_register(cadr(caddr(use))); |
117 | 1140 else if (car(caddr(use))==LVAR) |
1141 free_lvar(cadr(caddr(use))); | |
99 | 1142 use=cadr(use); |
61 | 1143 } |
1144 if(target) error(-1); | |
1145 | |
1146 if (env) { | |
1147 /* change the frame pointer */ | |
1148 e3 = emit_pop(0); | |
1149 code_frame_pointer(e3); | |
1150 emit_pop_free(e3); | |
98 | 1151 } else if (is_function(fnptr)) { |
128 | 1152 if (car(e2) != FNAME) { |
1153 e2 = emit_pop(0); | |
1154 code_fix_frame_pointer(disp_offset); | |
1155 code_indirect_jmp(e2); | |
1156 emit_pop_free(e2); | |
1157 return; | |
1158 } | |
61 | 1159 code_fix_frame_pointer(disp_offset); |
1160 } | |
1161 | |
1162 if (car(e2) == FNAME) { | |
1163 code_jmp(code0->nm); | |
1164 } else { | |
1165 e2 = emit_pop(0); | |
1166 code_indirect_jmp(e2); | |
1167 emit_pop_free(e2); | |
1168 } | |
1169 } | |
1170 | |
327 | 1171 static void |
61 | 1172 machinop(int e1) |
1173 { | |
240 | 1174 int e2,e3,op; |
61 | 1175 |
1176 e2 = cadr(e1); | |
1177 op = car(e1); | |
1178 e3 = caddr(e1); | |
240 | 1179 if (code_const_op_p(op,e3)) { |
189 | 1180 g_expr(e2); |
240 | 1181 oprtc(op,USE_CREG,e3); |
189 | 1182 return; |
1183 } | |
61 | 1184 g_expr(e3); |
1185 emit_push(); | |
1186 g_expr(e2); | |
221 | 1187 tosop(op,USE_CREG,(e2=pop_register())); |
61 | 1188 emit_pop_free(e2); |
1189 return; | |
1190 } | |
1191 | |
195 | 1192 #if FLOAT_CODE |
327 | 1193 static void |
133 | 1194 dmachinop(int e1,int d) |
81 | 1195 { |
1196 int e2,e3,op; | |
1197 | |
1198 e2 = cadr(e1); | |
1199 op = car(e1); | |
1200 e3 = caddr(e1); | |
1201 g_expr(e3); | |
133 | 1202 emit_dpush(d); |
81 | 1203 g_expr(e2); |
221 | 1204 dtosop(car(e1),USE_CREG,(e2=emit_dpop(d))); |
138 | 1205 emit_dpop_free(e2,d); |
81 | 1206 return; |
1207 } | |
195 | 1208 #endif |
1209 | |
1210 #if LONGLONG_CODE | |
327 | 1211 static void |
195 | 1212 lmachinop(int e1) |
1213 { | |
1214 int e2,e3,op; | |
1215 | |
1216 e2 = cadr(e1); | |
1217 op = car(e1); | |
1218 e3 = caddr(e1); | |
213 | 1219 if (code_lconst_op_p(op,e3)) { |
1220 g_expr(e2); | |
221 | 1221 loprtc(op,USE_CREG,e3); |
213 | 1222 return; |
1223 } | |
195 | 1224 g_expr(e3); |
1225 emit_lpush(); | |
1226 g_expr(e2); | |
221 | 1227 ltosop(car(e1),USE_CREG,(e2=emit_lpop())); |
195 | 1228 emit_lpop_free(e2); |
1229 return; | |
1230 } | |
1231 #endif | |
81 | 1232 |
327 | 1233 static void |
61 | 1234 sassign(int e1) |
1235 { | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
256
diff
changeset
|
1236 int e2,e3,e4,sz,xreg,det,offset; |
61 | 1237 |
1238 /* structure assignment */ | |
1239 e2 = cadr(e1); /* pointer variable to the struct */ | |
1240 e3 = cadr(e2); /* offset of the variable (distination) */ | |
1241 e4 = caddr(e1); /* right value (source) */ | |
1242 sz = cadddr(e1); /* size of struct or union */ | |
269 | 1243 if (is_same_type(e2,e4)&&cadr(e2)==cadr(e4)) { |
1244 if (use) g_expr(e4); | |
1245 return; | |
1246 } | |
61 | 1247 g_expr(e4); |
1248 emit_push(); | |
1249 g_expr(e2); | |
1250 xreg = emit_pop(0); | |
1251 /* °ìÈÌŪ¤Ë¤Ï¥³¥Ô¡¼¤Î¥ª¡¼¥Ð¥é¥Ã¥×¤Î¾õ¶·¤Ï¼Â¹Ô»þ¤Ë¤·¤«¤ï¤«¤é¤Ê¤¤ */ | |
1252 /* ¤·¤«¤·¡¢¤ï¤«¤ë¾ì¹ç¤â¤¢¤ë */ | |
1253 if (car(e4)==RSTRUCT) e4=cadr(e4); | |
1254 if (is_same_type(e2,e4)) { | |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
256
diff
changeset
|
1255 if(cadr(e2)<cadr(e4)) { offset=sz; sz=-sz;} |
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
256
diff
changeset
|
1256 det=1; |
61 | 1257 } else { |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
256
diff
changeset
|
1258 det = 0; offset=0; |
61 | 1259 } |
258
22949117768f
Complex function argments. Struct is done. Long long is odd.
kono
parents:
256
diff
changeset
|
1260 emit_copy(xreg,USE_CREG,sz,offset,1,det); |
61 | 1261 emit_pop_free(xreg); |
1262 return; | |
1263 } | |
1264 | |
269 | 1265 static void |
118 | 1266 assign_opt(int e5,int e2,int e4,int byte) |
1267 { | |
1268 int reg; | |
1269 /* e2=e4 */ | |
1270 if (e5==REGISTER) { | |
1271 reg = cadr(e4); | |
1272 switch(car(e2)) { | |
1273 case GVAR: code_assign_gvar(e2,reg,byte); return; | |
119 | 1274 case LVAR: code_assign_lvar(cadr(e2),reg,byte); return; |
118 | 1275 case REGISTER: code_assign_register(cadr(e2),byte,reg); return; |
1276 } | |
1277 g_expr(e2); | |
233 | 1278 code_assign(USE_CREG,byte,reg); |
118 | 1279 return; |
1280 } | |
1281 /* e2 is register now */ | |
1282 if (car(e2)!=REGISTER) error(-1); | |
1283 reg = cadr(e2); | |
1284 switch(e5) { | |
162 | 1285 case CRGVAR: |
165 | 1286 case CURGVAR: code_crgvar(e4,reg,e5==CRGVAR,1); return; |
1287 case SRGVAR: | |
1288 case SURGVAR: code_crgvar(e4,reg,e5==SRGVAR,size_of_short); return; | |
329 | 1289 case RGVAR: code_rgvar(e4,reg); return; |
162 | 1290 case CRLVAR: |
165 | 1291 case CURLVAR: code_crlvar(cadr(e4),reg,e5==CRLVAR,1); return; |
1292 case SRLVAR: | |
1293 case SURLVAR: code_crlvar(cadr(e4),reg,e5==SRLVAR,size_of_short); return; | |
329 | 1294 case RLVAR: code_rlvar(cadr(e4),reg); return; |
1295 case GVAR: code_gvar(e4,reg); return; | |
1296 case LVAR: code_lvar(cadr(e4),reg); return; | |
1297 case CONST: code_const(cadr(e4),reg); return; | |
118 | 1298 case ADDRESS: |
1299 if (car(cadr(e4))==STRING) code_string(cadr(e4),reg); | |
1300 else code_gvar(cadr(e4),reg); | |
1301 return; | |
329 | 1302 case FNAME: code_fname((NMTBL*)cadr(e4),reg); return; |
1303 case STRING: code_string(e4,reg); return; | |
135 | 1304 default: error(-1); |
118 | 1305 } |
1306 } | |
1307 | |
327 | 1308 static void |
61 | 1309 assign(int e1) |
1310 { | |
118 | 1311 int e2,e4,byte,e5; |
61 | 1312 |
166 | 1313 byte=(car(e1) == CASS)?1:(car(e1) == SASS)?size_of_short:0; |
61 | 1314 /* e2=e4 */ |
1315 e2 = cadr(e1); | |
118 | 1316 e4 = caddr(e1);e5=car(e4); |
269 | 1317 if (is_same_type(e2,e4)&&cadr(e2)==cadr(e4)) { |
1318 if (use) g_expr(e4); | |
1319 return; | |
1320 } | |
118 | 1321 if (!use && ( |
1322 (e5==REGISTER) || | |
1323 (car(e2)==REGISTER&&( | |
1324 e5== CRGVAR || e5== CRLVAR || e5== RGVAR || e5== RLVAR || | |
162 | 1325 e5== CURGVAR || e5== CURLVAR || |
165 | 1326 e5== SURGVAR || e5== SURLVAR || |
118 | 1327 e5== GVAR || e5== LVAR || |
1328 e5== CONST || e5== FNAME || e5== STRING || | |
1329 (e5==ADDRESS&&car(cadr(e4))==STRING) || | |
1330 (e5==ADDRESS&&car(cadr(e4))==GVAR) )))) { | |
1331 assign_opt(e5,e2,e4,byte); | |
1332 return; | |
1333 } | |
61 | 1334 switch(car(e2)) { |
1335 case GVAR: /* i=3 */ | |
1336 g_expr(e4); | |
221 | 1337 code_assign_gvar(e2,USE_CREG,byte); |
61 | 1338 return; |
1339 case LVAR: | |
1340 g_expr(e4); | |
221 | 1341 code_assign_lvar(cadr(e2),USE_CREG,byte); |
61 | 1342 return; |
1343 case REGISTER: | |
1344 g_expr(e4); | |
221 | 1345 code_assign_register(cadr(e2),byte,USE_CREG); |
61 | 1346 return; |
1347 } | |
1348 g_expr(e2); | |
1349 emit_push(); | |
1350 g_expr(e4); | |
1351 e2 = emit_pop(0); | |
221 | 1352 code_assign(e2,byte,USE_CREG); |
61 | 1353 emit_pop_free(e2); |
1354 return; | |
1355 } | |
1356 | |
195 | 1357 #if FLOAT_CODE |
1358 | |
269 | 1359 static void |
118 | 1360 dassign_opt(int e5,int e2,int e4,int d) |
1361 { | |
1362 int reg; | |
1363 /* e2=e4 */ | |
138 | 1364 if (e5==DREGISTER||e5==FREGISTER) { |
118 | 1365 reg = cadr(e4); |
1366 switch(car(e2)) { | |
1367 case GVAR: /* i=3 */ | |
1368 code_dassign_gvar(e2,reg,d); | |
1369 return; | |
1370 case LVAR: | |
119 | 1371 code_dassign_lvar(cadr(e2),reg,d); |
118 | 1372 return; |
1373 case DREGISTER: | |
138 | 1374 case FREGISTER: |
118 | 1375 if (reg!=cadr(e2)) |
138 | 1376 code_dassign_dregister(cadr(e2),d,reg); |
118 | 1377 return; |
135 | 1378 default: |
1379 error(-1); | |
118 | 1380 } |
1381 } | |
1382 /* e2 is register now */ | |
138 | 1383 if (car(e2)!=DREGISTER && car(e2)!=FREGISTER) error(-1); |
118 | 1384 reg = cadr(e2); |
1385 switch(e5) { | |
135 | 1386 case FRGVAR: |
118 | 1387 case DRGVAR: code_drgvar(e4,d,reg); return; |
135 | 1388 case FRLVAR: |
119 | 1389 case DRLVAR: code_drlvar(cadr(e4),d,reg); return; |
135 | 1390 case FCONST: |
264 | 1391 case DCONST: code_dconst(e4,reg,d); return; |
135 | 1392 default: |
118 | 1393 error(-1); |
1394 } | |
1395 } | |
1396 | |
327 | 1397 static void |
81 | 1398 dassign(int e1) |
1399 { | |
118 | 1400 int e2,e3,e4,d,e5; |
81 | 1401 |
1402 /* e2=e4 */ | |
1403 e2 = cadr(e1); | |
1404 e3 = cadr(e2); | |
118 | 1405 e4 = caddr(e1); e5=car(e4); |
269 | 1406 if (is_same_type(e2,e4)&&cadr(e2)==cadr(e4)) { |
1407 if (use) g_expr(e4); | |
1408 return; | |
1409 } | |
249 | 1410 if (car(e1)==DASS) d=1; |
1411 else if (car(e1)==FASS) d=0; | |
1412 else error(-1); | |
118 | 1413 if (!use && ( |
138 | 1414 (e5==DREGISTER) || (e5==FREGISTER) || |
133 | 1415 (car(e2)==DREGISTER&&(e5==DRGVAR||e5==DRLVAR||e5==DCONST))|| |
249 | 1416 (car(e2)==FREGISTER&&(e5==FRGVAR||e5==FRLVAR||e5==FCONST)) |
118 | 1417 )) { |
1418 dassign_opt(e5,e2,e4,d); | |
1419 return; | |
1420 } | |
81 | 1421 switch(car(e2)) { |
82 | 1422 case GVAR: |
81 | 1423 g_expr(e4); |
221 | 1424 code_dassign_gvar(e2,USE_CREG,d); |
81 | 1425 return; |
1426 case LVAR: | |
1427 g_expr(e4); | |
221 | 1428 code_dassign_lvar(cadr(e2),USE_CREG,d); |
81 | 1429 return; |
111 | 1430 case DREGISTER: |
138 | 1431 case FREGISTER: |
111 | 1432 g_expr(e4); |
221 | 1433 code_dassign_dregister(cadr(e2),d,USE_CREG); |
111 | 1434 return; |
81 | 1435 } |
1436 g_expr(e2); | |
82 | 1437 emit_push(); |
81 | 1438 g_expr(e4); |
82 | 1439 e2 = emit_pop(0); |
221 | 1440 code_dassign(e2,USE_CREG,d); |
82 | 1441 emit_pop_free(e2); |
81 | 1442 return; |
1443 } | |
1444 | |
195 | 1445 #endif |
1446 | |
1447 #if LONGLONG_CODE | |
1448 | |
327 | 1449 static void |
195 | 1450 lassign_opt(int e5,int e2,int e4) |
1451 { | |
1452 int reg; | |
1453 /* e2=e4 */ | |
1454 if (e5==LREGISTER) { | |
1455 reg = cadr(e4); | |
1456 switch(car(e2)) { | |
1457 case GVAR: /* i=3 */ | |
1458 code_lassign_gvar(e2,reg); | |
1459 return; | |
1460 case LVAR: | |
1461 code_lassign_lvar(cadr(e2),reg); | |
1462 return; | |
1463 case LREGISTER: | |
1464 if (reg!=cadr(e2)) | |
1465 code_lassign_lregister(cadr(e2),reg); | |
1466 return; | |
1467 default: | |
1468 error(-1); | |
1469 } | |
1470 } | |
1471 /* e2 is register now */ | |
1472 if (car(e2)!=LREGISTER) error(-1); | |
1473 reg = cadr(e2); | |
1474 switch(e5) { | |
1475 case LRGVAR: code_lrgvar(e4,reg); return; | |
1476 case LRLVAR: code_lrlvar(cadr(e4),reg); return; | |
1477 case LCONST: code_lconst(e4,reg); return; | |
1478 default: | |
1479 error(-1); | |
1480 } | |
1481 } | |
1482 | |
327 | 1483 static void |
195 | 1484 lassign(int e1) |
1485 { | |
1486 int e2,e3,e4,e5; | |
1487 | |
1488 /* e2=e4 */ | |
1489 e2 = cadr(e1); | |
1490 e3 = cadr(e2); | |
1491 e4 = caddr(e1); e5=car(e4); | |
269 | 1492 if (is_same_type(e2,e4)&&cadr(e2)==cadr(e4)) { |
1493 if (use) g_expr(e4); | |
1494 return; | |
1495 } | |
195 | 1496 if (!use && ( |
1497 (e5==LREGISTER) || | |
1498 (car(e2)==LREGISTER&&(e5==LRGVAR||e5==LRLVAR||e5==LCONST)) | |
1499 )) { | |
1500 lassign_opt(e5,e2,e4); | |
1501 return; | |
1502 } | |
1503 switch(car(e2)) { | |
1504 case GVAR: | |
1505 g_expr(e4); | |
221 | 1506 code_lassign_gvar(e2,USE_CREG); |
195 | 1507 return; |
1508 case LVAR: | |
1509 g_expr(e4); | |
221 | 1510 code_lassign_lvar(cadr(e2),USE_CREG); |
195 | 1511 return; |
1512 case LREGISTER: | |
1513 g_expr(e4); | |
221 | 1514 code_lassign_lregister(cadr(e2),USE_CREG); |
195 | 1515 return; |
1516 } | |
1517 g_expr(e2); | |
219 | 1518 emit_push(); |
195 | 1519 g_expr(e4); |
219 | 1520 e2 = emit_pop(0); |
221 | 1521 code_lassign(e2,USE_CREG); |
219 | 1522 emit_pop_free(e2); |
195 | 1523 return; |
1524 } | |
1525 | |
1526 #endif | |
1527 | |
327 | 1528 /* numerical type conversion */ |
1529 | |
1530 static int | |
1531 double_value(int e2,int type) | |
1532 { | |
1533 #if FLOAT_CODE | |
1534 if (car(e2)==CONST) return dlist2(DCONST,(double)cadr(e2)); | |
1535 if (car(e2)==FCONST) return dlist2(DCONST,dcadr(e2)); | |
1536 if(type==DOUBLE) return e2; | |
1537 if(type==FLOAT) return list3(CONV,rvalue_t(e2,type),F2D); | |
1538 if(type==UNSIGNED) return list3(CONV,rvalue_t(e2,type),U2D); | |
1539 if(integral(type)) return list3(CONV,rvalue_t(e2,type),I2D); | |
1540 if(type==LONGLONG) return list3(CONV,rvalue_t(e2,type),LL2D); | |
1541 if(type==ULONGLONG) return list3(CONV,rvalue_t(e2,type),ULL2D); | |
1542 error(TYERR); return dlist2(DCONST,1.0); | |
1543 #else | |
1544 error(TYERR); return list2(CONST,0); | |
1545 #endif | |
1546 } | |
1547 | |
1548 static int | |
1549 float_value(int e2,int type) | |
1550 { | |
1551 #if FLOAT_CODE | |
1552 #if LONGLONG_CODE | |
1553 if (car(e2)==LCONST) return dlist2(FCONST,(double)lcadr(e2)); | |
1554 if(type==LONGLONG) return list3(CONV,rvalue_t(e2,type),LL2F); | |
1555 if(type==ULONGLONG) return list3(CONV,rvalue_t(e2,type),ULL2F); | |
1556 #endif | |
1557 if (car(e2)==CONST) return dlist2(FCONST,(double)cadr(e2)); | |
1558 if (car(e2)==DCONST) return dlist2(FCONST,dcadr(e2)); | |
1559 if(type==FLOAT) return e2; | |
1560 if(type==DOUBLE) return list3(CONV,rvalue_t(e2,type),D2F); | |
1561 if(type==UNSIGNED) return list3(CONV,rvalue_t(e2,type),U2F); | |
1562 if(integral(type)) return list3(CONV,rvalue_t(e2,type),I2F); | |
1563 error(TYERR); return dlist2(DCONST,1.0); | |
1564 #else | |
1565 error(TYERR); return list2(CONST,0); | |
1566 #endif | |
1567 } | |
1568 | |
1569 static int | |
1570 longlong_value(int e2,int type) | |
1571 { | |
1572 #if LONGLONG_CODE | |
1573 if (car(e2)==CONST) return llist2(LCONST,(long long)cadr(e2)); | |
1574 if (car(e2)==LCONST) return e2; | |
1575 #if FLOAT_CODE | |
1576 if (car(e2)==DCONST||car(e2)==FCONST) | |
1577 return llist2(LCONST,(long long)dcadr(e2)); | |
1578 if(type==FLOAT) return list3(CONV,rvalue_t(e2,type),F2LL); | |
1579 if(type==DOUBLE) return list3(CONV,rvalue_t(e2,type),D2LL); | |
1580 #endif | |
1581 if(type==UNSIGNED) return list3(CONV,rvalue_t(e2,type),U2LL); | |
1582 if(type==LONGLONG) return e2; | |
1583 if(type==ULONGLONG) return e2; | |
1584 if(integral(type)) return list3(CONV,rvalue_t(e2,type),I2LL); | |
1585 error(TYERR); return llist2(LCONST,0LL); | |
1586 #else | |
1587 return int_value(e2,type); | |
1588 #endif | |
1589 } | |
1590 | |
1591 static int | |
1592 ulonglong_value(int e2,int type) | |
1593 { | |
1594 #if LONGLONG_CODE | |
1595 if (car(e2)==CONST) return llist2(LCONST,(unsigned long long)cadr(e2)); | |
1596 if (car(e2)==LCONST) return e2; | |
1597 #if FLOAT_CODE | |
1598 if (car(e2)==DCONST||car(e2)==FCONST) | |
1599 return llist2(LCONST,(unsigned long long)dcadr(e2)); | |
1600 if(type==FLOAT) return list3(CONV,rvalue_t(e2,type),F2ULL); | |
1601 if(type==DOUBLE) return list3(CONV,rvalue_t(e2,type),D2ULL); | |
1602 #endif | |
1603 if(type==UNSIGNED) return list3(CONV,rvalue_t(e2,type),U2ULL); | |
1604 if(type==LONGLONG) return e2; | |
1605 if(type==ULONGLONG) return e2; | |
1606 if(integral(type)) return list3(CONV,rvalue_t(e2,type),I2ULL); | |
1607 error(TYERR); return llist2(LCONST,0LL); | |
1608 #else | |
1609 unsigned_value(e2,type); | |
1610 #endif | |
1611 } | |
1612 | |
1613 static int | |
1614 int_value(int e2,int type) | |
1615 { | |
1616 if(scalar(type)) return e2; | |
1617 #if FLOAT_CODE | |
1618 if (car(e2)==DCONST||car(e2)==FCONST) return list2(CONST,(int)dcadr(e2)); | |
1619 if(type==FLOAT) return list3(CONV,rvalue_t(e2,type),F2I); | |
1620 if(type==DOUBLE) return list3(CONV,rvalue_t(e2,type),D2I); | |
1621 #endif | |
1622 #if LONGLONG_CODE | |
1623 if (car(e2)==LCONST) return list2(CONST,(int)lcadr(e2)); | |
1624 if(type==LONGLONG) return list3(CONV,rvalue_t(e2,type),LL2I); | |
1625 if(type==ULONGLONG) return list3(CONV,rvalue_t(e2,type),ULL2I); | |
1626 #endif | |
1627 if(car(type)==ARRAY) return e2; | |
1628 error(TYERR); return list2(CONST,1); | |
1629 } | |
1630 | |
1631 static int | |
1632 unsigned_value(int e2,int type) | |
1633 { | |
1634 if(scalar(type)) return e2; | |
1635 #if FLOAT_CODE | |
1636 // if (car(e2)==DCONST||car(e2)==FCONST) return list2(CONST,(unsigned)dcadr(e2)); | |
1637 if (car(e2)==DCONST||car(e2)==FCONST) return list2(CONST,(int)dcadr(e2)); | |
1638 if(type==FLOAT) return list3(CONV,rvalue_t(e2,type),F2U); | |
1639 if(type==DOUBLE) return list3(CONV,rvalue_t(e2,type),D2U); | |
1640 #endif | |
1641 #if LONGLONG_CODE | |
1642 if(type==LONGLONG) return list3(CONV,rvalue_t(e2,type),LL2U); | |
1643 if(type==ULONGLONG) return list3(CONV,rvalue_t(e2,type),ULL2U); | |
1644 #endif | |
1645 error(TYERR); return e2; | |
1646 } | |
1647 | |
1648 /* assign statement */ | |
1649 | |
1650 /* keep type */ | |
1651 | |
1652 extern int | |
1653 assign_expr0(int e1,int e2,int t,int type0) { | |
1654 int stype; | |
1655 stype=type; | |
1656 type = type0; | |
1657 e2 = rvalue(e2); | |
1658 e1=assign_expr(e1,e2,t,type); | |
1659 type=stype; | |
1660 return e1; | |
1661 } | |
1662 | |
1663 | |
1664 | |
1665 /* with conversion (will destroy type global variable) */ | |
1666 | |
1667 extern int | |
1668 assign_expr(int e1,int e2,int t,int type) { | |
1669 if(t==VOID) | |
1670 error(TYERR); | |
1671 if(t==CHAR||t==UCHAR) { | |
1672 e2=(t==UCHAR)?unsigned_value(e2,type):int_value(e2,type); | |
1673 if (!integral(type)) error(TYERR); | |
1674 type= INT;return(list3(CASS,e1,e2)); | |
1675 } else if(t==SHORT||t==USHORT) { | |
1676 e2=(t==USHORT)?unsigned_value(e2,type):int_value(e2,type); | |
1677 if (!integral(type)) error(TYERR); | |
1678 type= t;return(list3(SASS,e1,e2)); | |
1679 #if FLOAT_CODE | |
1680 } else if(t==DOUBLE) { | |
1681 e2=double_value(e2,type); | |
1682 type= t;return(list3(DASS,e1,e2)); | |
1683 } else if(t==FLOAT) { | |
1684 e2=float_value(e2,type); | |
1685 type= t;return(list3(FASS,e1,e2)); | |
1686 #endif | |
1687 #if LONGLONG_CODE | |
1688 } else if(t==LONGLONG) { | |
1689 e2=longlong_value(e2,type); | |
1690 type= t;return(list3(LASS,e1,e2)); | |
1691 } else if(t==ULONGLONG) { | |
1692 e2=ulonglong_value(e2,type); | |
1693 type= t;return(list3(LASS,e1,e2)); | |
1694 #endif | |
1695 } else if(scalar(t)) { | |
1696 e2=(t==UNSIGNED)?unsigned_value(e2,type):int_value(e2,type); | |
1697 type=t; | |
1698 return(list3(ASS,e1,e2)); | |
1699 } else if (car(t)==BIT_FIELD) { | |
1700 e2 = correct_type(e2,cadr(t)); | |
329 | 1701 return(list4(BASS,e1,e2,list2(BASS,t))); |
327 | 1702 } else if((car(t)==STRUCT||car(t)==UNION)) { |
1703 if (size(t)!=size(type)) error(TYERR); | |
1704 type=t; | |
1705 if(car(e2)==RSTRUCT && car(cadr(e2))==FUNCTION) { | |
1706 replace_return_struct(cadr(e2),e1); | |
1707 return cadr(e2); | |
1708 } else { | |
1709 return (list4(STASS,e1,e2,size(t))); | |
1710 } | |
1711 } else { | |
1712 error(TYERR); return list3(ASS,e1,e2); | |
1713 } | |
1714 } | |
1715 | |
1716 extern int | |
1717 cond(int t,int e1,int e2,int e3) | |
1718 { | |
1719 if(car(e1)==CONST) { | |
1720 if(cadr(e1)) {type=t;return e2;} else return e3; | |
1721 } | |
1722 #if FLOAT_CODE | |
1723 if(type==DOUBLE||t==DOUBLE) { | |
1724 e2=double_value(e2,t); | |
1725 e3=double_value(e3,type); | |
1726 t=type=DOUBLE; | |
1727 return(list4(DCOND,e1,e2,e3)); | |
1728 } | |
1729 if(type==FLOAT||t==FLOAT) { | |
1730 e2=float_value(e2,t); | |
1731 e3=float_value(e3,type); | |
1732 t=type=FLOAT; | |
1733 return(list4(FCOND,e1,e2,e3)); | |
1734 } | |
1735 #endif | |
1736 #if LONGLONG_CODE | |
1737 if(type==LONGLONG||t==LONGLONG) { | |
1738 e2=longlong_value(e2,t); | |
1739 e3=longlong_value(e3,type); | |
1740 t=type=LONGLONG; | |
1741 return(list4(LCOND,e1,e2,e3)); | |
1742 } | |
1743 if(type==ULONGLONG||t==ULONGLONG) { | |
1744 e2=ulonglong_value(e2,t); | |
1745 e3=ulonglong_value(e3,type); | |
1746 t=type=ULONGLONG; | |
1747 return(list4(LCOND,e1,e2,e3)); | |
1748 } | |
1749 #endif | |
1750 if(type==INT||(t!=INT&&type==UNSIGNED)) | |
1751 type=t; | |
1752 /* if (t!=type) error(TYERR); */ | |
1753 return(list4(COND,e1,e2,e3)); | |
1754 } | |
1755 | |
1756 extern int | |
1757 assop(int e1,int e2,int op,int t,int no_float) | |
1758 { | |
1759 if(!(integral(type)||type==FLOAT||type==DOUBLE|| | |
1760 type==LONGLONG||type==ULONGLONG | |
1761 )) error(TYERR); | |
1762 #if FLOAT_CODE | |
1763 if (t==FLOAT) { | |
1764 if (no_float) error(TYERR); | |
1765 e2=float_value(e2,type); type=t; | |
1766 return(list4(FASSOP,e1,e2,op+FOP)); | |
1767 } else if (t==DOUBLE) { | |
1768 if (no_float) error(TYERR); | |
1769 e2=double_value(e2,type); type=t; | |
1770 return(list4(DASSOP,e1,e2,op+DOP)); | |
1771 } | |
1772 #endif | |
1773 #if LONGLONG_CODE | |
1774 if (t==LONGLONG) { | |
1775 e2=longlong_value(e2,type); type=t; | |
1776 return(list4(LASSOP,e1,e2,op+LOP)); | |
1777 } else if (t==ULONGLONG) { | |
1778 e2=ulonglong_value(e2,type); type=t; | |
1779 return(list4(LASSOP,e1,e2,op+LOP+((op==MUL+AS||op==DIV+AS)?US:0))); | |
1780 } | |
1781 #endif | |
1782 if((t==UNSIGNED||t==UCHAR||t==USHORT||type==UNSIGNED)&& | |
1783 (op==MUL||op==DIV||op==MOD)) | |
1784 op=op+US; | |
1785 if((t==UNSIGNED||t==UCHAR||t==USHORT)&&(op==RSHIFT||op==LSHIFT)) | |
1786 op=op+US; | |
1787 if(t==CHAR) { | |
1788 type= INT; | |
1789 return(list4(CASSOP,e1,e2,op)); | |
1790 } | |
1791 if(t==UCHAR) { | |
1792 type= UNSIGNED; | |
1793 return(list4(CUASSOP,e1,e2,op)); | |
1794 } | |
1795 if(t==SHORT) { | |
1796 type= INT; | |
1797 return(list4(SASSOP,e1,e2,op)); | |
1798 } | |
1799 if(t==USHORT) { | |
1800 type= UNSIGNED; | |
1801 return(list4(SUASSOP,e1,e2,op)); | |
1802 } | |
1803 if (t>0 && car(t)==BIT_FIELD) { | |
1804 e2 = correct_type(e2,cadr(t)); | |
1805 return(list4(BASSOP,e1,e2,list2(op,t))); | |
1806 } | |
1807 type=t; | |
1808 if(integral(t)) return(list4(ASSOP,e1,e2,op)); | |
1809 /* pointer += ... */ | |
1810 if((op!=ADD&&op!=SUB)||car(t)!=POINTER) error(TYERR); | |
1811 e2=binop(MUL,e2,list2(CONST,size(cadr(t))),INT,UNSIGNED); | |
1812 type=t; | |
1813 | |
1814 return list4(ASSOP,e1,e2,op); | |
1815 } | |
1816 | |
1817 | |
1818 | |
1819 static void | |
1820 iassop(int e1) | |
61 | 1821 { |
165 | 1822 int e2,e3,byte,op,sign,size; |
255 | 1823 int n,t; |
61 | 1824 |
1825 /* e2 op= e3 */ | |
162 | 1826 if (car(e1) == CUASSOP) { |
165 | 1827 byte = 1; sign = 0; size = 1; |
162 | 1828 } else if (car(e1) == CASSOP) { |
165 | 1829 byte = 1; sign = 1; size = 1; |
1830 } else if (car(e1) == SUASSOP) { | |
1831 byte = size_of_short; sign = 0; size = size_of_short; | |
1832 } else if (car(e1) == SASSOP) { | |
1833 byte = size_of_short; sign = 1; size = size_of_short; | |
162 | 1834 } else { |
165 | 1835 byte = 0; sign = 1; size = size_of_int; |
162 | 1836 } |
61 | 1837 e2 = cadr(e1); |
1838 if (car(e2)==INDIRECT) e2=cadr(e2); | |
1839 e3 = caddr(e1); | |
1840 op = cadddr(e1); | |
1841 | |
285 | 1842 if (car(e2)==REGISTER) { |
1843 if (code_const_op_p(op,e3)) { | |
1844 oprtc(op,cadr(e2),e3); | |
1845 } else { | |
1846 g_expr(e3); | |
1847 code_register_assop(cadr(e2),USE_CREG,op,byte); | |
1848 } | |
1849 if (use) { | |
1850 code_register(cadr(e2),USE_CREG); | |
1851 } | |
1852 return; | |
1853 } | |
255 | 1854 if (car(e3)==CONST) { |
1855 /* e2 = e2 op e3; */ | |
1856 t = sign?INT:UNSIGNED; | |
285 | 1857 // oprtc expected |
1858 if (car(e2)==LVAR||car(e2)==GVAR) { | |
255 | 1859 g_expr(assign_expr0(e2,list3(op,rvalue_t(e2,t),e3),t,t)); |
1860 return; | |
1861 } | |
1862 /* new = &e2 */ | |
1863 /* *new = *new op e3 */ | |
1864 n = list2(LVAR,new_lvar(size_of_int)); | |
1865 g_expr_u(assign_expr0(n,list2(ADDRESS,e2),INT,INT)); | |
1866 g_expr(assign_expr0(list2(INDIRECT,n),list3(op,n,e3),t,t)); | |
1867 free_lvar(cadr(n)); | |
1868 return; | |
1869 } | |
61 | 1870 g_expr(e3); |
1871 emit_push(); | |
1872 g_expr(e2); | |
221 | 1873 code_assop(op,USE_CREG,byte,sign); |
61 | 1874 return; |
1875 } | |
1876 | |
195 | 1877 #if FLOAT_CODE |
1878 | |
327 | 1879 static void |
81 | 1880 dassop(int e1) |
1881 { | |
83 | 1882 int e2,e3,op,d; |
81 | 1883 |
83 | 1884 /* e2 op= e3 */ |
1885 d = (car(e1) == DASSOP); | |
1886 e2 = cadr(e1); | |
1887 if (car(e2)==INDIRECT) e2=cadr(e2); | |
1888 e3 = caddr(e1); | |
1889 op = cadddr(e1); | |
1890 | |
1891 g_expr(e3); | |
144 | 1892 if (car(e2)==DREGISTER||car(e2)==FREGISTER) { |
273 | 1893 emit_dpush(d); |
219 | 1894 code_register_dassop(cadr(e2),op,d); |
273 | 1895 if (use) |
1896 code_dregister(cadr(e2),USE_CREG,d); | |
1897 return; | |
144 | 1898 } |
238 | 1899 emit_dpush(d); |
1900 g_expr(e2); | |
221 | 1901 code_dassop(op,USE_CREG,d); |
83 | 1902 return; |
81 | 1903 } |
61 | 1904 |
195 | 1905 #endif |
1906 | |
1907 #if LONGLONG_CODE | |
1908 | |
238 | 1909 static int |
1910 long_sign(int op) | |
1911 { | |
1912 return (op==LUDIV||op==LUMOD||op==LULSHIFT||op==LURSHIFT)?ULONGLONG:LONGLONG; | |
1913 } | |
1914 | |
327 | 1915 static void |
195 | 1916 lassop(int e1) |
1917 { | |
1918 int e2,e3,op; | |
238 | 1919 int n,t; |
195 | 1920 |
1921 /* e2 op= e3 */ | |
1922 e2 = cadr(e1); | |
1923 if (car(e2)==INDIRECT) e2=cadr(e2); | |
1924 e3 = caddr(e1); | |
1925 op = cadddr(e1); | |
1926 | |
286 | 1927 if (car(e2)==LREGISTER) { |
285 | 1928 if (code_lconst_op_p(op,e3)) { |
1929 loprtc(op,cadr(e2),e3); | |
286 | 1930 if (use) { |
1931 code_lregister(cadr(e2),USE_CREG); | |
1932 } | |
1933 return; | |
1934 } | |
1935 if (code_lassop_p) { | |
285 | 1936 g_expr(e3); |
1937 emit_lpush(); | |
1938 code_register_lassop(cadr(e2),op); | |
286 | 1939 if (use) { |
1940 code_lregister(cadr(e2),USE_CREG); | |
1941 } | |
1942 return; | |
285 | 1943 } |
1944 } | |
238 | 1945 if (!code_lassop_p||car(e3)==LCONST) { |
1946 /* e2 = e2 op e3; */ | |
1947 t = long_sign(op); | |
286 | 1948 if (car(e2)==LREGISTER||car(e2)==LVAR||car(e2)==GVAR) { |
238 | 1949 g_expr(assign_expr0(e2,list3(op,rvalue_t(e2,t),e3),t,t)); |
239 | 1950 return; |
238 | 1951 } |
1952 /* new = &e2 */ | |
1953 /* *new = *new op e3 */ | |
1954 n = list2(LVAR,new_lvar(size_of_int)); | |
239 | 1955 g_expr_u(assign_expr0(n,list2(ADDRESS,e2),INT,INT)); |
238 | 1956 g_expr(assign_expr0(list2(INDIRECT,n),list3(op,n,e3),t,t)); |
1957 free_lvar(cadr(n)); | |
1958 return; | |
1959 } | |
1960 | |
195 | 1961 g_expr(e3); |
286 | 1962 if (car(e2)==LREGISTER) { |
1963 emit_lpush(); | |
1964 code_register_lassop(cadr(e2),op); | |
1965 if (use) | |
1966 code_lregister(cadr(e2),USE_CREG); | |
1967 return; | |
1968 } | |
238 | 1969 emit_lpush(); |
1970 g_expr(e2); | |
221 | 1971 code_lassop(op,USE_CREG); |
195 | 1972 return; |
1973 } | |
1974 | |
1975 #endif | |
1976 | |
327 | 1977 extern void |
287 | 1978 cmpdimm(int e, int csreg,int label,int cond) |
95 | 1979 { |
287 | 1980 code_cmpdimm(e, csreg,label,cond); |
95 | 1981 } |
1982 | |
327 | 1983 extern int |
95 | 1984 csvalue() |
1985 { | |
1986 return code_csvalue(); | |
1987 } | |
1988 | |
1989 | |
327 | 1990 extern int |
61 | 1991 fwdlabel(void) |
1992 { | |
1993 return labelno++; | |
1994 } | |
1995 | |
327 | 1996 extern void |
61 | 1997 fwddef(int l) |
1998 { | |
1999 control=1; | |
66 | 2000 if (!chk) |
92 | 2001 code_label(l); |
61 | 2002 } |
2003 | |
327 | 2004 extern int |
61 | 2005 backdef(void) |
2006 { | |
2007 control=1; | |
66 | 2008 if (!chk) |
92 | 2009 code_label(labelno); |
61 | 2010 return labelno++; |
2011 } | |
2012 | |
327 | 2013 extern void |
61 | 2014 def_label(int cslabel, int dlabel) |
2015 { | |
2016 int fl; | |
2017 | |
2018 fl = 0; | |
2019 if (control) { | |
2020 jmp(fl=fwdlabel()); | |
2021 } | |
2022 fwddef(cslabel); | |
2023 if (dlabel) | |
2024 jmp(dlabel); | |
2025 if (fl) { | |
2026 fwddef(fl); | |
2027 } | |
2028 } | |
2029 | |
327 | 2030 extern void |
61 | 2031 ret(void) |
2032 { | |
107 | 2033 code_set_return_register(1); |
61 | 2034 jmp(retlabel); |
2035 } | |
2036 | |
327 | 2037 extern void |
66 | 2038 opening(char *filename) |
2039 { | |
2040 emit_init(); | |
2041 if (!chk) | |
2042 code_opening(filename); | |
2043 } | |
2044 | |
327 | 2045 extern void |
66 | 2046 closing() |
2047 { | |
2048 if (!chk) | |
2049 code_closing(); | |
2050 } | |
2051 | |
327 | 2052 static int |
99 | 2053 contains_in_list(int e,int type) |
2054 { | |
2055 while(e) { | |
2056 if(contains(car(e),type)) return 1; | |
2057 e = cadr(e); | |
2058 } | |
2059 return 0; | |
2060 } | |
2061 | |
327 | 2062 static int |
99 | 2063 contains(int e,int type) |
2064 { | |
2065 while(e) { | |
2066 if (car(e)==type) return 1; | |
256
d80e6387c539
powerpc function call complex arugment pre computation.
kono
parents:
255
diff
changeset
|
2067 if (!car(e)) return 0; |
164 | 2068 if (LIST_ARGS(car(e))){ |
99 | 2069 /* list arguments */ |
2070 return contains_in_list(caddr(e),type); | |
164 | 2071 } else if (UNARY_ARGS(car(e))) { |
99 | 2072 /* unary operators */ |
2073 e = cadr(e); | |
2074 continue; | |
164 | 2075 } else if (BINARY_ARGS(car(e))) { |
99 | 2076 /* biary operators */ |
2077 if (contains(cadr(e),type)) return 1; | |
2078 e = caddr(e); | |
2079 continue; | |
164 | 2080 } else if (TARNARY_ARGS(car(e))) { |
99 | 2081 /* tarary operators */ |
2082 if (contains(cadr(e), type)) return 1; | |
2083 if (contains(caddr(e),type)) return 1; | |
2084 e = cadddr(e); | |
2085 continue; | |
164 | 2086 } else if (NULLARY_ARGS(car(e))) { |
135 | 2087 /* nullary operators */ |
2088 return 0; | |
164 | 2089 } else { |
327 | 2090 // fprintf(stderr,"Unknown Tree ID %d\n",car(e)); |
135 | 2091 error(-1); |
99 | 2092 return 0; |
2093 } | |
2094 } | |
2095 return 0; | |
2096 } | |
2097 | |
327 | 2098 static int |
223 | 2099 contains_in_list_p(int e,int (*p)(int)) |
2100 { | |
2101 while(e) { | |
2102 if(contains_p(car(e),p)) return 1; | |
2103 e = cadr(e); | |
2104 } | |
2105 return 0; | |
2106 } | |
2107 | |
327 | 2108 extern int |
223 | 2109 contains_p(int e,int (*p)(int)) |
2110 { | |
2111 while(e) { | |
256
d80e6387c539
powerpc function call complex arugment pre computation.
kono
parents:
255
diff
changeset
|
2112 if (!car(e)) return 0; |
223 | 2113 if (p(car(e))) return 1; |
2114 if (LIST_ARGS(car(e))){ | |
2115 /* list arguments */ | |
2116 return contains_in_list_p(caddr(e),p); | |
2117 } else if (UNARY_ARGS(car(e))) { | |
2118 /* unary operators */ | |
2119 e = cadr(e); | |
2120 continue; | |
2121 } else if (BINARY_ARGS(car(e))) { | |
2122 /* biary operators */ | |
2123 if (contains_p(cadr(e),p)) return 1; | |
2124 e = caddr(e); | |
2125 continue; | |
2126 } else if (TARNARY_ARGS(car(e))) { | |
2127 /* tarary operators */ | |
2128 if (contains_p(cadr(e), p)) return 1; | |
2129 if (contains_p(caddr(e),p)) return 1; | |
2130 e = cadddr(e); | |
2131 continue; | |
2132 } else if (NULLARY_ARGS(car(e))) { | |
2133 /* nullary operators */ | |
2134 return 0; | |
2135 } else { | |
327 | 2136 // fprintf(stderr,"Unknown Tree ID %d\n",car(e)); |
223 | 2137 error(-1); |
2138 return 0; | |
2139 } | |
2140 } | |
2141 return 0; | |
2142 } | |
2143 | |
320 | 2144 #if ASM_CODE |
2145 | |
2146 | |
2147 /* | |
2148 __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (a | |
2149 ddr)); | |
2150 asm string : output constraint parameter : input constraint parameter : opt | |
2151 | |
2152 1: asm string %1,%2 will be replaced by register or value | |
2153 2: constraint gcc constraint sting | |
2154 prefix | |
2155 = overwrite by this asm for output | |
2156 & overwrite by this asm and can't be used as input register | |
2157 ignored in this compiler | |
2158 constraints | |
326 | 2159 m value expression is modified (no corresponding register) |
320 | 2160 information for compiler |
2161 r register for input or output | |
2162 input register, output register can be shared | |
2163 0-9 same operands as outout register in input constraints | |
2164 3: opt "cc", "memory" | |
2165 ignored in this compiler | |
2166 */ | |
2167 | |
2168 static void | |
327 | 2169 gen_asm(int asm0,int in,int out,int opt,int e) |
320 | 2170 { |
2171 int i,e1,n; | |
2172 int repl = 0; | |
2173 int repl0; | |
2174 int assign = 0; | |
2175 char *p; | |
2176 | |
2177 printf("# asm\n"); | |
2178 in = reverse0(in); | |
2179 out = reverse0(out); | |
2180 e = reverse0(e); | |
2181 for(i=out;i;i=cadr(i)) { | |
2182 p = (char*)cadr(car(i)); | |
2183 e1 = car(e); e = cadr(e); | |
327 | 2184 repl = code_asm_operand(p,e1,ASM_OUTPUT,repl,0,0); |
320 | 2185 if (car(car(repl))==REGISTER) { |
2186 assign = list2(assign_expr0(e1,car(repl),INT,INT),assign); | |
2187 } | |
2188 } | |
2189 repl0 = repl; | |
2190 n = length(repl0); | |
2191 for(i=in;i;i=cadr(i)) { | |
2192 p = (char*)cadr(car(i)); | |
2193 e1 = car(e); e = cadr(e); | |
327 | 2194 repl = code_asm_operand(p,e1,ASM_INPUT,repl,n,repl0); |
320 | 2195 if (car(car(repl))==REGISTER) { |
2196 g_expr_u(assign_expr0(car(repl),e1,INT,INT)); | |
2197 } | |
2198 } | |
2199 repl = reverse0(repl); | |
327 | 2200 code_asm((char*)cadr(asm0),repl); |
320 | 2201 for(i=assign;i;i=cadr(i)) { |
2202 g_expr_u(car(i)); | |
2203 } | |
327 | 2204 code_free_asm_operand(repl); |
320 | 2205 // no check for opt |
2206 } | |
2207 | |
327 | 2208 #endif |
2209 | |
2210 | |
2211 extern NMTBL * | |
2212 def(NMTBL *n) | |
2213 { | |
2214 int sz,nsc,ndsp; | |
2215 int sbit_f = bit_field_disp; | |
2216 bit_field_disp = 0; // default is 0, recover only in bit-field | |
2217 | |
2218 if (n==0) { | |
2219 n=anonymous_nptr(); | |
2220 n->nm = "_"; | |
2221 } | |
2222 nsc=ndsp=0; | |
2223 if (stmode==EXTRN||mode==GDECL) | |
2224 n->ty = type; /* must be in global table/heap */ | |
2225 if(type>0&&(car(type)==FUNCTION || car(type)==CODE)) { | |
2226 if ((mode==GDECL)) { | |
2227 fcheck(n); | |
2228 return n; | |
2229 /* function and code segment are defined using fdecl/code_decl */ | |
2230 /* in decl() */ | |
2231 } | |
2232 } | |
2233 if (mode==GSDECL||mode==LSDECL|| mode==GUDECL||mode==LUDECL) { | |
2234 /* Struct fields name lists are in the struct type or tag. */ | |
2235 /* Only name in the table is used. */ | |
2236 if (car(n->ty)==BIT_FIELD) { | |
2237 bit_field_disp=sbit_f; // default is 0, recover only here. | |
2238 // n->ty = list4(BIT_FIELD,type,bit_offset,bit_width); | |
329 | 2239 caddr(n->ty) = code_bit_field_disp( |
2240 cadr(n->ty),cadddr(n->ty),&disp,&bit_field_disp,&sz); | |
2241 /* bit_field_disp is next bit posision */ | |
327 | 2242 } else { |
2243 sz = size(type); | |
2244 } | |
2245 fields = list4(type,fields,(int)(n->nm),disp); | |
2246 } else { | |
2247 if (n->sc!=EMPTY && !(n->sc==EXTRN||n->sc==EXTRN1||n->sc==STATIC)) { | |
2248 /* redefined case */ | |
2249 if (mode==ADECL) { /* K&R arguments case */ | |
2250 if (n->sc==LVAR && n->ty==INT); | |
2251 else if ( n->sc==REGISTER && n->ty==INT); | |
2252 else error(RDERR); | |
2253 } else error(RDERR); | |
2254 } | |
2255 sz = size(n->ty = type); | |
2256 } | |
2257 switch(mode) { | |
2258 case GDECL: | |
2259 gen_gdecl(n->nm,gpc); | |
2260 case STADECL: | |
2261 nsc = GVAR; | |
2262 ndsp = gpc; | |
2263 if (n->dsp!=-1) /* don't set dsp if initialized static */ | |
2264 n->dsp = ndsp; /* emit_data will override this */ | |
2265 if (stmode==EXTRN) | |
2266 nsc = EXTRN; | |
2267 else if (stmode==STATIC) | |
2268 nsc = STATIC; | |
2269 n->sc = nsc; | |
2270 if (stmode==LDECL) { | |
2271 n->nm = new_static_name(n->nm,'.'); | |
2272 } | |
2273 gpc +=sz; | |
2274 return n; | |
2275 case GSDECL: case LSDECL: | |
2276 disp += sz; | |
2277 return n; | |
2278 case GUDECL: case LUDECL: | |
2279 if (disp < sz) disp = sz; | |
2280 return n; | |
2281 case GTDECL: | |
2282 nsc = TYPE; | |
2283 gtypedefed=glist2((int)gnptr,gtypedefed); | |
2284 break; | |
2285 case LTDECL: | |
2286 nsc = TYPE; | |
2287 break; | |
2288 case ADECL: | |
2289 if(!integral(type)&&(car(type)==FUNCTION||car(type)==CODE)) { | |
2290 type=list2(POINTER,type); n->ty = type; | |
2291 } | |
2292 fnptr->dsp=list4(type,fnptr->dsp,(int)n,0); | |
2293 n->sc = LVAR; | |
2294 if(type==CHAR||type==UCHAR) { | |
2295 if (n->dsp==0) { | |
2296 n->dsp = args; | |
2297 if (endian) n->dsp += size_of_int-1; | |
2298 } | |
2299 args += size_of_int; | |
2300 } else if(type==SHORT||type==USHORT) { | |
2301 if (n->dsp==0) { | |
2302 n->dsp = args; | |
2303 if (endian) n->dsp += size_of_int-size_of_short; | |
2304 } | |
2305 args += size_of_int; | |
2306 } else if(type>0&&(type==UNION||type==STRUCT)) { | |
2307 n->dsp = args; | |
2308 args += ((sz+(size_of_int-1))&~(size_of_int-1)); | |
2309 } else { | |
2310 /* if (n->dsp==0) (argument list in ADECL is useless, type | |
2311 list can be found in type ) */ | |
2312 n->dsp = args; | |
2313 args += sz; | |
2314 } | |
2315 cadddr(fnptr->dsp)=sz; | |
2316 if(type==VOID) { | |
2317 } else { | |
2318 n->ty = type; | |
2319 } | |
2320 return n; | |
2321 case STAT: /* return (struct hoge)f() case? */ | |
2322 case LDECL: | |
2323 if (stmode==REGISTER) { | |
2324 if(scalar(type)) { | |
2325 ndsp = get_register_var(n); | |
2326 #if FLOAT_CODE | |
2327 } else if (type==FLOAT) { | |
2328 ndsp = get_dregister_var(n,0); | |
2329 } else if (type==DOUBLE) { | |
2330 ndsp = get_dregister_var(n,1); | |
2331 #endif | |
2332 #if LONGLONG_CODE | |
2333 } else if (type==LONGLONG||type==ULONGLONG) { | |
2334 ndsp = get_lregister_var(n); | |
2335 #endif | |
2336 } else error(DCERR); | |
2337 nsc = car(ndsp); | |
2338 ndsp = cadr(ndsp); | |
2339 } else { | |
2340 nsc = LVAR; | |
2341 ndsp = new_lvar(sz); | |
2342 } | |
2343 n->sc = nsc; | |
2344 n->dsp = ndsp; | |
2345 return n; | |
2346 default: | |
2347 error(DCERR); | |
2348 } | |
2349 n->sc = nsc; | |
2350 n->dsp = ndsp; | |
2351 if (stmode==EXTRN) | |
2352 n->sc = EXTRN; | |
2353 return n; | |
2354 } | |
2355 | |
2356 | |
2357 extern void | |
2358 emit_init_vars(void) | |
2359 { | |
2360 if (!init_vars) return; | |
2361 init_vars = reverse0(init_vars); | |
2362 while(init_vars) { | |
2363 gexpr(car(init_vars),0); | |
2364 init_vars = cadr(init_vars); | |
2365 } | |
2366 } | |
2367 | |
2368 static int | |
2369 str_init_eq() | |
2370 { | |
2371 // error(-1); // duplicate struct field value | |
2372 return 2; // allow override keep unique | |
2373 } | |
2374 | |
2375 extern int | |
2376 assign_data(int e, int t, NMTBL *n,int offset) | |
2377 { | |
329 | 2378 int ass,sz,bfd; |
327 | 2379 |
2380 if(mode==GDECL) { | |
2381 emit_data(e,t,n); | |
2382 } else if(mode==STADECL) { | |
2383 emit_data(e,t,n); | |
2384 } else if(mode==LDECL) { | |
329 | 2385 if (t==EMPTY) { |
2386 /* empty space in partial initialization */ | |
2387 return offset+cadr(e); | |
2388 } | |
327 | 2389 ass = assign_expr0( |
2390 (n->sc==REGISTER||n->sc==DREGISTER||n->sc==FREGISTER||n->sc==LREGISTER)? | |
2391 list3(n->sc,n->dsp,(int)n): | |
2392 list2(LVAR,n->dsp+offset), | |
2393 e,t,type); | |
2394 init_vars = list2(ass,init_vars); | |
2395 } else if(mode==SFDINIT) { | |
2396 decl_str_init=insert_ascend(decl_str_init, | |
2397 list4(offset,0,e,t),str_init_eq); | |
2398 } else { | |
2399 error(DCERR); | |
2400 return offset; | |
2401 } | |
329 | 2402 if (t>0&&car(t)==BIT_FIELD) { |
2403 sz = 0; | |
2404 bfd = caddr(t); /* bit_field_disp */ | |
2405 code_bit_field_disp(cadr(t),cadddr(t),&offset,&bfd,&sz); | |
2406 return offset+sz; | |
2407 } | |
327 | 2408 return offset+((t==EMPTY)?cadr(e):size(t)); |
2409 } | |
2410 | |
328 | 2411 extern void |
2412 data_closing(NMTBL *n) | |
2413 { | |
2414 emit_data_closing(n); | |
2415 } | |
2416 | |
2417 | |
327 | 2418 extern int |
2419 arg_reorder(int arg,int new_arg) | |
2420 { | |
2421 /* list4(type,fnptr->dsp,(int)n,size); */ | |
2422 int i,j,sz; | |
2423 int dsp = 0; | |
2424 NMTBL *n,*n1; | |
2425 | |
2426 /* f(a,b,c) { int c; short a; char* b;} case */ | |
2427 | |
2428 // fprintf(stderr,"arg_reorder old:\n"); | |
2429 // for(j=new_arg;j;j=cadr(j)) { | |
2430 // n=(NMTBL *)caddr(j); | |
2431 // fprintf(stderr,"dsp %d %s sz %d type %d\n",n->dsp,n->nm,cadddr(j),car(j)); | |
2432 // } | |
2433 // fprintf(stderr,"arg_reorder new:\n"); | |
2434 for(j=arg;j;j=cadr(j)) { | |
2435 n=(NMTBL *)caddr(j); | |
2436 for(i=new_arg;i;i=cadr(i)) { | |
2437 n1=(NMTBL *)caddr(i); | |
2438 if (!neqname(n1->nm,n->nm)) break; | |
2439 // if (n1==n) break; | |
2440 } | |
2441 // fprintf(stderr,"dsp %d %s %s sz %d type %d\n",dsp,n->nm,n1->nm,cadddr(i),car(i)); | |
2442 if (!i) { | |
2443 /* f(a,b,c) { int c; } case (what?!) */ | |
2444 i = j; | |
2445 } | |
2446 if(n->sc==LVAR) { | |
2447 n->dsp = dsp; | |
2448 car(j)=car(i); | |
2449 caddr(j)=caddr(i); | |
2450 cadddr(j)=sz= cadddr(i); | |
2451 if (sz==1||sz==size_of_short) sz = size_of_int; | |
2452 dsp += sz; | |
2453 } | |
2454 } | |
2455 // fprintf(stderr,"arg_reorder end:\n"); | |
2456 return arg; | |
2457 } | |
2458 | |
2459 | |
2460 static NMTBL str_ret; | |
2461 | |
2462 /* | |
2463 If function has structure return value, it has an extra | |
2464 argument for where to write the structure. It have to be | |
2465 a first argument. We add it here and we have to fix all arguments' | |
2466 offset. If it is the last value, we don't have to fix, but | |
2467 gcc has a first argument convention. | |
2468 */ | |
2469 | |
2470 extern void | |
2471 fdecl_struct(int fntype) | |
2472 { | |
2473 int type_save,mode_save,t,sz; | |
2474 NMTBL *n; | |
2475 | |
2476 t = cadr(fntype); | |
2477 if (t>0 && (car(t)==STRUCT||car(t)==UNION)) { | |
2478 mode_save = mode; | |
2479 mode=ADECL; | |
2480 type_save = type; | |
2481 /* extra argument for struct return */ | |
2482 /* this extra dummy arguments are set at calling sequence */ | |
2483 str_ret.nm = "str_ret"; str_ret.sc = EMPTY; | |
2484 str_ret.dsp = 0; str_ret.ty = 0; | |
2485 type=list2(POINTER,t); | |
2486 /* fix all argument's offset */ | |
2487 sz = size(type); | |
2488 for(t=fnptr->dsp;t;t=cadr(t)) { | |
2489 n=(NMTBL *)caddr(t); | |
2490 n->dsp += sz; | |
2491 } | |
2492 fnptr->dsp = reverse0(fnptr->dsp); | |
2493 if ((sz=size(cadr(fntype)))==-1) error(TYERR); | |
2494 else { | |
2495 args = 0; | |
2496 def(&str_ret); | |
2497 struct_return = list3(list2(LVAR,str_ret.dsp),sz,type); | |
2498 caddr(fnptr->ty) = glist2(POINTER,caddr(fnptr->ty)); | |
2499 } | |
2500 type = type_save; | |
2501 mode = mode_save; | |
2502 } else { | |
2503 struct_return = 0; | |
2504 fnptr->dsp = reverse0(fnptr->dsp); | |
2505 } | |
2506 } | |
2507 | |
2508 extern void | |
2509 fcheck(NMTBL *n) | |
2510 { | |
2511 if(!(mode==GDECL||mode==ADECL)|| | |
2512 (car(type)!=FUNCTION&&car(type)!=CODE)) error(DCERR); | |
2513 if (n->sc==EMPTY) { | |
2514 n->sc=EXTRN; | |
2515 n->ty=type; | |
2516 } else if(is_code(n)) compatible(cadr(n->ty),cadr(type)); | |
2517 else if(is_function(n)) compatible(cadr(n->ty),cadr(type)); | |
2518 else { | |
2519 error(DCERR); | |
2520 } | |
2521 } | |
2522 | |
2523 static void | |
2524 compatible(int t1, int t2) | |
2525 { | |
2526 if(integral(t1)) { | |
2527 if(t1!=t2) error(TYERR); | |
2528 } | |
2529 else if(car(t1)!=car(t2)) | |
2530 error(TYERR); | |
2531 else if((car(t1)==STRUCT || car(t1)==UNION) && cadr(t1)!=cadr(t2)) | |
2532 error(TYERR); | |
2533 else if(car(t1)==POINTER || car(t1)==ARRAY ||car(t1)==FUNCTION) | |
2534 compatible(cadr(t1),cadr(t2)); | |
2535 } | |
2536 | |
2537 extern int | |
2538 scalar(int t) | |
2539 { | |
2540 return(integral(t)||car(t)==POINTER); | |
2541 } | |
2542 | |
2543 extern int | |
2544 integral(int t) | |
2545 { | |
2546 return(t==INT||t==SIGNED||t==CHAR||t==UNSIGNED|| | |
2547 t==UCHAR||t==SHORT||t==USHORT||t==ENUM); | |
2548 } | |
2549 | |
2550 extern void | |
2551 checkret(void) | |
2552 { | |
2553 if (cslabel==0) { | |
2554 if (!control) error(-1); // no execute code in switch | |
2555 jmp(cslabel=fwdlabel()); | |
2556 } else if (retpending) { | |
2557 ret(); | |
2558 control=0; | |
2559 retpending=0; | |
2560 } | |
2561 if (lastexp) { | |
2562 gexpr(lastexp,0); | |
2563 lastexp = 0; | |
2564 } | |
2565 } | |
2566 | |
2567 | |
2568 extern void | |
2569 replace_return_struct(int func,int left) { | |
2570 int e = caddr(func); /* arg lists */ | |
2571 while(cadr(e)) e=cadr(e); /* find first arg */ | |
2572 e = car(e); /* return_struct arg */ | |
2573 cadr(e) = left; | |
2574 } | |
2575 | |
320 | 2576 |
327 | 2577 /* right value , get the value of the variable */ |
320 | 2578 |
327 | 2579 static int |
2580 indirect(int t,int e1) | |
2581 { | |
2582 int e2,e3,e4,offset; | |
2583 e2 = e1; | |
2584 offset = 0; | |
2585 e3 = cadr(e2); | |
2586 if (car(e2)==ADD) { | |
2587 e4=caddr(e2); | |
2588 if (car(e4)==CONST) { | |
2589 offset=cadr(e4); | |
2590 e1=e3; | |
2591 } | |
2592 } | |
2593 return list3(t,e1,offset); | |
2594 } | |
2595 | |
2596 extern int | |
2597 rvalue(int e) | |
2598 { | |
2599 int op; | |
2600 | |
2601 op = 0; | |
2602 switch(type) { | |
2603 case INT: break; | |
2604 case UNSIGNED: break; | |
2605 case VOID: break; | |
2606 case CHAR: op=COP; type=INT; break; | |
2607 case UCHAR: op=COP+US; type=UNSIGNED; break; | |
2608 case SHORT: op=SOP; type=SIGNED; break; | |
2609 case USHORT: op=SOP+US; type=UNSIGNED; break; | |
2610 case LONGLONG: op=LOP; break; | |
2611 case ULONGLONG: op=LOP+US; break; | |
2612 case FLOAT: op=FOP; break; | |
2613 case DOUBLE: op=DOP; break; | |
2614 case CODE: return e; | |
2615 default: | |
2616 if (integral(type)) break; | |
2617 switch(car(type)) { | |
2618 case ARRAY: | |
2619 type=list2(POINTER,cadr(type)); | |
2620 if(car(e)==INDIRECT) return cadr(e); | |
2621 return list2(ADDRESS,e); | |
2622 case STRUCT: case UNION: | |
2623 if(car(e)==RSTRUCT) return e; /* ??? */ | |
2624 return list3(RSTRUCT,e,cadr(type) /* size */); | |
2625 case FUNCTION: | |
2626 type=cadr(type); | |
2627 return e; | |
2628 case CODE: | |
2629 return e; | |
2630 case POINTER: | |
2631 break; | |
2632 case BIT_FIELD: | |
329 | 2633 return list3(RBIT_FIELD,rvalue(cadddr(e)),type); |
2634 /* byte rvalue, type */ | |
327 | 2635 type = cadr(e); |
2636 break; | |
2637 default: | |
2638 error(TYERR); | |
2639 } | |
2640 } | |
2641 switch(car(e)) { | |
2642 case GVAR: | |
2643 return(list2(RGVAR+op,cadr(e))); | |
2644 case LVAR: | |
2645 return(list2(RLVAR+op,cadr(e))); | |
2646 case INDIRECT: | |
2647 return(indirect(RINDIRECT+op,cadr(e))); | |
2648 default:return(e); /* idempotent case? */ | |
2649 } | |
2650 } | |
2651 | |
2652 extern int | |
2653 rvalue_t(int e,int t) | |
2654 { | |
2655 int stype = type; | |
2656 type = t; | |
2657 e = rvalue(e); | |
2658 type = stype; | |
2659 return e; | |
2660 } | |
2661 | |
2662 extern void | |
2663 lcheck(int e) | |
2664 { | |
2665 int t; | |
2666 if(!(scalar(type)||type==DOUBLE||type==FLOAT|| | |
2667 type==LONGLONG||type==ULONGLONG)|| | |
2668 (car(e)!=GVAR&&car(e)!=LVAR&&car(e)!=INDIRECT | |
2669 && car(e)!=REGISTER | |
2670 && car(e)!=DREGISTER | |
2671 && car(e)!=FREGISTER | |
2672 && car(e)!=LREGISTER) | |
2673 ) | |
2674 if ((t=car(type))<0 && t!=STRUCT && t!=UNION) | |
2675 error(LVERR); | |
2676 } | |
2677 | |
2678 extern int | |
2679 indop(int e) | |
2680 { | |
2681 if(type!=INT&&type!=UNSIGNED) { | |
2682 if(car(type)==POINTER) | |
2683 type=cadr(type); | |
2684 else if(car(type)==CODE || car(type)==FUNCTION) | |
2685 type=type; | |
2686 else error(TYERR); | |
2687 } else | |
2688 type= CHAR; | |
2689 if(car(e)==ADDRESS) | |
2690 return(cadr(e)); | |
2691 return(list2(INDIRECT,e)); | |
2692 } | |
2693 | |
2694 /* filed name search */ | |
2695 | |
2696 /* type = list4(s,disp,fields,tag_nptr); */ | |
2697 | |
2698 extern int | |
2699 search_struct_type(int type,char *name,int *dsp) | |
2700 { | |
2701 int t; | |
2702 NMTBL *nptr0; | |
2703 t = caddr(type); | |
2704 if (t==0) { | |
2705 nptr0=(NMTBL*)cadddr(type); | |
2706 t = caddr(type) = caddr(nptr0->ty); | |
2707 } | |
2708 for(;t;t = cadr(t)) { | |
2709 if (neqname((char *)caddr(t),name)==0) { | |
2710 *dsp = cadddr(t); | |
2711 return car(t); | |
2712 } | |
2713 } | |
2714 return 0; | |
2715 } | |
2716 | |
2717 extern int | |
2718 strop(int e,int ind) | |
2719 { | |
2720 int dsp = 0; | |
2721 | |
2722 if (ind) e = indop(rvalue(e)); | |
2723 if (integral(type)||(car(type)!=STRUCT && car(type)!=UNION)) | |
2724 e=rvalue(e); | |
2725 /* type = list4(s,disp,fields,tag_nptr); */ | |
2726 /* print_fields(caddr(type),"strop"); */ | |
2727 type = search_struct_type(type,nptr->nm,&dsp); | |
2728 if (!type) { error(TYERR); type=INT; return e; } | |
2729 if(dsp) { | |
2730 switch(car(e)) { | |
2731 case GVAR: | |
2732 e=list2(INDIRECT,list3(ADD,e,list2(CONST,dsp))); | |
2733 break; | |
2734 case LVAR: | |
2735 e=list2(LVAR,cadr(e) + dsp); | |
2736 break; | |
2737 case INDIRECT: | |
2738 e=list2(INDIRECT,list3(ADD,cadr(e),list2(CONST,dsp))); | |
2739 break; | |
2740 default: | |
2741 e=list2(INDIRECT,list3(ADD,e,list2(CONST,dsp))); | |
2742 } | |
2743 } else { | |
2744 switch(car(e)) { | |
2745 case GVAR: case LVAR: case INDIRECT: | |
2746 break; | |
2747 default: | |
2748 e=list2(INDIRECT,e); | |
2749 } | |
2750 } | |
2751 if (type>0&&car(type)==BIT_FIELD) { | |
2752 // n->ty = list4(BIT_FIELD,type,bit_offset, bit_size); | |
329 | 2753 e=list3(BIT_FIELD,e,type); |
327 | 2754 } |
2755 return e; | |
2756 } | |
2757 | |
2758 #if FLOAT_CODE | |
2759 /* binary floating computation */ | |
2760 | |
2761 #define DTYPE(dop) (dop==DOP?DOUBLE:FLOAT) | |
2762 | |
2763 static int | |
2764 fdbinop(int op, int e1, int e2, int t1, int t2, int dop) | |
2765 { | |
2766 double d1,d2,d; | |
2767 int b=0; | |
2768 | |
2769 type= DTYPE(dop); | |
2770 if (dop==DOP) { | |
2771 e1=double_value(e1,t1); | |
2772 e2=double_value(e2,t2); | |
2773 } else { | |
2774 e1=float_value(e1,t1); | |
2775 e2=float_value(e2,t2); | |
2776 } | |
2777 t1=t2=DTYPE(dop); | |
2778 if(car(e1)==dop+CONST&&car(e2)==dop+CONST) { | |
2779 d1=dcadr(e1); | |
2780 d2=dcadr(e2); | |
2781 switch(op) { | |
2782 case ADD: d=d1+d2; break; | |
2783 case SUB: d=d1-d2; break; | |
2784 case MUL: d=d1*d2;break; | |
2785 case DIV: | |
2786 if(!d2) error(EXERR);d=d1/d2;break; | |
2787 default: | |
2788 switch(op) { | |
2789 case GT: b=(d1>d2);break; | |
2790 case GE: b=(d1>=d2);break; | |
2791 case LT: b=(d1<d2);break; | |
2792 case LE: b=(d1<=d2);break; | |
2793 case EQ: b=(d1==d2);break; | |
2794 case NEQ: b=(d1!=d2);break; | |
2795 default: error(EXERR); | |
2796 } | |
2797 type = INT; | |
2798 return list2(CONST,b); | |
2799 } | |
2800 return dlist2(dop+CONST,d); | |
2801 } | |
2802 if(car(e1)==dop+CONST) { | |
2803 if ((op==SUB||op==ADD)&&dcadr(e1)==0.0) { | |
2804 return e2; | |
2805 } else if (op==MUL&&dcadr(e1)==1.0) { | |
2806 return e2; | |
2807 } else if (op==MUL&&-dcadr(e1)==1.0) { | |
2808 return list2(dop+MINUS,e2); | |
2809 } | |
2810 } | |
2811 if(car(e2)==dop+CONST) { | |
2812 if ((op==SUB||op==ADD)&&dcadr(e2)==0.0) { | |
2813 return e1; | |
2814 } | |
2815 if ((op==DIV||op==MUL)&&dcadr(e2)==1.0) { | |
2816 return e1; | |
2817 } | |
2818 if ((op==DIV||op==MUL)&&-dcadr(e2)==1.0) { | |
2819 return list2(DMINUS,e1); | |
2820 } | |
2821 if (op==SUB) { | |
2822 op=ADD; dcadr(e2) = -dcadr(e2); | |
2823 } else if(op==DIV) { | |
2824 if(dcadr(e2)==0.0) error(EXERR); | |
2825 op=MUL; dcadr(e2)=1/dcadr(e2); | |
2826 } | |
2827 } | |
2828 if ((op==ADD||op==MUL) && ( | |
2829 car(e1)==dop+CONST || | |
2830 car(e2)==DRLVAR || car(e2)==DRGVAR || | |
2831 car(e2)==FRLVAR || car(e2)==FRGVAR | |
2832 )) { | |
2833 return(list3(op+dop,e2,e1)); | |
2834 } | |
2835 if(op==LT) { | |
2836 type=INT; | |
2837 return(list3(GT+dop,e2,e1)); | |
2838 } else if(op==LE) { | |
2839 type=INT; | |
2840 return(list3(GE+dop,e2,e1)); | |
2841 } else if(op==GT||op==GE||op==EQ||op==NEQ) { | |
2842 type=INT; | |
2843 return(list3(op+dop,e1,e2)); | |
2844 } else if(op==ADD||op==SUB||op==MUL||op==DIV) | |
2845 return(list3(op+dop,e1,e2)); | |
2846 else { | |
2847 error(-1); | |
2848 return e1; | |
2849 } | |
2850 } | |
2851 | |
2852 static int | |
2853 dbinop(int op, int e1, int e2, int t1, int t2) | |
2854 { | |
2855 return fdbinop(op, e1, e2, t1, t2,DOP); | |
2856 } | |
2857 | |
2858 static int | |
2859 fbinop(int op, int e1, int e2, int t1, int t2) | |
2860 { | |
2861 return fdbinop(op, e1, e2, t1, t2,FOP); | |
2862 } | |
2863 | |
2864 #endif | |
2865 | |
2866 #if LONGLONG_CODE | |
2867 | |
2868 static int | |
2869 lbinop(int op, int e1, int e2, int t1, int t2) | |
2870 { | |
2871 int e=0; | |
2872 long long le1, le2; | |
2873 long long le = 0; | |
2874 int us = (t1==ULONGLONG&&t2==ULONGLONG); | |
2875 | |
2876 if (us||(t1==ULONGLONG&&(op==LSHIFT||op==RSHIFT))) { | |
2877 e1=ulonglong_value(e1,t1); | |
2878 e2=ulonglong_value(e2,t2); | |
2879 type = ULONGLONG; | |
2880 } else { | |
2881 e1=longlong_value(e1,t1); | |
2882 e2=longlong_value(e2,t2); | |
2883 type = LONGLONG; | |
2884 } | |
2885 if(car(e1)==LCONST&&car(e2)==LCONST) { | |
2886 le1=lcadr(e1); | |
2887 le2=lcadr(e2); | |
2888 switch(op) { | |
2889 case BOR: | |
2890 le=le1|le2;break; | |
2891 case EOR: | |
2892 le=le1^le2;break; | |
2893 case BAND: | |
2894 le=le1&le2;break; | |
2895 case ADD: | |
2896 le=le1+le2;break; | |
2897 case SUB: | |
2898 le=le1-le2;break; | |
2899 case MUL: | |
2900 le=le1*le2;break; | |
2901 case DIV: | |
2902 if(!le2) error(EXERR); | |
2903 if (us) le=(((unsigned long long )le1)/((unsigned long long )le2)); | |
2904 else e=(le1/le2); | |
2905 case MOD: | |
2906 if(!le2) error(EXERR); | |
2907 if (us) le=(((unsigned long long )le1)%((unsigned long long )le2)); | |
2908 else e=(le1%le2); | |
2909 case RSHIFT: | |
2910 if (t1==ULONGLONG) le=(((unsigned long long)le1)<<le2); else le=le1<<le2; | |
2911 break; | |
2912 case LSHIFT: | |
2913 if (t1==ULONGLONG) le=(((unsigned long long)le1)>>le2); else le=le1>>le2; | |
2914 break; | |
2915 default: | |
2916 switch(op) { | |
2917 case EQ: | |
2918 e=(le1==le2);break; | |
2919 case NEQ: | |
2920 e=(le1!=le2);break; | |
2921 case LT: | |
2922 le=le1;le1=le2;le2=le; | |
2923 case GT: | |
2924 if (us) e=((unsigned long long)le1>(unsigned long long)le2); | |
2925 else e=(le1>le2); | |
2926 break; | |
2927 case LE: | |
2928 le=le1;le1=le2;le2=le; | |
2929 case GE: | |
2930 if (us) e=((unsigned long long)le1>=(unsigned long long)le2); | |
2931 else e=(le1>=le2); | |
2932 break; | |
2933 default: | |
2934 error(-1); return list2(CONST,0); | |
2935 } | |
2936 type = INT; | |
2937 return list2(CONST,e); | |
2938 } | |
2939 return llist2(LCONST,le); | |
2940 } | |
2941 if(op==LT) { | |
2942 type = INT; return(list3(GT+LOP+us,e2,e1)); | |
2943 } else if(op==LE) { | |
2944 type = INT; return(list3(GE+LOP+us,e2,e1)); | |
2945 } else if(op==GT||op==GE||op==LT||op==LE) { | |
2946 type = INT; return(list3(op+LOP+us,e1,e2)); | |
2947 } | |
2948 if(op==SUB&&car(e2)==LCONST) { op=ADD; lcadr(e2)=-lcadr(e2); } | |
2949 if((op==ADD||op==MUL||op==BOR||op==EOR||op==BAND)&& | |
2950 (car(e1)!=LCONST) && ( | |
2951 car(e2)==LRGVAR||car(e2)==LRLVAR|| | |
2952 car(e2)==LURGVAR||car(e2)==LURLVAR | |
2953 )) { | |
2954 e=e1;e1=e2;e2=e;e=t1;t1=t2;t2=e; | |
2955 } | |
2956 if((op==MUL||op==DIV)&&car(e2)==LCONST&&lcadr(e2)==1) return e1; | |
2957 if(op==BOR||op==EOR||op==BAND||op==ADD||op==SUB||op==EQ||op==NEQ) | |
2958 return(list3(op+LOP,e1,e2)); | |
2959 if(op==LSHIFT||op==RSHIFT) return(list3(op+LOP+(t1==ULONGLONG),e1,e2)); | |
2960 return(list3(op+LOP+us,e1,e2)); | |
2961 } | |
320 | 2962 #endif |
2963 | |
327 | 2964 /* binary integer computation */ |
2965 | |
2966 extern int | |
2967 binop(int op, int e1, int e2, int t1, int t2) | |
2968 { | |
2969 int e=0; | |
2970 int us = (t1==UNSIGNED&&t2==UNSIGNED); | |
2971 | |
2972 if(t1>0&&car(t1)==POINTER) { e2= int_value(e2,t2); t2=INT; } | |
2973 else if(t2>0&&car(t2)==POINTER) { e1= int_value(e1,t1); t1=INT; } | |
2974 #if FLOAT_CODE | |
2975 else if(t1==DOUBLE||t2==DOUBLE) | |
2976 return dbinop(op,e1,e2,t1,t2); | |
2977 else if(t1==FLOAT||t2==FLOAT) | |
2978 return fbinop(op,e1,e2,t1,t2); | |
2979 #endif | |
2980 #if LONGLONG_CODE | |
2981 else if(t1==LONGLONG||t2==LONGLONG||t1==ULONGLONG||t2==ULONGLONG) | |
2982 return lbinop(op,e1,e2,t1,t2); | |
2983 #endif | |
2984 if(car(e1)==CONST&&car(e2)==CONST) { | |
2985 e1=cadr(e1); | |
2986 e2=cadr(e2); | |
2987 type= INT; | |
2988 switch(op) { | |
2989 case BOR: | |
2990 e=e1|e2;break; | |
2991 case EOR: | |
2992 e=e1^e2;break; | |
2993 case BAND: | |
2994 e=e1&e2;break; | |
2995 case ADD: | |
2996 if(integral(t1)) { | |
2997 if(integral(t2)) { | |
2998 e=e1+e2; | |
2999 } else { | |
3000 if(car(t2)!=POINTER) error(TYERR); | |
3001 e=size(cadr(t2))*e1+e2; | |
3002 type=t2; | |
3003 } | |
3004 } else { | |
3005 if(car(t1)!=POINTER) error(TYERR); | |
3006 e=e1+size(cadr(t1))*e2; | |
3007 type=t1; | |
3008 } | |
3009 break; | |
3010 case SUB: | |
3011 if(integral(t1)) { | |
3012 e=e1-e2; | |
3013 } else { | |
3014 if(car(t1)!=POINTER) error(TYERR); | |
3015 e=e1-size(cadr(t1))*e2; | |
3016 type=t1; | |
3017 } | |
3018 break; | |
3019 case MUL: | |
3020 e=e1*e2;break; | |
3021 case DIV: | |
3022 if(!e2) error(EXERR); | |
3023 if (us) e=(((unsigned)e1)/((unsigned)e2)); else e=e1/e2; | |
3024 break; | |
3025 case MOD: | |
3026 if(!e2) error(EXERR); | |
3027 if (us) e=(((unsigned)e1)%((unsigned)e2)); else e=e1%e2; | |
3028 break; | |
3029 case RSHIFT: | |
3030 if (t1==UNSIGNED) e=(((unsigned)e1)>>((unsigned)e2)); else e=e1>>e2; | |
3031 break; | |
3032 case LSHIFT: | |
3033 if (t1==UNSIGNED) e=(((unsigned)e1)<<((unsigned)e2)); else e=e1<<e2; | |
3034 break; | |
3035 case EQ: | |
3036 e=(e1==e2);break; | |
3037 case NEQ: | |
3038 e=(e1!=e2);break; | |
3039 case LT: | |
3040 e=e1;e1=e2;e2=e; | |
3041 case GT: | |
3042 if (us) e=(((unsigned)e1)>((unsigned)e2)); else e=(e1>e2); | |
3043 break; | |
3044 case LE: | |
3045 e=e1;e1=e2;e2=e; | |
3046 case GE: | |
3047 if (us) e=(((unsigned)e1)>=((unsigned)e2)); else e=(e1>=e2); | |
3048 break; | |
3049 e=(e1<=e2);break; | |
3050 default: error(-1); return list2(CONST,0); | |
3051 } | |
3052 return list2(CONST,e); | |
3053 } | |
3054 if(op==LT) { | |
3055 return(list3(GT+us,e2,e1)); | |
3056 } else if(op==LE) { | |
3057 return(list3(GE+us,e2,e1)); | |
3058 } else if(op==GT||op==GE||op==LT||op==LE) { | |
3059 return(list3(op+us,e1,e2)); | |
3060 } else if(op==EQ||op==NEQ) { | |
3061 return(list3(op,e1,e2)); | |
3062 } | |
3063 if(op==SUB&&car(e2)==CONST) { op=ADD; cadr(e2)=-cadr(e2); } | |
3064 if((op==ADD||op==MUL||op==BOR||op==EOR||op==BAND)&& | |
3065 (car(e1)!=CONST&& ( | |
3066 car(e2)==RGVAR||car(e2)==RLVAR|| | |
3067 car(e2)==URGVAR||car(e2)==URLVAR|| | |
3068 car(e2)==SRGVAR||car(e2)==SRLVAR|| | |
3069 car(e2)==SURGVAR||car(e2)==SURLVAR|| | |
3070 car(e2)==CRGVAR||car(e2)==CRLVAR|| | |
3071 car(e2)==CURGVAR||car(e2)==CURLVAR | |
3072 ))) { | |
3073 e=e1;e1=e2;e2=e;e=t1;t1=t2;t2=e; | |
3074 } | |
3075 if(op==ADD) { | |
3076 if(integral(t1)) { | |
3077 if(integral(t2)) { | |
3078 if(t1==INT) type=t2;else type=t1; | |
3079 return(list3(ADD,e1,e2)); | |
3080 } | |
3081 if(car(t2)!=POINTER) error(TYERR); | |
3082 e=binop(MUL,e1,list2(CONST,size(cadr(t2))),t1,INT); | |
3083 type=t2; | |
3084 return(list3(ADD,e,e2)); | |
3085 } | |
3086 if(car(t1)!=POINTER||!integral(t2)) error(TYERR); | |
3087 e=binop(MUL,e2,list2(CONST,size(cadr(t1))),t2,INT); | |
3088 type=t1; | |
3089 if (car(e)==CONST && cadr(e)==0) | |
3090 return(e1); | |
3091 if(car(e1)==ADDRESS&&car(e)==CONST&&car(cadr(e1))!=GVAR) | |
3092 return(list2(ADDRESS,list2(car(cadr(e1)), | |
3093 cadr(cadr(e1))+cadr(e)))); | |
3094 return(list3(ADD,e1,e)); | |
3095 } | |
3096 if(op==SUB) { | |
3097 if(integral(t1)) { | |
3098 if(!integral(t2)) error(TYERR); | |
3099 if(t1==INT) type=t2;else type=t1; | |
3100 return(list3(SUB,e1,e2)); | |
3101 } | |
3102 if(car(t1)!=POINTER) error(TYERR); | |
3103 if(integral(t2)) { | |
3104 e=binop(MUL,e2,list2(CONST,size(cadr(t1))),t2,INT); | |
3105 type=t1; | |
3106 return(list3(SUB,e1,e)); | |
3107 } | |
3108 if(car(t2)!=POINTER) | |
3109 error(TYERR); | |
3110 compatible(t1,t2); | |
3111 e=list3(SUB,e1,e2); | |
3112 e=binop(DIV,e,list2(CONST,size(cadr(t1))),UNSIGNED,INT); | |
3113 type= INT; | |
3114 return e; | |
3115 } | |
3116 if(!integral(t1)||!integral(t2)) error(TYERR); | |
3117 if(t1==INT) type=t2; else type=t1; /* ??? */ | |
3118 if((op==MUL||op==DIV)&&car(e2)==CONST&&cadr(e2)==1) return e1; | |
3119 if(op==BOR||op==EOR||op==BAND) return(list3(op,e1,e2)); | |
3120 if(op==LSHIFT||op==RSHIFT) return(list3(op+(t1==UNSIGNED?US:0),e1,e2)); | |
3121 // which ops remain? | |
3122 return(list3(op+us,e1,e2)); | |
3123 } | |
3124 | |
3125 /* coarse for function/code segments arguments */ | |
3126 | |
3127 extern int | |
3128 correct_type(int e,int t) | |
3129 { | |
3130 int t1; | |
3131 /* e = rvalue(e); */ | |
3132 if (type==FLOAT && t==DOTS) { t=DOUBLE;} // fall thru | |
3133 if (type==CHAR && t==DOTS) { t=INT;} // fall thru | |
3134 if (t==DOTS) return e; | |
3135 if (t==UNSIGNED) e = unsigned_value(e,type); | |
3136 else if (integral(t)) e = int_value(e,type); | |
3137 #if FLOAT_CODE | |
3138 else if (t==FLOAT) e = float_value(e,type); | |
3139 else if (t==DOUBLE) e = double_value(e,type); | |
3140 #endif | |
3141 #if LONGLONG_CODE | |
3142 else if (t==LONGLONG) e = longlong_value(e,type); | |
3143 else if (t==ULONGLONG) e = ulonglong_value(e,type); | |
3144 #endif | |
3145 else if ((t1=car(t))==STRUCT||t1==UNION) { | |
3146 if(size(t)!=size(type)) error(TYERR); | |
3147 } | |
3148 type = t; | |
3149 return e; | |
3150 } | |
3151 | |
3152 | |
3153 extern int | |
3154 cexpr(int e) | |
3155 { | |
3156 if (car(e) != CONST) error(CNERR); | |
3157 return (cadr(e)); | |
3158 } | |
3159 | |
329 | 3160 #define is_long_type(type) (type==LONGLONG||type==ULONGLONG) |
3161 | |
3162 #if BIT_FIELD_CODE | |
3163 static int | |
3164 bit_field(int e1,int t) | |
3165 { | |
3166 g_expr(e1); | |
3167 code_bit_field(cadr(t) /* type */, | |
3168 caddr(t) /* bit offset */, | |
3169 USE_CREG); | |
3170 return cadr(t); | |
3171 } | |
3172 | |
3173 static int | |
3174 bit_field_repl(int e1,int e2,int t) | |
3175 { | |
3176 /* e1 = e2 */ | |
3177 int lo = is_long_type(cadr(t)); | |
3178 g_expr(e2); | |
3179 if (lo) emit_lpush(); else emit_push(); | |
3180 g_expr(e1); | |
3181 code_bit_replace(USE_CREG,(e2=lo?emit_lpop():pop_register()), | |
3182 t /* type */,caddr(t) /* bit offset */); | |
3183 if (lo) emit_lpop_free(e2) else emit_pop_free(e2); | |
3184 return cadr(t); | |
3185 } | |
3186 | |
3187 static int | |
3188 bassop(int e2,int e3,int op,int t) | |
3189 { | |
3190 int type = cadr(t); | |
3191 /* if op==NULL e2 = e3 */ | |
3192 /* e2 = e2 op e3; */ | |
3193 if (car(e2)==LREGISTER||car(e2)==REGISTER||car(e2)==LVAR||car(e2)==GVAR) { | |
3194 g_expr(assign_expr0(e2, | |
3195 list4(BFD_REPL,e2,op?list3(op,rvalue_t(e2,t),e3):e3,t), | |
3196 type,type)); | |
3197 return type; | |
3198 } | |
3199 /* new = &e2 */ | |
3200 /* *new = *new op e3 */ | |
3201 n = list2(LVAR,new_lvar(size_of_int)); | |
3202 g_expr_u(assign_expr0(n,list2(ADDRESS,e2),INT,INT)); | |
3203 g_expr(assign_expr0(list2(INDIRECT,n), | |
3204 list4(BFD_REPL,n,op?list3(op,n,e3):e3,t), | |
3205 type,type)); | |
3206 free_lvar(cadr(n)); | |
3207 return type; | |
3208 } | |
3209 | |
3210 static int | |
3211 bassign(int e2,int e3,int t) | |
3212 { | |
3213 return bassop(e2,e3,0,t); | |
3214 } | |
3215 | |
3216 #endif | |
3217 | |
327 | 3218 /* temporal local variable free list */ |
3219 | |
3220 static int lvar_list,lvar_free_list; | |
3221 | |
3222 extern int | |
3223 new_lvar0(int sz) | |
3224 { | |
3225 return disp -= sz; | |
3226 } | |
3227 | |
3228 extern int | |
3229 new_lvar(int size) | |
3230 { | |
3231 int lvar,plvar; | |
3232 | |
3233 for (plvar = 0,lvar = lvar_free_list;lvar;lvar = cadr(lvar)) { | |
3234 if (caddr(lvar)==size) { | |
3235 if (plvar) cadr(plvar) = cadr(lvar); | |
3236 else lvar_free_list = cadr(lvar); | |
3237 break; | |
3238 } | |
3239 plvar = lvar; | |
3240 } | |
3241 if (!lvar) { | |
3242 lvar_list = glist3((lvar=new_lvar0(size)),lvar_list,size); | |
3243 } else { | |
3244 cadr(lvar) = lvar_list; lvar_list = lvar; | |
3245 lvar = car(lvar_list); | |
3246 } | |
3247 return lvar; | |
3248 } | |
3249 | |
3250 extern void | |
3251 free_lvar(int disp) | |
3252 { | |
3253 int lvar,plvar; | |
3254 | |
3255 for (plvar = 0,lvar = lvar_list;lvar;lvar = cadr(lvar)) { | |
3256 if (car(lvar)==disp) { | |
3257 if (plvar) cadr(plvar) = cadr(lvar); | |
3258 else lvar_list = cadr(lvar); | |
3259 break; | |
3260 } | |
3261 plvar = lvar; | |
3262 } | |
3263 if (!lvar) error(-1); | |
3264 cadr(lvar) = lvar_free_list; lvar_free_list = lvar; | |
3265 } | |
3266 | |
3267 extern void | |
3268 init_free_lvar_list() | |
3269 { | |
3270 int lvar; | |
3271 while((lvar=lvar_list)) { | |
3272 lvar_list=cadr(lvar_list); | |
3273 free_glist3(lvar); | |
3274 } | |
3275 while((lvar=lvar_free_list)) { | |
3276 lvar_free_list=cadr(lvar_free_list); | |
3277 free_glist3(lvar); | |
3278 } | |
3279 } | |
3280 | |
3281 extern void | |
3282 gen_code_enter(char *name) | |
3283 { | |
3284 code_enter(name); | |
3285 } | |
3286 | |
3287 extern void | |
3288 gen_code_enter1(int args) | |
3289 { | |
3290 code_enter1(args); | |
3291 } | |
3292 | |
3293 extern void | |
3294 gen_code_leave(char *name) | |
3295 { | |
3296 code_leave(name); | |
3297 } | |
3298 | |
3299 extern void | |
3300 gen_enter(char *name) | |
3301 { | |
3302 enter(name); | |
3303 } | |
3304 | |
3305 extern void | |
3306 gen_enter1() | |
3307 { | |
3308 enter1(); | |
3309 } | |
3310 | |
3311 extern void | |
3312 gen_leave(int control, char *name) | |
3313 { | |
3314 leave(control,name); | |
3315 } | |
3316 | |
3317 extern void | |
3318 gen_jmp(int l) | |
3319 { | |
3320 jmp(l); | |
3321 } | |
3322 | |
61 | 3323 /* end */ |