shithub: scc

Download patch

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: