cgen.c (7571B)
1 #include <stdlib.h> 2 #include <string.h> 3 4 #include <scc/scc.h> 5 6 #include "../cc2.h" 7 #include "arch.h" 8 9 #define NLOCALS 16 10 11 struct local { 12 Symbol *sym; 13 struct local *next; 14 }; 15 16 static Symbol *retlabel; 17 static int offpar, offvar; 18 19 static Node *reguse[NPAIRS]; 20 static int upper[] = {[DE] = D, [HL] = H, [BC] = B, [IY] = IYH}; 21 static int lower[] = {[DE] = E, [HL] = L, [BC] = C, [IY] = IYL}; 22 static int pair[] = { 23 [A] = A, 24 [H] = HL, [L] = HL, [HL] = HL, 25 [B] = BC, [C] = BC, [BC] = BC, 26 [D] = DE, [E] = DE, [DE] = DE, 27 [IYL] = IY, [IYH] = IY, [IY] = IY 28 }; 29 30 static Node regs[] = { 31 [E] = { 32 .op = OMREG, 33 .type.size = 1, 34 .u.reg = E 35 }, 36 [D] = { 37 .op = OMREG, 38 .type.size = 1, 39 .u.reg = D 40 }, 41 [H] = { 42 .op = OMREG, 43 .type.size = 1, 44 .u.reg = H 45 }, 46 [L] = { 47 .op = OMREG, 48 .type.size = 1, 49 .u.reg = L 50 }, 51 [C] = { 52 .op= OMREG, 53 .type.size = 1, 54 .u.reg = C 55 }, 56 [B] = { 57 .op= OMREG, 58 .type.size = 1, 59 .u.reg = B 60 }, 61 [A] = { 62 .op= OMREG, 63 .type.size = 1, 64 .u.reg = A 65 }, 66 [IYL] = { 67 .op = OMREG, 68 .type.size = 1, 69 .u.reg = IYL 70 }, 71 [IYH] = { 72 .op = OMREG, 73 .type.size = 1, 74 .u.reg = IYH 75 }, 76 [DE] = { 77 .op = OMREG, 78 .type.size = 2, 79 .u.reg = DE 80 }, 81 [HL] = { 82 .op = OMREG, 83 .type.size = 2, 84 .u.reg = HL 85 }, 86 [BC] = { 87 .op = OMREG, 88 .type.size = 2, 89 .u.reg = BC 90 }, 91 [IX] = { 92 .op = OMREG, 93 .type.size = 2, 94 .u.reg = IX 95 }, 96 [IY] = { 97 .op = OMREG, 98 .type.size = 2, 99 .u.reg = IY 100 }, 101 [SP] = { 102 .op = OMREG, 103 .type.size = 2, 104 .u.reg = SP 105 } 106 }; 107 108 void 109 defpar(Symbol *sym) 110 { 111 unsigned align, size; 112 113 if (sym->kind != SREG && sym->kind != SAUTO) 114 return; 115 align = sym->type.align; 116 size = sym->type.size; 117 118 if (offpar == 0) 119 offpar = +2; 120 121 sym->u.off = offpar; 122 offpar += size; 123 offpar += offpar & 1; 124 } 125 126 void 127 defvar(Symbol *sym) 128 { 129 unsigned long align, size; 130 131 if (sym->kind != SREG && sym->kind != SAUTO) 132 return; 133 align = sym->type.align; 134 size = sym->type.size; 135 136 if (offvar == 0) 137 offvar = -2; 138 139 sym->u.off = offvar; 140 offvar -= size; 141 offvar -= offpar & 1; 142 } 143 144 static Node * 145 function(void) 146 { 147 Node aux; 148 149 memset(reguse, 0, sizeof(reguse)); 150 151 retlabel = newlabel(); 152 153 code(ASPUSH, NULL, ®s[IX], NULL); 154 code(ASMOV, ®s[IX], ®s[SP], NULL); 155 156 constnode(&aux, offvar + 2, &ptrtype); 157 code(ASMOV, ®s[HL], &aux, NULL); 158 code(ASADD, ®s[HL], ®s[SP], ®s[HL]); 159 code(ASMOV, ®s[SP], ®s[HL], NULL); 160 } 161 162 static void 163 efunction(void) 164 { 165 setlabel(retlabel); 166 code(ASMOV, ®s[SP], ®s[IX], NULL); 167 code(ASPOP, ®s[IX], NULL, NULL); 168 code(ASRET, NULL, NULL, NULL); 169 offpar = offvar = 0; 170 } 171 172 static void 173 allocreg(Node *np) 174 { 175 } 176 177 static void 178 store(Node *np) 179 { 180 } 181 182 static void 183 load(Node *np) 184 { 185 } 186 187 static void 188 spill(int reg) 189 { 190 Node *np, *r; 191 Symbol *sym; 192 int p, h, l; 193 194 if ((np = reguse[reg]) == NULL) 195 return; 196 r = ®s[reg]; 197 198 store(r); 199 p = pair[reg]; 200 l = lower[p]; 201 h = upper[p]; 202 203 if (reg >= NREGS) 204 reguse[l] = reguse[h] = NULL; 205 else 206 reguse[reg] = NULL; 207 208 if (!reguse[l] && !reguse[h]) 209 reguse[p] = NULL; 210 } 211 212 static void 213 use(int reg, Node *np) 214 { 215 reguse[reg] = np; 216 217 if (reg < NREGS) { 218 reguse[pair[reg]] = np; 219 } else if (reg >= NREGS && reg < NPAIRS) { 220 reguse[lower[reg]] = np; 221 reguse[upper[reg]] = np; 222 } else { 223 abort(); 224 } 225 } 226 227 static void 228 load2(Node *np, int dst) 229 { 230 long offl, offh; 231 Node low, high; 232 233 switch (np->op) { 234 case OAUTO: 235 offl = np->u.sym->u.off - 1; 236 offh = offl + 1; 237 break; 238 default: 239 abort(); 240 } 241 242 code(ASLD, ®s[lower[dst]], idxnode(&low, offl), NULL); 243 code(ASLD, ®s[upper[dst]], idxnode(&high, offh), NULL); 244 use(dst, np); 245 } 246 247 static void 248 moveto1(Node *np, int dst) 249 { 250 int src; 251 Node *pdst = ®s[dst]; 252 253 switch (np->op) { 254 case OAUTO: 255 code(ASLD, pdst, np, NULL); 256 break; 257 case OMREG: 258 src = np->u.reg; 259 if (src == dst) 260 return; 261 262 code(ASMOV, pdst, ®s[np->u.reg], NULL); 263 break; 264 default: 265 abort(); 266 } 267 268 use(dst, np); 269 } 270 271 static void 272 moveto2(Node *np, int dst) 273 { 274 int src; 275 Node aux; 276 277 switch (np->op) { 278 case OAUTO: 279 load2(np, dst); 280 break; 281 case OMREG: 282 src = np->u.reg; 283 if (src == dst) 284 return; 285 286 if (src == HL && dst == DE || src == DE && dst == HL) { 287 code(ASEXHL, ®s[HL], ®s[HL], ®s[DE]); 288 use(src, reguse[dst]); 289 } else { 290 code(ASMOV, ®s[lower[dst]], ®s[lower[src]], NULL); 291 code(ASMOV, ®s[upper[dst]], ®s[upper[src]], NULL); 292 } 293 break; 294 default: 295 abort(); 296 } 297 298 use(dst, np); 299 } 300 301 static void 302 moveto4(Node *np, int dst) 303 { 304 abort(); 305 } 306 307 static void 308 moveto8(Node *np, int dst) 309 { 310 abort(); 311 } 312 313 static void 314 moveto(Node *np, int reg) 315 { 316 switch (np->type.size) { 317 case 1: 318 moveto1(np, reg); 319 break; 320 case 2: 321 moveto2(np, reg); 322 break; 323 case 4: 324 moveto4(np, reg); 325 break; 326 case 8: 327 moveto4(np, reg); 328 break; 329 default: 330 abort(); 331 } 332 } 333 334 static int 335 cmpnode(Node *n1, Node *n2) 336 { 337 if (n1 == n2) 338 return 1; 339 if (!n1 || !n2) 340 return 0; 341 if (n1->op != n2->op) 342 return 0; 343 344 switch (n1->op) { 345 case OAUTO: 346 return n1->u.sym == n2->u.sym; 347 default: 348 return 0; 349 } 350 } 351 352 static void 353 move(Node *np, int reg) 354 { 355 int i; 356 357 switch (np->type.size) { 358 case 1: 359 for (i = A; i < NREGS; ++i) { 360 if (cmpnode(reguse[i], np)) 361 goto found; 362 } 363 break; 364 case 2: 365 for (i = AF; i < NPAIRS; ++i) { 366 if (cmpnode(reguse[i], np)) 367 goto found; 368 } 369 break; 370 case 4: 371 abort(); 372 case 8: 373 abort(); 374 } 375 376 moveto(np, reg); 377 return; 378 379 found: 380 moveto(®s[i], reg); 381 } 382 383 static int 384 whatacc(Node *np) 385 { 386 switch (np->type.size) { 387 case 1: 388 return A; 389 case 2: 390 return HL; 391 case 4: 392 return HLDE; 393 case 8: 394 return EXHLDE; 395 default: 396 abort(); 397 } 398 } 399 400 static Node * 401 acc(Node *np) 402 { 403 int reg = whatacc(np); 404 move(np, reg); 405 return ®s[reg]; 406 } 407 408 static Node * 409 rhs(Node *np) 410 { 411 switch (np->op) { 412 case OAUTO: 413 return acc(np); 414 case OMEM: 415 case OSNEG: 416 case OTMP: 417 case OCONST: 418 case OREG: 419 case OMOD: 420 case OSHL: 421 case OBAND: 422 case OBOR: 423 case OBXOR: 424 case OSHR: 425 case ODIV: 426 case OLT: 427 case OGT: 428 case OLE: 429 case OGE: 430 case OADD: 431 case OSUB: 432 case OMUL: 433 case OEQ: 434 case ONE: 435 case OCALL: 436 case OCALLE: 437 case OCAST: 438 case OASSIG: 439 case OASK: 440 case OCOMMA: 441 case OPTR: 442 case OADDR: 443 case OFIELD: 444 case OBUILTIN: 445 default: 446 abort(); 447 } 448 } 449 450 static Node * 451 field(Node *np, int islhs) 452 { 453 } 454 455 static Node * 456 lhs(Node *np) 457 { 458 switch (np->op) { 459 case OMEM: 460 case OAUTO: 461 return np; 462 case OPTR: 463 return rhs(np->left); 464 case OFIELD: 465 return field(np, 1); 466 default: 467 abort(); 468 } 469 } 470 471 static void 472 ret(Node *np) 473 { 474 Node aux; 475 476 if (np->left) 477 acc(np->left); 478 label2node(&aux, retlabel); 479 code(ASJP, NULL, &aux, NULL); 480 } 481 482 static Node * 483 cgen(Node *np) 484 { 485 Node aux, *next; 486 487 setlabel(np->label); 488 switch (np->op) { 489 case OBFUN: 490 function(); 491 break; 492 case OEFUN: 493 efunction(); 494 break; 495 case ONOP: 496 case OBLOOP: 497 case OELOOP: 498 break; 499 case OJMP: 500 label2node(&aux, np->u.sym); 501 code(ASJP, NULL, &aux, NULL); 502 break; 503 case OBRANCH: 504 /* TODO */ 505 break; 506 case ORET: 507 ret(np); 508 break; 509 case OBSWITCH: 510 /* TODO */ 511 break; 512 default: 513 rhs(np); 514 break; 515 } 516 return np; 517 } 518 519 /* 520 * This is strongly influenced by 521 * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps) 522 * calculate addresability as follows 523 * AUTO => 11 value+fp 524 * REG => 13 reg 525 * STATIC => 12 (value) 526 * CONST => 20 $value 527 */ 528 Node * 529 tsethi(Node *np) 530 { 531 Node *l, *r; 532 533 l = np->left; 534 r = np->right; 535 switch (np->op) { 536 case OAUTO: 537 np->address = 11; 538 break; 539 case OREG: 540 np->address = 13; 541 break; 542 case OMEM: 543 np->address = 12; 544 break; 545 case OCONST: 546 np->address = 20; 547 break; 548 default: 549 l = sethi(l); 550 r = sethi(r); 551 break; 552 } 553 554 np->left = l; 555 np->right = r; 556 557 return np; 558 } 559 560 void 561 genasm(void) 562 { 563 apply(cgen); 564 }