From: Alan Cox Date: Mon, 30 Oct 2017 17:42:47 +0000 (+0000) Subject: asz80: Z180 initial support, fix range checking, correct IX disp non abs X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=d04671a661fb82beabeacaef33e7d3c30f746d6f;p=FUZIX.git asz80: Z180 initial support, fix range checking, correct IX disp non abs 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 --- diff --git a/Applications/MWC/cmd/asz80/as.h b/Applications/MWC/cmd/asz80/as.h index 0aaeb398..7285af2e 100644 --- a/Applications/MWC/cmd/asz80/as.h +++ b/Applications/MWC/cmd/asz80/as.h @@ -75,6 +75,11 @@ #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. @@ -143,10 +148,10 @@ #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); diff --git a/Applications/MWC/cmd/asz80/as0.c b/Applications/MWC/cmd/asz80/as0.c index 28514fc3..d2295554 100644 --- a/Applications/MWC/cmd/asz80/as0.c +++ b/Applications/MWC/cmd/asz80/as0.c @@ -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); diff --git a/Applications/MWC/cmd/asz80/as1.c b/Applications/MWC/cmd/asz80/as1.c index de3d3524..d7645051 100644 --- a/Applications/MWC/cmd/asz80/as1.c +++ b/Applications/MWC/cmd/asz80/as1.c @@ -28,6 +28,14 @@ #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; } diff --git a/Applications/MWC/cmd/asz80/as2.c b/Applications/MWC/cmd/asz80/as2.c index a03d8e7c..f6975692 100644 --- a/Applications/MWC/cmd/asz80/as2.c +++ b/Applications/MWC/cmd/asz80/as2.c @@ -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) diff --git a/Applications/MWC/cmd/asz80/as3.c b/Applications/MWC/cmd/asz80/as3.c index 8125e050..dfbf3674 100644 --- a/Applications/MWC/cmd/asz80/as3.c +++ b/Applications/MWC/cmd/asz80/as3.c @@ -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; diff --git a/Applications/MWC/cmd/asz80/as4.c b/Applications/MWC/cmd/asz80/as4.c index 5e528c2b..dfa473e5 100644 --- a/Applications/MWC/cmd/asz80/as4.c +++ b/Applications/MWC/cmd/asz80/as4.c @@ -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) diff --git a/Applications/MWC/cmd/asz80/as6.c b/Applications/MWC/cmd/asz80/as6.c index 7f43a490..9cd6c52f 100644 --- a/Applications/MWC/cmd/asz80/as6.c +++ b/Applications/MWC/cmd/asz80/as6.c @@ -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 } };