/* * * These are the Z80 instruction handlers * */ #include "asm.h" #define fix(token) ((((token) & 3) * 2) | 0x70) #define isreg(mask,reg) (((reg) & 7) | (mask)) #define idreg(mask,reg) ((((reg) & 7) << 3) | (mask)) #define iregp(mask,reg) ((((reg) & 3) << 4) | (mask)) #define getiy() getix() extern int xrefyes; extern int (*z80_func[])(); static char ma6[] = { 0xeb, 0xe3, 0xeb, 0 }; static char ma7[] = { 0xe1, 0xe3, 0 }; static char la1[7] = { 0xf5, 0x7c, 0x75, 0x23, 0x77, 0xf1, 0 }; static char la2[7] = { 0xf5, 0x7e, 0x23, 0x66, 0x6f, 0xf1, 0 }; void set_ascdno() { ascdno = 0; } /*. ************************************************************************* * * * ptok * * * * This routine will process the tokens set up by GTOR and GTOD, * * and sees if the tokens are correct syntax. If so, it will bail * * out to the group handlers for the tokens. * * * * * * * ************************************************************************* */ void ptok() { int c, token; #if DEBUG printf("ptok\n"); #endif c = ortkbf[0] & ~CONBIT; if (false_condit && c != CONDTK) return; /* * combine the tokens into one for lookup */ token = (opbyt1 & 0xf0) | ((opbyt2 >> 4) & 0xf); #if DEBUG printf("token: %x\top1: %x\top2: %x\n", token, opbyt1, opbyt2); printf("od1: %x\tod2: %x\n", odint1, odint2); printf("ortkbf[0]: %x\tortkbf[1]: %x\n", ortkbf[0] & ~CONBIT, ortkbf[1]); #endif if (c == ORGTOK) { porg(token); return; } (*z80_func[(int) c])(token); /* * adjust the pc counter for whatever happened */ adjarc(); } /*. ************************************************************************* * * * * * This is the DEFS handler. * * * * * * * ************************************************************************* */ void grp7() { #if DEBUG printf("group 7\n"); #endif if (filflg) { if (odint1 > ACBSIZ) { odint1 = ACBSIZ; eror('O'); } if(is_on(AFISEC)) adrefc[mode] += odint1; else { ascdno = odint1; clrbuf(asscod, ascdno); } } else { asscod[1] = (odint1 >> 8) & BYTMSK; asscod[0] = odint1 & BYTMSK; adrefc[mode] += odint1; if(is_on(AFISEC)) ascdno = 0; else { turn_on(AFADIS | AFORG); outchg = O7H; } } if (adrefc[mode] & (unsigned) 0xff0000 && passno == 2) { eror('o'); printl("Warning: address counter wrap with DEFS of %d on (%d)/%d\n", odint1, filenum, sline - 1); adrefc[mode] &= (unsigned) 0xffff; } } /*. ************************************************************************* * * * * * Handler for the single and double byte instructions that * * have no operand. * * * * * * * ************************************************************************* */ void grp11() { #if DEBUG printf("group 11\n"); #endif if (ortkbf[0] == DBTOK) asscod[ascdno++] = TWOPRE; asscod[ascdno++] = ortkbf[1]; } /*. ************************************************************************* * * * * * Handler for AND, OR, XOR, CP and SUB. * * * * * * * ************************************************************************* */ void grp12(token) register int token; { #if DEBUG printf("group 12\n"); #endif if (token == 0x70) { if (opbyt1 >= 0x78) opbyt1 = makhl(opbyt1); asscod[ascdno++] = isreg(ortkbf[1], opbyt1) | 0x80; } else if (token == INTTOK) { asscod[ascdno++] = ortkbf[1] | 0xC6; chkof(odint1); asscod[ascdno++] = odint1; } else if (token == 0xd0) { if ((opbyt1 = ckus1()) > 0xfd) return; goto okay; } else if ((token == 0x40) || (token == 0xb0)) { okay: indpf(opbyt1); asscod[ascdno++] = ortkbf[1] | 0x86; disbt(opbyt1, odint1); } else dnops(); } /*. ************************************************************************* * * * * * Handler for INC and DEC. * * * * * * * ************************************************************************* */ void grp13(token) register int token; { #if DEBUG printf("group 13\n"); #endif if (token == 0x70) { if (opbyt1 >= 0x78) opbyt1 = makhl(opbyt1); opbyt2 = (ortkbf[1] & 1) | 4; asscod[ascdno++] = idreg(opbyt2, opbyt1); } else if (token == 0x10) { if (opbyt1 == 0x17) { dnops(); return; } indpf(opbyt1); opbyt2 = (ortkbf[1] & 8) | 3; asscod[ascdno++] = iregp(opbyt2, opbyt1); } else if (token == 0xd0) { if ((opbyt1 = ckus1()) > 0xfd) return; goto okay; } else if (token == 0x40 || token == 0xb0) { okay: indpf(opbyt1); asscod[ascdno++] = (ortkbf[1] & 1) | 0x34; disbt(opbyt1, odint1); } else dnops(); } /*. ************************************************************************* * * * * * Handler for IM instrustion. * * * * * * * ************************************************************************* */ void grp14() { #if DEBUG printf("group 14\n"); #endif if (odint1 > 2) { dnops(); return; } if (odint1 != 0) ++odint1; asscod[ascdno++] = TWOPRE; asscod[ascdno++] = idreg(0x46, odint1); } /*. ************************************************************************* * * * * * Handler for the rotate and shift groups * * * * * * * ************************************************************************* */ void grp15(token) register int token; { int b; int hl; #if DEBUG printf("group 15\n"); #endif b = opbyt1; hl = odint1; if (token == 0x70) { if (b >= 0x78) b = makhl(b); asscod[ascdno++] = 0xCB; asscod[ascdno++] = isreg(ortkbf[1], b); } else if (token == 0xd0) { if ((b = ckus1()) > 0xfd) return; goto okay; } else if ((token == 0x40) || (token == 0xb0)) { okay: indpf(b); asscod[ascdno++] = 0xCB; disbt(b, hl); asscod[ascdno++] = ortkbf[1] | 0x6; } else dnops(); } /*. ************************************************************************* * * * * * Handler for BIT, SET, and RES. * * * * * * * ************************************************************************* */ void grp16(token) register int token; { int b, c, de, hl; #if DEBUG printf("group 16\n"); #endif b = opbyt1; c = opbyt2; hl = odint1; de = odint2; if (token == 0x97) { if (hl > 7) { dnops(); return; } if (c >= 0x78) c = makhl(c); asscod[ascdno++] = 0xCB; b = isreg(ortkbf[1], c); asscod[ascdno++] = idreg(b, hl); } else if (token == 0x9d) { if ((c = ckus2()) > 0xfd) return; goto okay; } else if (token == 0x94 || token == 0x9b) { okay: if (hl > 7) { dnops(); return; } indpf(c); asscod[ascdno++] = 0xCB; disbt(c, de); asscod[ascdno++] = idreg(ortkbf[1] | 0x6, hl); } else dnops(); } /*. ************************************************************************* * * * * * Handler for JP. * * * * * * * ************************************************************************* */ void grp17(token) register int token; { #if DEBUG printf("group 17\n"); #endif if (token == 0x40) { indpf(opbyt1); asscod[ascdno++] = 0xE9; } else if (token == 0x89) { asscod[ascdno++] = idreg(0xc2, opbyt1); appwd(odint2); } else if (token == 0x90) { asscod[ascdno++] = 0xC3; appwd(odint1); } else dnops(); } /*. ************************************************************************* * * * * * Handler for JR. * * * * * * * ************************************************************************* */ void grp18(tok) register int tok; { #if DEBUG printf("group 18\n"); #endif register int token,ob1,od1,od2; register unsigned char *ptr; token = tok; ob1 = opbyt1; od1 = odint1; od2 = odint2; ptr = asscod; if (token == 0x89) { if (ob1 & 4) { dnops(); return; } od2 = cdis(od2); *ptr++ = idreg(0x20, ob1); *ptr++ = od2; } else if (token == 0x90) { od1 = cdis(od1); *ptr++ = 0x18; *ptr++ = od1; } else dnops(); ascdno = 2; mathfg |= MFJRDJ; } /*. ************************************************************************* * * * * * Handler for DJNZ. * * * * * * * ************************************************************************* */ void grp19() { #if DEBUG printf("group 19\n"); #endif asscod[ascdno++] = 0x10; asscod[ascdno++] = cdis(odint1); mathfg |= MFJRDJ; } /*. ************************************************************************* * * * * * Handler for CALL. * * * * * * * ************************************************************************* */ void grp20(token) register int token; { #if DEBUG printf("group 20\n"); #endif register unsigned char *ptr; ptr = &asscod[ascdno]; if (token == 0x89) { *ptr++ = idreg(0xc4, opbyt1); *ptr++ = odint2; *ptr = (odint2 >> 8); ascdno += 3; } else if (token == 0x90) { *ptr++ = 0xCD; *ptr++ = odint1; *ptr = (odint1 >> 8); ascdno += 3; } else dnops(); } /*. ************************************************************************* * * * * * Handler for RET. * * * * * * * ************************************************************************* */ void grp21(token) register int token; { #if DEBUG printf("group 21\n"); #endif if (token == 0) asscod[ascdno++] = 0xC9; else if (token == 0x80) asscod[ascdno++] = idreg(0xc0, opbyt1); else dnops(); } /*. ************************************************************************* * * * * * Handler for RST. * * * * * * * ************************************************************************* */ void grp22() { short hl; #if DEBUG printf("group 22\n"); #endif hl = odint1; if (hl < 8) hl = hl * 8; if (hl % 8) { dnops(); return; } asscod[ascdno++] = (hl | 0xC7); } /*. ************************************************************************* * * * * * Handler for IN. * * * * * * * ************************************************************************* */ void grp23(token) register int token; { int b, de; #if DEBUG printf("group 23\n"); #endif b = opbyt1; de = odint2; if (token == 0x7d) { if (de >= 256) { dnops(); return; } if (b != 0x77) { dnops(); return; } asscod[ascdno++] = 0xdb; asscod[ascdno++] = de; } else if (token == 0x7a) { if (b >= 0x78) b = makhl(b); asscod[ascdno++] = TWOPRE; if (b == 0x76) { asscod[ascdno++] = 0x70; return; } asscod[ascdno++] = idreg(0x40, b); } else if (token == 0xea) { asscod[ascdno++] = TWOPRE; asscod[ascdno++] = 0x70; } else dnops(); } /*. ************************************************************************* * * * * * Handler for OUT. * * * * * * * ************************************************************************* */ void grp24(token) register int token; { int c, hl; #if DEBUG printf("group 24\n"); #endif c = opbyt2; hl = odint1; if (token == 0xa7) { if (c >= 0x78) c = makhl(c); asscod[ascdno++] = TWOPRE; asscod[ascdno++] = idreg(0x41, c); } else if (token == 0xd7) { if (hl >= 256) { dnops(); return; } if (c != 0x77) { dnops(); return; } asscod[ascdno++] = 0xD3; asscod[ascdno++] = hl; } else dnops(); } /*. ************************************************************************* * * * * * Handler for PUSH and POP. * * * * * * * ************************************************************************* */ void grp25(token) register int token; { #if DEBUG printf("group 25\n"); #endif if (token == 0) { if (ortkbf[1] != 0xc1) { dnops(); return; } appwd(0x3333); } else if (token == 0x10) { if (opbyt1 == 0x13) { dnops(); return; } indpf(opbyt1); asscod[ascdno++] = iregp(ortkbf[1], opbyt1); } else dnops(); } /*. ************************************************************************* * * * * * Handler for the EX instruction (including macros). * * * * * * * ************************************************************************* */ void grp26(token) register int token; { int b, c; #if DEBUG printf("group 26\n"); #endif b = opbyt1; c = opbyt2; if (token == 0x51) { if ((c & 3) == 2) { indpf(c); asscod[ascdno++] = 0xE3; return; } if (c == 0x11) { savit(ma6); return; } if (c == 0x13) { dnops(); return; } asscod[ascdno++] = 0xE3; opbyt1 = opbyt2; ortkbf[1] = 0xc5; grp25(0x10); asscod[ascdno++] = 0xE5; ortkbf[1] = 0xc1; grp25(0x10); savit(ma7); } else if (token == 0x1e) { if (b != 0x17) { dnops(); return; } asscod[ascdno++] = 0x8; } else if (token == 0x11) { if ((b == 0x11) && (c == 0x12)) { asscod[ascdno++] = 0xEB; return; } if ((b == 0x12) && (c == 0x11)) { asscod[ascdno++] = 0xEB; return; } if (b == c) { dnops(); return; } if ((b == 0x13) || (c == 0x13)) { dnops(); return; } if (c < 0x12) { opbyt1 = b; ortkbf[1] = 0xc5; grp25(0x10); opbyt1 = c; grp25(0x10); opbyt1 = b; ortkbf[1] = 0xc1; grp25(0x10); opbyt1 = c; grp25(0x10); return; } ortkbf[1] = 0xc5; grp25(0x10); grp26(0x51); ortkbf[1] = 0xc1; grp25(0x10); return; } else dnops(); } /*. ************************************************************************* * * * * * Handler for ADC and SBC instructions. * * * * * * * ************************************************************************* */ void grp27(token) register int token; { int b, c, de; #if DEBUG printf("group 27\n"); #endif b = opbyt1; c = opbyt2; de = odint2; if (token == 0x77) { if (b != 0x77) { dnops(); return; } if (c >= 0x78) c = makhl(c); b = (ortkbf[1] & 0x10) | 0x88; asscod[ascdno++] = isreg(b, c); } else if (token == 0x79) { if (b != 0x77) { dnops(); return; } asscod[ascdno++] = (ortkbf[1] & 0x10) | 0xCE; chkofr(de); asscod[ascdno++] = de; } else if (token == 0x7d) { if ((c = ckus2()) > 0xfd) return; goto okay; } else if (token == 0x74 || token == 0x7b) { okay: if (b != 0x77) { dnops(); return; } indpf(c); asscod[ascdno++] = (ortkbf[1] & 0x10) | 0x8E; disbt(c, de); } else if (token == 0x11) { if (b != 0x12 || c >= 0x14) { dnops(); return; } asscod[ascdno++] = TWOPRE; asscod[ascdno++] = iregp((ortkbf[1] & 0x8) | 0x42, c); } else dnops(); } /*. ************************************************************************* * * * * * Handler for ADD instructions. * * * * * * * ************************************************************************* */ void grp28(tok) register int tok; { #if DEBUG printf("group 28\n"); #endif register int token, b, c; token = tok; b = opbyt1; c = opbyt2; if (token == 0x77) { if (b != 0x77) { dnops(); return; } if (c >= 0x78) c = makhl(c); asscod[ascdno++] = isreg(0x80, c); } else if (token == 0x79) { if (b != 0x77) { dnops(); return; } indpf(c); asscod[ascdno++] = 0xC6; chkofr(odint2); asscod[ascdno++] = odint2; } else if (token == 0x7d) { if ((c = ckus2()) > 0xfd) return; goto okay; } else if (token == 0x74 || token == 0x7b) { okay: if (b != 0x77) { dnops(); return; } indpf(c); asscod[ascdno++] = 0x86; disbt(c, odint2); } else if (token == 0x11) { if ((b & 3) != 2) { dnops(); return; } if ((c & 3) == 2 && b != c) { dnops(); return; } indpf(b); asscod[ascdno++] = iregp(0x9, c); } else dnops(); } /*. ************************************************************************* * * * * * Handler for the LD instruction. * * * * * * * ************************************************************************* */ void grp29(tok) int tok; { #if DEBUG printf("group 29\n"); #endif register int token, op1, op2, od1, od2; register unsigned char *ptr; int b, c, x, de, hl; token = tok; ptr = &asscod[ascdno]; op1 = opbyt1; op2 = opbyt2; od1 = odint1; od2 = odint2; b = opbyt1; c = opbyt2; hl = odint1; de = odint2; if (token == 0x77) /* r,r */ { if (op1 >= 0x78) { if (op2 > 0x74 && op2 != 0x77) { dnops(); return; } if (op1 & 8) { *ptr++ = (op1 & 4) ? 0xfd : 0xdd; adroff++; } op1 = (op1 & 1) + 0x74; } else if (op2 >= 0x78) { if ((op1 > 0x74) && (op1 !=0x77)) { dnops(); return; } if (op2 & 8) { *ptr++ = (op2 & 4) ? 0xfd : 0xdd; adroff++; } op2 = (op2 & 1) + 0x74; } op2 = isreg(0x40, op2); *ptr++ = idreg(op2, op1); ascdno = ptr - &asscod[0]; return; } else if (token == 0x79) /* r,N */ { if (op1 >= 0x78) { if (op1 & 8) { *ptr++ = (op1 & 4) ? 0xfd : 0xdd; adroff++; } op1 = (op1 & 1) + 0x74; } *ptr++ = idreg(0x6, op1); chkofr(od2); *ptr++ = od2; ascdno = ptr - &asscod[0]; return; } else if (token == 0x19 || token == 0x1a) { if (op1 == 0x17) { dnops(); return; } if (op1 & 8) { *ptr++ = (op1 & 4) ? 0xfd : 0xdd; adroff++; } *ptr++ = iregp(0x1, op1); *ptr++ = od2; *ptr++ = (od2 >> 8); ascdno = ptr - &asscod[0]; return; } else if (token == 0x1d) /* rp,(NN) */ { if (op1 == 0x17) { dnops(); return; } if ((op1 & 3) == 2) { if (op1 & 8) { *ptr++ = (op1 & 4) ? 0xfd : 0xdd; adroff++; } *ptr++ = 0x2A; *ptr++ = od2; *ptr++ = (od2 >> 8); ascdno = ptr - &asscod[0]; return; } *ptr++ = TWOPRE; adroff++; *ptr++ = iregp(0x4b, op1); *ptr++ = od2; *ptr = (od2 >> 8); ascdno += 4; return; } else if (token == 0x76) /* A,(BC)|(DE) */ { if (op1 != 0x77) { dnops(); return; } *ptr = iregp(0x0A, op2); ascdno += 1; return; } else if (token == 0x72) /* A,I|R */ { if (op1 != 0x77) { dnops(); return; } *ptr++ = TWOPRE; *ptr = idreg(0x57, op2); ascdno += 2; return; } else if (token == 0x7d) /* A,(nn) */ { if (is_on(AFUSNG|AFUSPR) == (AFUSNG|AFUSPR)) { opbyt2 = getiy(); grp29(0x74); return; } if (op1 != 0x77) { dnops(); return; } *ptr++ = 0x3A; *ptr++ = od2; *ptr = (od2 >> 8); ascdno += 3; return; } else if (token == 0x67) /* (BC)|(DE),A */ { if (op2 != 0x77) { dnops(); return; } *ptr = iregp(0x2, op1); ascdno += 1; return; } else if (token == 0xd9) /* (isect),n */ { if (is_on(AFUSNG|AFUSPR) != (AFUSNG|AFUSPR)) { dnops(); return; } b = getix(); /* fall into next case */ goto g1; } else if (token == 0x49 || token == 0xb9) { g1: indpf(b); asscod[ascdno++] = 0x36; disbt(b, hl); chkofr(de); asscod[ascdno++] = de; return; } else if (token == 0x47 || token == 0xb7) { if (c >= 0x78) { dnops(); return; } indpf(b); asscod[ascdno++] = isreg(0x70, c); disbt(b,hl); return; } else if (token == 0x27) /* I|R,A */ { if (op2 != 0x77) { dnops(); return; } *ptr++ = TWOPRE; *ptr = idreg(0x47, op1); ascdno += 2; return; } else if (token == 0xd7) { if (is_on(AFUSNG|AFUSPR) == (AFUSNG|AFUSPR)) { opbyt1 = getix(); grp29(0x47); return; } if (op2 != 0x77) { dnops(); return; } *ptr++ = 0x32; *ptr++ = od1; *ptr = (od1 >> 8); ascdno += 3; return; } else if (token == 0xd1) /* (nn),rp */ { if (op2 == 0x17) { dnops(); return; } if ((op2 & 3) == 2) { if (op2 & 8) { *ptr++ = (op2 & 4) ? 0xfd : 0xdd; adroff++; } *ptr++ = 0x22; *ptr++ = od1; *ptr++ = (od1 >> 8); ascdno = ptr - &asscod[0]; return; } *ptr++ = TWOPRE; adroff++; *ptr++ = iregp(0x43, op2); *ptr++ = od1; *ptr = (od1 >> 8); ascdno += 4; return; } else if (token == 0x74 || token == 0x7b) { if (b >= 0x78) { dnops(); return; } indpf(c); asscod[ascdno++] = idreg(0x46, b); disbt(c,de); return; } else if (token == 0x11) /* SP,HL|IX|IY */ { if (b == 0x13) { if ((c & 3) != 2) { dnops(); return; } indpf(c); asscod[ascdno++] = 0xF9; return; } if ((b | c) < 0x14) { if (c == 0x13) { dnops(); return; } opbyt1 = fix(b); opbyt2 = fix(c); grp29(0x77); opbyt1 = fix(b) + 1; opbyt2 = fix(c) + 1; grp29(0x77); return; } if (b >= 0x20 || c == 0x13) { dnops(); return; } indpf(c); asscod[ascdno++] = iregp(0xC5, c); indpf(b); asscod[ascdno++] = iregp(0xC1,b); return; } else if (token == 0x17) /* BC|DE|HL,A (macro) */ { if (c != 0x77) { dnops(); return; } if (b < 0x1a) { if ((b & 3) == 3) { dnops(); return; } opbyt1 = fix(b) + 1; opbyt2 = 0x77; grp29(0x77); opbyt1 = fix(b); odint2 = 0; grp29(0x79); return; } if (b >= 0x1f) { dnops(); return; } opbyt1 = makhl(b) | 1; opbyt2 = 0x77; grp29(0x77); opbyt1 = makhl(b) & 0xfe; odint2 = 0; grp29(0x79); return; } else if (token == 0x14) /* BC|DE|HL,(HL)|(IX)|(IY) (macro) */ { if (b > 0x12) { dnops(); return; } if (b == 0x12 && c == 0x40) { savit(la2); return; } if (c > 0x40) { opbyt2 = cadj(c); grp29(0x1b); return; } opbyt1 = fix(b) + 1; grp29(0x74); opbyt1 = 0x12; ortkbf[0] = IDTOK; ortkbf[1] = 0; grp13(0x10); opbyt1 = fix(b); grp29(0x74); return; } else if (token == 0x1b) /* BC|DE|HL,(IX+dd)|(IY+dd) (macro) */ { if (b > 0x12) { dnops(); return; } opbyt1 = fix(b) + 1; grp29(0x7b); ortkbf[0] = IDTOK; ortkbf[1] = 0; opbyt1 = c & 0xe; opbyt1 |= 0x12; grp13(0x10); opbyt1 = fix(b); grp29(0x7b); return; } else if (token == 0x41) /* (IX)|(IY)|(HL),BC|DE|HL (macro) */ { if (c > 0x12) { dnops(); return; } if (c == 0x12 && b == 0x40) { savit(la1); return; } if (b > 0x40) { opbyt1 = cadj(b); grp29(0xb1); return; } opbyt2 = fix(c) + 1; grp29(0x47); opbyt1 = 0x12; ortkbf[0] = IDTOK; ortkbf[1] = 0; grp13(0x10); opbyt1 = b; opbyt2 = fix(c); grp29(0x47); return; } else if (token == 0xb1) /* (IX+dd)|(IY+dd),BC|DE|HL (macro) */ { if (c > 0x12) { dnops(); return; } opbyt2 = fix(c) + 1; grp29(0xb7); x = opbyt1; opbyt1 = b & 0xe; opbyt1 |= 0x12; ortkbf[0] = IDTOK; ortkbf[1] = 0; grp13(0x10); opbyt1 = x; opbyt2 = fix(c); grp29(0xb7); return; } else if (token == 0x66) /* (BC)|(DE),(BC)|(DE) */ { if (b == c) { dnops(); return; } opbyt1 = 0x77; grp29(0x76); opbyt1 = b; opbyt2 = 0x77; grp29(0x67); return; } else if (token == 0x46) /* (IX)|(IY)|(HL),(BC)|(DE) */ { if (b == c) { dnops(); return; } opbyt1 = 0x77; grp29(0x76); opbyt1 = b; opbyt2 = 0x77; grp29(0x47); return; } else if (token == 0x64) /* (BC)|(DE),(HL)|(IX) */ { if (b == c) { dnops(); return; } opbyt1 = 0x77; grp29(0x74); opbyt1 = b; opbyt2 = 0x77; grp29(0x67); return; } else if (token == 0xb6) /* (IX+dd)|(IY+dd),(BC)|(DE) */ { if (b == c) { dnops(); return; } opbyt1 = 0x77; grp29(0x76); opbyt1 = b; opbyt2 = 0x77; grp29(0xb7); return; } else if (token == 0xbb) /* (IX+dd)|(IY+dd),(IX+dd)|(IY+dd) */ { if (b == c) { dnops(); return; } opbyt1 = 0x77; grp29(0x7b); opbyt1 = b; opbyt2 = 0x77; grp29(0xb7); return; } else if (token == 0xb4) /* (IX+dd)|(IY+dd),(HL) */ { if (b == c) { dnops(); return; } opbyt1 = 0x77; grp29(0x74); opbyt1 = b; opbyt2 = 0x77; grp29(0xb7); return; } else if (token == 0x6b) /* (BC)|(DE),(IX+dd)|(IY+dd) */ { if (b == c) { dnops(); return; } opbyt1 = 0x77; grp29(0x7b); opbyt1 = b; opbyt2 = 0x77; grp29(0x67); return; } else if (token == 0x4b) /* (HL),(IX+dd)|(IY+dd) */ { if (b == c) { dnops(); return; } opbyt1 = 0x77; grp29(0x7b); opbyt1 = b; opbyt2 = 0x77; grp29(0x47); return; } else if (token == 0x61) /* (BC)|(DE),BC|DE|HL */ { if (c > 0x12) { dnops(); return; } if (c == 0x12) { asscod[ascdno++] = 0xF5; opbyt1 = 0x77; opbyt2 = fix(c) + 1; grp29(0x77); opbyt1 = b; opbyt2 = 0x77; grp29(0x67); opbyt1 = b & 0x1f; ortkbf[0] = IDTOK; ortkbf[1] = 0; grp13(0x10); opbyt1 = 0x77; opbyt2 = fix(c); grp29(0x77); opbyt1 = b; opbyt2 = 0x77; grp29(0x67); asscod[ascdno++] = 0xF1; return; } opbyt1 = b & 0x1f; ortkbf[0] = PUSHTK; ortkbf[1] = 0xc5; grp25(0x10); asscod[ascdno++] = 0xE3; opbyt1 = 0x40; opbyt2 = c; grp29(0x41); asscod[ascdno++] = 0xE3; opbyt1 = b & 0x1f; ortkbf[0] = PUSHTK; ortkbf[1] = 0xc1; grp25(0x10); return; } else if (token == 0x16) /* BC|DE|HL,(BC)|(DE) */ { if (b > 0x12) { dnops(); return; } if (b == 0x12) { asscod[ascdno++] = 0xF5; opbyt1 = 0x77; grp29(0x76); opbyt1 = fix(b) + 1; opbyt2 = 0x77; grp29(0x77); opbyt1 = c & 0x1f; ortkbf[0] = IDTOK; ortkbf[0] = 0; grp13(0x10); opbyt1 = 0x77; opbyt2 = c; grp29(0x76); opbyt1 = fix(b); opbyt2 = 0x77; grp29(0x77); asscod[ascdno++] = 0xF1; return; } opbyt1 = c & 0x1f; ortkbf[0] = PUSHTK; ortkbf[1] = 0xc5; grp25(0x10); asscod[ascdno++] = 0xE3; opbyt1 = b; opbyt2 = 0x40; grp29(0x14); asscod[ascdno++] = 0xE3; opbyt1 = c & 0x1f; ortkbf[0] = PUSHTK; ortkbf[1] = 0xc1; grp25(0x10); return; } else dnops(); } /*. ************************************************************************* * * * * * Handles the CD CR assembler macros. * * * * * * * ************************************************************************* */ void grp34(token) register int token; { int b; #if DEBUG printf("group 34\n"); #endif b = opbyt1; if (token == 0x10) { if (ortkbf[1] == 0x10) { if (b >= 0x14) { dnops(); return; } asscod[ascdno++] = 0xE5; asscod[ascdno++] = 0xB7; asscod[ascdno++] = TWOPRE; asscod[ascdno++] = iregp(0x42, b); asscod[ascdno++] = 0xE1; return; } if (b < 0x13) { opbyt1 = 0x77; opbyt2 = fix(b); grp29(0x77); opbyt1 = fix(b) + 1; ortkbf[1] = 0x30; grp12(0x70); return; } if (b >= 0x1f || b == 0x13 || b == 0x17) { dnops(); return; } indpf(b); asscod[ascdno++] = 0x7C; indpf(b); asscod[ascdno++] = 0xB5; } else dnops(); } /*. ************************************************************************* * * * * * USING handler. * * * * * * * ************************************************************************* */ void grp37(token) register int token; { int b; #if DEBUG printf("group 37\n"); #endif if (token == 0x10) { turn_on(AFUSNG); usin1[0] = usin1[1] = opbyt1; } else if (token == 0x91) { turn_on(AFUSNG); b = (odint1 - 1) & 1; usin1[b] = opbyt2; } else if (token == 0x19) { grp37(0x10); grp29(0x19); return; } else dnops(); } /*. ************************************************************************* * * * * * SVC assembler macro handler. * * * * * * * ************************************************************************* */ void grp41(token) register int token; { #if DEBUG printf("group 41\n"); #endif if (token == 0x90) { asscod[ascdno++] = 0x3E; chkofr(odint1); if (mathfg & MFEXT) { hladdr = odint1; turn_on(AFHILO); hilow |= O4LSB; } else asscod[ascdno++] = odint1; if (passno == 2 && objfile) { adjarc(); proces(); lstln(); minbuf[0] = 0; numbbb[0] = 0; errbuf[0] = SPACE; putobj(); } turn_off(AFENTS); mathfg = 0; adjflg = 0; asscod[ascdno++] = 0xCF; } else if (token == 0xd0) { asscod[ascdno++] = 0x3A; asscod[ascdno++] = odint1; asscod[ascdno++] = (odint1 >> 8); if (passno == 2 && objfile) { adjarc(); proces(); lstln(); minbuf[0] = 0; numbbb[0] = 0; errbuf[0] = SPACE; putobj(); } mathfg = 0; adjflg = 0; asscod[ascdno++] = 0xCF; } else dnops(); } /*. ************************************************************************* * * * * * ISECT definition handler. * * * * * * * ************************************************************************* */ void grp43(token) register int token; { #if DEBUG printf("group 43\n"); #endif if (token == 0) { cisect(); adrefc[mode] = 0; addisr = 0; idef = 0; } else if (token == 0x90) { cisect(); adrefc[mode] = 0; addisr = 0; if (odint2 > 2) { grp44(0); eror('S'); return; } idef = odint2; } else if (token == 0x99) { cisect(); adrefc[mode] = odint2 & (unsigned) 0xffff; addisr = odint2 & (unsigned) 0xffff; if (odint1 > 2) { grp44(0); eror('S'); return; } idef = odint1; } else dnops(); } /* * */ void cisect() { if (is_on(AFISEC)) return; turn_on(AFISEC); isave = adrefc[mode]; } /*. ************************************************************************* * * * * * ENDI handler * * * * * * * ************************************************************************* */ void grp44(token) register int token; { #if DEBUG printf("group 44\n"); #endif if (token == 0) { if (is_off(AFISEC)) { eror('S'); return; } turn_off(AFISEC); adrefc[mode] = isave; addisr = isave; idef = 0; } else dnops(); } /*. ************************************************************************* * * * * * DROP handler. * * * * * * * ************************************************************************* */ void grp45(token) register int token; { int b; #if DEBUG printf("group 45\n"); #endif if (token == 0 || token == 0x99) { turn_off(AFUSNG); usin1[0] = usin1[1] = 0; } else if (token == 0x90) { if (odint1 > 2) { eror('S'); return; } b = (odint1 - 1) & 1; usin1[b] = 0; if (usin1[0] || usin1[1]) return; grp45(0); } else dnops(); } /*. ************************************************************************* * * * * * This is the handler for the undocumented Z80 instructions of * * 'set and load', 'reset and load'. * * * * * * * ************************************************************************* */ void grp51(token) register int token; { int b, c, de; #if DEBUG printf("group 51\n"); #endif c = opbyt1; b = opbyt2; de = odint2; if (token == 0x74 || token == 0x7b) { if (b < 0x50) b += 0x52; if ((b & 0xf0) != 0xb0) { dnops(); return; } indpf(b); asscod[ascdno++] = 0xCB; disbt(b, de); asscod[ascdno++] = ortkbf[1] | (c & 7); } else dnops(); } /* * This is the handler for the CMP and MOV macro pseudo-op. */ /* NOTE: The follow three (bchhk1, cmpch1, bchhk2) MUST be in the order supplied. They make up the op-codes for: BCHHK1: LD A,B OR C JR NZ,BCHHK2 LD A,(DE) CP (HL) JR NZ,BCHHK2 CPI (or) CPD JR BCHHK1 BCHHK2: */ static char bchhk1[] = { 0x78, 0xb1, 0x28, 0x8, 0x1a, 0xbe, 0x20, 0x4, 0xed, 0 }; static char bchhk2[] = { 0x18, 0xf4, 0 }; static char dcount; static char dummy[100]; void cmp() { register char *lp; int i, cmpch1, temp1, temp2; dcount = 0; cmpch1 = ortkbf[1]; if (passno == 2 && objfile) clsrec(); linpnt = skipsp(linpnt); if (term(linpnt)) { dnops(); return; } /* pick up the first parameter */ if (getopd(linpnt, &opbyt1, &odint1, 1) == EMPTY) { dnops(); return; } if (opbyt1 == INTTOK || opbyt1 == 0xd0) ; else { dnops(); return; } if (opbyt1 == INTTOK) stobyt(0x11); else { stobyt(TWOPRE); stobyt(0x5b); } stowrd(odint1); if (passno == 2 && objfile) { proces(); putobj(); } /* pick up the second parameter */ if (chkspc(linpnt) || term(linpnt)) { dnops(); return; } (void) getopd(linpnt, &opbyt1, &odint1, 1); if (opbyt1 == INTTOK || opbyt1 == 0xd0) ; else { dnops(); return; } if (opbyt1 == INTTOK) stobyt(0x21); else stobyt(0x2a); stowrd(evalue); adjarc(); if (passno == 2 && objfile) { proces(); putobj(); } if (notend(linpnt)) { (void) getopd(linpnt, &opbyt1, &odint1, 1); if (opbyt1 == INTTOK || opbyt1 == 0xd0) ; else { dnops(); return; } if (opbyt1 == INTTOK) stobyt(0x1); else { stobyt(TWOPRE); stobyt(0x4b); stowrd(evalue); } adjarc(); if (passno == 2 && objfile) { proces(); putobj(); } } lp = bchhk1; while(*lp) stobyt(*lp++); stobyt(cmpch1); lp = bchhk2; while(*lp) stobyt(*lp++); adjarc(); if (passno == 2 && objfile) { proces(); putobj(); } temp1 = adrefc[mode]; temp2 = addisr; ascdno = 0; for(i = 0; i < dcount;) asscod[ascdno++] = dummy[i++]; lstln(); ascdno = 0; adrefc[mode] = temp1; addisr = temp2; dont = 1; } /* * Handler for some of the undocumented Z80 instructions. */ static char byte1; void reseld() { linpnt = skipsp(linpnt); if (term(linpnt)) { dnops(); return; } if (getopd(linpnt, &byte1, &odint1, 1) == EMPTY) { dnops(); return; } if (byte1 < 0x70 || byte1 > 0x77) { dnops(); return; } byte1 &= 0x7; gtod(linpnt); indpf(opbyt2); asscod[ascdno++] = 0xCB; disbt(opbyt2, odint2); byte1 |= ((odint1 & 7) << 3); asscod[ascdno++] = byte1 | ortkbf[1]; adjarc(); } #ifdef HITACHI /*. ************************************************************************ * * * * * This is the handler for the hitachi hd64180 instructions of * * tst and tstio. * * * * * * * ************************************************************************ */ void grp52(token) register int token; { int b, hl; b = opbyt1; asscod[ascdno++] = TWOPRE; if(token == 0x70) asscod[ascdno++] = idreg(4,b); else if(token == 0x90) { hl = odint1; if(hl > 256) { dnops(); return; } asscod[ascdno++] = ortkbf[1]; asscod[ascdno++] = hl; } else if(token == 0x40) { if(token != 0x40) { dnops(); return; } asscod[ascdno++] = 0x34; } else { dnops(); return; } } /*. ************************************************************************ * * * * * This is the handler for the hitachi hd64180 instructions of * * multiply. * * * * * * * ************************************************************************ */ void grp53(token) register int token; { int b; b = opbyt1; if(token != 0x10 || b > 0x12) { dnops(); return; } asscod[ascdno++] = TWOPRE; asscod[ascdno++] = iregp(0x4c, b); } /*. ************************************************************************ * * * * * This is the handler for the hitachi hd64180 instructions of * * in0 and out0. * * * * * * * ************************************************************************ */ void grp54(token) register int token; { int b, c, de, hl; b = opbyt1; c = opbyt2; de = odint2; hl = odint1; asscod[ascdno++] = TWOPRE; if (token == 0x7d) { if (de >= 256) { dnops(); return; } asscod[ascdno++] = (idreg(0,b)); asscod[ascdno++] = de; } else if (token == 0xd7) { if (hl >= 256) { dnops(); return; } asscod[ascdno++] = (idreg(1,c)); asscod[ascdno++] = hl; } else dnops(); } #endif /* store a byte in both asscod and dummy */ void stobyt(byte) unsigned byte; { asscod[ascdno++] = byte; dummy[dcount++] = byte; } /* store a word in both asscod and dummy */ void stowrd(word) register int word; { stobyt(word >> 8); stobyt(word); } /* see if a relative displacement is within range */ short cdis(n) short n; { short value; #if DEBUG printf("cdis\n"); #endif value = (n - (adrefc[mode] + 2) & 0xffff); if (value < 0) { value = -value & 0xffff; if (value > 128) { eror('R'); return(0xfe); } else return(-value); } else { if (value > 127) { eror('R'); return(0xfe); } else return(value); } } /* adjust an operator */ cadj(token) register int token; { if (token == 0xba) return(0x48); else if (token == 0xbe) return(0x4c); else return(token); } void savit(pnt) register char *pnt; { while(*pnt) asscod[ascdno++] = *pnt++; } void chkofr(value) int value; { if (mathfg & MFRLEX && is_off(AFHILO)) { hladdr = value; turn_on(AFHILO); hilow |= O4LSB; } chkof(value); } /* append IX or IY prefix if instruction warrents */ void indpf(token) register int token; { if ((token & 8) == 0) return; setcnt(token & 4 ? 0xfd : 0xdd); } /* generate displacement byte */ void disbt(token, value) register int token; short value; { if ((token & 8) == 0) return; chkof(value); setcnt(value); } /* check to see if a byte is within a byte range */ void chkof(value) unsigned short value; { if (value >= 0x8000) { value = -value; if (value > 255) eror('V'); return; } if (value > 255) eror('V'); } /* turn operand into hl type instruction */ makhl(token) register int token; { indpf(token); return((token & 1) + 0x74); } /* check for proper 'using' for IX */ ckus1() { if (is_on(AFUSNG | AFUSPR) != (AFUSNG | AFUSPR)) { dnops(); ascdno = 3; return(ERR); } return(getix()); } /* check for proper 'using' for IY */ ckus2() { if (is_on(AFUSNG | AFUSPR) != (AFUSNG | AFUSPR)) { dnops(); ascdno = 3; return(ERR); } return(getiy()); } /* return isext number if we're using */ getix() { if (isave2) return(usin1[isave2-1]); if (usin1[1]) return(usin1[1]); return(usin1[0]); } /* set correct count for appended IX or IY prefix */ void setcnt(opcode) unsigned opcode; { asscod[ascdno++] = opcode; ++adroff; }