ref: 9c39deaf29a1e655ab9d7fd35e6c6f86dc621bb9
parent: 551aa2e69a72c87ff63a356d38fa3c4fe668c219
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Sat Dec 16 17:43:18 EST 2017
[as-z80] Add dd register class dd register class covers BC, DE, HL and SP.
--- a/as/target/gen.awk
+++ b/as/target/gen.awk
@@ -81,12 +81,18 @@
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/)) {
--- a/as/target/x80/ins.c
+++ b/as/target/x80/ins.c
@@ -58,6 +58,20 @@
}
}
+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 @@
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 @@
}
void
-r_imm16(Op *op, Node **args)
+imm16(Op *op, Node **args)
{
Node *par1, *par2;
unsigned char buf[3];
@@ -166,5 +187,24 @@
memcpy(buf, op->bytes, n);
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);
}
--- a/as/target/x80/proc.h
+++ b/as/target/x80/proc.h
@@ -27,10 +27,12 @@
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 @@
extern int rclass(int reg);
extern int pclass(int reg);
extern int qclass(int reg);
+extern int ddclass(int reg);
--- a/as/target/x80/x80.dat
+++ b/as/target/x80/x80.dat
@@ -74,6 +74,7 @@
# 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 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
--- a/as/target/z80/proc.c
+++ b/as/target/z80/proc.c
@@ -67,7 +67,8 @@
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 @@
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 @@
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: