/* * Interactive disassembler (IDA). * Copyright (c) 1990-2001 by Ilfak Guilfanov. * ALL RIGHTS RESERVED. * E-mail: ig@datarescue.com * * */ #include "78k_0s.hpp" //---------------------------------------------------------------------- inline uint32 sfr(uchar sfr_offset) { return 0xFF00 + sfr_offset; } //---------------------------------------------------------------------- inline uint32 saddr(uchar Saddr_offset) { if ( Saddr_offset < 0x20 ) return 0xFF00 + Saddr_offset; else return 0xFE00 + Saddr_offset; } //---------------------------------------------------------------------- inline void addr16(insn_t &insn, op_t &x) { //x.offb = insn.size; uint32 low = insn.get_next_byte(); uint32 high = insn.get_next_byte(); //x.type = o_near; x.addr = low | (high << 8); x.addr16 = 1; } //---------------------------------------------------------------------- inline void jdisp(op_t &x, uchar addr, int previons_len, const insn_t &insn) { x.type = o_near; x.addr = insn.ip + (signed char)addr + previons_len; //x.offb = insn.size - 1; } //---------------------------------------------------------------------- inline void imm16(insn_t &insn, op_t &x) { x.type = o_imm; x.dtype = dt_word; uchar b1 = insn.get_next_byte(); uchar b2 = insn.get_next_byte(); x.value = b1 | (b2<<8); } //---------------------------------------------------------------------- int idaapi ana(insn_t *_insn) { if ( _insn == NULL ) return 0; insn_t &insn = *_insn; // get one byte uchar code = insn.get_next_byte(); switch ( code ) { // Mnemonic Operand Instruction Code // B1 B2 B3 B4 case 0x00: //ROR A, 1 0000 0000 insn.itype = NEC_78K_0S_ror; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_imm; insn.Op2.value = 1; insn.Op2.regmode = 1; break; case 0x02: //RORC A, 1 0000 0010 insn.itype = NEC_78K_0S_rorc; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_imm; insn.Op2.value = 1; insn.Op2.regmode = 1; break; case 0x04: //CLR1 CY 0000 0100 insn.itype = NEC_78K_0S_clr1; insn.Op1.type = o_phrase; insn.Op1.reg = bCY; break; case 0x05: //XCH A, saddr 0000 0101 Saddr-offset insn.itype = NEC_78K_0S_xch; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_mem; insn.Op2.dtype = dt_byte; insn.Op2.addr = saddr(insn.get_next_byte()); break; case 0x06: //NOT1 CY 0000 0110 insn.itype = NEC_78K_0S_not1; insn.Op1.type = o_phrase; insn.Op1.reg = bCY; break; case 0x07: //XCH A, sfr 0000 0111 Sfr-offset insn.itype = NEC_78K_0S_xch; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_mem; insn.Op2.dtype = dt_byte; insn.Op2.addr = sfr(insn.get_next_byte()); break; case 0x08: //NOP 0000 1000 insn.itype = NEC_78K_0S_nop; break; case 0x0A: // All 0x0A commands { uchar code2 = insn.get_next_byte(); switch ( code2 ) { case 0x88: case 0x98: case 0xA8: case 0xB8: case 0xC8: case 0xD8: case 0xE8: case 0xF8: //BT saddr.bit, $addr16 0000 1010 1 B2 B1 B0 1000 Saddr-offset jdisp insn.itype = NEC_78K_0S_bt; insn.Op1.type = o_bit; insn.Op1.dtype = dt_byte; insn.Op1.addr = saddr(insn.get_next_byte()); insn.Op1.value = (code2>>4) & 0x07; jdisp(insn.Op2, insn.get_next_byte(), 4, insn); break; case 0x84: case 0x94: case 0xA4: case 0xB4: case 0xC4: case 0xD4: case 0xE4: case 0xF4: { //BT sfr.bit, $addr16 0000 1010 1 B2 B1 B0 0100 Sfr-offset jdisp //BT PSW.bit, $addr16 0000 1010 1 B2 B1 B0 1000 0001 1110 jdisp insn.itype = NEC_78K_0S_bt; uchar code3 = insn.get_next_byte(); if ( code3 == 0x1E ) { insn.Op1.type = o_bit; insn.Op1.reg = rPSW; insn.Op1.value = (code2>>4)&0x07; jdisp(insn.Op2, code3, 4, insn); } else { insn.Op1.type = o_bit; insn.Op1.dtype = dt_byte; insn.Op1.addr = sfr(code3); insn.Op1.value = (code2>>4) & 0x07; jdisp(insn.Op2, insn.get_next_byte(), 4, insn); } } break; case 0x08: case 0x18: case 0x28: case 0x38: case 0x48: case 0x58: case 0x68: case 0x78: { //BF saddr.bit, $addr16 0000 1010 0 B2 B1 B0 1000 Saddr-offset jdisp //BF PSW.bit, $addr16 0000 1010 0 B2 B1 B0 1000 0001 1110 jdisp insn.itype = NEC_78K_0S_bf; uchar code3=insn.get_next_byte(); if ( code3 == 0x1E ) { insn.Op1.type = o_bit; insn.Op1.reg = rPSW; insn.Op1.value = (code2>>4)&0x07; jdisp(insn.Op2, insn.get_next_byte(), 4, insn); } else { insn.Op1.type = o_bit; insn.Op1.dtype = dt_byte; insn.Op1.addr = saddr(code3); insn.Op1.value = (code2>>4) & 0x07; jdisp(insn.Op2, insn.get_next_byte(), 4, insn); } } break; case 0x04: case 0x14: case 0x24: case 0x34: case 0x44: case 0x54: case 0x64: case 0x74: //BF sfr.bit, $addr16 0000 1010 0 B2 B1 B0 0100 Sfr-offset jdisp insn.itype = NEC_78K_0S_bf; insn.Op1.type = o_bit; insn.Op1.dtype = dt_byte; insn.Op1.addr = sfr(insn.get_next_byte()); insn.Op1.value = (code2>>4) & 0x07; jdisp(insn.Op2, insn.get_next_byte(), 4, insn); break; case 0x00: case 0x10: case 0x20: case 0x30: case 0x40: case 0x50: case 0x60: case 0x70: //BF A.bit, $addr16 0000 1010 0 B2 B1 B0 0000 jdisp insn.itype = NEC_78K_0S_bf; insn.Op1.type = o_bit; insn.Op1.reg = rA; insn.Op1.value = (code2>>4) & 0x07; jdisp(insn.Op2, insn.get_next_byte(), 3, insn); break; case 0x80: case 0x90: case 0xA0: case 0xB0: case 0xC0: case 0xD0: case 0xE0: case 0xF0: //BT A.bit, $addr16 0000 1010 1 B2 B1 B0 0000 jdisp insn.itype = NEC_78K_0S_bt; insn.Op1.type = o_bit; insn.Op1.reg = rA; insn.Op1.value = (code2>>4) & 0x07; jdisp(insn.Op2, insn.get_next_byte(), 3, insn); break; case 0x0A: case 0x1A: case 0x2A: case 0x3A: case 0x4A: case 0x5A: case 0x6A: case 0x7A: { //SET1 saddr.bit 0000 1010 0 B2 B1 B0 1010 Saddr-offset //SET1 PSW.bit 0000 1010 0 B2 B1 B0 1010 0001 1110 //EI 0000 1010 0 1 1 1 1010 0001 1110 uchar code3 = insn.get_next_byte(); if ( code3 == 0x1E ) { if ( code2 == 0x7A ) //EI { insn.itype = NEC_78K_0S_EI; } else //SET1 PSW.bit { insn.itype = NEC_78K_0S_set1; insn.Op1.type = o_bit; insn.Op1.reg = rPSW; insn.Op1.value = (code2>>4)&0x07; } } else //SET1 saddr.bit { insn.itype = NEC_78K_0S_set1; insn.Op1.type = o_bit; insn.Op1.dtype = dt_byte; insn.Op1.addr = saddr(code3); insn.Op1.value = (code2>>4)&0x07; } } break; case 0x06: case 0x16: case 0x26: case 0x36: case 0x46: case 0x56: case 0x66: case 0x76: //SET1 sfr.bit 0000 1010 0 B2 B1 B0 0110 Sfr-offset insn.itype = NEC_78K_0S_set1; insn.Op1.type = o_bit; insn.Op1.dtype = dt_byte; insn.Op1.addr = sfr(insn.get_next_byte()); insn.Op1.value = (code2>>4)&0x07; break; case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52: case 0x62: case 0x72: //SET1 A.bit 0000 1010 0 B2 B1 B0 0010 insn.itype = NEC_78K_0S_set1; insn.Op1.type = o_bit; insn.Op1.reg = rA; insn.Op1.value = (code2>>4)&0x07; break; case 0x0E: case 0x1E: case 0x2E: case 0x3E: case 0x4E: case 0x5E: case 0x6E: case 0x7E: //SET1 [HL].bit 0000 1010 0 B2 B1 B0 1110 insn.itype = NEC_78K_0S_set1; insn.Op1.type = o_bit; insn.Op1.reg = rHL; insn.Op1.prepost = 1; insn.Op1.value = (code2>>4)&0x07; break; case 0x8A: case 0x9A: case 0xAA: case 0xBA: case 0xCA: case 0xDA: case 0xEA: case 0xFA: { //CLR1 saddr.bit 0000 1010 1 B2 B1 B0 1010 Saddr-offset //CLR1 PSW.bit 0000 1010 1 B2 B1 B0 1010 0001 1110 //DI 0000 1010 1 1 1 1 1010 0001 1110 uchar code3 = insn.get_next_byte(); if ( code3 == 0x1E ) { if ( code2 == 0xFA ) //DI { insn.itype = NEC_78K_0S_DI; } else //CLR1 PSW.bit { insn.itype = NEC_78K_0S_clr1; insn.Op1.type = o_bit; insn.Op1.reg = rPSW; insn.Op1.value = (code2>>4)&0x07; } } else //CLR1 saddr.bit { insn.itype = NEC_78K_0S_clr1; insn.Op1.type = o_bit; insn.Op1.dtype = dt_byte; insn.Op1.addr = saddr(code3); insn.Op1.value = (code2>>4)&0x07; } } break; case 0x86: case 0x96: case 0xA6: case 0xB6: case 0xC6: case 0xD6: case 0xE6: case 0xF6: //CLR1 sfr.bit 0000 1010 1 B2 B1 B0 0110 Sfr-offset insn.itype = NEC_78K_0S_clr1; insn.Op1.type = o_bit; insn.Op1.dtype = dt_byte; insn.Op1.addr = sfr(insn.get_next_byte()); insn.Op1.value = (code2>>4)&0x07; break; case 0x82: case 0x92: case 0xA2: case 0xB2: case 0xC2: case 0xD2: case 0xE2: case 0xF2: //CLR1 A.bit 0000 1010 1 B2 B1 B0 0010 insn.itype = NEC_78K_0S_clr1; insn.Op1.type = o_bit; insn.Op1.reg = rA; insn.Op1.value = (code2>>4)&0x07; break; case 0x8E: case 0x9E: case 0xAE: case 0xBE: case 0xCE: case 0xDE: case 0xEE: case 0xFE: //CLR1 [HL].bit 0000 1010 1 B2 B1 B0 1110 insn.itype = NEC_78K_0S_clr1; insn.Op1.type = o_bit; insn.Op1.reg = rHL; insn.Op1.prepost = 1; insn.Op1.value = (code2>>4)&0x07; break; case 0xF1: case 0xF3: case 0xF5: case 0xF7: case 0xF9: case 0xFB: case 0xFD: case 0xFF: //MOV r, #byte 0000 1010 1111 R2R1R0 1 Data insn.itype = NEC_78K_0S_mov; insn.Op1.type = o_reg; insn.Op1.reg = ((code2>>1)&0x07)+rX; insn.Op2.type = o_imm; insn.Op2.dtype = dt_byte; insn.Op2.value = insn.get_next_byte(); break; case 0x21: case 0x25: case 0x27: case 0x29: case 0x2B: case 0x2D: case 0x2F: //MOV A, r 0000 1010 0010 R2R1R0 1 Except r = A. insn.itype = NEC_78K_0S_mov; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = ((code2>>1)&0x07)+rX; break; case 0xE1: case 0xE5: case 0xE7: case 0xE9: case 0xEB: case 0xED: case 0xEF: //MOV r, A 0000 1010 1110 R2R1R0 1 Except r = A. insn.itype = NEC_78K_0S_mov; insn.Op1.type = o_reg; insn.Op1.reg = ((code2>>1)&0x07)+rX; insn.Op2.type = o_reg; insn.Op2.reg = rA; break; case 0x05: case 0x07: case 0x09: case 0x0B: case 0x0D: case 0x0F: //XCH A, r 0000 1010 0000 R2R1R0 1 Except r = A, X. insn.itype = NEC_78K_0S_xch; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = ((code2>>1)&0x07)+rX; break; case 0x81: case 0x83: case 0x85: case 0x87: case 0x89: case 0x8B: case 0x8D: case 0x8F: //ADD A, r 0000 1010 1000 R2R1R0 1 insn.itype = NEC_78K_0S_add; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = ((code2>>1)&0x07)+rX; break; case 0xA1: case 0xA3: case 0xA5: case 0xA7: case 0xA9: case 0xAB: case 0xAD: case 0xAF: //ADDC A, r 0000 1010 1010 R2R1R0 1 insn.itype = NEC_78K_0S_addc; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = ((code2>>1)&0x07)+rX; break; case 0x91: case 0x93: case 0x95: case 0x97: case 0x99: case 0x9B: case 0x9D: case 0x9F: //SUB A, r 0000 1010 1001 R2R1R0 1 insn.itype = NEC_78K_0S_sub; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = ((code2>>1)&0x07)+rX; break; case 0xB1: case 0xB3: case 0xB5: case 0xB7: case 0xB9: case 0xBB: case 0xBD: case 0xBF: //SUBC A, r 0000 1010 1011 R2R1R0 1 insn.itype = NEC_78K_0S_subc; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = ((code2>>1)&0x07)+rX; break; case 0x61: case 0x63: case 0x65: case 0x67: case 0x69: case 0x6B: case 0x6D: case 0x6F: //AND A, r 0000 1010 0110 R2R1R0 1 insn.itype = NEC_78K_0S_and; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = ((code2>>1)&0x07)+rX; break; case 0x71: case 0x73: case 0x75: case 0x77: case 0x79: case 0x7B: case 0x7D: case 0x7F: //OR A, r 0000 1010 0111 R2R1R0 1 insn.itype = NEC_78K_0S_or; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = ((code2>>1)&0x07)+rX; break; case 0x41: case 0x43: case 0x45: case 0x47: case 0x49: case 0x4B: case 0x4D: case 0x4F: //XOR A, r 0000 1010 0100 R2R1R0 1 insn.itype = NEC_78K_0S_xor; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = ((code2>>1)&0x07)+rX; break; case 0x11: case 0x13: case 0x15: case 0x17: case 0x19: case 0x1B: case 0x1D: case 0x1F: //CMP A, r 0000 1010 0001 R2R1R0 1 insn.itype = NEC_78K_0S_cmp; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = ((code2>>1)&0x07)+rX; break; case 0xC1: case 0xC3: case 0xC5: case 0xC7: case 0xC9: case 0xCB: case 0xCD: case 0xCF: //INC r 0000 1010 1100 R2R1R0 1 insn.itype = NEC_78K_0S_inc; insn.Op1.type = o_reg; insn.Op1.reg = ((code2>>1)&0x07)+rX; break; case 0xD1: case 0xD3: case 0xD5: case 0xD7: case 0xD9: case 0xDB: case 0xDD: case 0xDF: //DEC r 0000 1010 1101 R2R1R0 1 insn.itype = NEC_78K_0S_dec; insn.Op1.type = o_reg; insn.Op1.reg = ((code2>>1)&0x07)+rX; break; default: // return with the error ERROR return 0; } // END switch 0x0A commands } break; // END case 0x0A case 0x0B: //XCH A, [DE] 0000 1011 insn.itype = NEC_78K_0S_xch; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = rDE; insn.Op2.prepost =1; break; case 0x0C: //HALT 0000 1100 insn.itype = NEC_78K_0S_HALT; break; case 0x0D: //XCH A, [HL+byte] 0000 1101 Data insn.itype = NEC_78K_0S_xch; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = rHL; insn.Op2.addr = insn.get_next_byte(); insn.Op2.prepost = 1; insn.Op2.xmode = 1; break; case 0x0E: //STOP 0000 1110 insn.itype = NEC_78K_0S_STOP; break; case 0x0F: //XCH A, [HL] 0000 1111 insn.itype = NEC_78K_0S_xch; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = rHL; insn.Op2.prepost = 1; break; case 0x10: //ROL A, 1 0001 0000 insn.itype = NEC_78K_0S_rol; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_imm; insn.Op2.value = 1; insn.Op2.regmode = 1; break; case 0x11: //CMP saddr, #byte 0001 0001 Saddr-offset Data insn.itype = NEC_78K_0S_cmp; insn.Op1.type = o_mem; insn.Op1.dtype = dt_byte; insn.Op1.addr = saddr(insn.get_next_byte()); insn.Op2.type = o_imm; insn.Op2.value = insn.get_next_byte(); break; case 0x12: //ROLC A, 1 0001 0010 insn.itype = NEC_78K_0S_rolc; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_imm; insn.Op2.value = 1; insn.Op2.regmode = 1; break; case 0x13: //CMP A, #byte 0001 0011 Data insn.itype = NEC_78K_0S_cmp; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_imm; insn.Op2.value = insn.get_next_byte(); break; case 0x14: //SET1 CY 0001 0100 insn.itype = NEC_78K_0S_set1; insn.Op1.type = o_phrase; insn.Op1.reg = bCY; break; case 0x15: //CMP A, saddr 0001 0101 Saddr-offset insn.itype = NEC_78K_0S_cmp; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_mem; insn.Op2.dtype = dt_byte; insn.Op2.addr = saddr(insn.get_next_byte()); break; case 0x19: //CMP A, !addr16 0001 1001 Low addr High addr insn.itype = NEC_78K_0S_cmp; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_mem; insn.Op2.dtype = dt_byte; insn.Op2.addr16 = 1; addr16(insn, insn.Op2); break; case 0x1D: //CMP A, [HL+byte] 0001 1101 Data insn.itype = NEC_78K_0S_cmp; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = rHL; insn.Op2.addr = insn.get_next_byte(); insn.Op2.prepost = 1; insn.Op2.xmode = 1; break; case 0x1F: //CMP A, [HL] 0001 1111 insn.itype = NEC_78K_0S_cmp; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = rHL; insn.Op2.prepost = 1; break; case 0x20: //RET 0010 0000 insn.itype = NEC_78K_0S_ret; break; case 0x22: //CALL !addr16 0010 0010 Low addr High addr insn.itype = NEC_78K_0S_call; //insn.Op1.offb = insn.size; insn.Op1.type = o_near; insn.Op1.addr16 = 1; addr16(insn, insn.Op1); break; case 0x24: //RETI 0010 0100 insn.itype = NEC_78K_0S_reti; break; case 0x25: { //MOV A, PSW 0010 0101 00011110 //MOV A, saddr 0010 0101 Saddr-offset insn.itype = NEC_78K_0S_mov; insn.Op1.type = o_reg; insn.Op1.reg = rA; uchar tst = insn.get_next_byte(); if ( tst == 0x1E ) { insn.Op2.type = o_reg; insn.Op2.reg = rPSW; } else { insn.Op2.type = o_mem; insn.Op2.dtype = dt_byte; insn.Op2.addr = saddr(tst); } } break; case 0x27: //MOV A, sfr 0010 0111 Sfr-offset insn.itype = NEC_78K_0S_mov; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_mem; insn.Op2.dtype = dt_byte; insn.Op2.addr = sfr(insn.get_next_byte()); break; case 0x29: //MOV A, !addr16 0010 1001 Low addr High addr insn.itype = NEC_78K_0S_mov; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_mem; insn.Op2.dtype = dt_byte; insn.Op2.addr16 = 1; addr16(insn, insn.Op2); break; case 0x2B: //MOV A, [DE] 0010 1011 insn.itype = NEC_78K_0S_mov; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = rDE; insn.Op2.prepost = 1; break; case 0x2C: //POP PSW 0010 1100 insn.itype = NEC_78K_0S_pop; insn.Op1.type = o_phrase; insn.Op1.reg = rPSW; break; case 0x2D: //MOV A, [HL+byte] 0010 1101 Data insn.itype = NEC_78K_0S_mov; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = rHL; insn.Op2.addr = insn.get_next_byte(); insn.Op2.prepost = 1; insn.Op2.xmode = 1; break; case 0x2E: //PUSH PSW 0010 1110 insn.itype = NEC_78K_0S_push; insn.Op1.type = o_phrase; insn.Op1.reg = rPSW; break; case 0x2F: //MOV A, [HL] 0010 1111 insn.itype = NEC_78K_0S_mov; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = rHL; insn.Op2.prepost = 1; break; case 0x30: //BR $addr16 0011 0000 jdisp insn.itype = NEC_78K_0S_br; jdisp(insn.Op1, insn.get_next_byte(), 2, insn); break; case 0x32: //DBNZ saddr, $addr16 0011 0010 Saddr-offset jdisp insn.itype = NEC_78K_0S_dbnz; insn.Op1.type = o_mem; insn.Op1.dtype = dt_byte; insn.Op1.addr = saddr(insn.get_next_byte()); jdisp(insn.Op2, insn.get_next_byte(), 3, insn); break; case 0x34: //DBNZ C, $addr16 0011 0100 jdisp insn.itype = NEC_78K_0S_dbnz; insn.Op1.type = o_reg; insn.Op1.reg = rC; jdisp(insn.Op2, insn.get_next_byte(), 2, insn); break; case 0x36: //DBNZ B, $addr16 0011 0110 jdisp insn.itype = NEC_78K_0S_dbnz; insn.Op1.type = o_reg; insn.Op1.reg = rB; jdisp(insn.Op2, insn.get_next_byte(), 2, insn); break; case 0x38: //BC $addr16 0011 1000 jdisp insn.itype = NEC_78K_0S_bc; jdisp(insn.Op1, insn.get_next_byte(), 2, insn); break; case 0x3A: //BNC $addr16 0011 1010 jdisp insn.itype = NEC_78K_0S_bnc; jdisp(insn.Op1, insn.get_next_byte(), 2, insn); break; case 0x3C: //BZ $addr16 0011 1100 jdisp insn.itype = NEC_78K_0S_bz; jdisp(insn.Op1, insn.get_next_byte(), 2, insn); break; case 0x3E: //BNZ $addr16 0011 1110 jdisp insn.itype = NEC_78K_0S_bnz; jdisp(insn.Op1, insn.get_next_byte(), 2, insn); break; case 0x41: //XOR saddr, #byte 0100 0001 Saddr-offset Data insn.itype = NEC_78K_0S_xor; insn.Op1.type = o_mem; insn.Op1.dtype = dt_byte; insn.Op1.addr = saddr(insn.get_next_byte()); insn.Op2.type = o_imm; insn.Op2.value = insn.get_next_byte(); break; case 0x43: //XOR A, #byte 0100 0011 Data insn.itype = NEC_78K_0S_xor; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_imm; insn.Op2.value = insn.get_next_byte(); break; case 0x45: //XOR A, saddr 0100 0101 Saddr-offset insn.itype = NEC_78K_0S_xor; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_mem; insn.Op2.dtype = dt_byte; insn.Op2.addr = saddr(insn.get_next_byte()); break; case 0x49: //XOR A, !addr16 0100 1001 Low addr High addr insn.itype = NEC_78K_0S_xor; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_mem; insn.Op2.dtype = dt_byte; insn.Op2.addr16 = 1; addr16(insn, insn.Op2); break; case 0x4D: //XOR A, [HL+byte] 0100 1101 Data insn.itype = NEC_78K_0S_xor; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = rHL; insn.Op2.addr = insn.get_next_byte(); insn.Op2.prepost = 1; insn.Op2.xmode = 1; break; case 0x4F: //XOR A, [HL] 0100 1111 insn.itype = NEC_78K_0S_xor; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = rHL; insn.Op2.prepost = 1; break; case 0x61: //AND saddr, #byte 0110 0001 Saddr-offset Data insn.itype = NEC_78K_0S_and; insn.Op1.type = o_mem; insn.Op1.dtype = dt_byte; insn.Op1.addr = saddr(insn.get_next_byte()); insn.Op2.type = o_imm; insn.Op2.value = insn.get_next_byte(); break; case 0x63: //AND A, #byte 0110 0011 Data insn.itype = NEC_78K_0S_and; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_imm; insn.Op2.value = insn.get_next_byte(); break; case 0x65: //AND A, saddr 0110 0101 Saddr-offset insn.itype = NEC_78K_0S_and; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_mem; insn.Op2.dtype = dt_byte; insn.Op2.addr = saddr(insn.get_next_byte()); break; case 0x69: //AND A, !addr16 0110 1001 Low addr High addr insn.itype = NEC_78K_0S_and; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_mem; insn.Op2.dtype = dt_byte; insn.Op2.addr16 = 1; addr16(insn, insn.Op2); break; case 0x6D: //AND A, [HL+byte] 0110 1101 Data insn.itype = NEC_78K_0S_and; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = rHL; insn.Op2.addr = insn.get_next_byte(); insn.Op2.prepost = 1; insn.Op2.xmode = 1; break; case 0x6F: //AND A, [HL] 0110 1111 insn.itype = NEC_78K_0S_and; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = rHL; insn.Op2.prepost = 1; break; case 0x71: //OR saddr, #byte 0111 0001 Saddr-offset Data insn.itype = NEC_78K_0S_or; insn.Op1.type = o_mem; insn.Op1.dtype = o_mem; insn.Op1.addr = saddr(insn.get_next_byte()); insn.Op2.type = o_imm; insn.Op2.value = insn.get_next_byte(); break; case 0x73: //OR A, #byte 0111 0011 Data insn.itype = NEC_78K_0S_or; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_imm; insn.Op2.value = insn.get_next_byte(); break; case 0x75: //OR A, saddr 0111 0101 Saddr-offset insn.itype = NEC_78K_0S_or; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_mem; insn.Op2.dtype = dt_byte; insn.Op2.addr = saddr(insn.get_next_byte()); break; case 0x79: //OR A, !addr16 0111 1001 Low addr High addr insn.itype = NEC_78K_0S_or; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_mem; insn.Op2.dtype = dt_byte; addr16(insn, insn.Op2); break; case 0x7D: //OR A, [HL+byte] 0111 1101 Data insn.itype = NEC_78K_0S_or; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = rHL; insn.Op2.addr = insn.get_next_byte(); insn.Op2.prepost = 1; insn.Op2.xmode = 1; break; case 0x7F: //OR A, [HL] 0111 1111 insn.itype = NEC_78K_0S_or; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = rHL; insn.Op2.prepost = 1; break; case 0x81: //ADD saddr, #byte 1000 0001 Saddr-offset Data insn.itype = NEC_78K_0S_add; insn.Op1.type = o_mem; insn.Op1.dtype = dt_byte; insn.Op1.addr = saddr(insn.get_next_byte()); insn.Op2.type = o_imm; insn.Op2.value = insn.get_next_byte(); break; case 0x83: //ADD A, #byte 1000 0011 Data insn.itype = NEC_78K_0S_add; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_imm; insn.Op2.value = insn.get_next_byte(); break; case 0x85: //ADD A, saddr 1000 0101 Saddr-offset insn.itype = NEC_78K_0S_add; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_mem; insn.Op2.dtype = dt_byte; insn.Op2.addr = saddr(insn.get_next_byte()); break; case 0x89: //ADD A, !addr16 1000 1001 Low addr High addr insn.itype = NEC_78K_0S_add; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_mem; insn.Op2.dtype = dt_byte; insn.Op2.addr16 = 1; addr16(insn, insn.Op2); break; case 0x8D: //ADD A, [HL+byte] 1000 1101 Data insn.itype = NEC_78K_0S_add; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = rHL; insn.Op2.addr = insn.get_next_byte(); insn.Op2.prepost = 1; insn.Op2.xmode = 1; break; case 0x8F: //ADD A, [HL] 1000 1111 insn.itype = NEC_78K_0S_add; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = rHL; insn.Op2.prepost = 1; break; case 0x80: case 0x84: case 0x88: case 0x8C: //INCW rp 1000 P1 P0 00 insn.itype = NEC_78K_0S_incw; insn.Op1.type = o_reg; insn.Op1.reg = ((code>>2)&0x03)+rAX; break; case 0x91: //SUB saddr, #byte 1001 0001 Saddr-offset Data insn.itype = NEC_78K_0S_sub; insn.Op1.type = o_mem; insn.Op1.dtype = dt_byte; insn.Op1.addr = saddr(insn.get_next_byte()); insn.Op2.type = o_imm; insn.Op2.value = insn.get_next_byte(); break; case 0x93: //SUB A, #byte 1001 0011 Data insn.itype = NEC_78K_0S_sub; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_imm; insn.Op2.value = insn.get_next_byte(); break; case 0x95: //SUB A, saddr 1001 0101 Saddr-offset insn.itype = NEC_78K_0S_sub; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_mem; insn.Op2.dtype = dt_byte; insn.Op2.addr = saddr(insn.get_next_byte()); break; case 0x99: //SUB A, !addr16 1001 1001 Low addr High addr insn.itype = NEC_78K_0S_sub; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_mem; insn.Op2.dtype = dt_byte; insn.Op2.addr16 = 1; addr16(insn, insn.Op2); break; case 0x9D: //SUB A, [HL+byte] 1001 1101 Data insn.itype = NEC_78K_0S_sub; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = rHL; insn.Op2.addr = insn.get_next_byte(); insn.Op2.prepost = 1; insn.Op2.xmode = 1; break; case 0x9F: //SUB A, [HL] 1001 1111 insn.itype = NEC_78K_0S_sub; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = rHL; insn.Op2.prepost = 1; break; case 0x90: case 0x94: case 0x98: case 0x9C: //DECW rp 1001 P1 P0 00 insn.itype = NEC_78K_0S_decw; insn.Op1.type = o_reg; insn.Op1.reg = ((code>>2)&0x03)+rAX; break; case 0xA1: //ADDC saddr,#byte 1010 0001 Saddr-offset Data insn.itype = NEC_78K_0S_addc; insn.Op1.type = o_mem; insn.Op1.dtype = dt_byte; insn.Op1.addr = saddr(insn.get_next_byte()); insn.Op2.type = o_imm; insn.Op2.value = insn.get_next_byte(); break; case 0xA3: //ADDC A, #byte 1010 0011 Data insn.itype = NEC_78K_0S_addc; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_imm; insn.Op2.value = insn.get_next_byte(); break; case 0xA5: //ADDC A, saddr 1010 0101 Saddr-offset insn.itype = NEC_78K_0S_addc; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_mem; insn.Op2.dtype = dt_byte; insn.Op2.addr = saddr(insn.get_next_byte()); break; case 0xA9: //ADDC A, !addr16 1010 1001 Low addr High addr insn.itype = NEC_78K_0S_addc; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_mem; insn.Op2.dtype = dt_byte; insn.Op2.addr16 = 1; addr16(insn, insn.Op2); break; case 0xAD: //ADDC A,[HL+byte] 1010 1101 Data insn.itype = NEC_78K_0S_addc; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = rHL; insn.Op2.addr = insn.get_next_byte(); insn.Op2.prepost = 1; insn.Op2.xmode = 1; break; case 0xAF: //ADDC A,[HL] 1010 1111 insn.itype = NEC_78K_0S_addc; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = rHL; insn.Op2.prepost = 1; break; case 0xA0: case 0xA4: case 0xA8: case 0xAC: //POP rp 1010 P1 P0 00 insn.itype = NEC_78K_0S_pop; insn.Op1.type = o_reg; insn.Op1.reg = rAX + ((code>>2)&0x03); break; case 0xA2: case 0xA6: case 0xAA: case 0xAE: //PUSH rp 1010 P1 P0 10 insn.itype = NEC_78K_0S_push; insn.Op1.type = o_reg; insn.Op1.reg = rAX + ((code>>2)&0x03); break; case 0xB0: //BR AX 1011 0000 insn.itype = NEC_78K_0S_br; insn.Op1.type = o_reg; insn.Op1.reg = rAX; break; case 0xB1: //SUBC saddr,#byte 1011 0001 Saddr-offset Data insn.itype = NEC_78K_0S_subc; insn.Op1.type = o_mem; insn.Op1.dtype = dt_byte; insn.Op1.addr = saddr(insn.get_next_byte()); insn.Op2.type = o_imm; insn.Op2.value = insn.get_next_byte(); break; case 0xB2: //BR !addr16 1011 0010 Low addr High addr insn.itype = NEC_78K_0S_br; insn.Op1.type = o_near; insn.Op1.addr16 = 1; addr16(insn, insn.Op1); break; case 0xB3: //SUBC A, #byte 1011 0011 Data insn.itype = NEC_78K_0S_subc; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_imm; insn.Op2.value = insn.get_next_byte(); break; case 0xB5: //SUBC A, saddr 1011 0101 Saddr-offset insn.itype = NEC_78K_0S_subc; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_mem; insn.Op2.dtype = dt_byte; insn.Op2.addr = saddr(insn.get_next_byte()); break; case 0xB9: //SUBC A, !addr16 1011 1001 Low addr High addr insn.itype = NEC_78K_0S_subc; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_mem; insn.Op2.dtype = dt_byte; insn.Op2.addr16 = 1; addr16(insn, insn.Op2); break; case 0xBD: //SUBC A, [HL+byte] 1011 1101 Data insn.itype = NEC_78K_0S_subc; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = rHL; insn.Op2.addr = insn.get_next_byte(); insn.Op2.prepost =1; insn.Op2.xmode =1; break; case 0xBF: //SUBC A, [HL] 1011 1111 insn.itype = NEC_78K_0S_subc; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = rHL; insn.Op2.prepost =1; break; case 0xC0: //XCH A, X 1100 0000 insn.itype = NEC_78K_0S_xch; insn.Op1.type = o_reg; insn.Op1.reg = rA; insn.Op2.type = o_reg; insn.Op2.reg = rX; break; case 0xC2: //SUBW AX, #word 1100 0010 Low byte High byte insn.itype = NEC_78K_0S_subw; insn.Op1.type = o_reg; insn.Op1.reg = rAX; imm16(insn, insn.Op2); break; case 0xC5: //INC saddr 1100 0101 Saddr-offset insn.itype = NEC_78K_0S_inc; insn.Op1.type = o_mem; insn.Op1.dtype = dt_byte; insn.Op1.addr = saddr(insn.get_next_byte()); break; case 0xC4: case 0xC8: case 0xCC: //XCHW AX, rp 1100 P1 P0 00 Only when rp = BC, DE, or HL. insn.itype = NEC_78K_0S_xchw; insn.Op1.type = o_reg; insn.Op1.reg = rAX; insn.Op2.type = o_reg; insn.Op2.reg = ((code>>2)&0x03)+rAX; break; case 0xD2: //ADDW AX, #word 1101 0010 Low byte High byte insn.itype = NEC_78K_0S_addw; insn.Op1.type = o_reg; insn.Op1.reg = rAX; imm16(insn, insn.Op2); break; case 0xD5: //DEC saddr 1101 0101 Saddr-offset insn.itype = NEC_78K_0S_inc; insn.Op1.type = o_mem; insn.Op1.dtype = dt_byte; insn.Op1.addr = saddr(insn.get_next_byte()); break; case 0xD6: { //MOVW AX, saddrp 1101 0110 Saddr-offset //MOVW AX, SP 1101 0110 0001 1100 insn.itype = NEC_78K_0S_movw; uchar tst = insn.get_next_byte(); if ( tst == 0x1C ) { insn.Op1.type = o_reg; insn.Op1.reg = rAX; insn.Op2.type = o_reg; insn.Op2.reg = rSP; } else { if ( (tst & 0x01) != 0 ) // return with the error ERROR return 0; // movw AX,saddrp insn.Op1.type = o_reg; insn.Op1.reg = rAX; insn.Op2.type = o_mem; insn.Op2.dtype = dt_word; insn.Op2.addr = saddr(tst); } } break; case 0xD4: case 0xD8: case 0xDC: //MOVW AX, rp 1101 P1 P0 00 Only when rp = BC, DE, or HL. insn.itype = NEC_78K_0S_movw; insn.Op1.type = o_reg; insn.Op1.reg = rAX; insn.Op2.type = o_reg; insn.Op2.reg = ((code>>2)&0x03)+rAX; break; case 0xE2: //CMPW AX, #word 1110 0010 Low byte High byte insn.itype = NEC_78K_0S_cmpw; insn.Op1.type = o_reg; insn.Op1.reg = rAX; insn.Op2.type = o_imm; imm16(insn, insn.Op2); break; case 0xEB: //MOV [DE], A 1110 1011 insn.itype = NEC_78K_0S_mov; insn.Op2.type = o_reg; insn.Op2.reg = rA; insn.Op1.type = o_reg; insn.Op1.reg = rDE; insn.Op1.prepost = 1; break; case 0xEF: //MOV [HL], A 1110 1111 insn.itype = NEC_78K_0S_mov; insn.Op2.type = o_reg; insn.Op2.reg = rA; insn.Op1.type = o_reg; insn.Op1.reg = rHL; insn.Op1.prepost = 1; break; case 0xE9: //MOV !addr16, A 1110 1001 Low addr High addr insn.itype = NEC_78K_0S_mov; insn.Op1.type = o_mem; insn.Op1.dtype = dt_byte; insn.Op1.addr16 = 1; addr16(insn, insn.Op1); insn.Op2.type = o_reg; insn.Op2.reg = rA; break; case 0xE5: { //MOV saddr, A 1110 0101 Saddr-offset //MOV PSW, A 1110 0101 00011110 insn.itype = NEC_78K_0S_mov; insn.Op2.type = o_reg; insn.Op2.reg = rA; uchar tst = insn.get_next_byte(); if ( tst == 0x1E ) { insn.Op1.type = o_reg; insn.Op1.reg = rPSW; } else { insn.Op1.type = o_mem; insn.Op1.dtype = dt_byte; insn.Op1.addr = saddr(tst); } } break; case 0xE6: { //MOVW saddrp, AX 1110 0110 Saddr-offset //MOVW SP, AX 1110 0110 0001 1100 insn.itype = NEC_78K_0S_movw; uchar byte2 = insn.get_next_byte(); if ( byte2 == 0x1C ) { insn.Op1.type = o_reg; insn.Op1.reg = rSP; insn.Op2.type = o_reg; insn.Op2.reg = rAX; } else { insn.Op1.type = o_mem; insn.Op1.dtype = dt_word; insn.Op1.addr = saddr(byte2); insn.Op2.type = o_reg; insn.Op2.reg = rAX; } } break; case 0xED: //MOV [HL+byte], A 1110 1101 Data insn.itype = NEC_78K_0S_mov; insn.Op1.type = o_reg; insn.Op1.reg = rHL; insn.Op1.addr = insn.get_next_byte(); insn.Op1.prepost = 1; insn.Op1.xmode = 1; insn.Op2.type = o_reg; insn.Op2.reg = rA; break; case 0xE7: //MOV sfr, A 1110 0111 Sfr-offset insn.itype = NEC_78K_0S_mov; insn.Op1.type = o_mem; insn.Op1.dtype = dt_byte; insn.Op1.addr = sfr(insn.get_next_byte()); insn.Op2.type = o_reg; insn.Op2.reg = rA; break; case 0xE4: case 0xE8: case 0xEC: //MOVW rp, AX 1110 P1 P0 00 Only when rp = BC, DE, or HL. insn.itype = NEC_78K_0S_movw; insn.Op1.type = o_reg; insn.Op1.reg = ((code>>2)&0x03)+rAX; insn.Op2.type = o_reg; insn.Op2.reg = rAX; break; case 0xF5: { //MOV saddr, #byte 1111 0101 Saddr-offset Data //MOV PSW, #byte 1111 0101 00011110 Data insn.itype = NEC_78K_0S_mov; uchar tst = insn.get_next_byte(); if ( tst != 0x1E ) { insn.Op1.type = o_mem; insn.Op1.dtype = dt_byte; insn.Op1.addr = saddr(tst); } else { insn.Op1.type = o_reg; insn.Op1.reg = rPSW; } insn.Op2.type = o_imm; insn.Op2.value = insn.get_next_byte(); } break; case 0xF7: //MOV sfr, #byte 1111 0111 Sfr-offset Data insn.itype = NEC_78K_0S_mov; insn.Op1.type = o_mem; insn.Op1.dtype = dt_byte; insn.Op1.addr = sfr(insn.get_next_byte()); insn.Op2.type = o_imm; insn.Op2.value = insn.get_next_byte(); break; case 0xF0: case 0xF4: case 0xF8: case 0xFC: //MOVW rp, #word 1111 P1 P0 00 Low byte High byte insn.itype = NEC_78K_0S_movw; insn.Op1.type = o_reg; insn.Op1.reg = ((code>>2)&0x03)+rAX; insn.Op2.type = o_imm; imm16(insn, insn.Op2); break; default: if ( (code&0xC1) == 0x40 ) { //CALLT [addr5] 01 ta4 to 0 0 insn.itype = NEC_78K_0S_callt; uint32 addr = (code&0x3E)+0x40; insn.Op1.type = o_near; insn.Op1.form = 1; insn.Op1.addr = get_byte(addr)|(get_byte(addr+1)<<8); } else { // return with the error ERROR return 0; } break; } // END main switch return insn.size; }