285 lines
13 KiB
C++
285 lines
13 KiB
C++
/*
|
|
* Interactive disassembler (IDA).
|
|
* Copyright (c) 1990-95 by Ilfak Guilfanov.
|
|
* ALL RIGHTS RESERVED.
|
|
* FIDO: 2:5020/209
|
|
* E-mail: ig@estar.msk.su
|
|
*
|
|
*/
|
|
|
|
#include "m65.hpp"
|
|
|
|
static const uchar nmos[256] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
/* 00 */ M65_brk, M65_ora, M65_null,M65_slo, M65_nop, M65_ora, M65_asl, M65_slo, M65_php, M65_ora, M65_asl, M65_anc, M65_nop, M65_ora, M65_asl, M65_slo, /* 00 */
|
|
/* 10 */ M65_bpl, M65_ora, M65_null,M65_slo, M65_nop, M65_ora, M65_asl, M65_slo, M65_clc, M65_ora, M65_nop, M65_slo, M65_nop, M65_ora, M65_asl, M65_slo, /* 10 */
|
|
/* 20 */ M65_jsr, M65_and, M65_null,M65_rla, M65_bit, M65_and, M65_rol, M65_rla, M65_plp, M65_and, M65_rol, M65_anc, M65_bit, M65_and, M65_rol, M65_rla, /* 20 */
|
|
/* 30 */ M65_bmi, M65_and, M65_null,M65_rla, M65_nop, M65_and, M65_rol, M65_rla, M65_sec, M65_and, M65_nop, M65_rla, M65_nop, M65_and, M65_rol, M65_rla, /* 30 */
|
|
/* 40 */ M65_rti, M65_eor, M65_null,M65_sre, M65_nop, M65_eor, M65_lsr, M65_sre, M65_pha, M65_eor, M65_lsr, M65_asr, M65_jmp, M65_eor, M65_lsr, M65_sre, /* 40 */
|
|
/* 50 */ M65_bvc, M65_eor, M65_null,M65_sre, M65_nop, M65_eor, M65_lsr, M65_sre, M65_cli, M65_eor, M65_nop, M65_sre, M65_nop, M65_eor, M65_lsr, M65_sre, /* 50 */
|
|
/* 60 */ M65_rts, M65_adc, M65_null,M65_rra, M65_nop, M65_adc, M65_ror, M65_rra, M65_pla, M65_adc, M65_ror, M65_arr, M65_jmpi,M65_adc, M65_ror, M65_rra, /* 60 */
|
|
/* 70 */ M65_bvs, M65_adc, M65_null,M65_rra, M65_nop, M65_adc, M65_ror, M65_rra, M65_sei, M65_adc, M65_nop, M65_rra, M65_nop, M65_adc, M65_ror, M65_rra, /* 70 */
|
|
/* 80 */ M65_nop, M65_sta, M65_nop, M65_sax, M65_sty, M65_sta, M65_stx, M65_sax, M65_dey, M65_nop, M65_txa, M65_ane, M65_sty, M65_sta, M65_stx, M65_sax, /* 80 */
|
|
/* 90 */ M65_bcc, M65_sta, M65_null,M65_sha, M65_sty, M65_sta, M65_stx, M65_sax, M65_tya, M65_sta, M65_txs, M65_shs, M65_shy, M65_sta, M65_shx, M65_sha, /* 90 */
|
|
/* A0 */ M65_ldy, M65_lda, M65_ldx, M65_lax, M65_ldy, M65_lda, M65_ldx, M65_lax, M65_tay, M65_lda, M65_tax, M65_lxa, M65_ldy, M65_lda, M65_ldx, M65_lax, /* A0 */
|
|
/* B0 */ M65_bcs, M65_lda, M65_null,M65_lax, M65_ldy, M65_lda, M65_ldx, M65_lax, M65_clv, M65_lda, M65_tsx, M65_lae, M65_ldy, M65_lda, M65_ldx, M65_lax, /* B0 */
|
|
/* C0 */ M65_cpy, M65_cmp, M65_nop, M65_dcp, M65_cpy, M65_cmp, M65_dec, M65_dcp, M65_iny, M65_cmp, M65_dex, M65_sbx, M65_cpy, M65_cmp, M65_dec, M65_dcp, /* C0 */
|
|
/* D0 */ M65_bne, M65_cmp, M65_null,M65_dcp, M65_nop, M65_cmp, M65_dec, M65_dcp, M65_cld, M65_cmp, M65_nop, M65_dcp, M65_nop, M65_cmp, M65_dec, M65_dcp, /* D0 */
|
|
/* E0 */ M65_cpx, M65_sbc, M65_nop, M65_isb, M65_cpx, M65_sbc, M65_inc, M65_isb, M65_inx, M65_sbc, M65_nop, M65_sbc, M65_cpx, M65_sbc, M65_inc, M65_isb, /* E0 */
|
|
/* F0 */ M65_beq, M65_sbc, M65_null,M65_isb, M65_nop, M65_sbc, M65_inc, M65_isb, M65_sed, M65_sbc, M65_nop, M65_isb, M65_nop, M65_sbc, M65_inc, M65_isb /* F0 */
|
|
};
|
|
|
|
static const uchar cmos[256] =
|
|
{
|
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
/* 00 */ M65_brk, M65_ora, M65_null,M65_null,M65_tsb, M65_ora, M65_asl, M65_rmb0,M65_php, M65_ora, M65_asl, M65_null,M65_tsb, M65_ora, M65_asl, M65_bbr0, /* 00 */
|
|
/* 10 */ M65_bpl, M65_ora, M65_ora, M65_null,M65_trb, M65_ora, M65_asl, M65_rmb1,M65_clc, M65_ora, M65_inc, M65_null,M65_trb, M65_ora, M65_asl, M65_bbr1, /* 10 */
|
|
/* 20 */ M65_jsr, M65_and, M65_null,M65_null,M65_bit, M65_and, M65_rol, M65_rmb2,M65_plp, M65_and, M65_rol, M65_null,M65_bit, M65_and, M65_rol, M65_bbr2, /* 20 */
|
|
/* 30 */ M65_bmi, M65_and, M65_and, M65_null,M65_bit, M65_and, M65_rol, M65_rmb3,M65_sec, M65_and, M65_dec, M65_null,M65_bit, M65_and, M65_rol, M65_bbr3, /* 30 */
|
|
/* 40 */ M65_rti, M65_eor, M65_null,M65_null,M65_null,M65_eor, M65_lsr, M65_rmb4,M65_pha, M65_eor, M65_lsr, M65_null,M65_jmp, M65_eor, M65_lsr, M65_bbr4, /* 40 */
|
|
/* 50 */ M65_bvc, M65_eor, M65_eor, M65_null,M65_null,M65_eor, M65_lsr, M65_rmb5,M65_cli, M65_eor, M65_phy, M65_null,M65_null,M65_eor, M65_lsr, M65_bbr5, /* 50 */
|
|
/* 60 */ M65_rts, M65_adc, M65_null,M65_null,M65_stz, M65_adc, M65_ror, M65_rmb6,M65_pla, M65_adc, M65_ror, M65_null,M65_jmpi,M65_adc, M65_ror, M65_bbr6, /* 60 */
|
|
/* 70 */ M65_bvs, M65_adc, M65_adc, M65_null,M65_stz, M65_adc, M65_ror, M65_rmb7,M65_sei, M65_adc, M65_ply, M65_null,M65_jmpi,M65_adc, M65_ror, M65_bbr7, /* 70 */
|
|
/* 80 */ M65_bra, M65_sta, M65_null,M65_null,M65_sty, M65_sta, M65_stx, M65_smb0,M65_dey, M65_bit, M65_txa, M65_null,M65_sty, M65_sta, M65_stx, M65_bbs0, /* 80 */
|
|
/* 90 */ M65_bcc, M65_sta, M65_sta, M65_null,M65_sty, M65_sta, M65_stx, M65_smb1,M65_tya, M65_sta, M65_txs, M65_null,M65_stz, M65_sta, M65_stz, M65_bbs1, /* 90 */
|
|
/* A0 */ M65_ldy, M65_lda, M65_ldx, M65_null,M65_ldy, M65_lda, M65_ldx, M65_smb2,M65_tay, M65_lda, M65_tax, M65_null,M65_ldy, M65_lda, M65_ldx, M65_bbs2, /* A0 */
|
|
/* B0 */ M65_bcs, M65_lda, M65_lda, M65_null,M65_ldy, M65_lda, M65_ldx, M65_smb3,M65_clv, M65_lda, M65_tsx, M65_null,M65_ldy, M65_lda, M65_ldx, M65_bbs3, /* B0 */
|
|
/* C0 */ M65_cpy, M65_cmp, M65_null,M65_null,M65_cpy, M65_cmp, M65_dec, M65_smb4,M65_iny, M65_cmp, M65_dex, M65_wai,M65_cpy, M65_cmp, M65_dec, M65_bbs4, /* C0 */
|
|
/* D0 */ M65_bne, M65_cmp, M65_cmp, M65_null,M65_null,M65_cmp, M65_dec, M65_smb5,M65_cld, M65_cmp, M65_phx, M65_stp,M65_null,M65_cmp, M65_dec, M65_bbs5, /* D0 */
|
|
/* E0 */ M65_cpx, M65_sbc, M65_null,M65_null,M65_cpx, M65_sbc, M65_inc, M65_smb6,M65_inx, M65_sbc, M65_nop, M65_null,M65_cpx, M65_sbc, M65_inc, M65_bbs6, /* E0 */
|
|
/* F0 */ M65_beq, M65_sbc, M65_sbc, M65_null,M65_null,M65_sbc, M65_inc, M65_smb7,M65_sed, M65_sbc, M65_plx, M65_null,M65_null,M65_sbc, M65_inc, M65_bbs7 /* F0 */
|
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
|
};
|
|
|
|
//----------------------------------------------------------------------
|
|
int m6502_t::ana(insn_t *_insn)
|
|
{
|
|
insn_t &insn = *_insn;
|
|
insn.Op1.dtype = dt_byte;
|
|
uchar code = insn.get_next_byte();
|
|
insn.itype = (is_cmos ? cmos : nmos)[code];
|
|
if ( insn.itype == M65_null )
|
|
return 0;
|
|
|
|
switch ( code & 0x1F )
|
|
{
|
|
// +08 PHP PLP PHA PLA DEY TAY INY INX Implied
|
|
// +18 CLC SEC CLI SEI TYA CLV CLD SED Implied
|
|
// +1a NOP* NOP* NOP* NOP* TXS TSX NOP* NOP* Implied
|
|
// +1a inc dec phy ply txs tsx phx ply
|
|
case 0x1A:
|
|
case 0x08:
|
|
case 0x18:
|
|
switch ( insn.itype )
|
|
{
|
|
case M65_inc:
|
|
case M65_dec:
|
|
insn.Op1.type = o_reg;
|
|
insn.Op1.reg = rA;
|
|
}
|
|
break;
|
|
// +0a ASL ROL LSR ROR TXA TAX DEX NOP Accu/impl
|
|
case 0x0A:
|
|
switch ( insn.itype )
|
|
{
|
|
case M65_asl:
|
|
case M65_rol:
|
|
case M65_lsr:
|
|
case M65_ror:
|
|
insn.Op1.type = o_reg;
|
|
insn.Op1.reg = rA;
|
|
}
|
|
break;
|
|
// +00 BRK JSR RTI RTS NOP*/bra LDY CPY CPX Impl/immed
|
|
// +02 t t t t NOP*t LDX NOP*t NOP*t ? /immed
|
|
// +09 ORA AND EOR ADC NOP* LDA CMP SBC Immediate
|
|
// +0b ANC** ANC** ASR** ARR** ANE** LXA** SBX** SBC* Immediate
|
|
case 0x00:
|
|
case 0x02:
|
|
case 0x09:
|
|
case 0x0B:
|
|
switch ( insn.itype )
|
|
{
|
|
case M65_jsr:
|
|
insn.Op1.dtype = dt_code;
|
|
insn.Op1.type = o_near;
|
|
insn.Op1.addr = insn.get_next_word();
|
|
break;
|
|
case M65_brk:
|
|
case M65_rti:
|
|
case M65_rts:
|
|
case M65_wai:
|
|
|
|
// no operands
|
|
break;
|
|
case M65_bra:
|
|
goto M65_RELATIVE;
|
|
default:
|
|
insn.Op1.type = o_imm;
|
|
insn.Op1.value = insn.get_next_byte();
|
|
break;
|
|
}
|
|
break;
|
|
// +0c NOP*/tsb BIT JMP JMP () STY LDY CPY CPX Absolute
|
|
// +0d ORA AND EOR ADC STA LDA CMP SBC Absolute
|
|
// +0e ASL ROL LSR ROR STX LDX DEC INC Absolute
|
|
// +0f SLO* RLA* SRE* RRA* SAX* LAX* DCP* ISB* Absolute
|
|
// +0f bbr0 bbr2 bbr4 bbr6 bbs0 bbs2 bbs4 bbs6 Zero page relative
|
|
case 0x0F:
|
|
if ( is_cmos )
|
|
goto ZP_RELATIVE;
|
|
case 0x0C:
|
|
case 0x0D:
|
|
case 0x0E:
|
|
M65_ABSOLUTE:
|
|
switch ( insn.itype )
|
|
{
|
|
case M65_jmp:
|
|
insn.Op1.dtype = dt_code;
|
|
insn.Op1.type = o_near;
|
|
break;
|
|
case M65_jmpi:
|
|
insn.Op1.dtype = dt_word;
|
|
insn.indirect = 1;
|
|
/* no break */
|
|
default:
|
|
insn.Op1.type = o_mem;
|
|
break;
|
|
}
|
|
insn.Op1.addr = insn.get_next_word();
|
|
break;
|
|
// +1c NOP*/trb NOP*/bit NOP* NOP*/jmp SHY**/stz LDY NOP* NOP* Absolute, x
|
|
// +1d ORA AND EOR ADC STA LDA CMP SBC Absolute, x
|
|
// +1e ASL ROL LSR ROR SHX**y) LDX y) DEC INC Absolute, x
|
|
// +1f SLO* RLA* SRE* RRA* SHA**y) LAX* y) DCP ISB Absolute, x
|
|
// +0f bbr1 bbr3 bbr5 bbr7 bbs1 bbs3 bbs5 bbs7 Zero page relative
|
|
case 0x1F:
|
|
if ( is_cmos )
|
|
{
|
|
ZP_RELATIVE:
|
|
insn.Op1.type = o_mem;
|
|
insn.Op1.addr = insn.get_next_byte();
|
|
insn.Op2.dtype = dt_code;
|
|
insn.Op2.type = o_near;
|
|
char x = insn.get_next_byte();
|
|
insn.Op2.addr = insn.ip + insn.size + x;
|
|
break;
|
|
}
|
|
/* fall thru */
|
|
case 0x1C:
|
|
case 0x1D:
|
|
case 0x1E:
|
|
insn.Op1.type = o_displ;
|
|
insn.Op1.phrase = rX;
|
|
switch ( insn.itype )
|
|
{
|
|
case M65_stz:
|
|
if ( code == 0x9E )
|
|
break;
|
|
// no break
|
|
case M65_trb:
|
|
goto M65_ABSOLUTE;
|
|
case M65_shx:
|
|
case M65_sha:
|
|
case M65_ldx:
|
|
case M65_lax:
|
|
insn.Op1.phrase = rY;
|
|
break;
|
|
case M65_jmpi:
|
|
insn.Op1.phrase = riX;
|
|
break;
|
|
}
|
|
insn.Op1.addr = insn.get_next_word();
|
|
break;
|
|
// +19 ORA AND EOR ADC STA LDA CMP SBC Absolute, y
|
|
// +1b SLO* RLA* SRE* RRA* SHS** LAS** DCP* ISB* Absolute, y
|
|
case 0x19:
|
|
case 0x1B:
|
|
if ( insn.itype == M65_stp )
|
|
// no operands
|
|
break;
|
|
insn.Op1.type = o_displ;
|
|
insn.Op1.phrase = rY;
|
|
insn.Op1.addr = insn.get_next_word();
|
|
break;
|
|
// +10 BPL BMI BVC BVS BCC BCS BNE BEQ Relative
|
|
case 0x10:
|
|
M65_RELATIVE:
|
|
insn.Op1.dtype = dt_code;
|
|
insn.Op1.type = o_near;
|
|
{
|
|
char x = insn.get_next_byte();
|
|
insn.Op1.addr = insn.ip + insn.size + x;
|
|
}
|
|
break;
|
|
// +01 ORA AND EOR ADC STA LDA CMP SBC (indir, x)
|
|
// +03 SLO* RLA* SRE* RRA* SAX* LAX* y) DCP* ISB* (indir, x)
|
|
case 0x01:
|
|
case 0x03:
|
|
insn.Op1.type = o_displ;
|
|
insn.Op1.phrase = uint16((insn.itype == M65_lax) ? riY : riX);
|
|
insn.Op1.addr = insn.get_next_byte(); // what about LAX?
|
|
break;
|
|
// +11 ORA AND EOR ADC STA LDA CMP SBC (indir), y
|
|
// +13 SLO* RLA* SRE* RRA* SHA** LAX* DCP* ISB* (indir), y
|
|
case 0x11:
|
|
case 0x13:
|
|
insn.Op1.type = o_displ;
|
|
insn.Op1.phrase = riY;
|
|
insn.Op1.addr = insn.get_next_byte();
|
|
break;
|
|
// +04 NOP*/tsb BIT NOP* NOP*/stz STY LDY CPY CPX Zeropage
|
|
// +05 ORA AND EOR ADC STA LDA CMP SBC Zeropage
|
|
// +06 ASL ROL LSR ROR STX LDX DEC INC Zeropage
|
|
// +07 SLO* RLA* SRE* RRA* SAX* LAX* DCP* ISB* Zeropage
|
|
// +07 rmb0 rmb2 rmb4 rmb6 smb0 smb2 smb4 smb6 Zeropage
|
|
case 0x04:
|
|
case 0x05:
|
|
case 0x06:
|
|
case 0x07:
|
|
ZEROPAGE:
|
|
insn.Op1.type = o_mem;
|
|
insn.Op1.addr = insn.get_next_byte();
|
|
break;
|
|
// +14 NOP*/trb NOP*/bit NOP* NOP*/stz STY LDY NOP* NOP* Zeropage, x
|
|
// +15 ORA AND EOR ADC STA LDA CMP SBC Zeropage, x
|
|
// +16 ASL ROL LSR ROR STX y) LDX y) DEC INC Zeropage, x
|
|
// +17 SLO* RLA* SRE* RRA* SAX* y) LAX* y) DCP ISB Zeropage, x
|
|
// +17 rmb1 rmb3 rmb5 rmb7 smb1 smb3 smb5 smb7 Zeropage
|
|
case 0x17:
|
|
if ( is_cmos )
|
|
goto ZEROPAGE;
|
|
/* fall thru */
|
|
case 0x14:
|
|
case 0x15:
|
|
case 0x16:
|
|
insn.Op1.type = o_displ;
|
|
insn.Op1.phrase = zX;
|
|
switch ( insn.itype )
|
|
{
|
|
case M65_trb:
|
|
goto ZEROPAGE;
|
|
case M65_stx:
|
|
case M65_sax:
|
|
case M65_ldx:
|
|
case M65_lax:
|
|
insn.Op1.phrase = zY;
|
|
break;
|
|
}
|
|
insn.Op1.addr = insn.get_next_byte();
|
|
break;
|
|
// +12 ora and eor adc sta lda cmp sbc Zeropage, indirect
|
|
case 0x12:
|
|
insn.indirect = 1;
|
|
insn.Op1.type = o_mem;
|
|
insn.Op1.addr = insn.get_next_byte();
|
|
break;
|
|
default:
|
|
error("ana: bad code %x",code);
|
|
}
|
|
if ( insn.itype == M65_nop )
|
|
insn.Op1.type = o_void;
|
|
return insn.size;
|
|
}
|