scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit ad164a259cf96e16ad311a3127578358cddbf432
parent 14ccdac412ca5138fc0492046ba62e9cada02b3c
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sun, 10 Aug 2014 18:10:30 +0200

Add stub of code generation for additions

This is only a stub of the generator code for additions that doesn't
check state of the register or only covers an addressability mode
(basically auto + const).

Diffstat:
Mcc2/cc2.h | 4++--
Mcc2/cgen.c | 107++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 103 insertions(+), 8 deletions(-)

diff --git a/cc2/cc2.h b/cc2/cc2.h @@ -31,8 +31,8 @@ typedef struct symbol { typedef struct node { char op; Type *type; - int8_t complex; - int8_t addable; + uint8_t complex; + uint8_t addable; union { Symbol *sym; int imm; diff --git a/cc2/cgen.c b/cc2/cgen.c @@ -25,7 +25,7 @@ genstack(Symbol *fun) } enum { - PUSH, POP, LD, ADD, RET, ADDI, LDI, ADDR + PUSH, POP, LD, ADD, RET, ADDI, LDI, ADDR, ADDX, ADCX }; enum { @@ -34,7 +34,8 @@ enum { char *opnames[] = { [PUSH] = "PUSH", [POP] = "POP", [LD] = "LD", [ADD] = "ADD", - [RET] = "RET" , [ADDI]= "ADD", [LDI] = "LD" + [RET] = "RET" , [ADDI]= "ADD", [LDI] = "LD", [ADDX] = "ADD", + [ADCX] = "ADC" }; char *regnames[] = { @@ -49,7 +50,8 @@ emit(char op, ...) { va_list va; uint8_t reg1, reg2; - short imm; + /* TODO: define a macro with the default integer type */ + short imm, off; char *label; va_start(va, op); @@ -71,6 +73,12 @@ emit(char op, ...) reg1 = va_arg(va, int); imm = va_arg(va, int); printf("\t%s\t%s,%hX\n", opnames[op], regnames[reg1], imm); + case ADDX: case ADCX: + reg1 = va_arg(va, int); + reg2 = va_arg(va, int); + off = va_arg(va, int); + printf("\t%s\t%s,(%s%+hd)\n", + opnames[op], regnames[reg1], regnames[reg2], off); break; case ADDR: label = va_arg(va, char *); @@ -82,9 +90,53 @@ emit(char op, ...) } void +xcgen(Node *np) +{ + Node *lp, *rp; + /* TODO: define a macro with the default integer type */ + unsigned imm, off; + + if (!np || np->complex == 0) + return; + lp = np->left; + rp = np->right; + if (!lp) { + xcgen(rp); + } else if (!rp) { + xcgen(lp); + } else { + Node *p, *q; + if (lp->complex > rp->complex) + p = lp, q = rp; + else + p = rp, q = lp; + xcgen(p); + xcgen(q); + } + + switch (np->op) { + case OADD: + if (lp->op == CONST) { + off = rp->u.sym->u.v.off; + imm = lp->u.imm; + emit(LDI, A, imm&0xFF); + emit(ADDX, A, IX, -(off+1)); + emit(LD, L, A); + emit(LDI, A, imm >> 8); + emit(ADCX, A, IX, -off); + emit(LD, H, A); + } + break; + default: + abort(); + } +} + +void cgen(Symbol *sym, Node *list[]) { extern char odebug; + Node *np; char frame = sym->u.f.stack != 0 || odebug; emit(ADDR, sym->u.f.name); @@ -96,6 +148,8 @@ cgen(Symbol *sym, Node *list[]) emit(LD, SP, HL); } + while (np = *list++) + xcgen(np); if (frame) { emit(LD, SP, IX); @@ -136,11 +190,52 @@ xaddable(Node *np) case CONST: np->addable = 20; break; - case OADD: - case OSUB: + case OADD: case OSUB: xaddable(lp); xaddable(rp); + switch (rp->addable) { + case 11: + switch (lp->addable) { + case 11: + case 20: + np->addable = 1; + goto complex; + default: + abort(); + } + case 20: + switch (lp->addable) { + case 20: + case 11: + np->addable = 1; + goto complex; + default: + abort(); + } + default: + abort(); + } + break; + default: + abort(); + } + +complex: + if (np->addable > 10) + return; + if (lp) + np->complex = lp->complex; + if (rp) { + int8_t d = rp->complex - np->complex; + + if (d == 0) + ++np->complex; + else if (d < 0) + np->complex = rp->complex; } + if (np->complex == 0) + ++np->complex; + return; } void @@ -148,6 +243,6 @@ genaddable(Node *list[]) { Node *np; - while ((np = *list++) != NULL) + while (np = *list++) xaddable(np); }