This commit is contained in:
olari
2021-06-05 21:10:25 +03:00
parent 807cffd9de
commit e0e0f2be99
923 changed files with 911857 additions and 15 deletions

View 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;
}

View 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;
}

View 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);

View 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 */

View 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

View 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 */

View 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

View 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);
}
}

View 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
};