ref: 23d465219fc21eae98468d5a5bcd82395934230a
parent: 461cca7fa3f4225b2aa9bbba5c4690cd90fa7513
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Sat Sep 30 04:17:13 EDT 2017
[as-z80] Add support for P and Q class registers These class of registers open a new world of new instructions.
--- a/as/target/gen.awk
+++ b/as/target/gen.awk
@@ -75,8 +75,12 @@
out = out "AIMM32"
} else if (match(a, /^imm64/)) {
out = "AIMM64"
- } else if (match(a, /^reg_8/)) {
- out = out "AREG_8"
+ } else if (match(a, /^reg_p/)) {
+ out = out "AREG_PCLASS"
+ } else if (match(a, /^reg_q/)) {
+ out = out "AREG_QCLASS"
+ } else if (match(a, /^reg_r/)) {
+ out = out "AREG_RCLASS"
} else {
print "wrong arg", a
exit 1
@@ -85,7 +89,7 @@
if (a ~ /^\+$/) {
return out "|AREP"
} else if (a != "") {
- print "wrong arg", a
+ print "wrong arg", a > "/dev/stderr"
exit 1
}
out = out ","
--- a/as/target/x80/ins.c
+++ b/as/target/x80/ins.c
@@ -1,33 +1,109 @@
static char sccsid[] = "@(#) ./as/target/z80/ins.c";
+#include <stdlib.h>
+#include <string.h>
+
#include "../../../inc/scc.h"
#include "../../as.h"
#include "proc.h"
int
-r8(int reg)
+rclass(int reg)
{
switch (reg) {
- case AREG_B: return 0;
- case AREG_C: return 1;
- case AREG_D: return 2;
- case AREG_E: return 3;
- case AREG_H: return 4;
- case AREG_L: return 5;
- case AREG_A: return 7;
- default: return -1;
+ case AREG_B:
+ case AREG_C:
+ case AREG_D:
+ case AREG_E:
+ case AREG_H:
+ case AREG_L:
+ case AREG_A:
+ return 1;
+ default:
+ return 0;
}
}
+int
+pclass(int reg)
+{
+ switch (reg) {
+ case AREG_B:
+ case AREG_C:
+ case AREG_D:
+ case AREG_E:
+ case AREG_IXH:
+ case AREG_IXL:
+ case AREG_A:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+int
+qclass(int reg)
+{
+ switch (reg) {
+ case AREG_B:
+ case AREG_C:
+ case AREG_D:
+ case AREG_E:
+ case AREG_IYH:
+ case AREG_IYL:
+ case AREG_A:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static int
+reg2int(int reg)
+{
+ switch (reg) {
+ case AREG_B: return 0;
+ case AREG_C: return 1;
+ case AREG_D: return 2;
+ case AREG_E: return 3;
+ case AREG_IXH:
+ case AREG_IYH:
+ case AREG_H: return 4;
+ case AREG_IXL:
+ case AREG_IYL:
+ case AREG_L: return 5;
+ case AREG_A: return 7;
+ default: abort();
+ }
+}
+
void
-r8_imm(Op *op, Node **args)
+r8_imm8(Op *op, Node **args)
{
Node *par1, *par2;
- unsigned char buf[2];
+ unsigned char buf[3];
+ int n = op->size;
- par1 = *args++;
- par2 = *args;
- buf[0] = *op->bytes | r8(par1->sym->argtype) << 3;
- buf[1] = par2->sym->value;
- emit(cursec, buf, 2);
+ par1 = args[0];
+ par2 = args[1];
+
+ memcpy(buf, op->bytes, n-1);
+ buf[n-1] = par2->sym->value;
+ buf[n-2] |= reg2int(par1->sym->argtype) << 3;
+ emit(cursec, buf, n);
+}
+
+void
+r8_r8(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 |
+ reg2int(par2->sym->argtype);
+ emit(cursec, buf, n);
}
--- a/as/target/x80/proc.h
+++ b/as/target/x80/proc.h
@@ -28,7 +28,11 @@
AREG_I,
AREG_AF_,
- AREG_8, /* class register for B, C, D, E, H, L and A */
+ 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 */
};
-extern int r8(int reg);
\ No newline at end of file
+extern int rclass(int reg);
+extern int pclass(int reg);
+extern int qclass(int reg);
--- a/as/target/x80/x80.dat
+++ b/as/target/x80/x80.dat
@@ -51,4 +51,14 @@
OTIR none 2 0xed,0xb3 noargs Z80,R800
OUTD none 2 0xed,0xab noargs Z80,R800
OTDR none 2 0xed,0xbb noargs Z80,R800
-LD reg_8,imm8 2 0x06 r8_imm Z80,R800,GB80
+
+# 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
+
+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 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
--- a/as/target/z80/proc.c
+++ b/as/target/z80/proc.c
@@ -65,10 +65,22 @@
--p;
np = *args++;
switch (arg & ~AREP) {
- case AREG_8:
+ case AREG_RCLASS:
if (np->op != AREG)
return 0;
- if (r8(np->sym->argtype) == -1)
+ if (!rclass(np->sym->argtype))
+ return 0;
+ break;
+ case AREG_PCLASS:
+ if (np->op != AREG)
+ return 0;
+ if (!pclass(np->sym->argtype))
+ return 0;
+ break;
+ case AREG_QCLASS:
+ if (np->op != AREG)
+ return 0;
+ if (!qclass(np->sym->argtype))
return 0;
break;
case AIMM8: