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:
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: