shithub: scc

Download patch

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: