/* * Process a machine op. */ VOID machine(struct mne * mp) { int op, t1, t2; struct expr e1, e2; int rf, v1, v2; clrexpr(&e1); clrexpr(&e2); op = (int) mp->m_valu; rf = mp->m_type; #if 0 if (!hd64 && rf>X_HD64) rf = 0; #endif if (!r4k_mode && rf > X_R4K_MODE) rf = 0; switch (rf) { case S_INH1: outab(op); break; case S_INH2: outab(0xED); outab(op); break; case S_RET: if (more()) { if ((v1 = admode(CND)) != 0) { outab(op | (v1<<3)); } else { qerr(); } } else { outab(0xC9); } break; case S_PUSH: if (admode(R16X)) { outab(op+0x30); break; } else if ((v1 = admode(R8IP)) != 0) { outab(0xED); if (op == 0xC5) outab(0x76); /* push */ else outab(0x7E); /* pop */ break; } else if ((v1 = admode(R16)) != 0 && (v1 &= 0xFF) != SP) { if (v1 != gixiy(v1)) { outab(op+0x20); break; } outab(op | (v1<<4)); break; } else if (r4k_mode) { if ( (v1 = admode(R32_JKHL)) != 0 ) { outab(JKHL_PG); outab(op+0x30); break; } else if ( (v1 = admode(R32_BCDE)) != 0 ) { outab(BCDE_PG); outab(op+0x30); break; } } aerr(); break; case S_RST: v1 = (int) absexpr(); /* ljm comment - * block RST 00, 08, and 30 b/c those opcodes * are assigned to different instructions in the * rabbit processor */ if ((v1 == 0x00) || (v1 == 0x08) || (v1 == 0x30)) { aerr( ); v1 = 0; } if (v1 & ~0x38) { aerr(); v1 = 0; } outab(op|v1); break; #if 0 /* IM x set interrupt mode on Z-80 */ /* Rabbit processor use the opcode to set interrupt level */ case S_IM: expr(&e1, 0); abscheck(&e1); if (e1.e_addr > 2) { aerr(); e1.e_addr = 0; } outab(op); outab(imtab[(int) e1.e_addr]); break; #endif case S_BIT: expr(&e1, 0); t1 = 0; v1 = (int) e1.e_addr; if (v1 > 7) { ++t1; v1 &= 0x07; } op |= (v1<<3); comma(1); addr(&e2); abscheck(&e1); if (genop(0xCB, op, &e2, 0) || t1) aerr(); break; case S_RL: t1 = 0; t2 = addr(&e2); if ((t2 == S_IMMED) && r4k_mode) { v1 = (int) e2.e_addr; /* v1 should be shift count of 1,2,4, or 8 */ comma(1); clrexpr(&e2); t2 = addr(&e2); if ((t2 != S_R32_BCDE) && (t2 != S_R32_JKHL)) aerr( ); if (v1 == 1) v1 = 0x48; else if (v1 == 2) v1 = 0x49; else if (v1 == 4) v1 = 0x4B; else if ((v1 == 8) && (op < 0x20 /* op is rlc|rrc|rl|rr */)) v1 = 0x4F; else { err('o'); break; } /* 00 rlc, 08 rrc, 10 rl , 18 rr * * 20 sla, 28 sra, 38 srl, [30 sll == sla] */ outab( ((t2 == S_R32_JKHL)?JKHL_PG:BCDE_PG) ); outab(v1 + (op << 1)); break; } else if (more()) { if ((t2 != S_R8) || (e2.e_addr != A)) ++t1; comma(1); clrexpr(&e2); t2 = addr(&e2); } else if (t2 == S_R16) { v2 = (int) e2.e_addr; if ((v2 == DE) && ((op == 0x10 /* rl */) || (op == 0x18 /* rr */))) { outab( 0xF3 - 0x10 + op ); break; } if ((v2 == HL) && (op == 0x18 /* rr */)) { outab( 0xFC ); break; } if (r4k_mode) { if ((v2 == HL) && (op == 0x10 /* rl */)) { outab( 0x42 ); break; } if (((v2 == BC)||(v2 == DE)) && (op < 0x20 /* 00 rlc, 08 rrc, 10 rl, 18 rr */)) { outab( 0x50 + (op >> 3) + ((v2==BC)?0x10:0x00) ); break; } } aerr( ); }
/* * Process machine ops. */ VOID machine(struct mne *mp) { char *p, *str; char pid[NINPUT], id[NINPUT]; int c, d, t, t1, v1; a_uint op; struct sym *sp; struct expr e, e1, e2; clrexpr(&e); clrexpr(&e1); clrexpr(&e2); op = mp->m_valu; switch (mp->m_type) { case S_CPU: opcycles = OPCY_CPU; lmode = SLIST; switch(op) { default: op = DS8XCXXX; case DS8XCXXX: v1 = 2; str = "DS8XCXXX"; sym[2].s_addr = X_DS8XCXXX; break; case DS80C310: v1 = 2; str = "DS80C310"; sym[2].s_addr = X_DS80C310; break; case DS80C320: v1 = 2; str = "DS80C320"; sym[2].s_addr = X_DS80C320; break; case DS80C323: v1 = 2; str = "DS80C323"; sym[2].s_addr = X_DS80C323; break; case DS80C390: v1 = 3; str = "DS80C390"; sym[2].s_addr = X_DS80C390; break; case DS83C520: v1 = 2; str = "DS83C520"; sym[2].s_addr = X_DS83C520; break; case DS83C530: v1 = 2; str = "DS83C530"; sym[2].s_addr = X_DS83C530; break; case DS83C550: v1 = 2; str = "DS83C550"; sym[2].s_addr = X_DS83C550; break; case DS87C520: v1 = 2; str = "DS87C520"; sym[2].s_addr = X_DS87C520; break; case DS87C530: v1 = 2; str = "DS87C530"; sym[2].s_addr = X_DS87C530; break; case DS87C550: v1 = 2; str = "DS87C550"; sym[2].s_addr = X_DS87C550; break; case DS______: v1 = 2; str = "DS______"; sym[2].s_addr = X_DS______; if (more()) { str = p = pid; d = getnb(); while ((c = get()) != d) { if (c == '\0') { qerr(); } if (p < &pid[sizeof(pid)-3]) { *p++ = c; } else { break; } } *p = 0; } break; } if (op != 0) { ds8_bytes = v1; exprmasks(v1); } mchtyp = (int) op; sprintf(id, "__%s", str); sp = lookup(id); if (sp->s_type != S_NEW && (sp->s_flag & S_ASG) == 0) { err('m'); } sp->s_type = S_USER; sp->s_addr = 1; sp->s_flag |= S_ASG; sprintf(buff, "%s %s", DS_CPU, str); cpu = buff; sp = lookup("__SFR_BITS"); if (sp->s_type != S_NEW && (sp->s_flag & S_ASG) == 0) { err('m'); } sp->s_type = S_USER; sp->s_flag |= S_ASG; if (more()) { expr(&e, 0); abscheck(&e); sp->s_addr = e.e_addr; } else { sp->s_addr = 1; } break; case S_AMODE: opcycles = OPCY_AMODE; if ((mchtyp != 0) && (mchtyp != DS80C390)) { err('o'); break; } expr(&e, 0); abscheck(&e); amode = (int) e.e_addr; if ((amode < 0) || (amode > 2)) { amode = 0; err('o'); } if ((c = getnb()) == ',') { expr(&e1, 0); abscheck(&e1); if (e1.e_addr != 0) { /* mov ta,#0aah */ outab(0x075); outab(0x0C7); outab(0x0AA); /* mov ta,#055h */ outab(0x075); outab(0x0C7); outab(0x055); /* mov acon,#amode */ outab(0x075); outab(0x09D); outab(amode); } else { lmode = SLIST; } } else { unget(c); lmode = SLIST; } break; case S_BITS: if (ds8_bytes == 0) { ds8_bytes = (int) op; exprmasks(ds8_bytes); } else if (ds8_bytes != (int) op) { err('m'); } opcycles = OPCY_BITS; lmode = SLIST; break; case S_INH: outab(op); break; case S_JMP11: expr(&e, 0); if (amode == 2) { outr3bm(&e, R_J19, op); } else { outrwm(&e, R_J11, op); } break; case S_JMP16: expr(&e, 0); outab(op); if (amode == 2) { outr3b(&e, R_NORM); } else { outrw(&e, R_NORM); } break; case S_ACC: t = addr(&e); if (t != S_A) aerr(); outab(op); break; case S_TYP1: /* A, direct, @R0, @R1, R0 to R7. "INC" also allows DPTR */ t = addr(&e); switch (t) { case S_A: outab(op + 4); break; case S_DIR: case S_EXT: /* Direct is also legal */ outab(op + 5); outrb(&e, R_PAG0); break; case S_AT_R: outab(op + 6 + e.e_addr); break; case S_REG: outab(op + 8 + e.e_addr); break; case S_DPTR: if (op != 0) /* only INC (op=0) has DPTR mode */ aerr(); else outab( 0xA3); break; default: aerr(); } break; case S_TYP2: /* A,#imm; A,direct; A,@R0; A,@R1; A,R0 to A,R7 */ t = addr(&e); if (t != S_A) aerr(); comma(1); t1 = addr(&e1); switch (t1) { case S_IMMED: outab(op + 4); outrb(&e1, R_NORM); break; case S_DIR: case S_EXT: outab(op + 5); outrb(&e1, R_PAG0); break; case S_AT_R: outab(op + 6 + e1.e_addr); break; case S_REG: outab(op + 8 + (e1.e_addr)); break; default: aerr(); } break; case S_TYP3: /* dir,A; dir,#imm; * A,#imm; A,direct; A,@R0; A,@R1; A,R0 to A,R7 * C,direct; C,/direct */ t = addr(&e); comma(1); t1 = addr(&e1); switch (t) { case S_DIR: case S_EXT: switch (t1) { case S_A: outab(op + 2); outrb(&e, R_PAG0); break; case S_IMMED: outab(op + 3); outrb(&e, R_PAG0); outrb(&e1, R_NORM); break; default: aerr(); } break; case S_A: switch (t1) { case S_IMMED: outab(op + 4); outrb(&e1, R_NORM); break; case S_DIR: case S_EXT: outab(op + 5); outrb(&e1, R_PAG0); break; case S_AT_R: outab(op + 6 + e1.e_addr); break; case S_REG: outab(op + 8 + e1.e_addr); break; default: aerr(); } break; case S_C: /* XRL has no boolean version. Trap it */ if (op == 0x60) aerr(); switch (t1) { case S_DIR: case S_EXT: outab(op + 0x32); outrb(&e1, R_PAG0); break; case S_NOT_BIT: outab(op + 0x60); outrb(&e1, R_PAG0); break; default: aerr(); } break; default: aerr(); } break; case S_TYP4: /* A,direct; A,@R0; A,@R1; A,R0 to A,R7 */ t = addr(&e); if (t != S_A) aerr(); comma(1); t1 = addr(&e1); switch (t1) { case S_DIR: case S_EXT: outab(op + 5); outrb(&e1, R_PAG0); break; case S_AT_R: outab(op + 6 + e1.e_addr); break; case S_REG: outab(op + 8 + e1.e_addr); break; default: aerr(); } break; /* MOV instruction, all modes */ case S_MOV: t = addr(&e); comma(1); t1 = addr(&e1); switch (t) { case S_A: switch (t1) { case S_IMMED: outab(0x74); outrb(&e1, R_NORM); break; case S_DIR: case S_EXT: outab(0xE5); outrb(&e1, R_PAG0); break; case S_AT_R: outab(0xE6 + e1.e_addr); break; case S_REG: outab(0xE8 + e1.e_addr); break; default: aerr(); } break; case S_REG: switch (t1) { case S_A: outab(0xF8 + e.e_addr); break; case S_IMMED: outab(0x78 + e.e_addr); outrb(&e1, R_NORM); break; case S_DIR: case S_EXT: outab(0xA8 + e.e_addr); outrb(&e1, R_PAG0); break; default: aerr(); } break; case S_DIR: case S_EXT: switch (t1) { case S_A: outab(0xF5); outrb(&e, R_PAG0); break; case S_IMMED: outab(0x75); outrb(&e, R_PAG0); outrb(&e1, R_NORM); break; case S_DIR: case S_EXT: outab(0x85); outrb(&e1, R_PAG0); outrb(&e, R_PAG0); break; case S_AT_R: outab(0x86 + e1.e_addr); outrb(&e, R_PAG0); break; case S_REG: outab(0x88 + e1.e_addr); outrb(&e, R_PAG0); break; case S_C: outab(0x92); outrb(&e, R_PAG0); break; default: aerr(); } break; case S_AT_R: switch (t1) { case S_IMMED: outab(0x76 + e.e_addr); outrb(&e1, R_NORM); break; case S_DIR: case S_EXT: outab(0xA6 + e.e_addr); outrb(&e1, R_PAG0); break; case S_A: outab(0xF6 + e.e_addr); break; default: aerr(); } break; case S_C: if ((t1 != S_DIR) && (t1 != S_EXT)) aerr(); outab(0xA2); outrb(&e1, R_PAG0); break; case S_DPTR: if (t1 != S_IMMED) aerr(); outab(0x90); if (amode == 2) outr3b(&e1, R_NORM); else outrw(&e1, R_NORM); break; default: aerr(); } break; case S_BITBR: /* JB, JBC, JNB bit,rel */ /* Branch on bit set/clear */ t = addr(&e); if ((t != S_DIR) && (t != S_EXT)) aerr(); /* sdcc svn rev #4994: fixed bug 1865114 */ comma(1); expr(&e1, 0); outab(op); outrb(&e, R_PAG0); if (mchpcr(&e1)) { v1 = (int) (e1.e_addr - dot.s_addr - 1); /* sdcc svn rev #602: Fix some path problems */ if (pass == 2 && ((v1 < -128) || (v1 > 127))) aerr(); outab(v1); } else { outrb(&e1, R_PCR); } if (e1.e_mode != S_USER) rerr(); break; case S_BR: /* JC, JNC, JZ, JNZ */ /* Relative branch */ /* sdcc svn rev #4994: fixed bug 1865114 */ expr(&e1, 0); outab(op); if (mchpcr(&e1)) { v1 = (int) (e1.e_addr - dot.s_addr - 1); /* sdcc svn rev #602: Fix some path problems */ if (pass == 2 && ((v1 < -128) || (v1 > 127))) aerr(); outab(v1); } else { outrb(&e1, R_PCR); } if (e1.e_mode != S_USER) rerr(); break; case S_CJNE: /* A,#; A,dir; @R0,#; @R1,#; Rn,# */ t = addr(&e); comma(1); t1 = addr(&e1); /* Benny */ comma(1); expr(&e2, 0); switch (t) { case S_A: if (t1 == S_IMMED) { outab(op + 4); outrb(&e1, R_NORM); } else if ((t1 == S_DIR) || (t1 == S_EXT)) { outab(op + 5); outrb(&e1, R_PAG0); } else aerr(); break; case S_AT_R: outab(op + 6 + e.e_addr); if (t1 != S_IMMED) aerr(); outrb(&e1, R_NORM); break; case S_REG: outab(op + 8 + e.e_addr); if (t1 != S_IMMED) aerr(); outrb(&e1, R_NORM); break; default: aerr(); break; } /* branch destination */ if (mchpcr(&e2)) { v1 = (int) (e2.e_addr - dot.s_addr - 1); /* sdcc svn rev #602: Fix some path problems */ if (pass == 2 && ((v1 < -128) || (v1 > 127))) aerr(); outab(v1); } else { outrb(&e2, R_PCR); } if (e2.e_mode != S_USER) rerr(); break; case S_DJNZ: /* Dir,dest; Reg,dest */ t = addr(&e); /* sdcc svn rev #4994: fixed bug 1865114 */ comma(1); expr(&e1, 0); switch (t) { case S_DIR: case S_EXT: outab(op + 5); outrb(&e, R_PAG0); break; case S_REG: outab(op + 8 + e.e_addr); break; default: aerr(); } /* branch destination */ /* sdcc svn rev #4994: fixed bug 1865114 */ if (mchpcr(&e1)) { v1 = (int) (e1.e_addr - dot.s_addr - 1); /* sdcc svn rev #602: Fix some path problems */ if (pass == 2 && ((v1 < -128) || (v1 > 127))) aerr(); outab(v1); } else { outrb(&e1, R_PCR); } if (e1.e_mode != S_USER) rerr(); break; case S_JMP: /* @A+DPTR */ t = addr(&e); if (t != S_AT_ADP) aerr(); outab(op); break; case S_MOVC: /* A,@A+DPTR A,@A+PC */ t = addr(&e); if (t != S_A) aerr(); comma(1); t1 = addr(&e1); if (t1 == S_AT_ADP) outab(0x93); else if (t1 == S_AT_APC) outab(0x83); else aerr(); break; case S_MOVX: /* A,@DPTR A,@R0 A,@R1 @DPTR,A @R0,A @R1,A */ t = addr(&e); comma(1); t1 = addr(&e1); switch (t) { case S_A: switch (t1) { case S_AT_DP: outab(0xE0); break; case S_AT_R: outab(0xE2 + e1.e_addr); break; default: aerr(); } break; case S_AT_DP: if (t1 == S_A) outab(0xF0); else aerr(); break; case S_AT_R: if (t1 == S_A) outab(0xF2 + e.e_addr); else aerr(); break; default: aerr(); } break; /* MUL/DIV A,B */ case S_AB: t = addr(&e); if (t != S_RAB) aerr(); outab(op); break; /* CLR or CPL: A, C, or bit */ case S_ACBIT: t = addr(&e); switch (t) { case S_A: if (op == 0xB2) outab(0xF4); else outab(0xE4); break; case S_C: outab(op+1); break; case S_DIR: case S_EXT: outab(op); outrb(&e, R_PAG0); break; default: aerr(); } break; /* SETB C or bit */ case S_SETB: t = addr(&e); switch (t) { case S_C: outab(op+1); break; case S_DIR: case S_EXT: outab(op); outrb(&e, R_PAG0); break; default: aerr(); } break; /* direct */ case S_DIRECT: t = addr(&e); if (t == S_A) { e.e_addr = 0xE0; e.e_mode = S_DIR; } else if ((t != S_DIR) && (t != S_EXT)) { aerr(); break; } outab(op); outrb(&e, R_PAG0); break; /* XCHD A,@Rn */ case S_XCHD: t = addr(&e); if (t != S_A) aerr(); comma(1); t1 = addr(&e1); switch (t1) { case S_AT_R: outab(op + e1.e_addr); break; default: aerr(); } break; default: opcycles = OPCY_ERR; err('o'); break; } if (opcycles == OPCY_NONE) { opcycles = ds8pg1[cb[0] & 0xFF]; } }