update to ida 7.6, add builds
This commit is contained in:
1334
idasdk76/module/hppa/ana.cpp
Normal file
1334
idasdk76/module/hppa/ana.cpp
Normal file
File diff suppressed because it is too large
Load Diff
979
idasdk76/module/hppa/emu.cpp
Normal file
979
idasdk76/module/hppa/emu.cpp
Normal file
@@ -0,0 +1,979 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hppa.hpp"
|
||||
#include <frame.hpp>
|
||||
#include <struct.hpp>
|
||||
#include <typeinf.hpp>
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// map virtual to physical ea
|
||||
ea_t calc_mem(ea_t ea)
|
||||
{
|
||||
return ea;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
ea_t hppa_t::get_dp(const insn_t &insn) const
|
||||
{
|
||||
if ( got == BADADDR )
|
||||
return BADADDR;
|
||||
sel_t delta = get_sreg(insn.ea, DPSEG);
|
||||
if ( delta == BADSEL )
|
||||
return BADADDR;
|
||||
// calculate the return value
|
||||
// if we don't do it in a separate statement, bcb6 generates
|
||||
// wrong code with __EA64__
|
||||
ea_t dp = got + delta;
|
||||
return dp;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// returns:
|
||||
// -1: doesn't spoil anything
|
||||
// -2: spoils everything
|
||||
// >=0: the number of the register which is spoiled
|
||||
static int spoils(const insn_t &insn, const uint32 *regs, int n)
|
||||
{
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case HPPA_call:
|
||||
case HPPA_blr:
|
||||
for ( int i=0; i < n; i++ )
|
||||
if ( regs[i] >= 23 && regs[i] != DP ) // assume the first 8 registers are not spoiled
|
||||
return i; // dp is never spoiled
|
||||
}
|
||||
return get_spoiled_reg(insn, regs, n);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool find_addil_or_ldil(ea_t ea, uint32 r, ea_t dp, uval_t *pv)
|
||||
{
|
||||
uval_t v;
|
||||
insn_t insn;
|
||||
func_item_iterator_t fii(get_func(ea), ea);
|
||||
while ( fii.decode_prev_insn(&insn) )
|
||||
{
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case HPPA_addil:
|
||||
if ( insn.Op3.reg == r )
|
||||
{
|
||||
if ( insn.Op2.reg == R0 )
|
||||
{
|
||||
v = insn.Op1.value;
|
||||
RETTRUE:
|
||||
*pv = v;
|
||||
return true;
|
||||
}
|
||||
if ( insn.Op2.reg == DP )
|
||||
{
|
||||
v = dp + insn.Op1.value;
|
||||
goto RETTRUE;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
case HPPA_ldil:
|
||||
if ( insn.Op2.reg == r )
|
||||
{
|
||||
v = insn.Op1.value;
|
||||
goto RETTRUE;
|
||||
}
|
||||
case HPPA_copy:
|
||||
if ( insn.Op2.reg == r )
|
||||
{
|
||||
r = insn.Op1.reg;
|
||||
if ( r == R0 )
|
||||
{
|
||||
v = 0;
|
||||
goto RETTRUE;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ( spoils(insn, &r, 1) != -1 )
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// addil -0x2800, %dp, %r1
|
||||
// stw %r5, 0x764(%sr0,%r1)
|
||||
ea_t hppa_t::calc_possible_memref(const insn_t &insn, const op_t &x)
|
||||
{
|
||||
ea_t dp = get_dp(insn);
|
||||
if ( dp != BADADDR )
|
||||
{
|
||||
if ( x.phrase == DP )
|
||||
{
|
||||
dp += x.addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
int r = x.phrase;
|
||||
uval_t v = x.addr;
|
||||
uval_t v2 = 0;
|
||||
if ( find_addil_or_ldil(insn.ea, r, dp, &v2) )
|
||||
{
|
||||
dp = v + v2;
|
||||
}
|
||||
else
|
||||
dp = BADADDR;
|
||||
}
|
||||
}
|
||||
return dp;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool is_stkreg(int r)
|
||||
{
|
||||
return r == SP;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
int idaapi is_sp_based(const insn_t &/*insn*/, const op_t &x)
|
||||
{
|
||||
return OP_SP_ADD | (is_stkreg(x.phrase) ? OP_SP_BASED : OP_FP_BASED);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// is the register the frame pointer?
|
||||
bool hppa_t::is_frreg(const insn_t &insn, int reg)
|
||||
{
|
||||
if ( reg != 0 )
|
||||
{
|
||||
func_t *pfn = get_func(insn.ea);
|
||||
if ( pfn != NULL )
|
||||
{
|
||||
ea_t ea = pfn->start_ea;
|
||||
if ( ea != oldea )
|
||||
{
|
||||
oldea = ea;
|
||||
oldreg = helper.altval_ea(oldea);
|
||||
}
|
||||
return reg == oldreg;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline bool stldwm(const insn_t &insn)
|
||||
{
|
||||
return insn.itype == HPPA_ldo && insn.Op2.reg == SP // ldo .., %sp
|
||||
|| (opcode(get_dword(insn.ea)) & 0x13) == 0x13; // st/ldw,m
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
inline void remove_unwanted_typeinfo(const insn_t &insn, int n)
|
||||
{
|
||||
if ( is_defarg(get_flags(insn.ea), n) )
|
||||
clr_op_type(insn.ea, n);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
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 HPPA_depd:
|
||||
case HPPA_depw:
|
||||
case HPPA_extrd:
|
||||
case HPPA_extrw:
|
||||
case HPPA_hshl:
|
||||
case HPPA_hshladd:
|
||||
case HPPA_hshr:
|
||||
case HPPA_hshradd:
|
||||
case HPPA_shladd:
|
||||
case HPPA_shrpd:
|
||||
case HPPA_shrpw:
|
||||
case HPPA_shrd:
|
||||
case HPPA_shrw:
|
||||
case HPPA_shld:
|
||||
case HPPA_shlw:
|
||||
op_dec(insn.ea, n);
|
||||
break;
|
||||
case HPPA_depdi:
|
||||
case HPPA_depwi:
|
||||
if ( n == 0 )
|
||||
op_num(insn.ea, n);
|
||||
else
|
||||
op_dec(insn.ea, n);
|
||||
break;
|
||||
case HPPA_popbts:
|
||||
case HPPA_rsm:
|
||||
case HPPA_ssm:
|
||||
op_num(insn.ea, n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
enum nullicode_t { NEVER, SKIP, NULLIFY };
|
||||
static nullicode_t may_skip_next_insn(ea_t ea)
|
||||
{
|
||||
nullicode_t may = NEVER;
|
||||
insn_t insn;
|
||||
if ( decode_insn(&insn, ea) > 0 )
|
||||
{
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case HPPA_pmdis: // format 55
|
||||
case HPPA_spop0: // format 34
|
||||
case HPPA_spop1: // format 35
|
||||
case HPPA_spop2: // format 36
|
||||
case HPPA_spop3: // format 37
|
||||
case HPPA_copr: // format 38
|
||||
may = (get_dword(ea) & BIT26) != 0 ? SKIP : NEVER;
|
||||
break;
|
||||
case HPPA_addb: // format 17
|
||||
case HPPA_addib:
|
||||
case HPPA_cmpb:
|
||||
case HPPA_cmpib:
|
||||
case HPPA_movb:
|
||||
case HPPA_movib:
|
||||
case HPPA_bb: // format 18
|
||||
case HPPA_be: // format 19
|
||||
case HPPA_b: // format 20
|
||||
case HPPA_blr: // format 21
|
||||
case HPPA_bv:
|
||||
case HPPA_call: // pseudo-op
|
||||
case HPPA_bve: // format 22
|
||||
case HPPA_ret: // pseudo-op
|
||||
may = ((get_dword(ea) & BIT30) != 0) ? NULLIFY : NEVER;
|
||||
break;
|
||||
default:
|
||||
may = (insn.auxpref & aux_cndc) != 0 ? SKIP : NEVER;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return may;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool is_cond_branch(uint32 code)
|
||||
{
|
||||
switch ( opcode(code) )
|
||||
{
|
||||
case 0x20: // cmpb
|
||||
case 0x22: // cmpb
|
||||
case 0x27: // cmpb
|
||||
case 0x2F: // cmpb
|
||||
case 0x28: // addb
|
||||
case 0x2A: // addb
|
||||
case 0x32: // movb
|
||||
case 0x21: // cmpib
|
||||
case 0x23: // cmpib
|
||||
case 0x3B: // cmpib
|
||||
case 0x29: // addib
|
||||
case 0x2B: // addib
|
||||
case 0x33: // movib
|
||||
case 0x30: // bb
|
||||
case 0x31: // bb
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool is_uncond_branch(uint32 code)
|
||||
{
|
||||
int sub;
|
||||
switch ( opcode(code) )
|
||||
{
|
||||
case 0x38: // be
|
||||
return true;
|
||||
case 0x3A:
|
||||
sub = (code>>13) & 7;
|
||||
switch ( sub )
|
||||
{
|
||||
case 0: // b,l
|
||||
case 1: // b,gate
|
||||
case 2: // blr
|
||||
return r06(code) == R0;
|
||||
case 6: // bv/bve
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case 0x22: // cmpb
|
||||
case 0x23: // cmpib
|
||||
case 0x2F: // cmpb
|
||||
case 0x2A: // addb
|
||||
case 0x2B: // addib
|
||||
return ((code>>13) & 7) == 0;
|
||||
case 0x32: // movb
|
||||
case 0x33: // movib
|
||||
return ((code>>13) & 7) == 4;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool is_call_branch(uint32 code)
|
||||
{
|
||||
int sub;
|
||||
switch ( opcode(code) )
|
||||
{
|
||||
case 0x39: // be,l
|
||||
return true;
|
||||
case 0x3A:
|
||||
sub = (code>>13) & 7;
|
||||
switch ( sub )
|
||||
{
|
||||
case 0: // b,l
|
||||
case 1: // b,gate
|
||||
case 2: // blr
|
||||
return r06(code) != R0;
|
||||
case 4: // b,l,push
|
||||
case 5: // b,l
|
||||
case 7: // bve,l
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static nullicode_t may_be_skipped(ea_t ea)
|
||||
{
|
||||
if ( !is_flow(get_flags(ea)) )
|
||||
return NEVER;
|
||||
return may_skip_next_insn(ea-4);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static ea_t calc_branch_target(ea_t ea)
|
||||
{
|
||||
ea_t res = BADADDR;
|
||||
insn_t insn;
|
||||
if ( decode_insn(&insn, ea) > 0 )
|
||||
{
|
||||
for ( int i=0; i < UA_MAXOP; i++ )
|
||||
{
|
||||
if ( insn.ops[i].type == o_near )
|
||||
{
|
||||
res = insn.ops[i].addr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline bool is_stop(uint32 code, bool include_calls_and_conds)
|
||||
{
|
||||
return is_uncond_branch(code)
|
||||
|| include_calls_and_conds
|
||||
&& (is_cond_branch(code) || is_call_branch(code));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// does the specified address have a delay slot?
|
||||
static bool has_delay_slot(ea_t ea, bool include_calls_and_conds)
|
||||
{
|
||||
if ( (include_calls_and_conds || may_be_skipped(ea) != SKIP)
|
||||
&& calc_branch_target(ea) != ea+4 )
|
||||
{
|
||||
uint32 code = get_dword(ea);
|
||||
return is_stop(code, include_calls_and_conds) && (code & BIT30) == 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// is the current insruction in a delay slot?
|
||||
static bool is_delayed_stop(const insn_t &insn, bool include_calls_and_conds)
|
||||
{
|
||||
uint32 code = get_dword(insn.ea);
|
||||
if ( (code & BIT30) != 0 // ,n
|
||||
&& is_stop(code, include_calls_and_conds)
|
||||
&& (include_calls_and_conds || may_be_skipped(insn.ea) != SKIP) )
|
||||
{
|
||||
// seems to be a branch which nullifies the next instruction
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( !is_flow(get_flags(insn.ea)) )
|
||||
return false;
|
||||
|
||||
return has_delay_slot(insn.ea-4, include_calls_and_conds);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void hppa_t::add_near_ref(const insn_t &insn, const op_t &x, ea_t ea)
|
||||
{
|
||||
cref_t ftype = fl_JN;
|
||||
if ( is_call_branch(get_dword(insn.ea)) )
|
||||
ftype = fl_CN;
|
||||
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);
|
||||
if ( ftype == fl_CN )
|
||||
auto_apply_type(insn.ea, ea);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline dref_t calc_dref_type(const insn_t &insn, bool isload)
|
||||
{
|
||||
if ( insn.itype == HPPA_ldo )
|
||||
return dr_O;
|
||||
return isload ? dr_R : dr_W;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool create_lvar(const insn_t &insn, const op_t &x, uval_t v)
|
||||
{
|
||||
struct lvar_info_t
|
||||
{
|
||||
int delta;
|
||||
const char *name; //lint !e958 padding is required to align members
|
||||
};
|
||||
static const lvar_info_t linfo[] =
|
||||
{
|
||||
{ -4, "prev_sp" },
|
||||
{ -8, "rs_rp" }, // RP'' (relocation stub RP)
|
||||
{ -12, "cleanup" },
|
||||
{ -16, "static_link" },
|
||||
{ -20, "cur_rp" },
|
||||
{ -24, "es_rp" }, // RP' (external/stub RP)
|
||||
{ -28, "LPT_" }, // (external SR4/LT pointer)
|
||||
{ -32, "LPT" }, // (external Data/LT pointer)
|
||||
};
|
||||
|
||||
func_t *pfn = get_func(insn.ea);
|
||||
if ( pfn == NULL )
|
||||
return false;
|
||||
|
||||
sval_t delta;
|
||||
member_t *mptr = get_stkvar(&delta, insn, x, v);
|
||||
if ( mptr == NULL )
|
||||
{
|
||||
if ( !insn.create_stkvar(x, v, STKVAR_VALID_SIZE) )
|
||||
return false;
|
||||
mptr = get_stkvar(&delta, insn, x, v);
|
||||
if ( mptr == NULL )
|
||||
return false; // should not happen but better check
|
||||
delta -= pfn->argsize;
|
||||
// delta contains real offset from SP
|
||||
for ( size_t i=0; i < qnumber(linfo); i++ )
|
||||
{
|
||||
if ( delta == linfo[i].delta )
|
||||
{
|
||||
set_member_name(get_frame(pfn), delta+pfn->argsize, linfo[i].name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( delta <= -0x34 ) // seems to be an argument in the stack
|
||||
{ // this means that the current function
|
||||
// has at least 4 register arguments
|
||||
pfn = get_func(insn.ea);
|
||||
while ( pfn->regargqty < 4 )
|
||||
add_regarg(pfn, R26-pfn->regargqty, tinfo_t(BT_INT), NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return op_stkvar(insn.ea, x.n);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// recognize the following code:
|
||||
// 20 20 08 01 ldil -0x40000000, %r1
|
||||
// E4 20 E0 08 be,l 4(%sr7,%r1), %sr0, %r31 # C0000004
|
||||
// followed by:
|
||||
// ldi NNN, %r22
|
||||
// as a system call number NNN.
|
||||
// return -1 if not found
|
||||
static int get_syscall_number(ea_t ea)
|
||||
{
|
||||
int syscall = -1;
|
||||
if ( get_dword(ea) == 0x20200801
|
||||
&& get_dword(ea+4) == 0xE420E008 )
|
||||
{
|
||||
insn_t l;
|
||||
decode_insn(&l, ea+8);
|
||||
if ( l.itype == HPPA_ldi && l.Op2.reg == R22 )
|
||||
syscall = (int)l.Op1.value;
|
||||
}
|
||||
return syscall;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void hppa_t::process_operand(const insn_t &insn, const op_t &x, bool isAlt, bool isload)
|
||||
{
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_reg:
|
||||
/* if ( x.reg == GP
|
||||
&& insn.itype != ALPHA_lda
|
||||
&& insn.itype != ALPHA_ldah
|
||||
&& insn.itype != ALPHA_br
|
||||
&& !isload ) split_srarea(insn.ea+insn.size, GPSEG, BADSEL, SR_auto);*/
|
||||
break;
|
||||
default:
|
||||
if ( insn.itype == HPPA_fcmp
|
||||
|| insn.itype == HPPA_b
|
||||
|| insn.itype == HPPA_ftest )
|
||||
{
|
||||
return;
|
||||
}
|
||||
interr(insn, "emu");
|
||||
break;
|
||||
case o_based: // (%r5)
|
||||
break;
|
||||
case o_imm:
|
||||
process_immediate_number(insn, x.n);
|
||||
if ( op_adds_xrefs(get_flags(insn.ea), x.n) )
|
||||
insn.add_off_drefs(x, dr_O, OOF_SIGNED);
|
||||
break;
|
||||
case o_displ:
|
||||
process_immediate_number(insn, x.n);
|
||||
if ( is_stkreg(x.reg) || is_frreg(insn, x.reg) )
|
||||
{
|
||||
if ( may_create_stkvars() && !is_defarg(get_flags(insn.ea), x.n) )
|
||||
{
|
||||
if ( stldwm(insn) )
|
||||
op_num(insn.ea, -1);
|
||||
else
|
||||
create_lvar(insn, x, x.addr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ea_t ea = calc_possible_memref(insn, x);
|
||||
if ( ea != BADADDR )
|
||||
{
|
||||
if ( insn.itype == HPPA_be )
|
||||
add_near_ref(insn, x, ea);
|
||||
else
|
||||
insn.add_dref(ea, x.offb, calc_dref_type(insn, isload));
|
||||
insn.create_op_data(ea, x);
|
||||
if ( isload )
|
||||
{
|
||||
ea_t ea2 = get_dword(ea);
|
||||
if ( is_mapped(ea2) )
|
||||
insn.add_dref(ea2, x.offb, dr_O);
|
||||
}
|
||||
}
|
||||
}
|
||||
// no break
|
||||
case o_phrase:
|
||||
if ( isAlt )
|
||||
break;
|
||||
if ( op_adds_xrefs(get_flags(insn.ea), x.n) )
|
||||
{
|
||||
ea_t ea = insn.add_off_drefs(x, isload ? dr_R : dr_W, OOF_SIGNED|OOF_ADDR);
|
||||
if ( ea != BADADDR )
|
||||
insn.create_op_data(ea, x);
|
||||
}
|
||||
break;
|
||||
case o_near:
|
||||
add_near_ref(insn, x, calc_mem(x.addr));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool add_stkpnt(const insn_t &insn, sval_t delta)
|
||||
{
|
||||
func_t *pfn = get_func(insn.ea);
|
||||
if ( pfn == NULL )
|
||||
return false;
|
||||
|
||||
return add_auto_stkpnt(pfn, insn.ea+insn.size, delta);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void hppa_t::trace_sp(const insn_t &insn)
|
||||
{
|
||||
switch ( insn.itype )
|
||||
{
|
||||
// stw,m %r3, 0x80(%sr0,%sp)
|
||||
case HPPA_stw:
|
||||
if ( opcode(get_dword(insn.ea)) == 0x1B // stw,m
|
||||
&& is_stkreg(insn.Op2.reg) )
|
||||
{
|
||||
add_stkpnt(insn, insn.Op2.addr);
|
||||
}
|
||||
break;
|
||||
// ldw,m -0x80(%sr0,%sp), %r3
|
||||
case HPPA_ldw:
|
||||
if ( opcode(get_dword(insn.ea)) == 0x13 // ldw,m
|
||||
&& is_stkreg(insn.Op1.reg) )
|
||||
{
|
||||
add_stkpnt(insn, insn.Op1.addr);
|
||||
}
|
||||
break;
|
||||
case HPPA_ldo:
|
||||
if ( is_stkreg(insn.Op2.reg) )
|
||||
{
|
||||
// ldo -0x80(%sp), %sp
|
||||
if ( is_stkreg(insn.Op1.reg) )
|
||||
{
|
||||
add_stkpnt(insn, insn.Op1.addr);
|
||||
}
|
||||
else if ( is_frreg(insn, insn.Op1.reg) )
|
||||
{
|
||||
// analog of the 'leave' instruction
|
||||
// (restores the original value of sp + optional delta
|
||||
// using the frame pointer register)
|
||||
// ldo 4(%r4), %sp
|
||||
func_t *pfn = get_func(insn.ea);
|
||||
if ( pfn != NULL )
|
||||
{
|
||||
sval_t delta = insn.Op1.addr + pfn->frregs - get_spd(pfn,insn.ea);
|
||||
add_stkpnt(insn, -delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
int hppa_t::emu(const insn_t &insn)
|
||||
{
|
||||
|
||||
if ( segtype(insn.ea) == SEG_XTRN )
|
||||
return 1;
|
||||
|
||||
uint32 Feature = insn.get_canon_feature(ph);
|
||||
flow = ((Feature & CF_STOP) == 0);
|
||||
|
||||
int i;
|
||||
for ( i=0; i < PROC_MAXOP; i++ )
|
||||
if ( has_cf_use(Feature, i) )
|
||||
process_operand(insn, insn.ops[i], is_forced_operand(insn.ea, i), true);
|
||||
|
||||
for ( i=0; i < PROC_MAXOP; i++ )
|
||||
if ( has_cf_chg(Feature, i) )
|
||||
process_operand(insn, insn.ops[i], is_forced_operand(insn.ea, i), false);
|
||||
|
||||
//
|
||||
// Determine if the next instruction should be executed
|
||||
//
|
||||
if ( Feature & CF_STOP )
|
||||
flow = false;
|
||||
if ( is_delayed_stop(insn, false) )
|
||||
flow = false;
|
||||
if ( flow )
|
||||
add_cref(insn.ea, insn.ea+insn.size,fl_F);
|
||||
|
||||
//
|
||||
// Handle SP modifications
|
||||
//
|
||||
if ( may_trace_sp() )
|
||||
{
|
||||
if ( !flow )
|
||||
recalc_spd(insn.ea); // recalculate SP register for the next insn
|
||||
else
|
||||
trace_sp(insn);
|
||||
}
|
||||
|
||||
// Handle system calls
|
||||
if ( insn.itype == HPPA_ldi && !has_cmt(get_flags(insn.ea)) )
|
||||
{
|
||||
int syscall = get_syscall_number(insn.ea-8);
|
||||
if ( syscall >= 0 )
|
||||
{
|
||||
const char *syscall_name = get_syscall_name(syscall);
|
||||
if ( syscall_name != NULL )
|
||||
{
|
||||
append_cmt(insn.ea, syscall_name, false);
|
||||
flags_t F = get_flags(insn.ea-8);
|
||||
if ( has_xref(F) && !has_user_name(F) )
|
||||
set_name(insn.ea-8, syscall_name, SN_NOCHECK|SN_NOWARN|SN_NODUMMY);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int may_be_func(const insn_t &/*insn*/) // can a function start here?
|
||||
// returns: probability 0..100
|
||||
{
|
||||
// ldah $gp, 0x2000($27)
|
||||
// if ( insn.itype == ALPHA_ldah && insn.Op1.reg == GP )
|
||||
// return 100;
|
||||
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.Op1.addr)) )
|
||||
return 0;
|
||||
// don't disassemble 0 as break 0,0 automatically
|
||||
if ( insn.itype == HPPA_break && get_dword(insn.ea) == 0 )
|
||||
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 HPPA_break:
|
||||
if ( get_dword(insn.ea) )
|
||||
return 0;
|
||||
break;
|
||||
case HPPA_nop:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return insn.size;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int idaapi hppa_get_frame_retsize(const func_t *)
|
||||
{
|
||||
return 0; // ALPHA doesn't use stack for function return addresses
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//lint -e{818} could be declared as pointing to const
|
||||
bool hppa_t::create_func_frame(func_t *pfn)
|
||||
{
|
||||
ea_t ea = pfn->start_ea;
|
||||
int frame_reg = 0;
|
||||
for ( int i=0; i < 16; i++ )
|
||||
{
|
||||
insn_t insn;
|
||||
decode_insn(&insn, ea);
|
||||
if ( insn.itype == HPPA_copy && is_stkreg(insn.Op1.reg) )
|
||||
frame_reg = insn.Op2.reg;
|
||||
if ( opcode(get_dword(ea)) == 0x1B ) // stw,m
|
||||
{
|
||||
if ( frame_reg != 0 )
|
||||
helper.altset_ea(pfn->start_ea, frame_reg);
|
||||
// return true;//add_frame(pfn, 0, 0, 0);
|
||||
return add_frame(pfn, insn.Op2.addr, 0, 0);
|
||||
}
|
||||
ea += 4;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool is_basic_block_end(const insn_t &insn)
|
||||
{
|
||||
if ( is_delayed_stop(insn, true) )
|
||||
return true;
|
||||
return !is_flow(get_flags(insn.ea+insn.size));
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
bool calc_hppa_arglocs(func_type_data_t *fti)
|
||||
{
|
||||
int r = 0;
|
||||
int n = fti->size();
|
||||
for ( int i=0; i < n; i++ )
|
||||
{
|
||||
funcarg_t &fa = fti->at(i);
|
||||
size_t a = fa.type.get_size();
|
||||
if ( a == BADSIZE )
|
||||
return false;
|
||||
a = align_up(a, inf_get_cc_size_i());
|
||||
if ( r < 4 ) // first 4 arguments are in %r26, 25, 24, 23
|
||||
fa.argloc.set_reg1(26 - r);
|
||||
else
|
||||
fa.argloc.set_stkoff(0x24 + r * 4);
|
||||
r += int(a / 4);
|
||||
}
|
||||
fti->stkargs = r < 4 ? 0 : 0x24 + r * 4;
|
||||
return true;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static bool hppa_set_op_type(
|
||||
const insn_t &insn,
|
||||
const op_t &x,
|
||||
const tinfo_t &tif,
|
||||
const char *name,
|
||||
eavec_t &visited)
|
||||
{
|
||||
tinfo_t type = tif;
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_imm:
|
||||
if ( type.is_ptr()
|
||||
&& x.value != 0
|
||||
&& !is_defarg(get_flags(insn.ea), x.n) )
|
||||
{
|
||||
return op_plain_offset(insn.ea, x.n, 0);
|
||||
}
|
||||
break;
|
||||
case o_mem:
|
||||
{
|
||||
ea_t dea = calc_mem(x.addr);
|
||||
return apply_once_tinfo_and_name(dea, type, name);
|
||||
}
|
||||
case o_displ:
|
||||
return apply_tinfo_to_stkarg(insn, x, x.addr, type, name);
|
||||
case o_reg:
|
||||
{
|
||||
uint32 r = x.reg;
|
||||
func_t *pfn = get_func(insn.ea);
|
||||
if ( pfn == NULL )
|
||||
return false;
|
||||
bool ok;
|
||||
bool farref;
|
||||
func_item_iterator_t fii;
|
||||
insn_t l;
|
||||
for ( ok=fii.set(pfn, insn.ea);
|
||||
ok && (ok=fii.decode_preceding_insn(&visited, &farref, &l)) != false;
|
||||
)
|
||||
{
|
||||
if ( visited.size() > 4096 )
|
||||
break; // decoded enough of it, abandon
|
||||
if ( farref )
|
||||
continue;
|
||||
switch ( l.itype )
|
||||
{
|
||||
case HPPA_ldo:
|
||||
if ( l.Op2.reg != r )
|
||||
continue;
|
||||
remove_tinfo_pointer(&type, &name);
|
||||
// no break
|
||||
case HPPA_copy:
|
||||
case HPPA_ldw:
|
||||
case HPPA_ldi:
|
||||
case HPPA_ldil:
|
||||
if ( l.Op2.reg != r )
|
||||
continue;
|
||||
return hppa_set_op_type(l, l.Op1, type, name, visited);
|
||||
default:
|
||||
{
|
||||
int code = spoils(insn, &r, 1);
|
||||
if ( code == -1 )
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ( !ok && l.ea == pfn->start_ea )
|
||||
{ // reached the function start, this looks like a register argument
|
||||
add_regarg(pfn, r, type, name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
inline bool set_op_type(
|
||||
const insn_t &insn,
|
||||
const op_t &x,
|
||||
const tinfo_t &type,
|
||||
const char *name)
|
||||
{
|
||||
eavec_t visited;
|
||||
return hppa_set_op_type(insn, x, type, name, visited);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
int use_hppa_regarg_type(ea_t ea, const funcargvec_t &rargs)
|
||||
{
|
||||
insn_t insn;
|
||||
int idx = -1;
|
||||
if ( decode_insn(&insn, ea) > 0 )
|
||||
{
|
||||
qvector<uint32> regs;
|
||||
int n = rargs.size();
|
||||
regs.resize(n);
|
||||
for ( int i=0; i < n; i++ )
|
||||
regs[i] = rargs[i].argloc.reg1();
|
||||
|
||||
idx = spoils(insn, regs.begin(), n);
|
||||
if ( idx >= 0 )
|
||||
{
|
||||
tinfo_t type = rargs[idx].type;
|
||||
const char *name = rargs[idx].name.begin();
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case HPPA_ldo:
|
||||
remove_tinfo_pointer(&type, &name);
|
||||
// no break
|
||||
case HPPA_copy:
|
||||
case HPPA_ldw:
|
||||
case HPPA_ldi:
|
||||
case HPPA_ldil:
|
||||
set_op_type(insn, insn.Op1, type, name);
|
||||
case HPPA_depw:
|
||||
case HPPA_depwi:
|
||||
case HPPA_depd:
|
||||
case HPPA_depdi:
|
||||
case HPPA_extrw:
|
||||
case HPPA_extrd:
|
||||
break;
|
||||
default: // unknown instruction changed the register, stop tracing it
|
||||
idx |= REG_SPOIL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
struct hppa_argtinfo_helper_t : public argtinfo_helper_t
|
||||
{
|
||||
bool idaapi set_op_tinfo(
|
||||
const insn_t &_insn,
|
||||
const op_t &x,
|
||||
const tinfo_t &tif,
|
||||
const char *name) override
|
||||
{
|
||||
return set_op_type(_insn, x, tif, name);
|
||||
}
|
||||
|
||||
// does the current instruction prepare a stack argument?
|
||||
bool idaapi is_stkarg_load(const insn_t &insn, int *src, int *dst) override
|
||||
{
|
||||
if ( insn.itype == HPPA_stw )
|
||||
{
|
||||
*src = 0;
|
||||
*dst = 1;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool idaapi has_delay_slot(ea_t caller) override
|
||||
{
|
||||
return ::has_delay_slot(caller, true);
|
||||
}
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void hppa_t::use_hppa_arg_types(ea_t ea, func_type_data_t *fti, funcargvec_t *rargs)
|
||||
{
|
||||
hppa_argtinfo_helper_t argtypes_helper;
|
||||
argtypes_helper.use_arg_tinfos(ea, fti, rargs);
|
||||
}
|
||||
241
idasdk76/module/hppa/hppa.hpp
Normal file
241
idasdk76/module/hppa/hppa.hpp
Normal file
@@ -0,0 +1,241 @@
|
||||
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _HPPA_HPP
|
||||
#define _HPPA_HPP
|
||||
|
||||
#include "../idaidp.hpp"
|
||||
#include "ins.hpp"
|
||||
#include <segregs.hpp>
|
||||
#include <typeinf.hpp>
|
||||
#include <diskio.hpp>
|
||||
#include <fixup.hpp>
|
||||
|
||||
#define PROCMOD_NAME hppa
|
||||
#define PROCMOD_NODE_NAME "$ hppa"
|
||||
|
||||
//------------------------------------------------------------------
|
||||
#define PROC_MAXOP 5 // max number of operands
|
||||
CASSERT(PROC_MAXOP <= UA_MAXOP);
|
||||
|
||||
#define aux_cndc 0x0007 // condition bits c
|
||||
#define aux_cndf 0x0008 // condition bits f
|
||||
#define aux_cndd 0x0010 // condition bits d
|
||||
#define aux_space 0x0020 // space register present
|
||||
|
||||
#define o_based o_idpspec2 // (%r5)
|
||||
// o_phrase: %r4(%r5)
|
||||
// o_displ: 55(%r5)
|
||||
#define sid specflag1
|
||||
#define secreg specflag2 // for o_phrase, the index register
|
||||
//------------------------------------------------------------------
|
||||
enum RegNo
|
||||
{
|
||||
// general registers
|
||||
R0, R1, R2, R3, R4, R5, R6, R7,
|
||||
R8, R9, R10, R11, R12, R13, R14, R15,
|
||||
R16, R17, R18, R19, R20, R21, R22, R23,
|
||||
R24, R25, R26, DP, R28, R29, SP, R31,
|
||||
// space registers
|
||||
SR0, SR1, SR2, SR3, SR4, SR5, SR6, SR7,
|
||||
// control registers
|
||||
CR0, CR1, CR2, CR3, CR4, CR5, CR6, CR7,
|
||||
CR8, CR9, CR10, CR11, CR12, CR13, CR14, CR15,
|
||||
CR16, CR17, CR18, CR19, CR20, CR21, CR22, CR23,
|
||||
CR24, CR25, CR26, CR27, CR28, CR29, CR30, CR31,
|
||||
// floating-point registers
|
||||
F0, F1, F2, F3, F4, F5, F6, F7,
|
||||
F8, F9, F10, F11, F12, F13, F14, F15,
|
||||
F16, F17, F18, F19, F20, F21, F22, F23,
|
||||
F24, F25, F26, F27, F28, F29, F30, F31,
|
||||
// register halves (valid only for fmpyadd/sub)
|
||||
F16L, F17L, F18L, F19L, F20L, F21L, F22L, F23L,
|
||||
F24L, F25L, F26L, F27L, F28L, F29L, F30L, F31L,
|
||||
F16R, F17R, F18R, F19R, F20R, F21R, F22R, F23R,
|
||||
F24R, F25R, F26R, F27R, F28R, F29R, F30R, F31R,
|
||||
// condition bits
|
||||
CA0, CA1, CA2, CA3, CA4, CA5, CA6,
|
||||
|
||||
DPSEG, rVcs, rVds, // virtual registers for code and data segments
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Bit definitions.
|
||||
// Note that the bit order is unusual: the LSB is BIT31
|
||||
// This is a so-called big-endian bit order.
|
||||
#define BIT31 0x00000001L
|
||||
#define BIT30 0x00000002L
|
||||
#define BIT29 0x00000004L
|
||||
#define BIT28 0x00000008L
|
||||
#define BIT27 0x00000010L
|
||||
#define BIT26 0x00000020L
|
||||
#define BIT25 0x00000040L
|
||||
#define BIT24 0x00000080L
|
||||
#define BIT23 0x00000100L
|
||||
#define BIT22 0x00000200L
|
||||
#define BIT21 0x00000400L
|
||||
#define BIT20 0x00000800L
|
||||
#define BIT19 0x00001000L
|
||||
#define BIT18 0x00002000L
|
||||
#define BIT17 0x00004000L
|
||||
#define BIT16 0x00008000L
|
||||
#define BIT15 0x00010000L
|
||||
#define BIT14 0x00020000L
|
||||
#define BIT13 0x00040000L
|
||||
#define BIT12 0x00080000L
|
||||
#define BIT11 0x00100000L
|
||||
#define BIT10 0x00200000L
|
||||
#define BIT9 0x00400000L
|
||||
#define BIT8 0x00800000L
|
||||
#define BIT7 0x01000000L
|
||||
#define BIT6 0x02000000L
|
||||
#define BIT5 0x04000000L
|
||||
#define BIT4 0x08000000L
|
||||
#define BIT3 0x10000000L
|
||||
#define BIT2 0x20000000L
|
||||
#define BIT1 0x40000000L
|
||||
#define BIT0 0x80000000L
|
||||
|
||||
//------------------------------------------------------------------
|
||||
ea_t calc_mem(ea_t ea); // map virtual to phisycal ea
|
||||
|
||||
typedef int proc_t;
|
||||
const proc_t PROC_HPPA = 0; // HPPA big endian
|
||||
|
||||
//------------------------------------------------------------------
|
||||
void interr(const insn_t &insn, const char *module);
|
||||
|
||||
void idaapi hppa_header(outctx_t &ctx);
|
||||
|
||||
void idaapi hppa_segend(outctx_t &ctx, segment_t *seg);
|
||||
|
||||
int idaapi is_align_insn(ea_t ea);
|
||||
int idaapi hppa_get_frame_retsize(const func_t *);
|
||||
|
||||
int idaapi is_sp_based(const insn_t &insn, const op_t &x);
|
||||
int is_sane_insn(const insn_t &insn, int nocrefs);
|
||||
int may_be_func(const insn_t &insn); // can a function start here?
|
||||
bool is_basic_block_end(const insn_t &insn);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// functions to get various fields from the instruction code
|
||||
inline int opcode(uint32 code) { return (code>>26) & 0x3F; }
|
||||
inline int r06(uint32 code) { return (code>>21) & 0x1F; }
|
||||
inline int r11(uint32 code) { return (code>>16) & 0x1F; }
|
||||
inline int r22(uint32 code) { return (code>> 5) & 0x1F; }
|
||||
inline int r27(uint32 code) { return (code>> 0) & 0x1F; }
|
||||
inline int get11(uint32 code) // 11bit field for branches
|
||||
{
|
||||
return ((code>>3) & 0x3FF) | ((code&4)<<(10-2));
|
||||
}
|
||||
inline int32 get17(uint32 code)
|
||||
{
|
||||
return ((code&1) << 16)
|
||||
| (r11(code) << 11)
|
||||
| get11(code);
|
||||
}
|
||||
inline sval_t as21(uint32 x)
|
||||
{
|
||||
// 1 2
|
||||
// 012345678901234567890 bit number
|
||||
// 2 1
|
||||
// 098765432109876543210 shift amount
|
||||
x = (((x>>12) & 0x003) << 0) // 2: x{7..8}
|
||||
| (((x>>16) & 0x01F) << 2) // 5: x{0..4}
|
||||
| (((x>>14) & 0x003) << 7) // 2: x{5..6}
|
||||
| (((x>> 1) & 0x7FF) << 9) // 11: x{9..19}
|
||||
| (((x>> 0) & 0x001) <<20); // 1: x{20}
|
||||
return int32(x << 11);
|
||||
}
|
||||
//--------------------------------------------------------------------------
|
||||
// type system functions
|
||||
bool calc_hppa_arglocs(func_type_data_t *fti);
|
||||
int use_hppa_regarg_type(ea_t ea, const funcargvec_t &rargs);
|
||||
void use_hppa_arg_types(
|
||||
ea_t ea,
|
||||
func_type_data_t *fti,
|
||||
funcargvec_t *rargs);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
struct hppa_cf_t;
|
||||
struct hppa_t : public procmod_t
|
||||
{
|
||||
// altval(-1) -> idpflags
|
||||
// altval(ea) -> function frame register or 0
|
||||
netnode helper;
|
||||
|
||||
ioports_t syscalls;
|
||||
|
||||
#define IDP_SIMPLIFY 0x0001 // simplify instructions
|
||||
#define IDP_PSW_W 0x0002 // W-bit in PSW is set
|
||||
#define IDP_MNEMONIC 0x0004 // use mnemonic register names
|
||||
ushort idpflags = IDP_SIMPLIFY;
|
||||
inline bool dosimple(void) { return (idpflags & IDP_SIMPLIFY) != 0; }
|
||||
inline bool psw_w(void) { return (idpflags & IDP_PSW_W) != 0; }
|
||||
inline bool mnemonic(void) { return (idpflags & IDP_MNEMONIC) != 0; }
|
||||
inline int assemble_16(int x, int y)
|
||||
{
|
||||
if ( psw_w() )
|
||||
{
|
||||
int r = 0;
|
||||
if ( y & 1 )
|
||||
{
|
||||
x ^= 3;
|
||||
r = 0x8000;
|
||||
}
|
||||
return ((y>>1) & 0x1FFF) | (x<<13) | r;
|
||||
}
|
||||
return ((y>>1) & 0x1FFF) | ((y&1) ? 0xE000 : 0);
|
||||
}
|
||||
inline int get_ldo(uint32 code) { return assemble_16((code>>14)&3,code & 0x3FFF); }
|
||||
|
||||
int ptype = 0; // processor type
|
||||
ea_t got = BADADDR;
|
||||
// custom fixups and refinfo
|
||||
hppa_cf_t *hppa_cf = nullptr;
|
||||
|
||||
bool flow = false;
|
||||
ea_t oldea = BADADDR;
|
||||
int oldreg = -1;
|
||||
|
||||
virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override;
|
||||
|
||||
const char *get_syscall_name(int syscall);
|
||||
const char *set_idp_options(
|
||||
const char *keyword,
|
||||
int value_type,
|
||||
const void * value,
|
||||
bool idb_loaded);
|
||||
void handle_new_flags(bool save=true);
|
||||
void init_custom_refs();
|
||||
void term_custom_refs();
|
||||
void setup_got(void);
|
||||
int ana(insn_t *_insn);
|
||||
int emu(const insn_t &insn);
|
||||
bool is_frreg(const insn_t &insn, int reg);
|
||||
void process_operand(const insn_t &insn, const op_t &x, bool isAlt, bool isload);
|
||||
void trace_sp(const insn_t &insn);
|
||||
bool create_func_frame(func_t *pfn);
|
||||
void add_near_ref(const insn_t &insn, const op_t &x, ea_t ea);
|
||||
ea_t get_dp(const insn_t &insn) const;
|
||||
ea_t calc_possible_memref(const insn_t &insn, const op_t &x);
|
||||
uval_t idaapi r11_get_value(const fixup_handler_t * /*fh*/, ea_t ea);
|
||||
char *build_insn_completer(const insn_t &insn, uint32 code, char *buf, size_t bufsize);
|
||||
void hppa_assumes(outctx_t &ctx); // function to produce assume directives
|
||||
void hppa_segstart(outctx_t &ctx, segment_t *Srange) const;
|
||||
void hppa_footer(outctx_t &ctx) const;
|
||||
void use_hppa_arg_types(ea_t ea, func_type_data_t *fti, funcargvec_t *rargs);
|
||||
|
||||
void save_idpflags() { helper.altset(-1, idpflags); }
|
||||
void load_from_idb();
|
||||
};
|
||||
extern int data_id;
|
||||
|
||||
#endif // _HPPA_HPP
|
||||
248
idasdk76/module/hppa/hppa_cfh.cpp
Normal file
248
idasdk76/module/hppa/hppa_cfh.cpp
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-2021 Hex-Rays
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
// This file contains custom fixup handlers for simplified fixups with high
|
||||
// and low parts. The word "simplified" means that we don't use LR and RR
|
||||
// rounding modes as prescribed in the documentation. We replace them by "
|
||||
// and R rounding modes.
|
||||
// They are used for the relocations:
|
||||
// - R_PARISC_DIR21L, R_PARISC_DPREL21L
|
||||
// - R_PARISC_DIR14R, R_PARISC_DPREL14R
|
||||
|
||||
#include <fixup.hpp>
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static uval_t idaapi l21_get_value(const fixup_handler_t * /*fh*/, ea_t ea)
|
||||
{
|
||||
uint32 insn = get_dword(ea);
|
||||
// extract `im21' from "Long immediate" instruction
|
||||
return as21(insn);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool idaapi l21_patch_value(
|
||||
const fixup_handler_t * /*fh*/,
|
||||
ea_t ea,
|
||||
const fixup_data_t &fd)
|
||||
{
|
||||
uint32 insn = get_dword(ea);
|
||||
ea_t expr = fd.off + fd.displacement;
|
||||
// 33222222222211111111110000000000
|
||||
// 10987654321098765432109876543210
|
||||
// abbbbbbbbbbbccdddddee___________ expr
|
||||
// ___________dddddcceebbbbbbbbbbba insn
|
||||
// 10987654321098765432109876543210
|
||||
uint32 im21 = (((expr >> 31) & 0x001) << 0) // a
|
||||
| (((expr >> 20) & 0x7FF) << 1) // b
|
||||
| (((expr >> 18) & 0x003) << 14) // c
|
||||
| (((expr >> 13) & 0x01F) << 16) // d
|
||||
| (((expr >> 11) & 0x003) << 12); // e
|
||||
put_dword(ea, (insn & 0xFFE00000) | im21);
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static bool idaapi l21_calc_reference_data(
|
||||
ea_t *target,
|
||||
ea_t *base,
|
||||
ea_t /*from*/,
|
||||
const refinfo_t &ri,
|
||||
adiff_t opval)
|
||||
{
|
||||
if ( ri.target == BADADDR
|
||||
|| ri.base == BADADDR
|
||||
|| ri.is_subtract() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
ea_t fullvalue = ri.target + ri.tdelta - ri.base;
|
||||
uint32 calc_opval = fullvalue & 0xFFFFF800;
|
||||
if ( calc_opval != uint32(opval) )
|
||||
return false;
|
||||
|
||||
*target = ri.target;
|
||||
*base = ri.base;
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void idaapi l21_get_format(qstring *format)
|
||||
{
|
||||
*format = COLSTR("l%%%s", SCOLOR_KEYWORD);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const custom_refinfo_handler_t ref_l21 =
|
||||
{
|
||||
sizeof(custom_refinfo_handler_t),
|
||||
"L21",
|
||||
"right-justified, high-order 21 bits",
|
||||
0, // properties (currently 0)
|
||||
NULL, // gen_expr
|
||||
l21_calc_reference_data, // calc_reference_data
|
||||
l21_get_format, // get_format
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// we use the R rounding mode (11-bit) in this fixup
|
||||
// but here we return the full immediated value (14-bit or 16-bit)
|
||||
static uval_t idaapi r11_get_value(const fixup_handler_t * /*fh*/, ea_t ea)
|
||||
{
|
||||
hppa_t &pm = *GET_MODULE_DATA(hppa_t);
|
||||
uint32 insn = get_dword(ea);
|
||||
// extract `im14' from "Load/Store" instruction
|
||||
return sval_t(int16(pm.get_ldo(insn)));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool idaapi r11_patch_value(
|
||||
const fixup_handler_t * /*fh*/,
|
||||
ea_t ea,
|
||||
const fixup_data_t &fd)
|
||||
{
|
||||
hppa_t &pm = *GET_MODULE_DATA(hppa_t);
|
||||
uint32 insn = get_dword(ea);
|
||||
// we use the R rounding mode (11-bit) in this fixup
|
||||
ea_t expr = (fd.off + fd.displacement) & 0x7FF;
|
||||
if ( pm.psw_w() )
|
||||
{
|
||||
// 33222222222211111111110000000000
|
||||
// 10987654321098765432109876543210
|
||||
// ________________abbccccccccccccc expr
|
||||
// ________________BBccccccccccccca insn
|
||||
// 10987654321098765432109876543210
|
||||
// B = a == 0 ? b : ~b;
|
||||
uint32 a = (expr >> 15) & 0x0001;
|
||||
uint32 b = (expr >> 13) & 0x0003;
|
||||
if ( a != 0 ) //-V547 'a != 0' is always false
|
||||
b = ~b;
|
||||
uint32 c = expr & 0x1FFF;
|
||||
uint32 im16 = a | (b << 14) | (c << 1);
|
||||
put_dword(ea, (insn & 0xFFFF0000) | im16);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 33222222222211111111110000000000
|
||||
// 10987654321098765432109876543210
|
||||
// __________________abbbbbbbbbbbbb expr
|
||||
// __________________bbbbbbbbbbbbba insn
|
||||
// 10987654321098765432109876543210
|
||||
uint32 im14 = (((expr >> 13) & 0x0001) << 0) // a
|
||||
| ((expr & 0x1FFF) << 1); // b
|
||||
put_dword(ea, (insn & 0xFFFFC000) | im14);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static bool idaapi r11_calc_reference_data(
|
||||
ea_t *target,
|
||||
ea_t *base,
|
||||
ea_t /*from*/,
|
||||
const refinfo_t &ri,
|
||||
adiff_t opval)
|
||||
{
|
||||
if ( ri.target == BADADDR
|
||||
|| ri.base == BADADDR
|
||||
|| ri.is_subtract() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
ea_t fullvalue = ri.target + ri.tdelta - ri.base;
|
||||
uint32 calc_opval = fullvalue & 0x7FF;
|
||||
if ( calc_opval != uint32(opval) )
|
||||
return false;
|
||||
|
||||
*target = ri.target;
|
||||
*base = ri.base;
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static void idaapi r11_get_format(qstring *format)
|
||||
{
|
||||
*format = COLSTR("r%%%s", SCOLOR_KEYWORD);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const custom_refinfo_handler_t ref_r11 =
|
||||
{
|
||||
sizeof(custom_refinfo_handler_t),
|
||||
"R11",
|
||||
"low-order 11 bits",
|
||||
0, // properties (currently 0)
|
||||
NULL, // gen_expr
|
||||
r11_calc_reference_data, // calc_reference_data
|
||||
r11_get_format, // get_format
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
struct hppa_cf_t
|
||||
{
|
||||
fixup_handler_t cfh_l21 =
|
||||
{
|
||||
sizeof(fixup_handler_t),
|
||||
"L21", // name
|
||||
FHF_CODE // verify that fixup points to code
|
||||
| FHF_FORCE_CODE, // convert unknonw item to code
|
||||
4, 0, 0, 0, // size, width, shift
|
||||
REFINFO_CUSTOM, // reftype
|
||||
NULL, // apply
|
||||
l21_get_value, // get_value
|
||||
l21_patch_value, // patch_value
|
||||
};
|
||||
|
||||
fixup_handler_t cfh_r11 =
|
||||
{
|
||||
sizeof(fixup_handler_t),
|
||||
"R11", // name
|
||||
FHF_CODE // verify that fixup points to code
|
||||
| FHF_FORCE_CODE, // convert unknonw item to code
|
||||
4, 0, 0, 0, // size, width, shift
|
||||
REFINFO_CUSTOM, // reftype
|
||||
NULL, // apply
|
||||
r11_get_value, // get_value
|
||||
r11_patch_value, // patch_value
|
||||
};
|
||||
|
||||
fixup_type_t cfh_l21_id = 0; // ids of fixup handlers
|
||||
fixup_type_t cfh_r11_id = 0;
|
||||
int ref_l21_id = 0; // ids of refinfo handlers
|
||||
int ref_r11_id = 0;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void hppa_t::init_custom_refs()
|
||||
{
|
||||
if ( hppa_cf == nullptr )
|
||||
{
|
||||
hppa_cf = new hppa_cf_t;
|
||||
hppa_cf->cfh_l21_id = register_custom_fixup(&hppa_cf->cfh_l21);
|
||||
hppa_cf->cfh_r11_id = register_custom_fixup(&hppa_cf->cfh_r11);
|
||||
hppa_cf->ref_l21_id = register_custom_refinfo(&ref_l21);
|
||||
hppa_cf->ref_r11_id = register_custom_refinfo(&ref_r11);
|
||||
hppa_cf->cfh_l21.reftype = REFINFO_CUSTOM | hppa_cf->ref_l21_id;
|
||||
hppa_cf->cfh_r11.reftype = REFINFO_CUSTOM | hppa_cf->ref_r11_id;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void hppa_t::term_custom_refs()
|
||||
{
|
||||
if ( hppa_cf != nullptr )
|
||||
{
|
||||
hppa_cf->cfh_l21.reftype = REFINFO_CUSTOM;
|
||||
hppa_cf->cfh_r11.reftype = REFINFO_CUSTOM;
|
||||
unregister_custom_refinfo(hppa_cf->ref_r11_id);
|
||||
unregister_custom_refinfo(hppa_cf->ref_l21_id);
|
||||
unregister_custom_fixup(hppa_cf->cfh_r11_id);
|
||||
unregister_custom_fixup(hppa_cf->cfh_l21_id);
|
||||
delete hppa_cf;
|
||||
hppa_cf = nullptr;
|
||||
}
|
||||
}
|
||||
409
idasdk76/module/hppa/hpux.cfg
Normal file
409
idasdk76/module/hppa/hpux.cfg
Normal file
@@ -0,0 +1,409 @@
|
||||
|
||||
; HPUX system call numbers
|
||||
|
||||
sys_nosys 0
|
||||
sys_exit 1
|
||||
sys_fork 2
|
||||
sys_read 3
|
||||
sys_write 4
|
||||
sys_open 5
|
||||
sys_close 6
|
||||
sys_wait 7
|
||||
sys_creat 8
|
||||
sys_link 9
|
||||
sys_unlink 10
|
||||
sys_execv 11
|
||||
sys_chdir 12
|
||||
sys_time 13
|
||||
sys_mknod 14
|
||||
sys_chmod 15
|
||||
sys_chown 16
|
||||
sys_brk 17
|
||||
sys_lchmod 18
|
||||
sys_lseek 19
|
||||
sys_getpid 20
|
||||
sys_mount 21
|
||||
sys_umount 22
|
||||
sys_setuid 23
|
||||
sys_getuid 24
|
||||
sys_stime 25
|
||||
sys_ptrace 26
|
||||
sys_alarm 27
|
||||
sys_cnx_lw_pmon_read 28
|
||||
sys_pause 29
|
||||
sys_utime 30
|
||||
sys_stty 31
|
||||
sys_gtty 32
|
||||
sys_access 33
|
||||
sys_nice 34
|
||||
sys_ftime 35
|
||||
sys_sync 36
|
||||
sys_kill 37
|
||||
sys_stat 38
|
||||
sys_setpgrp3 39
|
||||
sys_lstat 40
|
||||
sys_dup 41
|
||||
sys_pipe 42
|
||||
sys_times 43
|
||||
sys_profil 44
|
||||
sys_ki_call 45
|
||||
sys_setgid 46
|
||||
sys_getgid 47
|
||||
sys_acct 51
|
||||
sys_set_userthreadid 52
|
||||
sys_ioctl 54
|
||||
sys_reboot 55
|
||||
sys_symlink 56
|
||||
sys_utssys 57
|
||||
sys_readlink 58
|
||||
sys_execve 59
|
||||
sys_umask 60
|
||||
sys_chroot 61
|
||||
sys_fcntl 62
|
||||
sys_ulimit 63
|
||||
sys_vfork 66
|
||||
sys_lwp_getprivate 67
|
||||
sys_lwp_setprivate 68
|
||||
sys_mmap 71
|
||||
sys_munmap 73
|
||||
sys_mprotect 74
|
||||
sys_madvise 75
|
||||
sys_vhangup 76
|
||||
sys_swapoff 77
|
||||
sys_getgroups 79
|
||||
sys_setgroups 80
|
||||
sys_getpgrp2 81
|
||||
sys_setpgid 82
|
||||
sys_setitimer 83
|
||||
sys_wait3 84
|
||||
sys_swapon 85
|
||||
sys_getitimer 86
|
||||
sys_dup2 90
|
||||
sys_fstat 92
|
||||
sys_select 93
|
||||
sys_fsync 95
|
||||
sys_setpriority 96
|
||||
sys_getpriority 100
|
||||
sys_lf_send 103
|
||||
sys_sigvector 108
|
||||
sys_sigblock 109
|
||||
sys_sigsetmask 110
|
||||
sys_sigpause 111
|
||||
sys_sigstack 112
|
||||
sys_gettimeofday 116
|
||||
sys_getrusage 117
|
||||
sys_readv 120
|
||||
sys_writev 121
|
||||
sys_settimeofday 122
|
||||
sys_fchown 123
|
||||
sys_fchmod 124
|
||||
sys_setresuid 126
|
||||
sys_setresgid 127
|
||||
sys_rename 128
|
||||
sys_truncate 129
|
||||
sys_ftruncate 130
|
||||
sys_sysconf 132
|
||||
sys_mkdir 136
|
||||
sys_rmdir 137
|
||||
sys_sigcleanup 139
|
||||
sys_setcore 140
|
||||
sys_getrlimit 144
|
||||
sys_setrlimit 145
|
||||
sys_lwp_self 147
|
||||
sys_quotactl 148
|
||||
sys_get_sysinfo 149
|
||||
sys_privgrp 151
|
||||
sys_rtprio 152
|
||||
sys_plock 153
|
||||
sys_lf_next_scn 154
|
||||
sys_lockf 155
|
||||
sys_semget 156
|
||||
sys_semop 158
|
||||
sys_msgget 159
|
||||
sys_msgsnd 161
|
||||
sys_msgrcv 162
|
||||
sys_shmget 163
|
||||
sys_shmat 165
|
||||
sys_shmdt 166
|
||||
sys__set_mem_window 167
|
||||
sys_nsp_init 168
|
||||
sys_mkrnod 170
|
||||
sys_test 171
|
||||
sys_unsp_open 172
|
||||
sys_ogetcontext 174
|
||||
sys_osetcontext 175
|
||||
sys_bigio 176
|
||||
sys_pipenode 177
|
||||
sys_lsync 178
|
||||
sys_mysite 180
|
||||
sys_sitels 181
|
||||
sys_swapclients 182
|
||||
sys_rmtprocess 183
|
||||
sys_dskless_stats 184
|
||||
sys_sigprocmask 185
|
||||
sys_sigpending 186
|
||||
sys_sigsuspend 187
|
||||
sys_sigaction 188
|
||||
sys_lw_get_thread_times 189
|
||||
sys_nfssvc 190
|
||||
sys_getfh 191
|
||||
sys_getdomainname 192
|
||||
sys_setdomainname 193
|
||||
sys_async_daemon 194
|
||||
sys_getdirentries 195
|
||||
sys_statfs 196
|
||||
sys_fstatfs 197
|
||||
sys_vfsmount 198
|
||||
sys_qmml 199
|
||||
sys_waitpid 200
|
||||
sys_sigsetreturn 224
|
||||
sys_sigsetstatemask 225
|
||||
sys_cs 227
|
||||
sys_cds 228
|
||||
sys_set_no_trunc 229
|
||||
sys_pathconf 230
|
||||
sys_fpathconf 231
|
||||
sys_nfs_fcntl 234
|
||||
sys_ogetacl 235
|
||||
sys_ofgetacl 236
|
||||
sys_osetacl 237
|
||||
sys_ofsetacl 238
|
||||
sys_pstat 239
|
||||
sys_getaudid 240
|
||||
sys_setaudid 241
|
||||
sys_getaudproc 242
|
||||
sys_setaudproc 243
|
||||
sys_getevent 244
|
||||
sys_setevent 245
|
||||
sys_audwrite 246
|
||||
sys_audswitch 247
|
||||
sys_audctl 248
|
||||
sys_ogetaccess 249
|
||||
sys_fsctl 250
|
||||
sys_swapfs 259
|
||||
sys_fss 260
|
||||
sys_tsync 267
|
||||
sys_getnumfds 268
|
||||
sys_poll 269
|
||||
sys_getmsg 270
|
||||
sys_putmsg 271
|
||||
sys_fchdir 272
|
||||
sys_getmount_cnt 273
|
||||
sys_getmount_entry 274
|
||||
sys_accept 275
|
||||
sys_bind 276
|
||||
sys_connect 277
|
||||
sys_getpeername 278
|
||||
sys_getsockname 279
|
||||
sys_getsockopt 280
|
||||
sys_listen 281
|
||||
sys_recv 282
|
||||
sys_recvfrom 283
|
||||
sys_recvmsg 284
|
||||
sys_send 285
|
||||
sys_sendmsg 286
|
||||
sys_sendto 287
|
||||
sys_setsockopt 288
|
||||
sys_shutdown 289
|
||||
sys_socket 290
|
||||
sys_socketpair 291
|
||||
sys_proc_open 292
|
||||
sys_proc_close 293
|
||||
sys_proc_send 294
|
||||
sys_proc_recv 295
|
||||
sys_proc_sendrecv 296
|
||||
sys_proc_syscall 297
|
||||
sys_semctl 312
|
||||
sys_msgctl 313
|
||||
sys_shmctl 314
|
||||
sys_mpctl 315
|
||||
sys_exportfs 316
|
||||
sys_getpmsg 317
|
||||
sys_putpmsg 318
|
||||
sys_msync 320
|
||||
sys_msleep 321
|
||||
sys_mwakeup 322
|
||||
sys_msem_init 323
|
||||
sys_msem_remove 324
|
||||
sys_adjtime 325
|
||||
sys_kload 326
|
||||
sys_fattach 327
|
||||
sys_fdetach 328
|
||||
sys_serialize 329
|
||||
sys_statvfs 330
|
||||
sys_fstatvfs 331
|
||||
sys_lchown 332
|
||||
sys_getsid 333
|
||||
sys_sysfs 334
|
||||
sys_sched_setparam 337
|
||||
sys_sched_getparam 338
|
||||
sys_sched_setscheduler 339
|
||||
sys_sched_getscheduler 340
|
||||
sys_sched_yield 341
|
||||
sys_sched_get_priority_max 342
|
||||
sys_sched_get_priority_min 343
|
||||
sys_sched_rr_get_interval 344
|
||||
sys_clock_settime 345
|
||||
sys_clock_gettime 346
|
||||
sys_clock_getres 347
|
||||
sys_timer_create 348
|
||||
sys_timer_delete 349
|
||||
sys_timer_settime 350
|
||||
sys_timer_gettime 351
|
||||
sys_timer_getoverrun 352
|
||||
sys_nanosleep 353
|
||||
sys_toolbox 354
|
||||
sys_getdents 356
|
||||
sys_getcontext 357
|
||||
sys_sysinfo 358
|
||||
sys_fcntl64 359
|
||||
sys_ftruncate64 360
|
||||
sys_fstat64 361
|
||||
sys_getdirentries64 362
|
||||
sys_getrlimit64 363
|
||||
sys_lockf64 364
|
||||
sys_lseek64 365
|
||||
sys_lstat64 366
|
||||
sys_mmap64 367
|
||||
sys_setrlimit64 368
|
||||
sys_stat64 369
|
||||
sys_truncate64 370
|
||||
sys_ulimit64 371
|
||||
sys_pread 372
|
||||
sys_preadv 373
|
||||
sys_pwrite 374
|
||||
sys_pwritev 375
|
||||
sys_pread64 376
|
||||
sys_preadv64 377
|
||||
sys_pwrite64 378
|
||||
sys_pwritev64 379
|
||||
sys_setcontext 380
|
||||
sys_sigaltstack 381
|
||||
sys_waitid 382
|
||||
sys_setpgrp 383
|
||||
sys_recvmsg2 384
|
||||
sys_sendmsg2 385
|
||||
sys_socket2 386
|
||||
sys_socketpair2 387
|
||||
sys_setregid 388
|
||||
sys_lwp_create 389
|
||||
sys_lwp_terminate 390
|
||||
sys_lwp_wait 391
|
||||
sys_lwp_suspend 392
|
||||
sys_lwp_resume 393
|
||||
sys_lwp_abort_syscall 395
|
||||
sys_lwp_info 396
|
||||
sys_lwp_kill 397
|
||||
sys_ksleep 398
|
||||
sys_kwakeup 399
|
||||
sys_pstat_getlwp 401
|
||||
sys_lwp_exit 402
|
||||
sys_lwp_continue 403
|
||||
sys_getacl 404
|
||||
sys_fgetacl 405
|
||||
sys_setacl 406
|
||||
sys_fsetacl 407
|
||||
sys_getaccess 408
|
||||
sys_lwp_mutex_init 409
|
||||
sys_lwp_mutex_lock_sys 410
|
||||
sys_lwp_mutex_unlock 411
|
||||
sys_lwp_cond_init 412
|
||||
sys_lwp_cond_signal 413
|
||||
sys_lwp_cond_broadcast 414
|
||||
sys_lwp_cond_wait_sys 415
|
||||
sys_lwp_getscheduler 416
|
||||
sys_lwp_setscheduler 417
|
||||
sys_lwp_getstate 418
|
||||
sys_lwp_setstate 419
|
||||
sys_lwp_detach 420
|
||||
sys_mlock 421
|
||||
sys_munlock 422
|
||||
sys_mlockall 423
|
||||
sys_munlockall 424
|
||||
sys_shm_open 425
|
||||
sys_shm_unlink 426
|
||||
sys_sigqueue 427
|
||||
sys_sigwaitinfo 428
|
||||
sys_sigtimedwait 429
|
||||
sys_sigwait 430
|
||||
sys_aio_read 431
|
||||
sys_aio_write 432
|
||||
sys_lio_listio 433
|
||||
sys_aio_error 434
|
||||
sys_aio_return 435
|
||||
sys_aio_cancel 436
|
||||
sys_aio_suspend 437
|
||||
sys_aio_fsync 438
|
||||
sys_mq_open 439
|
||||
sys_mq_close 440
|
||||
sys_mq_unlink 441
|
||||
sys_mq_send 442
|
||||
sys_mq_receive 443
|
||||
sys_mq_notify 444
|
||||
sys_mq_setattr 445
|
||||
sys_mq_getattr 446
|
||||
sys_ksem_open 447
|
||||
sys_ksem_unlink 448
|
||||
sys_ksem_close 449
|
||||
sys_ksem_post 450
|
||||
sys_ksem_wait 451
|
||||
sys_ksem_read 452
|
||||
sys_ksem_trywait 453
|
||||
sys_lwp_rwlock_init 454
|
||||
sys_lwp_rwlock_destroy 455
|
||||
sys_lwp_rwlock_rdlock_sys 456
|
||||
sys_lwp_rwlock_wrlock_sys 457
|
||||
sys_lwp_rwlock_tryrdlock 458
|
||||
sys_lwp_rwlock_trywrlock 459
|
||||
sys_lwp_rwlock_unlock 460
|
||||
sys_ttrace 461
|
||||
sys_ttrace_wait 462
|
||||
sys_lf_wire_mem 463
|
||||
sys_lf_unwire_mem 464
|
||||
sys_lf_send_pin_map 465
|
||||
sys_lf_free_buf 466
|
||||
sys_lf_wait_nq 467
|
||||
sys_lf_wakeup_conn_q 468
|
||||
sys_lf_unused 469
|
||||
sys_lwp_sema_init 470
|
||||
sys_lwp_sema_post 471
|
||||
sys_lwp_sema_wait 472
|
||||
sys_lwp_sema_trywait 473
|
||||
sys_lwp_sema_destroy 474
|
||||
sys_statvfs64 475
|
||||
sys_fstatvfs64 476
|
||||
sys_msh_register 477
|
||||
sys_ptrace64 478
|
||||
sys_sendfile 479
|
||||
sys_sendpath 480
|
||||
sys_sendfile64 481
|
||||
sys_sendpath64 482
|
||||
sys_modload 483
|
||||
sys_moduload 484
|
||||
sys_modpath 485
|
||||
sys_getksym 486
|
||||
sys_modadm 487
|
||||
sys_modstat 488
|
||||
sys_lwp_detached_exit 489
|
||||
sys_crashconf 490
|
||||
sys_siginhibit 491
|
||||
sys_sigenable 492
|
||||
sys_spuctl 493
|
||||
sys_zerokernelsum 494
|
||||
sys_nfs_kstat 495
|
||||
sys_aio_read64 496
|
||||
sys_aio_write64 497
|
||||
sys_aio_error64 498
|
||||
sys_aio_return64 499
|
||||
sys_aio_cancel64 500
|
||||
sys_aio_suspend64 501
|
||||
sys_aio_fsync64 502
|
||||
sys_lio_listio64 503
|
||||
sys_recv2 504
|
||||
sys_recvfrom2 505
|
||||
sys_send2 506
|
||||
sys_sendto2 507
|
||||
sys_acl 508
|
||||
sys___cnx_p2p_ctl 509
|
||||
sys___cnx_gsched_ctl 510
|
||||
sys___cnx_pmon_ctl 511
|
||||
181
idasdk76/module/hppa/ins.cpp
Normal file
181
idasdk76/module/hppa/ins.cpp
Normal file
@@ -0,0 +1,181 @@
|
||||
/* -
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-2000 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hppa.hpp"
|
||||
|
||||
/*
|
||||
#define u 1
|
||||
#define c 2
|
||||
#define o1(x) ((x & u) ? CF_USE1 : 0) | (x & c) ? CF_CHG1 : 0))
|
||||
#define o2(x) ((x & u) ? CF_USE2 : 0) | (x & c) ? CF_CHG2 : 0))
|
||||
#define o3(x) ((x & u) ? CF_USE3 : 0) | (x & c) ? CF_CHG3 : 0))
|
||||
#define OPS(x,y,z,others) (o1(x) | o2(y) | o3(z) | others)
|
||||
*/
|
||||
|
||||
const instruc_t Instructions[] =
|
||||
{
|
||||
|
||||
{ "", 0 }, // Unknown Operation
|
||||
|
||||
{ "add", CF_USE1|CF_USE2|CF_CHG3 }, // Add
|
||||
{ "addb", CF_USE1|CF_USE2|CF_CHG2|CF_USE3 }, // Add and Branch
|
||||
{ "addi", CF_USE1|CF_USE2|CF_CHG3 }, // Add to Immediate
|
||||
{ "addib", CF_USE1|CF_USE2|CF_CHG2|CF_USE3 }, // Add Immediate and Branch
|
||||
{ "addil", CF_USE1|CF_USE2 }, // Add to Immediate Left
|
||||
{ "and", CF_USE1|CF_USE2|CF_CHG3 }, // AND
|
||||
{ "andcm", CF_USE1|CF_USE2|CF_CHG3 }, // AND complement
|
||||
{ "b", CF_USE1|CF_CHG2 }, // Branch
|
||||
{ "bb", CF_USE1|CF_USE2|CF_USE3 }, // Branch on Bit
|
||||
{ "be", CF_USE1 }, // Branch External
|
||||
{ "blr", CF_USE1|CF_CHG2|CF_CALL }, // Branch and Link Register
|
||||
{ "break", CF_USE1|CF_USE2 }, // Break
|
||||
{ "bv", CF_USE1 }, // Branch Vectored
|
||||
{ "bve", CF_USE1 }, // Branch Vectored External
|
||||
{ "cldd", CF_USE1|CF_CHG2 }, // Coprocessor Load Doubleword
|
||||
{ "cldw", CF_USE1|CF_CHG2 }, // Coprocessor Load Word
|
||||
{ "clrbts", 0 }, // Clear Branch Target Stack
|
||||
{ "cmpb", CF_USE1|CF_USE2|CF_USE3 }, // Compare and Branch
|
||||
{ "cmpclr", CF_USE1|CF_USE2|CF_CHG3 }, // Compare and Clear
|
||||
{ "cmpib", CF_USE1|CF_USE2|CF_USE3 }, // Compare Immediate and Branch
|
||||
{ "cmpiclr", CF_USE1|CF_USE2|CF_CHG3 }, // Compare Immediate and Clear
|
||||
{ "copr", 0 }, // Coprocessor Operation
|
||||
{ "cstd", CF_USE1|CF_CHG2 }, // Coprocessor Store Doubleword
|
||||
{ "cstw", CF_USE1|CF_CHG2 }, // Coprocessor Store Word
|
||||
{ "dcor", CF_USE1|CF_CHG2 }, // Decimal Correct
|
||||
{ "depd", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Deposit Doubleword
|
||||
{ "depdi", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Deposit Doubleword Immediate
|
||||
{ "depw", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Deposit Word
|
||||
{ "depwi", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Deposit Word Immediate
|
||||
{ "diag", CF_USE1 }, // Diagnose
|
||||
{ "ds", CF_USE1|CF_USE2|CF_CHG3 }, // Divide Step
|
||||
{ "extrd", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Extract Doubleword
|
||||
{ "extrw", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Extract Word
|
||||
{ "fdc", CF_USE1 }, // Flush Data Cache
|
||||
{ "fdce", CF_USE1 }, // Flush Data Cache Entry
|
||||
{ "fic", CF_USE1 }, // Flush Instruction Cache
|
||||
{ "fice", CF_USE1 }, // Flush Instruction Cache Entry
|
||||
{ "hadd", CF_USE1|CF_USE2|CF_CHG3 }, // Halfword Parallel Add
|
||||
{ "havg", CF_USE1|CF_USE2|CF_CHG3 }, // Halfword Parallel Average
|
||||
{ "hshl", CF_USE1|CF_USE2|CF_CHG3 }, // Halfword Parallel Shift Left
|
||||
{ "hshladd", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Halfword Parallel Shift Left and Add
|
||||
{ "hshr", CF_USE1|CF_USE2|CF_CHG3 }, // Halfword Parallel Shift Right
|
||||
{ "hshradd", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Halfword Parallel Shift Right and Add
|
||||
{ "hsub", CF_USE1|CF_USE2|CF_CHG3 }, // Halfword Parallel Subtract
|
||||
{ "idtlbt", CF_USE1|CF_USE2 }, // Insert Data TLB Translation
|
||||
{ "iitlbt", CF_USE1|CF_USE2 }, // Insert Instruction TLB Translation
|
||||
{ "lci", CF_USE1|CF_CHG2 }, // Load Coherence Index
|
||||
{ "ldb", CF_USE1|CF_CHG2 }, // Load Byte
|
||||
{ "ldcd", CF_USE1|CF_CHG2 }, // Load and Clear Doubleword
|
||||
{ "ldcw", CF_USE1|CF_CHG2 }, // Load and Clear Word
|
||||
{ "ldd", CF_USE1|CF_CHG2 }, // Load Doubleword
|
||||
{ "ldda", CF_USE1|CF_CHG2 }, // Load Doubleword Absolute
|
||||
{ "ldh", CF_USE1|CF_CHG2 }, // Load Halfword
|
||||
{ "ldil", CF_USE1|CF_CHG2 }, // Load Immediate Left
|
||||
{ "ldo", CF_USE1|CF_CHG2 }, // Load Offset
|
||||
{ "ldsid", CF_USE1|CF_CHG2 }, // Load Space Identifier
|
||||
{ "ldw", CF_USE1|CF_CHG2 }, // Load Word
|
||||
{ "ldwa", CF_USE1|CF_CHG2 }, // Load Word Absolute
|
||||
{ "lpa", CF_USE1|CF_CHG2 }, // Load Physical Address
|
||||
{ "mfctl", CF_USE1|CF_CHG2 }, // Move From Control Register
|
||||
{ "mfia", CF_CHG1 }, // Move From Instruction Address
|
||||
{ "mfsp", CF_USE1|CF_CHG2 }, // Move From Space Register
|
||||
{ "mixh", CF_USE1|CF_USE2|CF_CHG3 }, // Mix Halfwords
|
||||
{ "mixw", CF_USE1|CF_USE2|CF_CHG3 }, // Mix Words
|
||||
{ "movb", CF_USE1|CF_CHG2|CF_USE3 }, // Move and Branch
|
||||
{ "movib", CF_USE1|CF_CHG2|CF_USE3 }, // Move Immediate and Branch
|
||||
{ "mtctl", CF_USE1|CF_CHG2 }, // Move To Control Register
|
||||
{ "mtsarcm", CF_USE1 }, // Move To Shift Amount Register Complement
|
||||
{ "mtsm", CF_USE1 }, // Move To System Mask
|
||||
{ "mtsp", CF_USE1|CF_CHG2 }, // Move To Space Register
|
||||
{ "or", CF_USE1|CF_USE2|CF_CHG3 }, // Inclusive OR
|
||||
{ "pdc", CF_USE1 }, // Purge Data Cache
|
||||
{ "pdtlb", CF_USE1 }, // Purge Data TLB
|
||||
{ "pdtlbe", CF_USE1 }, // Purge Data TLB Entry
|
||||
{ "permh", CF_USE1|CF_CHG2 }, // Permute Halfwords
|
||||
{ "pitlb", CF_USE1 }, // Purge Instruction TLB
|
||||
{ "pitlbe", CF_USE1 }, // Purge Instruction TLB Entry
|
||||
{ "popbts", CF_USE1 }, // Pop Branch Target Stack
|
||||
{ "probe", CF_USE1|CF_USE2|CF_CHG3 }, // Probe Access
|
||||
{ "probei", CF_USE1|CF_USE2|CF_CHG3 }, // Probe Access Immediate
|
||||
{ "pushbts", CF_USE1 }, // Push Branch Target Stack
|
||||
{ "pushnom", 0 }, // Push Nominated
|
||||
{ "rfi", 0 }, // Return From Interruption
|
||||
{ "rsm", CF_USE1|CF_CHG2 }, // Reset System Mask
|
||||
{ "shladd", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Shift Left and Add
|
||||
{ "shrpd", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Sihft Right Pair Doubleword
|
||||
{ "shrpw", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Sihft Right Pair Word
|
||||
{ "spop0", 0 }, // Special Operation Zero
|
||||
{ "spop1", CF_CHG1 }, // Special Operation One
|
||||
{ "spop2", CF_USE1 }, // Special Operation Two
|
||||
{ "spop3", CF_USE1|CF_USE2 }, // Special Operation Three
|
||||
{ "ssm", CF_USE1|CF_CHG2 }, // Set System Mask
|
||||
{ "stb", CF_USE1|CF_CHG2 }, // Store Byte
|
||||
{ "stby", CF_USE1|CF_CHG2 }, // Store Bytes
|
||||
{ "std", CF_USE1|CF_CHG2 }, // Store Doubleword
|
||||
{ "stda", CF_USE1|CF_CHG2 }, // Store Doubleword Absolute
|
||||
{ "stdby", CF_USE1|CF_CHG2 }, // Store Doubleword Bytes
|
||||
{ "sth", CF_USE1|CF_CHG2 }, // Store Halfword
|
||||
{ "stw", CF_USE1|CF_CHG2 }, // Store Word
|
||||
{ "stwa", CF_USE1|CF_CHG2 }, // Store Word Absolute
|
||||
{ "sub", CF_USE1|CF_USE2|CF_CHG3 }, // Subtract
|
||||
{ "subi", CF_USE1|CF_USE2|CF_CHG3 }, // Subtract from Immediate
|
||||
{ "sync", 0 }, // Synchronize Caches
|
||||
{ "syncdma", 0 }, // Synchronize DMA
|
||||
{ "uaddcm", CF_USE1|CF_USE2|CF_CHG3 }, // Unit Add Complement
|
||||
{ "uxor", CF_USE1|CF_USE2|CF_CHG3 }, // Unit XOR
|
||||
{ "xor", CF_USE1|CF_USE2|CF_CHG3 }, // Exclusive OR
|
||||
|
||||
// Floating point instructions
|
||||
|
||||
{ "fabs", CF_USE1|CF_CHG2 }, // Floating-Point Absolute Value
|
||||
{ "fadd", CF_USE1|CF_USE2|CF_CHG3 }, // Floating-Point Add
|
||||
{ "fcmp", CF_USE1|CF_USE2|CF_CHG3 }, // Floating-Point Compare
|
||||
{ "fcnv", CF_USE1|CF_CHG2 }, // Floating-Point Convert
|
||||
{ "fcpy", CF_USE1|CF_CHG2 }, // Floating-Point Copy
|
||||
{ "fdiv", CF_USE1|CF_USE2|CF_CHG3 }, // Floating-Point Divide
|
||||
{ "fid", 0 }, // Floating-Point Identity
|
||||
{ "fldd", CF_USE1|CF_CHG2 }, // Floating-Point Load Doubleword
|
||||
{ "fldw", CF_USE1|CF_CHG2 }, // Floating-Point Load Word
|
||||
{ "fmpy", CF_USE1|CF_USE2|CF_CHG3 }, // Floating-Point Multiply
|
||||
{ "fmpyadd", CF_USE1|CF_USE2|CF_CHG3|CF_USE4|CF_CHG5 }, // Floating-Point Multiply/Add
|
||||
{ "fmpyfadd", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Floating-Point Multiply Fused Add
|
||||
{ "fmpynfadd", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Floating-Point Multiply Negate Fused Add
|
||||
{ "fmpysub", CF_USE1|CF_USE2|CF_CHG3|CF_USE4|CF_CHG5 }, // Floating-Point Multiply/Subtract
|
||||
{ "fneg", CF_USE1|CF_CHG2 }, // Floating-Point Negate
|
||||
{ "fnegabs", CF_USE1|CF_CHG2 }, // Floating-Point Negate Absolute Value
|
||||
{ "frem", CF_USE1|CF_USE2|CF_CHG3 }, // Floating-Point Remainder
|
||||
{ "frnd", CF_USE1|CF_CHG2 }, // Floating-Point Round to Integer
|
||||
{ "fsqrt", CF_USE1|CF_CHG2 }, // Floating-Point Square Root
|
||||
{ "fstd", CF_USE1|CF_CHG2 }, // Floating-Point Store Doubleword
|
||||
{ "fstw", CF_USE1|CF_CHG2 }, // Floating-Point Store Word
|
||||
{ "fsub", CF_USE1|CF_USE2|CF_CHG3 }, // Floating-Point Subtract
|
||||
{ "ftest", CF_CHG1 }, // Floating-Point Test
|
||||
{ "xmpyu", CF_USE1|CF_USE2|CF_CHG3 }, // Fixed-Point Multiply Unsigned
|
||||
|
||||
// Performance Monitor Coprocessor
|
||||
|
||||
{ "pmdis", 0 }, // Performance Monitor Disable
|
||||
{ "pmenb", 0 }, // Performance Monitor Enable
|
||||
|
||||
// Macros
|
||||
|
||||
{ "call", CF_USE1|CF_CALL }, // Call Subroutine
|
||||
{ "ret", 0 }, // Return From Subroutine
|
||||
{ "shld", CF_USE1|CF_USE2|CF_CHG3 }, // Shift Left Doubleword
|
||||
{ "shlw", CF_USE1|CF_USE2|CF_CHG3 }, // Shift Left Word
|
||||
{ "shrd", CF_USE1|CF_USE2|CF_CHG3 }, // Shift Right Doubleword
|
||||
{ "shrw", CF_USE1|CF_USE2|CF_CHG3 }, // Shift Right Word
|
||||
{ "ldi", CF_USE1|CF_CHG2 }, // Load Immediate
|
||||
{ "copy", CF_USE1|CF_CHG2 }, // Copy Register
|
||||
{ "mtsar", CF_USE1 }, // Move To %SAR
|
||||
{ "nop", 0 }, // No Operation
|
||||
|
||||
};
|
||||
|
||||
CASSERT(qnumber(Instructions) == HPPA_last);
|
||||
174
idasdk76/module/hppa/ins.hpp
Normal file
174
idasdk76/module/hppa/ins.hpp
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-2021 Hex-Rays
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __INSTRS_HPP
|
||||
#define __INSTRS_HPP
|
||||
|
||||
extern const instruc_t Instructions[];
|
||||
|
||||
enum nameNum ENUM_SIZE(uint16)
|
||||
{
|
||||
HPPA_null = 0, // Unknown Operation
|
||||
|
||||
HPPA_add, // Add
|
||||
HPPA_addb, // Add and Branch
|
||||
HPPA_addi, // Add to Immediate
|
||||
HPPA_addib, // Add Immediate and Branch
|
||||
HPPA_addil, // Add to Immediate Left
|
||||
HPPA_and, // AND
|
||||
HPPA_andcm, // AND complement
|
||||
HPPA_b, // Branch
|
||||
HPPA_bb, // Branch on Bit
|
||||
HPPA_be, // Branch External
|
||||
HPPA_blr, // Branch and Link Register
|
||||
HPPA_break, // Break
|
||||
HPPA_bv, // Branch Vectored
|
||||
HPPA_bve, // Branch Vectored External
|
||||
HPPA_cldd, // Coprocessor Load Doubleword
|
||||
HPPA_cldw, // Coprocessor Load Word
|
||||
HPPA_clrbts, // Clear Branch Target Stack
|
||||
HPPA_cmpb, // Compare and Branch
|
||||
HPPA_cmpclr, // Compare and Clear
|
||||
HPPA_cmpib, // Compare Immediate and Branch
|
||||
HPPA_cmpiclr, // Compare Immediate and Clear
|
||||
HPPA_copr, // Coprocessor Operation
|
||||
HPPA_cstd, // Coprocessor Store Doubleword
|
||||
HPPA_cstw, // Coprocessor Store Word
|
||||
HPPA_dcor, // Decimal Correct
|
||||
HPPA_depd, // Deposit Doubleword
|
||||
HPPA_depdi, // Deposit Doubleword Immediate
|
||||
HPPA_depw, // Deposit Word
|
||||
HPPA_depwi, // Deposit Word Immediate
|
||||
HPPA_diag, // Diagnose
|
||||
HPPA_ds, // Divide Step
|
||||
HPPA_extrd, // Extract Doubleword
|
||||
HPPA_extrw, // Extract Word
|
||||
HPPA_fdc, // Flush Data Cache
|
||||
HPPA_fdce, // Flush Data Cache Entry
|
||||
HPPA_fic, // Flush Instruction Cache
|
||||
HPPA_fice, // Flush Instruction Cache Entry
|
||||
HPPA_hadd, // Halfword Parallel Add
|
||||
HPPA_havg, // Halfword Parallel Average
|
||||
HPPA_hshl, // Halfword Parallel Shift Left
|
||||
HPPA_hshladd, // Halfword Parallel Shift Left and Add
|
||||
HPPA_hshr, // Halfword Parallel Shift Right
|
||||
HPPA_hshradd, // Halfword Parallel Shift Right and Add
|
||||
HPPA_hsub, // Halfword Parallel Subtract
|
||||
HPPA_idtlbt, // Insert Data TLB Translation
|
||||
HPPA_iitlbt, // Insert Instruction TLB Translation
|
||||
HPPA_lci, // Load Coherence Index
|
||||
HPPA_ldb, // Load Byte
|
||||
HPPA_ldcd, // Load and Clear Doubleword
|
||||
HPPA_ldcw, // Load and Clear Word
|
||||
HPPA_ldd, // Load Doubleword
|
||||
HPPA_ldda, // Load Doubleword Absolute
|
||||
HPPA_ldh, // Load Halfword
|
||||
HPPA_ldil, // Load Immediate Left
|
||||
HPPA_ldo, // Load Offset
|
||||
HPPA_ldsid, // Load Space Identifier
|
||||
HPPA_ldw, // Load Word
|
||||
HPPA_ldwa, // Load Word Absolute
|
||||
HPPA_lpa, // Load Physical Address
|
||||
HPPA_mfctl, // Move From Control Register
|
||||
HPPA_mfia, // Move From Instruction Address
|
||||
HPPA_mfsp, // Move From Space Register
|
||||
HPPA_mixh, // Mix Halfwords
|
||||
HPPA_mixw, // Mix Words
|
||||
HPPA_movb, // Move and Branch
|
||||
HPPA_movib, // Move Immediate and Branch
|
||||
HPPA_mtctl, // Move To Control Register
|
||||
HPPA_mtsarcm, // Move To Shift Amount Register Complement
|
||||
HPPA_mtsm, // Move To System Mask
|
||||
HPPA_mtsp, // Move To Space Register
|
||||
HPPA_or, // Inclusive OR
|
||||
HPPA_pdc, // Purge Data Cache
|
||||
HPPA_pdtlb, // Purge Data TLB
|
||||
HPPA_pdtlbe, // Purge Data TLB Entry
|
||||
HPPA_permh, // Permute Halfwords
|
||||
HPPA_pitlb, // Purge Instruction TLB
|
||||
HPPA_pitlbe, // Purge Instruction TLB Entry
|
||||
HPPA_popbts, // Pop Branch Target Stack
|
||||
HPPA_probe, // Probe Access
|
||||
HPPA_probei, // Probe Access Immediate
|
||||
HPPA_pushbts, // Push Branch Target Stack
|
||||
HPPA_pushnom, // Push Nominated
|
||||
HPPA_rfi, // Return From Interruption
|
||||
HPPA_rsm, // Reset System Mask
|
||||
HPPA_shladd, // Shift Left and Add
|
||||
HPPA_shrpd, // Sihft Right Pair Doubleword
|
||||
HPPA_shrpw, // Sihft Right Pair Word
|
||||
HPPA_spop0, // Special Operation Zero
|
||||
HPPA_spop1, // Special Operation One
|
||||
HPPA_spop2, // Special Operation Two
|
||||
HPPA_spop3, // Special Operation Three
|
||||
HPPA_ssm, // Set System Mask
|
||||
HPPA_stb, // Store Byte
|
||||
HPPA_stby, // Store Bytes
|
||||
HPPA_std, // Store Doubleword
|
||||
HPPA_stda, // Store Doubleword Absolute
|
||||
HPPA_stdby, // Store Doubleword Bytes
|
||||
HPPA_sth, // Store Halfword
|
||||
HPPA_stw, // Store Word
|
||||
HPPA_stwa, // Store Word Absolute
|
||||
HPPA_sub, // Subtract
|
||||
HPPA_subi, // Subtract from Immediate
|
||||
HPPA_sync, // Synchronize Caches
|
||||
HPPA_syncdma, // Synchronize DMA
|
||||
HPPA_uaddcm, // Unit Add Complement
|
||||
HPPA_uxor, // Unit XOR
|
||||
HPPA_xor, // Exclusive OR
|
||||
|
||||
// Floating point instructions
|
||||
|
||||
HPPA_fabs, // Floating-Point Absolute Value
|
||||
HPPA_fadd, // Floating-Point Add
|
||||
HPPA_fcmp, // Floating-Point Compare
|
||||
HPPA_fcnv, // Floating-Point Convert
|
||||
HPPA_fcpy, // Floating-Point Copy
|
||||
HPPA_fdiv, // Floating-Point Divide
|
||||
HPPA_fid, // Floating-Point Identity
|
||||
HPPA_fldd, // Floating-Point Load Doubleword
|
||||
HPPA_fldw, // Floating-Point Load Word
|
||||
HPPA_fmpy, // Floating-Point Multiply
|
||||
HPPA_fmpyadd, // Floating-Point Multiply/Add
|
||||
HPPA_fmpyfadd, // Floating-Point Multiply Fused Add
|
||||
HPPA_fmpynfadd, // Floating-Point Multiply Negate Fused Add
|
||||
HPPA_fmpysub, // Floating-Point Multiply/Subtract
|
||||
HPPA_fneg, // Floating-Point Negate
|
||||
HPPA_fnegabs, // Floating-Point Negate Absolute Value
|
||||
HPPA_frem, // Floating-Point Remainder
|
||||
HPPA_frnd, // Floating-Point Round to Integer
|
||||
HPPA_fsqrt, // Floating-Point Square Root
|
||||
HPPA_fstd, // Floating-Point Store Doubleword
|
||||
HPPA_fstw, // Floating-Point Store Word
|
||||
HPPA_fsub, // Floating-Point Subtract
|
||||
HPPA_ftest, // Floating-Point Test
|
||||
HPPA_xmpyu, // Fixed-Point Multiply Unsigned
|
||||
|
||||
// Performance Monitor Coprocessor
|
||||
|
||||
HPPA_pmdis, // Performance Monitor Disable
|
||||
HPPA_pmenb, // Performance Monitor Enable
|
||||
|
||||
// Macros
|
||||
|
||||
HPPA_call, // Call Subroutine
|
||||
HPPA_ret, // Return From Subroutine
|
||||
HPPA_shld, // Shift Left Doubleword
|
||||
HPPA_shlw, // Shift Left Word
|
||||
HPPA_shrd, // Shift Right Doubleword
|
||||
HPPA_shrw, // Shift Right Word
|
||||
HPPA_ldi, // Load Immediate
|
||||
HPPA_copy, // Copy Register
|
||||
HPPA_mtsar, // Move To %SAR
|
||||
HPPA_nop, // No Operation
|
||||
|
||||
HPPA_last,
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
59
idasdk76/module/hppa/makefile
Normal file
59
idasdk76/module/hppa/makefile
Normal file
@@ -0,0 +1,59 @@
|
||||
PROC=hppa
|
||||
CONFIGS=hpux.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)fixup.hpp $(I)fpro.h $(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)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \
|
||||
../idaidp.hpp ana.cpp hppa.hpp ins.hpp
|
||||
$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)fixup.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)struct.hpp $(I)typeinf.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp emu.cpp hppa.hpp \
|
||||
ins.hpp
|
||||
$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)fixup.hpp $(I)fpro.h $(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)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \
|
||||
../idaidp.hpp hppa.hpp ins.cpp ins.hpp
|
||||
$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)fixup.hpp $(I)fpro.h $(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)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \
|
||||
../idaidp.hpp hppa.hpp ins.hpp out.cpp
|
||||
$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)fixup.hpp $(I)fpro.h $(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)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \
|
||||
../idaidp.hpp hppa.hpp hppa_cfh.cpp ins.hpp \
|
||||
notify_codes.hpp reg.cpp
|
||||
31
idasdk76/module/hppa/notify_codes.hpp
Normal file
31
idasdk76/module/hppa/notify_codes.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-2021 Hex-Rays
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <idp.hpp>
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// The following events are supported by the PPC module in the ph.notify() function
|
||||
namespace hppa_module_t
|
||||
{
|
||||
enum event_codes_t
|
||||
{
|
||||
ev_dummy = processor_t::ev_loader, // was used before
|
||||
ev_is_psw_w, // W-bit in PSW is set
|
||||
};
|
||||
|
||||
inline processor_t::event_t idp_ev(event_codes_t ev)
|
||||
{
|
||||
return processor_t::event_t(ev);
|
||||
}
|
||||
|
||||
inline bool is_psw_w()
|
||||
{
|
||||
return processor_t::notify(idp_ev(ev_is_psw_w)) == 1;
|
||||
}
|
||||
}
|
||||
1304
idasdk76/module/hppa/out.cpp
Normal file
1304
idasdk76/module/hppa/out.cpp
Normal file
File diff suppressed because it is too large
Load Diff
606
idasdk76/module/hppa/reg.cpp
Normal file
606
idasdk76/module/hppa/reg.cpp
Normal file
@@ -0,0 +1,606 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hppa.hpp"
|
||||
#include "hppa_cfh.cpp"
|
||||
#include <diskio.hpp>
|
||||
#include <typeinf.hpp>
|
||||
#include "notify_codes.hpp"
|
||||
|
||||
#include <ieee.h>
|
||||
int data_id;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const char *const register_names_plain[] =
|
||||
{
|
||||
// general registers (r0 is always 0)
|
||||
// r31 is for BLE instruction
|
||||
"%r0", "%r1", "%rp", "%r3", "%r4", "%r5", "%r6", "%r7",
|
||||
"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
|
||||
"%r16", "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%r23",
|
||||
"%r24", "%r25", "%r26", "%dp", "%r28", "%r29", "%sp", "%r31",
|
||||
// space registers
|
||||
"%sr0", "%sr1", "%sr2", "%sr3", "%sr4", "%sr5", "%sr6", "%sr7",
|
||||
// control registers
|
||||
"%rctr", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5", "%cr6", "%cr7",
|
||||
"%pidr1","%pidr2", "%ccr", "%sar", "%pidr3", "%pidr4","%iva", "%eiem",
|
||||
"%itmr", "%pcsq", "pcoq", "%iir", "%isr", "%ior", "%ipsw", "%eirr",
|
||||
"%tr0", "%tr1", "%tr2", "%tr3", "%tr4", "%tr5", "%tr6", "%tr7",
|
||||
// floating-point registers
|
||||
"%fpsr", "%fr1", "%fr2", "%fr3", "%fr4", "%fr5", "%fr6", "%fr7",
|
||||
"%fr8", "%fr9", "%fr10", "%fr11", "%fr12", "%fr13", "%fr14", "%fr15",
|
||||
"%fr16", "%fr17", "%fr18", "%fr19", "%fr20", "%fr21", "%fr22", "%fr23",
|
||||
"%fr24", "%fr25", "%fr26", "%fr27", "%fr28", "%fr29", "%fr30", "%fr31",
|
||||
// register halves
|
||||
"%fr16l", "%fr17l", "%fr18l", "%fr19l", "%fr20l", "%fr21l", "%fr22l", "%fr23l",
|
||||
"%fr24l", "%fr25l", "%fr26l", "%fr27l", "%fr28l", "%fr29l", "%fr30l", "%fr31l",
|
||||
"%fr16r", "%fr17r", "%fr18r", "%fr19r", "%fr20r", "%fr21r", "%fr22r", "%fr23r",
|
||||
"%fr24r", "%fr25r", "%fr26r", "%fr27r", "%fr28r", "%fr29r", "%fr30r", "%fr31r",
|
||||
// condition bits
|
||||
"%ca0", "%ca1", "%ca2", "%ca3", "%ca4", "%ca5", "%ca6",
|
||||
|
||||
"dp", // segment register to represent DP
|
||||
"cs","ds", // virtual registers for code and data segments
|
||||
};
|
||||
|
||||
static const char *const register_names_mnemonic[] =
|
||||
{
|
||||
// general registers (r0 is always 0)
|
||||
// r31 is for BLE instruction
|
||||
"%r0", "%r1", "%rp", "%r3", "%r4", "%r5", "%r6", "%r7",
|
||||
"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
|
||||
"%r16", "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%arg3",
|
||||
"%arg2", "%arg1", "%arg0", "%dp", "%ret0", "%r29", "%sp", "%r31",
|
||||
// space registers
|
||||
"%sr0", "%sr1", "%sr2", "%sr3", "%sr4", "%sr5", "%sr6", "%sr7",
|
||||
// control registers
|
||||
"%rctr", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5", "%cr6", "%cr7",
|
||||
"%pidr1","%pidr2", "%ccr", "%sar", "%pidr3", "%pidr4","%iva", "%eiem",
|
||||
"%itmr", "%pcsq", "pcoq", "%iir", "%isr", "%ior", "%ipsw", "%eirr",
|
||||
"%tr0", "%tr1", "%tr2", "%tr3", "%tr4", "%tr5", "%tr6", "%tr7",
|
||||
// floating-point registers
|
||||
"%fpsr", "%fr1", "%fr2", "%fr3", "%fr4", "%fr5", "%fr6", "%fr7",
|
||||
"%fr8", "%fr9", "%fr10", "%fr11", "%fr12", "%fr13", "%fr14", "%fr15",
|
||||
"%fr16", "%fr17", "%fr18", "%fr19", "%fr20", "%fr21", "%fr22", "%fr23",
|
||||
"%fr24", "%fr25", "%fr26", "%fr27", "%fr28", "%fr29", "%fr30", "%fr31",
|
||||
// register halves
|
||||
"%fr16l", "%fr17l", "%fr18l", "%fr19l", "%fr20l", "%fr21l", "%fr22l", "%fr23l",
|
||||
"%fr24l", "%fr25l", "%fr26l", "%fr27l", "%fr28l", "%fr29l", "%fr30l", "%fr31l",
|
||||
"%fr16r", "%fr17r", "%fr18r", "%fr19r", "%fr20r", "%fr21r", "%fr22r", "%fr23r",
|
||||
"%fr24r", "%fr25r", "%fr26r", "%fr27r", "%fr28r", "%fr29r", "%fr30r", "%fr31r",
|
||||
// condition bits
|
||||
"%ca0", "%ca1", "%ca2", "%ca3", "%ca4", "%ca5", "%ca6",
|
||||
|
||||
"dp", // segment register to represent DP
|
||||
"cs","ds", // virtual registers for code and data segments
|
||||
};
|
||||
CASSERT(qnumber(register_names_plain) == qnumber(register_names_mnemonic));
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const uchar retcode_0[] = { 0xE8, 0x40, 0xC0, 0x00 }; // bv %r0(%rp)
|
||||
|
||||
static const bytes_t retcodes[] =
|
||||
{
|
||||
{ sizeof(retcode_0), retcode_0 },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// GNU ASM
|
||||
//-----------------------------------------------------------------------
|
||||
static const asm_t gas =
|
||||
{
|
||||
AS_ASCIIC|ASH_HEXF3|ASD_DECF0|ASB_BINF3|ASO_OCTF1|AS_COLON|AS_N2CHR|AS_NCMAS|AS_ONEDUP,
|
||||
0,
|
||||
"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
|
||||
".quad", // qwords
|
||||
NULL, // oword (16 bytes)
|
||||
".float", // float (4 bytes)
|
||||
".double", // 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
|
||||
NULL, // vstruc_fmt
|
||||
NULL, // rva
|
||||
};
|
||||
|
||||
static const asm_t *const asms[] = { &gas, NULL };
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// read all procmod data from the idb
|
||||
void hppa_t::load_from_idb()
|
||||
{
|
||||
idpflags = (ushort)helper.altval(-1);
|
||||
handle_new_flags(/*save*/ false);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void hppa_t::setup_got(void)
|
||||
{
|
||||
got = get_gotea();
|
||||
if ( got == BADADDR )
|
||||
got = get_name_ea(BADADDR, "_GLOBAL_OFFSET_TABLE_");
|
||||
if ( got == BADADDR )
|
||||
{
|
||||
segment_t *s = get_segm_by_name(".got");
|
||||
if ( s != NULL )
|
||||
got = s->start_ea;
|
||||
}
|
||||
msg("DP is assumed to be %08a\n", got);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void hppa_t::handle_new_flags(bool save)
|
||||
{
|
||||
if ( mnemonic() )
|
||||
ph.reg_names = register_names_mnemonic;
|
||||
else
|
||||
ph.reg_names = register_names_plain;
|
||||
if ( save )
|
||||
save_idpflags();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
const char *hppa_t::get_syscall_name(int syscall)
|
||||
{
|
||||
const ioport_t *p = find_ioport(syscalls, syscall);
|
||||
return p == NULL ? NULL : p->name.c_str();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
const char *hppa_t::set_idp_options(
|
||||
const char *keyword,
|
||||
int value_type,
|
||||
const void * value,
|
||||
bool idb_loaded)
|
||||
{
|
||||
static const char form[] =
|
||||
"HELP\n"
|
||||
"HP PA-RISC specific options\n"
|
||||
"\n"
|
||||
" Simplify instructions\n"
|
||||
"\n"
|
||||
" If this option is on, IDA will simplify instructions and replace\n"
|
||||
" them by clearer pseudo-instructions\n"
|
||||
" For example,\n"
|
||||
"\n"
|
||||
" or 0, 0, 0\n"
|
||||
"\n"
|
||||
" will be replaced by\n"
|
||||
"\n"
|
||||
" nop\n"
|
||||
"\n"
|
||||
" PSW bit W is on\n"
|
||||
"\n"
|
||||
" If this option is on, IDA will disassemble instructions as if\n"
|
||||
" PSW W bit is on, i.e. addresses are treated as 64bit. In fact,\n"
|
||||
" IDA still will truncate them to 32 bit, but this option changes\n"
|
||||
" disassembly of load/store instructions.\n"
|
||||
"\n"
|
||||
" Use mnemonic register names\n"
|
||||
"\n"
|
||||
" If checked, IDA will use mnemonic names of the registers:\n"
|
||||
" %r26: %arg0\n"
|
||||
" %r25: %arg1\n"
|
||||
" %r24: %arg2\n"
|
||||
" %r23: %arg3\n"
|
||||
" %r28: %ret0\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"ENDHELP\n"
|
||||
"HPPA specific options\n"
|
||||
"\n"
|
||||
" <~S~implify instructions:C>\n"
|
||||
" <PSW bit W is on (for 64-bit):C>\n"
|
||||
" <Use ~m~nemonic register names:C>>\n"
|
||||
"\n"
|
||||
"\n";
|
||||
|
||||
if ( keyword == NULL )
|
||||
{
|
||||
CASSERT(sizeof(idpflags) == sizeof(ushort));
|
||||
ask_form(form, &idpflags);
|
||||
OK:
|
||||
handle_new_flags(idb_loaded);
|
||||
return IDPOPT_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( value_type != IDPOPT_BIT )
|
||||
return IDPOPT_BADTYPE;
|
||||
if ( strcmp(keyword, "HPPA_SIMPLIFY") == 0 )
|
||||
{
|
||||
setflag(idpflags, IDP_SIMPLIFY, *(int*)value != 0);
|
||||
goto OK;
|
||||
}
|
||||
if ( strcmp(keyword, "HPPA_MNEMONIC") == 0 )
|
||||
{
|
||||
setflag(idpflags, IDP_MNEMONIC, *(int*)value != 0);
|
||||
goto OK;
|
||||
}
|
||||
if ( strcmp(keyword, "HPPA_PSW_W") == 0 )
|
||||
{
|
||||
setflag(idpflags, IDP_PSW_W, *(int*)value != 0);
|
||||
goto OK;
|
||||
}
|
||||
return IDPOPT_BADKEY;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// 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(hppa_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t idaapi hppa_t::on_event(ssize_t msgid, va_list va)
|
||||
{
|
||||
int code = 0;
|
||||
switch ( msgid )
|
||||
{
|
||||
case processor_t::ev_init:
|
||||
// __emit__(0xCC); // debugger trap
|
||||
helper.create(PROCMOD_NODE_NAME);
|
||||
inf_set_be(true); // always big endian
|
||||
read_ioports(&syscalls, NULL, "hpux.cfg");
|
||||
init_custom_refs();
|
||||
break;
|
||||
|
||||
case processor_t::ev_term:
|
||||
term_custom_refs();
|
||||
syscalls.clear();
|
||||
clr_module_data(data_id);
|
||||
break;
|
||||
|
||||
case processor_t::ev_newfile: // new file loaded
|
||||
handle_new_flags();
|
||||
setup_got();
|
||||
break;
|
||||
|
||||
case processor_t::ev_ending_undo:
|
||||
case processor_t::ev_oldfile: // old file loaded
|
||||
load_from_idb();
|
||||
setup_got();
|
||||
break;
|
||||
|
||||
case processor_t::ev_newprc: // new processor type
|
||||
break;
|
||||
|
||||
case processor_t::ev_newasm: // new assembler type
|
||||
break;
|
||||
|
||||
case processor_t::ev_creating_segm: // new segment
|
||||
{
|
||||
segment_t *sptr = va_arg(va, segment_t *);
|
||||
sptr->defsr[ rVds-ph.reg_first_sreg] = find_selector(sptr->sel);
|
||||
sptr->defsr[DPSEG-ph.reg_first_sreg] = 0;
|
||||
}
|
||||
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:
|
||||
{
|
||||
const insn_t *insn = va_arg(va, insn_t *);
|
||||
return may_be_func(*insn);
|
||||
}
|
||||
|
||||
case processor_t::ev_is_basic_block_end:
|
||||
{
|
||||
const insn_t *insn = va_arg(va, insn_t *);
|
||||
return is_basic_block_end(*insn) ? 1 : -1;
|
||||
}
|
||||
|
||||
// +++ TYPE CALLBACKS (only 32-bit programs for the moment)
|
||||
case processor_t::ev_decorate_name:
|
||||
{
|
||||
qstring *outbuf = va_arg(va, qstring *);
|
||||
const char *name = va_arg(va, const char *);
|
||||
bool mangle = va_argi(va, bool);
|
||||
cm_t cc = va_argi(va, cm_t);
|
||||
tinfo_t *type = va_arg(va, tinfo_t *);
|
||||
return gen_decorate_name(outbuf, name, mangle, cc, type) ? 1 : 0;
|
||||
}
|
||||
|
||||
case processor_t::ev_max_ptr_size:
|
||||
return 4;
|
||||
|
||||
case processor_t::ev_calc_arglocs:
|
||||
{
|
||||
func_type_data_t *fti = va_arg(va, func_type_data_t *);
|
||||
return calc_hppa_arglocs(fti) ? 1 : -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_use_stkarg_type:
|
||||
return 0;
|
||||
|
||||
case processor_t::ev_use_regarg_type:
|
||||
{
|
||||
int *used = va_arg(va, int *);
|
||||
ea_t ea = va_arg(va, ea_t);
|
||||
const funcargvec_t *rargs = va_arg(va, const funcargvec_t *);
|
||||
*used = use_hppa_regarg_type(ea, *rargs);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_use_arg_types:
|
||||
{
|
||||
ea_t ea = va_arg(va, ea_t);
|
||||
func_type_data_t *fti = va_arg(va, func_type_data_t *);
|
||||
funcargvec_t *rargs = va_arg(va, funcargvec_t *);
|
||||
use_hppa_arg_types(ea, fti, rargs);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_get_cc_regs:
|
||||
{
|
||||
callregs_t *callregs = va_arg(va, callregs_t *);
|
||||
cm_t cc = va_argi(va, cm_t);
|
||||
static const int fastcall_regs[] = { R26, R25, R24, R23, -1 };
|
||||
if ( cc == CM_CC_FASTCALL )
|
||||
callregs->set(ARGREGS_INDEPENDENT, fastcall_regs, NULL);
|
||||
else if ( cc == CM_CC_THISCALL )
|
||||
callregs->reset();
|
||||
else
|
||||
break;
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_calc_cdecl_purged_bytes:
|
||||
// calculate number of purged bytes after call
|
||||
{
|
||||
// ea_t ea = va_arg(va, ea_t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
case processor_t::ev_get_stkarg_offset:
|
||||
// get offset from SP to the first stack argument
|
||||
// args: none
|
||||
// returns: the offset+2
|
||||
return -0x34;
|
||||
|
||||
// --- TYPE CALLBACKS
|
||||
|
||||
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 *);
|
||||
hppa_header(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_footer:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
hppa_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 *);
|
||||
hppa_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 *);
|
||||
hppa_segend(*ctx, seg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_assumes:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
hppa_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_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_get_frame_retsize:
|
||||
{
|
||||
int *frsize = va_arg(va, int *);
|
||||
const func_t *pfn = va_arg(va, const func_t *);
|
||||
*frsize = hppa_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;
|
||||
}
|
||||
|
||||
case processor_t::ev_is_align_insn:
|
||||
{
|
||||
ea_t ea = va_arg(va, ea_t);
|
||||
return is_align_insn(ea);
|
||||
}
|
||||
|
||||
|
||||
case hppa_module_t::ev_is_psw_w:
|
||||
return psw_w() ? 1 : -1;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
static const char *const shnames[] = { "hppa", NULL };
|
||||
static const char *const lnames[] =
|
||||
{
|
||||
"PA-RISC",
|
||||
NULL
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Processor Definition
|
||||
//-----------------------------------------------------------------------
|
||||
processor_t LPH =
|
||||
{
|
||||
IDP_INTERFACE_VERSION, // version
|
||||
PLFM_HPPA, // id
|
||||
// flag
|
||||
PRN_HEX // hex numbers
|
||||
| PR_ALIGN // data items should be aligned
|
||||
| PR_DEFSEG32 // 32-bit segments by default
|
||||
| PR_SEGS // has segment registers
|
||||
| PR_SGROTHER // segment register mean something unknown to the kernel
|
||||
| PR_STACK_UP // stack grows up
|
||||
| PR_TYPEINFO // type system is supported
|
||||
| PR_USE_ARG_TYPES // use ph.use_arg_types()
|
||||
| PR_DELAYED, // has delayed jumps and calls
|
||||
// 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,
|
||||
lnames,
|
||||
|
||||
asms,
|
||||
|
||||
notify,
|
||||
|
||||
register_names_plain, // Register names
|
||||
qnumber(register_names_plain), // Number of registers
|
||||
|
||||
DPSEG, // first
|
||||
rVds, // last
|
||||
8, // size of a segment register
|
||||
rVcs,rVds,
|
||||
|
||||
NULL, // No known code start sequences
|
||||
retcodes,
|
||||
|
||||
HPPA_null,
|
||||
HPPA_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
|
||||
HPPA_rfi, // Icode of return instruction. It is ok to give any of possible return instructions
|
||||
};
|
||||
Reference in New Issue
Block a user