update to ida 7.6, add builds
This commit is contained in:
442
idasdk76/module/c39/ana.cpp
Normal file
442
idasdk76/module/c39/ana.cpp
Normal file
@@ -0,0 +1,442 @@
|
||||
/*
|
||||
* Rockwell C39 processor module for IDA.
|
||||
* Copyright (c) 2000-2006 Konstantin Norvatoff, <konnor@bk.ru>
|
||||
* Freeware.
|
||||
*/
|
||||
|
||||
#include "c39.hpp"
|
||||
|
||||
/*
|
||||
Operand types:
|
||||
1) none
|
||||
2) Register a, x, y
|
||||
3) address $xx address may be 8 or 16 bits
|
||||
4) indirect address ($xx) address of the cell with the target address
|
||||
5) immediate #$xx constant
|
||||
6) label Label target label of the jump
|
||||
*/
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// current byte(s) is immediate data, 1 byte
|
||||
static void SetImmData(op_t &op, uchar code)
|
||||
{
|
||||
op.type = o_imm;
|
||||
// always in the second byte
|
||||
op.offb = 1;
|
||||
// element size
|
||||
op.dtype = dt_byte;
|
||||
// value
|
||||
op.addr = op.value = code;
|
||||
// it can't be an offset!
|
||||
op.flags |= OF_NUMBER; // only number
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// registres are considered byte-sized
|
||||
static void SetReg(op_t &op, uchar reg_n)
|
||||
{
|
||||
op.type = o_reg; // only register
|
||||
op.reg = reg_n; // register number
|
||||
op.dtype = dt_byte; // size is always 8 bits
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// memory cell
|
||||
static void SetMemVar(op_t &op, ushort addr)
|
||||
{
|
||||
op.type = o_mem;
|
||||
op.addr = op.value = addr;
|
||||
op.dtype = dt_word;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// memory cell with an address
|
||||
static void SetMemVarI(op_t &op, ushort addr)
|
||||
{
|
||||
op.type = o_mem;
|
||||
op.specflag1 |= URR_IND;
|
||||
op.addr = op.value = addr;
|
||||
op.dtype = dt_word;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// relative branch
|
||||
static void SetRelative(const insn_t &insn, op_t &op, signed char disp)
|
||||
{
|
||||
op.type = o_near;
|
||||
op.dtype = dt_word;
|
||||
op.offb = 1; // in fact, not always...
|
||||
// calculate indirect value
|
||||
op.addr = op.value = insn.ip + insn.size + (int32)disp;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// absolute branch
|
||||
static void SetAbs(op_t &op, unsigned short disp)
|
||||
{
|
||||
op.type = o_near;
|
||||
op.dtype = dt_word;
|
||||
op.offb = 1; // in fact, not always...
|
||||
// calculate final value
|
||||
op.addr = op.value = disp;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// analyzer
|
||||
int idaapi C39_ana(insn_t *_insn)
|
||||
{
|
||||
static const uchar Dt[] =
|
||||
{
|
||||
C39_brk, C39_ora, C39_mpy, C39_tip, 0, C39_ora, C39_asl, C39_rmb, // 00
|
||||
C39_php, C39_ora, C39_asl, C39_jsb, C39_jpi, C39_ora, C39_asl, C39_bbr, // 08
|
||||
|
||||
C39_bpl, C39_ora, C39_mpa, C39_lab, 0, C39_ora, C39_asl, C39_rmb, // 10
|
||||
C39_clc, C39_ora, C39_neg, C39_jsb, 0, C39_ora, C39_asl, C39_bbr, // 18
|
||||
|
||||
C39_jsr, C39_and, C39_psh, C39_phw, C39_bit, C39_and, C39_rol, C39_rmb, // 20
|
||||
C39_plp, C39_and, C39_rol, C39_jsb, C39_bit, C39_and, C39_rol, C39_bbr, // 28
|
||||
|
||||
C39_bmi, C39_and, C39_pul, C39_plw, 0, C39_and, C39_rol, C39_rmb, // 30
|
||||
C39_sec, C39_and, C39_asr, C39_jsb, 0, C39_and, C39_rol, C39_bbr, // 38
|
||||
|
||||
C39_rti, C39_eor, C39_rnd, 0, 0, C39_eor, C39_lsr, C39_rmb, // 40
|
||||
C39_pha, C39_eor, C39_lsr, C39_jsb, C39_jmp, C39_eor, C39_lsr, C39_bbr, // 48
|
||||
|
||||
C39_bvc, C39_eor, C39_clw, 0, 0, C39_eor, C39_lsr, C39_rmb, // 50
|
||||
C39_cli, C39_eor, C39_phy, C39_jsb, 0, C39_eor, C39_lsr, C39_bbr, // 58
|
||||
|
||||
C39_rts, C39_adc, C39_taw, 0, C39_add, C39_adc, C39_ror, C39_rmb, // 60
|
||||
C39_pla, C39_adc, C39_ror, C39_jsb, C39_jmp, C39_adc, C39_ror, C39_bbr, // 68
|
||||
|
||||
C39_bvs, C39_adc, C39_twa, 0, C39_add, C39_adc, C39_ror, C39_rmb, // 70
|
||||
C39_sei, C39_adc, C39_ply, C39_jsb, C39_jmp, C39_adc, C39_ror, C39_bbr, // 78
|
||||
|
||||
C39_bra, C39_sta, 0, 0, C39_sty, C39_sta, C39_stx, C39_smb, // 80
|
||||
C39_dey, C39_add, C39_txa, C39_nxt, C39_sty, C39_sta, C39_stx, C39_bbs, // 88
|
||||
|
||||
C39_bcc, C39_sta, 0, 0, C39_sty, C39_sta, C39_stx, C39_smb, // 90
|
||||
C39_tya, C39_sta, C39_txs, C39_lii, 0, C39_sta, 0, C39_bbs, // 98
|
||||
|
||||
C39_ldy, C39_lda, C39_ldx, 0, C39_ldy, C39_lda, C39_ldx, C39_smb, // A0
|
||||
C39_tay, C39_lda, C39_tax, C39_lan, C39_ldy, C39_lda, C39_ldx, C39_bbs, // A8
|
||||
|
||||
C39_bcs, C39_lda, C39_sti, 0, C39_ldy, C39_lda, C39_ldx, C39_smb, // B0
|
||||
C39_clv, C39_lda, C39_tsx, C39_ini, C39_ldy, C39_lda, C39_ldx, C39_bbs, // B8
|
||||
|
||||
|
||||
C39_cpy, C39_cmp, C39_rba, 0, C39_cpy, C39_cmp, C39_dec, C39_smb, // C0
|
||||
C39_iny, C39_cmp, C39_dex, C39_phi, C39_cpy, C39_cmp, C39_dec, C39_bbs, // C8
|
||||
|
||||
C39_bne, C39_cmp, C39_sba, 0, C39_exc, C39_cmp, C39_dec, C39_smb, // D0
|
||||
C39_cld, C39_cmp, C39_phx, C39_pli, 0, C39_cmp, C39_dec, C39_bbs, // D8
|
||||
|
||||
C39_cpx, C39_sbc, C39_bar, 0, C39_cpx, C39_sbc, C39_inc, C39_smb, // E0
|
||||
C39_inx, C39_sbc, C39_nop, C39_lai, C39_cpx, C39_sbc, C39_inc, C39_bbs, // E8
|
||||
|
||||
C39_beq, C39_sbc, C39_bas, 0, 0, C39_sbc, C39_inc, C39_smb, // F0
|
||||
C39_sed, C39_sbc, C39_plx, C39_pia, 0, C39_sbc, C39_inc, C39_bbs // F8
|
||||
};
|
||||
|
||||
// get instruction byte
|
||||
insn_t &insn = *_insn;
|
||||
uchar code = insn.get_next_byte();
|
||||
// get instruction code
|
||||
insn.itype = Dt[code];
|
||||
// analyze instruction type
|
||||
switch ( insn.itype )
|
||||
{
|
||||
// unknown instruction
|
||||
case 0:
|
||||
return 0;
|
||||
// smb/rmb
|
||||
case C39_smb:
|
||||
case C39_rmb:
|
||||
SetImmData(insn.Op1, (code>>4) & 7);
|
||||
SetMemVar(insn.Op2, insn.get_next_byte());
|
||||
break;
|
||||
// bbs/bbr
|
||||
case C39_bbs:
|
||||
case C39_bbr:
|
||||
SetImmData(insn.Op1, (code>>4)&7);
|
||||
SetMemVar(insn.Op2, insn.get_next_byte());
|
||||
SetRelative(insn, insn.Op3, insn.get_next_byte());
|
||||
break;
|
||||
|
||||
// bpl/bmi/bvc/bvs/bra/bcc/bcs/bne/beq
|
||||
case C39_beq:
|
||||
case C39_bne:
|
||||
case C39_bcs:
|
||||
case C39_bcc:
|
||||
case C39_bra:
|
||||
case C39_bvs:
|
||||
case C39_bvc:
|
||||
case C39_bmi:
|
||||
case C39_bpl:
|
||||
SetRelative(insn, insn.Op1, insn.get_next_byte());
|
||||
break;
|
||||
|
||||
// jsb
|
||||
case C39_jsb:
|
||||
SetMemVar(insn.Op1,0xFFE0+((code>>4) & 7)*2);
|
||||
break;
|
||||
|
||||
// ora, and, eor, adc, sta, lda, cmp, sbc
|
||||
case C39_sbc:
|
||||
case C39_cmp:
|
||||
case C39_lda:
|
||||
case C39_sta:
|
||||
case C39_adc:
|
||||
case C39_eor:
|
||||
case C39_and:
|
||||
case C39_ora:
|
||||
switch ( code&0x1E )
|
||||
{
|
||||
// 01 - xxx ($b)
|
||||
case 0x00:
|
||||
SetMemVarI(insn.Op1, insn.get_next_byte());
|
||||
break;
|
||||
// 05 - xxx $b
|
||||
case 0x04:
|
||||
SetMemVar(insn.Op1, insn.get_next_byte());
|
||||
break;
|
||||
// 09 - xxx #$b
|
||||
case 0x08:
|
||||
SetImmData(insn.Op1, insn.get_next_byte());
|
||||
break;
|
||||
// 0D - xxx $w
|
||||
case 0x0C:
|
||||
SetMemVar(insn.Op1, insn.get_next_word());
|
||||
break;
|
||||
// 11 - xxx ($b), x
|
||||
case 0x10:
|
||||
SetMemVarI(insn.Op1, insn.get_next_byte());
|
||||
SetReg(insn.Op2,rX);
|
||||
break;
|
||||
// 15 - xxx $b, x
|
||||
case 0x14:
|
||||
SetMemVar(insn.Op1, insn.get_next_byte());
|
||||
SetReg(insn.Op2,rX);
|
||||
break;
|
||||
// 19 - xxx $w, y
|
||||
case 0x18:
|
||||
SetMemVar(insn.Op1, insn.get_next_word());
|
||||
SetReg(insn.Op2,rY);
|
||||
break;
|
||||
// 1d - xxx $w, x
|
||||
case 0x1C:
|
||||
SetMemVar(insn.Op1, insn.get_next_word());
|
||||
SetReg(insn.Op2,rX);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
// asl, rol, lsr, ror, asr
|
||||
case C39_asr: // this one has a single variant (asr a)
|
||||
case C39_ror:
|
||||
case C39_lsr:
|
||||
case C39_rol:
|
||||
case C39_asl:
|
||||
switch ( code & 0x1C )
|
||||
{
|
||||
// 6 - xxx $b
|
||||
case 0x04:
|
||||
SetMemVar(insn.Op1, insn.get_next_byte());
|
||||
break;
|
||||
// A - xxx a
|
||||
case 0x08:
|
||||
SetReg(insn.Op1,rA);
|
||||
break;
|
||||
// E - xxx $w
|
||||
case 0x0C:
|
||||
SetMemVar(insn.Op1, insn.get_next_word());
|
||||
break;
|
||||
// 16 - xxx $b, x
|
||||
case 0x14:
|
||||
SetMemVar(insn.Op1, insn.get_next_byte());
|
||||
SetReg(insn.Op2,rX);
|
||||
break;
|
||||
// 1E - xxx $w, x
|
||||
case 0x1C:
|
||||
SetMemVar(insn.Op1, insn.get_next_word());
|
||||
SetReg(insn.Op2,rX);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
// inc, dec
|
||||
case C39_dec:
|
||||
case C39_inc:
|
||||
switch ( code&0x18 )
|
||||
{
|
||||
// e6 - xxx $b
|
||||
case 0x00:
|
||||
SetMemVar(insn.Op1, insn.get_next_byte());
|
||||
break;
|
||||
// ee - xxx $w
|
||||
case 0x08:
|
||||
SetMemVar(insn.Op1, insn.get_next_word());
|
||||
break;
|
||||
// f6 - xxx $b, x
|
||||
case 0x10:
|
||||
SetMemVar(insn.Op1, insn.get_next_byte());
|
||||
SetReg(insn.Op2,rX);
|
||||
break;
|
||||
// fe - xxx $w, x
|
||||
case 0x18:
|
||||
SetMemVar(insn.Op1, insn.get_next_word());
|
||||
SetReg(insn.Op2,rX);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
// rba/sba $b, $w
|
||||
case C39_rba:
|
||||
case C39_sba:
|
||||
SetImmData(insn.Op1, insn.get_next_byte());
|
||||
SetMemVar(insn.Op2, insn.get_next_word());
|
||||
break;
|
||||
|
||||
// cpy/cpx
|
||||
case C39_cpx:
|
||||
case C39_cpy:
|
||||
switch ( code & 0x1C )
|
||||
{
|
||||
// a0 - xxx #$b
|
||||
case 0x00:
|
||||
SetImmData(insn.Op1, insn.get_next_byte());
|
||||
break;
|
||||
// a4 - xxx $b
|
||||
case 0x04:
|
||||
SetMemVar(insn.Op1, insn.get_next_byte());
|
||||
break;
|
||||
// ac - xxx $w
|
||||
case 0x0C:
|
||||
SetMemVar(insn.Op1, insn.get_next_word());
|
||||
break;
|
||||
// 14 - xxx $b, x
|
||||
case 0x14:
|
||||
SetMemVar(insn.Op1, insn.get_next_byte());
|
||||
SetReg(insn.Op2,rX);
|
||||
break;
|
||||
// 1C - xxx $w, x
|
||||
case 0x1C:
|
||||
SetMemVar(insn.Op1, insn.get_next_word());
|
||||
SetReg(insn.Op2,rX);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
// lab/neg
|
||||
case C39_neg:
|
||||
case C39_lab:
|
||||
SetReg(insn.Op1,rA);
|
||||
break;
|
||||
|
||||
// jpi ($w)
|
||||
case C39_jpi:
|
||||
SetMemVarI(insn.Op1, insn.get_next_word());
|
||||
break;
|
||||
|
||||
// jsr $w
|
||||
case C39_jsr:
|
||||
SetAbs(insn.Op1, insn.get_next_word());
|
||||
break;
|
||||
|
||||
// bar/bas $w, $b ,$rel
|
||||
case C39_bar:
|
||||
case C39_bas:
|
||||
SetMemVar(insn.Op1, insn.get_next_word());
|
||||
SetImmData(insn.Op2, insn.get_next_byte());
|
||||
SetRelative(insn, insn.Op3, insn.get_next_byte());
|
||||
break;
|
||||
|
||||
// bit
|
||||
case C39_bit:
|
||||
if ( code & 8 )
|
||||
SetMemVar(insn.Op1, insn.get_next_word()); // bit $w
|
||||
else
|
||||
SetMemVar(insn.Op1, insn.get_next_byte()); // bit $b
|
||||
break;
|
||||
|
||||
// jmp
|
||||
case C39_jmp:
|
||||
switch ( code )
|
||||
{
|
||||
case 0x4C:
|
||||
SetAbs(insn.Op1, insn.get_next_word());
|
||||
break;
|
||||
case 0x6C:
|
||||
SetMemVarI(insn.Op1, insn.get_next_word());
|
||||
break;
|
||||
case 0x7C:
|
||||
SetMemVarI(insn.Op1, insn.get_next_word());
|
||||
SetReg(insn.Op2, rX);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
// sti
|
||||
case C39_sti:
|
||||
SetImmData(insn.Op1,insn.get_next_byte());
|
||||
SetMemVar(insn.Op2,insn.get_next_byte());
|
||||
break;
|
||||
|
||||
// exc
|
||||
case C39_exc:
|
||||
SetMemVar(insn.Op1,insn.get_next_byte());
|
||||
SetReg(insn.Op2,rX);
|
||||
break;
|
||||
|
||||
// add
|
||||
case C39_add:
|
||||
switch ( code )
|
||||
{
|
||||
case 0x64:
|
||||
SetMemVar(insn.Op1,insn.get_next_byte());
|
||||
break;
|
||||
case 0x74:
|
||||
SetMemVar(insn.Op1,insn.get_next_byte());
|
||||
SetReg(insn.Op2,rX);
|
||||
break;
|
||||
case 0x89:
|
||||
SetImmData(insn.Op1,insn.get_next_byte());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
// sty
|
||||
case C39_stx:
|
||||
case C39_ldx:
|
||||
case C39_ldy:
|
||||
case C39_sty:
|
||||
switch ( code & 0x1C )
|
||||
{
|
||||
// A0 xxx #$b
|
||||
case 0x00:
|
||||
SetImmData(insn.Op1,insn.get_next_byte());
|
||||
break;
|
||||
// A4 xxx $b
|
||||
case 0x04:
|
||||
SetMemVar(insn.Op1,insn.get_next_byte());
|
||||
break;
|
||||
// AC xxx $w
|
||||
case 0x0C:
|
||||
SetMemVar(insn.Op1,insn.get_next_word());
|
||||
break;
|
||||
// B4 xxx $b, x
|
||||
case 0x14:
|
||||
SetMemVar(insn.Op1,insn.get_next_byte());
|
||||
SetReg(insn.Op2,
|
||||
insn.itype == C39_sty || insn.itype == C39_ldy ? rX : rY);
|
||||
break;
|
||||
// BC xxx $w, x
|
||||
case 0x1C:
|
||||
SetMemVar(insn.Op1,insn.get_next_word());
|
||||
SetReg(insn.Op2,
|
||||
insn.itype == C39_sty || insn.itype == C39_ldy ? rX : rY);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return insn.size;
|
||||
}
|
||||
Reference in New Issue
Block a user