update
This commit is contained in:
493
idasdk75/module/m740/ana.cpp
Normal file
493
idasdk75/module/m740/ana.cpp
Normal file
@@ -0,0 +1,493 @@
|
||||
|
||||
#include "m740.hpp"
|
||||
|
||||
// 740 addressing modes :
|
||||
enum m740_addr_mode_t ENUM_SIZE(uint8)
|
||||
{
|
||||
A_IMM, // immediate
|
||||
A_ACC, // accumulator
|
||||
A_ZP, // zero page
|
||||
A_ZPX, // zero page X
|
||||
A_ZPY, // zero page Y
|
||||
A_ABS, // absolute
|
||||
A_ABSX, // absolute X
|
||||
A_ABSY, // absolute Y
|
||||
A_IMPL, // implied
|
||||
A_REL, // relative
|
||||
A_INDX, // indirect X
|
||||
A_INDY, // indirect Y
|
||||
A_INDABS, // indirect absolute
|
||||
A_ZPIND, // zero page indirect
|
||||
A_SP, // special page
|
||||
A_ZPB, // zero page bit
|
||||
A_ACCB, // accumulator bit
|
||||
A_ACCBREL, // accumulator bit relative
|
||||
A_ZPBREL // zero page bit relative
|
||||
};
|
||||
|
||||
//lint -e{958} padding needed
|
||||
struct opcode
|
||||
{
|
||||
uint16 insn; // instruction ID
|
||||
uchar code; // operation code, one byte
|
||||
m740_addr_mode_t addr; // addressing mode
|
||||
};
|
||||
|
||||
// 740 operation codes :
|
||||
static const struct opcode opcodes[] =
|
||||
{
|
||||
{ m740_adc, 0x69, A_IMM },
|
||||
{ m740_adc, 0x65, A_ZP },
|
||||
{ m740_adc, 0x75, A_ZPX },
|
||||
{ m740_adc, 0x6D, A_ABS },
|
||||
{ m740_adc, 0x7D, A_ABSX },
|
||||
{ m740_adc, 0x79, A_ABSY },
|
||||
{ m740_adc, 0x61, A_INDX },
|
||||
{ m740_adc, 0x71, A_INDY },
|
||||
{ m740_and, 0x29, A_IMM },
|
||||
{ m740_and, 0x25, A_ZP },
|
||||
{ m740_and, 0x35, A_ZPX },
|
||||
{ m740_and, 0x2D, A_ABS },
|
||||
{ m740_and, 0x3D, A_ABSX },
|
||||
{ m740_and, 0x39, A_ABSY },
|
||||
{ m740_and, 0x21, A_INDX },
|
||||
{ m740_and, 0x31, A_INDY },
|
||||
{ m740_asl, 0x0A, A_ACC },
|
||||
{ m740_asl, 0x06, A_ZP },
|
||||
{ m740_asl, 0x16, A_ZPX },
|
||||
{ m740_asl, 0x0E, A_ABS },
|
||||
{ m740_asl, 0x1E, A_ABSX },
|
||||
{ m740_bcc, 0x90, A_REL },
|
||||
{ m740_bcs, 0xB0, A_REL },
|
||||
{ m740_beq, 0xF0, A_REL },
|
||||
{ m740_bit, 0x24, A_ZP },
|
||||
{ m740_bit, 0x2C, A_ABS },
|
||||
{ m740_bmi, 0x30, A_REL },
|
||||
{ m740_bne, 0xD0, A_REL },
|
||||
{ m740_bpl, 0x10, A_REL },
|
||||
{ m740_bra, 0x80, A_REL },
|
||||
{ m740_brk, 0x00, A_IMPL },
|
||||
{ m740_bvc, 0x50, A_REL },
|
||||
{ m740_bvs, 0x70, A_REL },
|
||||
{ m740_clc, 0x18, A_IMPL },
|
||||
{ m740_cld, 0xD8, A_IMPL },
|
||||
{ m740_cli, 0x58, A_IMPL },
|
||||
{ m740_clt, 0x12, A_IMPL },
|
||||
{ m740_clv, 0xB8, A_IMPL },
|
||||
{ m740_cmp, 0xC9, A_IMM },
|
||||
{ m740_cmp, 0xC5, A_ZP },
|
||||
{ m740_cmp, 0xD5, A_ZPX },
|
||||
{ m740_cmp, 0xCD, A_ABS },
|
||||
{ m740_cmp, 0xDD, A_ABSX },
|
||||
{ m740_cmp, 0xD9, A_ABSY },
|
||||
{ m740_cmp, 0xC1, A_INDX },
|
||||
{ m740_cmp, 0xD1, A_INDY },
|
||||
{ m740_com, 0x44, A_ZP },
|
||||
{ m740_cpx, 0xE0, A_IMM },
|
||||
{ m740_cpx, 0xE4, A_ZP },
|
||||
{ m740_cpx, 0xEC, A_ABS },
|
||||
{ m740_cpy, 0xC0, A_IMM },
|
||||
{ m740_cpy, 0xC4, A_ZP },
|
||||
{ m740_cpy, 0xCC, A_ABS },
|
||||
{ m740_dec, 0x1A, A_ACC },
|
||||
{ m740_dec, 0xC6, A_ZP },
|
||||
{ m740_dec, 0xD6, A_ZPX },
|
||||
{ m740_dec, 0xCE, A_ABS },
|
||||
{ m740_dec, 0xDE, A_ABSX },
|
||||
{ m740_dex, 0xCA, A_IMPL },
|
||||
{ m740_dey, 0x88, A_IMPL },
|
||||
{ m740_div, 0xE2, A_ZPX },
|
||||
{ m740_eor, 0x49, A_IMM },
|
||||
{ m740_eor, 0x45, A_ZP },
|
||||
{ m740_eor, 0x55, A_ZPX },
|
||||
{ m740_eor, 0x4D, A_ABS },
|
||||
{ m740_eor, 0x5D, A_ABSX },
|
||||
{ m740_eor, 0x59, A_ABSY },
|
||||
{ m740_eor, 0x41, A_INDX },
|
||||
{ m740_eor, 0x51, A_INDY },
|
||||
{ m740_inc, 0x3A, A_ACC },
|
||||
{ m740_inc, 0xE6, A_ZP },
|
||||
{ m740_inc, 0xF6, A_ZPX },
|
||||
{ m740_inc, 0xEE, A_ABS },
|
||||
{ m740_inc, 0xFE, A_ABSX },
|
||||
{ m740_inx, 0xE8, A_IMPL },
|
||||
{ m740_iny, 0xC8, A_IMPL },
|
||||
{ m740_jmp, 0x4C, A_ABS },
|
||||
{ m740_jmp, 0x6C, A_INDABS },
|
||||
{ m740_jmp, 0xB2, A_ZPIND },
|
||||
{ m740_jsr, 0x20, A_ABS },
|
||||
{ m740_jsr, 0x22, A_SP },
|
||||
{ m740_jsr, 0x02, A_ZPIND },
|
||||
{ m740_lda, 0xA9, A_IMM },
|
||||
{ m740_lda, 0xA5, A_ZP },
|
||||
{ m740_lda, 0xB5, A_ZPX },
|
||||
{ m740_lda, 0xAD, A_ABS },
|
||||
{ m740_lda, 0xBD, A_ABSX },
|
||||
{ m740_lda, 0xB9, A_ABSY },
|
||||
{ m740_lda, 0xA1, A_INDX },
|
||||
{ m740_lda, 0xB1, A_INDY },
|
||||
{ m740_ldm, 0x3C, A_ZP },
|
||||
{ m740_ldx, 0xA2, A_IMM },
|
||||
{ m740_ldx, 0xA6, A_ZP },
|
||||
{ m740_ldx, 0xB6, A_ZPY },
|
||||
{ m740_ldx, 0xAE, A_ABS },
|
||||
{ m740_ldx, 0xBE, A_ABSY },
|
||||
{ m740_ldy, 0xA0, A_IMM },
|
||||
{ m740_ldy, 0xA4, A_ZP },
|
||||
{ m740_ldy, 0xB4, A_ZPX },
|
||||
{ m740_ldy, 0xAC, A_ABS },
|
||||
{ m740_ldy, 0xBC, A_ABSX },
|
||||
{ m740_lsr, 0x4A, A_ACC },
|
||||
{ m740_lsr, 0x46, A_ZP },
|
||||
{ m740_lsr, 0x56, A_ZPX },
|
||||
{ m740_lsr, 0x4E, A_ABS },
|
||||
{ m740_lsr, 0x5E, A_ABSX },
|
||||
{ m740_mul, 0x62, A_ZPX },
|
||||
{ m740_nop, 0xEA, A_IMPL },
|
||||
{ m740_ora, 0x09, A_IMM },
|
||||
{ m740_ora, 0x05, A_ZP },
|
||||
{ m740_ora, 0x15, A_ZPX },
|
||||
{ m740_ora, 0x0D, A_ABS },
|
||||
{ m740_ora, 0x1D, A_ABSX },
|
||||
{ m740_ora, 0x19, A_ABSY },
|
||||
{ m740_ora, 0x01, A_INDX },
|
||||
{ m740_ora, 0x11, A_INDY },
|
||||
{ m740_pha, 0x48, A_IMPL },
|
||||
{ m740_php, 0x08, A_IMPL },
|
||||
{ m740_pla, 0x68, A_IMPL },
|
||||
{ m740_plp, 0x28, A_IMPL },
|
||||
{ m740_rol, 0x2A, A_ACC },
|
||||
{ m740_rol, 0x26, A_ZP },
|
||||
{ m740_rol, 0x36, A_ZPX },
|
||||
{ m740_rol, 0x2E, A_ABS },
|
||||
{ m740_rol, 0x3E, A_ABSX },
|
||||
{ m740_ror, 0x6A, A_ACC },
|
||||
{ m740_ror, 0x66, A_ZP },
|
||||
{ m740_ror, 0x76, A_ZPX },
|
||||
{ m740_ror, 0x6E, A_ABS },
|
||||
{ m740_ror, 0x7E, A_ABSX },
|
||||
{ m740_rrf, 0x82, A_ZP },
|
||||
{ m740_rti, 0x40, A_IMPL },
|
||||
{ m740_rts, 0x60, A_IMPL },
|
||||
{ m740_sbc, 0xE9, A_IMM },
|
||||
{ m740_sbc, 0xE5, A_ZP },
|
||||
{ m740_sbc, 0xF5, A_ZPX },
|
||||
{ m740_sbc, 0xED, A_ABS },
|
||||
{ m740_sbc, 0xFD, A_ABSX },
|
||||
{ m740_sbc, 0xF9, A_ABSY },
|
||||
{ m740_sbc, 0xE1, A_INDX },
|
||||
{ m740_sbc, 0xF1, A_INDY },
|
||||
{ m740_sec, 0x38, A_IMPL },
|
||||
{ m740_sed, 0xF8, A_IMPL },
|
||||
{ m740_sei, 0x78, A_IMPL },
|
||||
{ m740_set, 0x32, A_IMPL },
|
||||
{ m740_sta, 0x85, A_ZP },
|
||||
{ m740_sta, 0x95, A_ZPX },
|
||||
{ m740_sta, 0x8D, A_ABS },
|
||||
{ m740_sta, 0x9D, A_ABSX },
|
||||
{ m740_sta, 0x99, A_ABSY },
|
||||
{ m740_sta, 0x81, A_INDX },
|
||||
{ m740_sta, 0x91, A_INDY },
|
||||
{ m740_stp, 0x42, A_IMPL },
|
||||
{ m740_stx, 0x86, A_ZP },
|
||||
{ m740_stx, 0x96, A_ZPY },
|
||||
{ m740_stx, 0x8E, A_ABS },
|
||||
{ m740_sty, 0x84, A_ZP },
|
||||
{ m740_sty, 0x94, A_ZPX },
|
||||
{ m740_sty, 0x8C, A_ABS },
|
||||
{ m740_tax, 0xAA, A_IMPL },
|
||||
{ m740_tay, 0xA8, A_IMPL },
|
||||
{ m740_tst, 0x64, A_ZP },
|
||||
{ m740_tsx, 0xBA, A_IMPL },
|
||||
{ m740_txa, 0x8A, A_IMPL },
|
||||
{ m740_txs, 0x9A, A_IMPL },
|
||||
{ m740_tya, 0x98, A_IMPL },
|
||||
{ m740_wit, 0xC2, A_IMPL }
|
||||
};
|
||||
|
||||
struct opcode_flag
|
||||
{
|
||||
uint16 insn;
|
||||
uchar flags;
|
||||
#define MEM_R OP_ADDR_R // read access
|
||||
#define MEM_W OP_ADDR_W // write access
|
||||
};
|
||||
|
||||
static const struct opcode_flag opcodes_flags[] =
|
||||
{
|
||||
{ m740_adc, MEM_R },
|
||||
{ m740_and, MEM_R },
|
||||
{ m740_asl, MEM_W },
|
||||
{ m740_bbc, MEM_R },
|
||||
{ m740_bbs, MEM_R },
|
||||
{ m740_bit, MEM_R },
|
||||
{ m740_clb, MEM_W },
|
||||
{ m740_cmp, MEM_R },
|
||||
{ m740_com, MEM_W },
|
||||
{ m740_cpx, MEM_R },
|
||||
{ m740_cpy, MEM_R },
|
||||
{ m740_dec, MEM_W },
|
||||
{ m740_eor, MEM_R },
|
||||
{ m740_inc, MEM_W },
|
||||
{ m740_jmp, MEM_R },
|
||||
{ m740_jsr, MEM_R },
|
||||
{ m740_lda, MEM_R },
|
||||
{ m740_ldm, MEM_W },
|
||||
{ m740_ldx, MEM_R },
|
||||
{ m740_ldy, MEM_R },
|
||||
{ m740_lsr, MEM_W },
|
||||
{ m740_ora, MEM_R },
|
||||
{ m740_rol, MEM_W },
|
||||
{ m740_ror, MEM_W },
|
||||
{ m740_sbc, MEM_R },
|
||||
{ m740_seb, MEM_W },
|
||||
{ m740_sta, MEM_W },
|
||||
{ m740_stx, MEM_W },
|
||||
{ m740_sty, MEM_W },
|
||||
{ m740_tst, MEM_R },
|
||||
{ m740_rrf, MEM_W }
|
||||
};
|
||||
|
||||
// fill operand as a register
|
||||
inline static void set_op_reg(op_t &op, uint16 reg)
|
||||
{
|
||||
op.type = o_reg;
|
||||
op.reg = reg;
|
||||
op.dtype = dt_word; // XXX not sure
|
||||
}
|
||||
|
||||
// a shortcut to make our live easier
|
||||
#define set_op_acc(x) set_op_reg(x, rA)
|
||||
|
||||
// fill operand as a code address
|
||||
inline static void set_op_addr(op_t &op, ea_t addr)
|
||||
{
|
||||
op.type = o_near;
|
||||
op.addr = addr;
|
||||
op.dtype = dt_code;
|
||||
}
|
||||
|
||||
// fill operand as a displacement between a memory address and a register contents
|
||||
inline static void set_op_displ(insn_t &insn, int addr, uint16 reg, char d_typ = dt_byte)
|
||||
{
|
||||
insn.Op1.type = o_displ;
|
||||
insn.Op1.addr = addr;
|
||||
insn.Op1.reg = reg;
|
||||
insn.Op1.dtype = d_typ;
|
||||
}
|
||||
|
||||
// fill operand as a data address
|
||||
inline static void set_op_mem(op_t &op, int addr, const uchar flags = 0, char d_typ = dt_byte)
|
||||
{
|
||||
op.type = o_mem;
|
||||
op.addr = addr;
|
||||
op.dtype = d_typ;
|
||||
op.specflag1 = flags;
|
||||
}
|
||||
|
||||
// fill operand as an immediate value
|
||||
inline static void set_op_imm(op_t &op, int imm)
|
||||
{
|
||||
op.type = o_imm;
|
||||
op.value = imm;
|
||||
op.dtype = dt_byte;
|
||||
}
|
||||
|
||||
// fill the insn structure according to the addressing mode of the
|
||||
// current analyzed instruction
|
||||
static void fill_insn(insn_t &insn, m740_addr_mode_t addr, const uchar flags = 0)
|
||||
{
|
||||
switch ( addr )
|
||||
{
|
||||
case A_IMM: // immediate
|
||||
set_op_imm(insn.Op1, insn.get_next_byte());
|
||||
break;
|
||||
|
||||
case A_ACC: // accumulator
|
||||
set_op_acc(insn.Op1);
|
||||
break;
|
||||
|
||||
case A_ZP: // zero page
|
||||
if ( insn.itype == m740_ldm ) // special case
|
||||
{
|
||||
set_op_imm(insn.Op1, insn.get_next_byte());
|
||||
set_op_mem(insn.Op2, insn.get_next_byte(), flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_op_mem(insn.Op1, insn.get_next_byte(), flags);
|
||||
}
|
||||
break;
|
||||
|
||||
case A_ZPX: // zero page X
|
||||
set_op_displ(insn, insn.get_next_byte(), rX);
|
||||
insn.auxpref |= INSN_DISPL_ZPX;
|
||||
break;
|
||||
|
||||
case A_ZPY: // zero page Y
|
||||
set_op_displ(insn, insn.get_next_byte(), rY);
|
||||
insn.auxpref |= INSN_DISPL_ZPY;
|
||||
break;
|
||||
|
||||
case A_ABS: // absolute
|
||||
if ( insn.itype == m740_jmp || insn.itype == m740_jsr )
|
||||
set_op_addr(insn.Op1, insn.get_next_word());
|
||||
else
|
||||
set_op_mem(insn.Op1, insn.get_next_word(), flags);
|
||||
break;
|
||||
|
||||
case A_ABSX: // absolute X
|
||||
set_op_displ(insn, insn.get_next_word(), rX);
|
||||
insn.auxpref |= INSN_DISPL_ABSX;
|
||||
break;
|
||||
|
||||
case A_ABSY: // absolute Y
|
||||
set_op_displ(insn, insn.get_next_word(), rY);
|
||||
insn.auxpref |= INSN_DISPL_ABSY;
|
||||
break;
|
||||
|
||||
case A_IMPL: // implied
|
||||
// nothing to do..
|
||||
break;
|
||||
|
||||
case A_REL: // relative
|
||||
set_op_addr(insn.Op1, (signed char) insn.get_next_byte() + insn.ea + 2);
|
||||
break;
|
||||
|
||||
case A_INDX: // indirect X
|
||||
set_op_displ(insn, insn.get_next_byte(), rX, dt_word);
|
||||
insn.auxpref |= INSN_DISPL_INDX;
|
||||
break;
|
||||
|
||||
case A_INDY: // indirect Y
|
||||
set_op_displ(insn, insn.get_next_byte(), rY, dt_word);
|
||||
insn.auxpref |= INSN_DISPL_INDY;
|
||||
break;
|
||||
|
||||
case A_INDABS: // indirect absolute
|
||||
set_op_mem(insn.Op1, insn.get_next_word(), flags, dt_word);
|
||||
insn.Op1.specflag1 |= OP_ADDR_IND;
|
||||
break;
|
||||
|
||||
case A_ZPIND: // zero page indirect
|
||||
set_op_mem(insn.Op1, insn.get_next_byte(), 0, dt_word);
|
||||
insn.Op1.specflag1 |= OP_ADDR_IND;
|
||||
break;
|
||||
|
||||
case A_SP: // special page
|
||||
set_op_addr(insn.Op1, insn.get_next_byte() | 0xFF00);
|
||||
insn.Op1.specflag1 |= OP_ADDR_SP;
|
||||
break;
|
||||
|
||||
case A_ZPB: // zero page bit
|
||||
set_op_mem(insn.Op2, insn.get_next_byte(), flags, dt_word);
|
||||
break;
|
||||
|
||||
case A_ACCB: // accumulator bit
|
||||
set_op_acc(insn.Op2);
|
||||
break;
|
||||
|
||||
case A_ACCBREL: // accumulator bit relative
|
||||
set_op_acc(insn.Op2);
|
||||
set_op_addr(insn.Op3, (signed char) insn.get_next_byte() + insn.ea + 2);
|
||||
break;
|
||||
|
||||
case A_ZPBREL: // zero page bit relative
|
||||
set_op_mem(insn.Op2, insn.get_next_byte(), flags);
|
||||
set_op_addr(insn.Op3, (signed char) insn.get_next_byte() + insn.ea + 3);
|
||||
break;
|
||||
|
||||
default:
|
||||
INTERR(10025);
|
||||
}
|
||||
}
|
||||
|
||||
// try to find an opcode in our table from the fetched byte
|
||||
static const struct opcode *get_opcode(int byte)
|
||||
{
|
||||
for ( int i = 0; i < qnumber(opcodes); i++ )
|
||||
{
|
||||
if ( opcodes[i].code != byte )
|
||||
continue;
|
||||
return &opcodes[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static uchar get_opcode_flags(const uint16 insn)
|
||||
{
|
||||
for ( int i = 0; i < qnumber(opcodes_flags); i++ )
|
||||
{
|
||||
if ( opcodes_flags[i].insn != insn )
|
||||
continue;
|
||||
return opcodes_flags[i].flags;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// detect special instructions, whose we can't detect using the table and the
|
||||
// get_opcode() routine
|
||||
static bool ana_special(insn_t &insn, int byte)
|
||||
{
|
||||
bool special = false;
|
||||
|
||||
//lint -e{958} padding needed
|
||||
struct spec_info_t
|
||||
{
|
||||
uint16 insn; // instruction ID
|
||||
uchar val; // (20i + val)
|
||||
m740_addr_mode_t addr; // which addressing mode ?
|
||||
};
|
||||
static const spec_info_t specials[] =
|
||||
{
|
||||
{ m740_bbc, 0x13, A_ACCBREL },
|
||||
{ m740_bbc, 0x17, A_ZPBREL },
|
||||
{ m740_bbs, 0x03, A_ACCBREL },
|
||||
{ m740_bbs, 0x07, A_ZPBREL },
|
||||
{ m740_clb, 0x1B, A_ACCB },
|
||||
{ m740_clb, 0x1F, A_ZPB },
|
||||
{ m740_seb, 0x0B, A_ACCB },
|
||||
{ m740_seb, 0x0F, A_ZPB }
|
||||
};
|
||||
|
||||
for ( int i = 0; i < qnumber(specials); i++ )
|
||||
{
|
||||
int t = (uchar) byte - specials[i].val;
|
||||
if ( (t % 0x20) != 0 )
|
||||
continue;
|
||||
|
||||
insn.itype = specials[i].insn;
|
||||
|
||||
set_op_imm(insn.Op1, t / 0x20);
|
||||
insn.Op1.specflag1 |= OP_IMM_BIT;
|
||||
fill_insn(insn, specials[i].addr, get_opcode_flags(specials[i].insn));
|
||||
special = true;
|
||||
break;
|
||||
}
|
||||
|
||||
return special;
|
||||
}
|
||||
|
||||
// analyze an instruction
|
||||
int idaapi ana(insn_t *_insn)
|
||||
{
|
||||
insn_t &insn = *_insn;
|
||||
|
||||
bool special;
|
||||
int byte;
|
||||
|
||||
byte = insn.get_next_byte();
|
||||
special = ana_special(insn, byte);
|
||||
|
||||
if ( !special )
|
||||
{
|
||||
const struct opcode *op = get_opcode(byte);
|
||||
if ( op == NULL ) // unmatched insn
|
||||
return 0;
|
||||
|
||||
insn.itype = op->insn;
|
||||
fill_insn(insn, op->addr, get_opcode_flags(op->insn));
|
||||
}
|
||||
|
||||
return insn.size;
|
||||
}
|
||||
135
idasdk75/module/m740/emu.cpp
Normal file
135
idasdk75/module/m740/emu.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
|
||||
#include "m740.hpp"
|
||||
|
||||
static void handle_imm(const insn_t &insn, const op_t &op, flags_t F)
|
||||
{
|
||||
set_immd(insn.ea);
|
||||
if ( is_defarg(F, op.n) )
|
||||
return;
|
||||
bool in_hex = false;
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case m740_and:
|
||||
case m740_ora:
|
||||
in_hex = true;
|
||||
break;
|
||||
}
|
||||
if ( in_hex )
|
||||
op_hex(insn.ea, op.n);
|
||||
}
|
||||
|
||||
void m740_t::handle_operand(const insn_t &insn, const op_t &op)
|
||||
{
|
||||
flags_t F = get_flags(insn.ea);
|
||||
switch ( op.type )
|
||||
{
|
||||
// code address
|
||||
case o_near:
|
||||
{
|
||||
ea_t ea = to_ea(insn.cs, op.addr);
|
||||
cref_t mode = fl_JN;
|
||||
if ( insn.itype == m740_jsr )
|
||||
{
|
||||
if ( !func_does_return(ea) )
|
||||
flow = false;
|
||||
mode = fl_CN;
|
||||
}
|
||||
insn.add_cref(ea, op.offb, mode);
|
||||
}
|
||||
break;
|
||||
|
||||
// data address
|
||||
case o_mem:
|
||||
{
|
||||
enum dref_t mode = dr_U;
|
||||
|
||||
if ( is_addr_ind(op) )
|
||||
mode = dr_R; /* NOT dr_O */
|
||||
else if ( is_addr_read(op) )
|
||||
mode = dr_R;
|
||||
else if ( is_addr_write(op) )
|
||||
mode = dr_W;
|
||||
|
||||
insn.add_dref(to_ea(insn.cs, op.addr), op.offb, mode);
|
||||
insn.create_op_data(op.addr, op);
|
||||
}
|
||||
break;
|
||||
|
||||
// immediate
|
||||
case o_imm:
|
||||
handle_imm(insn, op, F);
|
||||
// if the value was converted to an offset, then create a data xref:
|
||||
if ( op_adds_xrefs(F, op.n) )
|
||||
insn.add_off_drefs(op, dr_O, 0);
|
||||
break;
|
||||
|
||||
// displ
|
||||
case o_displ:
|
||||
if ( op_adds_xrefs(F, op.n) )
|
||||
{
|
||||
ea_t ea = insn.add_off_drefs(op, dr_O, OOF_ADDR);
|
||||
insn.create_op_data(ea, op);
|
||||
}
|
||||
break;
|
||||
|
||||
// reg - do nothing
|
||||
case o_reg:
|
||||
case o_void:
|
||||
break;
|
||||
|
||||
default:
|
||||
INTERR(10022);
|
||||
}
|
||||
}
|
||||
|
||||
// emulate an instruction
|
||||
int m740_t::emu(const insn_t &insn)
|
||||
{
|
||||
uint32 feature = insn.get_canon_feature(ph);
|
||||
flow = ((feature & CF_STOP) == 0);
|
||||
|
||||
if ( insn.Op1.type != o_void ) handle_operand(insn, insn.Op1);
|
||||
if ( insn.Op2.type != o_void ) handle_operand(insn, insn.Op2);
|
||||
if ( insn.Op3.type != o_void ) handle_operand(insn, insn.Op3);
|
||||
|
||||
/*
|
||||
we can't use this code
|
||||
|
||||
if ( feature & CF_USE1) handle_operand(insn, insn.Op1, 1 );
|
||||
if ( feature & CF_USE2) handle_operand(insn, insn.Op2, 1 );
|
||||
if ( feature & CF_USE3) handle_operand(insn, insn.Op3, 1 );
|
||||
*/
|
||||
|
||||
// we don't use CF_JUMP
|
||||
//if ( feature & CF_JUMP )
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case m740_jmp:
|
||||
case m740_jsr:
|
||||
if ( insn.Op1.type != o_void && is_addr_ind(insn.Op1) )
|
||||
remember_problem(PR_JUMP, insn.ea);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
if ( feature & CF_CHG1) handle_operand(insn, insn.Op1, 0 );
|
||||
if ( feature & CF_CHG2) handle_operand(insn, insn.Op2, 0 );
|
||||
if ( feature & CF_CHG3) handle_operand(insn, insn.Op3, 0 );
|
||||
*/
|
||||
|
||||
if ( flow )
|
||||
{
|
||||
// skip the next byte if the current insn is brk
|
||||
if ( insn.itype == m740_brk )
|
||||
{
|
||||
add_cref(insn.ea, insn.ea + insn.size + 1, fl_JN);
|
||||
create_byte(insn.ea + insn.size, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
add_cref(insn.ea, insn.ea + insn.size, fl_F);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
80
idasdk75/module/m740/ins.cpp
Normal file
80
idasdk75/module/m740/ins.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
|
||||
#include "m740.hpp"
|
||||
|
||||
const instruc_t Instructions[] =
|
||||
{
|
||||
{ "", 0 }, // null instruction
|
||||
{ "adc", CF_USE1 }, // add with carry
|
||||
{ "and", CF_USE1 }, // logical and
|
||||
{ "asl", CF_USE1 }, // arithmetic shift left
|
||||
{ "bbc", CF_USE1|CF_USE2|CF_USE3 }, // branch on bit clear
|
||||
{ "bbs", CF_USE1|CF_USE2|CF_USE3 }, // branch on bit set
|
||||
{ "bcc", CF_USE1 }, // branch on carry clear
|
||||
{ "bcs", CF_USE1 }, // branch on carry set
|
||||
{ "beq", CF_USE1 }, // branch on equal
|
||||
{ "bit", CF_USE1 }, // test bit in memory with accumulator
|
||||
{ "bmi", CF_USE1 }, // branch on result minus
|
||||
{ "bne", CF_USE1 }, // branch on not equal
|
||||
{ "bpl", CF_USE1 }, // branch on result plus
|
||||
{ "bra", CF_USE1|CF_STOP }, // branch always
|
||||
{ "brk", 0 }, // force break
|
||||
{ "bvc", CF_USE1 }, // branch on overflow clear
|
||||
{ "bvs", CF_USE1 }, // branch on overflow set
|
||||
{ "clb", CF_USE1|CF_USE2|CF_CHG2 }, // clear bit
|
||||
{ "clc", 0 }, // clear carry flag
|
||||
{ "cld", 0 }, // clear decimal mode
|
||||
{ "cli", 0 }, // clear interrupt disable status
|
||||
{ "clt", 0 }, // clear transfer flag
|
||||
{ "clv", 0 }, // clear overflow flag
|
||||
{ "cmp", CF_USE1 }, // compare
|
||||
{ "com", CF_USE1|CF_CHG1 }, // complement
|
||||
{ "cpx", CF_USE1 }, // compare memory and index register X
|
||||
{ "cpy", CF_USE1 }, // compare memory and index register Y
|
||||
{ "dec", CF_USE1|CF_CHG1 }, // decrement by one
|
||||
{ "dex", 0 }, // decrement index register X by one
|
||||
{ "dey", 0 }, // decrement index register Y by one
|
||||
{ "div", CF_USE1 }, // divide memory by accumulator
|
||||
{ "eor", CF_USE1 }, // exclusive or memory with accumulator
|
||||
{ "inc", CF_USE1|CF_CHG1 }, // increment by one
|
||||
{ "inx", 0 }, // increment index register X by one
|
||||
{ "iny", 0 }, // increment index register Y by one
|
||||
{ "jmp", CF_USE1|CF_STOP }, // jump
|
||||
{ "jsr", CF_USE1|CF_CALL }, // jump to subroutine
|
||||
{ "lda", CF_USE1 }, // load accumulator with memory
|
||||
{ "ldm", CF_USE1|CF_USE2|CF_CHG2 }, // load immediate data to memory
|
||||
{ "ldx", CF_USE1 }, // load index register X from memory
|
||||
{ "ldy", CF_USE1 }, // load index register Y from memory
|
||||
{ "lsr", CF_USE1|CF_CHG1 }, // logical shift right
|
||||
{ "mul", CF_USE1 }, // multiply accumulator and memory
|
||||
{ "nop", 0 }, // no operation
|
||||
{ "ora", CF_USE1 }, // or memory with accumulator
|
||||
{ "pha", 0 }, // push accumulator on stack
|
||||
{ "php", 0 }, // push processor status on stack
|
||||
{ "pla", 0 }, // pull accumulator from stack
|
||||
{ "plp", 0 }, // pull processor status from stack
|
||||
{ "rol", CF_USE1|CF_CHG1 }, // rotate one bit left
|
||||
{ "ror", CF_USE1|CF_CHG1 }, // rotate one bit right
|
||||
{ "rrf", CF_USE1|CF_CHG1 }, // rotate right of four bits
|
||||
{ "rti", CF_STOP }, // return from interrupt
|
||||
{ "rts", CF_STOP }, // return from subroutine
|
||||
{ "sbc", CF_USE1 }, // subtract with carry
|
||||
{ "seb", CF_USE1|CF_USE2|CF_CHG2 }, // set bit
|
||||
{ "sec", 0 }, // set carry flag
|
||||
{ "sed", 0 }, // set decimal mode
|
||||
{ "sei", 0 }, // set interrupt disable flag
|
||||
{ "set", 0 }, // set transfert flag
|
||||
{ "sta", CF_CHG1 }, // store accumulator in memory
|
||||
{ "stp", 0 }, // stop
|
||||
{ "stx", CF_CHG1 }, // store index register X in memory
|
||||
{ "sty", CF_CHG1 }, // store index register Y in memory
|
||||
{ "tax", 0 }, // transfert accumulator to index register X
|
||||
{ "tay", 0 }, // transfert accumulator to index register Y
|
||||
{ "tst", CF_USE1 }, // test for negative or zero
|
||||
{ "tsx", 0 }, // transfert stack pointer to index register X
|
||||
{ "txa", 0 }, // transfert index register X to accumulator
|
||||
{ "txs", 0 }, // transfert index register X to stack pointer
|
||||
{ "tya", 0 }, // transfert index register Y to accumulator
|
||||
{ "wit", 0 } // wait
|
||||
};
|
||||
|
||||
CASSERT(qnumber(Instructions) == m740_last);
|
||||
86
idasdk75/module/m740/ins.hpp
Normal file
86
idasdk75/module/m740/ins.hpp
Normal file
@@ -0,0 +1,86 @@
|
||||
|
||||
#ifndef __INS_HPP
|
||||
#define __INS_HPP
|
||||
|
||||
extern const instruc_t Instructions[];
|
||||
|
||||
enum nameNum ENUM_SIZE(uint16)
|
||||
{
|
||||
m740_null = 0, // null instruction
|
||||
m740_adc, // add with carry
|
||||
m740_and, // logical and
|
||||
m740_asl, // arithmetic shift left
|
||||
m740_bbc, // branch on bit clear
|
||||
m740_bbs, // branch on bit set
|
||||
m740_bcc, // branch on carry clear
|
||||
m740_bcs, // branch on carry set
|
||||
m740_beq, // branch on equal
|
||||
m740_bit, // test bit in memory with accumulator
|
||||
m740_bmi, // branch on result minus
|
||||
m740_bne, // branch on not equal
|
||||
m740_bpl, // branch on result plus
|
||||
m740_bra, // branch always
|
||||
m740_brk, // force break
|
||||
m740_bvc, // branch on overflow clear
|
||||
m740_bvs, // branch on overflow set
|
||||
m740_clb, // clear bit
|
||||
m740_clc, // clear carry flag
|
||||
m740_cld, // clear decimal mode
|
||||
m740_cli, // clear interrupt disable status
|
||||
m740_clt, // clear transfer flag
|
||||
m740_clv, // clear overflow flag
|
||||
m740_cmp, // compare
|
||||
m740_com, // complement
|
||||
m740_cpx, // compare memory and index register X
|
||||
m740_cpy, // compare memory and index register Y
|
||||
m740_dec, // decrement by one
|
||||
m740_dex, // decrement index register X by one
|
||||
m740_dey, // decrement index register Y by one
|
||||
m740_div, // divide memory by accumulator
|
||||
m740_eor, // exclusive or memory with accumulator
|
||||
m740_inc, // increment by one
|
||||
m740_inx, // increment index register X by one
|
||||
m740_iny, // increment index register Y by one
|
||||
m740_jmp, // jump
|
||||
m740_jsr, // jump to subroutine
|
||||
m740_lda, // load accumulator with memory
|
||||
m740_ldm, // load immediate data to memory
|
||||
m740_ldx, // load index register X from memory
|
||||
m740_ldy, // load index register Y from memory
|
||||
m740_lsr, // logical shift right
|
||||
m740_mul, // multiply accumulator and memory
|
||||
m740_nop, // no operation
|
||||
m740_ora, // or memory with accumulator
|
||||
m740_pha, // push accumulator on stack
|
||||
m740_php, // push processor status on stack
|
||||
m740_pla, // pull accumulator from stack
|
||||
m740_plp, // pull processor status from stack
|
||||
m740_rol, // rotate one bit left
|
||||
m740_ror, // rotate one bit right
|
||||
m740_rrf, // rotate right of four bits
|
||||
m740_rti, // return from interrupt
|
||||
m740_rts, // return from subroutine
|
||||
m740_sbc, // subtract with carry
|
||||
m740_seb, // set bit
|
||||
m740_sec, // set carry flag
|
||||
m740_sed, // set decimal mode
|
||||
m740_sei, // set interrupt disable flag
|
||||
m740_set, // set transfert flag
|
||||
m740_sta, // store accumulator in memory
|
||||
m740_stp, // stop
|
||||
m740_stx, // store index register X in memory
|
||||
m740_sty, // store index register Y in memory
|
||||
m740_tax, // transfert accumulator to index register X
|
||||
m740_tay, // transfert accumulator to index register Y
|
||||
m740_tst, // test for negative or zero
|
||||
m740_tsx, // transfert stack pointer to index register X
|
||||
m740_txa, // transfert index register X to accumulator
|
||||
m740_txs, // transfert index register X to stack pointer
|
||||
m740_tya, // transfert index register Y to accumulator
|
||||
m740_wit, // wait
|
||||
|
||||
m740_last
|
||||
};
|
||||
|
||||
#endif /* __INS_HPP */
|
||||
|
||||
145
idasdk75/module/m740/m740.cfg
Normal file
145
idasdk75/module/m740/m740.cfg
Normal file
@@ -0,0 +1,145 @@
|
||||
|
||||
; Warning : this file is empty because we don't have documentation on 740
|
||||
; specific ports.
|
||||
;
|
||||
; Feel free to fill this file for your own usage, and please drop us a mail
|
||||
; if you find any documentation on the 740 ports.
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; devices from http://www.mitsubishiusb.com/documents/536/architecture740.pdf
|
||||
|
||||
.default 38000
|
||||
;
|
||||
;.37451
|
||||
P0 0xd0 P0 register
|
||||
P0_DIR 0xd1 P0 directional register
|
||||
P1 0xd2 P1 register
|
||||
P1_DIR 0xd3 P1 directional register
|
||||
P2 0xd4 P2 register
|
||||
P2_DIR 0xd5 P2 directional register
|
||||
P3 0xd6 P3 register
|
||||
P3_DIR 0xd7 P3 directional register
|
||||
P4_PWM 0xd8 P4 register/PWM prescaler latch
|
||||
ADD_FUNC 0xd9 Additional function register
|
||||
P5 0xda P5 register
|
||||
P5_DIR 0xdb P5 directional register
|
||||
P6 0xdc P6 register
|
||||
P6_DIR 0xdd P6 directional register
|
||||
MISRG1 0xde MISRG1
|
||||
MISRG2 0xdf MISRG2
|
||||
D2A1 0xe0 D-A1 register
|
||||
D2A2 0xe1 D-A2 register
|
||||
A2D 0xe2 A-D register
|
||||
A2D_CTRL 0xe3 A-D control register
|
||||
DB_BUFFER 0xe4 Data bus buffer register
|
||||
DB_STATUS 0xe5 Data bus buffer status register
|
||||
RX_TX_BUF 0xe6 Receive/Transmit buffer register
|
||||
SERIAL_STAT 0xe7 Serial I/O status register
|
||||
SERIAL_CTRL 0xe8 Serial I/O control register
|
||||
UART_CTRL 0xe9 UART control register
|
||||
BAUDRATE 0xea Baud rate generator
|
||||
PWM_LO 0xeb PWM register (low-order)
|
||||
PWM_HI 0xec PWN register (high-order)
|
||||
TMR1_CTRL 0xed Timer 1 control register
|
||||
TMR2_CTRL 0xee Timer 2 control register
|
||||
TMR3_CTRL 0xef Timer 3 control register
|
||||
TMR1_LO 0xf0 Timer 1 register (low-order)
|
||||
TMR1_HI 0xf1 Timer 1 register (high-order)
|
||||
TMR1_LCH_LO 0xf2 Timer 1 latch (low-order)
|
||||
TMR1_LCH_HI 0xf3 Timer 1 latch (high-order)
|
||||
TMR2_LO 0xf4 Timer 2 register (low-order)
|
||||
TMR2_HI 0xf5 Timer 2 register (high-order)
|
||||
TMR2_LCH_LO 0xf6 Timer 2 latch (low-order)
|
||||
TMR2_LCH_HI 0xf7 Timer 2 latch (high-order)
|
||||
TMR3_LO 0xf8 Timer 3 register (low-order)
|
||||
TMR3_HI 0xf9 Timer 3 register (high-order)
|
||||
TMR3_LCH_LO 0xfa Timer 3 latch (low-order)
|
||||
TMR3_LCH_HI 0xfb Timer 3 latch (high-order)
|
||||
INTREQ1 0xfc Interrupt request register 1
|
||||
INTREQ2 0xfd Interrupt request register 2
|
||||
INT_CTRL1 0xfe Interrupt control register 1
|
||||
INT_CTRL2 0xff Interrupt control register 2
|
||||
;
|
||||
;EX_37450 0x12 37450 only
|
||||
;
|
||||
;.37470
|
||||
;
|
||||
;EX_37470 0x13 37470 only
|
||||
;
|
||||
;.37500
|
||||
;
|
||||
;EX_37500 0x14 37500 only
|
||||
;
|
||||
;.Slim-740
|
||||
;
|
||||
;EX_SLIM_740 0x15 SLIM-740 only
|
||||
|
||||
.38000
|
||||
|
||||
; m3804x courtesy of mrnobody (from hex-rays' forum)
|
||||
.3804x
|
||||
|
||||
P0 0x00 P0 register
|
||||
P0D 0x01 P0 directional register
|
||||
P1 0x02 P1 register
|
||||
P1D 0x03 P1 directional register
|
||||
P2 0x04 P2 register
|
||||
P2D 0x05 P2 directional register
|
||||
P3 0x06 P3 register
|
||||
P3D 0x07 P3 directional register
|
||||
P4 0x08 P4 register
|
||||
P4D 0x09 P4 directional register
|
||||
P5 0x0a P5 register
|
||||
P5D 0x0b P5 directional register
|
||||
P6 0x0c P6 register
|
||||
P6D 0x0d P6 directional register
|
||||
T12XCSS 0x0e Timer 12, X count source selection register
|
||||
TYZCSS 0x0f Timer Y, Z count source selection register
|
||||
MISRG 0x10 MISGR
|
||||
S0 0x11 I2C data shift register
|
||||
S3 0x12 I2C special mode status register
|
||||
S1 0x13 I2C status register
|
||||
S1D 0x14 I2C control register
|
||||
S2 0x15 I2C clock control register
|
||||
S2D 0x16 I2C START/STOP condition control register
|
||||
S3D 0x17 I2C special mode control register
|
||||
TB1_RB1 0x18 Transmit/Receive buffer register 1
|
||||
SIO1STS 0x19 Serial I/O1 status register
|
||||
SIO1CON 0x1a Serial I/O1 control register
|
||||
UART1CON 0x1b UART1 control register
|
||||
BRG1 0x1c Baud rate generator
|
||||
SIO2CON 0x1d Serial I/O2 control register
|
||||
WDTCON 0x1e Watchdog timer control register
|
||||
SIO2 0x1f Serial I/O2 register
|
||||
PRE12 0x20 Prescaler 12
|
||||
T1 0x21 Timer 1
|
||||
T2 0x22 Timer 2
|
||||
TM 0x23 Timer XY mode register
|
||||
PREX 0x24 Prescaler X
|
||||
TX 0x25 Timer X
|
||||
PREY 0x26 Prescaler Y
|
||||
TY 0x27 Timer Y
|
||||
TZL 0x28 Timer Z low-order
|
||||
TZH 0x29 Timer Z high-order
|
||||
TZM 0x2a Timer Z mode register
|
||||
PWMCON 0x2b PWM control register
|
||||
PREPWM 0x2c PWM prescaler
|
||||
PWM 0x2d PWM register
|
||||
|
||||
BRG3 0x2f Baud rate generator 3
|
||||
TB3_RB3 0x30 Transmit/Receive buffer register 3
|
||||
SIO3STS 0x31 Serial I/O3 status register
|
||||
SIO3CON 0x32 Serial I/O3 control register
|
||||
UART3CON 0x33 UART3 control register
|
||||
ADCON 0x34 AD/DA control register
|
||||
AD1 0x35 AD conversion register 1
|
||||
DA1 0x36 DA1 conversion register
|
||||
DA2 0x37 DA2 conversion register
|
||||
AD2 0x38 AD conversion register 2
|
||||
INTSEL 0x39 Interrupt source selection register
|
||||
INTEDGE 0x3a Interrupt edge selection register
|
||||
CPUM 0x3b CPU mode register
|
||||
IREQ1 0x3c Interrupt request register 1
|
||||
IREQ2 0x3d Interrupt request register 2
|
||||
ICON1 0x3e Interrupt control register 1
|
||||
ICON2 0x3f Interrupt control register 2
|
||||
86
idasdk75/module/m740/m740.hpp
Normal file
86
idasdk75/module/m740/m740.hpp
Normal file
@@ -0,0 +1,86 @@
|
||||
|
||||
#ifndef __M740_HPP
|
||||
#define __M740_HPP
|
||||
|
||||
#include "../idaidp.hpp"
|
||||
#include "ins.hpp"
|
||||
#include <diskio.hpp>
|
||||
#include <frame.hpp>
|
||||
#include "../iohandler.hpp"
|
||||
|
||||
// flags for insn.auxpref
|
||||
#define INSN_DISPL_INDX 0x00000001 // indirect X
|
||||
#define INSN_DISPL_INDY 0x00000002 // indirect Y
|
||||
#define INSN_DISPL_ZPX 0x00000004 // zero page X
|
||||
#define INSN_DISPL_ZPY 0x00000008 // zero page Y
|
||||
#define INSN_DISPL_ABSX 0x00000010 // absolute X
|
||||
#define INSN_DISPL_ABSY 0x00000020 // absolute Y
|
||||
|
||||
inline bool is_displ_indx(const insn_t &insn) { return (insn.auxpref & INSN_DISPL_INDX) != 0; }
|
||||
inline bool is_displ_indy(const insn_t &insn) { return (insn.auxpref & INSN_DISPL_INDY) != 0; }
|
||||
inline bool is_displ_zpx(const insn_t &insn) { return (insn.auxpref & INSN_DISPL_ZPX) != 0; }
|
||||
inline bool is_displ_zpy(const insn_t &insn) { return (insn.auxpref & INSN_DISPL_ZPY) != 0; }
|
||||
inline bool is_displ_absx(const insn_t &insn) { return (insn.auxpref & INSN_DISPL_ABSX) != 0; }
|
||||
inline bool is_displ_absy(const insn_t &insn) { return (insn.auxpref & INSN_DISPL_ABSY) != 0; }
|
||||
|
||||
// flags for insn.Op[n].specflag1
|
||||
#define OP_ADDR_SP 0x00000001 // special page
|
||||
#define OP_ADDR_IND 0x00000002 // indirect address
|
||||
#define OP_ADDR_R 0x00000010 // read access
|
||||
#define OP_ADDR_W 0x00000020 // write access
|
||||
#define OP_IMM_BIT 0x00000004 // immediate bit index
|
||||
|
||||
inline bool is_addr_sp(const op_t &op) { return (op.specflag1 & OP_ADDR_SP) != 0; }
|
||||
inline bool is_addr_ind(const op_t &op) { return (op.specflag1 & OP_ADDR_IND) != 0; }
|
||||
inline bool is_addr_read(const op_t &op) { return (op.specflag1 & OP_ADDR_R) != 0; }
|
||||
inline bool is_addr_write(const op_t &op) { return (op.specflag1 & OP_ADDR_W) != 0; }
|
||||
|
||||
// flags for ash.uflag
|
||||
#define UAS_SEGM 0x0001 // segments are named "segment XXX"
|
||||
#define UAS_RSEG 0x0002 // segments are named "rseg XXX"
|
||||
#define UAS_INDX_NOSPACE 0x0004 // no spaces between operands in indirect X addressing mode
|
||||
|
||||
// 740 registers
|
||||
enum m740_registers
|
||||
{
|
||||
rA, // accumulator
|
||||
rX, // index register X
|
||||
rY, // index register Y
|
||||
rS, // stack pointer
|
||||
rPS, // processor status register
|
||||
rVcs, rVds // these 2 registers are required by the IDA kernel
|
||||
};
|
||||
|
||||
// 740 phrases
|
||||
enum m740_phrases {};
|
||||
|
||||
// exporting our routines
|
||||
void idaapi m740_header(outctx_t &ctx);
|
||||
int idaapi ana(insn_t *_insn);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
DECLARE_PROC_LISTENER(idb_listener_t, struct m740_t);
|
||||
|
||||
struct m740_t : public procmod_t
|
||||
{
|
||||
netnode helper;
|
||||
iohandler_t ioh = iohandler_t(helper);
|
||||
idb_listener_t idb_listener = idb_listener_t(*this);
|
||||
bool flow = false;
|
||||
|
||||
virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override;
|
||||
|
||||
const char *set_idp_options(
|
||||
const char *keyword,
|
||||
int /*value_type*/,
|
||||
const void * /*value*/,
|
||||
bool /*idb_loaded*/);
|
||||
|
||||
void handle_operand(const insn_t &insn, const op_t &op);
|
||||
int emu(const insn_t &insn);
|
||||
|
||||
void m740_header(outctx_t &ctx);
|
||||
void m740_footer(outctx_t &ctx) const;
|
||||
void m740_segstart(outctx_t &ctx, segment_t *Sarea) const;
|
||||
};
|
||||
#endif /* __M740_HPP */
|
||||
46
idasdk75/module/m740/makefile
Normal file
46
idasdk75/module/m740/makefile
Normal file
@@ -0,0 +1,46 @@
|
||||
PROC=m740
|
||||
CONFIGS=m740.cfg
|
||||
|
||||
include ../module.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \
|
||||
$(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \
|
||||
$(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 \
|
||||
../iohandler.hpp ana.cpp ins.hpp m740.hpp
|
||||
$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \
|
||||
$(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \
|
||||
$(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 \
|
||||
../iohandler.hpp emu.cpp ins.hpp m740.hpp
|
||||
$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \
|
||||
$(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \
|
||||
$(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 \
|
||||
../iohandler.hpp ins.cpp ins.hpp m740.hpp
|
||||
$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \
|
||||
$(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \
|
||||
$(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 \
|
||||
../iohandler.hpp ins.hpp m740.hpp out.cpp
|
||||
$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \
|
||||
$(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \
|
||||
$(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 \
|
||||
../iohandler.hpp ins.hpp m740.hpp reg.cpp
|
||||
203
idasdk75/module/m740/out.cpp
Normal file
203
idasdk75/module/m740/out.cpp
Normal file
@@ -0,0 +1,203 @@
|
||||
|
||||
#include "m740.hpp"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
class out_m740_t : public outctx_t
|
||||
{
|
||||
out_m740_t(void) = delete; // not used
|
||||
public:
|
||||
void outreg(const int n) { out_register(ph.reg_names[n]); }
|
||||
void outaddr(const op_t &op, bool replace_with_label = true);
|
||||
void outdispl(void);
|
||||
|
||||
bool out_operand(const op_t &x);
|
||||
void out_insn(void);
|
||||
};
|
||||
CASSERT(sizeof(out_m740_t) == sizeof(outctx_t));
|
||||
|
||||
DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_m740_t)
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// output an address
|
||||
void out_m740_t::outaddr(const op_t &op, bool replace_with_label)
|
||||
{
|
||||
bool ind = is_addr_ind(op); // is operand indirect ?
|
||||
bool sp = is_addr_sp(op); // is operand special page ?
|
||||
|
||||
int size = 16; // operand is 16 bits long
|
||||
|
||||
if ( ind )
|
||||
out_symbol('(');
|
||||
if ( sp )
|
||||
{
|
||||
out_symbol('\\');
|
||||
size = 8; /* just display the first 8 bits */
|
||||
}
|
||||
|
||||
if ( !replace_with_label
|
||||
|| !out_name_expr(op, to_ea(insn.cs, op.addr), op.addr) )
|
||||
{
|
||||
if ( replace_with_label )
|
||||
out_tagon(COLOR_ERROR);
|
||||
out_value(op, OOF_ADDR | OOFS_NOSIGN | (size < 16 ? OOFW_8 : OOFW_16));
|
||||
if ( replace_with_label )
|
||||
out_tagoff(COLOR_ERROR);
|
||||
}
|
||||
|
||||
if ( ind )
|
||||
out_symbol(')');
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// output a displacement
|
||||
void out_m740_t::outdispl(void)
|
||||
{
|
||||
if ( is_displ_indx(insn) )
|
||||
{
|
||||
out_symbol('(');
|
||||
outaddr(insn.Op1, false);
|
||||
out_symbol(',');
|
||||
if ( !(ash.uflag & UAS_INDX_NOSPACE) )
|
||||
out_char(' ');
|
||||
outreg(insn.Op1.reg);
|
||||
out_symbol(')');
|
||||
return;
|
||||
}
|
||||
if ( is_displ_indy(insn) )
|
||||
{
|
||||
out_symbol('(');
|
||||
outaddr(insn.Op1, false);
|
||||
out_symbol(')');
|
||||
out_symbol(',');
|
||||
out_char(' ');
|
||||
outreg(insn.Op1.reg);
|
||||
return;
|
||||
}
|
||||
if ( is_displ_zpx(insn) || is_displ_zpy(insn) || is_displ_absx(insn) || is_displ_absy(insn) )
|
||||
{
|
||||
outaddr(insn.Op1, false);
|
||||
out_symbol(',');
|
||||
out_char(' ');
|
||||
outreg(insn.Op1.reg);
|
||||
return;
|
||||
}
|
||||
INTERR(10023);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// generate header
|
||||
void m740_t::m740_header(outctx_t &ctx)
|
||||
{
|
||||
ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX, NULL, ioh.device.c_str());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// generate footer
|
||||
void m740_t::m740_footer(outctx_t &ctx) const
|
||||
{
|
||||
if ( ash.end != NULL )
|
||||
{
|
||||
ctx.gen_empty_line();
|
||||
ctx.out_line(ash.end, COLOR_ASMDIR);
|
||||
qstring name;
|
||||
if ( get_colored_name(&name, inf_get_start_ea()) > 0 )
|
||||
{
|
||||
ctx.out_char(' ');
|
||||
ctx.out_line(name.begin());
|
||||
}
|
||||
ctx.flush_outbuf(DEFAULT_INDENT);
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.gen_cmt_line("end of file");
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// output an operand
|
||||
bool out_m740_t::out_operand(const op_t &op)
|
||||
{
|
||||
switch ( op.type )
|
||||
{
|
||||
// register
|
||||
case o_reg:
|
||||
outreg(op.reg);
|
||||
break;
|
||||
|
||||
// immediate
|
||||
case o_imm:
|
||||
if ( (op.specflag1 & OP_IMM_BIT) == 0 )
|
||||
out_symbol('#');
|
||||
out_value(op, OOFW_IMM);
|
||||
break;
|
||||
|
||||
// data / code memory address
|
||||
case o_near:
|
||||
case o_mem:
|
||||
outaddr(op);
|
||||
break;
|
||||
|
||||
// displ
|
||||
case o_displ:
|
||||
outdispl();
|
||||
break;
|
||||
|
||||
// ignore void operands
|
||||
case o_void:
|
||||
break;
|
||||
|
||||
default:
|
||||
INTERR(10024);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// outputs an instruction
|
||||
void out_m740_t::out_insn(void)
|
||||
{
|
||||
out_mnemonic();
|
||||
out_one_operand(0); // output the first operand
|
||||
|
||||
if ( insn.Op2.type != o_void )
|
||||
{
|
||||
out_symbol(',');
|
||||
out_char(' ');
|
||||
out_one_operand(1);
|
||||
}
|
||||
|
||||
if ( insn.Op3.type != o_void )
|
||||
{
|
||||
out_symbol(',');
|
||||
out_char(' ');
|
||||
out_one_operand(2);
|
||||
}
|
||||
|
||||
// output a character representation of the immediate values
|
||||
// embedded in the instruction as comments
|
||||
out_immchar_cmts();
|
||||
flush_outbuf();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// generate segment header
|
||||
//lint -esym(1764, ctx) could be made const
|
||||
//lint -esym(818, Sarea) could be made const
|
||||
void m740_t::m740_segstart(outctx_t &ctx, segment_t *Sarea) const
|
||||
{
|
||||
qstring sname;
|
||||
get_visible_segm_name(&sname, Sarea);
|
||||
|
||||
if ( ash.uflag & UAS_SEGM )
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR("SEGMENT %s", SCOLOR_ASMDIR), sname.c_str());
|
||||
else if ( ash.uflag & UAS_RSEG )
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR("RSEG %s", SCOLOR_ASMDIR), sname.c_str());
|
||||
|
||||
ea_t orgbase = ctx.insn_ea - get_segm_para(Sarea);
|
||||
if ( orgbase != 0 )
|
||||
{
|
||||
char buf[MAX_NUMBUF];
|
||||
btoa(buf, sizeof(buf), orgbase);
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf);
|
||||
}
|
||||
}
|
||||
343
idasdk75/module/m740/reg.cpp
Normal file
343
idasdk75/module/m740/reg.cpp
Normal file
@@ -0,0 +1,343 @@
|
||||
|
||||
#include "m740.hpp"
|
||||
|
||||
// 740 registers names
|
||||
static const char *const RegNames[] =
|
||||
{
|
||||
"A", // accumulator
|
||||
"X", // index register X
|
||||
"Y", // index register Y
|
||||
"S", // stack pointer
|
||||
"PS", // processor status register
|
||||
"cs", "ds" // these 2 registers are required by the IDA kernel
|
||||
};
|
||||
|
||||
const char *m740_t::set_idp_options(
|
||||
const char *keyword,
|
||||
int /*value_type*/,
|
||||
const void * /*value*/,
|
||||
bool /*idb_loaded*/)
|
||||
{
|
||||
if ( keyword != NULL )
|
||||
return IDPOPT_BADKEY;
|
||||
|
||||
char cfgfile[QMAXFILE];
|
||||
ioh.get_cfg_filename(cfgfile, sizeof(cfgfile));
|
||||
if ( !choose_ioport_device(&ioh.device, cfgfile) )
|
||||
{
|
||||
if ( ioh.device == NONEPROC )
|
||||
warning("No devices are defined in the configuration file %s", cfgfile);
|
||||
}
|
||||
else
|
||||
{
|
||||
ioh.set_device_name(ioh.device.c_str(), IORESP_ALL);
|
||||
}
|
||||
return IDPOPT_OK;
|
||||
}
|
||||
|
||||
ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list)
|
||||
{
|
||||
switch ( code )
|
||||
{
|
||||
case idb_event::savebase:
|
||||
case idb_event::closebase:
|
||||
pm.helper.supset(-1, pm.ioh.device.c_str());
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// 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 m740_t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t idaapi m740_t::on_event(ssize_t msgid, va_list va)
|
||||
{
|
||||
int code = 0;
|
||||
switch ( msgid )
|
||||
{
|
||||
case processor_t::ev_init:
|
||||
hook_event_listener(HT_IDB, &idb_listener, &LPH);
|
||||
helper.create("$ m740");
|
||||
break;
|
||||
|
||||
case processor_t::ev_term:
|
||||
ioh.ports.clear();
|
||||
unhook_event_listener(HT_IDB, &idb_listener);
|
||||
break;
|
||||
|
||||
case processor_t::ev_newfile:
|
||||
set_idp_options(NULL, 0, NULL, true);
|
||||
break;
|
||||
|
||||
case processor_t::ev_ending_undo:
|
||||
case processor_t::ev_oldfile:
|
||||
ioh.restore_device();
|
||||
break;
|
||||
|
||||
case processor_t::ev_out_header:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
m740_header(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_footer:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
m740_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 *);
|
||||
m740_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;
|
||||
}
|
||||
|
||||
case processor_t::ev_set_idp_options:
|
||||
{
|
||||
const char *keyword = va_arg(va, const char *);
|
||||
int value_type = va_arg(va, int);
|
||||
const char *value = va_arg(va, const char *);
|
||||
const char **errmsg = va_arg(va, const char **);
|
||||
bool idb_loaded = va_argi(va, bool);
|
||||
const char *ret = set_idp_options(keyword, value_type, value, idb_loaded);
|
||||
if ( ret == IDPOPT_OK )
|
||||
return 1;
|
||||
if ( errmsg != NULL )
|
||||
*errmsg = ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static const asm_t as_asm =
|
||||
{
|
||||
AS_COLON
|
||||
|ASH_HEXF4 // hex $123 format
|
||||
|ASB_BINF3 // bin 0b010 format
|
||||
|ASO_OCTF5 // oct 123q format
|
||||
|AS_1TEXT, // 1 text per line, no bytes
|
||||
UAS_SEGM|UAS_INDX_NOSPACE,
|
||||
"Alfred Arnold's Macro Assembler",
|
||||
0,
|
||||
NULL, // no headers
|
||||
"ORG", // origin directive
|
||||
"END", // end directive
|
||||
";", // comment string
|
||||
'"', // string delimiter
|
||||
'\'', // char delimiter
|
||||
"\\\"'", // special symbols in char and string constants
|
||||
|
||||
"BYT", // ascii string directive
|
||||
"BYT", // byte directive (alias: DB)
|
||||
NULL, // word directive (alias: DW)
|
||||
NULL, // dword (4 bytes, alias: DD)
|
||||
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(...)
|
||||
"dfs %s", // uninited arrays
|
||||
"equ", // Equ
|
||||
NULL, // seg prefix
|
||||
"$", // current IP (instruction pointer) symbol in assembler
|
||||
NULL, // func_header
|
||||
NULL, // func_footer
|
||||
NULL, // public
|
||||
NULL, // weak
|
||||
NULL, // extrn
|
||||
NULL, // comm
|
||||
NULL, // get_type_name
|
||||
NULL, // align
|
||||
'(', ')', // lbrace, rbrace
|
||||
"%", // mod
|
||||
"&", // and
|
||||
"|", // or
|
||||
"^", // xor
|
||||
"!", // not
|
||||
"<<", // shl
|
||||
">>", // shr
|
||||
NULL, // sizeof
|
||||
0, // flag2 ???
|
||||
NULL, // comment close string
|
||||
NULL, // low8 op
|
||||
NULL, // high8 op
|
||||
NULL, // low16 op
|
||||
NULL // high16 op
|
||||
};
|
||||
|
||||
static const asm_t iar_asm =
|
||||
{
|
||||
AS_COLON
|
||||
|ASH_HEXF4 // hex $123 format
|
||||
|ASB_BINF3 // bin 0b010 format
|
||||
|ASO_OCTF5 // oct 123q format
|
||||
|AS_1TEXT, // 1 text per line, no bytes
|
||||
UAS_RSEG,
|
||||
"IAR 740 Assembler",
|
||||
0,
|
||||
NULL, // no headers
|
||||
"ORG", // origin directive
|
||||
"END", // end directive
|
||||
";", // comment string
|
||||
'"', // string delimiter
|
||||
'\'', // char delimiter
|
||||
"\\\"'", // special symbols in char and string constants
|
||||
|
||||
"BYTE", // ascii string directive
|
||||
"BYTE", // byte directive (alias: DB)
|
||||
"WORD", // word directive (alias: DW)
|
||||
"DWORD", // dword (4 bytes, alias: DD)
|
||||
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(...)
|
||||
"BLKB %s", // uninited arrays
|
||||
"EQU", // Equ
|
||||
NULL, // seg prefix
|
||||
"$", // current IP (instruction pointer) symbol in assembler
|
||||
NULL, // func_header
|
||||
NULL, // func_footer
|
||||
"PUBLIC", // public
|
||||
NULL, // weak
|
||||
NULL, // extrn
|
||||
NULL, // comm
|
||||
NULL, // get_type_name
|
||||
NULL, // align
|
||||
'(', ')', // lbrace, rbrace
|
||||
"%", // mod
|
||||
"&", // and
|
||||
"|", // or
|
||||
"^", // xor
|
||||
"!", // not
|
||||
"<<", // shl
|
||||
">>", // shr
|
||||
"SIZEOF", // sizeof
|
||||
0, // flag2 ???
|
||||
NULL, // comment close string
|
||||
NULL, // low8 op
|
||||
NULL, // high8 op
|
||||
NULL, // low16 op
|
||||
NULL // high16 op
|
||||
};
|
||||
|
||||
// Supported assemblers
|
||||
static const asm_t *const asms[] = { &as_asm, &iar_asm, NULL };
|
||||
|
||||
// Short and long name for our module
|
||||
#define FAMILY "Mitsubishi 8-BIT 740 family:" // MELPS 740, Renesas 740
|
||||
|
||||
static const char *const shnames[] =
|
||||
{
|
||||
"m740",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *const lnames[] =
|
||||
{
|
||||
FAMILY "Mitsubishi 8-BIT 740 family",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const uchar retcode_1[] = { 0x40 }; // rti
|
||||
static const uchar retcode_2[] = { 0x60 }; // rts
|
||||
|
||||
static const bytes_t retcodes[] =
|
||||
{
|
||||
{ sizeof(retcode_1), retcode_1 },
|
||||
{ sizeof(retcode_2), retcode_2 },
|
||||
{ 0, NULL } // NULL terminated array
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Processor Definition
|
||||
//-----------------------------------------------------------------------
|
||||
processor_t LPH =
|
||||
{
|
||||
IDP_INTERFACE_VERSION, // version
|
||||
PLFM_M740, // id
|
||||
// flag
|
||||
PR_RNAMESOK // can use register names for byte names
|
||||
| PR_BINMEM, // The module creates RAM/ROM segments for binary files
|
||||
// (the kernel shouldn't ask the user about their sizes and addresses)
|
||||
// flag2
|
||||
PR2_IDP_OPTS, // the module has processor-specific configuration options
|
||||
8, // 8 bits in a byte for code segments
|
||||
8, // 8 bits in a byte for other segments
|
||||
|
||||
shnames, // array of short processor names
|
||||
// the short names are used to specify the processor
|
||||
// with the -p command line switch)
|
||||
lnames, // array of long processor names
|
||||
// the long names are used to build the processor type
|
||||
// selection menu
|
||||
|
||||
asms, // array of target assemblers
|
||||
|
||||
notify, // the kernel event notification callback
|
||||
|
||||
RegNames, // Regsiter names
|
||||
qnumber(RegNames), // Number of registers
|
||||
|
||||
rVcs,rVds,
|
||||
0, // size of a segment register
|
||||
rVcs,rVds,
|
||||
|
||||
NULL, // No known code start sequences
|
||||
retcodes,
|
||||
|
||||
0, m740_last,
|
||||
Instructions, // instruc
|
||||
0, // int tbyte_size; -- doesn't exist
|
||||
{ 0, 7, 15, 0 }, // char real_width[4];
|
||||
// number of symbols after decimal point
|
||||
// 2byte float (0-does not exist)
|
||||
// normal float
|
||||
// normal double
|
||||
// long double
|
||||
m740_rts, // Icode of return instruction. It is ok to give any of possible return instructions
|
||||
};
|
||||
Reference in New Issue
Block a user