1711 lines
47 KiB
C++
1711 lines
47 KiB
C++
/*
|
|
* 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_dec;
|
|
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;
|
|
}
|