scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | README | LICENSE

commit f92c413f7a8a6629366edb729782f4de47ae3c97
parent 9a4a477ae954a2c0b251a5cbe3811a01fd996f6f
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sat, 16 Dec 2017 22:43:18 +0100

[as-z80] Add dd register class

dd register class covers BC, DE, HL and SP.

Diffstat:
Mas/target/gen.awk | 8+++++++-
Mas/target/x80/ins.c | 42+++++++++++++++++++++++++++++++++++++++++-
Mas/target/x80/proc.h | 3+++
Mas/target/x80/x80.dat | 5++++-
Mas/target/z80/proc.c | 12++++++++----
5 files changed, 63 insertions(+), 7 deletions(-)

diff --git a/as/target/gen.awk b/as/target/gen.awk @@ -81,12 +81,18 @@ function str2args(s, args, i, out, n) out = out "AREG_QCLASS" } else if (match(a, /^reg_r/)) { out = out "AREG_RCLASS" + } else if (match(a, /^reg_dd/)) { + out = out "AREG_DDCLASS" } else if (match(a, /^regA/)) { out = out "AREG_A" } else if (match(a, /^indir_HL/)) { out = out "AINDER_HL" - } else if (match(a, /^HL/)) { + } else if (match(a, /^regHL/)) { out = out "AREG_HL" + } else if (match(a, /^regIX/)) { + out = out "AREG_IX" + } else if (match(a, /^regIY/)) { + out = out "AREG_IY" } else if (match(a, /^sym/)) { out = out "ASYM" } else if (match(a, /^string/)) { diff --git a/as/target/x80/ins.c b/as/target/x80/ins.c @@ -58,6 +58,20 @@ qclass(int reg) } } +int +ddclass(int reg) +{ + switch (reg) { + case AREG_BC: + case AREG_DE: + case AREG_HL: + case AREG_SP: + return 1; + default: + return 0; + } +} + static int reg2int(int reg) { @@ -73,6 +87,13 @@ reg2int(int reg) case AREG_IYL: case AREG_L: return 5; case AREG_A: return 7; + case AREG_BC: return 0; + case AREG_DE: return 1; + case AREG_HL: + case AREG_IX: + case AREG_IY: return 2; + case AREG_AF: + case AREG_SP: return 3; default: abort(); } } @@ -108,7 +129,7 @@ imm8(Op *op, Node **args) } void -r_imm16(Op *op, Node **args) +imm16(Op *op, Node **args) { Node *par1, *par2; unsigned char buf[3]; @@ -168,3 +189,22 @@ r8_xx(Op *op, Node **args) buf[n-1] |= reg2int(par1->sym->argtype) << 3; emit(buf, n); } + +void +r16_imm16(Op *op, Node **args) +{ + Node *par1, *par2; + unsigned char buf[4]; + int n = op->size; + unsigned val; + + par1 = args[0]; + par2 = args[1]; + + memcpy(buf, op->bytes, n-1); + val = par2->sym->value; + buf[n-1] = val >> 8; + buf[n-2] = val; + buf[n-3] |= reg2int(par1->sym->argtype) << 3; + emit(buf, n); +} diff --git a/as/target/x80/proc.h b/as/target/x80/proc.h @@ -27,10 +27,12 @@ enum args { AREG_R, AREG_I, AREG_AF_, + AREG_SP, AREG_RCLASS, /* register class for B, C, D, E, H, L and A */ AREG_PCLASS, /* register class for B, C, D, E, IXH, IXL and A */ AREG_QCLASS, /* register class for B, C, D, E, IYH, IYL and A */ + AREG_DDCLASS, /* register class for BC, DE, HL and SP */ AINDER_HL, /* (HL) */ }; @@ -38,3 +40,4 @@ enum args { extern int rclass(int reg); extern int pclass(int reg); extern int qclass(int reg); +extern int ddclass(int reg); diff --git a/as/target/x80/x80.dat b/as/target/x80/x80.dat @@ -74,6 +74,7 @@ OTDR none 2 0xed,0xbb noargs Z80,R800 # p is any register from B, C, D, E, IXL, IXH, A # q is any register from B, C, D, E, IYL, IYH, A # r is any register from B, C, D, E, L, H, A +# dd is any register from BC, DE, HL, SP LD reg_r,imm8 2 0x06 r8_imm8 Z80,R800,GB80 LD reg_p,imm8 3 0xdd,0x06 r8_imm8 Z80,R800 @@ -86,7 +87,9 @@ LD reg_q,reg_q 2 0xfd,0x40 r8_r8 Z80,R800 LD indir_HL,reg_r 1 0x70 xx_r8 Z80,R800,GB80 LD reg_r,indir_HL 1 0x46 r8_xx Z80,R800,GB80 -LD HL,imm16 3 0x21 r_imm16 Z80,R800,GB80 +LD reg_dd,imm16 3 0x01 r16_imm16 Z80,R800,GB80 +LD regIX,imm16 4 0xdd,0x21 imm16 Z80,R800 +LD regIY,imm16 4 0xfd,0x21 imm16 Z80,R800 ADD regA,reg_r 1 0x80 xx_r8 Z80,R800,GB80 ADD regA,reg_p 2 0xdd,0x80 xx_r8 Z80,R800 diff --git a/as/target/z80/proc.c b/as/target/z80/proc.c @@ -67,7 +67,8 @@ match(Op *op, Node **args) if ((np = *args++) == NULL) return (arg & (AREP|AOPT)) != 0; - switch (arg & ~(AREP|AOPT)) { + arg &= ~(AREP|AOPT); + switch (arg) { case AINDER_HL: if (np->addr != AINDIR) return 0; @@ -75,7 +76,10 @@ match(Op *op, Node **args) return 0; break; case AREG_A: - if (np->addr != AREG || np->sym->argtype != AREG_A) + case AREG_HL: + case AREG_IY: + case AREG_IX: + if (np->addr != AREG || np->sym->argtype != arg) return 0; break; case AREG_RCLASS: @@ -96,10 +100,10 @@ match(Op *op, Node **args) if (!qclass(np->sym->argtype)) return 0; break; - case AREG_HL: + case AREG_DDCLASS: if (np->addr != AREG) return 0; - if (np->sym->argtype != AREG_HL) + if (!ddclass(np->sym->argtype)) return 0; break; case AIMM8: