scc

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

commit a0758440d875f800b9cd5e9d726cc568a8633a43
parent a7dba1661a8d960eac3e8f7f315a50b23673cc39
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Tue, 16 Sep 2014 17:56:21 +0200

Move addresable nodes to register

This is a first attemp of generating some code. It only allocate
register for a value, but it doesn't save to stack or anything similar.
This code is only a stub.

Diffstat:
Mcc2/cc2.h | 2++
Mcc2/cgen.c | 115++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
2 files changed, 111 insertions(+), 6 deletions(-)

diff --git a/cc2/cc2.h b/cc2/cc2.h @@ -90,6 +90,8 @@ enum nerrors { #define OCPL '~' #define OCOMMA ',' +#define ADDABLE 10 + extern void error(unsigned nerror, ...); extern void genaddable(Node *list[]); extern void generate(Symbol *sym, Node *list[]); diff --git a/cc2/cgen.c b/cc2/cgen.c @@ -11,24 +11,25 @@ enum { - PUSH, POP, LD, ADD, RET, ADDI, LDI, ADDR, ADDX, ADCX, LDX + PUSH, POP, LD, ADD, RET, ADDI, LDI, ADDR, ADDX, ADCX, LDX, + LDFX }; enum { - AF, HL, DE, BC, IX, IY, SP, A, F, B, C, D, E, H, L, IXL, IXH, IYL, IYH + A, B, C, D, E, H, L, IYL, IYH, NREGS, IXL, IXH, F, I, SP, AF, HL, DE, BC, IX, IY }; char *opnames[] = { [PUSH] = "PUSH", [POP] = "POP", [LD] = "LD", [ADD] = "ADD", [RET] = "RET" , [ADDI]= "ADD", [LDI] = "LD", [ADDX] = "ADD", - [ADCX] = "ADC" , [LDX] = "LD" + [ADCX] = "ADC" , [LDX] = "LD" , [LDFX] = "LD" }; char *regnames[] = { [AF] = "AF", [HL] = "HL", [DE] = "DE", [BC] = "BC", [IX] = "IX", [IY] = "IY", [SP] = "SP", [A] = "A", [F] = "F", [B] = "B", [C] = "C", [D] = "D", [E] = "E", [H] = "H", [L] = "L", - [IXL]= "IXL",[IXH]= "IXH",[IYL]= "IYL",[IYH]= "IYH" + [IXL]= "IXL",[IXH]= "IXH",[IYL]= "IYL",[IYH]= "IYH", [I] = "I" }; void @@ -60,6 +61,13 @@ emit(char op, ...) imm = va_arg(va, int); printf("\t%s\t%s,%d\n", opnames[op], regnames[reg1], imm); break; + case LDFX: + reg1 = va_arg(va, int); + reg2 = va_arg(va, int); + off = va_arg(va, int); + printf("\t%s\t%s,(%s%+d)\n", + opnames[op], regnames[reg1], regnames[reg2], off); + break; case LDX: reg1 = va_arg(va, int); off = va_arg(va, int); @@ -83,16 +91,111 @@ emit(char op, ...) va_end(va); } -void +static char +upper(char pair) +{ + switch (pair) { + case HL: return H; + case BC: return B; + case DE: return D; + case IY: return IYH; + } +} + +static char +lower(char pair) +{ + switch (pair) { + case HL: return L; + case DE: return E; + case BC: return B; + case IY: return IYL; + } +} + +static char +allocreg(Node *np) +{ + static bool regs[NREGS], *bp; + + switch (np->type->size) { + case 1: + for (bp = regs; bp < &regs[NREGS]; ++bp) { + if (*bp) + continue; + *bp = 1; + return bp - regs; + } + /* TODO: Move variable to stack using PUSH/POP */ + break; + case 2: + if (!regs[H] && !regs[L]) { + regs[H] = regs [L] = 1; + return HL; + } + if (!regs[D] && !regs[E]) { + regs[D] = regs [E] = 1; + return DE; + } + if (!regs[C] && !regs[B]) { + regs[B] = regs [C] = 1; + return BC; + } + if (!regs[IYL] && !regs[IYH]) { + regs[IYL] = regs [IYH] = 1; + return IY; + } + /* TODO: Move variable to stack using PUSH/POP */ + } + abort(); +} + +static void +move(Node *np) +{ + Type *tp = np->type; + Symbol *sym; + char reg; + + switch (np->op) { + case AUTO: + sym = np->u.sym; + switch (tp->size) { + case 1: + emit(LDFX, allocreg(np), sym->u.v.off); + break; + case 2: + reg = allocreg(np); + emit(LDFX, lower(reg), IX, sym->u.v.off); + emit(LDFX, upper(reg), IX, sym->u.v.off+1); + break; + case 4: + case 8: + default: + abort(); + } + break; + default: + abort(); + } +} + +static void cgen(Node *np) { Node *lp, *rp; TINT imm; - if (!np || np->complex == 0) + if (!np) return; + lp = np->left; rp = np->right; + if (np->addable >= ADDABLE) { + move(np); + return; + } + if (!lp) { cgen(rp); } else if (!rp) {