update
This commit is contained in:
296
idasdk75/module/kr1878/ana.cpp
Normal file
296
idasdk75/module/kr1878/ana.cpp
Normal file
@@ -0,0 +1,296 @@
|
||||
|
||||
#include "kr1878.hpp"
|
||||
|
||||
#define FUNCS_COUNT 3
|
||||
|
||||
struct funcdesc_t
|
||||
{
|
||||
bool (kr1878_t:: *func)(const insn_t &insn, int);
|
||||
int mask;
|
||||
int shift;
|
||||
};
|
||||
|
||||
struct opcode
|
||||
{
|
||||
ushort itype;
|
||||
const char *recog; //lint !e958 padding is required to align members
|
||||
funcdesc_t funcs[FUNCS_COUNT];
|
||||
uint32 mask;
|
||||
uint32 value;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline uint32 ua_16bits(const insn_t &insn)
|
||||
{
|
||||
return get_wide_byte(insn.ea);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void kr1878_t::opreg(uint16 reg)
|
||||
{
|
||||
op->type = o_reg;
|
||||
op->dtype = dt_word;
|
||||
op->reg = reg;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void kr1878_t::make_o_mem(const insn_t &insn)
|
||||
{
|
||||
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case KR1878_jmp:
|
||||
case KR1878_jsr:
|
||||
case KR1878_jnz:
|
||||
case KR1878_jz:
|
||||
case KR1878_jns:
|
||||
case KR1878_js:
|
||||
case KR1878_jnc:
|
||||
case KR1878_jc:
|
||||
op->type = o_near;
|
||||
op->dtype = dt_code;
|
||||
return;
|
||||
}
|
||||
op->type = o_mem;
|
||||
op->dtype = dt_byte;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool kr1878_t::D_ddddd(const insn_t &, int value)
|
||||
{
|
||||
op->type = o_phrase;
|
||||
op->dtype = dt_byte;
|
||||
op->reg = (value >> 3) & 0x03;
|
||||
op->value = value & 7;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool kr1878_t::S_ddddd(const insn_t &insn, int value)
|
||||
{
|
||||
if ( D_ddddd(insn, value) )
|
||||
{
|
||||
op++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool kr1878_t::D_SR(const insn_t &, int value)
|
||||
{
|
||||
op->type = o_reg;
|
||||
op->dtype = dt_word;
|
||||
op->reg = uint16(SR0 + value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool kr1878_t::S_SR(const insn_t &insn, int value)
|
||||
{
|
||||
if ( D_SR(insn, value) )
|
||||
{
|
||||
op++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool kr1878_t::D_Imm(const insn_t &, int value)
|
||||
{
|
||||
op->type = o_imm;
|
||||
op->dtype = dt_word;
|
||||
op->value = value & 0xffff;
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool kr1878_t::D_pImm(const insn_t &insn, int value)
|
||||
{
|
||||
|
||||
if ( value & 0x10 )
|
||||
D_Imm(insn, (value & 0x0f) << 4);
|
||||
else
|
||||
D_Imm(insn, value & 0x0f);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool kr1878_t::D_EA(const insn_t &insn, int value)
|
||||
{
|
||||
op->addr = value;
|
||||
make_o_mem(insn);
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// singleton to init table thread-aware
|
||||
struct table_t
|
||||
{
|
||||
static int count() { return qnumber(table); }
|
||||
static const opcode &get(int opcode)
|
||||
{
|
||||
static const table_t instance; //lint !e1788 only by its constructor/destructor
|
||||
return instance.table[opcode]; //lint !e727 static local symbol 'instance' of type 'const struct table_t' not explicitly initialized
|
||||
}
|
||||
|
||||
private:
|
||||
opcode table[52] =
|
||||
{
|
||||
{ KR1878_mov, "000001sssssddddd", {{&kr1878_t::S_ddddd, 0x1f}, {&kr1878_t::D_ddddd, 0x3e0}} },
|
||||
{ KR1878_cmp, "000010sssssddddd", {{&kr1878_t::S_ddddd, 0x1f}, {&kr1878_t::D_ddddd, 0x3e0}} },
|
||||
{ KR1878_add, "000100sssssddddd", {{&kr1878_t::S_ddddd, 0x1f}, {&kr1878_t::D_ddddd, 0x3e0}} },
|
||||
{ KR1878_sub, "000011sssssddddd", {{&kr1878_t::S_ddddd, 0x1f}, {&kr1878_t::D_ddddd, 0x3e0}} },
|
||||
{ KR1878_and, "000101sssssddddd", {{&kr1878_t::S_ddddd, 0x1f}, {&kr1878_t::D_ddddd, 0x3e0}} },
|
||||
{ KR1878_or, "000110sssssddddd", {{&kr1878_t::S_ddddd, 0x1f}, {&kr1878_t::D_ddddd, 0x3e0}} },
|
||||
{ KR1878_xor, "000111sssssddddd", {{&kr1878_t::S_ddddd, 0x1f}, {&kr1878_t::D_ddddd, 0x3e0}} },
|
||||
{ KR1878_movl, "010ccccccccddddd", {{&kr1878_t::S_ddddd, 0x1f}, {&kr1878_t::D_Imm, 0x1fe0}} },
|
||||
{ KR1878_cmpl, "011ccccccccddddd", {{&kr1878_t::S_ddddd, 0x1f}, {&kr1878_t::D_Imm, 0x1fe0}} },
|
||||
{ KR1878_addl, "001100cccccddddd", {{&kr1878_t::S_ddddd, 0x1f}, {&kr1878_t::D_Imm, 0x3e0}} },
|
||||
{ KR1878_subl, "001011cccccddddd", {{&kr1878_t::S_ddddd, 0x1f}, {&kr1878_t::D_Imm, 0x3e0}} },
|
||||
{ KR1878_bic, "001010pccccddddd", {{&kr1878_t::S_ddddd, 0x1f}, {&kr1878_t::D_pImm, 0x3e0}} },
|
||||
{ KR1878_bis, "001110pccccddddd", {{&kr1878_t::S_ddddd, 0x1f}, {&kr1878_t::D_pImm, 0x3e0}} },
|
||||
{ KR1878_btg, "001111pccccddddd", {{&kr1878_t::S_ddddd, 0x1f}, {&kr1878_t::D_pImm, 0x3e0}} },
|
||||
{ KR1878_btt, "001101pccccddddd", {{&kr1878_t::S_ddddd, 0x1f}, {&kr1878_t::D_pImm, 0x3e0}} },
|
||||
{ KR1878_swap, "00000000001ddddd", {{&kr1878_t::D_ddddd, 0x1f}} },
|
||||
{ KR1878_neg, "00000000010ddddd", {{&kr1878_t::D_ddddd, 0x1f}} },
|
||||
{ KR1878_not, "00000000011ddddd", {{&kr1878_t::D_ddddd, 0x1f}} },
|
||||
{ KR1878_shl, "00000000100ddddd", {{&kr1878_t::D_ddddd, 0x1f}} },
|
||||
{ KR1878_shr, "00000000101ddddd", {{&kr1878_t::D_ddddd, 0x1f}} },
|
||||
{ KR1878_shra, "00000000110ddddd", {{&kr1878_t::D_ddddd, 0x1f}} },
|
||||
{ KR1878_rlc, "00000000111ddddd", {{&kr1878_t::D_ddddd, 0x1f}} },
|
||||
{ KR1878_rrc, "00000001000ddddd", {{&kr1878_t::D_ddddd, 0x1f}} },
|
||||
{ KR1878_adc, "00000001001ddddd", {{&kr1878_t::D_ddddd, 0x1f}} },
|
||||
{ KR1878_sbc, "00000001010ddddd", {{&kr1878_t::D_ddddd, 0x1f}} },
|
||||
{ KR1878_ldr, "00100ccccccccnnn", {{&kr1878_t::S_SR, 0x07}, {&kr1878_t::D_Imm, 0x07f8}} },
|
||||
{ KR1878_mtpr, "00000010nnnsssss", {{&kr1878_t::S_ddddd, 0x1f}, {&kr1878_t::D_SR, 0xe0 }} },
|
||||
{ KR1878_mfpr, "00000011nnnddddd", {{&kr1878_t::S_SR, 0xe0}, {&kr1878_t::D_ddddd, 0x1f }} },
|
||||
{ KR1878_push, "0000000000010nnn", {{&kr1878_t::D_SR, 0x07}} },
|
||||
{ KR1878_pop, "0000000000011nnn", {{&kr1878_t::D_SR, 0x07}} },
|
||||
{ KR1878_sst, "000000011000bbbb", {{&kr1878_t::D_Imm, 0x0f}} },
|
||||
{ KR1878_cst, "000000011100bbbb", {{&kr1878_t::D_Imm, 0x0f}} },
|
||||
{ KR1878_tof, "0000000000000100" },
|
||||
{ KR1878_tdc, "0000000000000101" },
|
||||
{ KR1878_jmp, "100000aaaaaaaaaa", {{&kr1878_t::D_EA, 0x3ff}} },
|
||||
{ KR1878_jsr, "100100aaaaaaaaaa", {{&kr1878_t::D_EA, 0x3ff}} },
|
||||
{ KR1878_jnz, "101100aaaaaaaaaa", {{&kr1878_t::D_EA, 0x3ff}} },
|
||||
{ KR1878_jz, "101000aaaaaaaaaa", {{&kr1878_t::D_EA, 0x3ff}} },
|
||||
{ KR1878_jns, "110000aaaaaaaaaa", {{&kr1878_t::D_EA, 0x3ff}} },
|
||||
{ KR1878_js, "110100aaaaaaaaaa", {{&kr1878_t::D_EA, 0x3ff}} },
|
||||
{ KR1878_jnc, "111000aaaaaaaaaa", {{&kr1878_t::D_EA, 0x3ff}} },
|
||||
{ KR1878_jc, "111100aaaaaaaaaa", {{&kr1878_t::D_EA, 0x3ff}} },
|
||||
{ KR1878_ijmp, "0000000000000011" },
|
||||
{ KR1878_ijsr, "0000000000000111" },
|
||||
{ KR1878_rts, "0000000000001100" },
|
||||
{ KR1878_rtsc, "000000000000111c", {{&kr1878_t::D_Imm, 0x01}} },
|
||||
{ KR1878_rti, "0000000000001101" },
|
||||
{ KR1878_nop, "0000000000000000" },
|
||||
{ KR1878_wait, "0000000000000001" },
|
||||
{ KR1878_stop, "0000000000001000" },
|
||||
{ KR1878_reset, "0000000000000010" },
|
||||
{ KR1878_sksp, "0000000000000110" },
|
||||
};
|
||||
|
||||
table_t()
|
||||
{
|
||||
make_masks();
|
||||
}
|
||||
~table_t() = default;
|
||||
table_t(const table_t&) = delete;
|
||||
table_t &operator=(const table_t&) = delete;
|
||||
|
||||
void make_masks(void)
|
||||
{
|
||||
for ( int i = 0; i < qnumber(table); i++ )
|
||||
{
|
||||
int bmax = strlen(table[i].recog);
|
||||
for ( int b = 0; b < bmax; b++ )
|
||||
{
|
||||
table[i].value <<= 1;
|
||||
table[i].mask <<= 1;
|
||||
|
||||
if ( table[i].recog[b] == '1' || table[i].recog[b] == '0' )
|
||||
table[i].mask++;
|
||||
|
||||
if ( table[i].recog[b] == '1' )
|
||||
table[i].value++;
|
||||
}
|
||||
|
||||
for ( int j = 0; j < FUNCS_COUNT; j++ )
|
||||
{
|
||||
if ( table[i].funcs[j].func != NULL )
|
||||
{
|
||||
for ( int b = 0; b < 16; b++ )
|
||||
{
|
||||
if ( table[i].funcs[j].mask & (1 << b) )
|
||||
break;
|
||||
else
|
||||
table[i].funcs[j].shift++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void init_analyzer(void)
|
||||
{
|
||||
// TODO make_masks();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool kr1878_t::use_table(const insn_t &insn, uint32 code, int entry, int start, int end) //lint !e1762 could be made const
|
||||
{
|
||||
const opcode &ptr = table_t::get(entry);
|
||||
for ( int j = start; j <= end; j++ )
|
||||
{
|
||||
if ( ptr.funcs[j].func == NULL )
|
||||
break;
|
||||
int value = (code & ptr.funcs[j].mask) >> ptr.funcs[j].shift;
|
||||
if ( !(this->*ptr.funcs[j].func)(insn, value) )
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int kr1878_t::ana(insn_t *_insn)
|
||||
{
|
||||
insn_t &insn = *_insn;
|
||||
uint code = ua_16bits(insn);
|
||||
op = &insn.Op1;
|
||||
|
||||
int cnt = table_t::count();
|
||||
for ( int i = 0; i < cnt; i++ )
|
||||
{
|
||||
const auto &te = table_t::get(i);
|
||||
if ( (code & te.mask) == te.value )
|
||||
{
|
||||
insn.itype = te.itype;
|
||||
insn.size = 1;
|
||||
|
||||
if ( !use_table(insn, code, i, 0, FUNCS_COUNT - 1) )
|
||||
continue;
|
||||
|
||||
return insn.size;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void interr(const insn_t &insn, const char *module)
|
||||
{
|
||||
const char *name = NULL;
|
||||
if ( insn.itype < KR1878_last )
|
||||
name = Instructions[insn.itype].name;
|
||||
warning("%a(%s): internal error in %s", insn.ea, name, module);
|
||||
}
|
||||
184
idasdk75/module/kr1878/emu.cpp
Normal file
184
idasdk75/module/kr1878/emu.cpp
Normal file
@@ -0,0 +1,184 @@
|
||||
|
||||
#include "kr1878.hpp"
|
||||
#include <frame.hpp>
|
||||
#include <segregs.hpp>
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
ea_t calc_mem(const insn_t &insn, const op_t &x)
|
||||
{
|
||||
return to_ea(insn.cs, x.addr);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
ea_t kr1878_t::calc_data_mem(const insn_t &insn, const op_t &x, ushort segreg) const
|
||||
{
|
||||
sel_t dpage = get_sreg(insn.ea, segreg);
|
||||
if ( dpage == BADSEL )
|
||||
return BADSEL;
|
||||
return xmem + (((dpage & 0xFF) << 3) | (x.value));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool is_stkreg(int r)
|
||||
{
|
||||
return r == DSP;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
int idaapi is_sp_based(const insn_t &, const op_t &x)
|
||||
{
|
||||
return OP_SP_ADD | (x.phrase == DSP ? OP_SP_BASED : OP_FP_BASED);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static void process_immediate_number(const insn_t &insn, int n)
|
||||
{
|
||||
set_immd(insn.ea);
|
||||
if ( is_defarg(get_flags(insn.ea),n) )
|
||||
return;
|
||||
switch ( insn.itype )
|
||||
{
|
||||
|
||||
case KR1878_movl:
|
||||
case KR1878_cmpl: // Compare
|
||||
case KR1878_addl: // Addition
|
||||
case KR1878_subl: // Subtract
|
||||
case KR1878_bic:
|
||||
case KR1878_bis:
|
||||
case KR1878_btg:
|
||||
case KR1878_btt:
|
||||
case KR1878_ldr:
|
||||
case KR1878_sst:
|
||||
case KR1878_cst:
|
||||
|
||||
op_num(insn.ea, n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void kr1878_t::add_near_ref(const insn_t &insn, const op_t &x, ea_t ea)
|
||||
{
|
||||
cref_t ftype = fl_JN;
|
||||
if ( has_insn_feature(insn.itype, CF_CALL) )
|
||||
{
|
||||
if ( !func_does_return(ea) )
|
||||
flow = false;
|
||||
ftype = fl_CN;
|
||||
}
|
||||
insn.add_cref(ea, x.offb, ftype);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void kr1878_t::handle_operand(const insn_t &insn, const op_t &x, bool isAlt, bool isload)
|
||||
{
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_reg:
|
||||
break;
|
||||
default:
|
||||
// interr("emu");
|
||||
break;
|
||||
case o_imm:
|
||||
if ( !isload )
|
||||
interr(insn, "emu2");
|
||||
process_immediate_number(insn, x.n);
|
||||
if ( op_adds_xrefs(get_flags(insn.ea), x.n) )
|
||||
insn.add_off_drefs(x, dr_O, OOFS_IFSIGN);
|
||||
break;
|
||||
case o_mem:
|
||||
if ( !isAlt )
|
||||
{
|
||||
ea_t ea = calc_mem(insn, x);
|
||||
insn.add_dref(ea, x.offb, isload ? dr_R : dr_W);
|
||||
insn.create_op_data(ea, x);
|
||||
}
|
||||
break;
|
||||
case o_phrase:
|
||||
if ( !isAlt )
|
||||
{
|
||||
if ( x.reg != SR3 || x.value < 6 )
|
||||
{
|
||||
ea_t ea = calc_data_mem(insn, x, as + x.reg);
|
||||
insn.add_dref(ea, x.offb, isload ? dr_R : dr_W);
|
||||
insn.create_op_data(ea, x);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case o_near:
|
||||
if ( !isAlt )
|
||||
add_near_ref(insn, x, calc_mem(insn, x));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int kr1878_t::emu(const insn_t &insn)
|
||||
{
|
||||
if ( segtype(insn.ea) == SEG_XTRN )
|
||||
return 1;
|
||||
|
||||
uint32 Feature = insn.get_canon_feature(ph);
|
||||
bool flag1 = is_forced_operand(insn.ea, 0);
|
||||
bool flag2 = is_forced_operand(insn.ea, 1);
|
||||
bool flag3 = is_forced_operand(insn.ea, 2);
|
||||
|
||||
flow = ((Feature & CF_STOP) == 0);
|
||||
|
||||
if ( Feature & CF_USE1 ) handle_operand(insn, insn.Op1, flag1, true);
|
||||
if ( Feature & CF_USE2 ) handle_operand(insn, insn.Op2, flag2, true);
|
||||
if ( Feature & CF_USE3 ) handle_operand(insn, insn.Op3, flag3, true);
|
||||
|
||||
if ( Feature & CF_CHG1 ) handle_operand(insn, insn.Op1, flag1, false);
|
||||
if ( Feature & CF_CHG2 ) handle_operand(insn, insn.Op2, flag2, false);
|
||||
if ( Feature & CF_CHG3 ) handle_operand(insn, insn.Op3, flag3, false);
|
||||
|
||||
// check for Segment changes
|
||||
if ( insn.itype == KR1878_ldr
|
||||
&& insn.Op1.type == o_reg
|
||||
&& insn.Op1.reg < SR4 )
|
||||
{
|
||||
split_sreg_range(get_item_end(insn.ea), as + insn.Op1.reg, insn.Op2.value & 0xFF, SR_auto);
|
||||
}
|
||||
//
|
||||
// Determine if the next instruction should be executed
|
||||
//
|
||||
if ( Feature & CF_STOP )
|
||||
flow = false;
|
||||
if ( flow )
|
||||
add_cref(insn.ea, insn.ea+insn.size, fl_F);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int may_be_func(const insn_t &) // can a function start here?
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int is_sane_insn(const insn_t &insn, int /*nocrefs*/)
|
||||
{
|
||||
// disallow jumps to nowhere
|
||||
if ( insn.Op1.type == o_near && !is_mapped(calc_mem(insn, insn.Op1)) )
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int idaapi is_align_insn(ea_t ea)
|
||||
{
|
||||
insn_t insn;
|
||||
if ( decode_insn(&insn, ea) < 1 )
|
||||
return 0;
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case KR1878_nop:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return insn.size;
|
||||
}
|
||||
|
||||
69
idasdk75/module/kr1878/ins.cpp
Normal file
69
idasdk75/module/kr1878/ins.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
|
||||
#include "kr1878.hpp"
|
||||
|
||||
const instruc_t Instructions[] =
|
||||
{
|
||||
|
||||
{ "", 0 }, // Unknown Operation
|
||||
|
||||
{ "mov", CF_USE2|CF_CHG1 },
|
||||
{ "cmp", CF_USE1|CF_USE2 }, // Compare
|
||||
{ "add", CF_USE1|CF_USE2|CF_CHG1 }, // Addition
|
||||
{ "sub", CF_USE1|CF_USE2|CF_CHG1 }, // Subtract
|
||||
{ "and", CF_USE1|CF_USE2|CF_CHG1 }, // Logical AND
|
||||
{ "or", CF_USE1|CF_USE2|CF_CHG1 }, // Logical Inclusive OR
|
||||
{ "xor", CF_USE1|CF_USE2|CF_CHG1 }, // Logical Exclusive OR
|
||||
|
||||
{ "movl", CF_USE2|CF_CHG1 },
|
||||
{ "cmpl", CF_USE1|CF_USE2 }, // Compare
|
||||
{ "addl", CF_USE1|CF_USE2|CF_CHG1 }, // Addition
|
||||
{ "subl", CF_USE1|CF_USE2|CF_CHG1 }, // Subtract
|
||||
{ "bic", CF_USE1|CF_USE2|CF_CHG1 },
|
||||
{ "bis", CF_USE1|CF_USE2|CF_CHG1 },
|
||||
{ "btg", CF_USE1|CF_USE2|CF_CHG1 },
|
||||
{ "btt", CF_USE1|CF_USE2|CF_CHG1 },
|
||||
|
||||
{ "swap", CF_USE1|CF_CHG1 },
|
||||
{ "neg", CF_USE1|CF_CHG1 },
|
||||
{ "not", CF_USE1|CF_CHG1 },
|
||||
{ "shl", CF_USE1|CF_CHG1 }, // Shift Left
|
||||
{ "shr", CF_USE1|CF_CHG1 }, // Shift Right
|
||||
{ "shra", CF_USE1|CF_CHG1 }, // Arithmetic Shift Right
|
||||
{ "rlc", CF_USE1|CF_CHG1 }, // Rotate Left
|
||||
{ "rrc", CF_USE1|CF_CHG1 }, // Rotate Right
|
||||
{ "adc", CF_USE1|CF_CHG1 }, // Add with Carry
|
||||
{ "sbc", CF_USE1|CF_CHG1 }, // Subtract with Carry
|
||||
|
||||
{ "ldr", CF_USE2|CF_CHG1 },
|
||||
{ "mtpr", CF_USE2|CF_CHG1 },
|
||||
{ "mfpr", CF_USE2|CF_CHG1 },
|
||||
{ "push", CF_USE1 },
|
||||
{ "pop", CF_CHG1 },
|
||||
{ "sst", CF_USE1 },
|
||||
{ "cst", CF_USE1 },
|
||||
{ "tof", 0 },
|
||||
{ "tdc", 0 },
|
||||
|
||||
{ "jmp", CF_USE1|CF_STOP|CF_JUMP }, // Jump
|
||||
{ "jsr", CF_USE1|CF_CALL }, // Jump to Subroutine
|
||||
{ "jnz", CF_USE1|CF_JUMP }, // Jump
|
||||
{ "jz", CF_USE1|CF_JUMP }, // Jump
|
||||
{ "jns", CF_USE1|CF_JUMP }, // Jump
|
||||
{ "js", CF_USE1|CF_JUMP }, // Jump
|
||||
{ "jnc", CF_USE1|CF_JUMP }, // Jump
|
||||
{ "jc", CF_USE1|CF_JUMP }, // Jump
|
||||
{ "ijmp", CF_STOP }, // Jump
|
||||
{ "ijsr", CF_STOP }, // Jump to Subroutine
|
||||
{ "rts", CF_STOP }, // Return from Subroutine
|
||||
{ "rtsc", CF_USE1|CF_STOP }, // Return from Subroutine
|
||||
{ "rti", CF_STOP }, // Return from Interrupt
|
||||
|
||||
{ "nop", 0 }, // No Operation
|
||||
{ "wait", 0 },
|
||||
{ "stop", 0 },
|
||||
{ "reset", 0 },
|
||||
{ "sksp", 0 },
|
||||
|
||||
};
|
||||
|
||||
CASSERT(qnumber(Instructions) == KR1878_last);
|
||||
73
idasdk75/module/kr1878/ins.hpp
Normal file
73
idasdk75/module/kr1878/ins.hpp
Normal file
@@ -0,0 +1,73 @@
|
||||
|
||||
#ifndef __INSTRS_HPP
|
||||
#define __INSTRS_HPP
|
||||
|
||||
extern const instruc_t Instructions[];
|
||||
|
||||
enum nameNum
|
||||
{
|
||||
KR1878_null = 0, // Unknown Operation
|
||||
|
||||
KR1878_mov,
|
||||
KR1878_cmp, // Compare
|
||||
KR1878_add, // Addition
|
||||
KR1878_sub, // Subtract
|
||||
KR1878_and, // Logical AND
|
||||
KR1878_or, // Logical Inclusive OR
|
||||
KR1878_xor, // Logical Exclusive OR
|
||||
|
||||
KR1878_movl,
|
||||
KR1878_cmpl, // Compare
|
||||
KR1878_addl, // Addition
|
||||
KR1878_subl, // Subtract
|
||||
KR1878_bic,
|
||||
KR1878_bis,
|
||||
KR1878_btg,
|
||||
KR1878_btt,
|
||||
|
||||
KR1878_swap,
|
||||
KR1878_neg,
|
||||
KR1878_not,
|
||||
KR1878_shl, // Shift Left
|
||||
KR1878_shr, // Shift Right
|
||||
KR1878_shra, // Arithmetic Shift Right
|
||||
KR1878_rlc, // Rotate Left
|
||||
KR1878_rrc, // Rotate Right
|
||||
KR1878_adc, // Add with Carry
|
||||
KR1878_sbc, // Subtract with Carry
|
||||
|
||||
KR1878_ldr,
|
||||
KR1878_mtpr,
|
||||
KR1878_mfpr,
|
||||
KR1878_push,
|
||||
KR1878_pop,
|
||||
KR1878_sst,
|
||||
KR1878_cst,
|
||||
KR1878_tof,
|
||||
KR1878_tdc,
|
||||
|
||||
KR1878_jmp, // Jump
|
||||
KR1878_jsr, // Jump to Subroutine
|
||||
KR1878_jnz, // Jump
|
||||
KR1878_jz, // Jump
|
||||
KR1878_jns, // Jump
|
||||
KR1878_js, // Jump
|
||||
KR1878_jnc, // Jump
|
||||
KR1878_jc, // Jump
|
||||
KR1878_ijmp, // Jump
|
||||
KR1878_ijsr, // Jump to Subroutine
|
||||
KR1878_rts, // Return from Subroutine
|
||||
KR1878_rtsc, // Return from Subroutine
|
||||
KR1878_rti, // Return from Interrupt
|
||||
|
||||
KR1878_nop, // No Operation
|
||||
KR1878_wait,
|
||||
KR1878_stop,
|
||||
KR1878_reset,
|
||||
KR1878_sksp,
|
||||
|
||||
KR1878_last,
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
20
idasdk75/module/kr1878/kr1878.cfg
Normal file
20
idasdk75/module/kr1878/kr1878.cfg
Normal file
@@ -0,0 +1,20 @@
|
||||
|
||||
; This file describes the standard addresses for Angstrem KR1878
|
||||
|
||||
.default kr1878
|
||||
|
||||
.kr1878
|
||||
|
||||
ST 0x00
|
||||
PortA 0x01
|
||||
PortB 0x02
|
||||
TCtl 0x04
|
||||
Twrk 0x05
|
||||
PCtlA 0x19
|
||||
PCtlB 0x1A
|
||||
WDCtl 0x1D
|
||||
EEPCtl 0x38
|
||||
EEPLoA 0x39
|
||||
EEPHiA 0x3A
|
||||
EEPData 0x3F
|
||||
|
||||
122
idasdk75/module/kr1878/kr1878.hpp
Normal file
122
idasdk75/module/kr1878/kr1878.hpp
Normal file
@@ -0,0 +1,122 @@
|
||||
|
||||
#ifndef _KR1878_HPP
|
||||
#define _KR1878_HPP
|
||||
|
||||
#include "../idaidp.hpp"
|
||||
#include "ins.hpp"
|
||||
#include <diskio.hpp>
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
||||
#define amode specflag2 // addressing mode
|
||||
#define amode_x 0x10 // X:
|
||||
|
||||
//------------------------------------------------------------------
|
||||
#define UAS_GNU 0x0001 // GNU assembler
|
||||
//------------------------------------------------------------------
|
||||
enum RegNo
|
||||
{
|
||||
SR0,
|
||||
SR1,
|
||||
SR2,
|
||||
SR3,
|
||||
SR4,
|
||||
SR5,
|
||||
SR6,
|
||||
SR7,
|
||||
DSP,
|
||||
ISP,
|
||||
as,
|
||||
bs,
|
||||
cs,
|
||||
ds,
|
||||
vCS, vDS, // virtual registers for code and data segments
|
||||
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
||||
struct addargs_t
|
||||
{
|
||||
ea_t ea;
|
||||
int nargs;
|
||||
op_t args[4][2];
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
#define IDP_SIMPLIFY 0x0001 // simplify instructions
|
||||
#define IDP_PSW_W 0x0002 // W-bit in PSW is set
|
||||
|
||||
extern ushort idpflags;
|
||||
|
||||
inline bool dosimple(void) { return (idpflags & IDP_SIMPLIFY) != 0; }
|
||||
inline bool psw_w(void) { return (idpflags & IDP_PSW_W) != 0; }
|
||||
|
||||
ea_t calc_mem(const insn_t &insn, const op_t &x);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
void interr(const insn_t &insn, const char *module);
|
||||
|
||||
void idaapi kr1878_header(outctx_t &ctx);
|
||||
|
||||
void idaapi kr1878_segend(outctx_t &ctx, segment_t *seg);
|
||||
|
||||
int idaapi is_align_insn(ea_t ea);
|
||||
int idaapi is_sp_based(const insn_t &insn, const op_t &x);
|
||||
|
||||
int is_jump_func(const func_t *pfn, ea_t *jump_target);
|
||||
int is_sane_insn(const insn_t &insn, int nocrefs);
|
||||
int may_be_func(const insn_t &insn); // can a function start here?
|
||||
|
||||
void init_analyzer(void);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
DECLARE_PROC_LISTENER(idb_listener_t, struct kr1878_t);
|
||||
|
||||
struct kr1878_t : public procmod_t
|
||||
{
|
||||
ioports_t ports;
|
||||
qstring device;
|
||||
netnode helper;
|
||||
ea_t xmem = BADADDR;
|
||||
op_t *op = nullptr; // current operand
|
||||
bool flow = false;
|
||||
|
||||
idb_listener_t idb_listener = idb_listener_t(*this);
|
||||
|
||||
virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override;
|
||||
|
||||
const ioport_t *find_port(ea_t address);
|
||||
void read_kr1878_cfg(void);
|
||||
void set_device_name(const char *dev);
|
||||
const char *set_idp_options(
|
||||
const char *keyword,
|
||||
int /*value_type*/,
|
||||
const void * /*value*/,
|
||||
bool /*idb_loaded*/);
|
||||
|
||||
ea_t calc_data_mem(const insn_t &insn, const op_t &x, ushort segreg) const;
|
||||
void handle_operand(const insn_t &insn, const op_t &x, bool isAlt, bool isload);
|
||||
void add_near_ref(const insn_t &insn, const op_t &x, ea_t ea);
|
||||
int emu(const insn_t &insn);
|
||||
|
||||
void opreg(uint16 reg);
|
||||
void make_o_mem(const insn_t &insn);
|
||||
bool D_ddddd(const insn_t &, int value);
|
||||
bool S_ddddd(const insn_t &insn, int value);
|
||||
bool D_SR(const insn_t &, int value);
|
||||
bool S_SR(const insn_t &insn, int value);
|
||||
bool D_Imm(const insn_t &, int value);
|
||||
bool D_pImm(const insn_t &insn, int value);
|
||||
bool D_EA(const insn_t &insn, int value);
|
||||
bool use_table(const insn_t &insn, uint32 code, int entry, int start, int end);
|
||||
int ana(insn_t *_insn);
|
||||
|
||||
void kr1878_assumes(outctx_t &ctx);
|
||||
void print_segment_register(outctx_t &ctx, int reg, sel_t value);
|
||||
void kr1878_segstart(outctx_t &ctx, segment_t *Srange) const;
|
||||
void kr1878_footer(outctx_t &ctx) const;
|
||||
};
|
||||
#endif // _KR1878_HPP
|
||||
46
idasdk75/module/kr1878/makefile
Normal file
46
idasdk75/module/kr1878/makefile
Normal file
@@ -0,0 +1,46 @@
|
||||
PROC=kr1878
|
||||
CONFIGS=kr1878.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)fpro.h $(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 ana.cpp ins.hpp \
|
||||
kr1878.hpp
|
||||
$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.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)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
|
||||
emu.cpp ins.hpp kr1878.hpp
|
||||
$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp $(I)fpro.h $(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 ins.cpp ins.hpp \
|
||||
kr1878.hpp
|
||||
$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp $(I)fpro.h $(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)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
|
||||
ins.hpp kr1878.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)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)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
|
||||
ins.hpp kr1878.hpp reg.cpp
|
||||
243
idasdk75/module/kr1878/out.cpp
Normal file
243
idasdk75/module/kr1878/out.cpp
Normal file
@@ -0,0 +1,243 @@
|
||||
|
||||
#include <ctype.h>
|
||||
#include "kr1878.hpp"
|
||||
#include <segregs.hpp>
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
class out_kr1878_t : public outctx_t
|
||||
{
|
||||
out_kr1878_t(void) = delete; // not used
|
||||
kr1878_t &pm() { return *static_cast<kr1878_t *>(procmod); }
|
||||
public:
|
||||
void outreg(int r) { out_register(ph.reg_names[r]); }
|
||||
bool out_port_address(ea_t addr);
|
||||
void out_bad_address(ea_t addr);
|
||||
void out_address(ea_t ea, const op_t &x);
|
||||
void out_ip_rel(int displ);
|
||||
|
||||
bool out_operand(const op_t &x);
|
||||
void out_insn(void);
|
||||
};
|
||||
CASSERT(sizeof(out_kr1878_t) == sizeof(outctx_t));
|
||||
|
||||
DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_kr1878_t)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool out_kr1878_t::out_port_address(ea_t addr)
|
||||
{
|
||||
const ioport_t *port = pm().find_port(addr);
|
||||
if ( port != NULL && !port->name.empty() )
|
||||
{
|
||||
out_line(port->name.c_str(), COLOR_IMPNAME);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_kr1878_t::out_bad_address(ea_t addr)
|
||||
{
|
||||
if ( !out_port_address(addr) )
|
||||
{
|
||||
out_tagon(COLOR_ERROR);
|
||||
out_btoa(addr, 16);
|
||||
out_tagoff(COLOR_ERROR);
|
||||
remember_problem(PR_NONAME, insn.ea);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_kr1878_t::out_address(ea_t ea, const op_t &x)
|
||||
{
|
||||
segment_t *s = getseg(ea);
|
||||
ea_t value = s != NULL ? ea - get_segm_base(s) : ea;
|
||||
if ( !out_name_expr(x, ea, value) )
|
||||
{
|
||||
out_tagon(COLOR_ERROR);
|
||||
out_printf("%a", ea);
|
||||
out_tagoff(COLOR_ERROR);
|
||||
remember_problem(PR_NONAME, insn.ea);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_kr1878_t::out_ip_rel(int displ)
|
||||
{
|
||||
out_printf(COLSTR("%s+", SCOLOR_SYMBOL) COLSTR("%d", SCOLOR_NUMBER),
|
||||
ash.a_curip, displ);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool out_kr1878_t::out_operand(const op_t & x)
|
||||
{
|
||||
ea_t ea;
|
||||
if ( x.type == o_imm )
|
||||
out_symbol('#');
|
||||
char buf[MAXSTR];
|
||||
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_void:
|
||||
return 0;
|
||||
|
||||
case o_imm:
|
||||
out_value(x, OOFS_IFSIGN|OOFW_IMM);
|
||||
break;
|
||||
|
||||
case o_reg:
|
||||
outreg(x.reg);
|
||||
|
||||
break;
|
||||
|
||||
case o_mem:
|
||||
// no break;
|
||||
case o_near:
|
||||
{
|
||||
ea = calc_mem(insn, x);
|
||||
if ( ea == insn.ea+insn.size )
|
||||
out_ip_rel(insn.size);
|
||||
else if ( !out_name_expr(x, ea, x.addr) )
|
||||
out_bad_address(x.addr);
|
||||
}
|
||||
break;
|
||||
|
||||
case o_phrase:
|
||||
qsnprintf(buf, sizeof(buf), "%%%c%" FMT_EA "x", 'a' + x.reg, x.value);
|
||||
|
||||
ea = pm().calc_data_mem(insn, x, as + x.reg);
|
||||
if ( ea != BADADDR && (x.reg != SR3 || x.value < 6) )
|
||||
{
|
||||
out_line(buf, COLOR_AUTOCMT);
|
||||
out_symbol(' ');
|
||||
out_address(ea, x);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_line(buf, COLOR_REG);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
interr(insn, "out");
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_kr1878_t::out_insn(void)
|
||||
{
|
||||
out_mnemonic();
|
||||
|
||||
bool comma = out_one_operand(0);
|
||||
if ( insn.Op2.type != o_void )
|
||||
{
|
||||
if ( comma )
|
||||
out_symbol(',');
|
||||
out_one_operand(1);
|
||||
}
|
||||
if ( insn.Op3.type != o_void )
|
||||
{
|
||||
out_symbol(',');
|
||||
out_one_operand(2);
|
||||
}
|
||||
|
||||
out_immchar_cmts();
|
||||
flush_outbuf();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void kr1878_t::print_segment_register(outctx_t &ctx, int reg, sel_t value)
|
||||
{
|
||||
if ( reg == ph.reg_data_sreg )
|
||||
return;
|
||||
if ( value != BADADDR )
|
||||
{
|
||||
char buf[MAX_NUMBUF];
|
||||
btoa(buf, sizeof(buf), value);
|
||||
ctx.gen_cmt_line("assume %s = %s", ph.reg_names[reg], buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.gen_cmt_line("drop %s", ph.reg_names[reg]);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// function to produce assume directives
|
||||
void kr1878_t::kr1878_assumes(outctx_t &ctx)
|
||||
{
|
||||
ea_t ea = ctx.insn_ea;
|
||||
segment_t *seg = getseg(ea);
|
||||
if ( seg == NULL || (inf_get_outflags() & OFLG_GEN_ASSUME) == 0 )
|
||||
return;
|
||||
bool seg_started = (ea == seg->start_ea);
|
||||
|
||||
for ( int i = ph.reg_first_sreg; i <= ph.reg_last_sreg; ++i )
|
||||
{
|
||||
if ( i == ph.reg_code_sreg )
|
||||
continue;
|
||||
sreg_range_t sra;
|
||||
if ( !get_sreg_range(&sra, ea, i) )
|
||||
continue;
|
||||
sel_t now = get_sreg(ea, i);
|
||||
if ( seg_started || sra.start_ea == ea )
|
||||
{
|
||||
sreg_range_t prev_sra;
|
||||
bool prev_exists = get_sreg_range(&prev_sra, ea - 1, i);
|
||||
if ( seg_started || (prev_exists && get_sreg(prev_sra.start_ea, i) != now) )
|
||||
print_segment_register(ctx, i, now);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//lint -esym(1764, ctx) could be made const
|
||||
//lint -esym(818, Srange) could be made const
|
||||
void kr1878_t::kr1878_segstart(outctx_t &ctx, segment_t *Srange) const
|
||||
{
|
||||
if ( is_spec_segm(Srange->type) )
|
||||
return;
|
||||
|
||||
qstring sclas;
|
||||
get_segm_class(&sclas, Srange);
|
||||
|
||||
if ( sclas == "CODE" )
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR(".text", SCOLOR_ASMDIR));
|
||||
else if ( sclas == "DATA" )
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR(".data", SCOLOR_ASMDIR));
|
||||
|
||||
if ( Srange->orgbase != 0 )
|
||||
{
|
||||
char buf[MAX_NUMBUF];
|
||||
btoa(buf, sizeof(buf), Srange->orgbase);
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void idaapi kr1878_segend(outctx_t &, segment_t *)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void idaapi kr1878_header(outctx_t &ctx)
|
||||
{
|
||||
ctx.gen_header(GH_PRINT_ALL);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void kr1878_t::kr1878_footer(outctx_t &ctx) const
|
||||
{
|
||||
qstring nbuf = get_colored_name(inf_get_start_ea());
|
||||
const char *name = nbuf.c_str();
|
||||
const char *end = ash.end;
|
||||
if ( end == NULL )
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s end %s",SCOLOR_AUTOCMT), ash.cmnt, name);
|
||||
else
|
||||
ctx.gen_printf(DEFAULT_INDENT,
|
||||
COLSTR("%s",SCOLOR_ASMDIR) " " COLSTR("%s %s",SCOLOR_AUTOCMT),
|
||||
ash.end, ash.cmnt, name);
|
||||
}
|
||||
|
||||
499
idasdk75/module/kr1878/reg.cpp
Normal file
499
idasdk75/module/kr1878/reg.cpp
Normal file
@@ -0,0 +1,499 @@
|
||||
|
||||
#include <ctype.h>
|
||||
#include "kr1878.hpp"
|
||||
#include <diskio.hpp>
|
||||
#include <entry.hpp>
|
||||
#include <segregs.hpp>
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const char *const register_names[] =
|
||||
{
|
||||
// data arithmetic logic unit
|
||||
"SR0", "SR1", "SR2", "SR3",
|
||||
"SR4", "SR5", "SR6", "SR7",
|
||||
"DSP", "ISP",
|
||||
"a", "b", "c", "d",
|
||||
"cs","ds", // virtual registers for code and data segments
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const uchar retcode_0[] = { 0x0c, 0x00 };
|
||||
static const uchar retcode_1[] = { 0x0d, 0x00 };
|
||||
|
||||
static const bytes_t retcodes[] =
|
||||
{
|
||||
{ sizeof(retcode_0), retcode_0 },
|
||||
{ sizeof(retcode_1), retcode_1 },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
struct interrupt_t
|
||||
{
|
||||
int offset;
|
||||
const char *name; //lint !e958 padding is required to align members
|
||||
};
|
||||
|
||||
static const interrupt_t ints[] =
|
||||
{
|
||||
{ 0x0000, "HRESET" }, // Hardware RESET
|
||||
{ 0x0001, "WDOG" },
|
||||
{ 0x0002, "STOVF" },
|
||||
{ 0x0003, "TIMER" },
|
||||
{ 0x0006, "PORTA" },
|
||||
{ 0x0007, "PORTB" },
|
||||
{ 0x000F, "EEPWr" },
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Angstrem KR1878VE1 Assembler
|
||||
//-----------------------------------------------------------------------
|
||||
static const asm_t motasm =
|
||||
{
|
||||
ASH_HEXF4 // $34
|
||||
|ASD_DECF0 // 34
|
||||
|ASB_BINF2 // %01010
|
||||
|ASO_OCTF1 // 0123
|
||||
|AS_COLON
|
||||
|AS_N2CHR
|
||||
|AS_NCMAS
|
||||
|AS_ONEDUP,
|
||||
0,
|
||||
"Angstrem KR1878VE1 Assembler",
|
||||
0,
|
||||
NULL, // header lines
|
||||
"org", // org
|
||||
"end", // end
|
||||
|
||||
";", // comment string
|
||||
'"', // string delimiter
|
||||
'\'', // char delimiter
|
||||
"\"'", // special symbols in char and string constants
|
||||
|
||||
"dc", // ascii string directive
|
||||
"dcb", // byte directive
|
||||
"dc", // word directive
|
||||
NULL, // double words
|
||||
NULL, // qwords
|
||||
NULL, // oword (16 bytes)
|
||||
NULL, // float (4 bytes)
|
||||
NULL, // double (8 bytes)
|
||||
NULL, // tbyte (10/12 bytes)
|
||||
NULL, // packed decimal real
|
||||
"bs#s(c,) #d, #v", // arrays (#h,#d,#v,#s(...)
|
||||
"ds %s", // uninited arrays
|
||||
"equ", // equ
|
||||
NULL, // 'seg' prefix (example: push seg seg001)
|
||||
"*", // current IP (instruction pointer)
|
||||
NULL, // func_header
|
||||
NULL, // func_footer
|
||||
"global", // "public" name keyword
|
||||
NULL, // "weak" name keyword
|
||||
"xref", // "extrn" name keyword
|
||||
// .extern directive requires an explicit object size
|
||||
NULL, // "comm" (communal variable)
|
||||
NULL, // get_type_name
|
||||
NULL, // "align" keyword
|
||||
'(', ')', // lbrace, rbrace
|
||||
"%", // mod
|
||||
"&", // and
|
||||
"|", // or
|
||||
"^", // xor
|
||||
"~", // not
|
||||
"<<", // shl
|
||||
">>", // shr
|
||||
NULL, // sizeof
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// GNU ASM
|
||||
//-----------------------------------------------------------------------
|
||||
static const asm_t gas =
|
||||
{
|
||||
AS_ASCIIC
|
||||
|ASH_HEXF4 // $34
|
||||
|ASD_DECF0 // 34
|
||||
|ASB_BINF3 // 0b01010
|
||||
|ASO_OCTF1 // 0123
|
||||
|AS_COLON
|
||||
|AS_N2CHR
|
||||
|AS_NCMAS
|
||||
|AS_ONEDUP,
|
||||
UAS_GNU,
|
||||
"GNU-like hypothetical assembler",
|
||||
0,
|
||||
NULL, // header lines
|
||||
".org", // org
|
||||
NULL, // end
|
||||
|
||||
";", // comment string
|
||||
'"', // string delimiter
|
||||
'\'', // char delimiter
|
||||
"\"'", // special symbols in char and string constants
|
||||
|
||||
".string", // ascii string directive
|
||||
".byte", // byte directive
|
||||
".short", // word directive
|
||||
".long", // double words
|
||||
NULL, // qwords
|
||||
NULL, // oword (16 bytes)
|
||||
NULL, // float (4 bytes)
|
||||
NULL, // double (8 bytes)
|
||||
NULL, // tbyte (10/12 bytes)
|
||||
NULL, // packed decimal real
|
||||
".ds.#s(b,w,l,d) #d, #v", // arrays (#h,#d,#v,#s(...)
|
||||
".space %s", // uninited arrays
|
||||
"=", // equ
|
||||
NULL, // 'seg' prefix (example: push seg seg001)
|
||||
".", // current IP (instruction pointer)
|
||||
NULL, // func_header
|
||||
NULL, // func_footer
|
||||
".global", // "public" name keyword
|
||||
NULL, // "weak" name keyword
|
||||
".extern", // "extrn" name keyword
|
||||
// .extern directive requires an explicit object size
|
||||
".comm", // "comm" (communal variable)
|
||||
NULL, // get_type_name
|
||||
".align", // "align" keyword
|
||||
'(', ')', // lbrace, rbrace
|
||||
"mod", // mod
|
||||
"and", // and
|
||||
"or", // or
|
||||
"xor", // xor
|
||||
"not", // not
|
||||
"shl", // shl
|
||||
"shr", // shr
|
||||
NULL, // sizeof
|
||||
0, // flag2
|
||||
NULL, // cmnt2
|
||||
NULL, // low8
|
||||
NULL, // high8
|
||||
NULL, // low16
|
||||
NULL, // high16
|
||||
"#include \"%s\"", // a_include_fmt
|
||||
};
|
||||
|
||||
static const asm_t *const asms[] = { &motasm, &gas, NULL };
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static ea_t AdditionalSegment(int size, int offset, const char *name)
|
||||
{
|
||||
segment_t s;
|
||||
s.start_ea = free_chunk(0x100000, size, 0xF);
|
||||
s.end_ea = s.start_ea + size;
|
||||
s.sel = allocate_selector((s.start_ea-offset) >> 4);
|
||||
s.type = SEG_DATA;
|
||||
add_segm_ex(&s, name, "DATA", ADDSEG_NOSREG|ADDSEG_OR_DIE);
|
||||
return s.start_ea - offset;
|
||||
}
|
||||
|
||||
inline ea_t get_start(const segment_t *s)
|
||||
{
|
||||
return s ? s->start_ea : BADADDR;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
const ioport_t *kr1878_t::find_port(ea_t address)
|
||||
{
|
||||
return find_ioport(ports, address);
|
||||
}
|
||||
|
||||
void kr1878_t::read_kr1878_cfg(void)
|
||||
{
|
||||
read_ioports(&ports, &device, "kr1878.cfg");
|
||||
for ( size_t i=0; i < ports.size(); i++ )
|
||||
{
|
||||
const ioport_t &p = ports[i];
|
||||
ea_t ea = xmem + p.address;
|
||||
const char *name = p.name.c_str();
|
||||
ea_t nameea = get_name_ea(BADADDR, name);
|
||||
if ( nameea != ea )
|
||||
{
|
||||
set_name(nameea, "");
|
||||
if ( !set_name(ea, name, SN_NOCHECK|SN_NOWARN|SN_NODUMMY) )
|
||||
set_cmt(ea, name, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void kr1878_t::set_device_name(const char *dev)
|
||||
{
|
||||
if ( dev )
|
||||
{
|
||||
device = dev;
|
||||
read_kr1878_cfg();
|
||||
}
|
||||
}
|
||||
|
||||
const char *kr1878_t::set_idp_options(
|
||||
const char *keyword,
|
||||
int /*value_type*/,
|
||||
const void * /*value*/,
|
||||
bool /*idb_loaded*/)
|
||||
{
|
||||
if ( keyword != NULL )
|
||||
return IDPOPT_BADKEY;
|
||||
if ( choose_ioport_device(&device, "kr1878.cfg") )
|
||||
read_kr1878_cfg();
|
||||
return IDPOPT_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// We always return "yes" because of the messy problem that
|
||||
// there are additional operands with wrong operand number (always 1)
|
||||
static bool idaapi can_have_type(const op_t &)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
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(0, pm.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 kr1878_t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
ssize_t idaapi kr1878_t::on_event(ssize_t msgid, va_list va)
|
||||
{
|
||||
int code = 0;
|
||||
switch ( msgid )
|
||||
{
|
||||
case processor_t::ev_init:
|
||||
// __emit__(0xCC); // debugger trap
|
||||
hook_event_listener(HT_IDB, &idb_listener, &LPH);
|
||||
helper.create("$ kr1878");
|
||||
init_analyzer();
|
||||
inf_set_gen_tryblks(true);
|
||||
break;
|
||||
|
||||
case processor_t::ev_term:
|
||||
ports.clear();
|
||||
unhook_event_listener(HT_IDB, &idb_listener);
|
||||
break;
|
||||
|
||||
case processor_t::ev_newfile: // new file loaded
|
||||
{
|
||||
for ( int i=0; i < qnumber(ints); i++ )
|
||||
{
|
||||
ea_t ea = inf_get_min_ea() + ints[i].offset;
|
||||
if ( !is_loaded(ea) )
|
||||
continue;
|
||||
add_entry(ea, ea, ints[i].name, true);
|
||||
}
|
||||
|
||||
segment_t *s0 = get_first_seg();
|
||||
if ( s0 != NULL )
|
||||
{
|
||||
segment_t *s1 = get_next_seg(s0->start_ea);
|
||||
set_segm_name(s0, "CODE");
|
||||
for ( int i = as; i <= vDS; i++ )
|
||||
{
|
||||
set_default_sreg_value(s0, i, BADSEL);
|
||||
set_default_sreg_value(s1, i, BADSEL);
|
||||
}
|
||||
}
|
||||
xmem = AdditionalSegment(0x100, 0, "MEM");
|
||||
}
|
||||
read_kr1878_cfg();
|
||||
break;
|
||||
|
||||
case processor_t::ev_ending_undo:
|
||||
case processor_t::ev_oldfile: // old file loaded
|
||||
xmem = get_start(get_segm_by_name("MEM"));
|
||||
if ( helper.supstr(&device, 0) > 0 )
|
||||
set_device_name(device.c_str());
|
||||
break;
|
||||
|
||||
case processor_t::ev_is_sane_insn:
|
||||
{
|
||||
const insn_t *insn = va_arg(va, insn_t *);
|
||||
int nocrefs = va_arg(va, int);
|
||||
return is_sane_insn(*insn, nocrefs) == 1 ? 1 : -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_may_be_func:
|
||||
// can a function start here?
|
||||
// arg: instruction
|
||||
// returns: probability 0..100
|
||||
{
|
||||
const insn_t *insn = va_arg(va, insn_t *);
|
||||
return may_be_func(*insn);
|
||||
}
|
||||
|
||||
case processor_t::ev_out_header:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
kr1878_header(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_footer:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
kr1878_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 *);
|
||||
kr1878_segstart(*ctx, seg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_segend:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
segment_t *seg = va_arg(va, segment_t *);
|
||||
kr1878_segend(*ctx, seg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_assumes:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
kr1878_assumes(*ctx);
|
||||
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_can_have_type:
|
||||
{
|
||||
const op_t *_op = va_arg(va, const op_t *);
|
||||
return can_have_type(*_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_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 code;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
#define FAMILY "Angstrem KR1878:"
|
||||
static const char *const shnames[] = { "kr1878", NULL };
|
||||
static const char *const lnames[] =
|
||||
{
|
||||
FAMILY"Angstrem KR1878",
|
||||
NULL
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Processor Definition
|
||||
//-----------------------------------------------------------------------
|
||||
processor_t LPH =
|
||||
{
|
||||
IDP_INTERFACE_VERSION, // version
|
||||
PLFM_KR1878, // id
|
||||
// flag
|
||||
PRN_HEX // hex numbers
|
||||
| PR_ALIGN // data items must be aligned
|
||||
| PR_BINMEM // segmentation is done by the processor mode
|
||||
| PR_SEGS, // has segment registers
|
||||
// flag2
|
||||
PR2_IDP_OPTS, // the module has processor-specific configuration options
|
||||
16, // 16 bits in a byte for code segments
|
||||
8, // 8 bits in a byte for other segments
|
||||
|
||||
shnames,
|
||||
lnames,
|
||||
|
||||
asms,
|
||||
|
||||
notify,
|
||||
|
||||
register_names, // Register names
|
||||
qnumber(register_names), // Number of registers
|
||||
|
||||
as, // first
|
||||
vDS, // last
|
||||
1, // size of a segment register
|
||||
vCS, vDS,
|
||||
|
||||
NULL, // No known code start sequences
|
||||
retcodes,
|
||||
|
||||
KR1878_null,
|
||||
KR1878_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
|
||||
KR1878_rts, // Icode of return instruction. It is ok to give any of possible return instructions
|
||||
};
|
||||
Reference in New Issue
Block a user