/* * NEC 78K0 processor module for IDA. * Copyright (c) 2006 Konstantin Norvatoff, * Freeware. */ #include "78k0.hpp" //---------------------------------------------------------------------- inline uint32 Get_Data_16bits(insn_t &insn) { uint32 low = insn.get_next_byte(); uint32 high = insn.get_next_byte(); return low | (high << 8); } //---------------------------------------------------------------------- inline void Operand_Sfr(insn_t &insn, op_t &x) { x.type = o_mem; x.dtype = dt_byte; x.offb = (uchar)insn.size; x.value = x.addr = 0xFF00 + insn.get_next_byte(); } //---------------------------------------------------------------------- inline void Operand_Registr(op_t &x, int rReg, uchar Flags) { x.type = o_reg; x.reg = (uint16)rReg; x.FormOut = Flags; } //---------------------------------------------------------------------- inline void Operand_Bit(op_t &x, uchar TypeOrd, int Bit) { x.type = o_bit; x.FormOut = TypeOrd; x.value = Bit & 7; x.offb = 0; } //---------------------------------------------------------------------- // convert short address to full address inline uint32 GetFullAddress(uchar addr) { if ( addr < 0x20 ) return 0xFF00 + addr; return 0xFE00 + addr; } //---------------------------------------------------------------------- inline void Operand_Saddr(op_t &x, uchar addr, const insn_t &insn) { x.type = o_mem; x.dtype = dt_byte; x.offb = uchar(insn.size - 1); x.addr = GetFullAddress(addr); x.value = x.addr; } //---------------------------------------------------------------------- inline void Operand_Saddr1(insn_t &insn, op_t &x) { Operand_Saddr(x, insn.get_next_byte(), insn); } //---------------------------------------------------------------------- inline void Operand_SaddrSP(insn_t &insn, op_t &x) { uchar bt = insn.get_next_byte(); if ( bt == 0x1C ) { Operand_Registr(x, rSP, 0); } else { Operand_Saddr(x, bt, insn); x.dtype = dt_word; } } //---------------------------------------------------------------------- inline void Operand_SaddrPSW(insn_t &insn, op_t &x) { uchar bt = insn.get_next_byte(); if ( bt == 0x1E ) Operand_Registr(x, rPSW, 0); else Operand_Saddr(x, bt, insn); } //---------------------------------------------------------------------- inline void Operand_SA_Bit(insn_t &insn, op_t &x, uchar Bit) { uchar bt; x.offb = (uchar)insn.size; x.type = o_bit; x.dtype = dt_byte; bt = insn.get_next_byte(); if ( bt == 0x1E ) { x.FormOut = FORM_OUT_PSW; } else { x.addr = GetFullAddress(bt); x.FormOut = FORM_OUT_S_ADDR; } x.value = Bit & 7; } //---------------------------------------------------------------------- inline void Operand_SFR_Bit(insn_t &insn, op_t &x, uchar Bit) { x.offb = (uchar)insn.size; x.addr = 0xFF00 + insn.get_next_byte(); x.type = o_bit; x.FormOut = FORM_OUT_SFR; x.value = Bit & 7; } //---------------------------------------------------------------------- inline void Operand_Data_8bits(op_t &x, uchar Data) { x.type = o_imm; x.addr = Data; x.value = Data; x.dtype = dt_byte; } //---------------------------------------------------------------------- inline void Operand_Data_8bitsI(insn_t &insn, op_t &x) { x.offb = (uchar)insn.size; Operand_Data_8bits(x, insn.get_next_byte()); } //---------------------------------------------------------------------- inline void Operand_Data_16bitsI(insn_t &insn, op_t &x) { x.type = o_imm; x.dtype = dt_word; x.offb = (uchar)insn.size; x.value = Get_Data_16bits(insn); x.addr = x.value; } //---------------------------------------------------------------------- inline void Operand_Addr16(op_t &x, uint32 Res, char Target_data_type) { x.type = o_mem; x.value = Res; x.addr = Res; x.dtype = Target_data_type; x.FormOut = FORM_OUT_VSK; } //---------------------------------------------------------------------- inline void Operand_Addr16I(insn_t &insn, op_t &x, char Target_data_type) { x.offb = (uchar)insn.size; Operand_Addr16(x, Get_Data_16bits(insn),Target_data_type); } //---------------------------------------------------------------------- // [HL+XXX] inline void Operand_HL_OffI(insn_t &insn, op_t &x) { Operand_Registr(x, rHL, FORM_OUT_SKOBA | FORM_OUT_PLUS | FORM_OUT_DISP); x.offb = (uchar)insn.size; x.addr = x.value = insn.get_next_byte(); } //---------------------------------------------------------------------- // [HL+Reg] inline void Operand_HL_OffReg(op_t &x, int rReg) { Operand_Registr(x, rHL, FORM_OUT_SKOBA | FORM_OUT_PLUS | FORM_OUT_REG); x.SecondReg = (uchar)rReg; } //---------------------------------------------------------------------- inline void Operand_NearByteI(insn_t &insn, op_t &x) { x.type = o_near; x.offb = (uchar)insn.size; x.addr = insn.ip + (signed char)insn.get_next_byte(); x.addr += insn.size; x.value = x.addr; } //---------------------------------------------------------------------- static const uchar icode[16] = { NEC_78K_0_add, NEC_78K_0_sub, NEC_78K_0_addc, NEC_78K_0_subc, NEC_78K_0_cmp, NEC_78K_0_and, NEC_78K_0_or, NEC_78K_0_xor, NEC_78K_0_xch }; //---------------------------------------------------------------------- static int Opcode_61(insn_t &insn) { uchar code = insn.get_next_byte(); uchar nib = (code >> 4) & 0xF; uchar cd = code & 0xF; // sel RBx // 11R1 R000 if ( (code & 0xD7) == 0xD0 ) { insn.itype = NEC_78K_0_sel; Operand_Registr(insn.Op1, (rRB0 + ((code >>4) & 0x2)) | ((code>>3) & 0x1), 0); return insn.size; } if ( (code & 0x80) == 0 ) { // add A, r ( 0000 1RRR ) // add r, A ( 0000 0RRR ) // sub A, r ( 0001 1RRR ) // sub r, A ( 0001 0RRR ) // addc A, r ( 0010 1RRR ) // addc r, A ( 0010 0RRR ) // subc A, r ( 0011 1RRR ) // subc r, A ( 0011 0RRR ) // cmp A, r ( 0100 1RRR ) // cmp r, A ( 0100 0RRR ) // and A, r ( 0101 1RRR ) // and r, A ( 0101 0RRR ) // or A, r ( 0110 1RRR ) // or r, A ( 0110 0RRR ) // xor A, r ( 0111 1RRR ) // xor r, A ( 0111 0RRR ) insn.itype = icode[nib]; if ( code & 0x8 ) { Operand_Registr(insn.Op1, rA, 0); Operand_Registr(insn.Op2, code & 0x7, 0); } else { Operand_Registr(insn.Op1, code & 0x7, 0); Operand_Registr(insn.Op2, rA, 0); } return insn.size; } switch ( code ) { // adjba ( 0110 0001 1000 0000 ) case 0x80: insn.itype = NEC_78K_0_adjba; break; // adjbs ( 0110 0001 1000 0000 ) case 0x90: insn.itype = NEC_78K_0_adjbs; break; default: switch ( cd ) { // mov1 A.bit, CY case 0x9: insn.itype = NEC_78K_0_mov1; Operand_Bit(insn.Op1, FORM_OUT_A, nib); Operand_Registr(insn.Op2, bCY, 0); break; case 0xA: insn.itype = NEC_78K_0_set1; Operand_Bit(insn.Op1, FORM_OUT_A, nib); break; case 0xB: insn.itype = NEC_78K_0_clr1; Operand_Bit(insn.Op1, FORM_OUT_A, nib); break; // mov1 CY, A.bit case 0xC: insn.itype = NEC_78K_0_mov1; Operand_Registr(insn.Op1, bCY, 0); Operand_Bit(insn.Op2, FORM_OUT_A, nib); break; case 0xD: insn.itype = NEC_78K_0_and1; Operand_Registr(insn.Op1, bCY, 0); Operand_Bit(insn.Op2, FORM_OUT_A, nib); break; case 0xE: insn.itype = NEC_78K_0_or1; Operand_Registr(insn.Op1, bCY, 0); Operand_Bit(insn.Op2, FORM_OUT_A, nib); break; case 0xF: insn.itype = NEC_78K_0_xor1; Operand_Registr(insn.Op1, bCY, 0); Operand_Bit(insn.Op2, FORM_OUT_A, nib); break; default: return 0; } } return insn.size; } //---------------------------------------------------------------------- static int Opcode_71(insn_t &insn) { uchar code = insn.get_next_byte(); uchar nib = code >> 4; // analyze the high bit by 1 switch ( code & 0x8F ) { // mov1 [HL].bit, CY case 0x81: insn.itype = NEC_78K_0_mov1; Operand_Bit(insn.Op1, FORM_OUT_HL, nib); Operand_Registr(insn.Op2, bCY, 0); break; // set1 [HL].bit case 0x82: insn.itype = NEC_78K_0_set1; Operand_Bit(insn.Op1, FORM_OUT_HL, nib); break; // clr1 [HL].bit case 0x83: insn.itype = NEC_78K_0_clr1; Operand_Bit(insn.Op1, FORM_OUT_HL, nib); break; // mov1 CY,[HL].bit case 0x84: insn.itype = NEC_78K_0_mov1; Operand_Registr(insn.Op1, bCY, 0); Operand_Bit(insn.Op2, FORM_OUT_HL, nib); break; // and1 CY,[HL].bit case 0x85: insn.itype = NEC_78K_0_and1; Operand_Registr(insn.Op1, bCY, 0); Operand_Bit(insn.Op2, FORM_OUT_HL, nib); break; // or1 CY,[HL].bit case 0x86: insn.itype = NEC_78K_0_or1; Operand_Registr(insn.Op1, bCY, 0); Operand_Bit(insn.Op2, FORM_OUT_HL, nib); break; // xor1 CY,[HL].bit case 0x87: insn.itype = NEC_78K_0_xor1; Operand_Registr(insn.Op1, bCY, 0); Operand_Bit(insn.Op2, FORM_OUT_HL, nib); break; // mov1 CY, A.bit case 0x8C: insn.itype = NEC_78K_0_mov1; Operand_Registr(insn.Op1, bCY, 0); Operand_Bit(insn.Op2, FORM_OUT_A, nib); break; case 0x0: switch ( nib & 7 ) { case 0: insn.itype = NEC_78K_0_STOP; break; case 1: insn.itype = NEC_78K_0_HALT; break; default: return 0; } break; // mov1 PSW.bit, CY // mov1 saddr.bit, CY case 0x1: insn.itype = NEC_78K_0_mov1; Operand_SA_Bit(insn, insn.Op1, nib); Operand_Registr(insn.Op2, bCY, 0); break; // mov1 CY, saddr.bit // mov1 CY, PSW.bit case 0x4: insn.itype = NEC_78K_0_mov1; Operand_Registr(insn.Op1, bCY, 0); Operand_SA_Bit(insn, insn.Op2, nib); break; // and1 CY, saddr.bit // and1 CY, PSW.bit case 0x5: insn.itype = NEC_78K_0_and1; Operand_Registr(insn.Op1, bCY, 0); Operand_SA_Bit(insn, insn.Op2, nib); break; // or1 CY, addr.bit // or1 CY, PSW.bit case 0x6: insn.itype = NEC_78K_0_or1; Operand_Registr(insn.Op1, bCY, 0); Operand_SA_Bit(insn, insn.Op2, nib); break; // xor1 CY, addr.bit // xor1 CY, PSW.bit case 0x7: insn.itype = NEC_78K_0_xor1; Operand_Registr(insn.Op1, bCY, 0); Operand_SA_Bit(insn, insn.Op2, nib); break; //????? // case 0x8: // insn.itype = NEC_78K_0_EI; // insn.get_next_byte(); // break; // mov1 sfr.bit, CY case 0x9: insn.itype = NEC_78K_0_mov1; Operand_SFR_Bit(insn, insn.Op1, nib); Operand_Registr(insn.Op2, bCY, 0); break; // set1 sfr.bit case 0xA: insn.itype = NEC_78K_0_set1; Operand_SFR_Bit(insn, insn.Op1, nib); break; // clr1 sfr.bit case 0xB: insn.itype = NEC_78K_0_clr1; Operand_SFR_Bit(insn, insn.Op1, nib); break; // and1 CY, sfr.bit case 0xD: insn.itype = NEC_78K_0_and1; Operand_Registr(insn.Op1, bCY, 0); Operand_SFR_Bit(insn, insn.Op2, nib); break; // bad instruction default: return 0; } return insn.size; } //---------------------------------------------------------------------- static int Opcode_31(insn_t &insn) { uchar code = insn.get_next_byte(); uchar nib = (code >> 4) & 0xF; switch ( code ) { case 0x0B:// add A,[HL+B] ( 0000 1011 ) case 0x1B:// sub A,[HL+B] ( 0001 1011 ) case 0x2B:// addc A,[HL+B] ( 0010 1011 ) case 0x3B:// subc A,[HL+B] ( 0011 1011 ) case 0x4B:// cmp A,[HL+B] ( 0100 1011 ) case 0x5B:// and A,[HL+B] ( 0101 1011 ) case 0x6B:// or A,[HL+B] ( 0110 1011 ) case 0x7B:// xor A,[HL+B] ( 0111 1011 ) case 0x8B:// xch A,[HL+B] ( 1000 1011 ) insn.itype = icode[nib]; Operand_Registr(insn.Op1, rA, 0); Operand_HL_OffReg(insn.Op2, rB); break; case 0x0A:// add A,[HL+C] ( 0000 1010 ) case 0x1A:// sub A,[HL+C] ( 0001 1010 ) case 0x2A:// addc A,[HL+C] ( 0010 1010 ) case 0x3A:// subc A,[HL+C] ( 0011 1010 ) case 0x4A:// cmp A,[HL+C] ( 0100 1010 ) case 0x5A:// and A,[HL+C] ( 0101 1010 ) case 0x6A:// or A,[HL+C] ( 0110 1010 ) case 0x7A:// xor A,[HL+C] ( 0111 1010 ) case 0x8A:// xch A,[HL+C] ( 1000 1010 ) insn.itype = icode[nib]; Operand_Registr(insn.Op1, rA, 0); Operand_HL_OffReg(insn.Op2, rC); break; case 0x98:// br AX (0011 0001 1001 1000) insn.itype = NEC_78K_0_br; Operand_Registr(insn.Op1, rAX, 0); break; case 0x88:// mulu X ( 0011 0001 1000 1000) insn.itype = NEC_78K_0_mulu; Operand_Registr(insn.Op1, rX, 0); break; case 0x82:// divuw X ( 0011 0001 1000 0010) insn.itype = NEC_78K_0_divuw; Operand_Registr(insn.Op1, rC, 0); break; case 0x90:// ror4 [HL] ( 0011 0001 1001 0000) insn.itype = NEC_78K_0_ror4; Operand_Registr(insn.Op1, rHL, FORM_OUT_SKOBA); break; case 0x80:// rol4 [HL] ( 0011 0001 1000 0000) insn.itype = NEC_78K_0_rol4; Operand_Registr(insn.Op1, rHL, FORM_OUT_SKOBA); break; default: switch ( code & 0x8F ) { // sfr.bit, $addr16 // A.bit, $addr16 // PSW.bit,$addr16 // 0xxx 0001 case 0x1: insn.itype = NEC_78K_0_btclr; Operand_SA_Bit(insn, insn.Op1, nib); Operand_NearByteI(insn, insn.Op2); break; // 0xxx 0011 case 0x3: insn.itype = NEC_78K_0_bf; Operand_SA_Bit(insn, insn.Op1, nib); Operand_NearByteI(insn, insn.Op2); break; // 0xxx 0101 case 0x5: insn.itype = NEC_78K_0_btclr; Operand_SFR_Bit(insn, insn.Op1, nib); Operand_NearByteI(insn, insn.Op2); break; // 0xxx 0110 case 0x6: insn.itype = NEC_78K_0_bt; Operand_SFR_Bit(insn, insn.Op1, nib); Operand_NearByteI(insn, insn.Op2); break; // 0xxx 0111 case 0x7: insn.itype = NEC_78K_0_bf; Operand_SFR_Bit(insn, insn.Op1, nib); Operand_NearByteI(insn, insn.Op2); break; // 0xxx 1101 case 0xD: insn.itype = NEC_78K_0_btclr; Operand_Bit(insn.Op1, FORM_OUT_A, nib); Operand_NearByteI(insn, insn.Op2); break; // 0xxx 1110 case 0xE: insn.itype = NEC_78K_0_bt; Operand_Bit(insn.Op1, FORM_OUT_A, nib); Operand_NearByteI(insn, insn.Op2); break; // 0xxx 1111 - bf case 0xF: insn.itype = NEC_78K_0_bf; Operand_Bit(insn.Op1, FORM_OUT_A, nib); Operand_NearByteI(insn, insn.Op2); break; // 1xxx 01xx // btclr case 0x85: insn.itype = NEC_78K_0_btclr; Operand_Bit(insn.Op1, FORM_OUT_HL, nib); Operand_NearByteI(insn, insn.Op2); break; // bt case 0x86: insn.itype = NEC_78K_0_bt; Operand_Bit(insn.Op1, FORM_OUT_HL, nib); Operand_NearByteI(insn, insn.Op2); break; // bf case 0x87: insn.itype = NEC_78K_0_bf; Operand_Bit(insn.Op1, FORM_OUT_HL, nib); Operand_NearByteI(insn, insn.Op2); break; default: return 0; } } return insn.size; } //---------------------------------------------------------------------- int idaapi N78K_ana(insn_t *_insn) { if ( _insn == NULL ) return 0; insn_t &insn = *_insn; uchar code = insn.get_next_byte(); switch ( code ) { // nop ( 0000 0000 ) case 0x00: insn.itype = NEC_78K_0_nop; break; // not1 CY ( 0000 0001 ) case 0x01: insn.itype = NEC_78K_0_not1; Operand_Registr(insn.Op1, bCY, 0); break; // movw AX,!addr16 ( 0000 0010) case 0x02: insn.itype = NEC_78K_0_movw; Operand_Registr(insn.Op1, rAX, 0); Operand_Addr16I(insn, insn.Op2, dt_word); break; // movw !addr16, AX ( 0000 0011) case 0x03: insn.itype = NEC_78K_0_movw; Operand_Addr16I(insn, insn.Op1, dt_word); Operand_Registr(insn.Op2, rAX, 0); break; // dbnz saddr,$addr16 (0000 0100) case 0x04: insn.itype = NEC_78K_0_dbnz; Operand_Saddr1(insn, insn.Op1); Operand_NearByteI(insn, insn.Op2); break; // xch A,[DE] ( 0000 0101 ) case 0x05: insn.itype = NEC_78K_0_xch; Operand_Registr(insn.Op1, rA, 0); Operand_Registr(insn.Op1, rDE, FORM_OUT_SKOBA); break; // Bad command case 0x06: return 0; // xch A,[HL] ( 0000 0111 ) case 0x07: insn.itype = NEC_78K_0_xch; Operand_Registr(insn.Op1, rA, 0); Operand_Registr(insn.Op1, rHL, FORM_OUT_SKOBA); break; // add A, addr16 case 0x08: insn.itype = NEC_78K_0_add; Operand_Registr(insn.Op1, rA, 0); Operand_Addr16I(insn, insn.Op2, dt_byte); break; // add A, [HL+off] case 0x09: insn.itype = NEC_78K_0_add; Operand_Registr(insn.Op1, rA, 0); Operand_HL_OffI(insn, insn.Op2); break; // set1 saddr.bit (0xxx 1010) // set1 PSW.bit (0xxx 1010) case 0x0A: case 0x1A: case 0x2A: case 0x3A: case 0x4A: case 0x5A: case 0x6A: case 0x7A: insn.itype = NEC_78K_0_set1; Operand_SA_Bit(insn, insn.Op1, code >> 4); // convert set PSW.EI to EI if ( code == 0x7A && insn.Op1.FormOut == FORM_OUT_PSW ) { insn.itype = NEC_78K_0_EI; insn.Op1.type = o_void; } break; // clr1 saddr.bit (0BBB 1011) // clr1 PSW.bit (0BBB 1011) case 0x0B: case 0x1B: case 0x2B: case 0x3B: case 0x4B: case 0x5B: case 0x6B: case 0x7B: insn.itype = NEC_78K_0_clr1; Operand_SA_Bit(insn, insn.Op1, code >> 4); // convert clr PSW.EI to DI if ( code == 0x7B && insn.Op1.FormOut == FORM_OUT_PSW ) { insn.itype = NEC_78K_0_DI; insn.Op1.type = o_void; } break; // call11 (0x800-0xFFF) case 0x0C: case 0x1C: case 0x2C: case 0x3C: case 0x4C: case 0x5C: case 0x6C: case 0x7C: insn.itype = NEC_78K_0_callf; insn.Op1.type = o_near; insn.Op1.addr = (uint32(( code & 0xF0 )<<8) | (uint32)insn.get_next_byte()) + 0x800; insn.Op1.FormOut = FORM_OUT_VSK; break; // add A, #byte case 0x0D: insn.itype = NEC_78K_0_add; Operand_Registr(insn.Op1, rA, 0); Operand_Data_8bitsI(insn, insn.Op2); break; // add A, saddr case 0x0E: insn.itype = NEC_78K_0_add; Operand_Registr(insn.Op1, rA, 0); Operand_Saddr1(insn, insn.Op2); break; // add A, [HL] case 0x0F: insn.itype = NEC_78K_0_add; Operand_Registr(insn.Op1, rA, 0); Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); break; // movw rp,#word case 0x10: case 0x12: case 0x14: case 0x16: insn.itype = NEC_78K_0_movw; Operand_Registr(insn.Op1, rAX+((code>>1)&7), 0); Operand_Data_16bitsI(insn, insn.Op2); break; // mov saddr,#byte ( 0001 0001 SADDR DATA) // mov PSW,#byte ( 0001 0001 SADDR DATA) case 0x11: insn.itype = NEC_78K_0_mov; Operand_SaddrPSW(insn, insn.Op1); Operand_Data_8bitsI(insn, insn.Op2); break; // case 0x12 - movw rp,#word // mov sfr,#byte ( 0001 0011 SFR DATA) case 0x13: insn.itype = NEC_78K_0_mov; Operand_Sfr(insn, insn.Op1); Operand_Data_8bitsI(insn, insn.Op2); break; // case 0x14 - movw rp,#word // Bad Opcode case 0x15: return 0; // case 0x16 - movw rp,#word // Bad Opcode case 0x17: return 0; // sub A, addr16 case 0x18: insn.itype = NEC_78K_0_sub; Operand_Registr(insn.Op1, rA, 0); Operand_Addr16I(insn, insn.Op2, dt_byte); break; // sub A, [HL+off] case 0x19: insn.itype = NEC_78K_0_sub; Operand_Registr(insn.Op1, rA, 0); Operand_HL_OffI(insn, insn.Op2); break; // sub A, #byte case 0x1D: insn.itype = NEC_78K_0_sub; Operand_Registr(insn.Op1, rA, 0); Operand_Data_8bitsI(insn, insn.Op2); break; // sub A, saddr case 0x1E: insn.itype = NEC_78K_0_sub; Operand_Registr(insn.Op1, rA, 0); Operand_Saddr1(insn, insn.Op2); break; // sub A, [HL] case 0x1F: insn.itype = NEC_78K_0_sub; Operand_Registr(insn.Op1, rA, 0); Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); break; // set1 CY ( 0010 0000 ) case 0x20: insn.itype = NEC_78K_0_set1; Operand_Registr(insn.Op1, bCY, 0); break; // clr1 CY ( 0010 0001 ) case 0x21: insn.itype = NEC_78K_0_clr1; Operand_Registr(insn.Op1, bCY, 0); break; // push PSW ( 0010 0010 ) case 0x22: insn.itype = NEC_78K_0_push; Operand_Registr(insn.Op1, rPSW, 0); break; // pop PSW ( 0010 0011 ) case 0x23: insn.itype = NEC_78K_0_pop; Operand_Registr(insn.Op1, rPSW, 0); break; // ror A,1 ( 0010 0100 ) case 0x24: insn.itype = NEC_78K_0_ror; Operand_Registr(insn.Op1, rA, 0); Operand_Data_8bits(insn.Op2, 1); break; // rorc A,1 ( 0010 0101 ) case 0x25: insn.itype = NEC_78K_0_rorc; Operand_Registr(insn.Op1, rA, 0); Operand_Data_8bits(insn.Op2, 1); break; // rol A,1 ( 0010 0110 ) case 0x26: insn.itype = NEC_78K_0_rol; Operand_Registr(insn.Op1, rA, 0); Operand_Data_8bits(insn.Op2, 1); break; // rolc A,1 ( 0010 0111 ) case 0x27: insn.itype = NEC_78K_0_rolc; Operand_Registr(insn.Op1, rA, 0); Operand_Data_8bits(insn.Op2, 1); break; // addc A, addr16 case 0x28: insn.itype = NEC_78K_0_addc; Operand_Registr(insn.Op1, rA, 0); Operand_Addr16I(insn, insn.Op2, dt_byte); break; // addc A, [HL+off] case 0x29: insn.itype = NEC_78K_0_addc; Operand_Registr(insn.Op1, rA, 0); Operand_HL_OffI(insn, insn.Op2); break; // addc A, #byte case 0x2D: insn.itype = NEC_78K_0_addc; Operand_Registr(insn.Op1, rA, 0); Operand_Data_8bitsI(insn, insn.Op2); break; // addc A, saddr case 0x2E: insn.itype = NEC_78K_0_addc; Operand_Registr(insn.Op1, rA, 0); Operand_Saddr1(insn, insn.Op2); break; // addc A, [HL] case 0x2F: insn.itype = NEC_78K_0_addc; Operand_Registr(insn.Op1, rA, 0); Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); break; // xch A, r (0011 0RRR) case 0x30: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: insn.itype = NEC_78K_0_xch; Operand_Registr(insn.Op1, rA, 0); Operand_Registr(insn.Op2, code & 7, 0); break; // xxx A,[HL+B], xxx A,[HL+C] case 0x31: return Opcode_31(insn); // subc A, addr16 case 0x38: insn.itype = NEC_78K_0_subc; Operand_Registr(insn.Op1, rA, 0); Operand_Addr16I(insn, insn.Op2, dt_byte); break; // subc A, [HL+off] case 0x39: insn.itype = NEC_78K_0_subc; Operand_Registr(insn.Op1, rA, 0); Operand_HL_OffI(insn, insn.Op2); break; // subc A, #byte case 0x3D: insn.itype = NEC_78K_0_subc; Operand_Registr(insn.Op1, rA, 0); Operand_Data_8bitsI(insn, insn.Op2); break; // subc A, saddr case 0x3E: insn.itype = NEC_78K_0_subc; Operand_Registr(insn.Op1, rA, 0); Operand_Saddr1(insn, insn.Op2); break; // subc A, [HL] case 0x3F: insn.itype = NEC_78K_0_subc; Operand_Registr(insn.Op1, rA, 0); Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); break; // inc r (0100 0RRR) case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: insn.itype = NEC_78K_0_inc; Operand_Registr(insn.Op1, code & 7, 0); break; // cmp A, addr16 case 0x48: insn.itype = NEC_78K_0_cmp; Operand_Registr(insn.Op1, rA, 0); Operand_Addr16I(insn, insn.Op2, dt_byte); break; // cmp A, [HL+off] case 0x49: insn.itype = NEC_78K_0_cmp; Operand_Registr(insn.Op1, rA, 0); Operand_HL_OffI(insn, insn.Op2); break; // cmp A, #byte case 0x4D: insn.itype = NEC_78K_0_cmp; Operand_Registr(insn.Op1, rA, 0); Operand_Data_8bitsI(insn, insn.Op2); break; // cmp A, saddr case 0x4E: insn.itype = NEC_78K_0_cmp; Operand_Registr(insn.Op1, rA, 0); Operand_Saddr1(insn, insn.Op2); break; // cmp A, [HL] case 0x4F: insn.itype = NEC_78K_0_cmp; Operand_Registr(insn.Op1, rA, 0); Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); break; // dec r (0101 0RRR) case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57: insn.itype = NEC_78K_0_dec; Operand_Registr(insn.Op1, code & 7, 0); break; // and A, addr16 case 0x58: insn.itype = NEC_78K_0_and; Operand_Registr(insn.Op1, rA, 0); Operand_Addr16I(insn, insn.Op2, dt_byte); break; // and A, [HL+off] case 0x59: insn.itype = NEC_78K_0_and; Operand_Registr(insn.Op1, rA, 0); Operand_HL_OffI(insn, insn.Op2); break; // and A, #byte case 0x5D: insn.itype = NEC_78K_0_and; Operand_Registr(insn.Op1, rA, 0); Operand_Data_8bitsI(insn, insn.Op2); break; // and A, saddr case 0x5E: insn.itype = NEC_78K_0_and; Operand_Registr(insn.Op1, rA, 0); Operand_Saddr1(insn, insn.Op2); break; // and A, [HL] case 0x5F: insn.itype = NEC_78K_0_and; Operand_Registr(insn.Op1, rA, 0); Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); break; // mov A, r (0110 0RRR) case 0x60: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: insn.itype = NEC_78K_0_mov; Operand_Registr(insn.Op1, rA, 0); Operand_Registr(insn.Op2, code & 7, 0); break; case 0x61: return Opcode_61(insn); // or A, addr16 case 0x68: insn.itype = NEC_78K_0_or; Operand_Registr(insn.Op1, rA, 0); Operand_Addr16I(insn, insn.Op2, dt_byte); break; // or A, [HL+off] case 0x69: insn.itype = NEC_78K_0_or; Operand_Registr(insn.Op1, rA, 0); Operand_HL_OffI(insn, insn.Op2); break; // or A, #byte case 0x6D: insn.itype = NEC_78K_0_or; Operand_Registr(insn.Op1, rA, 0); Operand_Data_8bitsI(insn, insn.Op2); break; // or A, saddr case 0x6E: insn.itype = NEC_78K_0_or; Operand_Registr(insn.Op1, rA, 0); Operand_Saddr1(insn, insn.Op2); break; // or A, [HL] case 0x6F: insn.itype = NEC_78K_0_or; Operand_Registr(insn.Op1, rA, 0); Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); break; // mov r, A (0111 0RRR) case 0x70: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: insn.itype = NEC_78K_0_mov; Operand_Registr(insn.Op1, code & 7, 0); Operand_Registr(insn.Op2, rA, 0); break; case 0x71: return Opcode_71(insn); // xor A, addr16 case 0x78: insn.itype = NEC_78K_0_xor; Operand_Registr(insn.Op1, rA, 0); Operand_Addr16I(insn, insn.Op2, dt_byte); break; // xor A, [HL+off] case 0x79: insn.itype = NEC_78K_0_xor; Operand_Registr(insn.Op1, rA, 0); Operand_HL_OffI(insn, insn.Op2); break; // xor A, #byte case 0x7D: insn.itype = NEC_78K_0_xor; Operand_Registr(insn.Op1, rA, 0); Operand_Data_8bitsI(insn, insn.Op2); break; // xor A, saddr case 0x7E: insn.itype = NEC_78K_0_xor; Operand_Registr(insn.Op1, rA, 0); Operand_Saddr1(insn, insn.Op2); break; // xor A, [HL] case 0x7F: insn.itype = NEC_78K_0_xor; Operand_Registr(insn.Op1, rA, 0); Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); break; // incw rp (1000 0PP0) case 0x80: case 0x82: case 0x84: case 0x86: insn.itype = NEC_78K_0_incw; Operand_Registr(insn.Op1, rAX+((code>>1)&7), 0); break; // inc saddr ( 1000 0001 SADDR) case 0x81: insn.itype = NEC_78K_0_inc; Operand_Saddr1(insn, insn.Op1); break; // xch A, saddr ( 1000 0011 SADDR ) case 0x83: insn.itype = NEC_78K_0_xch; Operand_Registr(insn.Op1, rA, 0); Operand_Saddr1(insn, insn.Op2); break; // mov A,[DE] ( 1000 0101) case 0x85: insn.itype = NEC_78K_0_mov; Operand_Registr(insn.Op1, rA, 0); Operand_Registr(insn.Op2, rDE, FORM_OUT_SKOBA); break; // mov A,[HL] ( 1000 0111) case 0x87: insn.itype = NEC_78K_0_mov; Operand_Registr(insn.Op1, rA, 0); Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); break; // add saddr, #byte case 0x88: insn.itype = NEC_78K_0_add; Operand_Saddr1(insn, insn.Op1); Operand_Data_8bitsI(insn, insn.Op2); break; // movw AX, SP ( 1000 1001 0001 1100 ) // movw AX, SADDRP ( 1000 1001 SADDRP ) case 0x89: insn.itype = NEC_78K_0_movw; Operand_Registr(insn.Op1, rAX, 0); Operand_SaddrSP(insn, insn.Op2); break; // dbnz C,$addr16 (1000 1010 JDISP ) case 0x8A: insn.itype = NEC_78K_0_dbnz; Operand_Registr(insn.Op1, rC, 0); Operand_NearByteI(insn, insn.Op2); break; // dbnz B,$addr16 (1000 1011 JDISP ) case 0x8B: insn.itype = NEC_78K_0_dbnz; Operand_Registr(insn.Op1, rB, 0); Operand_NearByteI(insn, insn.Op2); break; // bt xxxxxxxx case 0x8C: case 0x9C: case 0xAC: case 0xBC: case 0xCC: case 0xDC: case 0xEC: case 0xFC: insn.itype = NEC_78K_0_bt; Operand_SA_Bit(insn, insn.Op1, code >> 4); Operand_NearByteI(insn, insn.Op2); break; // bc $addr16 (1000 1101 JDISP ) case 0x8D: insn.itype = NEC_78K_0_bc; Operand_NearByteI(insn, insn.Op1); break; // mov A,!addr16 ( 1000 1110 LOW HIGH) case 0x8E: insn.itype = NEC_78K_0_mov; Operand_Registr(insn.Op1, rA, 0); Operand_Addr16I(insn, insn.Op2, dt_byte); break; // ret ( 1000 1111 ) case 0x8F: insn.itype = NEC_78K_0_reti; break; // decw case 0x90: case 0x92: case 0x94: case 0x96: insn.itype = NEC_78K_0_decw; Operand_Registr(insn.Op1, rAX+((code>>1)&7), 0); break; // dec saddr ( 1001 0001 SADDR) case 0x91: insn.itype = NEC_78K_0_dec; Operand_Saddr1(insn, insn.Op1); break; // xch A, sfr ( 1001 0011 SFR ) case 0x93: insn.itype = NEC_78K_0_xch; Operand_Registr(insn.Op1, rA, 0); Operand_Sfr(insn, insn.Op2); break; // mov [DE], A ( 1001 0101) case 0x95: insn.itype = NEC_78K_0_mov; Operand_Registr(insn.Op1, rDE, FORM_OUT_SKOBA); Operand_Registr(insn.Op2, rA, 0); break; // mov [HL], A ( 1001 0111) case 0x97: insn.itype = NEC_78K_0_mov; Operand_Registr(insn.Op1, rHL, FORM_OUT_SKOBA); Operand_Registr(insn.Op2, rA, 0); break; // sub saddr, #byte case 0x98: insn.itype = NEC_78K_0_sub; Operand_Saddr1(insn, insn.Op1); Operand_Data_8bitsI(insn, insn.Op2); break; // movw SP, AX ( 1001 1001 0001 1100 ) // movw SADDRP, AX ( 1001 1001 SADDRP ) case 0x99: insn.itype = NEC_78K_0_movw; Operand_SaddrSP(insn, insn.Op1); Operand_Registr(insn.Op2, rAX, 0); break; // call !addr16 ( 1001 1010 LOW HIGH ) case 0x9A: insn.itype = NEC_78K_0_call; insn.Op1.FormOut = FORM_OUT_VSK;// outputting char '!' insn.Op1.type = o_near; insn.Op1.dtype = dt_word; insn.Op1.offb = (uchar)insn.size; insn.Op1.addr = Get_Data_16bits(insn); break; // br !addr16 (1111 1011 LOW HIGH) case 0x9B: insn.itype = NEC_78K_0_br; insn.Op1.FormOut = FORM_OUT_VSK; insn.Op1.type = o_near; insn.Op1.dtype = dt_word; insn.Op1.offb = (uchar)insn.size; insn.Op1.value = insn.Op1.addr = Get_Data_16bits(insn); break; // case 9C - bt // bnc $addr16 (1001 1101 JDISP ) case 0x9D: insn.itype = NEC_78K_0_bnc; Operand_NearByteI(insn, insn.Op1); break; // mov !addr16, A ( 1001 1110 LOW HIGH) case 0x9E: insn.itype = NEC_78K_0_mov; Operand_Addr16I(insn, insn.Op1, dt_byte); Operand_Registr(insn.Op2, rA, 0); break; // retb ( 1001 1111 ) case 0x9F: insn.itype = NEC_78K_0_retb; break; // mov r,#byte (1010 0RRR) case 0xA0: case 0xA1: case 0xA2: case 0xA3: case 0xA4: case 0xA5: case 0xA6: case 0xA7: insn.itype = NEC_78K_0_mov; Operand_Registr(insn.Op1, code & 7, 0); Operand_Data_8bitsI(insn, insn.Op2); break; // addc saddr, #byte case 0xA8: insn.itype = NEC_78K_0_addc; Operand_Saddr1(insn, insn.Op1); Operand_Data_8bitsI(insn, insn.Op2); break; // movw AX, SFR ( 1010 1001 SFR ) case 0xA9: insn.itype = NEC_78K_0_movw; Operand_Registr(insn.Op1, rAX, 0); Operand_Sfr(insn, insn.Op2); break; // mov A,[HL+C] ( 1010 1010) case 0xAA: insn.itype = NEC_78K_0_mov; Operand_Registr(insn.Op1, rA, 0); Operand_HL_OffReg(insn.Op2, rC); break; // mov A,[HL+B] ( 1010 1011) case 0xAB: insn.itype = NEC_78K_0_mov; Operand_Registr(insn.Op1, rA, 0); Operand_HL_OffReg(insn.Op2, rB); break; // case 0xAC - bt // bz $addr16 (1010 1101 JDISP ) case 0xAD: insn.itype = NEC_78K_0_bz; Operand_NearByteI(insn, insn.Op1); break; // mov A,[HL+byte] ( 1010 1110) case 0xAE: insn.itype = NEC_78K_0_mov; Operand_Registr(insn.Op1, rA, 0); Operand_HL_OffI(insn, insn.Op2); break; // ret ( 1010 1111 ) case 0xAF: insn.itype = NEC_78K_0_ret; break; // pop case 0xB0: case 0xB2: case 0xB4: case 0xB6: insn.itype=NEC_78K_0_pop; Operand_Registr(insn.Op1, rAX+((code>>1)&7), 0); break; // Push case 0xB1: case 0xB3: case 0xB5: case 0xB7: insn.itype=NEC_78K_0_push; Operand_Registr(insn.Op1, rAX+((code>>1)&7), 0); break; // subc saddr, #byte case 0xB8: insn.itype = NEC_78K_0_subc; Operand_Saddr1(insn, insn.Op1); Operand_Data_8bitsI(insn, insn.Op2); break; // movw SFR, AX ( 1011 1001 SFR ) case 0xB9: insn.itype = NEC_78K_0_movw; Operand_Sfr(insn, insn.Op1); Operand_Registr(insn.Op2, rAX, 0); break; // mov [HL+B], A ( 1011 1010) case 0xBA: insn.itype = NEC_78K_0_mov; Operand_HL_OffReg(insn.Op1, rC); Operand_Registr(insn.Op2, rA, 0); break; // mov [HL+B], A ( 1011 1011) case 0xBB: insn.itype = NEC_78K_0_mov; Operand_HL_OffReg(insn.Op1, rB); Operand_Registr(insn.Op2, rA, 0); break; // case 0xBC - bt // bnz $addr16 (1011 1101 JDISP ) case 0xBD: insn.itype = NEC_78K_0_bnz; Operand_NearByteI(insn, insn.Op1); break; // mov [HL+byte], A ( 1011 1110) case 0xBE: insn.itype = NEC_78K_0_mov; Operand_HL_OffI(insn, insn.Op1); Operand_Registr(insn.Op2, rA, 0); break; // brk ( 1011 1111 ) case 0xBF: insn.itype = NEC_78K_0_brk; break; // movw AX, rp (1100 0PP0) case 0xC0: case 0xC2: case 0xC4: case 0xC6: insn.itype = NEC_78K_0_movw; Operand_Registr(insn.Op1, rAX, 0); Operand_Registr(insn.Op2, rAX+((code>>1)&7), 0); break; // cmp saddr, #byte case 0xC8: insn.itype = NEC_78K_0_cmp; Operand_Saddr1(insn, insn.Op1); Operand_Data_8bitsI(insn, insn.Op2); break; // addw AX,#word ( 1100 1010 LOW HIGH) case 0xCA: insn.itype = NEC_78K_0_addw; Operand_Registr(insn.Op1, rAX, 0); Operand_Data_16bitsI(insn, insn.Op2); break; // case 0xCC - bt // xch A,!addr ( 1100 1110 LOW HIGH ) case 0xCE: insn.itype = NEC_78K_0_xch; Operand_Registr(insn.Op1, rA, 0); Operand_Addr16I(insn, insn.Op2, dt_byte); break; // movw rp, AX (1101 0PP0) case 0xD0: case 0xD2: case 0xD4: case 0xD6: insn.itype = NEC_78K_0_movw; Operand_Registr(insn.Op1, rAX+((code>>1)&7), 0); Operand_Registr(insn.Op2, rAX, 0); break; // and saddr, #byte case 0xD8: insn.itype = NEC_78K_0_and; Operand_Saddr1(insn, insn.Op1); Operand_Data_8bitsI(insn, insn.Op2); break; // subw AX,#word ( 1101 1010 LOW HIGH) case 0xDA: insn.itype = NEC_78K_0_subw; Operand_Registr(insn.Op1, rAX, 0); Operand_Data_16bitsI(insn, insn.Op2); break; // case 0xDC - bt // xch A,[HL+byte] ( 1101 1110 DATA ) case 0xDE: insn.itype = NEC_78K_0_xch; Operand_Registr(insn.Op1, rA, 0); Operand_HL_OffI(insn, insn.Op2); break; // xchw AX, rp (1101 0PP0) case 0xE0: case 0xE2: case 0xE4: case 0xE6: insn.itype = NEC_78K_0_xchw; Operand_Registr(insn.Op1, rAX, 0); Operand_Registr(insn.Op2, rAX+((code>>1)&7), 0); break; // or saddr, #byte case 0xE8: insn.itype = NEC_78K_0_or; Operand_Saddr1(insn, insn.Op1); Operand_Data_8bitsI(insn, insn.Op2); break; // cmpw AX,#word ( 1110 1010 LOW HIGH) case 0xEA: insn.itype = NEC_78K_0_cmpw; Operand_Registr(insn.Op1, rAX, 0); Operand_Data_16bitsI(insn, insn.Op2); break; // case 0xEC - bt // movw SP,#word ( 1110 1110 0001 1100 LOW HIGH) // movw saddrp,#word ( 1110 1110 SADDR LOW HIGH) case 0xEE: insn.itype = NEC_78K_0_movw; Operand_SaddrSP(insn, insn.Op1); Operand_Data_16bitsI(insn, insn.Op2); break; // mov A, saddr ( 1111 0000 A SADDRR ) // mov A, PSW ( 1111 0000 A PSW ) case 0xF0: insn.itype = NEC_78K_0_mov; Operand_SaddrPSW(insn, insn.Op2); Operand_Registr(insn.Op1, rA, 0); break; // mov saddr, A ( 1111 0010 SADDRR A) // mov PSW, A ( 1111 0010 SADDRR A) case 0xF2: insn.itype = NEC_78K_0_mov; Operand_SaddrPSW(insn, insn.Op1); Operand_Registr(insn.Op2, rA, 0); break; // mov A, sfr ( 1111 0100 A SFR ) case 0xF4: insn.itype = NEC_78K_0_mov; Operand_Registr(insn.Op1, rA, 0); Operand_Sfr(insn, insn.Op2); break; // mov saddr, A ( 1111 0110 SFR A) case 0xF6: insn.itype = NEC_78K_0_mov; Operand_Sfr(insn, insn.Op1); Operand_Registr(insn.Op2, rA, 0); break; // xor saddr, #byte case 0xF8: insn.itype = NEC_78K_0_xor; Operand_Saddr1(insn, insn.Op1); Operand_Data_8bitsI(insn, insn.Op2); break; // br $addr16 (1111 01010 JDISP) case 0xFA: insn.itype = NEC_78K_0_br; Operand_NearByteI(insn, insn.Op1); break; // case 0xFC - bt // movw sfr,#word ( 1111 1110 SFR LOW HIGH) case 0xFE: insn.itype = NEC_78K_0_movw; Operand_Sfr(insn, insn.Op1); Operand_Data_16bitsI(insn, insn.Op2); break; // callt case 0xC1:case 0xC3:case 0xC5:case 0xC7:case 0xC9:case 0xCB:case 0xCD:case 0xCF: case 0xD1:case 0xD3:case 0xD5:case 0xD7:case 0xD9:case 0xDB:case 0xDD:case 0xDF: case 0xE1:case 0xE3:case 0xE5:case 0xE7:case 0xE9:case 0xEB:case 0xED:case 0xEF: case 0xF1:case 0xF3:case 0xF5:case 0xF7:case 0xF9:case 0xFB:case 0xFD:case 0xFF: insn.itype = NEC_78K_0_callt; Operand_Addr16(insn.Op1,0x40 + (code & 0x3E), dt_word); // change format insn.Op1.FormOut = FORM_OUT_SKOBA; break; // unknown code - return error default: return 0; } return insn.size; }