asz80: Z180 initial support, fix range checking, correct IX disp non abs
authorAlan Cox <alan@linux.intel.com>
Mon, 30 Oct 2017 17:42:47 +0000 (17:42 +0000)
committerAlan Cox <alan@linux.intel.com>
Mon, 30 Oct 2017 17:42:47 +0000 (17:42 +0000)
In particular

out (300),a  errors
ld (ix+300),a errors

ld (ix+FOO),a generates a relocation entry for FOO

That means you can

FOO .equ 21

ld (ix+FOO),a

or even define FOO as an external

Applications/MWC/cmd/asz80/as.h
Applications/MWC/cmd/asz80/as0.c
Applications/MWC/cmd/asz80/as1.c
Applications/MWC/cmd/asz80/as2.c
Applications/MWC/cmd/asz80/as3.c
Applications/MWC/cmd/asz80/as4.c
Applications/MWC/cmd/asz80/as6.c

index 0aaeb39..7285af2 100644 (file)
 #define        TSUB    0x1E00                  /* sub et al */
 #define TSEGMENT 0x1F00                        /* segments by number */
 #define TEXPORT 0x2000                 /* symbol export */
+#define TNOP180        0x2100                  /* Z180 immediate */
+#define TTST180        0x2200                  /* TST m/g/(hl) */
+#define TIMMED8        0x2300                  /* TSTIO m */
+#define        TMUL    0x2400                  /* MUL */
+#define TIO180 0x2500                  /* IN0/OUT0 */
 
 /*
  * Registers.
 #define INVALID_ID     21
 #define REG_MUST_BE_C  22
 #define DIVIDE_BY_ZERO 23
-#define INVALID_CONSTANT 24
+#define CONSTANT_RANGE  24
 #define DATA_IN_BSS     25
 #define SEGMENT_OVERFLOW 26
-
+#define REQUIRE_Z180   27
 
 typedef        uint16_t        VALUE;          /* For symbol values */
 
@@ -196,6 +201,7 @@ extern  int segment;
 extern int     debug_write;
 extern char    *fname;
 extern int     noobj;
+extern int     cpu_flags;
 
 extern void asmline(void);
 extern void asmld(void);
@@ -227,6 +233,7 @@ extern void outabsolute(int);
 extern void outsegment(int);
 extern void outaw(uint16_t);
 extern void outab(uint8_t);
+extern void outabchk(uint16_t);
 extern void outraw(ADDR *);
 extern void outrab(ADDR *);
 extern void outeof(void);
index 28514fc..d229555 100644 (file)
@@ -23,7 +23,7 @@ int   line;
 jmp_buf        env;
 int    debug_write = 1 ;
 int    noobj;
-
+int    cpu_flags = OA_8080_Z80;
 
 /*
  * Make up a file name.
@@ -65,6 +65,9 @@ int main(int argc, char *argv[])
                if (*p == '-') {
                        while ((c = *++p) != 0) {
                                switch (c) {
+                               case '1':
+                                       cpu_flags |= OA_8080_Z180;
+                                       break;
                                default:
                                        fprintf(stderr, "Bad option %c\n", c);
                                        exit(BAD);
index de3d352..d764505 100644 (file)
 #define        OPJR    0x20                    /* Opcode: jr cc base */
 #define        OPRET   0xC0                    /* Opcode: ret cc base */
 
+static void require_z180(void)
+{
+       if (!(cpu_flags & OA_8080_Z180)) {
+               cpu_flags |= OA_8080_Z180;
+               err('1',REQUIRE_Z180);
+       }
+}
+
 /*
  * Assemble one line.
  * The line in in "ib", the "ip"
@@ -166,6 +174,9 @@ loop:
                        outab(0);
                break;
 
+       case TNOP180:
+               require_z180();
+               /* Fall through */
        case TNOP:
                if ((opcode&0xFF00) != 0)
                        outab(opcode >> 8);
@@ -268,13 +279,37 @@ loop:
                outab(OPIM|(value<<3));
                break;
 
+       case TIMMED8:
+               require_z180();
+               getaddr(&a1);
+               istuser(&a1);
+               outab(opcode);
+               outabchk(value);
+               break;
+
+       case TIO180:    /* out0 and in0 */
+               require_z180();
+               getaddr((opcode & 1) ? &a2 : &a1);
+               comma();
+               getaddr((opcode & 1) ? &a1 : &a2);
+               if ((a1.a_type&TMMODE) == TBR && a2.a_type == (TUSER|TMINDIR)) {
+                       reg = a1.a_type & TMREG;
+                       if (reg == M || reg == IX || reg == IY)
+                               aerr(INVALID_REG);
+                       outab(opcode << 8);
+                       outab(opcode | (reg << 3));
+                       outabchk(a2.a_value);
+                       break;
+               }
+               aerr(INVALID_REG);
+
        case TIO:
                getaddr(opcode==OPIN ? &a1 : &a2);
                comma();
                getaddr(opcode==OPIN ? &a2 : &a1);
                if (a1.a_type==(TBR|A) && a2.a_type==(TUSER|TMINDIR)) {
                        outab(opcode);
-                       outab(a2.a_value);
+                       outabchk(a2.a_value);
                        break;
                }
                if ((a1.a_type&TMMODE)==TBR && a2.a_type==(TBR|TMINDIR|C)) {
@@ -374,11 +409,30 @@ loop:
                        aerr(INVALID_REG);
                break;
 
+       case TMUL:
+               getaddr(&a1);
+               if ((a1.a_type & TMMODE) == TWR) {
+                       reg = a1.a_type & TMREG;
+                       switch(reg) {
+                               case IX:
+                               case IY:
+                               case AF:
+                               case AFPRIME:
+                                       aerr(INVALID_REG);
+                                       break;
+                       }
+                       outab(opcode >> 8);
+                       outab(opcode|(reg << 3));
+                       break;
+               }
+               aerr(INVALID_REG);
+               break;
+
        case TSUB:
                getaddr(&a1);
                if (a1.a_type == TUSER) {
                        outab(opcode | OPSUBI);
-                       outab(a1.a_value);
+                       outabchk(a1.a_value);
                        break;
                }
                if ((a1.a_type&TMMODE) == TBR) {
@@ -397,7 +451,7 @@ loop:
                if (a1.a_type == (TBR|A)) {
                        if (a2.a_type == TUSER) {
                                outab(opcode | OPSUBI);
-                               outab(a2.a_value);
+                               outabchk(a2.a_value);
                                break;
                        }
                        if ((a2.a_type&TMMODE) == TBR) {
@@ -535,7 +589,7 @@ void asmld(void)
                if (mdst == TBR) {
                        outab(0x06|(rdst<<3));          /* ld r8,#n */
                        if (indexap != NULL)
-                               outab(indexap->a_value);
+                               outrab(indexap);
                        outrab(&src);
                        return;
                }
index a03d8e7..f697569 100644 (file)
@@ -43,9 +43,10 @@ static char *etext[] = {
        "invalid id",
        "must be C",
        "divide by 0",
-       "invalid constant",
+       "constant out of range",
        "data in BSS",
-       "segment overflow"
+       "segment overflow",
+       "Z180 instruction"
 };
 
 static void errstr(uint8_t code)
index 8125e05..dfbf367 100644 (file)
@@ -305,9 +305,9 @@ void expr3(ADDR *ap, int c)
                else if (c>='a' && c<='f')
                        c -= 'a'-10;
                else
-                       err('n', INVALID_CONSTANT);
+                       err('n', INVALID_CONST);
                if (c >= radix)
-                       err('n', INVALID_CONSTANT);
+                       err('n', INVALID_CONST);
                value = radix*value + c;
        }
        ap->a_type  = TUSER;
index 5e528c2..dfa473e 100644 (file)
@@ -29,10 +29,9 @@ void outpass(void)
                        obh.o_size[i] = truesize[i];
                }
                obh.o_magic = 0;
-               obh.o_arch = OA_Z80;
+               obh.o_arch = OA_8080;
                obh.o_flags = 0;
-               /* Will need changing if we add .Z180 and the Z180 ops */
-               obh.o_cpuflags = 0;
+               obh.o_cpuflags = cpu_flags;
                obh.o_symbase = base;
                obh.o_dbgbase = 0;      /* for now */
                /* Number the symbols for output */
@@ -109,6 +108,13 @@ void outab(uint8_t b)
                err('o', SEGMENT_OVERFLOW);
 }
 
+void outabchk(uint16_t b)
+{
+       if (b > 255)
+               err('o', CONSTANT_RANGE);
+       outab(b);
+}
+
 void outrab(ADDR *a)
 {
        /* FIXME: handle symbols */
@@ -125,7 +131,7 @@ void outrab(ADDR *a)
                        outbyte(a->a_sym->s_number >> 8);
                }
        }
-       outab(a->a_value);
+       outabchk(a->a_value);
 }
 
 static void putsymbol(SYM *s, FILE *ofp)
index 7f43a49..9cd6c52 100644 (file)
@@ -126,6 +126,18 @@ SYM        sym[] = {
        {       0,      "xor",          TSUB,           0x00A8  },
        {       0,      "or",           TSUB,           0x00B0  },
        {       0,      "cp",           TSUB,           0x00B8  },
+       /* Z180 */
+       {       0,      "slp",          TNOP180,        0xED76  },
+       {       0,      "otim",         TNOP180,        0xED83  },
+       {       0,      "otimr",        TNOP180,        0xED93  },
+       {       0,      "otdm",         TNOP180,        0xED8B  },
+       {       0,      "otdmr",        TNOP180,        0xED9B  },
+       {       0,      "tst",          TTST180,        0xED04  },
+       {       0,      "tstio",        TIMMED8,        0xED74  },
+       {       0,      "mlt",          TMUL,           0xED4C  },
+       {       0,      "in0",          TIO180,         0xED00  },
+       {       0,      "out0",         TIO180,         0xED01  },
+       /* The joys of ld */
        {       0,      "ld",           TLD,            XXXX    }
 };