1#include <stdlib.h>2#include <string.h>34#include <scc/scc.h>56#include "../cc2.h"7#include "arch.h"89#define NLOCALS 161011struct local {12 Symbol *sym;13 struct local *next;14};1516static Symbol *retlabel;17static int offpar, offvar;1819static Node *reguse[NPAIRS];20static int upper[] = {[DE] = D, [HL] = H, [BC] = B, [IY] = IYH};21static int lower[] = {[DE] = E, [HL] = L, [BC] = C, [IY] = IYL};22static 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] = IY28};2930static Node regs[] = {31 [E] = {32 .op = OMREG,33 .type.size = 1,34 .u.reg = E35 },36 [D] = {37 .op = OMREG,38 .type.size = 1,39 .u.reg = D40 },41 [H] = {42 .op = OMREG,43 .type.size = 1,44 .u.reg = H45 },46 [L] = {47 .op = OMREG,48 .type.size = 1,49 .u.reg = L50 },51 [C] = {52 .op= OMREG,53 .type.size = 1,54 .u.reg = C55 },56 [B] = {57 .op= OMREG,58 .type.size = 1,59 .u.reg = B60 },61 [A] = {62 .op= OMREG,63 .type.size = 1,64 .u.reg = A65 },66 [IYL] = {67 .op = OMREG,68 .type.size = 1,69 .u.reg = IYL70 },71 [IYH] = {72 .op = OMREG,73 .type.size = 1,74 .u.reg = IYH75 },76 [DE] = {77 .op = OMREG,78 .type.size = 2,79 .u.reg = DE80 },81 [HL] = {82 .op = OMREG,83 .type.size = 2,84 .u.reg = HL85 },86 [BC] = {87 .op = OMREG,88 .type.size = 2,89 .u.reg = BC90 },91 [IX] = {92 .op = OMREG,93 .type.size = 2,94 .u.reg = IX95 },96 [IY] = {97 .op = OMREG,98 .type.size = 2,99 .u.reg = IY100 },101 [SP] = {102 .op = OMREG,103 .type.size = 2,104 .u.reg = SP105 }106};107108void109defpar(Symbol *sym)110{111 unsigned align, size;112113 if (sym->kind != SREG && sym->kind != SAUTO)114 return;115 align = sym->type.align;116 size = sym->type.size;117118 if (offpar == 0)119 offpar = +2;120121 sym->u.off = offpar;122 offpar += size;123 offpar += offpar & 1;124}125126void127defvar(Symbol *sym)128{129 unsigned long align, size;130131 if (sym->kind != SREG && sym->kind != SAUTO)132 return;133 align = sym->type.align;134 size = sym->type.size;135136 if (offvar == 0)137 offvar = -2;138139 sym->u.off = offvar;140 offvar -= size;141 offvar -= offpar & 1;142}143144static Node *145function(void)146{147 Node aux;148149 memset(reguse, 0, sizeof(reguse));150151 retlabel = newlabel();152153 code(ASPUSH, NULL, ®s[IX], NULL);154 code(ASMOV, ®s[IX], ®s[SP], NULL);155156 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}161162static void163efunction(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}171172static void173allocreg(Node *np)174{175}176177static void178store(Node *np)179{180}181182static void183load(Node *np)184{185}186187static void188spill(int reg)189{190 Node *np, *r;191 Symbol *sym;192 int p, h, l;193194 if ((np = reguse[reg]) == NULL)195 return;196 r = ®s[reg];197198 store(r);199 p = pair[reg];200 l = lower[p];201 h = upper[p];202203 if (reg >= NREGS)204 reguse[l] = reguse[h] = NULL;205 else206 reguse[reg] = NULL;207208 if (!reguse[l] && !reguse[h])209 reguse[p] = NULL;210}211212static void213use(int reg, Node *np)214{215 reguse[reg] = np;216217 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}226227static void228load2(Node *np, int dst)229{230 long offl, offh;231 Node low, high;232233 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 }241242 code(ASLD, ®s[lower[dst]], idxnode(&low, offl), NULL);243 code(ASLD, ®s[upper[dst]], idxnode(&high, offh), NULL);244 use(dst, np);245}246247static void248moveto1(Node *np, int dst)249{250 int src;251 Node *pdst = ®s[dst];252253 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;261262 code(ASMOV, pdst, ®s[np->u.reg], NULL);263 break;264 default:265 abort();266 }267268 use(dst, np);269}270271static void272moveto2(Node *np, int dst)273{274 int src;275 Node aux;276277 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;285286 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 }297298 use(dst, np);299}300301static void302moveto4(Node *np, int dst)303{304 abort();305}306307static void308moveto8(Node *np, int dst)309{310 abort();311}312313static void314moveto(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}333334static int335cmpnode(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;343344 switch (n1->op) {345 case OAUTO:346 return n1->u.sym == n2->u.sym;347 default:348 return 0;349 }350}351352static void353move(Node *np, int reg)354{355 int i;356357 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 }375376 moveto(np, reg);377 return;378379found:380 moveto(®s[i], reg);381}382383static int384whatacc(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}399400static Node *401acc(Node *np)402{403 int reg = whatacc(np);404 move(np, reg);405 return ®s[reg];406}407408static Node *409rhs(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}449450static Node *451field(Node *np, int islhs)452{453}454455static Node *456lhs(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}470471static void472ret(Node *np)473{474 Node aux;475476 if (np->left)477 acc(np->left);478 label2node(&aux, retlabel);479 code(ASJP, NULL, &aux, NULL);480}481482static Node *483cgen(Node *np)484{485 Node aux, *next;486487 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}518519/*520 * This is strongly influenced by521 * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps)522 * calculate addresability as follows523 * AUTO => 11 value+fp524 * REG => 13 reg525 * STATIC => 12 (value)526 * CONST => 20 $value527 */528Node *529tsethi(Node *np)530{531 Node *l, *r;532533 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 }553554 np->left = l;555 np->right = r;556557 return np;558}559560void561genasm(void)562{563 apply(cgen);564}