update to ida 7.6, add builds

This commit is contained in:
2021-10-31 21:20:46 +02:00
parent e0e0f2be99
commit b1809fe2d9
1408 changed files with 279193 additions and 302468 deletions

795
idasdk76/module/fr/ana.cpp Normal file
View File

@@ -0,0 +1,795 @@
#include "fr.hpp"
// distinct sizes :
//lint -esym(749, S_11) not referenced
enum
{
S_0,
S_4, // 4 bits
S_5, // 5 bits
S_8, // 8 bits
S_11, // 11 bits
S_12, // 12 bits
S_16 // 16 bits
};
// bits numbers for sizes :
const int bits[] =
{
0,
4,
5,
8,
11,
12,
16
};
// masks for sizes :
const int masks[] =
{
0x0000,
0x000F,
0x001F,
0x00FF,
0x07FF,
0x0FFF,
0xFFFF
};
const char dtypes[] =
{
0,
dt_byte,
dt_byte,
dt_byte,
dt_word,
dt_word,
dt_word
};
// distinct operands :
enum
{
O_null, // null opcode
O_gr, // general register Ri
O_gri, // general register indirect @Ri
O_grip, // general register indirect post-increment @Ri+
O_r13_gr_i, // indirect r13 + general register @(R13, Ri)
O_r14_imm8_i, // indirect r14 + 8 bits immediate value @(R14, imm)
O_r15_imm4_i, // indirect r15 + 4 bits immediate value @(R15, imm)
O_r15ip, // indirect r15 post-increment @R15+
O_r15im, // indirect r15 pre-decrement @-R15
O_r13, // register r13 R13
O_r13ip, // indirect r13 post-increment @R13+
O_dr, // dedicated register Rs
O_ps, // program status register (PS) PS
O_imm, // immediate value #i
O_diri, // indirect direct value @i
O_rel, // relative value label5
O_reglist // register list (R0, R1, R2, ...)
};
static int invert_word(int word)
{
int new_word = 0;
new_word |= (word & 0x000F) >> 0;
new_word <<= 4;
new_word |= (word & 0x00F0) >> 4;
new_word <<= 4;
new_word |= (word & 0x0F00) >> 8;
new_word <<= 4;
new_word |= (word & 0xF000) >> 12;
return new_word;
}
// structure of an opcode :
struct opcode_t
{
int itype;
int opcode;
int opcode_size;
int op1;
int op1_size;
int op2;
int op2_size;
#define I_SWAPOPS 0x00000100 // swap operands
#define I_DSHOT 0x00000200 // delay shot
#define I_ADDR_R OP_ADDR_R
#define I_ADDR_W OP_ADDR_W
#define I_IMM_2 0x00001000 // imm = imm * 2
#define I_IMM_4 0x00002000 // imm = imm * 4
int flags;
inline bool swap_ops(void) const { return (flags & I_SWAPOPS) != 0; }
inline bool delay_shot(void) const { return (flags & I_DSHOT) != 0; }
inline bool implied(void) const { return op1 == O_null && op2 == O_null; }
int size(void) const
{
int n = bits[opcode_size];
if ( op1 != O_null )
n += bits[op1_size];
if ( op2 != O_null )
n += bits[op2_size];
return n;
}
static void check(void);
static const struct opcode_t *find(insn_t &insn, int *_data);
};
// FR opcodes :
static const struct opcode_t opcodes[] =
{
{ fr_add, 0xA6, S_8, O_gr, S_4, O_gr, S_4, 0 },
{ fr_add, 0xA4, S_8, O_imm, S_4, O_gr, S_4, 0 },
{ fr_add2, 0xA5, S_8, O_imm, S_4, O_gr, S_4, 0 },
{ fr_addc, 0xA7, S_8, O_gr, S_4, O_gr, S_4, 0 },
{ fr_addn, 0xA2, S_8, O_gr, S_4, O_gr, S_4, 0 },
{ fr_addn, 0xA0, S_8, O_imm, S_4, O_gr, S_4, 0 },
{ fr_addn2, 0xA1, S_8, O_imm, S_4, O_gr, S_4, 0 },
{ fr_sub, 0xAC, S_8, O_gr, S_4, O_gr, S_4, 0 },
{ fr_subc, 0xAD, S_8, O_gr, S_4, O_gr, S_4, 0 },
{ fr_subn, 0xAE, S_8, O_gr, S_4, O_gr, S_4, 0 },
{ fr_cmp, 0xAA, S_8, O_gr, S_4, O_gr, S_4, 0 },
{ fr_cmp, 0xA8, S_8, O_imm, S_4, O_gr, S_4, 0 },
{ fr_cmp2, 0xA9, S_8, O_imm, S_4, O_gr, S_4, 0 },
{ fr_and, 0x82, S_8, O_gr, S_4, O_gr, S_4, 0 },
{ fr_and, 0x84, S_8, O_gr, S_4, O_gri, S_4, 0 },
{ fr_andh, 0x85, S_8, O_gr, S_4, O_gri, S_4, 0 },
{ fr_andb, 0x86, S_8, O_gr, S_4, O_gri, S_4, 0 },
{ fr_or, 0x92, S_8, O_gr, S_4, O_gr, S_4, 0 },
{ fr_or, 0x94, S_8, O_gr, S_4, O_gri, S_4, 0 },
{ fr_orh, 0x95, S_8, O_gr, S_4, O_gri, S_4, 0 },
{ fr_orb, 0x96, S_8, O_gr, S_4, O_gri, S_4, 0 },
{ fr_eor, 0x9A, S_8, O_gr, S_4, O_gr, S_4, 0 },
{ fr_eor, 0x9C, S_8, O_gr, S_4, O_gri, S_4, 0 },
{ fr_eorh, 0x9D, S_8, O_gr, S_4, O_gri, S_4, 0 },
{ fr_eorb, 0x9E, S_8, O_gr, S_4, O_gri, S_4, 0 },
{ fr_bandl, 0x80, S_8, O_imm, S_4, O_gri, S_4, 0 },
{ fr_bandh, 0x81, S_8, O_imm, S_4, O_gri, S_4, 0 },
{ fr_borl, 0x90, S_8, O_imm, S_4, O_gri, S_4, 0 },
{ fr_borh, 0x91, S_8, O_imm, S_4, O_gri, S_4, 0 },
{ fr_beorl, 0x98, S_8, O_imm, S_4, O_gri, S_4, 0 },
{ fr_beorh, 0x99, S_8, O_imm, S_4, O_gri, S_4, 0 },
{ fr_btstl, 0x88, S_8, O_imm, S_4, O_gri, S_4, 0 },
{ fr_btsth, 0x89, S_8, O_imm, S_4, O_gri, S_4, 0 },
{ fr_mul, 0xAF, S_8, O_gr, S_4, O_gr, S_4, 0 },
{ fr_mulu, 0xAB, S_8, O_gr, S_4, O_gr, S_4, 0 },
{ fr_mulh, 0xBF, S_8, O_gr, S_4, O_gr, S_4, 0 },
{ fr_muluh, 0xBB, S_8, O_gr, S_4, O_gr, S_4, 0 },
{ fr_div0s, 0x974, S_12, O_gr, S_4, O_null, 0, 0 },
{ fr_div0u, 0x975, S_12, O_gr, S_4, O_null, 0, 0 },
{ fr_div1, 0x976, S_12, O_gr, S_4, O_null, 0, 0 },
{ fr_div2, 0x977, S_12, O_gr, S_4, O_null, 0, 0 },
{ fr_div3, 0x9F60, S_16, O_null, 0, O_null, 0, 0 },
{ fr_div4s, 0x9F70, S_16, O_null, 0, O_null, 0, 0 },
{ fr_lsl, 0xB6, S_8, O_gr, S_4, O_gr, S_4, 0 },
{ fr_lsl, 0xB4, S_8, O_imm, S_4, O_gr, S_4, 0 },
{ fr_lsl2, 0xB5, S_8, O_imm, S_4, O_gr, S_4, 0 },
{ fr_lsr, 0xB2, S_8, O_gr, S_4, O_gr, S_4, 0 },
{ fr_lsr, 0xB0, S_8, O_imm, S_4, O_gr, S_4, 0 },
{ fr_lsr2, 0xB1, S_8, O_imm, S_4, O_gr, S_4, 0 },
{ fr_asr, 0xBA, S_8, O_gr, S_4, O_gr, S_4, 0 },
{ fr_asr, 0xB8, S_8, O_imm, S_4, O_gr, S_4, 0 },
{ fr_asr2, 0xB9, S_8, O_imm, S_4, O_gr, S_4, 0 },
// fr_ldi_32 not here (considered as special)
// fr_ldi_20 not here (considered as special)
{ fr_ldi_8, 0x0C, S_4, O_imm, S_8, O_gr, S_4, 0 },
{ fr_ld, 0x04, S_8, O_gri, S_4, O_gr, S_4, 0 },
{ fr_ld, 0x00, S_8, O_r13_gr_i, S_4, O_gr, S_4, 0 },
{ fr_ld, 0x02, S_4, O_r14_imm8_i, S_8, O_gr, S_4, I_IMM_4 },
{ fr_ld, 0x03, S_8, O_r15_imm4_i, S_4, O_gr, S_4, I_IMM_4 },
{ fr_ld, 0x70, S_12, O_r15ip, S_0, O_gr, S_4, 0 },
{ fr_ld, 0x78, S_12, O_r15ip, S_0, O_dr, S_4, 0 },
{ fr_ld, 0x790, S_16, O_r15ip, S_0, O_ps, S_0, 0 },
{ fr_lduh, 0x05, S_8, O_gri, S_4, O_gr, S_4, 0 },
{ fr_lduh, 0x01, S_8, O_r13_gr_i, S_4, O_gr, S_4, 0 },
{ fr_lduh, 0x04, S_4, O_r14_imm8_i, S_8, O_gr, S_4, I_IMM_2 },
{ fr_ldub, 0x06, S_8, O_gri, S_4, O_gr, S_4, 0 },
{ fr_ldub, 0x02, S_8, O_r13_gr_i, S_4, O_gr, S_4, 0 },
{ fr_ldub, 0x06, S_4, O_r14_imm8_i, S_8, O_gr, S_4, 0 },
{ fr_st, 0x14, S_8, O_gri, S_4, O_gr, S_4, I_SWAPOPS },
{ fr_st, 0x10, S_8, O_r13_gr_i, S_4, O_gr, S_4, I_SWAPOPS },
{ fr_st, 0x03, S_4, O_r14_imm8_i, S_8, O_gr, S_4, I_SWAPOPS|I_IMM_4 },
{ fr_st, 0x13, S_8, O_r15_imm4_i, S_4, O_gr, S_4, I_SWAPOPS|I_IMM_4 },
{ fr_st, 0x170, S_12, O_gr, S_4, O_r15im, S_0, 0 },
{ fr_st, 0x178, S_12, O_dr, S_4, O_r15im, S_0, 0 },
{ fr_st, 0x1790, S_16, O_ps, S_0, O_r15im, S_0, 0 },
{ fr_sth, 0x15, S_8, O_gri, S_4, O_gr, S_4, I_SWAPOPS },
{ fr_sth, 0x11, S_8, O_r13_gr_i, S_4, O_gr, S_4, I_SWAPOPS },
{ fr_sth, 0x05, S_4, O_r14_imm8_i, S_8, O_gr, S_4, I_SWAPOPS|I_IMM_2 },
{ fr_stb, 0x16, S_8, O_gri, S_4, O_gr, S_4, I_SWAPOPS },
{ fr_stb, 0x12, S_8, O_r13_gr_i, S_4, O_gr, S_4, I_SWAPOPS },
{ fr_stb, 0x07, S_4, O_r14_imm8_i, S_8, O_gr, S_4, I_SWAPOPS },
{ fr_mov, 0x8B, S_8, O_gr, S_4, O_gr, S_4, 0 },
{ fr_mov, 0xB7, S_8, O_dr, S_4, O_gr, S_4, 0 },
{ fr_mov, 0x171, S_12, O_ps, S_0, O_gr, S_4, 0 },
{ fr_mov, 0xB3, S_8, O_dr, S_4, O_gr, S_4, I_SWAPOPS },
{ fr_mov, 0x71, S_12, O_gr, S_4, O_ps, S_0, 0 },
{ fr_jmp, 0x970, S_12, O_gri, S_4, O_null, 0, 0 },
{ fr_call, 0x971, S_12, O_gri, S_4, O_null, 0, 0 },
{ fr_ret, 0x9720, S_16, O_null, 0, O_null, 0, 0 },
{ fr_int, 0x1F, S_8, O_imm, S_8, O_null, 0, 0 },
{ fr_inte, 0x9F30, S_16, O_null, 0, O_null, 0, 0 },
{ fr_reti, 0x9730, S_16, O_null, 0, O_null, 0, 0 },
{ fr_bra, 0xE0, S_8, O_rel, S_8, O_null, 0, 0 },
{ fr_bno, 0xE1, S_8, O_rel, S_8, O_null, 0, 0 },
{ fr_beq, 0xE2, S_8, O_rel, S_8, O_null, 0, 0 },
{ fr_bne, 0xE3, S_8, O_rel, S_8, O_null, 0, 0 },
{ fr_bc, 0xE4, S_8, O_rel, S_8, O_null, 0, 0 },
{ fr_bnc, 0xE5, S_8, O_rel, S_8, O_null, 0, 0 },
{ fr_bn, 0xE6, S_8, O_rel, S_8, O_null, 0, 0 },
{ fr_bp, 0xE7, S_8, O_rel, S_8, O_null, 0, 0 },
{ fr_bv, 0xE8, S_8, O_rel, S_8, O_null, 0, 0 },
{ fr_bnv, 0xE9, S_8, O_rel, S_8, O_null, 0, 0 },
{ fr_blt, 0xEA, S_8, O_rel, S_8, O_null, 0, 0 },
{ fr_bge, 0xEB, S_8, O_rel, S_8, O_null, 0, 0 },
{ fr_ble, 0xEC, S_8, O_rel, S_8, O_null, 0, 0 },
{ fr_bgt, 0xED, S_8, O_rel, S_8, O_null, 0, 0 },
{ fr_bls, 0xEE, S_8, O_rel, S_8, O_null, 0, 0 },
{ fr_bhi, 0xEF, S_8, O_rel, S_8, O_null, 0, 0 },
{ fr_jmp, 0x9F0, S_12, O_gri, S_4, O_null, 0, I_DSHOT },
{ fr_call, 0x9F1, S_12, O_gri, S_4, O_null, 0, I_DSHOT },
{ fr_ret, 0x9F20, S_16, O_null, 0, O_null, 0, I_DSHOT },
{ fr_bra, 0xF0, S_8, O_rel, S_8, O_null, 0, I_DSHOT },
{ fr_bno, 0xF1, S_8, O_rel, S_8, O_null, 0, I_DSHOT },
{ fr_beq, 0xF2, S_8, O_rel, S_8, O_null, 0, I_DSHOT },
{ fr_bne, 0xF3, S_8, O_rel, S_8, O_null, 0, I_DSHOT },
{ fr_bc, 0xF4, S_8, O_rel, S_8, O_null, 0, I_DSHOT },
{ fr_bnc, 0xF5, S_8, O_rel, S_8, O_null, 0, I_DSHOT },
{ fr_bn, 0xF6, S_8, O_rel, S_8, O_null, 0, I_DSHOT },
{ fr_bp, 0xF7, S_8, O_rel, S_8, O_null, 0, I_DSHOT },
{ fr_bv, 0xF8, S_8, O_rel, S_8, O_null, 0, I_DSHOT },
{ fr_bnv, 0xF9, S_8, O_rel, S_8, O_null, 0, I_DSHOT },
{ fr_blt, 0xFA, S_8, O_rel, S_8, O_null, 0, I_DSHOT },
{ fr_bge, 0xFB, S_8, O_rel, S_8, O_null, 0, I_DSHOT },
{ fr_ble, 0xFC, S_8, O_rel, S_8, O_null, 0, I_DSHOT },
{ fr_bgt, 0xFD, S_8, O_rel, S_8, O_null, 0, I_DSHOT },
{ fr_bls, 0xFE, S_8, O_rel, S_8, O_null, 0, I_DSHOT },
{ fr_bhi, 0xFF, S_8, O_rel, S_8, O_null, 0, I_DSHOT },
{ fr_dmov, 0x08, S_8, O_diri, S_8, O_r13, S_0, I_ADDR_R },
{ fr_dmov, 0x18, S_8, O_r13, S_0, O_diri, S_8, I_ADDR_W },
{ fr_dmov, 0x0C, S_8, O_diri, S_8, O_r13ip, S_0, I_ADDR_R },
{ fr_dmov, 0x1C, S_8, O_r13ip, S_0, O_diri, S_8, I_ADDR_W },
{ fr_dmov, 0x0B, S_8, O_diri, S_8, O_r15im, S_0, I_ADDR_R },
{ fr_dmov, 0x1B, S_8, O_r15ip, S_0, O_diri, S_8, I_ADDR_W },
{ fr_dmovh, 0x09, S_8, O_diri, S_8, O_r13, S_0, I_ADDR_R },
{ fr_dmovh, 0x19, S_8, O_r13, S_0, O_diri, S_8, I_ADDR_W },
{ fr_dmovh, 0x0D, S_8, O_diri, S_8, O_r13ip, S_0, I_ADDR_R },
{ fr_dmovh, 0x1D, S_8, O_r13ip, S_0, O_diri, S_8, I_ADDR_W },
{ fr_dmovb, 0x0A, S_8, O_diri, S_8, O_r13, S_0, I_ADDR_R },
{ fr_dmovb, 0x1A, S_8, O_r13, S_0, O_diri, S_8, I_ADDR_W },
{ fr_dmovb, 0x0E, S_8, O_diri, S_8, O_r13ip, S_0, I_ADDR_R },
{ fr_dmovb, 0x1E, S_8, O_r13ip, S_0, O_diri, S_8, I_ADDR_W },
{ fr_ldres, 0xBC, S_8, O_imm, S_4, O_grip, S_4, I_SWAPOPS },
{ fr_stres, 0xBD, S_8, O_imm, S_4, O_grip, S_4, 0 },
// fr_copop not here (considered as special)
// fr_copld not here (considered as special)
// fr_copst not here (considered as special)
// fr_copsv not here (considered as special)
{ fr_nop, 0x9FA0, S_16, O_null, 0, O_null, 0, 0 },
{ fr_andccr, 0x83, S_8, O_imm, S_8, O_null, 0, 0 },
{ fr_orccr, 0x93, S_8, O_imm, S_8, O_null, 0, 0 },
{ fr_stilm, 0x87, S_8, O_imm, S_8, O_null, 0, 0 },
{ fr_addsp, 0xA3, S_8, O_imm, S_8, O_null, 0, 0 },
{ fr_extsb, 0x978, S_12, O_gr, S_4, O_null, 0, 0 },
{ fr_extub, 0x979, S_12, O_gr, S_4, O_null, 0, 0 },
{ fr_extsh, 0x97A, S_12, O_gr, S_4, O_null, 0, 0 },
{ fr_extuh, 0x97B, S_12, O_gr, S_4, O_null, 0, 0 },
{ fr_ldm0, 0x8C, S_8, O_reglist, S_8, O_null, 0, 0 },
{ fr_ldm1, 0x8D, S_8, O_reglist, S_8, O_null, 0, 0 },
{ fr_stm0, 0x8E, S_8, O_reglist, S_8, O_null, 0, 0 },
{ fr_stm1, 0x8F, S_8, O_reglist, S_8, O_null, 0, 0 },
{ fr_enter, 0x0F, S_8, O_imm, S_8, O_null, 0, I_IMM_4 },
{ fr_leave, 0x9F90, S_16, O_null, 0, O_null, 0, 0 },
{ fr_xchb, 0x8A, S_8, O_gri, S_4, O_gr, S_4, 0 }
};
void opcode_t::check(void)
{
for ( int i = 0; i < qnumber(opcodes); i++ )
{
int n = opcodes[i].size();
// if ( n != 16 && n != 32 )
// msg("instruction n%d (%d) : size %d\n", i, opcodes[i].insn, n);
QASSERT(10001, n == 16 || n == 32);
}
}
const struct opcode_t * opcode_t::find(insn_t &insn, int *_data)
{
QASSERT(10002, _data != NULL);
int data = (*_data << 8) | get_byte(insn.ip + insn.size);
for ( int i = 0; i < qnumber(opcodes); i++ )
{
int mask;
int shift;
switch ( opcodes[i].opcode_size )
{
case S_4: mask = 0xF000; shift = 12; break;
case S_5: mask = 0xF100; shift = 11; break;
case S_8: mask = 0xFF00; shift = 8; break;
case S_12: mask = 0xFFF0; shift = 4; break;
case S_16: mask = 0xFFFF; shift = 0; break;
default: INTERR(10012);
}
if ( ((data & mask) >> shift) != opcodes[i].opcode )
continue;
insn.size++;
*_data = invert_word(data);
return &opcodes[i];
}
return NULL;
}
// get general register.
static int get_gr(const int num)
{
QASSERT(10003, num >= 0 && num <= 15);
return num;
}
// get coprocessor register.
static int get_cr(const int num)
{
QASSERT(10004, num >= 0 && num <= 15);
return num + 16;
}
// get dedicated register.
static int get_dr(int num)
{
static const int drs[] =
{
rTBR,
rRP,
rSSP,
rUSP,
rMDH,
rMDL,
rReserved6,
rReserved7,
rReserved8,
rReserved9,
rReserved10,
rReserved11,
rReserved12,
rReserved13,
rReserved14,
rReserved15
};
QASSERT(10005, num >= 0 && num <= 15);
return drs[num];
}
// fill an operand as a register.
static void set_reg(op_t &op, int reg, char d_typ)
{
op.type = o_reg;
op.reg = (uint16)reg;
op.dtype = d_typ;
}
// fill an operand as an immediate value.
static void set_imm(op_t &op, int imm, char d_typ)
{
op.type = o_imm;
switch ( d_typ )
{
case dt_byte: op.value = (char) imm; break;
case dt_word: op.value = (short) imm; break;
case dt_dword: op.value = imm; break;
default: INTERR(10013);
}
op.dtype = d_typ;
}
// fill an operand as a phrase.
static void set_phrase(op_t &op, int type, int val, char d_typ)
{
switch ( type )
{
case fIGR: // indirect general register
case fIGRP: // indirect general register with post-increment
case fIGRM: // indirect general register with pre-decrement
case fR13RI: // indirect displacement between R13 and a general register
op.reg = (uint16)val;
break;
case fIRA: // indirect relative address
op.addr = val;
break;
default:
INTERR(10014);
}
op.type = o_phrase;
op.specflag2 = (char)type;
op.dtype = d_typ;
}
// fill an operand as a relative address.
static void set_rel(const insn_t &insn, op_t &op, int addr, char d_typ)
{
op.type = o_near;
int raddr;
switch ( d_typ ) /* ugly but functional */
{
case dt_byte:
raddr = ((signed char) addr);
break;
case dt_word:
raddr = ((signed short) addr);
break;
default:
INTERR(10015);
}
op.addr = insn.ip + 2 + (raddr * 2); //-V614 uninitialized variable 'raddr'
#if defined(__DEBUG__)
msg("0x%a = 0x%a + 2 + ((signed) 0x%X) * 2)\n", op.addr, insn.ip, addr);
#endif /* __DEBUG__ */
op.dtype = dt_code;
}
// fill an operand as a reglist
static void set_reglist(op_t &op, int list)
{
op.type = o_reglist;
op.value = list;
op.dtype = dt_byte; // list is coded in a byte
}
static void set_displ(op_t &op, int reg, int imm, int flag, int local_flag)
{
op.type = o_displ;
if ( reg != -1 )
op.reg = (uint16)get_gr(reg);
if ( imm != -1 )
{
int mul = 1;
if ( local_flag & I_IMM_2 )
mul = 2;
if ( local_flag & I_IMM_4 )
mul = 4;
op.value = ((unsigned) imm) * mul;
}
op.dtype = dt_byte;
op.specflag1 |= flag;
}
// swap 2 opcodes (o1 <=> o2).
static void swap_ops(op_t &o1, op_t &o2)
{
QASSERT(10006, o1.type != o_void && o2.type != o_void);
op_t tmp = o1;
o1 = o2;
o2 = tmp;
}
static void adjust_data(int size, int *data)
{
QASSERT(10007, data != NULL);
int new_data = *data >> bits[size];
*data = new_data;
}
/*
static void prepare_data(int size, int *data) {
QASSERT(10008, data != NULL);
int new_data = 0;
switch ( size ) {
case S_0:
case S_4:
new_data = *data;
break;
case S_5:
case S_8:
new_data |= (*data & 0x00F0) >> 4;
new_data |= (*data & 0x000F) << 4;
break;
case S_11:
case S_12:
new_data |= (*data & 0x0F00) >> 8;
new_data |= (*data & 0x00F0) >> 0;
new_data |= (*data & 0x000F) << 8;
break;
case S_16:
new_data |= (*data & 0xF000) >> 12;
new_data |= (*data & 0x0F00) >> 4;
new_data |= (*data & 0x00F0) << 4;
new_data |= (*data & 0x000F) << 12;
break;
}
*data = new_data;
}*/
#define SWAP_IF_BYTE(data) \
do \
{ \
if ( operand_size == S_8 ) \
{ \
int h = (data & 0x0F) << 4; \
int l = (data & 0xF0) >> 4; \
data = h | l; \
} \
} \
while ( 0 )
//
// defines some shortcuts.
//
#define __set_gr(op, reg) set_reg(op, reg, dt_byte)
#define set_gr(op, reg) __set_gr(op, get_gr(reg))
#define __set_dr(op, reg) set_reg(op, reg, dt_word)
#define set_dr(op, reg) __set_dr(op, get_dr(reg))
#define __set_cr(op, reg) set_reg(op, reg, dt_word)
#define set_cr(op, reg) __set_cr(op, get_cr(reg))
#define set_gri(insn, op, reg) set_phrase(op, fIGR, get_gr(reg), dt_byte)
#define set_grip(insn, op, reg) set_phrase(op, fIGRP, get_gr(reg), dt_byte)
#define set_grim(insn, op, reg) set_phrase(op, fIGRM, get_gr(reg), dt_byte)
#define set_diri(insn, op, addr) set_phrase(op, fIRA, addr, dt_word)
#define set_r13_gr_i(insn, op, reg) set_phrase(op, fR13RI, get_gr(reg), dt_byte)
#define fill_op1(insn, data, opc) fill_op(insn, data, insn.Op1, opc->op1, opc->op1_size, opc->flags)
#define fill_op2(insn, data, opc) fill_op(insn, data, insn.Op2, opc->op2, opc->op2_size, opc->flags)
//#define set_displ_gr(op, gr, f1) set_displ(op, gr, -1, f1, 0)
#define set_displ_imm(op, imm, f1, f2) set_displ(op, -1, imm, f1, f2)
static void fill_op(const insn_t &insn, int data, op_t &op, int operand, int operand_size, int flags)
{
data &= masks[operand_size];
//prepare_data(operand_size, &data);
switch ( operand )
{
case O_gr: // general register Ri
QASSERT(10009, operand_size == S_4);
set_gr(op, data);
break;
case O_gri: // general register indirect @Ri
QASSERT(10010, operand_size == S_4);
set_gri(insn, op, data);
break;
case O_grip: // general register indirect @Ri
QASSERT(10011, operand_size == S_4);
set_grip(insn, op, data);
break;
case O_r13_gr_i: // indirect r13 + general register @(R13, Ri)
set_r13_gr_i(insn, op, data);
break;
case O_r14_imm8_i: // indirect r14 + 8 bits immediate value @(R14, imm)
SWAP_IF_BYTE(data);
set_displ_imm(op, data, OP_DISPL_IMM_R14, flags);
break;
case O_r15_imm4_i: // indirect r15 + 4 bits immediate value @(R15, imm)
SWAP_IF_BYTE(data);
set_displ_imm(op, data, OP_DISPL_IMM_R15, flags);
break;
case O_r15ip: // indirect r15 post-increment @R15+
set_grip(insn, op, rR15);
break;
case O_r15im: // indirect r15 pre-decrement @-R15
set_grim(insn, op, rR15);
break;
case O_r13: // register r13 R13
__set_gr(op, rR13);
break;
case O_r13ip: // indirect r13 post-increment @R13+
set_grip(insn, op, rR13);
break;
case O_dr: // dedicated register Rs
set_dr(op, data);
break;
case O_ps: // program status register (PS) PS
__set_dr(op, rPS);
break;
case O_imm: // immediate value #i
SWAP_IF_BYTE(data);
if ( insn.itype == fr_enter )
data *= 4;
if ( insn.itype == fr_addsp )
data = ((signed) data) * 4;
set_imm(op, data, dtypes[operand_size]);
break;
case O_diri: // indirect direct value @i
SWAP_IF_BYTE(data);
if ( insn.itype == fr_dmov )
data *= 4;
if ( insn.itype == fr_dmovh )
data *= 2;
set_diri(insn, op, data);
op.specflag1 |= flags;
break;
case O_rel: // relative value label5
SWAP_IF_BYTE(data);
set_rel(insn, op, data, dtypes[operand_size]);
break;
case O_reglist: // register list (R0, R1, R2, ...)
SWAP_IF_BYTE(data);
set_reglist(op, data);
break;
case O_null: // null opcode
INTERR(10016);
}
}
// analyze a "common" instruction (those which are listed in the opcodes[] array).
static bool ana_common(insn_t &insn, int data)
{
const struct opcode_t *op = opcode_t::find(insn, &data);
if ( op == NULL )
return false;
// fill instruction type
insn.itype = (uint16)op->itype;
// if instruction is implied, our job is finished!
if ( op->implied() )
goto ana_finished;
adjust_data(op->opcode_size, &data);
// fill operand 1
if ( op->op1 != O_null )
{
fill_op1(insn, data, op);
adjust_data(op->op1_size, &data);
}
// fill operand 2
if ( op->op2 != O_null )
{
fill_op2(insn, data, op);
adjust_data(op->op2_size, &data);
}
// swap opcodes if needed
if ( op->swap_ops() )
swap_ops(insn.Op1, insn.Op2);
ana_finished:
insn.auxpref = 0;
// is insn delay shot ?
if ( op->delay_shot() )
insn.auxpref |= INSN_DELAY_SHOT;
return true;
}
// analyze a "special" instruction (those which are NOT listed in the opcodes[] array).
static bool ana_special(insn_t &insn, int data)
{
// detect ldi:20 instructions
if ( data == 0x9B )
{
insn.itype = fr_ldi_20;
data = (data << 8) | insn.get_next_byte();
set_gr(insn.Op2, data & 0x000F);
set_imm(insn.Op1, insn.get_next_word() | ((data & 0x00F0) << 12), dt_dword);
return true;
}
data = (data << 8) | get_byte(insn.ea + insn.size);
// detect ldi:32 instructions
if ( (data & 0xFFF0) == 0x9F80 )
{
insn.size++;
insn.itype = fr_ldi_32;
set_gr(insn.Op2, data & 0x000F);
set_imm(insn.Op1, insn.get_next_dword(), dt_dword);
return true;
}
// detect call [rel] instructions
int tmp = (data & 0xF800) >> 11;
if ( tmp == 0x1A || tmp == 0x1B )
{
insn.itype = fr_call;
insn.size++;
// extend sign
if ( data & 0x400 )
data |= ~0x07FF;
else
data &= 0x07FF;
set_rel(insn, insn.Op1, data, dt_word);
if ( tmp == 0x1B )
insn.auxpref |= INSN_DELAY_SHOT;
return true;
}
// detect copop/copld/copst/copsv instructions
if ( ((data & 0xFF00) >> 8) == 0x9F )
{
int word = get_word(insn.ea + insn.size + 1);
insn.itype = fr_null;
switch ( (data & 0x00F0) >> 4 )
{
// copop
case 0xC:
insn.itype = fr_copop;
set_cr(insn.Op3, (word & 0x00F0) >> 4);
set_cr(insn.Op4, word & 0x000F);
break;
// copld
case 0xD:
insn.itype = fr_copld;
set_gr(insn.Op3, (word & 0x00F0) >> 4);
set_cr(insn.Op4, word & 0x000F);
break;
// copst
case 0xE:
insn.itype = fr_copst;
set_cr(insn.Op3, (word & 0x00F0) >> 4);
set_gr(insn.Op4, word & 0x000F);
break;
// copsv
case 0xF:
insn.itype = fr_copsv;
set_cr(insn.Op3, (word & 0x00F0) >> 4);
set_gr(insn.Op4, word & 0x000F);
break;
}
if ( insn.itype != fr_null )
{
set_imm(insn.Op1, data & 0x000F, dt_byte);
set_imm(insn.Op2, (word & 0xFF00) >> 8, dt_byte);
insn.size += 3;
return true;
}
}
return false;
}
// analyze an instruction.
int idaapi ana(insn_t *_insn)
{
insn_t &insn = *_insn;
#if defined(__DEBUG__)
opcode_t::check();
#endif /* __DEBUG__ */
int byte = insn.get_next_byte();
bool ok = ana_special(insn, byte);
if ( !ok )
ok = ana_common(insn, byte);
return ok ? insn.size : 0;
}

250
idasdk76/module/fr/emu.cpp Normal file
View File

@@ -0,0 +1,250 @@
#include "fr.hpp"
// Analyze an instruction
static ea_t next_insn(insn_t *insn, ea_t ea)
{
if ( decode_insn(insn, ea) == 0 )
return 0;
ea += insn->size;
return ea;
}
// Emulate an operand.
static void handle_operand(const insn_t &insn, const op_t &op)
{
bool offset = false;
switch ( op.type )
{
case o_near:
insn.add_cref(to_ea(insn.cs, op.addr), op.offb, (insn.itype == fr_call) ? fl_CN : fl_JN);
break;
case o_mem:
{
enum dref_t mode = dr_U;
if ( op.specflag1 & OP_ADDR_R )
mode = dr_R;
else if ( op.specflag1 & OP_ADDR_W )
mode = dr_W;
ea_t ea = to_ea(insn.cs, op.addr);
insn.add_dref(ea, op.offb, mode);
insn.create_op_data(ea, op);
}
break;
case o_imm:
// if current insn is ldi:32 #imm, r1
// and next insn is call @r1,
// replace the immediate value with an offset.
if ( insn.itype == fr_ldi_32
&& insn.Op1.type == o_imm
&& insn.Op2.type == o_reg )
{
const int callreg = insn.Op2.reg;
insn_t nexti;
if ( next_insn(&nexti, insn.ea + insn.size ) > 0
&& nexti.itype == fr_call
&& nexti.Op1.type == o_phrase
&& nexti.Op1.specflag2 == fIGR
&& nexti.Op1.reg == callreg )
{
offset = true;
}
if ( !is_defarg(get_flags(insn.ea), 0) && offset )
op_plain_offset(insn.ea, 0, 0);
}
set_immd(insn.ea);
// if the value was converted to an offset, then create a data xref:
if ( !offset && op_adds_xrefs(get_flags(insn.ea), op.n) )
insn.add_off_drefs(op, dr_O, 0);
// create stack variables if necessary
{
bool ok = false;
// ldi8 #our_value, R1
// extsb R1
// addn R14, R1
if ( insn.itype == fr_ldi_8
&& insn.Op2.type == o_reg
&& insn.Op2.reg == rR1 )
{
insn_t nexti;
next_insn(&nexti, insn.ea + insn.size);
if ( nexti.itype == fr_extsb
&& nexti.Op1.type == o_reg
&& nexti.Op1.reg == rR1 )
{
ok = true;
}
if ( ok )
{
ok = false;
next_insn(&nexti, nexti.ea + insn.size);
if ( nexti.itype == fr_addn
&& nexti.Op1.type == o_reg
&& nexti.Op1.reg == rR14
&& nexti.Op2.type == o_reg
&& nexti.Op2.reg == rR1 )
{
ok = true;
}
}
}
// ldi32 #our_value, Ri
// addn R14, Ri
//
// (where Ri is either R1 or R2)
else if ( insn.itype == fr_ldi_32
&& insn.Op2.type == o_reg
&& (insn.Op2.reg == rR1 || insn.Op2.reg == rR2) )
{
ushort the_reg = insn.Op2.reg;
insn_t nexti;
next_insn(&nexti, insn.ea + insn.size);
if ( nexti.itype == fr_addn
&& nexti.Op1.type == o_reg
&& nexti.Op1.reg == rR14
&& nexti.Op2.type == o_reg
&& nexti.Op2.reg == the_reg )
{
ok = true;
}
}
if ( ok && may_create_stkvars()
&& !is_defarg(get_flags(insn.ea), op.n) )
{
func_t *pfn = get_func(insn.ea);
if ( pfn != NULL && pfn->flags & FUNC_FRAME )
{
if ( insn.create_stkvar(op, op.value, 0) )
op_stkvar(insn.ea, op.n);
}
}
}
break;
case o_displ:
case o_phrase: // XXX
case o_reglist:
case o_void:
case o_reg:
break;
default:
INTERR(10017);
}
}
inline bool fr_t::is_stop(const insn_t &insn) const
{
uint32 feature = insn.get_canon_feature(ph);
return (feature & CF_STOP) != 0;
}
// Emulate an instruction.
int fr_t::emu(const insn_t &insn) const
{
bool flow = !is_stop(insn) || (insn.auxpref & INSN_DELAY_SHOT);
if ( flow )
{
insn_t previ;
if ( decode_prev_insn(&previ, insn.ea) != BADADDR )
flow = !(is_stop(previ) && (previ.auxpref & INSN_DELAY_SHOT));
}
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);
if ( insn.Op4.type != o_void ) handle_operand(insn, insn.Op4);
if ( flow )
add_cref(insn.ea, insn.ea + insn.size, fl_F);
return 1;
}
// Create a function frame
bool idaapi create_func_frame(func_t *pfn)
{
ushort savedreg_size = 0;
uint32 args_size = 0;
uint32 localvar_size;
ea_t ea = pfn->start_ea;
// detect multiple ``st Ri, @-R15'' instructions.
insn_t insn;
while ( (ea=next_insn(&insn, ea)) != 0
&& insn.itype == fr_st
&& insn.Op1.type == o_reg
&& insn.Op2.type == o_phrase
&& insn.Op2.reg == rR15
&& insn.Op2.specflag2 == fIGRM )
{
savedreg_size += 4;
#if defined(__DEBUG__)
msg("0x%a: detected st Rx, @-R15\n", ea);
#endif /* __DEBUG__ */
}
// detect enter #nn
if ( insn.itype == fr_enter )
{
// R14 is automatically pushed by fr_enter
savedreg_size += 4;
localvar_size = uint32(insn.Op1.value - 4);
#if defined(__DEBUG__)
msg("0x%a: detected enter #0x%a\n", ea, insn.Op1.value);
#endif /* __DEBUG__ */
}
// detect mov R15, R14 + ldi #imm, R0 instructions
else
{
if ( insn.itype != fr_mov
|| insn.Op1.type != o_reg
|| insn.Op1.reg != rR15
|| insn.Op2.type != o_reg
|| insn.Op2.reg != rR14 )
{
goto BAD_FUNC;
}
/*ea = */next_insn(&insn, ea);
if ( (insn.itype == fr_ldi_20 || insn.itype == fr_ldi_32)
&& insn.Op1.type == o_imm
&& insn.Op2.type == o_reg
&& insn.Op2.reg == rR0 )
{
localvar_size = uint32(insn.Op1.value);
}
else
{
goto BAD_FUNC;
}
#if defined(__DEBUG__)
msg("0x%a: detected ldi #0x%a, R0\n", ea, insn.Op1.value);
#endif /* __DEBUG__ */
}
// XXX we don't care about near/far functions, because currently
// we don't know how to detect them ;-)
pfn->flags |= FUNC_FRAME;
return add_frame(pfn, localvar_size, savedreg_size, args_size);
BAD_FUNC:
return 0;
}
int idaapi is_sp_based(const insn_t &, const op_t &)
{
return OP_SP_ADD | OP_FP_BASED;
}
int idaapi is_align_insn(ea_t ea)
{
return get_byte(ea) == 0;
}

249
idasdk76/module/fr/fr.cfg Normal file
View File

@@ -0,0 +1,249 @@
; http://edevice.fujitsu.com/fj/MANUAL/MANUALl/allliste.html#WEB6
.default FR30
DUMMY 0xdeadbeef Dummy port
;.FR20 documentation under preparation...
.FR30
interrupt RESET 0x000FFFFC Reset
; 0x000FFFF8 Reserved for system
; 0x000FFFF4 Reserved for system
; 0x000FFFF0 Reserved for system
; 0x000FFFEC Reserved for system
; 0x000FFFE8 Reserved for system
; 0x000FFFE4 Reserved for system
; 0x000FFFE0 Reserved for system
; 0x000FFFDC Reserved for system
; 0x000FFFD8 Reserved for system
; 0x000FFFD4 Reserved for system
; 0x000FFFD0 Reserved for system
; 0x000FFFCC Reserved for system
; 0x000FFFC8 Reserved for system
interrupt UIE 0x000FFFC4 Undefined instruction exception
interrupt NMI 0x000FFFC0 NMI request
interrupt EI0 0x000FFFBC External 0
interrupt EI1 0x000FFFB8 External 1
interrupt EI2 0x000FFFB4 External 2
interrupt EI3 0x000FFFB0 External 3
interrupt UARTR0 0x000FFFAC UART 0 reception complete
interrupt UARTR1 0x000FFFA8 UART 1 reception complete
interrupt UARTR2 0x000FFFA4 UART 2 reception complete
interrupt UARTT0 0x000FFFA0 UART 0 transmission complete
interrupt UARTT1 0x000FFF9C UART 1 transmission complete
interrupt UARTT2 0x000FFF98 UART 2 transmission complete
interrupt DMAC0 0x000FFF94 DMAC 0 (end or error)
interrupt DMAC1 0x000FFF90 DMAC 1 (end or error)
interrupt DMAC2 0x000FFF8C DMAC 2 (end or error)
interrupt DMAC3 0x000FFF88 DMAC 3 (end or error)
interrupt DMAC4 0x000FFF84 DMAC 4 (end or error)
interrupt DMAC5 0x000FFF80 DMAC 5 (end or error)
interrupt DMAC6 0x000FFF7C DMAC 6 (end or error)
interrupt DMAC7 0x000FFF78 DMAC 7 (end or error)
interrupt AD 0x000FFF74 A/D (successive approximation)
interrupt RLTIM0 0x000FFF70 Reload timer 0
interrupt RLTIM1 0x000FFF6C Reload timer 1
interrupt RLTIM2 0x000FFF68 Reload timer 2
interrupt PWM0 0x000FFF64 PWM 0
interrupt PWM1 0x000FFF60 PWM 1
interrupt PWM2 0x000FFF5C PWM 2
interrupt PWM3 0x000FFF58 PWM 3
interrupt UTIMER0 0x000FFF54 U-TIMER 0
interrupt UTIMER1 0x000FFF50 U-TIMER 1
interrupt UTIMER2 0x000FFF4C U-TIMER 2
interrupt EI4 0x000FFF48 External 4
interrupt EI5 0x000FFF44 External 5
interrupt EI6 0x000FFF40 External 6
interrupt EI7 0x000FFF3C External 7
interrupt DSPSI 0x000FFF38 DSP macro software interrupt
interrupt DSPOI 0x000FFF34 DSP macro offset interrupt
; 0x000FFF30 Reserved for system
; 0x000FFF2C Reserved for system
; 0x000FFF28 Reserved for system
; 0x000FFF24 Reserved for system
; 0x000FFF20 Reserved for system
; 0x000FFF1C Reserved for system
; 0x000FFF18 Reserved for system
; 0x000FFF14 Reserved for systemword
; 0x000FFF10 Reserved for system
; 0x000FFF0C Reserved for system
; 0x000FFF08 Reserved for system
; 0x000FFF04 Reserved for system
interrupt DIS 0x000FFF00 Delayed ressource
; 0x000FFEFC Reserved for system (used by REALOS)
; 0x000FFEF8 Reserved for system (used by REALOS)
interrupt INT 0x000FFEF4 For INT instruction
.FR50
interrupt RESET 0x000FFFFC Reset
interrupt MVEC 0x000FFFF8 Mode vector
;0x000FFFF4 System reserved
;0x000FFFF0 System reserved
;0x000FFFEC System reserved
;0x000FFFE8 System reserved
;0x000FFFE4 System reserved
interrupt COPTRAP 0x000FFFE0 Co-processor fault trap *4
interrupt COPETRAP 0x000FFFDC Co-processor error trap *4
interrupt INTE 0x000FFFD8 INTE instruction *4
interrupt IBE 0x000FFFD4 Instruction break exception *4
interrupt OBT 0x000FFFD0 Operand break trap *4
interrupt STT 0x000FFFCC Step trace trap *4
interrupt NMI 0x000FFFC8 NMI (tool)*4
interrupt UIE 0x000FFFC4 Undefined instruction exception
interrupt NMI_REQ 0x000FFFC0 NMI request
interrupt EI0 0x000FFFBC External Interrupt 0
interrupt EI1 0x000FFFB8 External Interrupt 1
interrupt EI2 0x000FFFB4 External Interrupt 2
interrupt EI3 0x000FFFB0 External Interrupt 3
interrupt EI4 0x000FFFAC External Interrupt 4
interrupt EI5 0x000FFFA8 External Interrupt 5
interrupt EI6 0x000FFFA4 External Interrupt 6
interrupt EI7 0x000FFFA0 External Interrupt 7
interrupt RLTIM0 0x000FFF9C Reload Timer 0
interrupt RLTIM1 0x000FFF98 Reload Timer 1
interrupt RLTIM2 0x000FFF94 Reload Timer 2
interrupt CAN0RX 0x000FFF90 CAN 0 RX
interrupt CAN0TX 0x000FFF8C CAN 0 TX/NS
interrupt CAN1RX 0x000FFF88 CAN 1 RX
interrupt CAN1TX 0x000FFF84 CAN 1 TX/NS
interrupt CAN2RX 0x000FFF80 CAN 2 RX
interrupt CAN2TX 0x000FFF7C CAN 2 TX/NS
interrupt CAN3RX 0x000FFF78 CAN 3 RX *5
interrupt CAN3TX 0x000FFF74 CAN 3 TX/NS *5
interrupt PPG01 0x000FFF70 PPG 0/1
interrupt PPG23 0x000FFF6C PPG 2/3
interrupt PPG45 0x000FFF68 PPG 4/5
interrupt PPG67 0x000FFF64 PPG 6/7
interrupt RLTIM3 0x000FFF60 Reload Timer 3
interrupt RLTIM4 0x000FFF5C Reload Timer 4
interrupt RLTIM5 0x000FFF58 Reload Timer 5
interrupt ICU01 0x000FFF54 ICU 0/1
interrupt OCU01 0x000FFF50 OCU 0/1
interrupt ICU23 0x000FFF4C ICU 2/3
interrupt OCU23 0x000FFF48 OCU 2/3
interrupt ADC 0x000FFF44 ADC
interrupt TO 0x000FFF40 Timebase Overflow
interrupt FRC0 0x000FFF3C Free Running Counter 0
interrupt FRC1 0x000FFF38 Free Running Counter 1
interrupt SIO0 0x000FFF34 SIO 0 *6
interrupt SIO1 0x000FFF30 SIO 1 *6
interrupt SG 0x000FFF2C Sound Generator
interrupt UART0RX 0x000FFF28 UART 0 RX
interrupt UART0TX 0x000FFF24 UART 0 TX
interrupt UART1RX 0x000FFF20 UART 1 RX
interrupt UART1TX 0x000FFF1C UART 1 TX
interrupt UART2RX 0x000FFF18 UART 2 RX
interrupt UART3TX 0x000FFF14 UART 2 TX
interrupt I2C 0x000FFF10 I2C
interrupt ACMP 0x000FFF0C Alarm Comparator
interrupt RTC 0x000FFF08 RTC (Watchtimer) / Calibration Unit
interrupt DMA 0x000FFF04 DMA
interrupt DIAB 0x000FFF00 Delayed activation bit
;0x000FFEFC System reserved *3
;0x000FFEF8 System reserved *3
interrupt SECVEC 0x000FFEF4 Security vector
;0x000FFEF0 System reserved
;0x000FFEEC System reserved
;0x000FFEE8 System reserved
;0x000FFEE4 System reserved
;0x000FFEE0 System reserved
;0x000FFEDC System reserved
;0x000FFED8 System reserved
;0x000FFED4 System reserved
;0x000FFED0 System reserved
;0x000FFECC System reserved
;0x000FFEC8 System reserved
;0x000FFEC4 System reserved
;0x000FFEC0 System reserved
interrupt INT0 0x000FFEBC Used by the INT instruction.
interrupt INT1 0x000FFC00 Used by the INT instruction.
.FR65E
interrupt RESET 0x000FFFFC Reset
interrupt MVEC 0x000FFFF8 Mode vector
; 0x000FFFF4 Reserved for system
; 0x000FFFF0 Reserved for system
; 0x000FFFEC Reserved for system
; 0x000FFFE8 Reserved for system
; 0x000FFFE4 Reserved for system
interrupt COPTRAP 0x000FFFE0 No-coprocessor trap
interrupt COPETRAP 0x000FFFDC Coprocessor error trap
interrupt INTE 0x000FFFD8 INTE instruction
interrupt IBE 0x000FFFD4 Instruction break exception
interrupt OBT 0x000FFFD0 Operand break trap
interrupt STT 0x000FFFCC Step trace trap
interrupt NMI 0x000FFFC8 NMI request (tool)
interrupt UIE 0x000FFFC4 Undefined instruction exception
interrupt NMIREQ 0x000FFFC0 NMI request
interrupt EI0 0x000FFFBC External Interrupt 0
interrupt EI1 0x000FFFB8 External Interrupt 1
interrupt EI2 0x000FFFB4 External Interrupt 2
interrupt EI3 0x000FFFB0 External Interrupt 3
interrupt EI4 0x000FFFAC External Interrupt 4
interrupt EI5 0x000FFFA8 External Interrupt 5
interrupt EI6 0x000FFFA4 External Interrupt 6
interrupt EI7 0x000FFFA0 External Interrupt 7
interrupt RLTIM0 0x000FFF9C Reload Timer 0
interrupt RLTIM1 0x000FFF98 Reload Timer 1
interrupt RLTIM2 0x000FFF94 Reload Timer 2
interrupt UARTR0 0x000FFF90 UART0 (reception completed)
interrupt UARTR1 0x000FFF8C UART1 (reception completed)
interrupt UARTR2 0x000FFF88 UART2 (reception completed)
interrupt UARTT0 0x000FFF84 UART0 (transmission completed)
interrupt UARTT1 0x000FFF80 UART1 (transmission completed)
interrupt UARTT2 0x000FFF7C UART2 (transmission completed)
interrupt DMAC0 0x000FFF78 DMAC0 (end, error)
interrupt DMAC1 0x000FFF74 DMAC1 (end, error)
interrupt DMAC2 0x000FFF70 DMAC2 (end, error)
interrupt DMAC3 0x000FFF6C DMAC3 (end, error)
interrupt DMAC4 0x000FFF68 DMAC4 (end, error)
interrupt AD 0x000FFF64 A/D
interrupt I2C 0x000FFF60 I2C
; 0x000FFF5C Reserved for system
; 0x000FFF58 Reserved for system
; 0x000FFF54 Reserved for system
; 0x000FFF50 Reserved for system
interrupt UTIMER0 0x000FFF4C U-TIMER0
interrupt UTIMER1 0x000FFF48 U-TIMER1
interrupt UTIMER2 0x000FFF44 U-TIMER2
interrupt TBTO 0x000FFF40 Time base timer overflow
; 0x000FFF3C Reserved for system
; 0x000FFF38 Reserved for system
; 0x000FFF34 Reserved for system
; 0x000FFF30 Reserved for system
; 0x000FFF2C Reserved for system
; 0x000FFF28 Reserved for system
; 0x000FFF24 Reserved for system
; 0x000FFF20 Reserved for system
; 0x000FFF1C Reserved for system
; 0x000FFF18 Reserved for system
; 0x000FFF14 Reserved for system
; 0x000FFF10 Reserved for system
; 0x000FFF0C Reserved for system
; 0x000FFF08 Reserved for system
; 0x000FFF04 Reserved for system
interrupt DISB 0x000FFF00 Delayed source bit
; 0x000FFEFC Reserved for system (used by REALOS)
; 0x000FFEF8 Reserved for system (used by REALOS)
; 0x000FFEF4 Reserved for system
; 0x000FFEF0 Reserved for system
; 0x000FFEEC Reserved for system
; 0x000FFEE8 Reserved for system
; 0x000FFEE4 Reserved for system
; 0x000FFEE0 Reserved for system
; 0x000FFEDC Reserved for system
; 0x000FFED8 Reserved for system
; 0x000FFED4 Reserved for system
; 0x000FFED0 Reserved for system
; 0x000FFECC Reserved for system
; 0x000FFEC8 Reserved for system
; 0x000FFEC4 Reserved for system
; 0x000FFEC0 Reserved for system
interrupt INT0 0x000FFEBC Used in INT instruction
interrupt INT1 0x000FFC00 Used in INT instruction

144
idasdk76/module/fr/fr.hpp Normal file
View File

@@ -0,0 +1,144 @@
#ifndef __FR_HPP
#define __FR_HPP
#include "../idaidp.hpp"
#include "ins.hpp"
#include <diskio.hpp>
#include <frame.hpp>
#include "../iohandler.hpp"
// uncomment this for the final release
//#define __DEBUG__
// FR registers
enum fr_registers
{
// general purpose registers :
rR0,
rR1,
rR2,
rR3,
rR4,
rR5,
rR6,
rR7,
rR8,
rR9,
rR10,
rR11,
rR12,
rR13,
rR14,
rR15,
// coprocessor registers :
rCR0,
rCR1,
rCR2,
rCR3,
rCR4,
rCR5,
rCR6,
rCR7,
rCR8,
rCR9,
rCR10,
rCR11,
rCR12,
rCR13,
rCR14,
rCR15,
// dedicated registers :
rPC, // program counter
rPS, // program status
rTBR, // table base register
rRP, // return pointer
rSSP, // system stack pointer
rUSP, // user stack pointer
rMDL, // multiplication/division register (LOW)
rMDH, // multiplication/division register (HIGH)
// system use dedicated registers
rReserved6,
rReserved7,
rReserved8,
rReserved9,
rReserved10,
rReserved11,
rReserved12,
rReserved13,
rReserved14,
rReserved15,
// these 2 registers are required by the IDA kernel :
rVcs,
rVds
};
enum fr_phrases
{
fIGR, // indirect general register
fIRA, // indirect relative address
fIGRP, // indirect general register with post-increment
fIGRM, // indirect general register with pre-decrement
fR13RI, // indirect displacement between R13 and a general register
};
// shortcut for a new operand type
#define o_reglist o_idpspec0
// flags for insn.auxpref
#define INSN_DELAY_SHOT 0x00000001 // postfix insn mnem by ":D"
// flags for opt.specflag1
#define OP_DISPL_IMM_R14 0x00000001 // @(R14, #i)
#define OP_DISPL_IMM_R15 0x00000002 // @(R15, #i)
#define OP_ADDR_R 0x00000010 // read-access to memory
#define OP_ADDR_W 0x00000012 // write-access to memory
inline bool op_displ_imm_r14(const op_t &op) { return (op.specflag1 & OP_DISPL_IMM_R14) != 0; }
inline bool op_displ_imm_r15(const op_t &op) { return (op.specflag1 & OP_DISPL_IMM_R15) != 0; }
// exporting our routines
int idaapi ana(insn_t *_insn);
bool idaapi create_func_frame(func_t *pfn);
int idaapi is_sp_based(const insn_t &, const op_t &x);
int idaapi is_align_insn(ea_t ea);
struct fr_t : public procmod_t
{
netnode helper;
iohandler_t ioh = iohandler_t(helper);
bool print_comma = false;
virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override;
int choose_device();
const ioport_t *find_sym(ea_t address);
const char *set_idp_options(
const char *keyword,
int /*value_type*/,
const void * /*value*/,
bool /*idb_loaded*/);
void fr_header(outctx_t &ctx);
int emu(const insn_t &insn) const;
bool is_stop(const insn_t &insn) const;
void fr_footer(outctx_t &ctx) const;
void fr_segstart(outctx_t &ctx, segment_t *Sarea) const;
void load_from_idb();
};
extern int data_id;
#define PROCMOD_NODE_NAME "$ fr"
#define PROCMOD_NAME fr
#endif /* __FR_HPP */

109
idasdk76/module/fr/ins.cpp Normal file
View File

@@ -0,0 +1,109 @@
#include "fr.hpp"
const instruc_t Instructions[] =
{
{ "", 0 }, // null instruction
{ "add", CF_USE1|CF_USE2|CF_CHG2 }, // add word data of source register / 4-bit immediate data to destination register
{ "add2", CF_USE1|CF_USE2|CF_CHG2 }, // add 4-bit immediate data to destination register
{ "addc", CF_USE1|CF_USE2|CF_CHG2 }, // add word data of source register and carry bit to destination register
{ "addn", CF_USE1|CF_USE2|CF_CHG2 }, // add word data of source register / immediate data to destination register
{ "addn2", CF_USE1|CF_USE2|CF_CHG2 }, // add immediate data to destination register
{ "sub", CF_USE1|CF_USE2|CF_CHG2 }, // subtract word data in source register from destination register
{ "subc", CF_USE1|CF_USE2|CF_CHG2 }, // subtract word data in source register and carry bit from destination register
{ "subn", CF_USE1|CF_USE2|CF_CHG2 }, // subtract word data in source register from destination register
{ "cmp", CF_USE1|CF_USE2 }, // compare word / immediate data in source register and destination register
{ "cmp2", CF_USE1|CF_USE2 }, // compare immediate data and destination register
{ "and", CF_USE1|CF_USE2|CF_CHG2 }, // and word data of source register to destination register / data in memory
{ "andh", CF_USE1|CF_USE2|CF_CHG2 }, // and half-word data of source register to data in memory
{ "andb", CF_USE1|CF_USE2|CF_CHG2 }, // and byte data of source register to data in memory
{ "or", CF_USE1|CF_USE2|CF_CHG2 }, // or word data of source register to destination register / data in memory
{ "orh", CF_USE1|CF_USE2|CF_CHG2 }, // or half-word data of source register to data in memory
{ "orb", CF_USE1|CF_USE2|CF_CHG2 }, // or byte data of source register to data in memory
{ "eor", CF_USE1|CF_USE2|CF_CHG2 }, // exclusive or word data of source register to destination register / data in memory
{ "eorh", CF_USE1|CF_USE2|CF_CHG2 }, // exclusive or half-word data of source register to data in memory
{ "eorb", CF_USE1|CF_USE2|CF_CHG2 }, // exclusive or byte data of source register to data in memory
{ "bandl", CF_USE1|CF_USE2|CF_CHG2 }, // and 4-bit immediate data to lower 4 bits of byte data in memory
{ "bandh", CF_USE1|CF_USE2|CF_CHG2 }, // and 4-bit immediate data to higher 4 bits of byte data in memory
{ "borl", CF_USE1|CF_USE2|CF_CHG2 }, // or 4-bit immediate data to lower 4 bits of byte data in memory
{ "borh", CF_USE1|CF_USE2|CF_CHG2 }, // or 4-bit immediate data to higher 4 bits of byte data in memory
{ "beorl", CF_USE1|CF_USE2|CF_CHG2 }, // eor 4-bit immediate data to lower 4 bits of byte data in memory
{ "beorh", CF_USE1|CF_USE2|CF_CHG2 }, // eor 4-bit immediate data to higher 4 bits of byte data in memory
{ "btstl", CF_USE1|CF_USE2 }, // test lower 4 bits of byte data in memory
{ "btsth", CF_USE1|CF_USE2 }, // test higher 4 bits of byte data in memory
{ "mul", CF_USE1|CF_USE2 }, // multiply word data
{ "mulu", CF_USE1|CF_USE2 }, // multiply unsigned word data
{ "mulh", CF_USE1|CF_USE2 }, // multiply half-word data
{ "muluh", CF_USE1|CF_USE2 }, // multiply unsigned half-word data
{ "div0s", CF_USE1 }, // initial setting up for signed division
{ "div0u", CF_USE1 }, // initial setting up for unsigned division
{ "div1", CF_USE1 }, // main process of division
{ "div2", CF_USE1 }, // correction when remainder is 0
{ "div3", 0 }, // correction when remainder is 0
{ "div4s", 0 }, // correction answer for signed division
{ "lsl", CF_USE1|CF_USE2|CF_CHG2 }, // logical shift to the left direction
{ "lsl2", CF_USE1|CF_USE2|CF_CHG2 }, // logical shift to the left direction
{ "lsr", CF_USE1|CF_USE2|CF_CHG2 }, // logical shift to the right direction
{ "lsr2", CF_USE1|CF_USE2|CF_CHG2 }, // logical shift to the right direction
{ "asr", CF_USE1|CF_USE2|CF_CHG2 }, // arithmetic shift to the right direction
{ "asr2", CF_USE1|CF_USE2|CF_CHG2 }, // arithmetic shift to the right direction
{ "ldi:32", CF_USE1|CF_USE2|CF_CHG2 }, // load immediate 32-bit data to destination register
{ "ldi:20", CF_USE1|CF_USE2|CF_CHG2 }, // load immediate 20-bit data to destination register
{ "ldi:8", CF_USE1|CF_USE2|CF_CHG2 }, // load immediate 8-bit data to destination register
{ "ld", CF_USE1|CF_USE2|CF_CHG2 }, // load word data in memory to register / program status register
{ "lduh", CF_USE1|CF_USE2|CF_CHG2 }, // load half-word data in memory to register
{ "ldub", CF_USE1|CF_USE2|CF_CHG2 }, // load byte data in memory to register
{ "st", CF_USE1|CF_USE2|CF_CHG2 }, // store word data in register / program status register to memory
{ "sth", CF_USE1|CF_USE2|CF_CHG2 }, // store half-word data in register to memory
{ "stb", CF_USE1|CF_USE2|CF_CHG2 }, // store byte data in register to memory
{ "mov", CF_USE1|CF_USE2|CF_CHG2 }, // move word data in source register / program status register to destination register / program status register
{ "jmp", CF_USE1|CF_STOP }, // jump
{ "call", CF_USE1|CF_CALL }, // call subroutine
{ "ret", CF_STOP }, // return from subroutine
{ "int", CF_USE1 }, // software interrupt
{ "inte", 0 }, // software interrupt for emulator
{ "reti", CF_STOP }, // return from interrupt
{ "bra", CF_USE1|CF_STOP }, // branch relative if condition satisfied
{ "bno", CF_USE1 }, // branch relative if condition satisfied
{ "beq", CF_USE1 }, // branch relative if condition satisfied
{ "bne", CF_USE1 }, // branch relative if condition satisfied
{ "bc", CF_USE1 }, // branch relative if condition satisfied
{ "bnc", CF_USE1 }, // branch relative if condition satisfied
{ "bn", CF_USE1 }, // branch relative if condition satisfied
{ "bp", CF_USE1 }, // branch relative if condition satisfied
{ "bv", CF_USE1 }, // branch relative if condition satisfied
{ "bnv", CF_USE1 }, // branch relative if condition satisfied
{ "blt", CF_USE1 }, // branch relative if condition satisfied
{ "bge", CF_USE1 }, // branch relative if condition satisfied
{ "ble", CF_USE1 }, // branch relative if condition satisfied
{ "bgt", CF_USE1 }, // branch relative if condition satisfied
{ "bls", CF_USE1 }, // branch relative if condition satisfied
{ "bhi", CF_USE1 }, // branch relative if condition satisfied
{ "dmov", CF_USE1|CF_USE2|CF_CHG2 }, // move word data from register / address to register / address
{ "dmovh", CF_USE1|CF_USE2|CF_CHG2 }, // move half-word data from register / address to register / address
{ "dmovb", CF_USE1|CF_USE2|CF_CHG2 }, // move byte data from register / address to register / address
{ "ldres", CF_USE1|CF_USE2|CF_CHG1 }, // load word data in memory to resource
{ "stres", CF_USE1|CF_USE2|CF_CHG1 }, // store word data in resource to memory
{ "copop", CF_USE1|CF_USE2|CF_USE3|CF_USE4 }, // coprocessor operation
{ "copld", CF_USE1|CF_USE2|CF_USE3|CF_USE4|CF_CHG4 }, // load 32-bit data from register to coprocessor register
{ "copst", CF_USE1|CF_USE2|CF_USE3|CF_USE4|CF_CHG4 }, // store 32-bit data from coprocessor register to register
{ "copsv", CF_USE1|CF_USE2|CF_USE3|CF_USE4|CF_CHG4 }, // save 32-bit data from coprocessor register to register
{ "nop", 0 }, // no operation
{ "andccr", CF_USE1 }, // and condition code register and immediate data
{ "orccr", CF_USE1 }, // or condition code register and immediate data
{ "stilm", CF_USE1 }, // set immediate data to interrupt level mask register
{ "addsp", CF_USE1 }, // add stack pointer and immediate data
{ "extsb", CF_USE1|CF_CHG1 }, // sign extend from byte data to word data
{ "extub", CF_USE1|CF_CHG1 }, // unsign extend from byte data to word data
{ "extsh", CF_USE1|CF_CHG1 }, // sign extend from byte data to word data
{ "extuh", CF_USE1|CF_CHG1 }, // unsigned extend from byte data to word data
{ "ldm0", CF_USE1 }, // load multiple registers
{ "ldm1", CF_USE1 }, // load multiple registers
{ "stm0", CF_USE1 }, // store multiple registers
{ "stm1", CF_USE1 }, // store multiple registers
{ "enter", CF_USE1 }, // enter function
{ "leave", CF_USE1 }, // leave function
{ "xchb", CF_CHG1|CF_CHG2 } // exchange byte data
};
CASSERT(qnumber(Instructions) == fr_last);

114
idasdk76/module/fr/ins.hpp Normal file
View File

@@ -0,0 +1,114 @@
#ifndef __ins_hpp
#define __ins_hpp
extern const instruc_t Instructions[];
enum nameNum ENUM_SIZE(uint16)
{
fr_null = 0, // null instruction
fr_add, // add word data of source register / 4-bit immediate data to destination register
fr_add2, // add 4-bit immediate data to destination register
fr_addc, // add word data of source register and carry bit to destination register
fr_addn, // add word data of source register / immediate data to destination register
fr_addn2, // add immediate data to destination register
fr_sub, // subtract word data in source register from destination register
fr_subc, // subtract word data in source register and carry bit from destination register
fr_subn, // subtract word data in source register from destination register
fr_cmp, // compare word / immediate data in source register and destination register
fr_cmp2, // compare immediate data and destination register
fr_and, // and word data of source register to destination register / data in memory
fr_andh, // and half-word data of source register to data in memory
fr_andb, // and byte data of source register to data in memory
fr_or, // or word data of source register to destination register / data in memory
fr_orh, // or half-word data of source register to data in memory
fr_orb, // or byte data of source register to data in memory
fr_eor, // exclusive or word data of source register to destination register / data in memory
fr_eorh, // exclusive or half-word data of source register to data in memory
fr_eorb, // exclusive or byte data of source register to data in memory
fr_bandl, // and 4-bit immediate data to lower 4 bits of byte data in memory
fr_bandh, // and 4-bit immediate data to higher 4 bits of byte data in memory
fr_borl, // or 4-bit immediate data to lower 4 bits of byte data in memory
fr_borh, // or 4-bit immediate data to higher 4 bits of byte data in memory
fr_beorl, // eor 4-bit immediate data to lower 4 bits of byte data in memory
fr_beorh, // eor 4-bit immediate data to higher 4 bits of byte data in memory
fr_btstl, // test lower 4 bits of byte data in memory
fr_btsth, // test higher 4 bits of byte data in memory
fr_mul, // multiply word data
fr_mulu, // multiply unsigned word data
fr_mulh, // multiply half-word data
fr_muluh, // multiply unsigned half-word data
fr_div0s, // initial setting up for signed division
fr_div0u, // initial setting up for unsigned division
fr_div1, // main process of division
fr_div2, // correction when remainder is 0
fr_div3, // correction when remainder is 0
fr_div4s, // correction answer for signed division
fr_lsl, // logical shift to the left direction
fr_lsl2, // logical shift to the left direction
fr_lsr, // logical shift to the right direction
fr_lsr2, // logical shift to the right direction
fr_asr, // arithmetic shift to the right direction
fr_asr2, // arithmetic shift to the right direction
fr_ldi_32, // load immediate 32-bit data to destination register
fr_ldi_20, // load immediate 20-bit data to destination register
fr_ldi_8, // load immediate 8-bit data to destination register
fr_ld, // load word data in memory to register / program status register
fr_lduh, // load half-word data in memory to register
fr_ldub, // load byte data in memory to register
fr_st, // store word data in register / program status register to memory
fr_sth, // store half-word data in register to memory
fr_stb, // store byte data in register to memory
fr_mov, // move word data in source register / program status register to destination register / program status register
fr_jmp, // jump
fr_call, // call subroutine
fr_ret, // return from subroutine
fr_int, // software interrupt
fr_inte, // software interrupt for emulator
fr_reti, // return from interrupt
fr_bra, // branch relative if condition satisfied
fr_bno, // branch relative if condition satisfied
fr_beq, // branch relative if condition satisfied
fr_bne, // branch relative if condition satisfied
fr_bc, // branch relative if condition satisfied
fr_bnc, // branch relative if condition satisfied
fr_bn, // branch relative if condition satisfied
fr_bp, // branch relative if condition satisfied
fr_bv, // branch relative if condition satisfied
fr_bnv, // branch relative if condition satisfied
fr_blt, // branch relative if condition satisfied
fr_bge, // branch relative if condition satisfied
fr_ble, // branch relative if condition satisfied
fr_bgt, // branch relative if condition satisfied
fr_bls, // branch relative if condition satisfied
fr_bhi, // branch relative if condition satisfied
fr_dmov, // move word data from register / address to register / address
fr_dmovh, // move half-word data from register / address to register / address
fr_dmovb, // move byte data from register / address to register / address
fr_ldres, // load word data in memory to resource
fr_stres, // store word data in resource to memory
fr_copop, // coprocessor operation
fr_copld, // load 32-bit data from register to coprocessor register
fr_copst, // store 32-bit data from coprocessor register to register
fr_copsv, // save 32-bit data from coprocessor register to register
fr_nop, // no operation
fr_andccr, // and condition code register and immediate data
fr_orccr, // or condition code register and immediate data
fr_stilm, // set immediate data to interrupt level mask register
fr_addsp, // add stack pointer and immediate data
fr_extsb, // sign extend from byte data to word data
fr_extub, // unsign extend from byte data to word data
fr_extsh, // sign extend from byte data to word data
fr_extuh, // unsigned extend from byte data to word data
fr_ldm0, // load multiple registers
fr_ldm1, // load multiple registers
fr_stm0, // store multiple registers
fr_stm1, // store multiple registers
fr_enter, // enter function
fr_leave, // leave function
fr_xchb, // exchange byte data
fr_last // last instruction
};
#endif /* __ins_hpp */

View File

@@ -0,0 +1,57 @@
PROC=fr
CONFIGS=fr.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)ieee.h $(I)kernwin.hpp \
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
$(I)nalt.hpp $(I)name.hpp \
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \
ana.cpp fr.hpp ins.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)ieee.h $(I)kernwin.hpp \
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
$(I)nalt.hpp $(I)name.hpp \
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \
emu.cpp fr.hpp ins.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)ieee.h $(I)kernwin.hpp \
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
$(I)nalt.hpp $(I)name.hpp \
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \
fr.hpp ins.cpp ins.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)ieee.h $(I)kernwin.hpp \
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
$(I)nalt.hpp $(I)name.hpp \
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \
fr.hpp ins.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)ieee.h $(I)kernwin.hpp \
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
$(I)nalt.hpp $(I)name.hpp \
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
$(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
../iohandler.hpp fr.hpp ins.hpp reg.cpp

298
idasdk76/module/fr/out.cpp Normal file
View File

@@ -0,0 +1,298 @@
#include "fr.hpp"
//----------------------------------------------------------------------
class out_fr_t : public outctx_t
{
out_fr_t(void) = delete; // not used
public:
void out_reg(ushort reg) { out_register(ph.reg_names[reg]); }
void out_reg(const op_t &op) { out_reg(op.reg); }
void out_imm(const op_t &op, bool no_sharp = false);
void out_addr(const op_t &op);
void out_reglist(const op_t &op);
bool out_operand(const op_t &x);
void out_insn(void);
void out_proc_mnem(void);
private:
void out_reg_if_bit(ushort reg, uval_t value, int bit);
};
CASSERT(sizeof(out_fr_t) == sizeof(outctx_t));
DECLARE_OUT_FUNCS(out_fr_t)
//----------------------------------------------------------------------
// Output an operand as an immediate value
void out_fr_t::out_imm(const op_t &op, bool no_sharp)
{
if ( !no_sharp )
out_symbol('#');
out_value(op, OOFW_IMM);
}
//----------------------------------------------------------------------
// Output an operand as an address
void out_fr_t::out_addr(const op_t &op)
{
if ( !out_name_expr(op, to_ea(insn.cs, op.addr), op.addr) )
out_value(op, OOF_ADDR | OOFS_NOSIGN | OOFW_32);
}
//----------------------------------------------------------------------
void out_fr_t::out_reg_if_bit(ushort reg, uval_t value, int bit)
{
fr_t &pm = *static_cast<fr_t *>(procmod);
if ( (value & bit) == bit )
{
if ( pm.print_comma )
{
out_symbol(',');
out_char(' ');
}
out_reg(reg);
pm.print_comma = true;
}
}
void out_fr_t::out_reglist(const op_t &op)
{
static const uint16 regs_ldm0[] = { rR7, rR6, rR5, rR4, rR3, rR2, rR1, rR0 };
static const uint16 regs_stm0[] = { rR0, rR1, rR2, rR3, rR4, rR5, rR6, rR7 };
static const uint16 regs_ldm1[] = { rR15, rR14, rR13, rR12, rR11, rR10, rR9, rR8 };
static const uint16 regs_stm1[] = { rR8, rR9, rR10, rR11, rR12, rR13, rR14, rR15 };
fr_t &pm = *static_cast<fr_t *>(procmod);
const uint16 *regs;
bool left;
switch ( insn.itype )
{
case fr_ldm0: regs = regs_ldm0; left = false; break;
case fr_stm0: regs = regs_stm0; left = true; break;
case fr_ldm1: regs = regs_ldm1; left = false; break;
case fr_stm1: regs = regs_stm1; left = true; break;
default:
INTERR(10018);
}
pm.print_comma = false;
out_symbol('(');
if ( left ) //-V614 uninitialized variable 'left'
{
for ( int i = 0, bit = 128; bit != 0; bit >>= 1, i++ )
out_reg_if_bit(regs[i], op.value, bit);
}
else
{
for ( int i = 7, bit = 1; bit <= 128; bit <<= 1, i-- )
out_reg_if_bit(regs[i], op.value, bit);
}
out_symbol(')');
}
//----------------------------------------------------------------------
// Generate disassembly header
void fr_t::fr_header(outctx_t &ctx)
{
ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX, NULL, ioh.device.c_str());
}
//----------------------------------------------------------------------
// Generate disassembly footer
void fr_t::fr_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");
}
}
//----------------------------------------------------------------------
// Generate a segment header
//lint -esym(1764, ctx) could be made const
//lint -esym(818, Sarea) could be made const
void fr_t::fr_segstart(outctx_t &ctx, segment_t *Sarea) const
{
qstring sname;
if ( get_visible_segm_name(&sname, Sarea) <= 0 )
return;
const char *segname = sname.c_str();
if ( *segname == '_' )
segname++;
ctx.gen_printf(DEFAULT_INDENT, COLSTR(".section .%s", SCOLOR_ASMDIR), segname);
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);
}
}
//----------------------------------------------------------------------
// Output an operand.
bool out_fr_t::out_operand(const op_t & op)
{
fr_t &pm = *static_cast<fr_t *>(procmod);
switch ( op.type )
{
case o_near:
case o_mem:
out_addr(op);
break;
// immediate value
case o_imm:
{
const ioport_t *port = pm.find_sym(op.value);
// this immediate is represented in the .cfg file
// output the port name instead of the numeric value
if ( port != NULL )
out_line(port->name.c_str(), COLOR_IMPNAME);
else // otherwise, simply print the value
out_imm(op);
}
break;
// register
case o_reg:
out_reg(op);
break;
// phrase
case o_phrase:
out_symbol('@');
switch ( op.specflag2 )
{
case fIGR: // indirect general register
out_reg(op);
break;
case fIRA: // indirect relative address
out_value(op, OOF_ADDR | OOFS_NOSIGN | OOFW_32);
break;
case fIGRP: // indirect general register with post-increment
out_reg(op);
out_symbol('+');
break;
case fIGRM: // indirect general register with pre-decrement
out_symbol('-');
out_reg(op);
break;
case fR13RI: // indirect displacement between R13 and a general register
out_symbol('(');
out_reg(rR13);
out_symbol(',');
out_char(' ');
out_reg(op);
out_symbol(')');
break;
default:
INTERR(10019);
}
break;
// displacement
case o_displ:
out_symbol('@');
out_symbol('(');
// @(R14, #i)
if ( op_displ_imm_r14(op) )
{
out_reg(rR14);
out_symbol(',');
out_char(' ');
out_imm(op, true);
}
// @(R15, #i)
else if ( op_displ_imm_r15(op) )
{
out_reg(rR15);
out_symbol(',');
out_char(' ');
out_imm(op, true);
}
else
INTERR(10020);
out_symbol(')');
break;
// reglist
case o_reglist:
out_reglist(op);
break;
// void operand
case o_void:
break;
default:
INTERR(10021);
}
return 1;
}
//----------------------------------------------------------------------
void out_fr_t::out_proc_mnem(void)
{
char postfix[5];
postfix[0] = '\0';
if ( insn.auxpref & INSN_DELAY_SHOT )
qstrncpy(postfix, ":D", sizeof(postfix));
out_mnem(8, postfix);
}
//----------------------------------------------------------------------
// Output an instruction
void out_fr_t::out_insn(void)
{
//
// print insn mnemonic
//
out_mnemonic();
for ( int i=0; i < 4; i++ )
{
if ( insn.ops[i].type != o_void )
{
if ( i != 0 )
{
out_symbol(',');
out_char(' ');
}
out_one_operand(i);
}
}
// output a character representation of the immediate values
// embedded in the instruction as comments
out_immchar_cmts();
flush_outbuf();
}

439
idasdk76/module/fr/reg.cpp Normal file
View File

@@ -0,0 +1,439 @@
#include "fr.hpp"
#include <segregs.hpp>
int data_id;
// FR registers names
static const char *const RegNames[] =
{
// general purpose registers :
"r0",
"r1",
"r2",
"r3",
"r4",
"r5",
"r6",
"r7",
"r8",
"r9",
"r10",
"r11",
"r12",
"r13",
"r14",
"r15",
// coprocessor registers :
"cr0",
"cr1",
"cr2",
"cr3",
"cr4",
"cr5",
"cr6",
"cr7",
"cr8",
"cr9",
"cr10",
"cr11",
"cr12",
"cr13",
"cr14",
"cr15",
// dedicated registers :
"pc", // program counter
"ps", // program status
"tbr", // table base register
"rp", // return pointer
"ssp", // system stack pointer
"usp", // user stack pointer
"mdl", // multiplication/division register (LOW)
"mdh", // multiplication/division register (HIGH)
// system use dedicated registers
"reserved6",
"reserved7",
"reserved8",
"reserved9",
"reserved10",
"reserved11",
"reserved12",
"reserved13",
"reserved14",
"reserved15",
// these 2 registers are required by the IDA kernel :
"cs",
"ds"
};
int fr_t::choose_device()
{
char cfgfile[QMAXFILE];
ioh.get_cfg_filename(cfgfile, sizeof(cfgfile));
if ( choose_ioport_device(&ioh.device, cfgfile) )
ioh.set_device_name(ioh.device.c_str(), IORESP_NONE);
return 0;
}
// returns a pointer to a ioport_t object if address was found in the config file.
// otherwise, returns NULL.
const ioport_t *fr_t::find_sym(ea_t address)
{
return find_ioport(ioh.ports, address);
}
const char *fr_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)
&& ioh.device == NONEPROC )
{
warning("No devices are defined in the configuration file %s", cfgfile);
}
else
{
ioh.set_device_name(ioh.device.c_str(), IORESP_NONE);
}
return IDPOPT_OK;
}
//----------------------------------------------------------------------
void fr_t::load_from_idb()
{
ioh.restore_device();
}
//----------------------------------------------------------------------
// 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(SET_MODULE_DATA(fr_t));
return 0;
}
ssize_t idaapi fr_t::on_event(ssize_t msgid, va_list va)
{
switch ( msgid )
{
case processor_t::ev_init:
inf_set_be(true);
helper.create(PROCMOD_NODE_NAME);
break;
case processor_t::ev_term:
ioh.ports.clear();
clr_module_data(data_id);
break;
case processor_t::ev_newfile:
choose_device();
ioh.set_device_name(ioh.device.c_str(), IORESP_ALL);
break;
case processor_t::ev_ending_undo:
case processor_t::ev_oldfile:
load_from_idb();
break;
case processor_t::ev_out_mnem:
{
outctx_t *ctx = va_arg(va, outctx_t *);
out_mnem(*ctx);
return 1;
}
case processor_t::ev_out_header:
{
outctx_t *ctx = va_arg(va, outctx_t *);
fr_header(*ctx);
return 1;
}
case processor_t::ev_out_footer:
{
outctx_t *ctx = va_arg(va, outctx_t *);
fr_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 *);
fr_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_is_sp_based:
{
int *mode = va_arg(va, int *);
const insn_t *insn = va_arg(va, const insn_t *);
const op_t *op = va_arg(va, const op_t *);
*mode = is_sp_based(*insn, *op);
return 1;
}
case processor_t::ev_create_func_frame:
{
func_t *pfn = va_arg(va, func_t *);
create_func_frame(pfn);
return 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;
}
case processor_t::ev_is_align_insn:
{
ea_t ea = va_arg(va, ea_t);
return is_align_insn(ea);
}
default:
break;
}
return 0;
}
//
// GNU assembler for fujitsu FR
//
//-----------------------------------------------------------------------
// gets a function's name
//lint -e{818} could be declared const
static bool fr_get_func_name(qstring *name, func_t *pfn)
{
ea_t ea = pfn->start_ea;
if ( get_demangled_name(name, ea, inf_get_long_demnames(), DEMNAM_NAME) <= 0 )
return false;
tag_addr(name, ea, true);
return true;
}
//-----------------------------------------------------------------------
// prints function header
static void idaapi gnu_func_header(outctx_t &ctx, func_t *pfn)
{
ctx.gen_func_header(pfn);
qstring namebuf;
if ( fr_get_func_name(&namebuf, pfn) )
{
const char *name = namebuf.begin();
ctx.gen_printf(DEFAULT_INDENT, COLSTR(".type %s, @function", SCOLOR_ASMDIR), name);
ctx.gen_printf(0, COLSTR("%s:", SCOLOR_ASMDIR), name);
ctx.ctxflags |= CTXF_LABEL_OK;
}
}
//-----------------------------------------------------------------------
// prints function footer
static void idaapi gnu_func_footer(outctx_t &ctx, func_t *pfn)
{
qstring namebuf;
if ( fr_get_func_name(&namebuf, pfn) )
{
const char *name = namebuf.begin();
ctx.gen_printf(DEFAULT_INDENT, COLSTR(".size %s, .-%s", SCOLOR_ASMDIR), name, name);
}
}
//-----------------------------------------------------------------------
static const asm_t gnu_asm =
{
AS_COLON
|ASH_HEXF3 // hex 0x123 format
|ASB_BINF0 // bin 0110b format
|ASO_OCTF1 // oct 012345 format
// don't display the final 0 in string declarations
|/*AS_1TEXT |*/ AS_NCMAS,
0,
"GNU Assembler for the Fujitsu FR Family",
0,
NULL, // no headers
".org", // origin directive
NULL, // end directive
";", // comment string
'"', // string delimiter
'\'', // char delimiter
"\\\"'", // special symbols in char and string constants
".ascii", // ascii string directive
".byte", // byte directive
".word", // word directive
".long", // dword (4 bytes)
NULL, // qword (8 bytes)
NULL, // oword (16 bytes)
".float", // float (4 bytes)
".double", // 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
gnu_func_header, // func_header
gnu_func_footer, // func_footer
".globl", // public
NULL, // weak
NULL, // extrn
NULL, // comm
NULL, // get_type_name
".align", // 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
};
//
// Supported assemblers :
//
static const asm_t *const asms[] = { &gnu_asm, NULL };
//
// Short and long name for our module
//
#define FAMILY "Fujitsu FR 32-Bit Family:"
static const char *const shnames[] =
{
"fr",
NULL
};
static const char *const lnames[] =
{
FAMILY"Fujitsu FR 32-Bit Family",
NULL
};
static const uchar retcode_1[] = { 0x97, 0x20 }; // ret
static const uchar retcode_2[] = { 0x9F, 0x20 }; // ret with delay shot
static const uchar retcode_3[] = { 0x9F, 0x30 }; // reti
static const bytes_t retcodes[] =
{
{ sizeof(retcode_1), retcode_1 },
{ sizeof(retcode_2), retcode_2 },
{ sizeof(retcode_3), retcode_3 },
{ 0, NULL } // NULL terminated array
};
//-----------------------------------------------------------------------
// Processor Definition
//-----------------------------------------------------------------------
processor_t LPH =
{
IDP_INTERFACE_VERSION, // version
PLFM_FR, // id
// flag
PR_RNAMESOK // can use register names for byte names
| PR_USE32 // supports 32-bit addressing
| PR_DEFSEG32 // segments are 32-bit by default
| 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, fr_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
fr_ret, // Icode of return instruction. It is ok to give any of possible return instructions
};