update to ida 7.6, add builds
This commit is contained in:
532
idasdk76/module/nec850/reg.cpp
Normal file
532
idasdk76/module/nec850/reg.cpp
Normal file
@@ -0,0 +1,532 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) Hex-Rays
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
* Processor description structures
|
||||
*
|
||||
*/
|
||||
#include "necv850.hpp"
|
||||
#include "ins.hpp"
|
||||
#include <loader.hpp>
|
||||
#include <segregs.hpp>
|
||||
|
||||
int data_id;
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void nec850_t::save_all_options()
|
||||
{
|
||||
helper.altset(GP_EA_IDX, ea2node(g_gp_ea));
|
||||
helper.altset(CTBP_EA_IDX, ea2node(g_ctbp_ea));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// read all procmod data from the idb
|
||||
void nec850_t::load_from_idb()
|
||||
{
|
||||
g_gp_ea = node2ea(helper.altval(GP_EA_IDX));
|
||||
g_ctbp_ea = node2ea(helper.altval(CTBP_EA_IDX));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
const char *nec850_t::set_idp_options(
|
||||
const char *keyword,
|
||||
int value_type,
|
||||
const void * value,
|
||||
bool idb_loaded)
|
||||
{
|
||||
if ( keyword != NULL )
|
||||
{
|
||||
if ( streq(keyword, "GP_EA") )
|
||||
{
|
||||
if ( value_type != IDPOPT_NUM )
|
||||
return IDPOPT_BADTYPE;
|
||||
g_gp_ea = *((uval_t *)value);
|
||||
goto SAVE;
|
||||
}
|
||||
if ( streq(keyword, "CTBP_EA") )
|
||||
{
|
||||
if ( value_type != IDPOPT_NUM )
|
||||
return IDPOPT_BADTYPE;
|
||||
g_ctbp_ea = *((uval_t *)value);
|
||||
goto SAVE;
|
||||
}
|
||||
return IDPOPT_BADKEY;
|
||||
}
|
||||
|
||||
static const char form[] =
|
||||
"NEC V850x analyzer options\n"
|
||||
"\n"
|
||||
" <~G~lobal Pointer address:$::18::>\n"
|
||||
" <CALLT ~B~ase pointer :$::18::>\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n";
|
||||
CASSERT(sizeof(g_gp_ea) == sizeof(ea_t));
|
||||
CASSERT(sizeof(g_ctbp_ea) == sizeof(ea_t));
|
||||
if ( ask_form(form, &g_gp_ea, &g_ctbp_ea) == ASKBTN_YES )
|
||||
{
|
||||
SAVE:
|
||||
if ( idb_loaded )
|
||||
save_all_options();
|
||||
}
|
||||
|
||||
return IDPOPT_OK;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static const asm_t nec850_asm =
|
||||
{
|
||||
ASH_HEXF3 | AS_UNEQU | AS_COLON | ASB_BINF4 | AS_N2CHR, // flags
|
||||
0, // user flags
|
||||
"NEC V850 Assembler", // assembler name
|
||||
0, // help
|
||||
NULL, // array of automatically generated header lines
|
||||
".org", // org directive
|
||||
".end", // end directive
|
||||
"--", // comment string
|
||||
'"', // string delimiter
|
||||
'\'', // char delimiter
|
||||
"'\"", // special symbols in char and string constants
|
||||
".str", // ascii string directive
|
||||
".byte", // byte directive
|
||||
".hword", // halfword (16 bits) [IDA: word]
|
||||
".word", // word (32 bits) [IDA: dword]
|
||||
".dword", // doubleword (64 bits) [IDA: qword]
|
||||
NULL, // oword (16 bytes)
|
||||
".float", // float (4-byte)
|
||||
".double", // double (8-byte)
|
||||
NULL, // no tbytes
|
||||
NULL, // no packreal
|
||||
"#d dup(#v)", //".db.#s(b,w) #d,#v"
|
||||
".byte (%s) ?", // uninited data (reserve space) ;?
|
||||
".set", // 'equ' Used if AS_UNEQU is set
|
||||
NULL, // seg prefix
|
||||
"PC", // a_curip
|
||||
NULL, // returns function header line
|
||||
NULL, // returns function footer line
|
||||
".globl", // public
|
||||
NULL, // weak
|
||||
".extern", // extrn
|
||||
".comm", // comm
|
||||
NULL, // get_type_name
|
||||
".align", // align
|
||||
'(', // lbrace
|
||||
')', // rbrace
|
||||
NULL, // mod
|
||||
"&", // bit-and
|
||||
"|", // or
|
||||
"^", // xor
|
||||
"!", // not
|
||||
"<<", // shl
|
||||
">>", // shr
|
||||
NULL, // sizeof
|
||||
0, // flags2
|
||||
NULL, // cmnt2
|
||||
NULL, // low8 operation, should contain %s for the operand
|
||||
NULL, // high8
|
||||
NULL, // low16
|
||||
NULL, // high16
|
||||
".include %s", // a_include_fmt
|
||||
NULL, // if a named item is a structure and displayed
|
||||
NULL // 'rva' keyword for image based offsets
|
||||
};
|
||||
|
||||
static const asm_t *const asms[] = { &nec850_asm, NULL };
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
#define FAMILY "NEC/Renesas 850 series:"
|
||||
|
||||
static const char *const shnames[] =
|
||||
{
|
||||
"V850",
|
||||
"V850E",
|
||||
"V850E1",
|
||||
"V850E2M",
|
||||
"RH850",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *const lnames[] =
|
||||
{
|
||||
FAMILY"NEC V850",
|
||||
"NEC V850E",
|
||||
"NEC/Renesas V850E1/ES",
|
||||
"NEC/Renesas V850E2/E2M",
|
||||
"Renesas RH850",
|
||||
NULL
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list)
|
||||
{
|
||||
switch ( code )
|
||||
{
|
||||
// all options are saved immediately after the change
|
||||
// case idb_event::savebase:
|
||||
|
||||
case idb_event::segm_moved: // A segment is moved
|
||||
// Fix processor dependent address sensitive information
|
||||
// {
|
||||
// ea_t from = va_arg(va, ea_t);
|
||||
// ea_t to = va_arg(va, ea_t);
|
||||
// asize_t size = va_arg(va, asize_t);
|
||||
// bool changed_netmap = va_argi(va, bool);
|
||||
// // adjust gp_ea
|
||||
// }
|
||||
break;
|
||||
|
||||
default:
|
||||
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(SET_MODULE_DATA(nec850_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
ssize_t idaapi nec850_t::on_event(ssize_t msgid, va_list va)
|
||||
{
|
||||
int code = 0;
|
||||
switch ( msgid )
|
||||
{
|
||||
case processor_t::ev_init:
|
||||
helper.create(PROCMOD_NODE_NAME);
|
||||
hook_event_listener(HT_IDB, &idb_listener, &LPH);
|
||||
inf_set_be(false);
|
||||
break;
|
||||
|
||||
case processor_t::ev_term:
|
||||
unhook_event_listener(HT_IDB, &idb_listener);
|
||||
clr_module_data(data_id);
|
||||
break;
|
||||
|
||||
case processor_t::ev_newfile:
|
||||
save_all_options();
|
||||
break;
|
||||
|
||||
case processor_t::ev_newprc:
|
||||
{
|
||||
int procnum = va_arg(va, int);
|
||||
// bool keep_cfg = va_argi(va, bool);
|
||||
ptype = procnum;
|
||||
break;
|
||||
}
|
||||
|
||||
case processor_t::ev_ending_undo:
|
||||
// restore ptype
|
||||
ptype = ph.get_proc_index();
|
||||
//fall through
|
||||
case processor_t::ev_oldfile:
|
||||
load_from_idb();
|
||||
break;
|
||||
|
||||
case processor_t::ev_creating_segm:
|
||||
{
|
||||
segment_t *s = va_arg(va, segment_t *);
|
||||
// Set default value of DS register for all segments
|
||||
set_default_dataseg(s->sel);
|
||||
}
|
||||
break;
|
||||
|
||||
case processor_t::ev_is_sane_insn:
|
||||
{
|
||||
const insn_t &insn = *va_arg(va, insn_t *);
|
||||
int no_crefs = va_arg(va, int);
|
||||
code = nec850_is_sane_insn(insn, no_crefs) == 1 ? 1 : -1;
|
||||
break;
|
||||
}
|
||||
|
||||
case processor_t::ev_may_be_func:
|
||||
{
|
||||
const insn_t &insn = *va_arg(va, insn_t *);
|
||||
code = nec850_may_be_func(insn);
|
||||
}
|
||||
break;
|
||||
|
||||
case processor_t::ev_is_ret_insn:
|
||||
{
|
||||
const insn_t &insn = *va_arg(va, insn_t *);
|
||||
bool strict = va_argi(va, bool);
|
||||
code = nec850_is_return(insn, strict) ? 1 : -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case processor_t::ev_out_header:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
nec850_header(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_footer:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
nec850_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 *);
|
||||
nec850_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 *);
|
||||
nec850_segend(*ctx, seg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_ana_insn:
|
||||
{
|
||||
insn_t *out = va_arg(va, insn_t *);
|
||||
return nec850_ana(out);
|
||||
}
|
||||
|
||||
case processor_t::ev_emu_insn:
|
||||
{
|
||||
const insn_t *insn = va_arg(va, const insn_t *);
|
||||
return nec850_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_switch:
|
||||
{
|
||||
switch_info_t *si = va_arg(va, switch_info_t *);
|
||||
const insn_t *insn = va_arg(va, const insn_t *);
|
||||
return nec850_is_switch(si, *insn) ? 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 = nec850_is_sp_based(*insn, *op);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_create_func_frame:
|
||||
{
|
||||
func_t *pfn = va_arg(va, func_t *);
|
||||
nec850_create_func_frame(pfn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_get_frame_retsize:
|
||||
{
|
||||
int *frsize = va_arg(va, int *);
|
||||
const func_t *pfn = va_arg(va, const func_t *);
|
||||
*frsize = nec850_get_frame_retsize(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;
|
||||
}
|
||||
|
||||
|
||||
// START OF DEBUGGER CALLBACKS
|
||||
case processor_t::ev_next_exec_insn:
|
||||
{
|
||||
ea_t *target = va_arg(va, ea_t *);
|
||||
ea_t ea = va_arg(va, ea_t);
|
||||
int tid = va_arg(va, int);
|
||||
getreg_t *getreg = va_arg(va, getreg_t *);
|
||||
const regval_t *regvalues = va_arg(va, const regval_t *);
|
||||
qnotused(tid);
|
||||
*target = nec850_next_exec_insn(ea, getreg, regvalues);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_calc_step_over:
|
||||
{
|
||||
ea_t *target = va_arg(va, ea_t *);
|
||||
ea_t ip = va_arg(va, ea_t);
|
||||
*target = nec850_calc_step_over(ip);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_get_idd_opinfo:
|
||||
{
|
||||
idd_opinfo_t *opinf = va_arg(va, idd_opinfo_t *);
|
||||
ea_t ea = va_arg(va, ea_t);
|
||||
int n = va_arg(va, int);
|
||||
int thread_id = va_arg(va, int);
|
||||
getreg_t *getreg = va_arg(va, getreg_t *);
|
||||
const regval_t *regvalues = va_arg(va, const regval_t *);
|
||||
qnotused(thread_id);
|
||||
return nec850_get_operand_info(opinf, ea, n, getreg, regvalues) ? 1 : 0;
|
||||
}
|
||||
|
||||
case processor_t::ev_get_reg_info:
|
||||
{
|
||||
const char **main_regname = va_arg(va, const char **);
|
||||
bitrange_t *bitrange = va_arg(va, bitrange_t *);
|
||||
const char *regname = va_arg(va, const char *);
|
||||
return nec850_get_reg_info(main_regname, bitrange, regname) ? 1 : -1;
|
||||
}
|
||||
// END OF DEBUGGER CALLBACKS
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Registers Definition
|
||||
//-----------------------------------------------------------------------
|
||||
const char *const RegNames[rLastRegister] =
|
||||
{
|
||||
"r0",
|
||||
"r1",
|
||||
"r2",
|
||||
"sp",
|
||||
"gp",
|
||||
"r5", // text pointer - tp
|
||||
"r6",
|
||||
"r7",
|
||||
"r8",
|
||||
"r9",
|
||||
"r10",
|
||||
"r11",
|
||||
"r12",
|
||||
"r13",
|
||||
"r14",
|
||||
"r15",
|
||||
"r16",
|
||||
"r17",
|
||||
"r18",
|
||||
"r19",
|
||||
"r20",
|
||||
"r21",
|
||||
"r22",
|
||||
"r23",
|
||||
"r24",
|
||||
"r25",
|
||||
"r26",
|
||||
"r27",
|
||||
"r28",
|
||||
"r29",
|
||||
"ep",
|
||||
"lp",
|
||||
// system registers start here
|
||||
"eipc",
|
||||
"eipsw",
|
||||
"fepc",
|
||||
"fepsw",
|
||||
"ecr",
|
||||
"psw",
|
||||
"sr6",
|
||||
"sr7",
|
||||
"sr8",
|
||||
"sr9",
|
||||
"sr10",
|
||||
"sr11",
|
||||
"sr12",
|
||||
"sr13",
|
||||
"sr14",
|
||||
"sr15",
|
||||
"sr16",
|
||||
"sr17",
|
||||
"sr18",
|
||||
"sr19",
|
||||
"sr20",
|
||||
"sr21",
|
||||
"sr22",
|
||||
"sr23",
|
||||
"sr24",
|
||||
"sr25",
|
||||
"sr26",
|
||||
"sr27",
|
||||
"sr28",
|
||||
"sr29",
|
||||
"sr30",
|
||||
"sr31",
|
||||
|
||||
"EFG", "ECT",
|
||||
|
||||
//
|
||||
"ep", "cs", "ds"
|
||||
};
|
||||
CASSERT(qnumber(RegNames) == rLastRegister);
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Processor Definition
|
||||
//-----------------------------------------------------------------------
|
||||
processor_t LPH =
|
||||
{
|
||||
IDP_INTERFACE_VERSION, // version
|
||||
PLFM_NEC_V850X, // id
|
||||
// flag
|
||||
PR_DEFSEG32
|
||||
| PR_USE32
|
||||
| PRN_HEX
|
||||
| PR_RNAMESOK,
|
||||
// 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, // short processor names
|
||||
lnames, // long processor names
|
||||
|
||||
asms, // assemblers
|
||||
|
||||
notify,
|
||||
|
||||
RegNames, // Regsiter names
|
||||
rLastRegister, // Number of registers
|
||||
|
||||
rVcs/*rVep*/, // number of first segment register
|
||||
rVds/*rVcs*/, // number of last segment register
|
||||
0 /*4*/, // size of a segment register
|
||||
rVcs,
|
||||
rVds,
|
||||
NULL, // No known code start sequences
|
||||
NULL, // Array of 'return' instruction opcodes
|
||||
NEC850_NULL,
|
||||
NEC850_LAST_INSTRUCTION,
|
||||
Instructions, // instruc
|
||||
0, // size of tbyte
|
||||
{0,7,15,0}, // real width
|
||||
0, // icode_return
|
||||
NULL, // Micro virtual machine description
|
||||
};
|
||||
Reference in New Issue
Block a user