ref: d125d933343eea7ca85d4c37e6f224eaf1893184
parent: 5fb3dda9da04112b9d166df06c46ab0288a9bade
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Sun Oct 1 07:57:35 EDT 2017
[as-z80] Add (HL) addressing mode
--- a/as/as.h
+++ b/as/as.h
@@ -39,6 +39,10 @@
AIMM16,
AIMM32,
AIMM64,
+ AINDIR,
+ AINDEX,
+ ADIRECT,
+ AREG_OFF,
AMAX,
AREP = 128
};
--- a/as/expr.c
+++ b/as/expr.c
@@ -145,6 +145,8 @@
return fold(op, l, r);
if (l->addr == AIMM && r->addr == AIMM)
addr = AIMM;
+ else if (l->addr == AREG && r->addr == AIMM)
+ addr = AREG_OFF;
else
error("incorrect operand");
np = node(op, l, r);
@@ -327,6 +329,26 @@
next();
}
+Node *
+content(Node *np)
+{
+ int op;
+
+ switch (np->addr) {
+ case AREG:
+ op = AINDIR;
+ goto new_node;
+ case AREG_OFF:
+ op = AINDEX;
+ goto new_node;
+ case AIMM:
+ op = ADIRECT;
+ new_node:
+ return node(op, np, NULL);
+ }
+ return np;
+}
+
/*************************************************************************/
/* grammar functions */
/*************************************************************************/
@@ -336,7 +358,7 @@
static Node *
primary(void)
{
- int addr;
+ int addr, op;
Node *np;
switch (yytoken) {
@@ -354,6 +376,12 @@
np->sym = yylval.sym;
np->addr = addr;
next();
+ break;
+ case '(':
+ next();
+ np = or();
+ expect(')');
+ np = content(np);
break;
default:
unexpected();
--- a/as/target/gen.awk
+++ b/as/target/gen.awk
@@ -83,6 +83,8 @@
out = out "AREG_RCLASS"
} else if (match(a, /^regA/)) {
out = out "AREG_A"
+ } else if (match(a, /^indir_HL/)) {
+ out = out "AINDER_HL"
} else {
print "wrong arg", a
exit 1
--- a/as/target/x80/ins.c
+++ b/as/target/x80/ins.c
@@ -123,7 +123,7 @@
}
void
-r8(Op *op, Node **args)
+xx_r8_2(Op *op, Node **args)
{
Node *par1, *par2;
unsigned char buf[3];
@@ -131,7 +131,38 @@
par1 = args[0];
par2 = args[1];
+
memcpy(buf, op->bytes, n);
buf[n-1] |= reg2int(par2->sym->argtype);
+ emit(cursec, buf, n);
+}
+
+void
+r8_xx_2(Op *op, Node **args)
+{
+ Node *par1, *par2;
+ unsigned char buf[3];
+ int n = op->size;
+
+ par1 = args[0];
+ par2 = args[1];
+
+ memcpy(buf, op->bytes, n);
+ buf[n-1] |= reg2int(par2->sym->argtype) << 3;
+ emit(cursec, buf, n);
+}
+
+void
+r8_xx_1(Op *op, Node **args)
+{
+ Node *par1, *par2;
+ unsigned char buf[3];
+ int n = op->size;
+
+ par1 = args[0];
+ par2 = args[1];
+
+ memcpy(buf, op->bytes, n);
+ buf[n-1] |= reg2int(par1->sym->argtype) << 3;
emit(cursec, buf, n);
}
--- a/as/target/x80/proc.h
+++ b/as/target/x80/proc.h
@@ -31,6 +31,8 @@
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 */
+
+ AINDER_HL, /* (HL) */
};
extern int rclass(int reg);
--- a/as/target/x80/x80.dat
+++ b/as/target/x80/x80.dat
@@ -59,11 +59,17 @@
LD reg_r,imm8 2 0x06 r8_imm8 Z80,R800,GB80
LD reg_p,imm8 3 0xdd,0x06 r8_imm8 Z80,R800
LD reg_q,imm8 3 0xfd,0x06 r8_imm8 Z80,R800
+LD indir_HL,imm8 2 0x36 imm8 Z80,R800,GB80
+
LD reg_r,reg_r 1 0x40 r8_r8 Z80,R800,GB80
LD reg_p,reg_p 2 0xdd,0x40 r8_r8 Z80,R800
LD reg_q,reg_q 2 0xfd,0x40 r8_r8 Z80,R800
+LD indir_HL,reg_r 1 0x70 xx_r8_2 Z80,R800,GB80
+LD reg_r,indir_HL 1 0x46 r8_xx_1 Z80,R800,GB80
-ADD regA,reg_r 1 0x80 r8 Z80,R800,GB80
-ADD regA,reg_p 2 0xdd,0x80 r8 Z80,R800
-ADD regA,reg_q 2 0xfd,0x80 r8 Z80,R800
-ADD regA,imm8 2 0xc6 imm8 Z80,R800
+ADD regA,reg_r 1 0x80 xx_r8_2 Z80,R800,GB80
+ADD regA,reg_p 2 0xdd,0x80 xx_r8_2 Z80,R800
+ADD regA,reg_q 2 0xfd,0x80 xx_r8_2 Z80,R800
+ADD regA,imm8 2 0xc6 imm8 Z80,R800,GB80
+
+ADD regA,indir_HL 1 0x86 noargs Z80,R800,GB80
--- a/as/target/z80/proc.c
+++ b/as/target/z80/proc.c
@@ -65,6 +65,12 @@
--p;
np = *args++;
switch (arg & ~AREP) {
+ case AINDER_HL:
+ if (np->op != AINDIR)
+ return 0;
+ if (np->left->sym->argtype != AREG_HL)
+ return 0;
+ break;
case AREG_A:
if (np->op != AREG || np->sym->argtype != AREG_A)
return 0;