update to ida 7.6, add builds
This commit is contained in:
284
idasdk76/module/6502/ana.cpp
Normal file
284
idasdk76/module/6502/ana.cpp
Normal file
@@ -0,0 +1,284 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
94
idasdk76/module/6502/emu.cpp
Normal file
94
idasdk76/module/6502/emu.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Version 3.05
|
||||
* Copyright (c) 1990-95 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* FIDO: 2:5020/209
|
||||
* E-mail: ig@estar.msk.su
|
||||
*
|
||||
*/
|
||||
|
||||
#include "m65.hpp"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void m6502_t::handle_operand(
|
||||
const op_t &x,
|
||||
bool isload,
|
||||
const insn_t &insn,
|
||||
bool *flow) const
|
||||
{
|
||||
ea_t ea;
|
||||
dref_t xreftype;
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_reg:
|
||||
break;
|
||||
case o_imm:
|
||||
if ( !isload )
|
||||
goto badTouch;
|
||||
xreftype = dr_O;
|
||||
goto MAKE_IMMD;
|
||||
case o_displ:
|
||||
xreftype = isload ? dr_R : dr_W;
|
||||
MAKE_IMMD:
|
||||
set_immd(insn.ea);
|
||||
if ( op_adds_xrefs(get_flags(insn.ea), x.n) )
|
||||
insn.add_off_drefs(x, xreftype, m65_opflags(x));
|
||||
break;
|
||||
case o_mem:
|
||||
ea = map_data_ea(insn, x);
|
||||
insn.create_op_data(ea, x);
|
||||
insn.add_dref(ea, x.offb, isload ? dr_R : dr_W);
|
||||
// add xref to the target address
|
||||
if ( insn.itype == M65_jmpi && x.dtype == dt_word && is_loaded(ea) )
|
||||
{
|
||||
ea_t callee = get_word(ea);
|
||||
if ( callee > 32 && is_mapped(callee) ) // is good address?
|
||||
{
|
||||
add_cref(insn.ea, callee, fl_JN);
|
||||
if ( !is_defarg0(get_flags(ea)) )
|
||||
op_plain_offset(ea, 0, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case o_near:
|
||||
{
|
||||
ea = map_code_ea(insn, x);
|
||||
ea_t segbase = (ea - x.addr) >> 4;
|
||||
ea_t thisseg = insn.cs;
|
||||
bool iscall = has_insn_feature(insn.itype, CF_CALL);
|
||||
insn.add_cref(
|
||||
ea,
|
||||
x.offb,
|
||||
iscall ? (segbase == thisseg ? fl_CN : fl_CF)
|
||||
: (segbase == thisseg ? fl_JN : fl_JF));
|
||||
if ( iscall && *flow )
|
||||
*flow = func_does_return(ea);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
badTouch:
|
||||
const char *mnem = insn.get_canon_mnem(ph);
|
||||
warning("%a: %s,%d: bad optype %d", insn.ea, mnem, x.n, x.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int m6502_t::emu(const insn_t &insn) const
|
||||
{
|
||||
uint32 Feature = insn.get_canon_feature(ph);
|
||||
bool flow = ((Feature & CF_STOP) == 0);
|
||||
|
||||
if ( Feature & CF_USE1 ) handle_operand(insn.Op1, 1, insn, &flow);
|
||||
if ( Feature & CF_USE2 ) handle_operand(insn.Op2, 1, insn, &flow);
|
||||
if ( Feature & CF_CHG1 ) handle_operand(insn.Op1, 0, insn, &flow);
|
||||
if ( Feature & CF_CHG2 ) handle_operand(insn.Op2, 0, insn, &flow);
|
||||
if ( Feature & CF_JUMP )
|
||||
remember_problem(PR_JUMP, insn.ea);
|
||||
|
||||
if ( flow )
|
||||
add_cref(insn.ea, insn.ea + insn.size, fl_F);
|
||||
|
||||
return 1;
|
||||
}
|
||||
140
idasdk76/module/6502/ins.cpp
Normal file
140
idasdk76/module/6502/ins.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Version 3.05
|
||||
* Copyright (c) 1990-95 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* FIDO: 2:5020/209
|
||||
* E-mail: ig@estar.msk.su
|
||||
*
|
||||
*/
|
||||
|
||||
#include "m65.hpp"
|
||||
|
||||
const instruc_t Instructions[] =
|
||||
{
|
||||
{ "", 0 },
|
||||
{ "ADC", CF_USE1 }, // A <- (A) + M + C
|
||||
{ "ANC", CF_USE1 }, // A <- A /\ M, C <- ~A7
|
||||
{ "AND", CF_USE1 }, // A <- (A) /\ M
|
||||
{ "ANE", CF_USE1 }, // M <-[(A)\/$EE] /\ (X)/\(M)
|
||||
{ "ARR", CF_USE1 }, // A <- [(A /\ M) >> 1]
|
||||
{ "ASL", CF_CHG1 }, // C <- A7, A <- (A) << 1
|
||||
{ "ASR", CF_USE1 }, // A <- [(A /\ M) >> 1]
|
||||
{ "BCC", CF_USE1 }, // if C=0, PC = PC + offset
|
||||
{ "BCS", CF_USE1 }, // if C=1, PC = PC + offset
|
||||
{ "BEQ", CF_USE1 }, // if Z=1, PC = PC + offset
|
||||
{ "BIT", CF_USE1 }, // Z <- ~(A /\ M) N<-M7 V<-M6
|
||||
{ "BMI", CF_USE1 }, // if N=1, PC = PC + offset
|
||||
{ "BNE", CF_USE1 }, // if Z=0, PC = PC + offset
|
||||
{ "BPL", CF_USE1 }, // if N=0, PC = PC + offset
|
||||
{ "BRK", CF_STOP }, // Stack <- PC, PC <- ($fffe)
|
||||
{ "BVC", CF_USE1 }, // if V=0, PC = PC + offset
|
||||
{ "BVS", CF_USE1 }, // if V=1, PC = PC + offset
|
||||
{ "CLC", 0 }, // C <- 0
|
||||
{ "CLD", 0 }, // D <- 0
|
||||
{ "CLI", 0 }, // I <- 0
|
||||
{ "CLV", 0 }, // V <- 0
|
||||
{ "CMP", CF_USE1 }, // (A - M) -> NZC
|
||||
{ "CPX", CF_USE1 }, // (X - M) -> NZC
|
||||
{ "CPY", CF_USE1 }, // (Y - M) -> NZC
|
||||
{ "DCP", CF_USE1|CF_CHG1 }, // M <- (M)-1, (A-M) -> NZC
|
||||
{ "DEC", CF_USE1|CF_CHG1 }, // M <- (M) - 1
|
||||
{ "DEX", 0 }, // X <- (X) - 1
|
||||
{ "DEY", 0 }, // Y <- (Y) - 1
|
||||
{ "EOR", CF_USE1 }, // A <- (A) \-/ M
|
||||
{ "INC", CF_USE1|CF_CHG1 }, // M <- (M) + 1
|
||||
{ "INX", 0 }, // X <- (X) +1
|
||||
{ "INY", 0 }, // Y <- (Y) + 1
|
||||
{ "ISB", CF_USE1|CF_CHG1 }, // M <- (M) - 1,A <- (A)-M-~C
|
||||
{ "JMP", CF_USE1|CF_STOP }, // PC <- Address
|
||||
{ "JMP", CF_USE1|CF_JUMP|CF_STOP }, // PC <- (Address)
|
||||
{ "JSR", CF_USE1|CF_CALL }, // Stack <- PC, PC <- Address
|
||||
{ "LAE", CF_USE1 }, // X,S,A <- (S /\ M)
|
||||
{ "LAX", CF_USE1 }, // A <- M, X <- M
|
||||
{ "LDA", CF_USE1 }, // A <- M
|
||||
{ "LDX", CF_USE1 }, // X <- M
|
||||
{ "LDY", CF_USE1 }, // Y <- M
|
||||
{ "LSR", CF_CHG1 }, // C <- A0, A <- (A) >> 1
|
||||
{ "LXA", CF_USE1 }, // X04 <- (X04) /\ M04, A04 <- (A04) /\ M04
|
||||
{ "NOP", 0 }, // [no operation]
|
||||
{ "ORA", CF_USE1 }, // A <- (A) V M
|
||||
{ "PHA", 0 }, // Stack <- (A)
|
||||
{ "PHP", 0 }, // Stack <- (P)
|
||||
{ "PLA", 0 }, // A <- (Stack)
|
||||
{ "PLP", 0 }, // A <- (Stack)
|
||||
{ "RLA", CF_USE1|CF_CHG1 }, // M <- (M << 1) /\ (A)
|
||||
{ "ROL", CF_CHG1 }, // C <- A7 & A <- A << 1 + C
|
||||
{ "ROR", CF_CHG1 }, // C<-A0 & A<- (A7=C + A>>1)
|
||||
{ "RRA", CF_USE1|CF_CHG1 }, // M <- (M >> 1) + (A) + C
|
||||
{ "RTI", CF_STOP }, // P <- (Stack), PC <-(Stack)
|
||||
{ "RTS", CF_STOP }, // PC <- (Stack)
|
||||
{ "SAX", CF_CHG1 }, // M <- (A) /\ (X)
|
||||
{ "SBC", CF_USE1 }, // A <- (A) - M - ~C
|
||||
{ "SBX", CF_USE1 }, // X <- (X)/\(A) - M
|
||||
{ "SEC", 0 }, // C <- 1
|
||||
{ "SED", 0 }, // D <- 1
|
||||
{ "SEI", 0 }, // I <- 1
|
||||
{ "SHA", CF_CHG1 }, // M <- (A) /\ (X) /\ (PCH+1)
|
||||
{ "SHS", CF_CHG1 }, // X <- (A) /\ (X), S <- (X), M <- (X) /\ (PCH+1)
|
||||
{ "SHX", CF_CHG1 }, // M <- (X) /\ (PCH+1)
|
||||
{ "SHY", CF_CHG1 }, // M <- (Y) /\ (PCH+1)
|
||||
{ "SLO", CF_USE1|CF_CHG1 }, // M <- (M >> 1) + A + C
|
||||
{ "SRE", CF_USE1|CF_CHG1 }, // M <- (M >> 1) \-/ A
|
||||
{ "STA", CF_CHG1 }, // M <- (A)
|
||||
{ "STX", CF_CHG1 }, // M <- (X)
|
||||
{ "STY", CF_CHG1 }, // M <- (Y)
|
||||
{ "TAX", 0 }, // X <- (A)
|
||||
{ "TAY", 0 }, // Y <- (A)
|
||||
{ "TSX", 0 }, // X <- (S)
|
||||
{ "TXA", 0 }, // A <- (X)
|
||||
{ "TXS", 0 }, // S <- (X)
|
||||
{ "TYA", 0 }, // A <- (Y)
|
||||
|
||||
|
||||
// CMOS instructions
|
||||
|
||||
{ "BBR0", CF_USE1|CF_USE2 }, // Branch if bit 0 reset
|
||||
{ "BBR1", CF_USE1|CF_USE2 }, // Branch if bit 1 reset
|
||||
{ "BBR2", CF_USE1|CF_USE2 }, // Branch if bit 2 reset
|
||||
{ "BBR3", CF_USE1|CF_USE2 }, // Branch if bit 3 reset
|
||||
{ "BBR4", CF_USE1|CF_USE2 }, // Branch if bit 4 reset
|
||||
{ "BBR5", CF_USE1|CF_USE2 }, // Branch if bit 5 reset
|
||||
{ "BBR6", CF_USE1|CF_USE2 }, // Branch if bit 6 reset
|
||||
{ "BBR7", CF_USE1|CF_USE2 }, // Branch if bit 7 reset
|
||||
{ "BBS0", CF_USE1|CF_USE2 }, // Branch if bit 0 set
|
||||
{ "BBS1", CF_USE1|CF_USE2 }, // Branch if bit 1 set
|
||||
{ "BBS2", CF_USE1|CF_USE2 }, // Branch if bit 2 set
|
||||
{ "BBS3", CF_USE1|CF_USE2 }, // Branch if bit 3 set
|
||||
{ "BBS4", CF_USE1|CF_USE2 }, // Branch if bit 4 set
|
||||
{ "BBS5", CF_USE1|CF_USE2 }, // Branch if bit 5 set
|
||||
{ "BBS6", CF_USE1|CF_USE2 }, // Branch if bit 6 set
|
||||
{ "BBS7", CF_USE1|CF_USE2 }, // Branch if bit 7 set
|
||||
{ "RMB0", CF_CHG1 }, // Reset memory bit 0
|
||||
{ "RMB1", CF_CHG1 }, // Reset memory bit 1
|
||||
{ "RMB2", CF_CHG1 }, // Reset memory bit 2
|
||||
{ "RMB3", CF_CHG1 }, // Reset memory bit 3
|
||||
{ "RMB4", CF_CHG1 }, // Reset memory bit 4
|
||||
{ "RMB5", CF_CHG1 }, // Reset memory bit 5
|
||||
{ "RMB6", CF_CHG1 }, // Reset memory bit 6
|
||||
{ "RMB7", CF_CHG1 }, // Reset memory bit 7
|
||||
{ "SMB0", CF_CHG1 }, // Set memory bit 0
|
||||
{ "SMB1", CF_CHG1 }, // Set memory bit 1
|
||||
{ "SMB2", CF_CHG1 }, // Set memory bit 2
|
||||
{ "SMB3", CF_CHG1 }, // Set memory bit 3
|
||||
{ "SMB4", CF_CHG1 }, // Set memory bit 4
|
||||
{ "SMB5", CF_CHG1 }, // Set memory bit 5
|
||||
{ "SMB6", CF_CHG1 }, // Set memory bit 6
|
||||
{ "SMB7", CF_CHG1 }, // Set memory bit 7
|
||||
{ "STZ", CF_CHG1 }, // Store zero
|
||||
{ "TSB", CF_USE1|CF_CHG1 }, // Test and set bits
|
||||
{ "TRB", CF_USE1|CF_CHG1 }, // Test and reset bits
|
||||
{ "PHY", 0 }, // Push Y register
|
||||
{ "PLY", 0 }, // Pull Y register
|
||||
{ "PHX", 0 }, // Push X register
|
||||
{ "PLX", 0 }, // Pull X register
|
||||
{ "BRA", CF_USE1|CF_STOP }, // Branch always
|
||||
{ "WAI", 0 }, // Wait for interrupt
|
||||
{ "STP", CF_STOP }, // Stop processor
|
||||
};
|
||||
|
||||
CASSERT(qnumber(Instructions) == M65_last);
|
||||
144
idasdk76/module/6502/ins.hpp
Normal file
144
idasdk76/module/6502/ins.hpp
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-2021 Hex-Rays
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __INSTRS_HPP
|
||||
#define __INSTRS_HPP
|
||||
|
||||
extern const instruc_t Instructions[];
|
||||
|
||||
enum nameNum ENUM_SIZE(uint16)
|
||||
{
|
||||
M65_null = 0, // Unknown Operation
|
||||
|
||||
// NMOS instructions
|
||||
|
||||
M65_adc, // A <- (A) + M + C
|
||||
M65_anc, // A <- A /\ M, C <- ~A7
|
||||
M65_and, // A <- (A) /\ M
|
||||
M65_ane, // M <-[(A)\/$EE] /\ (X)/\(M)
|
||||
M65_arr, // A <- [(A /\ M) >> 1]
|
||||
M65_asl, // C <- A7, A <- (A) << 1
|
||||
M65_asr, // A <- [(A /\ M) >> 1]
|
||||
M65_bcc, // if C=0, PC = PC + offset
|
||||
M65_bcs, // if C=1, PC = PC + offset
|
||||
M65_beq, // if Z=1, PC = PC + offset
|
||||
M65_bit, // Z <- ~(A /\ M) N<-M7 V<-M6
|
||||
M65_bmi, // if N=1, PC = PC + offset
|
||||
M65_bne, // if Z=0, PC = PC + offset
|
||||
M65_bpl, // if N=0, PC = PC + offset
|
||||
M65_brk, // Stack <- PC, PC <- ($fffe)
|
||||
M65_bvc, // if V=0, PC = PC + offset
|
||||
M65_bvs, // if V=1, PC = PC + offset
|
||||
M65_clc, // C <- 0
|
||||
M65_cld, // D <- 0
|
||||
M65_cli, // I <- 0
|
||||
M65_clv, // V <- 0
|
||||
M65_cmp, // (A - M) -> NZC
|
||||
M65_cpx, // (X - M) -> NZC
|
||||
M65_cpy, // (Y - M) -> NZC
|
||||
M65_dcp, // M <- (M)-1, (A-M) -> NZC
|
||||
M65_dec, // M <- (M) - 1
|
||||
M65_dex, // X <- (X) - 1
|
||||
M65_dey, // Y <- (Y) - 1
|
||||
M65_eor, // A <- (A) \-/ M
|
||||
M65_inc, // M <- (M) + 1
|
||||
M65_inx, // X <- (X) +1
|
||||
M65_iny, // Y <- (Y) + 1
|
||||
M65_isb, // M <- (M) - 1,A <- (A)-M-~C
|
||||
M65_jmp, // PC <- Address
|
||||
M65_jmpi, // (PC <- Address)
|
||||
M65_jsr, // Stack <- PC, PC <- Address
|
||||
M65_lae, // X,S,A <- (S /\ M)
|
||||
M65_lax, // A <- M, X <- M
|
||||
M65_lda, // A <- M
|
||||
M65_ldx, // X <- M
|
||||
M65_ldy, // Y <- M
|
||||
M65_lsr, // C <- A0, A <- (A) >> 1
|
||||
M65_lxa, // X04 <- (X04) /\ M04, A04 <- (A04) /\ M04
|
||||
M65_nop, // [no operation]
|
||||
M65_ora, // A <- (A) V M
|
||||
M65_pha, // Stack <- (A)
|
||||
M65_php, // Stack <- (P)
|
||||
M65_pla, // A <- (Stack)
|
||||
M65_plp, // A <- (Stack)
|
||||
M65_rla, // M <- (M << 1) /\ (A)
|
||||
M65_rol, // C <- A7 & A <- A << 1 + C
|
||||
M65_ror, // C<-A0 & A<- (A7=C + A>>1)
|
||||
M65_rra, // M <- (M >> 1) + (A) + C
|
||||
M65_rti, // P <- (Stack), PC <-(Stack)
|
||||
M65_rts, // PC <- (Stack)
|
||||
M65_sax, // M <- (A) /\ (X)
|
||||
M65_sbc, // A <- (A) - M - ~C
|
||||
M65_sbx, // X <- (X)/\(A) - M
|
||||
M65_sec, // C <- 1
|
||||
M65_sed, // D <- 1
|
||||
M65_sei, // I <- 1
|
||||
M65_sha, // M <- (A) /\ (X) /\ (PCH+1)
|
||||
M65_shs, // X <- (A) /\ (X), S <- (X), M <- (X) /\ (PCH+1)
|
||||
M65_shx, // M <- (X) /\ (PCH+1)
|
||||
M65_shy, // M <- (Y) /\ (PCH+1)
|
||||
M65_slo, // M <- (M >> 1) + A + C
|
||||
M65_sre, // M <- (M >> 1) \-/ A
|
||||
M65_sta, // M <- (A)
|
||||
M65_stx, // M <- (X)
|
||||
M65_sty, // M <- (Y)
|
||||
M65_tax, // X <- (A)
|
||||
M65_tay, // Y <- (A)
|
||||
M65_tsx, // X <- (S)
|
||||
M65_txa, // A <- (X)
|
||||
M65_txs, // S <- (X)
|
||||
M65_tya, // A <- (Y)
|
||||
|
||||
// CMOS instructions
|
||||
|
||||
M65_bbr0, // Branch if bit 0 reset
|
||||
M65_bbr1, // Branch if bit 1 reset
|
||||
M65_bbr2, // Branch if bit 2 reset
|
||||
M65_bbr3, // Branch if bit 3 reset
|
||||
M65_bbr4, // Branch if bit 4 reset
|
||||
M65_bbr5, // Branch if bit 5 reset
|
||||
M65_bbr6, // Branch if bit 6 reset
|
||||
M65_bbr7, // Branch if bit 7 reset
|
||||
M65_bbs0, // Branch if bit 0 set
|
||||
M65_bbs1, // Branch if bit 1 set
|
||||
M65_bbs2, // Branch if bit 2 set
|
||||
M65_bbs3, // Branch if bit 3 set
|
||||
M65_bbs4, // Branch if bit 4 set
|
||||
M65_bbs5, // Branch if bit 5 set
|
||||
M65_bbs6, // Branch if bit 6 set
|
||||
M65_bbs7, // Branch if bit 7 set
|
||||
M65_rmb0, // Reset memory bit 0
|
||||
M65_rmb1, // Reset memory bit 1
|
||||
M65_rmb2, // Reset memory bit 2
|
||||
M65_rmb3, // Reset memory bit 3
|
||||
M65_rmb4, // Reset memory bit 4
|
||||
M65_rmb5, // Reset memory bit 5
|
||||
M65_rmb6, // Reset memory bit 6
|
||||
M65_rmb7, // Reset memory bit 7
|
||||
M65_smb0, // Set memory bit 0
|
||||
M65_smb1, // Set memory bit 1
|
||||
M65_smb2, // Set memory bit 2
|
||||
M65_smb3, // Set memory bit 3
|
||||
M65_smb4, // Set memory bit 4
|
||||
M65_smb5, // Set memory bit 5
|
||||
M65_smb6, // Set memory bit 6
|
||||
M65_smb7, // Set memory bit 7
|
||||
M65_stz, // Store zero
|
||||
M65_tsb, // Test and set bits
|
||||
M65_trb, // Test and reset bits
|
||||
M65_phy, // Push Y register
|
||||
M65_ply, // Pull Y register
|
||||
M65_phx, // Push X register
|
||||
M65_plx, // Pull X register
|
||||
M65_bra, // Branch always
|
||||
M65_wai, // Wait for interrupt
|
||||
M65_stp, // Stop processor
|
||||
|
||||
M65_last,
|
||||
};
|
||||
|
||||
#endif
|
||||
51
idasdk76/module/6502/m65.hpp
Normal file
51
idasdk76/module/6502/m65.hpp
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Version 3.05
|
||||
* Copyright (c) 1990-95 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* FIDO: 2:5020/209
|
||||
* E-mail: ig@estar.msk.su
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _M65_HPP
|
||||
#define _M65_HPP
|
||||
|
||||
#include "../idaidp.hpp"
|
||||
#include "ins.hpp"
|
||||
|
||||
struct m6502_t : public procmod_t
|
||||
{
|
||||
bool is_cmos = false; // is CMOS (otherwise, NMOS)
|
||||
|
||||
virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override;
|
||||
int ana(insn_t *_insn);
|
||||
int emu(const insn_t &insn) const;
|
||||
void handle_operand(const op_t &x, bool isload, const insn_t &insn, bool *flow) const;
|
||||
|
||||
void header(outctx_t &ctx) const;
|
||||
void segstart(outctx_t &ctx, segment_t *seg) const;
|
||||
void footer(outctx_t &ctx) const;
|
||||
};
|
||||
extern int data_id;
|
||||
|
||||
// Is indirect memory reference?
|
||||
|
||||
#define indirect auxpref
|
||||
|
||||
#define UAS_SECT 0x0002 // Segments are named .SECTION
|
||||
#define UAS_NOSEG 0x0004 // No 'segment' directives
|
||||
#define UAS_SELSG 0x0010 // Segment should be selected by its name
|
||||
#define UAS_CDSEG 0x0080 // Only DSEG, CSEG, XSEG
|
||||
#define UAS_NOENS 0x0200 // don't specify start addr in the .end directive
|
||||
//------------------------------------------------------------------------
|
||||
enum M65_registers { rA, rX, rY, rVcs, rVds, riX, riY, zX, zY };
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
int idaapi ana(insn_t *insn);
|
||||
int idaapi emu(const insn_t &insn);
|
||||
void idaapi assumes(outctx_t &ctx, ea_t ea);
|
||||
int m65_opflags(const op_t &x);
|
||||
|
||||
|
||||
#endif
|
||||
50
idasdk76/module/6502/makefile
Normal file
50
idasdk76/module/6502/makefile
Normal file
@@ -0,0 +1,50 @@
|
||||
PROC=m65
|
||||
|
||||
include ../module.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)fpro.h $(I)funcs.hpp \
|
||||
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ana.cpp ins.hpp \
|
||||
m65.hpp
|
||||
$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)fpro.h $(I)funcs.hpp \
|
||||
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp emu.cpp ins.hpp \
|
||||
m65.hpp
|
||||
$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)fpro.h $(I)funcs.hpp \
|
||||
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.cpp ins.hpp \
|
||||
m65.hpp
|
||||
$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)fpro.h $(I)funcs.hpp \
|
||||
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.hpp m65.hpp \
|
||||
out.cpp
|
||||
$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)fpro.h $(I)funcs.hpp \
|
||||
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.hpp m65.hpp \
|
||||
reg.cpp
|
||||
190
idasdk76/module/6502/out.cpp
Normal file
190
idasdk76/module/6502/out.cpp
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Version 3.05
|
||||
* Copyright (c) 1990-95 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* FIDO: 2:5020/209
|
||||
* E-mail: ig@estar.msk.su
|
||||
*
|
||||
*/
|
||||
|
||||
#include "m65.hpp"
|
||||
|
||||
int m65_opflags(const op_t &x)
|
||||
{
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_displ:
|
||||
return OOF_ADDR|OOFS_NOSIGN|OOFW_16;
|
||||
case o_near:
|
||||
case o_mem:
|
||||
return OOF_ADDR|OOF_NUMBER|OOFS_NOSIGN|OOFW_16|OOF_ZSTROFF;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
// simple wrapper class for syntactic sugar of member functions
|
||||
// this class may have only simple member functions.
|
||||
// virtual functions and data fields are forbidden, otherwise the class
|
||||
// layout may change
|
||||
class out_6502_t : public outctx_t
|
||||
{
|
||||
out_6502_t(void) = delete; // not used
|
||||
public:
|
||||
bool out_operand(const op_t &x);
|
||||
void out_insn(void);
|
||||
};
|
||||
CASSERT(sizeof(out_6502_t) == sizeof(outctx_t));
|
||||
|
||||
DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_6502_t)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool out_6502_t::out_operand(const op_t &x)
|
||||
{
|
||||
int outf = m65_opflags(x);
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_reg:
|
||||
out_register("A");
|
||||
break;
|
||||
case o_imm:
|
||||
out_symbol('#');
|
||||
out_value(x, outf);
|
||||
break;
|
||||
case o_near:
|
||||
case o_mem:
|
||||
if ( insn.indirect )
|
||||
out_symbol('(');
|
||||
{
|
||||
ea_t v = map_ea(insn, x, x.type == o_near);
|
||||
if ( !out_name_expr(x, v, x.addr) )
|
||||
out_value(x, outf);
|
||||
}
|
||||
if ( insn.indirect )
|
||||
out_symbol(')');
|
||||
break;
|
||||
case o_displ:
|
||||
switch ( x.phrase )
|
||||
{
|
||||
case rX:
|
||||
case rY:
|
||||
case zX:
|
||||
case zY:
|
||||
out_value(x, outf);
|
||||
out_symbol(',');
|
||||
out_register((x.phrase == zX || x.phrase == rX) ? "X" : "Y");
|
||||
break;
|
||||
case riX:
|
||||
out_symbol('(');
|
||||
out_value(x, outf);
|
||||
out_symbol(',');
|
||||
out_register("X");
|
||||
out_symbol(')');
|
||||
break;
|
||||
case riY:
|
||||
out_symbol('(');
|
||||
out_value(x, outf);
|
||||
out_symbol(')');
|
||||
out_symbol(',');
|
||||
out_register("Y");
|
||||
break;
|
||||
default:
|
||||
goto err;
|
||||
}
|
||||
break;
|
||||
case o_void:
|
||||
return 0;
|
||||
default:
|
||||
err:
|
||||
warning("out: %a: bad optype %d", insn.ea, x.type);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_6502_t::out_insn(void)
|
||||
{
|
||||
out_mnemonic();
|
||||
out_one_operand(0);
|
||||
if ( insn.Op2.type != o_void )
|
||||
{
|
||||
out_symbol(',');
|
||||
out_char(' ');
|
||||
out_one_operand(1);
|
||||
}
|
||||
|
||||
out_immchar_cmts();
|
||||
flush_outbuf();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void m6502_t::header(outctx_t &ctx) const
|
||||
{
|
||||
ctx.gen_cmt_line("%s Processor: %s", ash.cmnt, inf_get_procname().c_str());
|
||||
ctx.gen_cmt_line("%s Target assembler: %s", ash.cmnt, ash.name);
|
||||
if ( ash.header != NULL )
|
||||
for ( const char *const *ptr = ash.header; *ptr != NULL; ptr++ )
|
||||
ctx.flush_buf(*ptr, 0);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//lint -e{1764} ctx could be const
|
||||
//lint -e{818} seg could be const
|
||||
void m6502_t::segstart(outctx_t &ctx, segment_t *seg) const
|
||||
{
|
||||
ea_t ea = ctx.insn_ea;
|
||||
qstring name;
|
||||
get_visible_segm_name(&name, seg);
|
||||
if ( ash.uflag & UAS_SECT )
|
||||
{
|
||||
ctx.gen_printf(0, COLSTR("%s: .section", SCOLOR_ASMDIR), name.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.gen_printf(DEFAULT_INDENT,
|
||||
COLSTR("%s.segment %s", SCOLOR_ASMDIR),
|
||||
(ash.uflag & UAS_NOSEG) ? ash.cmnt : "",
|
||||
name.c_str());
|
||||
if ( ash.uflag & UAS_SELSG )
|
||||
ctx.flush_buf(name.c_str(), DEFAULT_INDENT);
|
||||
if ( ash.uflag & UAS_CDSEG )
|
||||
ctx.flush_buf(COLSTR("CSEG", SCOLOR_ASMDIR), DEFAULT_INDENT); // XSEG - eXternal memory
|
||||
}
|
||||
if ( (inf_get_outflags() & OFLG_GEN_ORG) != 0 )
|
||||
{
|
||||
ea_t org = ea - get_segm_base(seg);
|
||||
if ( org != 0 )
|
||||
{
|
||||
char buf[MAX_NUMBUF];
|
||||
btoa(buf, sizeof(buf), org);
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void m6502_t::footer(outctx_t &ctx) const
|
||||
{
|
||||
char buf[MAXSTR];
|
||||
if ( ash.end != NULL )
|
||||
{
|
||||
ctx.gen_empty_line();
|
||||
char *ptr = buf;
|
||||
char *end = buf + sizeof(buf);
|
||||
APPEND(ptr, end, ash.end);
|
||||
qstring name;
|
||||
if ( get_colored_name(&name, inf_get_start_ea()) > 0 )
|
||||
{
|
||||
if ( ash.uflag & UAS_NOENS )
|
||||
APPEND(ptr, end, ash.cmnt);
|
||||
APPCHAR(ptr, end, ' ');
|
||||
APPEND(ptr, end, name.begin());
|
||||
}
|
||||
ctx.flush_buf(buf, DEFAULT_INDENT);
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.gen_cmt_line("end of file");
|
||||
}
|
||||
}
|
||||
319
idasdk76/module/6502/reg.cpp
Normal file
319
idasdk76/module/6502/reg.cpp
Normal file
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Version 3.05
|
||||
* 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 char *const regnames[] =
|
||||
{
|
||||
"A", "X", "Y", "cs", "ds"
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// This old-style callback only returns the processor module object.
|
||||
static ssize_t idaapi notify(void *, int msgid, va_list)
|
||||
{
|
||||
if ( msgid == processor_t::ev_get_procmod )
|
||||
return size_t(new m6502_t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
ssize_t idaapi m6502_t::on_event(ssize_t msgid, va_list va)
|
||||
{
|
||||
switch ( msgid )
|
||||
{
|
||||
case processor_t::ev_ending_undo:
|
||||
is_cmos = static_cast<bool>(ph.get_proc_index());
|
||||
break;
|
||||
|
||||
case processor_t::ev_newprc:
|
||||
is_cmos = va_arg(va, int) != 0;
|
||||
break;
|
||||
|
||||
case processor_t::ev_creating_segm:
|
||||
{ // default DS is equal to CS
|
||||
segment_t *sptr = va_arg(va, segment_t *);
|
||||
sptr->defsr[rVds-ph.reg_first_sreg] = sptr->sel;
|
||||
}
|
||||
break;
|
||||
|
||||
case processor_t::ev_out_header:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
header(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_footer:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
footer(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_segstart:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
segment_t *seg = va_arg(va, segment_t *);
|
||||
segstart(*ctx, seg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_ana_insn:
|
||||
{
|
||||
insn_t *out = va_arg(va, insn_t *);
|
||||
return ana(out);
|
||||
}
|
||||
|
||||
case processor_t::ev_emu_insn:
|
||||
{
|
||||
const insn_t *insn = va_arg(va, const insn_t *);
|
||||
return emu(*insn) ? 1 : -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_insn:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
out_insn(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_operand:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
const op_t *op = va_arg(va, const op_t *);
|
||||
return out_opnd(*ctx, *op) ? 1 : -1;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// PseudoSam
|
||||
//-----------------------------------------------------------------------
|
||||
static const char *const ps_headers[] =
|
||||
{
|
||||
".code",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const asm_t pseudosam =
|
||||
{
|
||||
AS_COLON | ASH_HEXF1 | AS_N2CHR | AS_NOXRF,
|
||||
UAS_SELSG,
|
||||
"PseudoSam by PseudoCode",
|
||||
0,
|
||||
ps_headers,
|
||||
".org",
|
||||
".end",
|
||||
|
||||
";", // comment string
|
||||
'"', // string delimiter
|
||||
'\'', // char delimiter
|
||||
"\\\"'", // special symbols in char and string constants
|
||||
|
||||
".db", // ascii string directive
|
||||
".db", // byte directive
|
||||
".dw", // word directive
|
||||
NULL, // dword (4 bytes)
|
||||
NULL, // qword (8 bytes)
|
||||
NULL, // oword (16 bytes)
|
||||
NULL, // float (4 bytes)
|
||||
NULL, // double (8 bytes)
|
||||
NULL, // tbyte (10/12 bytes)
|
||||
NULL, // packed decimal real
|
||||
NULL, // arrays (#h,#d,#v,#s(...)
|
||||
".rs %s", // uninited arrays
|
||||
".equ", // equ
|
||||
NULL, // seg prefix
|
||||
NULL, // curip
|
||||
NULL, // func_header
|
||||
NULL, // func_footer
|
||||
NULL, // public
|
||||
NULL, // weak
|
||||
NULL, // extrn
|
||||
NULL, // comm
|
||||
NULL, // get_type_name
|
||||
NULL, // align
|
||||
'(', ')', // lbrace, rbrace
|
||||
NULL, // mod
|
||||
NULL, // and
|
||||
NULL, // or
|
||||
NULL, // xor
|
||||
NULL, // not
|
||||
NULL, // shl
|
||||
NULL, // shr
|
||||
NULL, // sizeof
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// SVENSON ELECTRONICS 6502/65C02 ASSEMBLER - V.1.0 - MAY, 1988
|
||||
//-----------------------------------------------------------------------
|
||||
static const asm_t svasm =
|
||||
{
|
||||
AS_COLON | ASH_HEXF4,
|
||||
UAS_NOSEG,
|
||||
"SVENSON ELECTRONICS 6502/65C02 ASSEMBLER - V.1.0 - MAY, 1988",
|
||||
0,
|
||||
NULL, // headers
|
||||
"* = ",
|
||||
".END",
|
||||
|
||||
";", // comment string
|
||||
'\'', // string delimiter
|
||||
'\'', // char delimiter
|
||||
"\\'", // special symbols in char and string constants
|
||||
|
||||
".BYTE", // ascii string directive
|
||||
".BYTE", // byte directive
|
||||
".WORD", // word directive
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// TASM assembler definiton
|
||||
//-----------------------------------------------------------------------
|
||||
static const asm_t tasm =
|
||||
{
|
||||
AS_COLON | AS_N2CHR | AS_1TEXT,
|
||||
UAS_NOENS | UAS_NOSEG,
|
||||
"Table Driven Assembler (TASM) by Speech Technology Inc.",
|
||||
0,
|
||||
NULL, // headers,
|
||||
".org",
|
||||
".end",
|
||||
|
||||
";", // comment string
|
||||
'"', // string delimiter
|
||||
'\'', // char delimiter
|
||||
"\\\"'", // special symbols in char and string constants
|
||||
|
||||
".text", // ascii string directive
|
||||
".db", // byte directive
|
||||
".dw", // word directive
|
||||
NULL, // dword (4 bytes)
|
||||
NULL, // qword (8 bytes)
|
||||
NULL, // oword (16 bytes)
|
||||
NULL, // float (4 bytes)
|
||||
NULL, // double (8 bytes)
|
||||
NULL, // tbyte (10/12 bytes)
|
||||
NULL, // packed decimal real
|
||||
NULL, // arrays (#h,#d,#v,#s(...)
|
||||
".block %s", // uninited arrays
|
||||
".equ",
|
||||
NULL, // seg prefix
|
||||
NULL, // curip
|
||||
NULL, // func_header
|
||||
NULL, // func_footer
|
||||
NULL, // public
|
||||
NULL, // weak
|
||||
NULL, // extrn
|
||||
NULL, // comm
|
||||
NULL, // get_type_name
|
||||
NULL, // align
|
||||
'(', ')', // lbrace, rbrace
|
||||
NULL, // mod
|
||||
"and", // and
|
||||
"or", // or
|
||||
NULL, // xor
|
||||
"not", // not
|
||||
NULL, // shl
|
||||
NULL, // shr
|
||||
NULL, // sizeof
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Avocet assembler definiton
|
||||
//-----------------------------------------------------------------------
|
||||
static const asm_t avocet =
|
||||
{
|
||||
AS_COLON | AS_N2CHR | AS_1TEXT,
|
||||
UAS_NOENS | UAS_NOSEG,
|
||||
"Avocet Systems 2500AD 6502 Assembler",
|
||||
0,
|
||||
NULL, // headers,
|
||||
".org",
|
||||
".end",
|
||||
|
||||
";", // comment string
|
||||
'"', // string delimiter
|
||||
'\'', // char delimiter
|
||||
"\\\"'", // special symbols in char and string constants
|
||||
|
||||
".fcc", // ascii string directive
|
||||
".db", // byte directive
|
||||
".dw", // word directive
|
||||
NULL, // dword (4 bytes)
|
||||
NULL, // qword (8 bytes)
|
||||
NULL, // oword (16 bytes)
|
||||
NULL, // float (4 bytes)
|
||||
NULL, // double (8 bytes)
|
||||
NULL, // tbyte (10/12 bytes)
|
||||
NULL, // packed decimal real
|
||||
NULL, // arrays (#h,#d,#v,#s(...)
|
||||
".ds %s", // uninited arrays
|
||||
};
|
||||
|
||||
static const asm_t *const asms[] = { &svasm, &tasm, &pseudosam, &avocet, NULL };
|
||||
//-----------------------------------------------------------------------
|
||||
#define FAMILY "MOS Technology 65xx series:"
|
||||
static const char *const shnames[] = { "M6502", "M65C02", NULL };
|
||||
static const char *const lnames[] = { FAMILY"MOS Technology 6502", "MOS Technology 65C02", NULL };
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const uchar retcode_1[] = { 0x60 };
|
||||
static const uchar retcode_2[] = { 0x40 };
|
||||
|
||||
static const bytes_t retcodes[] =
|
||||
{
|
||||
{ sizeof(retcode_1), retcode_1 },
|
||||
{ sizeof(retcode_2), retcode_2 },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Processor Definition
|
||||
//-----------------------------------------------------------------------
|
||||
processor_t LPH =
|
||||
{
|
||||
IDP_INTERFACE_VERSION, // version
|
||||
PLFM_6502, // id
|
||||
PR_SEGS // flag
|
||||
| PR_SEGTRANS,
|
||||
0, // flag2
|
||||
8, // 8 bits in a byte for code segments
|
||||
8, // 8 bits in a byte for other segments
|
||||
|
||||
shnames,
|
||||
lnames,
|
||||
|
||||
asms,
|
||||
|
||||
notify,
|
||||
|
||||
regnames, // Register names
|
||||
qnumber(regnames), // Number of registers
|
||||
|
||||
rVcs, // first
|
||||
rVds, // last
|
||||
0, // size of a segment register
|
||||
rVcs,rVds,
|
||||
|
||||
NULL, // No known code start sequences
|
||||
retcodes,
|
||||
|
||||
0, M65_last,
|
||||
Instructions, // instruc
|
||||
};
|
||||
Reference in New Issue
Block a user