update to ida 7.6, add builds
This commit is contained in:
2776
idasdk76/module/arc/ana.cpp
Normal file
2776
idasdk76/module/arc/ana.cpp
Normal file
File diff suppressed because it is too large
Load Diff
502
idasdk76/module/arc/arc.hpp
Normal file
502
idasdk76/module/arc/arc.hpp
Normal file
@@ -0,0 +1,502 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 2012-2021 Hex-Rays
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
* ARC (Argonaut RISC Core) processor module
|
||||
*
|
||||
* Based on code contributed by by Felix Domke <tmbinc@gmx.net>
|
||||
*/
|
||||
|
||||
#ifndef _ARC_HPP
|
||||
#define _ARC_HPP
|
||||
|
||||
#include "../idaidp.hpp"
|
||||
#include "ins.hpp"
|
||||
#include <typeinf.hpp>
|
||||
#include <diskio.hpp>
|
||||
#include "../iohandler.hpp"
|
||||
|
||||
#define PROCMOD_NAME arc
|
||||
#define PROCMOD_NODE_NAME "$ arc"
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// customization of the 'cmd' structure:
|
||||
|
||||
enum processor_subtype_t
|
||||
{
|
||||
prc_arc = 0, // ARCTangent-A4 (old 32-bit ISA)
|
||||
prc_arcompact = 1, // ARCtangent-A5 and later (32/16-bit mixed)
|
||||
prc_arcv2 = 2, // ARC EM (ARCompact successor)
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
enum RegNo
|
||||
{
|
||||
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, R27, R28, R29, R30, R31,
|
||||
|
||||
R32, R33, R34, R35, R36, R37, R38, R39,
|
||||
R40, R41, R42, R43, R44, R45, R46, R47,
|
||||
R48, R49, R50, R51, R52, R53, R54, R55,
|
||||
R56, R57, R58, R59, R60, R61, R62, R63,
|
||||
|
||||
CF, ZF, NF, VF,
|
||||
|
||||
// registers used for indexed instructions
|
||||
// keep these consecutive
|
||||
NEXT_PC,
|
||||
LDI_BASE, JLI_BASE, EI_BASE,
|
||||
|
||||
GP_SEG, // virtual segment register for global pointer value
|
||||
|
||||
rVcs, rVds, // virtual registers for code and data segments
|
||||
|
||||
// aliases
|
||||
|
||||
GP = R26, // Global Pointer
|
||||
FP = R27, // Frame Pointer
|
||||
SP = R28, // Stack Pointer
|
||||
ILINK1 = R29, // Level 1 interrupt link register
|
||||
ILINK2 = R30, // Level 2 interrupt link register
|
||||
BLINK = R31, // Branch link register
|
||||
LP_COUNT = R60, // Loop count register
|
||||
PCL = R63, // 32-bit aligned PC value (ARCompact)
|
||||
|
||||
// optional extension
|
||||
MLO = R57, // Multiply low 32 bits, read only
|
||||
MMID = R58, // Multiply middle 32 bits, read only
|
||||
MHI = R59, // Multiply high 32 bits, read only
|
||||
};
|
||||
|
||||
#define SHIMM_F 61 // Short immediate data indicator setting flags
|
||||
#define LIMM 62 // Long immediate data indicator
|
||||
#define SHIMM 63 // Short immediate data indicator not setting flags (NB: not used in ARCompact)
|
||||
#define LIMM5 30 // 5-bit long immediate data indicator (used in ARCv2)
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
const ioport_t *find_port(ea_t address);
|
||||
|
||||
#define PROC_MAXOP 4 // max number of operands
|
||||
CASSERT(PROC_MAXOP <= UA_MAXOP);
|
||||
|
||||
//---------------------------------
|
||||
|
||||
inline int getreg(const op_t &x)
|
||||
{
|
||||
return x.type == o_reg ? x.reg : -1;
|
||||
}
|
||||
|
||||
inline bool isreg(const op_t &x, int reg)
|
||||
{
|
||||
return getreg(x) == reg;
|
||||
}
|
||||
|
||||
inline bool issp(const op_t &x) { return isreg(x, SP); }
|
||||
|
||||
//---------------------------------
|
||||
// cmd.auxpref bits
|
||||
// instructions that use condition flags (Bcc, Jcc)
|
||||
#define aux_f 0x0100 // Flags set field (.f postfix)
|
||||
#define aux_nmask 0x0060 // Jump/Call nullify instruction mode
|
||||
#define aux_nd 0x00 // No Delayed instruction slot (only execute next instruction when not jumping)
|
||||
#define aux_d 0x20 // Delayed instruction slot (always execute next instruction)
|
||||
#define aux_jd 0x40 // Jump Delayed instruction slot (only execute next instruction when jumping)
|
||||
#define aux_cmask 0x001F // condition code mask
|
||||
// load/store instructions flags (Di.AA.ZZ.X)
|
||||
#define aux_di 0x0020 // direct to memory (cache bypass) (.di suffix)
|
||||
#define aux_amask 0x0018 // Address write-back
|
||||
#define aux_anone 0x00 // no writeback
|
||||
#define aux_a 0x08 // pre-increment (.a or .aw)
|
||||
#define aux_ab 0x10 // post-increment (.ab)
|
||||
#define aux_as 0x18 // scaled access (.as)
|
||||
#define aux_zmask 0x0006 // size mask
|
||||
#define aux_l 0x0 // long size (no suffix)
|
||||
#define aux_w 0x4 // word size (.w suffix)
|
||||
#define aux_b 0x2 // byte size (.b suffix)
|
||||
#define aux_x 0x0001 // Sign extend field (.x suffix)
|
||||
|
||||
#define aux_pcload 0x0200 // converted pc-relative to memory load (used when ARC_INLINECONST is set)
|
||||
#define aux_bhint 0x0400 // non-default static branch prediction hint (.t or .nt suffix)
|
||||
#define aux_s 0x0800 // 16-bit encoded instruction
|
||||
|
||||
// Operand types:
|
||||
#define o_reglist o_idpspec0 // register list for enter/leave
|
||||
|
||||
#define reglist specval // o_reglist: registers to save/restore
|
||||
#define REGLIST_REGS 0x0F // number of core registers to save/restore
|
||||
#define REGLISTR_MAX 0x0E // max number of core registers to save/restore
|
||||
#define REGLIST_FP 0x10 // save/restore stack frame
|
||||
#define REGLIST_BLINK 0x20 // save/restore blink register
|
||||
#define REGLIST_PCL 0x40 // jump to blink register after restore (leave only)
|
||||
|
||||
// o_phrase
|
||||
#define secreg specflag1 // o_phrase: the second register is here: [op.phrase, op.secreg]
|
||||
|
||||
// o_displ
|
||||
#define membase specflag1 // o_displ: if set, displacement is the base value: [op.addr, op.reg]
|
||||
// this is important for scaled loads, e.g. ld.as r1, [0x23445, r2]
|
||||
// o_reg
|
||||
#define regpair specflag1 // o_reg: if set, this operand is the second register of a register pair
|
||||
// the previous operand contains the other register of the pair
|
||||
// o_mem
|
||||
#define immdisp specval // o_mem: immediate displacement to immediate address.
|
||||
// addr contains the already displaced address.
|
||||
// addr - get_scale_factor(insn) * immdisp is the base address for immdisp
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Condition codes:
|
||||
enum cond_t
|
||||
{
|
||||
cAL=0, cRA=0, // Always 1 0x00
|
||||
cEQ=1, cZ=1, // Zero Z 0x01
|
||||
cNE=2, cNZ=2, // Non-Zero /Z 0x02
|
||||
cPL=3, cP=3, // Positive /N 0x03
|
||||
cMI=4, cN=4, // Negative N 0x04
|
||||
cCS=5, cC=5, cLO=5, // Carry set, lower than (unsigned) C 0x05
|
||||
cCC=6, cNC=6, cHS=6, // Carry clear, higher or same (unsigned) /C 0x06
|
||||
cVS=7, cV=7, // Over-flow set V 0x07
|
||||
cVC=8, cNV=8, // Over-flow clear /V 0x08
|
||||
cGT=9, // Greater than (signed) (N and V and /Z) or (/N and /V and /Z) 0x09
|
||||
cGE=0x0A, // Greater than or equal to (signed) (N and V) or (/N and /V) 0x0A
|
||||
cLT=0x0B, // Less than (signed) (N and /V) or (/N and V) 0x0B
|
||||
cLE=0x0C, // Less than or equal to (signed) Z or (N and /V) or (/N and V) 0x0C
|
||||
cHI=0x0D, // Higher than (unsigned) /C and /Z 0x0D
|
||||
cLS=0x0E, // Lower than or same (unsigned) C or Z 0x0E
|
||||
cPNZ=0x0F, // Positive non-zero /N and /Z 0x0F
|
||||
cLAST
|
||||
};
|
||||
inline uint8 get_cond(const insn_t &insn)
|
||||
{
|
||||
if ( insn.itype <= ARC_store_instructions )
|
||||
return cAL;
|
||||
return uint8(insn.auxpref & aux_cmask);
|
||||
}
|
||||
inline bool has_cond(const insn_t &insn)
|
||||
{
|
||||
if ( insn.itype <= ARC_store_instructions )
|
||||
return false;
|
||||
return (insn.auxpref & aux_cmask) != cAL;
|
||||
}
|
||||
inline cond_t get_core_cond(const insn_t &insn)
|
||||
{
|
||||
if ( insn.itype <= ARC_store_instructions )
|
||||
return cAL;
|
||||
uint8 cond = insn.auxpref & aux_cmask;
|
||||
if ( cond >= cLAST )
|
||||
return cLAST;
|
||||
return cond_t(cond);
|
||||
}
|
||||
inline bool has_core_cond(const insn_t &insn)
|
||||
{
|
||||
if ( insn.itype <= ARC_store_instructions )
|
||||
return false;
|
||||
uint8 cond = insn.auxpref & aux_cmask;
|
||||
return cond != cAL && cond < cLAST;
|
||||
}
|
||||
inline cond_t invert_cond(cond_t cond)
|
||||
{
|
||||
switch ( cond )
|
||||
{
|
||||
case cNE: return cEQ;
|
||||
case cEQ: return cNE;
|
||||
case cCC: return cCS;
|
||||
case cCS: return cCC;
|
||||
case cPL: return cMI;
|
||||
case cMI: return cPL;
|
||||
case cVC: return cVS;
|
||||
case cVS: return cVC;
|
||||
case cHI: return cLS;
|
||||
case cLS: return cHI;
|
||||
case cGE: return cLT;
|
||||
case cLT: return cGE;
|
||||
case cGT: return cLE;
|
||||
case cLE: return cGT;
|
||||
default: return cLAST;
|
||||
}
|
||||
}
|
||||
|
||||
// ARC ABI conventions from gdb/arc-tdep.h
|
||||
#define ARC_ABI_GLOBAL_POINTER 26
|
||||
#define ARC_ABI_FRAME_POINTER 27
|
||||
#define ARC_ABI_STACK_POINTER 28
|
||||
|
||||
#define ARC_ABI_FIRST_CALLEE_SAVED_REGISTER 13
|
||||
#define ARC_ABI_LAST_CALLEE_SAVED_REGISTER 26
|
||||
|
||||
#define ARC_ABI_FIRST_ARGUMENT_REGISTER 0
|
||||
#define ARC_ABI_LAST_ARGUMENT_REGISTER 7
|
||||
|
||||
#define ARC_ABI_RETURN_REGNUM 0
|
||||
#define ARC_ABI_RETURN_LOW_REGNUM 0
|
||||
#define ARC_ABI_RETURN_HIGH_REGNUM 1
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// does 'ins' have a delay slot? (next instruction is executed before branch/jump)
|
||||
inline bool has_dslot(const insn_t &ins)
|
||||
{
|
||||
// EXCEPTION: jl.jd <addr> uses delay slot to
|
||||
// hide the long immediate used for the address
|
||||
if ( ins.itype == ARC_jl
|
||||
&& (ins.auxpref & aux_nmask) == aux_jd
|
||||
&& ins.Op1.type == o_near )
|
||||
return false;
|
||||
return ins.itype > ARC_store_instructions && (ins.auxpref & aux_nmask) != 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Scale factor for indexed memory access
|
||||
inline int get_scale_factor(const insn_t &ins)
|
||||
{
|
||||
switch ( ins.itype )
|
||||
{
|
||||
case ARC_st:
|
||||
case ARC_ld:
|
||||
if ( (ins.auxpref & aux_amask) == aux_as )
|
||||
{
|
||||
if ( (ins.auxpref & aux_zmask) == aux_w )
|
||||
return 2;
|
||||
if ( (ins.auxpref & aux_zmask) == aux_l )
|
||||
return 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case ARC_bih:
|
||||
return 2;
|
||||
|
||||
case ARC_bi:
|
||||
case ARC_ldi:
|
||||
case ARC_jli:
|
||||
case ARC_ei:
|
||||
return 4;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Should the register be hidden when used as base in o_displ/o_phrase?
|
||||
//
|
||||
// 0 output normally
|
||||
// 1 hide base reg
|
||||
// -1 hide base reg and output as immediate
|
||||
inline int is_hidden_base_reg(int reg)
|
||||
{
|
||||
if ( reg >= NEXT_PC && reg <= EI_BASE )
|
||||
{
|
||||
return reg == JLI_BASE || reg == EI_BASE ? -1 : 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// The sreg that contains the current value for the given register
|
||||
//
|
||||
// Returns -1 if there is no such sreg
|
||||
inline int get_base_sreg(int reg)
|
||||
{
|
||||
if ( reg == GP )
|
||||
return GP_SEG;
|
||||
else if ( reg >= LDI_BASE && reg <= GP_SEG )
|
||||
return reg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void idaapi arc_header(outctx_t &ctx);
|
||||
void idaapi arc_footer(outctx_t &ctx);
|
||||
|
||||
int idaapi is_sp_based(const insn_t &insn, const op_t & x);
|
||||
bool idaapi create_func_frame(func_t * pfn);
|
||||
int idaapi arc_get_frame_retsize(const func_t * pfn);
|
||||
bool is_arc_return_insn(const insn_t &insn);
|
||||
bool arc_is_switch(switch_info_t *si, const insn_t &insn);
|
||||
inline bool is_arc_simple_branch(uint16 itype)
|
||||
{
|
||||
return itype == ARC_bl
|
||||
|| itype == ARC_jl
|
||||
|| itype == ARC_b
|
||||
|| itype == ARC_j;
|
||||
}
|
||||
|
||||
int get_arc_fastcall_regs(const int **regs);
|
||||
bool calc_arc_arglocs(func_type_data_t *fti);
|
||||
bool calc_arc_varglocs(
|
||||
func_type_data_t *fti,
|
||||
regobjs_t *regargs,
|
||||
int nfixed);
|
||||
bool calc_arc_retloc(argloc_t *retloc, const tinfo_t &tif, cm_t cc);
|
||||
void use_arc_arg_types(
|
||||
ea_t ea,
|
||||
func_type_data_t *fti,
|
||||
funcargvec_t *rargs);
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct arc_iohandler_t : public iohandler_t
|
||||
{
|
||||
struct arc_t ±
|
||||
arc_iohandler_t(arc_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {}
|
||||
virtual const char *iocallback(const ioports_t &iop, const char *line) override;
|
||||
virtual void get_cfg_filename(char *buf, size_t bufsize) override;
|
||||
};
|
||||
|
||||
DECLARE_PROC_LISTENER(pm_idb_listener_t, struct arc_t);
|
||||
|
||||
struct arc_t : public procmod_t
|
||||
{
|
||||
netnode helper; // altval(-1): idp flags
|
||||
#define CALLEE_TAG 'A' // altval(ea): callee address for indirect calls
|
||||
#define DXREF_TAG 'd' // altval(ea): resolved address for complex calculation (e.g. ADD R1, PC)
|
||||
#define DSLOT_TAG 's' // altval(ea): 1: delay slot of an unconditional jump/branch
|
||||
// 2: delay slot of a conditional jump/branch
|
||||
// 3: delay slot of a jl/bl
|
||||
inline void set_callee(ea_t ea, ea_t callee) { helper.easet(ea, callee, CALLEE_TAG); }
|
||||
inline ea_t get_callee(ea_t ea) { return helper.eaget(ea, CALLEE_TAG); }
|
||||
inline void del_callee(ea_t ea) { helper.eadel(ea, CALLEE_TAG); }
|
||||
|
||||
inline void set_dxref(ea_t ea, ea_t dxref) { helper.easet(ea, dxref, DXREF_TAG); }
|
||||
inline ea_t get_dxref(ea_t ea) { return helper.eaget(ea, DXREF_TAG); }
|
||||
inline void del_dxref(ea_t ea) { helper.eadel(ea, DXREF_TAG); }
|
||||
|
||||
instruc_t Instructions[ARC_last];
|
||||
|
||||
ioports_t auxregs;
|
||||
arc_iohandler_t ioh = arc_iohandler_t(*this, helper);
|
||||
pm_idb_listener_t idb_listener = pm_idb_listener_t(*this);
|
||||
|
||||
processor_subtype_t ptype = prc_arc;
|
||||
inline bool is_a4() { return ptype == prc_arc; }
|
||||
inline bool is_arcv2() { return ptype == prc_arcv2; }
|
||||
|
||||
int arc_respect_info = IORESP_ALL;
|
||||
|
||||
int ref_arcsoh_id = 0;
|
||||
int ref_arcsol_id = 0;
|
||||
|
||||
#define ARC_SIMPLIFY 0x01
|
||||
#define ARC_INLINECONST 0x02
|
||||
#define ARC_TRACKREGS 0x04
|
||||
ushort idpflags = ARC_SIMPLIFY | ARC_INLINECONST | ARC_TRACKREGS;
|
||||
|
||||
int g_limm = 0;
|
||||
bool got_limm = false;
|
||||
|
||||
std::set<ea_t> renamed;
|
||||
int islast = 0;
|
||||
|
||||
// is 'ea' in a delay slot of a branch/jump?
|
||||
inline bool is_dslot(ea_t ea, bool including_calls = true)
|
||||
{
|
||||
nodeidx_t v = helper.altval_ea(ea, DSLOT_TAG);
|
||||
if ( including_calls )
|
||||
return v != 0;
|
||||
else
|
||||
return v == 1 || v == 2;
|
||||
}
|
||||
|
||||
inline bool is_imm(int regno)
|
||||
{
|
||||
if ( regno == LIMM )
|
||||
return true;
|
||||
if ( regno == SHIMM_F || regno == SHIMM )
|
||||
return is_a4();
|
||||
return false;
|
||||
}
|
||||
|
||||
arc_t();
|
||||
virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override;
|
||||
|
||||
void save_idpflags() { helper.altset(-1, idpflags); }
|
||||
void load_from_idb();
|
||||
|
||||
bool select_device(int resp_info);
|
||||
inline void add_dxref(const insn_t &insn, ea_t target);
|
||||
int emu(const insn_t &insn);
|
||||
bool is_arc_basic_block_end(
|
||||
const insn_t &insn,
|
||||
bool call_insn_stops_block);
|
||||
void del_insn_info(ea_t ea);
|
||||
const char *set_idp_options(
|
||||
const char *keyword,
|
||||
int value_type,
|
||||
const void *value,
|
||||
bool idb_loaded);
|
||||
void set_codeseqs() const;
|
||||
void set_instruc_names();
|
||||
void ptype_changed();
|
||||
void doIndirectOperand(const insn_t &insn, int b, int c, op_t &op, int d, int li, bool special);
|
||||
void doRegisterInstruction(insn_t &insn, uint32 code);
|
||||
int ana_old(insn_t &insn);
|
||||
void decode_operand(
|
||||
insn_t &insn,
|
||||
uint32 code,
|
||||
int &op_pos,
|
||||
uint32 opkind);
|
||||
int analyze_compact(insn_t &insn, uint32 code, int idx, const struct arcompact_opcode_t *table);
|
||||
int ana_compact(insn_t &insn);
|
||||
int ana(insn_t *_insn);
|
||||
int is_align_insn(ea_t ea) const;
|
||||
bool good_target(const insn_t &insn, ea_t target) const;
|
||||
bool copy_insn_optype(const insn_t &insn, const op_t &x, ea_t ea, void *value = NULL, bool force = false) const;
|
||||
void handle_operand(const insn_t &insn, const op_t & x, bool loading);
|
||||
int get_limm(insn_t &insn);
|
||||
inline void opreg(insn_t &insn, op_t &x, int rgnum, int limm=LIMM);
|
||||
inline void opdisp(insn_t &insn, op_t &x, int rgnum, ea_t disp);
|
||||
void rename_if_not_set(ea_t ea, const char *name);
|
||||
bool check_ac_pop_chain(int *regno, ea_t ea);
|
||||
bool detect_millicode(qstring *mname, ea_t ea);
|
||||
bool is_millicode(ea_t ea, sval_t *spdelta=nullptr);
|
||||
sval_t calc_sp_delta(const insn_t &insn);
|
||||
void trace_sp(const insn_t &insn);
|
||||
bool arc_calc_spdelta(sval_t *spdelta, const insn_t &insn);
|
||||
int arc_may_be_func(const insn_t &insn, int state);
|
||||
void force_offset(
|
||||
ea_t ea,
|
||||
int n,
|
||||
ea_t base,
|
||||
bool issub = false,
|
||||
int scale = 1);
|
||||
bool spoils(const insn_t &insn, int reg) const;
|
||||
int spoils(const insn_t &insn, const uint32 *regs, int n) const;
|
||||
bool is_arc_call_insn(const insn_t &insn);
|
||||
bool find_op_value_ex(
|
||||
const insn_t &insn,
|
||||
const op_t &x,
|
||||
struct ldr_value_info_t *lvi,
|
||||
bool /*check_fbase_reg*/);
|
||||
bool find_ldr_value_ex(
|
||||
const insn_t &insn,
|
||||
ea_t ea,
|
||||
int reg,
|
||||
struct ldr_value_info_t *lvi,
|
||||
bool /*check_fbase_reg*/);
|
||||
bool find_op_value(
|
||||
const insn_t &insn,
|
||||
const op_t &x,
|
||||
uval_t *p_val,
|
||||
ea_t *p_val_ea=NULL,
|
||||
bool check_fbase_reg=true,
|
||||
bool *was_const_load=NULL);
|
||||
bool find_ldr_value(
|
||||
const insn_t &insn,
|
||||
ea_t ea,
|
||||
int reg,
|
||||
uval_t *p_val,
|
||||
ea_t *p_val_ea=NULL,
|
||||
bool check_fbase_reg=true,
|
||||
bool *was_const_load=NULL);
|
||||
int use_arc_regarg_type(ea_t ea, const funcargvec_t &rargs);
|
||||
bool arc_set_op_type(
|
||||
const insn_t &insn,
|
||||
const op_t &x,
|
||||
const tinfo_t &tif,
|
||||
const char *name,
|
||||
eavec_t *visited);
|
||||
void use_arc_arg_types(ea_t ea, func_type_data_t *fti, funcargvec_t *rargs);
|
||||
|
||||
void arc_segstart(outctx_t &ctx, segment_t *Sarea) const;
|
||||
};
|
||||
extern int data_id;
|
||||
|
||||
#endif
|
||||
2887
idasdk76/module/arc/emu.cpp
Normal file
2887
idasdk76/module/arc/emu.cpp
Normal file
File diff suppressed because it is too large
Load Diff
361
idasdk76/module/arc/ins.cpp
Normal file
361
idasdk76/module/arc/ins.cpp
Normal file
@@ -0,0 +1,361 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-98 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@estar.msk.su, ig@datarescue.com
|
||||
* FIDO: 2:5020/209
|
||||
*
|
||||
*/
|
||||
|
||||
#include "arc.hpp"
|
||||
|
||||
instruc_t Instructions[] =
|
||||
{
|
||||
|
||||
{ "", 0 }, // Unknown Operation
|
||||
{ "ld", CF_CHG1|CF_USE2 }, // Load
|
||||
{ "lr", CF_CHG1|CF_USE2 }, // Load from auxiliary register
|
||||
{ "st", CF_USE1|CF_CHG2 }, // Store
|
||||
{ "sr", CF_USE1|CF_USE2|CF_CHG2 }, // Store to auxiliary register
|
||||
{ "flag", CF_USE1 }, // Set flags
|
||||
{ "asr", CF_CHG1|CF_USE2|CF_USE3 }, // Arithmetic shift right
|
||||
{ "lsr", CF_CHG1|CF_USE2|CF_USE3 }, // Logical shift right
|
||||
{ "sexb", CF_CHG1|CF_USE2 }, // Sign extend byte
|
||||
{ "sexw", CF_CHG1|CF_USE2 }, // Sign extend word
|
||||
{ "extb", CF_CHG1|CF_USE2 }, // Zero extend byte
|
||||
{ "extw", CF_CHG1|CF_USE2 }, // Zero extend word
|
||||
{ "ror", CF_CHG1|CF_USE2|CF_USE3 }, // Rotate right
|
||||
{ "rrc", CF_CHG1|CF_USE2 }, // Rotate right through carry
|
||||
{ "b", CF_USE1|CF_JUMP }, // Branch
|
||||
{ "bl", CF_USE1|CF_CALL }, // Branch and link
|
||||
{ "lp", CF_USE1 }, // Zero-overhead loop setup
|
||||
{ "j", CF_USE1|CF_JUMP }, // Jump
|
||||
{ "jl", CF_USE1|CF_CALL }, // Jump and link
|
||||
{ "add", CF_CHG1|CF_USE2|CF_USE3 }, // Add
|
||||
{ "adc", CF_CHG1|CF_USE2|CF_USE3 }, // Add with carry
|
||||
{ "sub", CF_CHG1|CF_USE2|CF_USE3 }, // Subtract
|
||||
{ "sbc", CF_CHG1|CF_USE2|CF_USE3 }, // Subtract with carry
|
||||
{ "and", CF_CHG1|CF_USE2|CF_USE3 }, // Logical bitwise AND
|
||||
{ "or", CF_CHG1|CF_USE2|CF_USE3 }, // Logical bitwise OR
|
||||
{ "bic", CF_CHG1|CF_USE2|CF_USE3 }, // Logical bitwise AND with invert
|
||||
{ "xor", CF_CHG1|CF_USE2|CF_USE3 }, // Logical bitwise exclusive-OR
|
||||
{ "mov", CF_CHG1|CF_USE2 }, // Move
|
||||
{ "nop", 0 }, // No operation
|
||||
{ "lsl", CF_CHG1|CF_USE2|CF_USE3 }, // Logical shift left
|
||||
{ "rlc", CF_CHG1|CF_USE2 }, // Rotate left through carry
|
||||
{ "brk", 0 }, // Breakpoint
|
||||
{ "sleep", 0 }, // Sleep until interrupt or restart
|
||||
{ "swi", 0 }, // Software interrupt
|
||||
{ "asl", CF_CHG1|CF_USE2|CF_USE3 }, // Arithmetic shift left
|
||||
{ "mul64", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32x32 multiply
|
||||
{ "mulu64", CF_CHG1|CF_USE2|CF_USE3 }, // Unsigned 32x32 multiply
|
||||
{ "max", CF_CHG1|CF_USE2|CF_USE3 }, // Maximum of two signed integers
|
||||
{ "min", CF_CHG1|CF_USE2|CF_USE3 }, // Minimum of two signed integers
|
||||
{ "swap", CF_CHG1|CF_USE2 }, // Exchange upper and lower 16 bits
|
||||
{ "norm", CF_CHG1|CF_USE2 }, // Normalize (find-first-bit)
|
||||
|
||||
// ARCompact instructions
|
||||
{ "bbit0", CF_USE1|CF_USE2|CF_USE3 }, // Branch if bit cleared to 0
|
||||
{ "bbit1", CF_USE1|CF_USE2|CF_USE3 }, // Branch if bit set to 1
|
||||
{ "br", CF_USE1|CF_USE2|CF_USE3 }, // Branch on compare
|
||||
{ "pop", CF_CHG1 }, // Restore register value from stack
|
||||
{ "push", CF_USE1 }, // Store register value on stack
|
||||
|
||||
{ "abs", CF_CHG1|CF_USE2 }, // Absolute value
|
||||
{ "add1", CF_CHG1|CF_USE2|CF_USE3 }, // Add with left shift by 1 bit
|
||||
{ "add2", CF_CHG1|CF_USE2|CF_USE3 }, // Add with left shift by 2 bits
|
||||
{ "add3", CF_CHG1|CF_USE2|CF_USE3 }, // Add with left shift by 3 bits
|
||||
{ "bclr", CF_CHG1|CF_USE2|CF_USE3 }, // Clear specified bit (to 0)
|
||||
{ "bmsk", CF_CHG1|CF_USE2|CF_USE3 }, // Bit Mask
|
||||
{ "bset", CF_CHG1|CF_USE2|CF_USE3 }, // Set specified bit (to 1)
|
||||
{ "btst", CF_USE1|CF_USE2 }, // Test value of specified bit
|
||||
{ "bxor", CF_CHG1|CF_USE2|CF_USE3 }, // Bit XOR
|
||||
{ "cmp", CF_USE1|CF_USE2 }, // Compare
|
||||
{ "ex", CF_CHG1|CF_USE2 }, // Atomic Exchange
|
||||
{ "mpy", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32x32 multiply (low)
|
||||
{ "mpyh", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32x32 multiply (high)
|
||||
{ "mpyhu", CF_CHG1|CF_USE2|CF_USE3 }, // Unsigned 32x32 multiply (high)
|
||||
{ "mpyu", CF_CHG1|CF_USE2|CF_USE3 }, // Unsigned 32x32 multiply (low)
|
||||
{ "neg", CF_CHG1|CF_USE2 }, // Negate
|
||||
{ "not", CF_CHG1|CF_USE2 }, // Logical bit inversion
|
||||
{ "rcmp", CF_USE1|CF_USE2 }, // Reverse Compare
|
||||
{ "rsub", CF_CHG1|CF_USE2|CF_USE3 }, // Reverse Subtraction
|
||||
{ "rtie", 0 }, // Return from Interrupt/Exception
|
||||
{ "sub1", CF_CHG1|CF_USE2|CF_USE3 }, // Subtract with left shift by 1 bit
|
||||
{ "sub2", CF_CHG1|CF_USE2|CF_USE3 }, // Subtract with left shift by 2 bits
|
||||
{ "sub3", CF_CHG1|CF_USE2|CF_USE3 }, // Subtract with left shift by 3 bits
|
||||
{ "sync", 0 }, // Synchronize
|
||||
{ "trap", CF_USE1 }, // Raise an exception
|
||||
{ "tst", CF_USE1|CF_USE2 }, // Test
|
||||
{ "unimp", 0 }, // Unimplemented instruction
|
||||
|
||||
{ "abss", CF_CHG1|CF_USE2 }, // Absolute and saturate
|
||||
{ "abssw", CF_CHG1|CF_USE2 }, // Absolute and saturate of word
|
||||
{ "adds", CF_CHG1|CF_USE2|CF_USE3 }, // Add and saturate
|
||||
{ "addsdw", CF_CHG1|CF_USE2|CF_USE3 }, // Add and saturate dual word
|
||||
{ "asls", CF_CHG1|CF_USE2|CF_USE3 }, // Arithmetic shift left and saturate
|
||||
{ "asrs", CF_CHG1|CF_USE2|CF_USE3 }, // Arithmetic shift right and saturate
|
||||
{ "divaw", CF_CHG1|CF_USE2|CF_USE3 }, // Division assist
|
||||
{ "negs", CF_CHG1|CF_USE2 }, // Negate and saturate
|
||||
{ "negsw", CF_CHG1|CF_USE2 }, // Negate and saturate of word
|
||||
{ "normw", CF_CHG1|CF_USE2 }, // Normalize to 16 bits
|
||||
{ "rnd16", CF_CHG1|CF_USE2 }, // Round to word
|
||||
{ "sat16", CF_CHG1|CF_USE2 }, // Saturate to word
|
||||
{ "subs", CF_CHG1|CF_USE2|CF_USE3 }, // Subtract and saturate
|
||||
{ "subsdw", CF_CHG1|CF_USE2|CF_USE3 }, // Subtract and saturate dual word
|
||||
|
||||
{ "muldw", CF_CHG1|CF_USE2|CF_USE3 }, //
|
||||
{ "muludw", CF_CHG1|CF_USE2|CF_USE3 }, //
|
||||
{ "mulrdw", CF_CHG1|CF_USE2|CF_USE3 }, //
|
||||
{ "macdw", CF_CHG1|CF_USE2|CF_USE3 }, //
|
||||
{ "macudw", CF_CHG1|CF_USE2|CF_USE3 }, //
|
||||
{ "macrdw", CF_CHG1|CF_USE2|CF_USE3 }, //
|
||||
{ "msubdw", CF_CHG1|CF_USE2|CF_USE3 }, //
|
||||
|
||||
{ "mululw", CF_CHG1|CF_USE2|CF_USE3 }, //
|
||||
{ "mullw", CF_CHG1|CF_USE2|CF_USE3 }, //
|
||||
{ "mulflw", CF_CHG1|CF_USE2|CF_USE3 }, //
|
||||
{ "maclw", CF_CHG1|CF_USE2|CF_USE3 }, //
|
||||
{ "macflw", CF_CHG1|CF_USE2|CF_USE3 }, //
|
||||
{ "machulw", CF_CHG1|CF_USE2|CF_USE3 }, //
|
||||
{ "machlw", CF_CHG1|CF_USE2|CF_USE3 }, //
|
||||
{ "machflw", CF_CHG1|CF_USE2|CF_USE3 }, //
|
||||
{ "mulhlw", CF_CHG1|CF_USE2|CF_USE3 }, //
|
||||
{ "mulhflw", CF_CHG1|CF_USE2|CF_USE3 }, //
|
||||
|
||||
// Major 6 compact insns
|
||||
{ "acm", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "addqbs", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "avgqb", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "clamp", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "daddh11", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "daddh12", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "daddh21", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "daddh22", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "dexcl1", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "dexcl2", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "dmulh11", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "dmulh12", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "dmulh21", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "dmulh22", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "dsubh11", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "dsubh12", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "dsubh21", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "dsubh22", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "drsubh11", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "drsubh12", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "drsubh21", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "drsubh22", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "fadd", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "fmul", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "fsub", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "fxtr", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "iaddr", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "mpyqb", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "sfxtr", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "pkqb", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "upkqb", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
{ "xpkqb", CF_CHG1|CF_USE2|CF_USE3 },
|
||||
|
||||
|
||||
// ARCv2 only major 4 instructions
|
||||
{ "mpyw", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 16x16 multiply
|
||||
{ "mpyuw", CF_CHG1|CF_USE2|CF_USE3 }, // Unsigned 16x16 multiply
|
||||
{ "bi", CF_USE1|CF_JUMP }, // Branch indexed
|
||||
{ "bih", CF_USE1|CF_JUMP }, // Branch indexed half-word
|
||||
{ "ldi", CF_CHG1|CF_USE2 }, // Load indexed
|
||||
{ "aex", CF_USE1|CF_CHG1|CF_USE2|CF_CHG2 }, // Exchange with auxiliary register
|
||||
{ "bmskn", CF_CHG1|CF_USE2|CF_USE3 }, // Bit mask negated
|
||||
{ "seteq", CF_CHG1|CF_USE2|CF_USE3 }, // Set if equal
|
||||
{ "setne", CF_CHG1|CF_USE2|CF_USE3 }, // Set if not equal
|
||||
{ "setlt", CF_CHG1|CF_USE2|CF_USE3 }, // Set if less than
|
||||
{ "setge", CF_CHG1|CF_USE2|CF_USE3 }, // Set if greater or equal
|
||||
{ "setlo", CF_CHG1|CF_USE2|CF_USE3 }, // Set if lower than
|
||||
{ "seths", CF_CHG1|CF_USE2|CF_USE3 }, // Set if higher or same
|
||||
{ "setle", CF_CHG1|CF_USE2|CF_USE3 }, // Set if less than or equal
|
||||
{ "setgt", CF_CHG1|CF_USE2|CF_USE3 }, // Set if greater than
|
||||
|
||||
{ "rol", CF_CHG1|CF_USE2 }, // Rotate left
|
||||
{ "llock", CF_CHG1|CF_USE2 }, // Load locked
|
||||
{ "scond", CF_USE1|CF_CHG2 }, // Store conditional
|
||||
|
||||
{ "seti", CF_USE1 }, // Set interrupt enable and priority level
|
||||
{ "clri", CF_CHG1 }, // Clear and get interrupt enable and priority level
|
||||
|
||||
// ARCv2 compact prolog / epilog instructions
|
||||
{ "enter", CF_USE1|CF_JUMP }, // Function prologue sequence
|
||||
{ "leave", CF_USE1|CF_JUMP }, // Function epilogue sequence
|
||||
|
||||
// ARCv2 32-bit extension major 5 DOP instructions
|
||||
{ "div", CF_CHG1|CF_USE2|CF_USE3 }, // Signed integer divsion
|
||||
{ "divu", CF_CHG1|CF_USE2|CF_USE3 }, // Unsigned integer divsion
|
||||
{ "rem", CF_CHG1|CF_USE2|CF_USE3 }, // Signed integer remainder
|
||||
{ "remu", CF_CHG1|CF_USE2|CF_USE3 }, // Unsigned integer remainder
|
||||
{ "asrsr", CF_CHG1|CF_USE2|CF_USE3 }, // Shift right rounding and saturating
|
||||
{ "valgn2h", CF_CHG1|CF_USE2|CF_USE3 }, // Two-way 16-bit vector align
|
||||
{ "setacc", CF_USE2|CF_USE3 }, // Set the accumulator
|
||||
{ "mac", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32x32 multiply accumulate
|
||||
{ "macu", CF_CHG1|CF_USE2|CF_USE3 }, // Unsigned 32x32 multiply accumulate
|
||||
{ "dmpyh", CF_CHG1|CF_USE2|CF_USE3 }, // Sum of dual signed 16x16 multiplication
|
||||
{ "dmpyhu", CF_CHG1|CF_USE2|CF_USE3 }, // Sum of dual unsigned 16x16 multiplication
|
||||
{ "dmach", CF_CHG1|CF_USE2|CF_USE3 }, // Dual signed 16x16 multiply accumulate
|
||||
{ "dmachu", CF_CHG1|CF_USE2|CF_USE3 }, // Dual unsigned 16x16 multiply accumulate
|
||||
{ "vadd2h", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16-bit addition
|
||||
{ "vadds2h", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16-bit saturating addition
|
||||
{ "vsub2h", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16-bit subtraction
|
||||
{ "vsubs2h", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16-bit saturating subtraction
|
||||
{ "vaddsub2h", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16-bit addition/subtraction
|
||||
{ "vaddsubs2h", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16-bit saturating addition/subtraction
|
||||
{ "vsubadd2h", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16-bit subtraction/addition
|
||||
{ "vsubadds2h", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16-bit saturating subtraction/addition
|
||||
{ "mpyd", CF_CHG1|CF_CHG2|CF_USE3|CF_USE4 }, // Signed 32x32 multiply (wide)
|
||||
{ "mpydu", CF_CHG1|CF_CHG2|CF_USE3|CF_USE4 }, // Unsigned 32x32 multiply (wide)
|
||||
{ "macd", CF_CHG1|CF_CHG2|CF_USE3|CF_USE4 }, // Signed 32x32 multiply accumulate (wide)
|
||||
{ "macdu", CF_CHG1|CF_CHG2|CF_USE3|CF_USE4 }, // Unsigned 32x32 multiply accumulate (wide)
|
||||
{ "vmpy2h", CF_CHG1|CF_CHG2|CF_USE3|CF_USE4 }, // Dual signed 16x16 multiply (wide)
|
||||
{ "vmpy2hf", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16x16 saturating fractional multiply
|
||||
{ "vmpy2hu", CF_CHG1|CF_CHG2|CF_USE3|CF_USE4 }, // Dual unsigned 16x16 multiply (wide)
|
||||
{ "vmpy2hfr", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16x16 saturating rounded fractional multiply
|
||||
{ "vmac2h", CF_CHG1|CF_CHG2|CF_USE3|CF_USE4 }, // Dual signed 16x16 multiply (wide)
|
||||
{ "vmac2hf", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16x16 saturating fractional multiply
|
||||
{ "vmac2hu", CF_CHG1|CF_CHG2|CF_USE3|CF_USE4 }, // Dual unsigned 16x16 multiply (wide)
|
||||
{ "vmac2hfr", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16x16 saturating rounded fractional multiply
|
||||
{ "vmpy2hwf", CF_CHG1|CF_CHG2|CF_USE3|CF_USE4 }, // Dual 16x16 saturating fractional multiply (wide)
|
||||
{ "vasl2h", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16-bit arithmetic shift left
|
||||
{ "vasls2h", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16-bit saturating arithmetic shift left
|
||||
{ "vasr2h", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16-bit arithmetic shift right
|
||||
{ "vasrs2h", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16-bit saturating arithmetic shift right
|
||||
{ "vlsr2h", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16-bit logical shift right
|
||||
{ "vasrsr2h", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16-bit saturating rounded arithmetic shift right
|
||||
{ "vadd4b", CF_CHG1|CF_USE2|CF_USE3 }, // Quad 8-bit addition
|
||||
{ "vmax2h", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16-bit maximum
|
||||
{ "vsub4b", CF_CHG1|CF_USE2|CF_USE3 }, // Quad 8-bit subtraction
|
||||
{ "vmin2h", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16-bit minimum
|
||||
{ "adcs", CF_CHG1|CF_USE2|CF_USE3 }, // Signed saturating addition with carry in
|
||||
{ "sbcs", CF_CHG1|CF_USE2|CF_USE3 }, // Signed saturating subtraction with carry in
|
||||
{ "dmpyhwf", CF_CHG1|CF_USE2|CF_USE3 }, // Fractional saturating sum of dual 16x16 signed fractional multiply
|
||||
{ "vpack2hl", CF_CHG1|CF_USE2|CF_USE3 }, // Compose lower 16-bits
|
||||
{ "vpack2hm", CF_CHG1|CF_USE2|CF_USE3 }, // Compose upper 16-bits
|
||||
{ "dmpyhf", CF_CHG1|CF_USE2|CF_USE3 }, // Saturating sum of dual 16x16 signed fractional multiply
|
||||
{ "dmpyhfr", CF_CHG1|CF_USE2|CF_USE3 }, // Saturating rounded sum of dual 16x16 signed fractional multiply
|
||||
{ "dmachf", CF_CHG1|CF_USE2|CF_USE3 }, // Saturating sum of dual 16x16 signed fractional multiply accumulate
|
||||
{ "dmachfr", CF_CHG1|CF_USE2|CF_USE3 }, // Saturating rounded sum of dual 16x16 signed fractional multiply accumulate
|
||||
{ "vperm", CF_CHG1|CF_USE2|CF_USE3 }, // Byte permutation with zero or sign extension
|
||||
{ "bspush", CF_CHG1|CF_USE2|CF_USE3 }, // Bitstream push
|
||||
|
||||
// ARCv2 32-bit extension major 5 SOP instructions
|
||||
{ "swape", CF_CHG1|CF_USE2 }, // Swap byte ordering
|
||||
{ "lsl16", CF_CHG1|CF_USE2 }, // Logical shift left by 16 bits
|
||||
{ "lsr16", CF_CHG1|CF_USE2 }, // Logical shift right by 16 bits
|
||||
{ "asr16", CF_CHG1|CF_USE2 }, // Arithmetic shift right by 16 bits
|
||||
{ "asr8", CF_CHG1|CF_USE2 }, // Arithmetic shift right by 8 bits
|
||||
{ "lsr8", CF_CHG1|CF_USE2 }, // Logical shift right by 8 bits
|
||||
{ "lsl8", CF_CHG1|CF_USE2 }, // Logical shift left by 8 bits
|
||||
{ "rol8", CF_CHG1|CF_USE2 }, // Rotate left by 8 bits
|
||||
{ "ror8", CF_CHG1|CF_USE2 }, // Rotate right by 8 bits
|
||||
{ "ffs", CF_CHG1|CF_USE2 }, // Find first set bit
|
||||
{ "fls", CF_CHG1|CF_USE2 }, // Find last set bit
|
||||
|
||||
|
||||
{ "getacc", CF_CHG1|CF_USE2 }, // Get accumulator
|
||||
{ "normacc", CF_CHG1|CF_USE2 }, // Normalize accumulator
|
||||
{ "satf", CF_CHG1|CF_USE2 }, // Saturate according to flags
|
||||
{ "vpack2hbl", CF_CHG1|CF_USE2 }, // Pack lower bytes into lower 16 bits
|
||||
{ "vpack2hbm", CF_CHG1|CF_USE2 }, // Pack upper bytes into upper 16 bits
|
||||
{ "vpack2hblf", CF_CHG1|CF_USE2 }, // Pack upper bytes into lower 16 bits
|
||||
{ "vpack2hbmf", CF_CHG1|CF_USE2 }, // Pack lower bytes into upper 16 bits
|
||||
{ "vext2bhlf", CF_CHG1|CF_USE2 }, // Pack lower 2 bytes into upper byte of 16 bits each
|
||||
{ "vext2bhmf", CF_CHG1|CF_USE2 }, // Pack upper 2 bytes into upper byte of 16 bits each
|
||||
{ "vrep2hl", CF_CHG1|CF_USE2 }, // Repeat lower 16 bits
|
||||
{ "vrep2hm", CF_CHG1|CF_USE2 }, // Repeat upper 16 bits
|
||||
{ "vext2bhl", CF_CHG1|CF_USE2 }, // Pack lower 2 bytes into zero extended 16 bits
|
||||
{ "vext2bhm", CF_CHG1|CF_USE2 }, // Pack upper 2 bytes into zero extended 16 bits
|
||||
{ "vsext2bhl", CF_CHG1|CF_USE2 }, // Pack lower 2 bytes into sign extended 16 bits
|
||||
{ "vsext2bhm", CF_CHG1|CF_USE2 }, // Pack upper 2 bytes into sign extended 16 bits
|
||||
{ "vabs2h", CF_CHG1|CF_USE2 }, // Dual 16-bit absolute value
|
||||
{ "vabss2h", CF_CHG1|CF_USE2 }, // Dual saturating 16-bit absolute value
|
||||
{ "vneg2h", CF_CHG1|CF_USE2 }, // Dual 16-bit negation
|
||||
{ "vnegs2h", CF_CHG1|CF_USE2 }, // Dual saturating 16-bit negation
|
||||
{ "vnorm2h", CF_CHG1|CF_USE2 }, // Dual 16-bit normalization
|
||||
{ "bspeek", CF_CHG1|CF_USE2 }, // Bitstream peek
|
||||
{ "bspop", CF_CHG1|CF_USE2 }, // Bitstream pop
|
||||
{ "sqrt", CF_CHG1|CF_USE2 }, // Integer square root
|
||||
{ "sqrtf", CF_CHG1|CF_USE2 }, // Fractional square root
|
||||
|
||||
// ARCv2 32-bit extension major 5 ZOP instructions
|
||||
{ "aslacc", CF_USE1 }, // Arithmetic shift of accumulator
|
||||
{ "aslsacc", CF_USE1 }, // Saturating arithmetic shift of accumulator
|
||||
{ "flagacc", CF_USE1 }, // Copy accumulator flags to status32 register
|
||||
{ "modif", CF_USE1 }, // Update address pointer
|
||||
|
||||
// ARCv2 32-bit extension major 6 DOP instructions
|
||||
{ "cmpyhnfr", CF_CHG1|CF_USE2|CF_USE3 }, // Fractional 16+16 bit complex saturating rounded unshifted multiply
|
||||
{ "cmpyhfr", CF_CHG1|CF_USE2|CF_USE3 }, // Fractional 16+16 bit complex saturating rounded multiply
|
||||
{ "cmpychfr", CF_CHG1|CF_USE2|CF_USE3 }, // Fractional 16+16 bit complex saturating rounded conjugated multiply
|
||||
{ "vmsub2hf", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16x16 saturating fractional multiply subtract
|
||||
{ "vmsub2hfr", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16x16 saturating rounded fractional multiply subtract
|
||||
{ "cmpychnfr", CF_CHG1|CF_USE2|CF_USE3 }, // Fractional 16+16 bit complex saturating rounded unshifted conjugated multiply
|
||||
{ "cmachnfr", CF_CHG1|CF_USE2|CF_USE3 }, // Fractional 16+16 bit complex saturating rounded unshifted multiply accumulate
|
||||
{ "cmachfr", CF_CHG1|CF_USE2|CF_USE3 }, // Fractional 16+16 bit complex saturating rounded unshifted accumulate
|
||||
{ "cmacchnfr", CF_CHG1|CF_USE2|CF_USE3 }, // Fractional 16+16 bit complex saturating rounded conjugated multiply accumulate
|
||||
{ "cmacchfr", CF_CHG1|CF_USE2|CF_USE3 }, // Fractional 16+16 bit complex saturating rounded unshifted conjugated multiply accumulate
|
||||
{ "mpyf", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32-bit fractional saturating multiply
|
||||
{ "mpyfr", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32-bit fractional saturating rounded multiply
|
||||
{ "macf", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32-bit fractional saturating multiply accumulate
|
||||
{ "macfr", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32-bit fractional saturating rounded multiply accumulate
|
||||
{ "msubf", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32-bit fractional saturating multiply subtract
|
||||
{ "msubfr", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32-bit fractional saturating rounded multiply subtract
|
||||
{ "divf", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32-bit fractional division
|
||||
{ "vmac2hnfr", CF_CHG1|CF_USE2|CF_USE3 }, // Dual signed 16-bit fractional saturating rounded multiply accumulate
|
||||
{ "vmsub2hnfr", CF_CHG1|CF_USE2|CF_USE3 }, // Dual signed 16-bit fractional saturating rounded multiply subtract
|
||||
{ "mpydf", CF_CHG1|CF_CHG2|CF_USE3|CF_USE4 }, // Signed 32-bit fractional multiply (wide)
|
||||
{ "macdf", CF_CHG1|CF_CHG2|CF_USE3|CF_USE4 }, // Signed 32-bit fractional multiply accumulate (wide)
|
||||
{ "msubwhfl", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32 x 16 (lower) fractional saturating multiply subtract
|
||||
{ "msubdf", CF_CHG1|CF_CHG2|CF_USE3|CF_USE4 }, // Signed 32-bit fractional multiply subtract (wide)
|
||||
{ "dmpyhbl", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16x8 signed multiply with lower two bytes
|
||||
{ "dmpyhbm", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16x8 signed multiply with upper two bytes
|
||||
{ "dmachbl", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16x8 signed multiply accumulate with lower two bytes
|
||||
{ "dmachbm", CF_CHG1|CF_USE2|CF_USE3 }, // Dual 16x8 signed multiply accumulate with upper two bytes
|
||||
{ "msubwhflr", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32 x 16 (lower) fractional saturating rounded multiply subtract
|
||||
{ "cmpyhfmr", CF_CHG1|CF_USE2|CF_USE3 }, // Fractional 16+16 bit complex x 16bit real (upper) saturating rounded multiply
|
||||
{ "cbflyhf0r", CF_CHG1|CF_USE2|CF_USE3 }, // Fractional 16+16 bit complex FFT butterfly, first half
|
||||
{ "mpywhl", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32 x 16 (lower) multiply
|
||||
{ "macwhl", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32 x 16 (lower) multiply accumulate
|
||||
{ "mpywhul", CF_CHG1|CF_USE2|CF_USE3 }, // Unsigned 32 x 16 (lower) multiply
|
||||
{ "macwhul", CF_CHG1|CF_USE2|CF_USE3 }, // Unsigned 32 x 16 (lower) multiply accumulate
|
||||
{ "mpywhfm", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32 x 16 (upper) fractional saturating multiply
|
||||
{ "mpywhfmr", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32 x 16 (upper) fractional saturating rounded multiply
|
||||
{ "macwhfm", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32 x 16 (upper) fractional saturating multiply accumulate
|
||||
{ "macwhfmr", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32 x 16 (upper) fractional saturating rounded multiply accumulate
|
||||
{ "mpywhfl", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32 x 16 (lower) fractional saturating multiply
|
||||
{ "mpywhflr", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32 x 16 (lower) fractional saturating rounded multiply
|
||||
{ "macwhfl", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32 x 16 (lower) fractional saturating multiply accumulate
|
||||
{ "macwhflr", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32 x 16 (lower) fractional saturating rounded multiply accumulate
|
||||
{ "macwhkl", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32 x 16 (lower) 16-bit shifted multiply accumulate
|
||||
{ "macwhkul", CF_CHG1|CF_USE2|CF_USE3 }, // Unsigned 32 x 16 (lower) 16-bit shifted multiply accumulate
|
||||
{ "mpywhkl", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32 x 16 (lower) 16-bit shifted multiply
|
||||
{ "mpywhkul", CF_CHG1|CF_USE2|CF_USE3 }, // Unsigned 32 x 16 (lower) 16-bit shifted multiply
|
||||
{ "msubwhfm", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32 x 16 (upper) fractional saturating multiply subtract
|
||||
{ "msubwhfmr", CF_CHG1|CF_USE2|CF_USE3 }, // Signed 32 x 16 (upper) fractional saturating rounded multiply subtract
|
||||
|
||||
// ARCv2 32-bit extension major 6 SOP instructions
|
||||
{ "cbflyhf1r", CF_CHG1|CF_USE2 }, // Fractional 16+16 bit complex FFT butterfly, second half
|
||||
|
||||
{ "fscmp", CF_USE1|CF_USE2 }, // Single precision floating point compare
|
||||
{ "fscmpf", CF_USE1|CF_USE2 }, // Single precision floating point compare (IEEE 754 flag generation)
|
||||
{ "fsmadd", CF_CHG1|CF_USE2|CF_USE3 }, // Single precision floating point fused multiply add
|
||||
{ "fsmsub", CF_CHG1|CF_USE2|CF_USE3 }, // Single precision floating point fused multiply subtract
|
||||
{ "fsdiv", CF_CHG1|CF_USE2|CF_USE3 }, // Single precision floating point division
|
||||
{ "fcvt32", CF_CHG1|CF_USE2 }, // Single precision floating point / integer conversion
|
||||
{ "fssqrt", CF_CHG1|CF_USE2|CF_USE3 }, // Single precision floating point square root
|
||||
|
||||
// ARCv2 jump / execute indexed instructions
|
||||
{ "jli", CF_USE1|CF_CALL }, // Jump and link
|
||||
{ "ei", CF_USE1|CF_CALL }, // Execute indexed
|
||||
|
||||
{ "kflag", CF_USE1 }, // Set kernel flags
|
||||
{ "wevt", CF_USE1 }, // Enter sleep state
|
||||
};
|
||||
|
||||
CASSERT(qnumber(Instructions) == ARC_last);
|
||||
|
||||
387
idasdk76/module/arc/ins.hpp
Normal file
387
idasdk76/module/arc/ins.hpp
Normal file
@@ -0,0 +1,387 @@
|
||||
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-2021 Hex-Rays
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __INS_HPP
|
||||
#define __INS_HPP
|
||||
|
||||
extern instruc_t Instructions[];
|
||||
|
||||
enum nameNum
|
||||
{
|
||||
|
||||
ARC_null = 0, // Unknown Operation
|
||||
|
||||
ARC_ld, // Load
|
||||
ARC_lr, // Load from auxiliary register
|
||||
ARC_st, // Store
|
||||
ARC_sr, // Store to auxiliary register
|
||||
ARC_store_instructions = ARC_sr,
|
||||
ARC_flag, // Set flags
|
||||
ARC_asr, // Arithmetic shift right
|
||||
ARC_lsr, // Logical shift right
|
||||
ARC_sexb, // Sign extend byte
|
||||
ARC_sexw, // Sign extend word
|
||||
ARC_sexh = ARC_sexw,
|
||||
ARC_extb, // Zero extend byte
|
||||
ARC_extw, // Zero extend word
|
||||
ARC_exth = ARC_extw,
|
||||
ARC_ror, // Rotate right
|
||||
ARC_rrc, // Rotate right through carry
|
||||
ARC_b, // Branch
|
||||
ARC_bl, // Branch and link
|
||||
ARC_lp, // Zero-overhead loop setup
|
||||
ARC_j, // Jump
|
||||
ARC_jl, // Jump and link
|
||||
ARC_add, // Add
|
||||
ARC_adc, // Add with carry
|
||||
ARC_sub, // Subtract
|
||||
ARC_sbc, // Subtract with carry
|
||||
ARC_and, // Logical bitwise AND
|
||||
ARC_or, // Logical bitwise OR
|
||||
ARC_bic, // Logical bitwise AND with invert
|
||||
ARC_xor, // Logical bitwise exclusive-OR
|
||||
|
||||
// pseudo instructions
|
||||
ARC_mov, // Move
|
||||
ARC_nop, // No operation
|
||||
ARC_lsl, // Logical shift left
|
||||
ARC_rlc, // Rotate left through carry
|
||||
|
||||
// arc7
|
||||
ARC_brk, // Breakpoint
|
||||
ARC_sleep, // Sleep until interrupt or restart
|
||||
|
||||
// arc8
|
||||
ARC_swi, // Software interrupt
|
||||
|
||||
// extra optional instrutions
|
||||
ARC_asl, // Arithmetic shift left
|
||||
ARC_mul64, // Signed 32x32 multiply
|
||||
ARC_mulu64, // Unsigned 32x32 multiply
|
||||
ARC_max, // Maximum of two signed integers
|
||||
ARC_min, // Minimum of two signed integers
|
||||
ARC_swap, // Exchange upper and lower 16 bits
|
||||
ARC_norm, // Normalize (find-first-bit)
|
||||
|
||||
// ARCompact instructions
|
||||
ARC_bbit0, // Branch if bit cleared to 0
|
||||
ARC_bbit1, // Branch if bit set to 1
|
||||
ARC_br, // Branch on compare
|
||||
ARC_pop, // Restore register value from stack
|
||||
ARC_push, // Store register value on stack
|
||||
|
||||
ARC_abs, // Absolute value
|
||||
ARC_add1, // Add with left shift by 1 bit
|
||||
ARC_add2, // Add with left shift by 2 bits
|
||||
ARC_add3, // Add with left shift by 3 bits
|
||||
ARC_bclr, // Clear specified bit (to 0)
|
||||
ARC_bmsk, // Bit Mask
|
||||
ARC_bset, // Set specified bit (to 1)
|
||||
ARC_btst, // Test value of specified bit
|
||||
ARC_bxor, // Bit XOR
|
||||
ARC_cmp, // Compare
|
||||
ARC_ex, // Atomic Exchange
|
||||
ARC_mpy, // Signed 32x32 multiply (low)
|
||||
ARC_mpyh, // Signed 32x32 multiply (high)
|
||||
ARC_mpym = ARC_mpyh,
|
||||
ARC_mpyhu, // Unsigned 32x32 multiply (high)
|
||||
ARC_mpyhm = ARC_mpyhu,
|
||||
ARC_mpyu, // Unsigned 32x32 multiply (low)
|
||||
ARC_neg, // Negate
|
||||
ARC_not, // Logical bit inversion
|
||||
ARC_rcmp, // Reverse Compare
|
||||
ARC_rsub, // Reverse Subtraction
|
||||
ARC_rtie, // Return from Interrupt/Exception
|
||||
ARC_sub1, // Subtract with left shift by 1 bit
|
||||
ARC_sub2, // Subtract with left shift by 2 bits
|
||||
ARC_sub3, // Subtract with left shift by 3 bits
|
||||
ARC_sync, // Synchronize
|
||||
ARC_trap, // Raise an exception
|
||||
ARC_tst, // Test
|
||||
ARC_unimp, // Unimplemented instruction
|
||||
|
||||
ARC_abss, // Absolute and saturate
|
||||
ARC_abssw, // Absolute and saturate of word
|
||||
ARC_abssh = ARC_abssw,
|
||||
ARC_adds, // Add and saturate
|
||||
ARC_addsdw, // Add and saturate dual word
|
||||
ARC_asls, // Arithmetic shift left and saturate
|
||||
ARC_asrs, // Arithmetic shift right and saturate
|
||||
ARC_divaw, // Division assist
|
||||
ARC_negs, // Negate and saturate
|
||||
ARC_negsw, // Negate and saturate of word
|
||||
ARC_negsh = ARC_negsw,
|
||||
ARC_normw, // Normalize to 16 bits
|
||||
ARC_normh = ARC_normw,
|
||||
ARC_rnd16, // Round to word
|
||||
ARC_rndh = ARC_rnd16,
|
||||
ARC_sat16, // Saturate to word
|
||||
ARC_sath = ARC_sat16,
|
||||
ARC_subs, // Subtract and saturate
|
||||
ARC_subsdw, // Subtract and saturate dual word
|
||||
|
||||
// mac d16
|
||||
ARC_muldw,
|
||||
ARC_muludw,
|
||||
ARC_mulrdw,
|
||||
ARC_macdw,
|
||||
ARC_macudw,
|
||||
ARC_macrdw,
|
||||
ARC_msubdw,
|
||||
|
||||
// 32x16 MUL/MAC
|
||||
ARC_mululw,
|
||||
ARC_mullw,
|
||||
ARC_mulflw,
|
||||
ARC_maclw,
|
||||
ARC_macflw,
|
||||
ARC_machulw,
|
||||
ARC_machlw,
|
||||
ARC_machflw,
|
||||
ARC_mulhlw,
|
||||
ARC_mulhflw,
|
||||
|
||||
// Major 6 compact insns
|
||||
ARC_acm,
|
||||
ARC_addqbs,
|
||||
ARC_avgqb,
|
||||
ARC_clamp,
|
||||
ARC_daddh11,
|
||||
ARC_daddh12,
|
||||
ARC_daddh21,
|
||||
ARC_daddh22,
|
||||
ARC_dexcl1,
|
||||
ARC_dexcl2,
|
||||
ARC_dmulh11,
|
||||
ARC_dmulh12,
|
||||
ARC_dmulh21,
|
||||
ARC_dmulh22,
|
||||
ARC_dsubh11,
|
||||
ARC_dsubh12,
|
||||
ARC_dsubh21,
|
||||
ARC_dsubh22,
|
||||
ARC_drsubh11,
|
||||
ARC_drsubh12,
|
||||
ARC_drsubh21,
|
||||
ARC_drsubh22,
|
||||
ARC_fadd,
|
||||
ARC_fsadd = ARC_fadd,
|
||||
ARC_fmul,
|
||||
ARC_fsmul = ARC_fmul,
|
||||
ARC_fsub,
|
||||
ARC_fssub = ARC_fsub,
|
||||
ARC_fxtr,
|
||||
ARC_iaddr,
|
||||
ARC_mpyqb,
|
||||
ARC_sfxtr,
|
||||
ARC_pkqb,
|
||||
ARC_upkqb,
|
||||
ARC_xpkqb,
|
||||
|
||||
// ARCv2 only major 4 instructions
|
||||
ARC_mpyw, // Signed 16x16 multiply
|
||||
ARC_mpyuw, // Unsigned 16x16 multiply
|
||||
ARC_bi, // Branch indexed
|
||||
ARC_bih, // Branch indexed half-word
|
||||
ARC_ldi, // Load indexed
|
||||
ARC_aex, // Exchange with auxiliary register
|
||||
ARC_bmskn, // Bit mask negated
|
||||
ARC_seteq, // Set if equal
|
||||
ARC_setne, // Set if not equal
|
||||
ARC_setlt, // Set if less than
|
||||
ARC_setge, // Set if greater or equal
|
||||
ARC_setlo, // Set if lower than
|
||||
ARC_seths, // Set if higher or same
|
||||
ARC_setle, // Set if less than or equal
|
||||
ARC_setgt, // Set if greater than
|
||||
|
||||
ARC_rol, // Rotate left
|
||||
ARC_llock, // Load locked
|
||||
ARC_scond, // Store conditional
|
||||
|
||||
ARC_seti, // Set interrupt enable and priority level
|
||||
ARC_clri, // Cler and get interrupt enable and priority level
|
||||
|
||||
// ARCv2 compact prolog / epilog instructions
|
||||
ARC_enter, // Function prologue sequence
|
||||
ARC_leave, // Function epilogue sequence
|
||||
|
||||
// ARCv2 32-bit extension major 5 DOP instructions
|
||||
ARC_div, // Signed integer divsion
|
||||
ARC_divu, // Unsigned integer divsion
|
||||
ARC_rem, // Signed integer remainder
|
||||
ARC_remu, // Unsigned integer remainder
|
||||
ARC_asrsr, // Shift right rounding and saturating
|
||||
ARC_valgn2h, // Two-way 16-bit vector align
|
||||
ARC_setacc, // Set the accumulator
|
||||
ARC_mac, // Signed 32x32 multiply accumulate
|
||||
ARC_macu, // Unsigned 32x32 multiply accumulate
|
||||
ARC_dmpyh, // Sum of dual signed 16x16 multiplication
|
||||
ARC_dmpyhu, // Sum of dual unsigned 16x16 multiplication
|
||||
ARC_dmach, // Dual signed 16x16 multiply accumulate
|
||||
ARC_dmachu, // Dual unsigned 16x16 multiply accumulate
|
||||
ARC_vadd2h, // Dual 16-bit addition
|
||||
ARC_vadds2h, // Dual 16-bit saturating addition
|
||||
ARC_vsub2h, // Dual 16-bit subtraction
|
||||
ARC_vsubs2h, // Dual 16-bit saturating subtraction
|
||||
ARC_vaddsub2h, // Dual 16-bit addition/subtraction
|
||||
ARC_vaddsubs2h, // Dual 16-bit saturating addition/subtraction
|
||||
ARC_vsubadd2h, // Dual 16-bit subtraction/addition
|
||||
ARC_vsubadds2h, // Dual 16-bit saturating subtraction/addition
|
||||
ARC_mpyd, // Signed 32x32 multiply (wide)
|
||||
ARC_mpydu, // Unsigned 32x32 multiply (wide)
|
||||
ARC_macd, // Signed 32x32 multiply accumulate (wide)
|
||||
ARC_macdu, // Unsigned 32x32 multiply accumulate (wide)
|
||||
ARC_vmpy2h, // Dual signed 16x16 multiply (wide)
|
||||
ARC_vmpy2hf, // Dual 16x16 saturating fractional multiply
|
||||
ARC_vmpy2hu, // Dual unsigned 16x16 multiply (wide)
|
||||
ARC_vmpy2hfr, // Dual 16x16 saturating rounded fractional multiply
|
||||
ARC_vmac2h, // Dual signed 16x16 multiply (wide)
|
||||
ARC_vmac2hf, // Dual 16x16 saturating fractional multiply
|
||||
ARC_vmac2hu, // Dual unsigned 16x16 multiply (wide)
|
||||
ARC_vmac2hfr, // Dual 16x16 saturating rounded fractional multiply
|
||||
ARC_vmpy2hwf, // Dual 16x16 saturating fractional multiply (wide)
|
||||
ARC_vasl2h, // Dual 16-bit arithmetic shift left
|
||||
ARC_vasls2h, // Dual 16-bit saturating arithmetic shift left
|
||||
ARC_vasr2h, // Dual 16-bit arithmetic shift right
|
||||
ARC_vasrs2h, // Dual 16-bit saturating arithmetic shift right
|
||||
ARC_vlsr2h, // Dual 16-bit logical shift right
|
||||
ARC_vasrsr2h, // Dual 16-bit saturating rounded arithmetic shift right
|
||||
ARC_vadd4b, // Quad 8-bit addition
|
||||
ARC_vmax2h, // Dual 16-bit maximum
|
||||
ARC_vsub4b, // Quad 8-bit subtraction
|
||||
ARC_vmin2h, // Dual 16-bit minimum
|
||||
ARC_adcs, // Signed saturating addition with carry in
|
||||
ARC_sbcs, // Signed saturating subtraction with carry in
|
||||
ARC_dmpyhwf, // Fractional saturating sum of dual 16x16 signed fractional multiply
|
||||
ARC_vpack2hl, // Compose lower 16-bits
|
||||
ARC_vpack2hm, // Compose upper 16-bits
|
||||
ARC_dmpyhf, // Saturating sum of dual 16x16 signed fractional multiply
|
||||
ARC_dmpyhfr, // Saturating rounded sum of dual 16x16 signed fractional multiply
|
||||
ARC_dmachf, // Saturating sum of dual 16x16 signed fractional multiply accumulate
|
||||
ARC_dmachfr, // Saturating rounded sum of dual 16x16 signed fractional multiply accumulate
|
||||
ARC_vperm, // Byte permutation with zero or sign extension
|
||||
ARC_bspush, // Bitstream push
|
||||
|
||||
// ARCv2 32-bit extension major 5 SOP instructions
|
||||
ARC_swape, // Swap byte ordering
|
||||
ARC_lsl16, // Logical shift left by 16 bits
|
||||
ARC_lsr16, // Logical shift right by 16 bits
|
||||
ARC_asr16, // Arithmetic shift right by 16 bits
|
||||
ARC_asr8, // Arithmetic shift right by 8 bits
|
||||
ARC_lsr8, // Logical shift right by 8 bits
|
||||
ARC_lsl8, // Logical shift left by 8 bits
|
||||
ARC_rol8, // Rotate left by 8 bits
|
||||
ARC_ror8, // Rotate right by 8 bits
|
||||
ARC_ffs, // Find first set bit
|
||||
ARC_fls, // Find last set bit
|
||||
|
||||
ARC_getacc, // Get accumulator
|
||||
ARC_normacc, // Normalize accumulator
|
||||
ARC_satf, // Saturate according to flags
|
||||
ARC_vpack2hbl, // Pack lower bytes into lower 16 bits
|
||||
ARC_vpack2hbm, // Pack upper bytes into upper 16 bits
|
||||
ARC_vpack2hblf, // Pack upper bytes into lower 16 bits
|
||||
ARC_vpack2hbmf, // Pack lower bytes into upper 16 bits
|
||||
ARC_vext2bhlf, // Pack lower 2 bytes into upper byte of 16 bits each
|
||||
ARC_vext2bhmf, // Pack upper 2 bytes into upper byte of 16 bits each
|
||||
ARC_vrep2hl, // Repeat lower 16 bits
|
||||
ARC_vrep2hm, // Repeat upper 16 bits
|
||||
ARC_vext2bhl, // Pack lower 2 bytes into zero extended 16 bits
|
||||
ARC_vext2bhm, // Pack upper 2 bytes into zero extended 16 bits
|
||||
ARC_vsext2bhl, // Pack lower 2 bytes into sign extended 16 bits
|
||||
ARC_vsext2bhm, // Pack upper 2 bytes into sign extended 16 bits
|
||||
ARC_vabs2h, // Dual 16-bit absolute value
|
||||
ARC_vabss2h, // Dual saturating 16-bit absolute value
|
||||
ARC_vneg2h, // Dual 16-bit negation
|
||||
ARC_vnegs2h, // Dual saturating 16-bit negation
|
||||
ARC_vnorm2h, // Dual 16-bit normalization
|
||||
ARC_bspeek, // Bitstream peek
|
||||
ARC_bspop, // Bitstream pop
|
||||
ARC_sqrt, // Integer square root
|
||||
ARC_sqrtf, // Fractional square root
|
||||
|
||||
// ARCv2 32-bit extension major 5 ZOP instructions
|
||||
ARC_aslacc, // Arithmetic shift of accumulator
|
||||
ARC_aslsacc, // Saturating arithmetic shift of accumulator
|
||||
ARC_flagacc, // Copy accumulator flags to status32 register
|
||||
ARC_modif, // Update address pointer
|
||||
|
||||
// ARCv2 32-bit extension major 6 DOP instructions
|
||||
ARC_cmpyhnfr, // Fractional 16+16 bit complex saturating rounded unshifted multiply
|
||||
ARC_cmpyhfr, // Fractional 16+16 bit complex saturating rounded multiply
|
||||
ARC_cmpychfr, // Fractional 16+16 bit complex saturating rounded conjugated multiply
|
||||
ARC_vmsub2hf, // Dual 16x16 saturating fractional multiply subtract
|
||||
ARC_vmsub2hfr, // Dual 16x16 saturating rounded fractional multiply subtract
|
||||
ARC_cmpychnfr, // Fractional 16+16 bit complex saturating rounded unshifted conjugated multiply
|
||||
ARC_cmachnfr, // Fractional 16+16 bit complex saturating rounded unshifted multiply accumulate
|
||||
ARC_cmachfr, // Fractional 16+16 bit complex saturating rounded unshifted accumulate
|
||||
ARC_cmacchnfr, // Fractional 16+16 bit complex saturating rounded conjugated multiply accumulate
|
||||
ARC_cmacchfr, // Fractional 16+16 bit complex saturating rounded unshifted conjugated multiply accumulate
|
||||
ARC_mpyf, // Signed 32-bit fractional saturating multiply
|
||||
ARC_mpyfr, // Signed 32-bit fractional saturating rounded multiply
|
||||
ARC_macf, // Signed 32-bit fractional saturating multiply accumulate
|
||||
ARC_macfr, // Signed 32-bit fractional saturating rounded multiply accumulate
|
||||
ARC_msubf, // Signed 32-bit fractional saturating multiply subtract
|
||||
ARC_msubfr, // Signed 32-bit fractional saturating rounded multiply subtract
|
||||
ARC_divf, // Signed 32-bit fractional division
|
||||
ARC_vmac2hnfr, // Dual signed 16-bit fractional saturating rounded multiply accumulate
|
||||
ARC_vmsub2hnfr, // Dual signed 16-bit fractional saturating rounded multiply subtract
|
||||
ARC_mpydf, // Signed 32-bit fractional multiply (wide)
|
||||
ARC_macdf, // Signed 32-bit fractional multiply accumulate (wide)
|
||||
ARC_msubwhfl, // Signed 32 x 16 (lower) fractional saturating multiply subtract
|
||||
ARC_msubdf, // Signed 32-bit fractional multiply subtract (wide)
|
||||
ARC_dmpyhbl, // Dual 16x8 signed multiply with lower two bytes
|
||||
ARC_dmpyhbm, // Dual 16x8 signed multiply with upper two bytes
|
||||
ARC_dmachbl, // Dual 16x8 signed multiply accumulate with lower two bytes
|
||||
ARC_dmachbm, // Dual 16x8 signed multiply accumulate with upper two bytes
|
||||
ARC_msubwhflr, // Signed 32 x 16 (lower) fractional saturating rounded multiply subtract
|
||||
ARC_cmpyhfmr, // Fractional 16+16 bit complex x 16bit real (upper) saturating rounded multiply
|
||||
ARC_cbflyhf0r, // Fractional 16+16 bit complex FFT butterfly, first half
|
||||
ARC_mpywhl, // Signed 32 x 16 (lower) multiply
|
||||
ARC_macwhl, // Signed 32 x 16 (lower) multiply accumulate
|
||||
ARC_mpywhul, // Unsigned 32 x 16 (lower) multiply
|
||||
ARC_macwhul, // Unsigned 32 x 16 (lower) multiply accumulate
|
||||
ARC_mpywhfm, // Signed 32 x 16 (upper) fractional saturating multiply
|
||||
ARC_mpywhfmr, // Signed 32 x 16 (upper) fractional saturating rounded multiply
|
||||
ARC_macwhfm, // Signed 32 x 16 (upper) fractional saturating multiply accumulate
|
||||
ARC_macwhfmr, // Signed 32 x 16 (upper) fractional saturating rounded multiply accumulate
|
||||
ARC_mpywhfl, // Signed 32 x 16 (lower) fractional saturating multiply
|
||||
ARC_mpywhflr, // Signed 32 x 16 (lower) fractional saturating rounded multiply
|
||||
ARC_macwhfl, // Signed 32 x 16 (lower) fractional saturating multiply accumulate
|
||||
ARC_macwhflr, // Signed 32 x 16 (lower) fractional saturating rounded multiply accumulate
|
||||
ARC_macwhkl, // Signed 32 x 16 (lower) 16-bit shifted multiply accumulate
|
||||
ARC_macwhkul, // Unsigned 32 x 16 (lower) 16-bit shifted multiply accumulate
|
||||
ARC_mpywhkl, // Signed 32 x 16 (lower) 16-bit shifted multiply
|
||||
ARC_mpywhkul, // Unsigned 32 x 16 (lower) 16-bit shifted multiply
|
||||
ARC_msubwhfm, // Signed 32 x 16 (upper) fractional saturating multiply subtract
|
||||
ARC_msubwhfmr, // Signed 32 x 16 (upper) fractional saturating rounded multiply subtract
|
||||
|
||||
// ARCv2 32-bit extension major 6 SOP instructions
|
||||
ARC_cbflyhf1r, // Fractional 16+16 bit complex FFT butterfly, second half
|
||||
|
||||
// ARCv2 FPU instructions
|
||||
ARC_fscmp, // Single precision floating point compare
|
||||
ARC_fscmpf, // Single precision floating point compare (IEEE 754 flag generation)
|
||||
ARC_fsmadd, // Single precision floating point fused multiply add
|
||||
ARC_fsmsub, // Single precision floating point fused multiply subtract
|
||||
ARC_fsdiv, // Single precision floating point division
|
||||
ARC_fcvt32, // Single precision floating point / integer conversion
|
||||
ARC_fssqrt, // Single precision floating point square root
|
||||
|
||||
// ARCv2 jump / execute indexed instructions
|
||||
ARC_jli, // Jump and link indexed
|
||||
ARC_ei, // Execute indexed
|
||||
|
||||
ARC_kflag, // Set kernel flags
|
||||
ARC_wevt, // Enter sleep state
|
||||
|
||||
ARC_last,
|
||||
};
|
||||
|
||||
#endif
|
||||
57
idasdk76/module/arc/makefile
Normal file
57
idasdk76/module/arc/makefile
Normal file
@@ -0,0 +1,57 @@
|
||||
PROC=arc
|
||||
CONFIGS=arc.cfg
|
||||
|
||||
|
||||
include ../module.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \
|
||||
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
|
||||
../iohandler.hpp ana.cpp arc.hpp ins.hpp
|
||||
$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \
|
||||
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)jumptable.hpp \
|
||||
$(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \
|
||||
$(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp \
|
||||
$(I)pro.h $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)segregs.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \
|
||||
../idaidp.hpp ../iohandler.hpp arc.hpp emu.cpp ins.hpp
|
||||
$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)entry.hpp $(I)fpro.h $(I)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)typeinf.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
|
||||
../iohandler.hpp arc.hpp ins.cpp ins.hpp
|
||||
$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)entry.hpp $(I)fpro.h $(I)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)typeinf.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
|
||||
../iohandler.hpp arc.hpp ins.hpp out.cpp
|
||||
$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)entry.hpp $(I)fpro.h $(I)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)typeinf.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
|
||||
../iohandler.hpp arc.hpp ins.hpp reg.cpp
|
||||
539
idasdk76/module/arc/out.cpp
Normal file
539
idasdk76/module/arc/out.cpp
Normal file
@@ -0,0 +1,539 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-98 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@estar.msk.su, ig@datarescue.com
|
||||
* FIDO: 2:5020/209
|
||||
*
|
||||
*/
|
||||
|
||||
#include "arc.hpp"
|
||||
|
||||
// generic condition codes
|
||||
static const char *const ccode[] =
|
||||
{
|
||||
"", ".z", ".nz", ".p",
|
||||
".n", ".c", ".nc", ".v",
|
||||
".nv", ".gt", ".ge", ".lt",
|
||||
".le", ".hi", ".ls", ".pnz",
|
||||
".ss", ".sc", ".c0x12", ".c0x13",
|
||||
".c0x14", ".c0x15", ".c0x16", ".c0x17",
|
||||
".c0x18", ".c0x19", ".c0x1A", ".c0x1B",
|
||||
".c0x1C", ".c0x1D", ".c0x1E", ".c0x1F",
|
||||
};
|
||||
|
||||
// generic condition codes for ARCv2
|
||||
static const char *const ccode_v2[] =
|
||||
{
|
||||
"", ".eq", ".ne", ".p",
|
||||
".n", ".c", ".nc", ".v",
|
||||
".nv", ".gt", ".ge", ".lt",
|
||||
".le", ".hi", ".ls", ".pnz",
|
||||
".c0x10", ".c0x11", ".c0x12", ".c0x13",
|
||||
".c0x14", ".c0x15", ".c0x16", ".c0x17",
|
||||
".c0x18", ".c0x19", ".c0x1A", ".c0x1B",
|
||||
".c0x1C", ".c0x1D", ".c0x1E", ".c0x1F",
|
||||
};
|
||||
|
||||
|
||||
// condition codes for branches
|
||||
static const char *const ccode_b[] =
|
||||
{
|
||||
"", "eq", "ne", "pl",
|
||||
"mi", "lo", "hs", "vs",
|
||||
"vc", "gt", "ge", "lt",
|
||||
"le", "hi", "ls", "pnz",
|
||||
"ss", "sc", "c0x12", "c0x13",
|
||||
"c0x14", "c0x15", "c0x16", "c0x17",
|
||||
"c0x18", "c0x19", "c0x1A", "c0x1B",
|
||||
"c0x1C", "c0x1D", "c0x1E", "c0x1F",
|
||||
};
|
||||
|
||||
// condition codes for ARCv2 branches
|
||||
static const char *const ccode_b_v2[] =
|
||||
{
|
||||
"", "eq", "ne", "p",
|
||||
"n", "lo", "hs", "v",
|
||||
"nv", "gt", "ge", "lt",
|
||||
"le", "hi", "ls", "pnz",
|
||||
"c0x10", "c0x11", "c0x12", "c0x13",
|
||||
"c0x14", "c0x15", "c0x16", "c0x17",
|
||||
"c0x18", "c0x19", "c0x1A", "c0x1B",
|
||||
"c0x1C", "c0x1D", "c0x1E", "c0x1F",
|
||||
};
|
||||
|
||||
|
||||
/* jump delay slot codes */
|
||||
static const char ncode[][4] = { "", ".d", ".jd", ".d?" };
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
class out_arc_t : public outctx_t
|
||||
{
|
||||
out_arc_t(void) = delete; // not used
|
||||
void set_gr_cmt(const char *cmt) { user_data = (void *)cmt; }
|
||||
const char *get_gr_cmt(void) const { return (const char *)user_data; }
|
||||
public:
|
||||
void outreg(int rn);
|
||||
|
||||
bool out_operand(const op_t &x);
|
||||
void out_insn(void);
|
||||
void out_proc_mnem(void);
|
||||
void out_specreg(const ioports_t &table, const op_t &x);
|
||||
void out_aux(const op_t &x)
|
||||
{
|
||||
arc_t &pm = *static_cast<arc_t *>(procmod);
|
||||
out_specreg(pm.auxregs, x);
|
||||
}
|
||||
};
|
||||
CASSERT(sizeof(out_arc_t) == sizeof(outctx_t));
|
||||
|
||||
DECLARE_OUT_FUNCS(out_arc_t)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_arc_t::outreg(int rn)
|
||||
{
|
||||
const char *regname = (rn < ph.regs_num) ? ph.reg_names[rn] : "<bad register>";
|
||||
out_register(regname);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_arc_t::out_specreg(const ioports_t &table, const op_t &x)
|
||||
{
|
||||
const ioport_t *reg = find_ioport(table, x.value);
|
||||
if ( reg == NULL )
|
||||
{
|
||||
out_symbol('[');
|
||||
out_value(x, OOFS_IFSIGN | OOFW_32);
|
||||
out_symbol(']');
|
||||
}
|
||||
else
|
||||
{
|
||||
out_register(reg->name.c_str());
|
||||
if ( !reg->cmt.empty() && !has_cmt(F) )
|
||||
set_gr_cmt(reg->cmt.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
/* outputs an operand 'x' */
|
||||
bool out_arc_t::out_operand(const op_t & x)
|
||||
{
|
||||
arc_t &pm = *static_cast<arc_t *>(procmod);
|
||||
ea_t v;
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_reg:
|
||||
outreg(x.reg);
|
||||
break;
|
||||
|
||||
case o_phrase:
|
||||
{
|
||||
int hidden_base = is_hidden_base_reg(x.reg);
|
||||
if ( hidden_base != -1 )
|
||||
out_symbol('[');
|
||||
if ( hidden_base == 0 )
|
||||
{
|
||||
outreg(x.reg);
|
||||
out_symbol(',');
|
||||
}
|
||||
outreg(x.secreg);
|
||||
if ( hidden_base != -1 )
|
||||
out_symbol(']');
|
||||
}
|
||||
break;
|
||||
|
||||
case o_imm:
|
||||
// check for: LR <dest>, [aux]
|
||||
// SR <src>, [aux]
|
||||
if ( x.n == 1
|
||||
&& !is_defarg(F, x.n) // don't use aux register if op type is set
|
||||
&& (insn.itype == ARC_lr || insn.itype == ARC_sr) )
|
||||
out_aux(x);
|
||||
else
|
||||
out_value(x, OOFS_IFSIGN | OOFW_IMM);
|
||||
break;
|
||||
|
||||
case o_mem:
|
||||
{
|
||||
ea_t ea = to_ea(insn.cs, x.addr);
|
||||
if ( (insn.auxpref & aux_pcload) != 0 )
|
||||
{
|
||||
// A little hack to make the output
|
||||
// more readable...
|
||||
op_t y;
|
||||
if ( pm.copy_insn_optype(insn, x, ea, &y.value) )
|
||||
{
|
||||
y.dtype = x.dtype;
|
||||
y.flags = OF_SHOW;
|
||||
out_symbol('=');
|
||||
set_dlbind_opnd();
|
||||
ea_t insn_ea_sav = insn_ea;
|
||||
flags_t savedF = F;
|
||||
insn_ea = ea; // change context
|
||||
F = get_flags(ea);
|
||||
out_value(y, OOFS_IFSIGN|OOFW_IMM);
|
||||
insn_ea = insn_ea_sav; // restore context
|
||||
F = savedF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
out_symbol('[');
|
||||
if ( insn.itype != ARC_lr && insn.itype != ARC_sr )
|
||||
{
|
||||
if ( !out_name_expr(x, ea, x.addr) )
|
||||
{
|
||||
out_tagon(COLOR_ERROR);
|
||||
out_btoa(uint32(x.addr), 16);
|
||||
out_tagoff(COLOR_ERROR);
|
||||
remember_problem(PR_NONAME, insn.ea);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
out_btoa(uint32(x.addr), 16);
|
||||
}
|
||||
if ( x.immdisp != 0 )
|
||||
{
|
||||
out_symbol('-');
|
||||
out_btoa(uint32(x.immdisp * get_scale_factor(insn)), 16);
|
||||
out_symbol(',');
|
||||
out_btoa(uint32(x.immdisp), 16);
|
||||
}
|
||||
out_symbol(']');
|
||||
}
|
||||
break;
|
||||
|
||||
case o_near:
|
||||
v = to_ea(insn.cs, x.addr);
|
||||
if ( !out_name_expr(x, v, x.addr) )
|
||||
{
|
||||
out_value(x, OOF_ADDR|OOF_NUMBER|OOFS_NOSIGN|OOFW_32);
|
||||
remember_problem(PR_NONAME, insn.ea);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case o_displ:
|
||||
{
|
||||
// membase=0: [reg, #addr]
|
||||
// membase=1: [#addr, reg]
|
||||
int hidden_base = is_hidden_base_reg(x.reg);
|
||||
if ( hidden_base != -1 )
|
||||
out_symbol('[');
|
||||
if ( x.membase == 0 && hidden_base == 0 )
|
||||
outreg(x.reg);
|
||||
if ( x.addr != 0
|
||||
|| hidden_base != 0
|
||||
|| is_off(F, x.n)
|
||||
|| is_stkvar(F, x.n)
|
||||
|| is_enum(F, x.n)
|
||||
|| is_stroff(F, x.n) )
|
||||
{
|
||||
if ( x.membase == 0 && hidden_base == 0 )
|
||||
out_symbol(',');
|
||||
out_value(x, OOF_ADDR|OOFS_IFSIGN|OOF_SIGNED|OOFW_32);
|
||||
if ( x.membase != 0 )
|
||||
out_symbol(',');
|
||||
}
|
||||
if ( x.membase != 0 )
|
||||
outreg(x.reg);
|
||||
if ( hidden_base != -1 )
|
||||
out_symbol(']');
|
||||
}
|
||||
break;
|
||||
|
||||
case o_reglist:
|
||||
{
|
||||
out_symbol('{');
|
||||
bool need_comma = false;
|
||||
int regs = x.reglist & REGLIST_REGS;
|
||||
if ( regs > REGLISTR_MAX )
|
||||
{
|
||||
out_tagon(COLOR_ERROR);
|
||||
out_btoa(regs, 16);
|
||||
out_tagoff(COLOR_ERROR);
|
||||
need_comma = true;
|
||||
}
|
||||
else if ( regs > 0 )
|
||||
{
|
||||
outreg(R13);
|
||||
if ( regs > 1 )
|
||||
{
|
||||
out_symbol('-');
|
||||
outreg(R13 + regs - 1);
|
||||
}
|
||||
need_comma = true;
|
||||
}
|
||||
if ( (x.reglist & REGLIST_FP) != 0 )
|
||||
{
|
||||
if ( need_comma )
|
||||
out_symbol(',');
|
||||
outreg(FP);
|
||||
need_comma = true;
|
||||
}
|
||||
if ( (x.reglist & REGLIST_BLINK) != 0 )
|
||||
{
|
||||
if ( need_comma )
|
||||
out_symbol(',');
|
||||
outreg(BLINK);
|
||||
need_comma = true;
|
||||
}
|
||||
if ( (x.reglist & REGLIST_PCL) != 0 )
|
||||
{
|
||||
if ( need_comma )
|
||||
out_symbol(',');
|
||||
outreg(PCL);
|
||||
need_comma = true;
|
||||
}
|
||||
out_symbol('}');
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
out_symbol('?');
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline bool is_branch(const insn_t &insn)
|
||||
{
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case ARC_b:
|
||||
case ARC_lp:
|
||||
case ARC_bl:
|
||||
case ARC_j:
|
||||
case ARC_jl:
|
||||
case ARC_br:
|
||||
case ARC_bbit0:
|
||||
case ARC_bbit1:
|
||||
return true;
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
// delay slot bits must be only set for branches
|
||||
QASSERT(10184, !has_dslot(insn));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_arc_t::out_proc_mnem(void)
|
||||
{
|
||||
arc_t &pm = *static_cast<arc_t *>(procmod);
|
||||
char postfix[MAXSTR];
|
||||
postfix[0] = '\0';
|
||||
if ( insn.itype == ARC_null )
|
||||
{
|
||||
uint32 code = get_dword(insn.ea);
|
||||
|
||||
int i = (code>>27)&31;
|
||||
if ( i == 3 )
|
||||
{
|
||||
int c = (code>>9)&63;
|
||||
qsnprintf(postfix, sizeof(postfix), "ext%02X_%02X", i, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
qsnprintf(postfix, sizeof(postfix), "ext%02X", i);
|
||||
}
|
||||
}
|
||||
|
||||
/* if we have a load or store instruction, flags are used a bit different */
|
||||
if ( insn.itype <= ARC_store_instructions )
|
||||
{
|
||||
switch ( insn.auxpref & aux_zmask )
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case aux_b:
|
||||
qstrncat(postfix, "b", sizeof(postfix));
|
||||
break;
|
||||
case aux_w:
|
||||
qstrncat(postfix, pm.is_arcv2() ? "h" : "w", sizeof(postfix));
|
||||
break;
|
||||
default:
|
||||
qstrncat(postfix, "?", sizeof(postfix));
|
||||
break;
|
||||
}
|
||||
if ( (insn.auxpref & aux_s) != 0 )
|
||||
qstrncat(postfix, "_s", sizeof(postfix));
|
||||
if ( insn.auxpref & aux_x )
|
||||
qstrncat(postfix, ".x", sizeof(postfix));
|
||||
switch ( insn.auxpref & aux_amask )
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case aux_a:
|
||||
qstrncat(postfix, ".a", sizeof(postfix));
|
||||
break;
|
||||
case aux_as:
|
||||
qstrncat(postfix, ".as", sizeof(postfix));
|
||||
break;
|
||||
case aux_ab:
|
||||
qstrncat(postfix, ".ab", sizeof(postfix));
|
||||
break;
|
||||
default:
|
||||
qstrncat(postfix, "?", sizeof(postfix));
|
||||
break;
|
||||
}
|
||||
if ( insn.auxpref & aux_di )
|
||||
qstrncat(postfix, ".di", sizeof(postfix));
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8 cond = insn.auxpref & aux_cmask;
|
||||
if ( cond != cAL && is_branch(insn) )
|
||||
{
|
||||
if ( pm.is_arcv2() )
|
||||
qstrncat(postfix, ccode_b_v2[cond], sizeof(postfix));
|
||||
else
|
||||
qstrncat(postfix, ccode_b[cond], sizeof(postfix));
|
||||
}
|
||||
|
||||
if ( (insn.auxpref & aux_s) != 0 )
|
||||
qstrncat(postfix, "_s", sizeof(postfix));
|
||||
|
||||
if ( cond != cAL && !is_branch(insn) )
|
||||
{
|
||||
if ( pm.is_arcv2() )
|
||||
qstrncat(postfix, ccode_v2[cond], sizeof(postfix));
|
||||
else
|
||||
qstrncat(postfix, ccode[cond], sizeof(postfix));
|
||||
}
|
||||
}
|
||||
if ( is_branch(insn) ) // delay slot code
|
||||
qstrncat(postfix, ncode[(insn.auxpref >> 5) & 3], sizeof(postfix));
|
||||
else if ( (insn.auxpref & aux_f) != 0 )
|
||||
{
|
||||
// for these load/store like instructions, the f bit is used for the .di
|
||||
if ( insn.itype == ARC_ex
|
||||
|| insn.itype == ARC_llock
|
||||
|| insn.itype == ARC_scond )
|
||||
{
|
||||
qstrncat(postfix, ".di", sizeof(postfix));
|
||||
}
|
||||
else if ( insn.itype != ARC_flag // flag implicitly sets this bit
|
||||
&& insn.itype != ARC_rcmp ) // rcmp implicitly sets this bit
|
||||
{
|
||||
qstrncat(postfix, ".f", sizeof(postfix));
|
||||
}
|
||||
}
|
||||
|
||||
if ( pm.is_arcv2() && ( insn.auxpref & aux_bhint ) != 0 )
|
||||
{
|
||||
// print static prediction hint
|
||||
/*
|
||||
from "Assembler Syntax for Static Branch Predictions"
|
||||
The default static prediction, in the absence of any <.T> syntax, is always BTFN (Backwards Taken, Forwards Not Taken).
|
||||
Therefore, a BRcc instruction always has the Y bit set to 0 by default, whereas a BBITn instruction always has the Y bit set to 1
|
||||
by default.
|
||||
*/
|
||||
bool backwards = insn.Op3.addr <= insn.ea;
|
||||
const char *suf = NULL;
|
||||
if ( insn.itype == ARC_br )
|
||||
suf = backwards ? ".t" : ".nt";
|
||||
else
|
||||
suf = backwards ? ".nt" : ".t";
|
||||
qstrncat(postfix, suf, sizeof(postfix));
|
||||
}
|
||||
|
||||
out_mnem(8, postfix); // output instruction mnemonics
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_arc_t::out_insn(void)
|
||||
{
|
||||
arc_t &pm = *static_cast<arc_t *>(procmod);
|
||||
out_mnemonic();
|
||||
if ( insn.Op1.type != o_void )
|
||||
out_one_operand(0); // output the first operand
|
||||
|
||||
for ( int i = 1; i < PROC_MAXOP; ++i )
|
||||
{
|
||||
if ( insn.ops[i].type != o_void )
|
||||
{
|
||||
if ( !(insn.ops[i].type == o_reg && insn.ops[i].regpair) )
|
||||
{
|
||||
out_symbol(',');
|
||||
out_char(' ');
|
||||
}
|
||||
out_one_operand(i); // output the current operand
|
||||
}
|
||||
}
|
||||
|
||||
// output a character representation of the immediate values
|
||||
// embedded in the instruction as comments
|
||||
out_immchar_cmts();
|
||||
|
||||
// add comments for indirect calls or calculated data xrefs
|
||||
nodeidx_t callee = pm.get_callee(insn.ea);
|
||||
if ( callee == BADADDR )
|
||||
callee = pm.get_dxref(insn.ea);
|
||||
if ( callee != BADADDR )
|
||||
set_comment_addr(callee & ~1);
|
||||
const char *gr_cmt = get_gr_cmt();
|
||||
if ( gr_cmt != NULL )
|
||||
{
|
||||
out_char(' ');
|
||||
out_line(ash.cmnt, COLOR_AUTOCMT);
|
||||
out_char(' ');
|
||||
|
||||
out_line(gr_cmt, COLOR_AUTOCMT);
|
||||
if ( ash.cmnt2 != NULL )
|
||||
{
|
||||
out_char(' ');
|
||||
out_line(ash.cmnt2, COLOR_AUTOCMT);
|
||||
}
|
||||
}
|
||||
flush_outbuf();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// generate start of the disassembly
|
||||
|
||||
void idaapi arc_header(outctx_t &ctx)
|
||||
{
|
||||
ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// generate start of a segment
|
||||
//lint -esym(1764, ctx) could be made const
|
||||
//lint -esym(818, Sarea) could be made const
|
||||
void arc_t::arc_segstart(outctx_t &ctx, segment_t *Sarea) const
|
||||
{
|
||||
qstring name;
|
||||
get_visible_segm_name(&name, Sarea);
|
||||
ctx.gen_printf(0, COLSTR(".section %s", SCOLOR_ASMDIR), name.c_str());
|
||||
if ( (inf_get_outflags() & OFLG_GEN_ORG) != 0 )
|
||||
{
|
||||
adiff_t org = ctx.insn_ea - get_segm_base(Sarea);
|
||||
|
||||
if ( org != 0 )
|
||||
{
|
||||
char buf[MAX_NUMBUF];
|
||||
|
||||
btoa(buf, sizeof(buf), org);
|
||||
ctx.gen_printf(0, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// generate end of the disassembly
|
||||
void idaapi arc_footer(outctx_t &ctx)
|
||||
{
|
||||
ctx.gen_empty_line();
|
||||
|
||||
ctx.out_line(".end", COLOR_ASMDIR);
|
||||
|
||||
qstring name;
|
||||
if ( get_colored_name(&name, inf_get_start_ea()) > 0 )
|
||||
{
|
||||
ctx.out_line(" #");
|
||||
ctx.out_line(name.begin());
|
||||
}
|
||||
ctx.flush_outbuf(DEFAULT_INDENT);
|
||||
}
|
||||
908
idasdk76/module/arc/reg.cpp
Normal file
908
idasdk76/module/arc/reg.cpp
Normal file
@@ -0,0 +1,908 @@
|
||||
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-98 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
* E-mail: ig@estar.msk.su, ig@datarescue.com
|
||||
* FIDO: 2:5020/209
|
||||
*
|
||||
*/
|
||||
|
||||
#include "arc.hpp"
|
||||
int data_id;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const char *const RegNames[] =
|
||||
{
|
||||
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", // 0 .. 7
|
||||
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", // 8 .. 15
|
||||
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", // 16 .. 23
|
||||
"r24", "r25", "gp", "fp", "sp", "ilink1", "ilink2", "blink", // 23 .. 31
|
||||
|
||||
"r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", // 31 .. 39
|
||||
"r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47", // 40 .. 47
|
||||
"r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55", // 48 .. 55
|
||||
"r56", "mlo", "mmid", "mhi","lp_count", "r61", "<limm>", "pcl", // 56 .. 63
|
||||
// condition codes
|
||||
"CF", "ZF", "NF", "VF",
|
||||
|
||||
// registers used for indexed instructions
|
||||
"next_pc",
|
||||
"ldi_base", "jli_base", "ei_base",
|
||||
|
||||
"gp_base",
|
||||
|
||||
"cs", "ds"
|
||||
};
|
||||
|
||||
static const uchar codeseq_arcompact[] = { 0xF1, 0xC0 }; // push blink
|
||||
static const uchar codeseq_arctg4[] = { 0x04, 0x3E, 0x0E, 0x10 }; // st blink, [sp,4]
|
||||
|
||||
static const bytes_t codestart_arcompact[] =
|
||||
{
|
||||
{ sizeof(codeseq_arcompact), codeseq_arcompact },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static const bytes_t codestart_arctg4[] =
|
||||
{
|
||||
{ sizeof(codeseq_arctg4), codeseq_arctg4 },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void arc_t::set_codeseqs() const
|
||||
{
|
||||
switch ( ptype )
|
||||
{
|
||||
case prc_arc:
|
||||
ph.codestart = codestart_arctg4;
|
||||
break;
|
||||
case prc_arcompact:
|
||||
case prc_arcv2:
|
||||
ph.codestart = codestart_arcompact;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// new names for old instructions in ARCv2
|
||||
//lint -e{958} padding of 6 bytes needed to align member on a 8 byte boundary
|
||||
struct instruc_alt_name_t
|
||||
{
|
||||
uint16 itype;
|
||||
const char *old_name; // ARCompact name
|
||||
const char *new_name; // ARCv2 name
|
||||
};
|
||||
|
||||
static const instruc_alt_name_t InstructionNamesARCv2[] =
|
||||
{
|
||||
{ ARC_mpyh, "mpyh", "mpym" },
|
||||
{ ARC_mpyhu, "mpyhu", "mpymu" },
|
||||
{ ARC_sexw, "sexw", "sexh" },
|
||||
{ ARC_extw, "extw", "exth" },
|
||||
{ ARC_sat16, "sat16", "sath" },
|
||||
{ ARC_rnd16, "rnd16", "rndh" },
|
||||
{ ARC_abssw, "abssw", "abssh" },
|
||||
{ ARC_negsw, "negsw", "negsh" },
|
||||
{ ARC_normw, "normw", "normh" },
|
||||
{ ARC_fadd, "fadd", "fsadd" },
|
||||
{ ARC_fmul, "fmul", "fsmul" },
|
||||
{ ARC_fsub, "fsub", "fssub" },
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
arc_t::arc_t()
|
||||
{
|
||||
memcpy(Instructions, ::Instructions, sizeof(Instructions));
|
||||
ph.instruc = Instructions;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// updates names in Instruction array to match the subtype
|
||||
void arc_t::set_instruc_names()
|
||||
{
|
||||
for ( int i = 0; i < qnumber(InstructionNamesARCv2); ++i )
|
||||
{
|
||||
const instruc_alt_name_t &name = InstructionNamesARCv2[i];
|
||||
Instructions[name.itype].name = is_arcv2() ? name.new_name : name.old_name;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// updates affected global state after a ptype change
|
||||
void arc_t::ptype_changed()
|
||||
{
|
||||
set_codeseqs();
|
||||
set_instruc_names();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// handler for some IDB events
|
||||
ssize_t idaapi pm_idb_listener_t::on_event(ssize_t notification_code, va_list va)
|
||||
{
|
||||
switch ( notification_code )
|
||||
{
|
||||
case idb_event::op_type_changed:
|
||||
// An operand type (offset, hex, etc...) has been set or deleted
|
||||
{
|
||||
ea_t ea = va_arg(va, ea_t);
|
||||
int n = va_arg(va, int);
|
||||
if ( n >= 0 && n < UA_MAXOP && is_code(get_flags(ea)) )
|
||||
{
|
||||
insn_t insn;
|
||||
decode_insn(&insn, ea);
|
||||
op_t &x = insn.ops[n];
|
||||
if ( x.type == o_mem )
|
||||
{
|
||||
ea = to_ea(insn.cs, x.addr);
|
||||
pm.copy_insn_optype(insn, x, ea, NULL, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// ASMI
|
||||
//-----------------------------------------------------------------------
|
||||
static const asm_t gnuas =
|
||||
{
|
||||
AS_COLON | AS_N2CHR | AS_1TEXT | ASH_HEXF3 | ASO_OCTF1 | ASB_BINF3
|
||||
|AS_ONEDUP | AS_ASCIIC,
|
||||
0,
|
||||
"GNU assembler",
|
||||
0,
|
||||
NULL, // no headers
|
||||
".org", // org directive
|
||||
0, // end directive
|
||||
"#", // comment string
|
||||
'"', // string delimiter
|
||||
'\'', // char delimiter
|
||||
"\\\"'", // special symbols in char and string constants
|
||||
|
||||
".ascii", // ascii string directive
|
||||
".byte", // byte directive
|
||||
".short", // word directive
|
||||
".long", // dword (4 bytes)
|
||||
".quad", // qword (8 bytes)
|
||||
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
|
||||
".", // curent ip
|
||||
NULL, // func_header
|
||||
NULL, // func_footer
|
||||
".global", // public
|
||||
NULL, // weak
|
||||
".extern", // extrn
|
||||
".comm", // comm
|
||||
NULL, // get_type_name
|
||||
".align", // align
|
||||
'(', ')', // lbrace, rbrace
|
||||
"%", // mod
|
||||
"&", // and
|
||||
"|", // or
|
||||
"^", // xor
|
||||
"!", // not
|
||||
"<<", // shl
|
||||
">>", // shr
|
||||
NULL, // sizeof
|
||||
};
|
||||
|
||||
|
||||
static const asm_t *const asms[] = { &gnuas, NULL };
|
||||
|
||||
static int idaapi choose_device(int, form_actions_t &);
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
const char *arc_t::set_idp_options(
|
||||
const char *keyword,
|
||||
int value_type,
|
||||
const void *value,
|
||||
bool idb_loaded)
|
||||
{
|
||||
if ( keyword == NULL )
|
||||
{
|
||||
static const char form[] =
|
||||
"HELP\n"
|
||||
"ARC specific options\n"
|
||||
"\n"
|
||||
" Simplify instructions\n"
|
||||
"\n"
|
||||
" If this option is on, IDA will simplify instructions and replace\n"
|
||||
" them by more natural pseudo-instructions or alternative mnemonics.\n"
|
||||
" For example,\n"
|
||||
"\n"
|
||||
" sub.f 0, a, b\n"
|
||||
"\n"
|
||||
" will be replaced by\n"
|
||||
"\n"
|
||||
" cmp a, b\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" Inline constant pool loads\n"
|
||||
"\n"
|
||||
" If this option is on, IDA will use =label syntax for\n"
|
||||
" pc-relative loads (commonly used to load constants)\n"
|
||||
" For example,\n"
|
||||
"\n"
|
||||
" ld r1, [pcl,0x1C]\n"
|
||||
" ...\n"
|
||||
" .long 0x2051D1C8\n"
|
||||
"\n"
|
||||
" will be replaced by\n"
|
||||
"\n"
|
||||
" ld r1, =0x2051D1C8\n"
|
||||
"\n"
|
||||
"\n"
|
||||
" Track register accesses\n"
|
||||
"\n"
|
||||
" This option tells IDA to track values loaded\n"
|
||||
" into registers and use it to improve the listing.\n"
|
||||
" For example,\n"
|
||||
"\n"
|
||||
" mov r13, 0x172C\n"
|
||||
" ...\n"
|
||||
" add r0, r13, 0x98\n"
|
||||
"\n"
|
||||
" will be replaced by\n"
|
||||
"\n"
|
||||
" add r0, r13, (dword_17C4 - 0x172C)\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"ENDHELP\n"
|
||||
"ARC specific options\n"
|
||||
"%*\n"
|
||||
" <~S~implify instructions:C>\n"
|
||||
" <~I~nline constant pool loads:C>\n"
|
||||
" <Track ~r~egister accesses:C>>\n"
|
||||
" <~C~hoose core variant:B:0::>\n"
|
||||
"\n";
|
||||
CASSERT(sizeof(idpflags) == sizeof(ushort));
|
||||
ask_form(form, this, &idpflags, choose_device);
|
||||
goto SAVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( value_type != IDPOPT_BIT )
|
||||
return IDPOPT_BADTYPE;
|
||||
if ( strcmp(keyword, "ARC_SIMPLIFY") == 0 )
|
||||
{
|
||||
setflag(idpflags, ARC_SIMPLIFY, *(int*)value != 0);
|
||||
}
|
||||
else if ( strcmp(keyword, "ARC_INLINECONST") == 0 )
|
||||
{
|
||||
setflag(idpflags, ARC_INLINECONST, *(int*)value != 0);
|
||||
}
|
||||
else if ( strcmp(keyword, "ARC_TRACKREGS") == 0 )
|
||||
{
|
||||
setflag(idpflags, ARC_TRACKREGS, *(int*)value != 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return IDPOPT_BADKEY;
|
||||
}
|
||||
SAVE:
|
||||
if ( idb_loaded )
|
||||
save_idpflags();
|
||||
return IDPOPT_OK;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// The short and long names of the supported processors
|
||||
#define FAMILY "Argonaut RISC Core:"
|
||||
|
||||
static const char *const shnames[] =
|
||||
{
|
||||
"arc",
|
||||
"arcmpct",
|
||||
"arcv2",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const char *const lnames[] =
|
||||
{
|
||||
FAMILY"Argonaut RISC Core ARCtangent-A4",
|
||||
"Argonaut RISC Core ARCompact",
|
||||
"Argonaut RISC Core ARCv2",
|
||||
NULL
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Opcodes of "return" instructions. This information will be used in 2 ways:
|
||||
// - if an instruction has the "return" opcode, its autogenerated label
|
||||
// will be "locret" rather than "loc".
|
||||
// - IDA will use the first "return" opcode to create empty subroutines.
|
||||
|
||||
static const bytes_t retcodes[] =
|
||||
{
|
||||
{ 0, NULL } // NULL terminated array
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void arc_iohandler_t::get_cfg_filename(char *buf, size_t bufsize)
|
||||
{
|
||||
qstrncpy(buf, "arc.cfg", bufsize);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
const char *arc_iohandler_t::iocallback(const ioports_t &iop, const char *line)
|
||||
{
|
||||
int len;
|
||||
sval_t ea1;
|
||||
char word[MAXSTR];
|
||||
word[MAXSTR-1] = '\0';
|
||||
CASSERT(MAXSTR == 1024);
|
||||
if ( qsscanf(line, "aux %1023s %" FMT_EA "i%n", word, &ea1, &len) == 2 )
|
||||
{
|
||||
const char *cmt = &line[len];
|
||||
cmt = skip_spaces(cmt);
|
||||
ioport_t &port = pm.auxregs.push_back();
|
||||
port.address = ea1;
|
||||
port.name = word;
|
||||
if ( cmt[0] != '\0' )
|
||||
port.cmt = cmt;
|
||||
return NULL;
|
||||
}
|
||||
return standard_callback(iop, line);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool arc_t::select_device(int resp_info)
|
||||
{
|
||||
char cfgfile[QMAXFILE];
|
||||
arc_respect_info = resp_info;
|
||||
ioh.get_cfg_filename(cfgfile, sizeof(cfgfile));
|
||||
if ( !choose_ioport_device(&ioh.device, cfgfile) )
|
||||
{
|
||||
ioh.device = NONEPROC;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !ioh.display_infotype_dialog(IORESP_ALL, &arc_respect_info, cfgfile) )
|
||||
return false;
|
||||
|
||||
ioh.set_device_name(ioh.device.c_str(), arc_respect_info);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static int idaapi choose_device(int, form_actions_t &fa)
|
||||
{
|
||||
arc_t &pm = *(arc_t *)fa.get_ud();
|
||||
if ( pm.select_device(IORESP_ALL) )
|
||||
{
|
||||
// load_symbols(IORESP_ALL);
|
||||
// apply_symbols();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static int idaapi arcso_gen_scaled_expr(
|
||||
qstring * /*buf*/,
|
||||
qstring *format,
|
||||
ea_t /*ea*/,
|
||||
int /*numop*/,
|
||||
const refinfo_t &ri,
|
||||
ea_t /*from*/,
|
||||
adiff_t * /*opval*/,
|
||||
ea_t * /*target*/,
|
||||
ea_t * /*fullvalue*/,
|
||||
int /*getn_flags*/)
|
||||
{
|
||||
arc_t &pm = *GET_MODULE_DATA(arc_t);
|
||||
int scale = ri.type() == pm.ref_arcsoh_id ? 2 : 4;
|
||||
format->sprnt("%%s " COLSTR("/", SCOLOR_SYMBOL) " %i", scale);
|
||||
return 4; // normal processing with custom format
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static bool idaapi arcso_calc_reference_data(
|
||||
ea_t *target,
|
||||
ea_t *base,
|
||||
ea_t from,
|
||||
const refinfo_t &ri,
|
||||
adiff_t opval)
|
||||
{
|
||||
arc_t &pm = *GET_MODULE_DATA(arc_t);
|
||||
qnotused(from);
|
||||
if ( ri.base == BADADDR || ri.is_subtract() )
|
||||
return false;
|
||||
|
||||
int scale = ri.type() == pm.ref_arcsoh_id ? 2 : 4;
|
||||
|
||||
*base = ri.base;
|
||||
*target = ri.base + scale * opval;
|
||||
|
||||
if ( ri.target != BADADDR && ri.target != *target )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const custom_refinfo_handler_t ref_arcsoh =
|
||||
{
|
||||
sizeof(custom_refinfo_handler_t),
|
||||
"ARCSOH",
|
||||
"ARC 16-bit scaled offset",
|
||||
RHF_TGTOPT, // properties: target be calculated using operand value
|
||||
arcso_gen_scaled_expr, // gen_expr
|
||||
arcso_calc_reference_data, // calc_reference_data
|
||||
NULL, // get_format
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const custom_refinfo_handler_t ref_arcsol =
|
||||
{
|
||||
sizeof(custom_refinfo_handler_t),
|
||||
"ARCSOL",
|
||||
"ARC 32-bit scaled offset",
|
||||
RHF_TGTOPT, // properties: target be calculated using operand value
|
||||
arcso_gen_scaled_expr, // gen_expr
|
||||
arcso_calc_reference_data, // calc_reference_data
|
||||
NULL, // get_format
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// 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(arc_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void arc_t::load_from_idb()
|
||||
{
|
||||
ptype = processor_subtype_t(ph.get_proc_index());
|
||||
ptype_changed();
|
||||
idpflags = (ushort)helper.altval(-1);
|
||||
ioh.restore_device();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
ssize_t idaapi arc_t::on_event(ssize_t msgid, va_list va)
|
||||
{
|
||||
int code = 0;
|
||||
switch ( msgid )
|
||||
{
|
||||
case processor_t::ev_init:
|
||||
helper.create(PROCMOD_NODE_NAME);
|
||||
inf_set_be(false); // Set little-endian mode of the IDA kernel
|
||||
set_codeseqs();
|
||||
hook_event_listener(HT_IDB, &idb_listener, &LPH);
|
||||
ref_arcsol_id = register_custom_refinfo(&ref_arcsol);
|
||||
ref_arcsoh_id = register_custom_refinfo(&ref_arcsoh);
|
||||
break;
|
||||
|
||||
case processor_t::ev_term:
|
||||
unregister_custom_refinfo(ref_arcsoh_id);
|
||||
unregister_custom_refinfo(ref_arcsol_id);
|
||||
unhook_event_listener(HT_IDB, &idb_listener);
|
||||
clr_module_data(data_id);
|
||||
break;
|
||||
|
||||
case processor_t::ev_newfile:
|
||||
save_idpflags();
|
||||
set_codeseqs();
|
||||
if ( inf_like_binary() )
|
||||
{
|
||||
// ask the user
|
||||
select_device(IORESP_ALL);
|
||||
}
|
||||
else
|
||||
{
|
||||
// load the default AUX regs
|
||||
ioh.set_device_name(is_a4() ? "ARC4": "ARCompact", IORESP_NONE);
|
||||
}
|
||||
break;
|
||||
|
||||
case processor_t::ev_ending_undo:
|
||||
case processor_t::ev_oldfile:
|
||||
load_from_idb();
|
||||
break;
|
||||
|
||||
case processor_t::ev_creating_segm:
|
||||
break;
|
||||
|
||||
case processor_t::ev_newprc:
|
||||
ptype = va_argi(va, processor_subtype_t);
|
||||
// bool keep_cfg = va_argi(va, bool);
|
||||
if ( uint(ptype) > prc_arcv2 ) //lint !e685 //-V547 is always false
|
||||
{
|
||||
code = -1;
|
||||
break;
|
||||
}
|
||||
ptype_changed();
|
||||
break;
|
||||
|
||||
case processor_t::ev_out_mnem:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
out_mnem(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_is_call_insn:
|
||||
// Is the instruction a "call"?
|
||||
// ea_t ea - instruction address
|
||||
// returns: 1-unknown, 0-no, 2-yes
|
||||
{
|
||||
const insn_t *insn = va_arg(va, insn_t *);
|
||||
code = is_arc_call_insn(*insn) ? 1 : -1;
|
||||
return code;
|
||||
}
|
||||
|
||||
case processor_t::ev_is_ret_insn:
|
||||
{
|
||||
const insn_t *insn = va_arg(va, insn_t *);
|
||||
// bool strict = va_argi(va, bool);
|
||||
code = is_arc_return_insn(*insn) ? 1 : -1;
|
||||
return code;
|
||||
}
|
||||
|
||||
case processor_t::ev_is_basic_block_end:
|
||||
{
|
||||
const insn_t *insn = va_arg(va, insn_t *);
|
||||
bool call_insn_stops_block = va_argi(va, bool);
|
||||
return is_arc_basic_block_end(*insn, call_insn_stops_block) ? 1 : -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_delay_slot_insn:
|
||||
// Get delay slot instruction
|
||||
// ea_t *ea in: instruction address in question,
|
||||
// it may point to the instruction with a
|
||||
// delay slot or to the delay slot
|
||||
// instruction itself
|
||||
// out: (if the answer is positive)
|
||||
// if the delay slot contains valid insn:
|
||||
// the address of the delay slot insn
|
||||
// else:
|
||||
// BADADDR (invalid insn, e.g. a branch)
|
||||
// bool *bexec execute slot if jumping
|
||||
// bool *fexec execute slot if not jumping
|
||||
// returns: 1 positive answer
|
||||
// <=0 ordinary insn
|
||||
{
|
||||
ea_t *ea = va_arg(va, ea_t *);
|
||||
bool *bexec = va_arg(va, bool *);
|
||||
bool *fexec = va_arg(va, bool *);
|
||||
insn_t insn;
|
||||
if ( decode_insn(&insn, *ea) == 0 )
|
||||
return -1;
|
||||
if ( has_dslot(insn) )
|
||||
{
|
||||
// the current instruction is a delayed slot instruction
|
||||
// set EA to the address of the delay slot
|
||||
*ea = insn.ea + insn.size;
|
||||
// check the insn in the delay slot
|
||||
// doc: "The Illegal Instruction Sequence type also occurs when
|
||||
// any of the following instructions are attempted in an executed
|
||||
// delay slot of a jump or branch:
|
||||
// * Another jump or branch instruction (Bcc, BLcc, Jcc, JLcc)
|
||||
// * Conditional loop instruction (LPcc)
|
||||
// * Return from interrupt (RTIE)
|
||||
// * Any instruction with long-immediate data as a source operand"
|
||||
insn_t dslot_insn;
|
||||
if ( decode_insn(&dslot_insn, *ea) == 0
|
||||
|| is_arc_simple_branch(dslot_insn.itype)
|
||||
|| dslot_insn.itype == ARC_lp
|
||||
|| dslot_insn.itype == ARC_rtie
|
||||
|| dslot_insn.size > 4
|
||||
|| dslot_insn.itype == ARC_br // ARCompact instructions
|
||||
|| dslot_insn.itype == ARC_bbit0
|
||||
|| dslot_insn.itype == ARC_bbit1 )
|
||||
{
|
||||
*ea = BADADDR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !is_flow(get_flags(*ea))
|
||||
|| decode_prev_insn(&insn, *ea) == BADADDR
|
||||
|| !has_dslot(insn) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
// the previous instruction is a delayed slot instruction
|
||||
// EA already has the address of the delay slot
|
||||
}
|
||||
*bexec = true;
|
||||
*fexec = (insn.auxpref & aux_nmask) != aux_jd;
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_is_switch:
|
||||
{
|
||||
switch_info_t *si = va_arg(va, switch_info_t *);
|
||||
const insn_t *insn = va_arg(va, const insn_t *);
|
||||
return arc_is_switch(si, *insn) ? 1 : -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_may_be_func:
|
||||
// can a function start here?
|
||||
///< \param insn (const ::insn_t*) the instruction
|
||||
///< \param state (int) autoanalysis phase
|
||||
///< 0: creating functions
|
||||
///< 1: creating chunks
|
||||
///< \return probability 0..100
|
||||
{
|
||||
const insn_t *insn = va_arg(va, insn_t *);
|
||||
int state = va_arg(va, int);
|
||||
return arc_may_be_func(*insn, state);
|
||||
}
|
||||
|
||||
case processor_t::ev_undefine:
|
||||
{
|
||||
// an item is being undefined; delete data attached to it
|
||||
ea_t ea = va_arg(va, ea_t);
|
||||
del_insn_info(ea);
|
||||
}
|
||||
return 1;
|
||||
|
||||
// +++ TYPE CALLBACKS
|
||||
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_arc_arglocs(fti) ? 1 : -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_calc_varglocs:
|
||||
{
|
||||
func_type_data_t *fti = va_arg(va, func_type_data_t *);
|
||||
regobjs_t *regargs = va_arg(va, regobjs_t *);
|
||||
/*relobj_t *stkargs =*/ va_arg(va, relobj_t *);
|
||||
int nfixed = va_arg(va, int);
|
||||
return calc_arc_varglocs(fti, regargs, nfixed) ? 1 : -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_calc_retloc:
|
||||
{
|
||||
argloc_t *retloc = va_arg(va, argloc_t *);
|
||||
const tinfo_t *type = va_arg(va, const tinfo_t *);
|
||||
cm_t cc = va_argi(va, cm_t);
|
||||
return calc_arc_retloc(retloc, *type, cc) ? 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_arc_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_arc_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);
|
||||
if ( cc == CM_CC_FASTCALL || cc == CM_CC_ELLIPSIS )
|
||||
{
|
||||
const int *regs;
|
||||
get_arc_fastcall_regs(®s);
|
||||
callregs->set(ARGREGS_INDEPENDENT, regs, NULL);
|
||||
return 1;
|
||||
}
|
||||
else if ( cc == CM_CC_THISCALL )
|
||||
{
|
||||
callregs->reset();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
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 0;
|
||||
|
||||
|
||||
// --- TYPE CALLBACKS
|
||||
|
||||
case processor_t::ev_out_header:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
arc_header(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_footer:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
arc_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 *);
|
||||
arc_segstart(*ctx, seg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_ana_insn:
|
||||
{
|
||||
insn_t *out = va_arg(va, insn_t *);
|
||||
return ana(out);
|
||||
}
|
||||
|
||||
case processor_t::ev_emu_insn:
|
||||
{
|
||||
const insn_t *insn = va_arg(va, const insn_t *);
|
||||
return emu(*insn) ? 1 : -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_insn:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
out_insn(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_operand:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
const op_t *op = va_arg(va, const op_t *);
|
||||
return out_opnd(*ctx, *op) ? 1 : -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_is_sp_based:
|
||||
{
|
||||
int *mode = va_arg(va, int *);
|
||||
const insn_t *insn = va_arg(va, const insn_t *);
|
||||
const op_t *op = va_arg(va, const op_t *);
|
||||
*mode = is_sp_based(*insn, *op);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_create_func_frame:
|
||||
{
|
||||
func_t *pfn = va_arg(va, func_t *);
|
||||
create_func_frame(pfn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_calc_spdelta:
|
||||
{
|
||||
sval_t *spdelta = va_arg(va, sval_t *);
|
||||
const insn_t *insn = va_arg(va, const insn_t *);
|
||||
return arc_calc_spdelta(spdelta, *insn);
|
||||
}
|
||||
|
||||
case processor_t::ev_get_frame_retsize:
|
||||
{
|
||||
int *frsize = va_arg(va, int *);
|
||||
const func_t *pfn = va_arg(va, const func_t *);
|
||||
*frsize = arc_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);
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Processor Definition
|
||||
//-----------------------------------------------------------------------
|
||||
processor_t LPH =
|
||||
{
|
||||
IDP_INTERFACE_VERSION, // version
|
||||
PLFM_ARC, // id
|
||||
// flag
|
||||
PR_USE32 // 32-bit processor
|
||||
| PR_DEFSEG32 // create 32-bit segments by default
|
||||
| PRN_HEX // Values are hexadecimal by default
|
||||
| PR_TYPEINFO // Support the type system notifications
|
||||
| PR_CNDINSNS // Has conditional instructions
|
||||
| PR_DELAYED // Has delay slots
|
||||
| PR_USE_ARG_TYPES // use ph.use_arg_types callback
|
||||
| PR_RNAMESOK // register names can be reused for location names
|
||||
| PR_SEGS // has segment registers
|
||||
| PR_SGROTHER, // the segment registers don't contain the segment selectors.
|
||||
// flag2
|
||||
PR2_IDP_OPTS, // the module has processor-specific configuration options
|
||||
8, // 8 bits in a byte for code segments
|
||||
8, // 8 bits in a byte for other segments
|
||||
|
||||
shnames, // array of short processor names
|
||||
// the short names are used to specify the processor
|
||||
// with the -p command line switch)
|
||||
lnames, // array of long processor names
|
||||
// the long names are used to build the processor type
|
||||
// selection menu
|
||||
|
||||
asms, // array of target assemblers
|
||||
|
||||
notify, // the kernel event notification callback
|
||||
|
||||
RegNames, // Register names
|
||||
qnumber(RegNames), // Number of registers
|
||||
|
||||
LDI_BASE, // first
|
||||
rVds, // last
|
||||
4, // size of a segment register
|
||||
rVcs, rVds,
|
||||
|
||||
codestart_arcompact, // code start sequences
|
||||
retcodes,
|
||||
|
||||
0, ARC_last,
|
||||
Instructions, // instruc
|
||||
0, // size of tbyte
|
||||
{0}, // real width
|
||||
0, // Icode of a return instruction
|
||||
NULL, // Micro virtual machine description
|
||||
};
|
||||
Reference in New Issue
Block a user