update to ida 7.6, add builds

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

1334
idasdk76/module/hppa/ana.cpp Normal file

File diff suppressed because it is too large Load Diff

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

View 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

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

View 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

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

View 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

View 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

View 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

File diff suppressed because it is too large Load Diff

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