2777 lines
116 KiB
C++
2777 lines
116 KiB
C++
/*
|
|
* 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>
|
|
*/
|
|
|
|
#include "arc.hpp"
|
|
#include <frame.hpp>
|
|
|
|
/*
|
|
doRegisterOperand converts the 6 bit field 'code' to an IDA-"op_t"-operand.
|
|
|
|
'd' is the maybe-used (signed) immediate in the lowest 9 bits, li is the
|
|
long-immediate which is loaded in the instruction decoding, since it's
|
|
loaded only once, even if an instructions uses multiple times a long immediate
|
|
|
|
when it's all about a branch (isbranch is true), we have to multiply the absolute
|
|
address by 4, since it's granularity are words then (and not bytes)
|
|
|
|
FYI:
|
|
register code 61 means "short immediate with .f-flag set", 63 "short immediate
|
|
without .f-flag" and 62 means "long immediate (4 bytes following the instruction,
|
|
making the instruction 8 bytes long (insn.size)).
|
|
*/
|
|
|
|
//----------------------------------------------------------------------
|
|
void doRegisterOperand(int code, op_t &op, int d, int li, int isbranch)
|
|
{
|
|
/* we always deal with double words, exceptions are load/stores
|
|
with 8 or 16 bits. these are covered by the instruction decoding */
|
|
|
|
op.dtype = dt_dword;
|
|
if ( code == SHIMM_F || code == SHIMM ) // short immediate with/wo flags
|
|
{
|
|
if ( isbranch )
|
|
{
|
|
op.type = o_near;
|
|
op.addr = d * 4;
|
|
}
|
|
else
|
|
{
|
|
op.type = o_imm;
|
|
op.value = d;
|
|
}
|
|
}
|
|
else if ( code == LIMM ) // long immediate
|
|
{
|
|
if ( isbranch )
|
|
{
|
|
op.type = o_near;
|
|
/* the upper 7 bits containing processor flags to set */
|
|
/* they are handled in the instruction decoding, since */
|
|
/* they produce a second (ida-)operand */
|
|
op.addr = (li & 0x1FFFFFF) * 4;
|
|
}
|
|
else
|
|
{
|
|
op.type = o_imm;
|
|
op.value = li;
|
|
}
|
|
op.offb = 4;
|
|
}
|
|
else /* just a register */
|
|
{
|
|
op.type = o_reg;
|
|
op.reg = uint16(code);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// make indirect [b,c] operand
|
|
// b c
|
|
// imm imm mem: [imm1+imm2]
|
|
// reg imm displ: [reg, imm]
|
|
// imm reg displ: [imm, reg] (membase=1)
|
|
// reg reg phrase: [reg, reg]
|
|
void arc_t::doIndirectOperand(const insn_t &insn, int b, int c, op_t &op, int d, int li, bool special)
|
|
{
|
|
if ( is_imm(b) && is_imm(c) )
|
|
{
|
|
// [#imm, #imm]
|
|
int imm1 = b == LIMM ? li : d;
|
|
int imm2 = c == LIMM ? li : d;
|
|
if ( special )
|
|
{
|
|
// use a simple immediate for AUX reg numbers
|
|
op.type = o_imm;
|
|
op.value = imm1;
|
|
}
|
|
else
|
|
{
|
|
op.type = o_mem;
|
|
op.immdisp = is_a4() ? 0 : imm2;
|
|
op.addr = imm1 + imm2 * get_scale_factor(insn);
|
|
}
|
|
}
|
|
else if ( !is_imm(b) && !is_imm(c) )
|
|
{
|
|
// [reg, reg]
|
|
op.type = o_phrase;
|
|
op.reg = b;
|
|
op.secreg = c;
|
|
}
|
|
else
|
|
{
|
|
op.type = o_displ;
|
|
if ( is_imm(c) )
|
|
{
|
|
// [reg, #imm]
|
|
op.reg = b;
|
|
op.addr = c == LIMM ? li : d;
|
|
if ( special )
|
|
op.addr = 0;
|
|
op.membase = 0;
|
|
}
|
|
else
|
|
{
|
|
// [#imm, reg]
|
|
op.reg = c;
|
|
op.addr = b == LIMM ? li : d;
|
|
op.membase = 1;
|
|
}
|
|
}
|
|
switch ( insn.auxpref & aux_zmask )
|
|
{
|
|
default:
|
|
op.dtype = dt_dword;
|
|
break;
|
|
case aux_b:
|
|
op.dtype = dt_byte;
|
|
break;
|
|
case aux_w:
|
|
op.dtype = dt_word;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// doBranchOperand handles pc-relative word offsets.
|
|
// nothing special here.
|
|
void doBranchOperand(const insn_t &insn, op_t &op, int l)
|
|
{
|
|
op.dtype = dt_dword;
|
|
op.type = o_near;
|
|
op.addr = insn.ip + l * 4 + 4;
|
|
op.offb = 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void arc_t::doRegisterInstruction(insn_t &insn, uint32 code)
|
|
{
|
|
|
|
int i = (code >> 27) & 31;
|
|
int a = (code >> 21) & 63;
|
|
int b = (code >> 15) & 63;
|
|
int c = (code >> 9) & 63;
|
|
|
|
/* the (maybe used?) short immediate value */
|
|
uint32 d = code & 0x1FF;
|
|
|
|
// sign-extend
|
|
if ( d >= 0x100 )
|
|
d -= 0x200;
|
|
|
|
/* store the flags. if there are actually no flags at that place, they */
|
|
/* will be reconstructed later */
|
|
insn.auxpref = code & (aux_cmask|aux_f);
|
|
|
|
switch ( i )
|
|
{
|
|
case 0: // LD register+register
|
|
insn.itype = ARC_ld;
|
|
insn.auxpref |= (code & aux_di);
|
|
break;
|
|
case 1: // LD register+offset, LR
|
|
if ( code & (1 << 13) )
|
|
insn.itype = ARC_lr;
|
|
else
|
|
insn.itype = ARC_ld;
|
|
break;
|
|
case 2: // ST, SR
|
|
if ( code & (1 << 25) )
|
|
{
|
|
insn.itype = ARC_sr;
|
|
}
|
|
else
|
|
{
|
|
insn.itype = ARC_st;
|
|
// 26 = Di
|
|
// 24 = A
|
|
// 23..22 = ZZ
|
|
insn.auxpref = (code >> 20) & (aux_di|aux_amask|aux_zmask);
|
|
}
|
|
break;
|
|
case 3: // single operand instructions
|
|
switch ( c )
|
|
{
|
|
case 0:
|
|
insn.itype = ARC_flag;
|
|
a = b; // flag has no 'a' operand, so we're moving the b-operand to a.
|
|
break;
|
|
case 1:
|
|
insn.itype = ARC_asr;
|
|
break;
|
|
case 2:
|
|
insn.itype = ARC_lsr;
|
|
break;
|
|
case 3:
|
|
insn.itype = ARC_ror;
|
|
break;
|
|
case 4:
|
|
insn.itype = ARC_rrc;
|
|
break;
|
|
case 5:
|
|
insn.itype = ARC_sexb;
|
|
break;
|
|
case 6:
|
|
insn.itype = ARC_sexw;
|
|
break;
|
|
case 7:
|
|
insn.itype = ARC_extb;
|
|
break;
|
|
case 8:
|
|
insn.itype = ARC_extw;
|
|
break;
|
|
case 9:
|
|
insn.itype = ARC_swap;
|
|
break;
|
|
case 10:
|
|
insn.itype = ARC_norm;
|
|
break;
|
|
case 0x3F:
|
|
switch ( d )
|
|
{
|
|
case 0:
|
|
insn.itype = ARC_brk;
|
|
break;
|
|
case 1:
|
|
insn.itype = ARC_sleep;
|
|
break;
|
|
case 2:
|
|
insn.itype = ARC_swi;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
a = b = -1;
|
|
insn.auxpref = 0;
|
|
break;
|
|
}
|
|
c = -1; // c operand is no real operand, so don't try to convert it.
|
|
break;
|
|
case 7: // Jcc, JLcc
|
|
insn.itype = ARC_j;
|
|
if ( code & (1<<9) )
|
|
insn.itype = ARC_jl;
|
|
else
|
|
insn.itype = ARC_j;
|
|
// copy the NN bits
|
|
insn.auxpref |= (code & aux_nmask);
|
|
break;
|
|
case 8: // ADD
|
|
insn.itype = ARC_add;
|
|
break;
|
|
case 9: // ADC
|
|
insn.itype = ARC_adc;
|
|
break;
|
|
case 10: // SUB
|
|
insn.itype = ARC_sub;
|
|
break;
|
|
case 11: // SBC
|
|
insn.itype = ARC_sbc;
|
|
break;
|
|
case 12: // AND
|
|
insn.itype = ARC_and;
|
|
break;
|
|
case 13: // OR
|
|
insn.itype = ARC_or;
|
|
break;
|
|
case 14: // BIC
|
|
insn.itype = ARC_bic;
|
|
break;
|
|
case 15: // XOR
|
|
insn.itype = ARC_xor;
|
|
break;
|
|
case 0x10:
|
|
insn.itype = ARC_asl;
|
|
break;
|
|
case 0x11:
|
|
insn.itype = ARC_lsr;
|
|
break;
|
|
case 0x12:
|
|
insn.itype = ARC_asr;
|
|
break;
|
|
case 0x13:
|
|
insn.itype = ARC_ror;
|
|
break;
|
|
case 0x14:
|
|
insn.itype = ARC_mul64;
|
|
break;
|
|
case 0x15:
|
|
insn.itype = ARC_mulu64;
|
|
break;
|
|
case 0x1E:
|
|
insn.itype = ARC_max;
|
|
break;
|
|
case 0x1F:
|
|
insn.itype = ARC_min;
|
|
break;
|
|
}
|
|
|
|
uint32 immediate = 0;
|
|
int noop3 = 0, isnop = 0;
|
|
|
|
if ( a == SHIMM_F || b == SHIMM_F || c == SHIMM_F )
|
|
insn.auxpref = aux_f; // .f
|
|
|
|
if ( b == SHIMM || c == SHIMM )
|
|
insn.auxpref = 0;
|
|
|
|
if ( b == LIMM || c == LIMM )
|
|
immediate = insn.get_next_dword();
|
|
|
|
/*
|
|
pseudo instruction heuristic:
|
|
|
|
we have some types of pseudo-instructions:
|
|
|
|
(rS might be an immediate)
|
|
insn will be coded as
|
|
move rD, rS and rD, rS, rS
|
|
asl rD, rS add rD, rS, rS
|
|
lsl rD, rS add rD, rS, rS (the same as asl, of course...)
|
|
rlc rD, rS adc.f rD, rS, rS
|
|
rol rD, rS add.f rD, rS, rS; adc rD, rD, 0
|
|
nop xxx 0, 0, 0
|
|
*/
|
|
|
|
switch ( insn.itype )
|
|
{
|
|
case ARC_flag:
|
|
// special handling for flag, since its a-operand is a source here
|
|
b = -1;
|
|
break;
|
|
|
|
case ARC_and:
|
|
case ARC_or:
|
|
if ( b == c )
|
|
{
|
|
noop3 = 1;
|
|
insn.itype = ARC_mov;
|
|
}
|
|
break;
|
|
|
|
case ARC_add:
|
|
if ( b == c )
|
|
{
|
|
noop3 = 1;
|
|
if ( b >= SHIMM_F )
|
|
{
|
|
// add rD, imm, imm -> move rD, imm*2
|
|
insn.itype = ARC_mov;
|
|
d <<= 1;
|
|
immediate <<= 1;
|
|
}
|
|
else
|
|
{
|
|
insn.itype = ARC_lsl;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ARC_adc:
|
|
if ( b == c )
|
|
{
|
|
noop3 = 1;
|
|
insn.itype = ARC_rlc;
|
|
}
|
|
break;
|
|
|
|
case ARC_xor:
|
|
if ( code == 0x7FFFFFFF ) // XOR 0x1FF, 0x1FF, 0x1FF
|
|
isnop = 1;
|
|
break;
|
|
}
|
|
|
|
if ( !isnop )
|
|
{
|
|
if ( i == 0 )
|
|
{
|
|
// ld a, [b,c]
|
|
doRegisterOperand(a, insn.Op1, d, immediate, 0);
|
|
doIndirectOperand(insn, b, c, insn.Op2, d, immediate, false);
|
|
}
|
|
else if ( i == 1 || i == 2 )
|
|
{
|
|
/* fetch the flag-bits from the right location */
|
|
if ( insn.itype == ARC_ld )
|
|
insn.auxpref = (code >> 9) & 0x3F;
|
|
else if ( insn.itype == ARC_st )
|
|
insn.auxpref = (code >> 21) & 0x3F;
|
|
else
|
|
insn.auxpref = 0;
|
|
if ( insn.itype == ARC_st || insn.itype == ARC_sr )
|
|
{
|
|
/* in a move to special register or load from special register,
|
|
we have the target operand somewhere else */
|
|
a = c;
|
|
/* c=-1; not used anyway */
|
|
}
|
|
doRegisterOperand(a, insn.Op1, d, immediate, 0);
|
|
doIndirectOperand(insn, b, SHIMM, insn.Op2, d, immediate, insn.itype == ARC_lr || insn.itype == ARC_sr);
|
|
}
|
|
else if ( i == 7 )
|
|
{
|
|
/* the jump (absolute) instruction, with a special imm-encoding */
|
|
doRegisterOperand(b, insn.Op1, d, immediate, 1);
|
|
}
|
|
else
|
|
{
|
|
if ( a != -1 )
|
|
doRegisterOperand(a, insn.Op1, 0, immediate, 0);
|
|
/* this is a bugfix for the gnu-as: long immediate must be equal, while short */
|
|
/* immediates don't have to. */
|
|
if ( b != -1 )
|
|
doRegisterOperand(b, insn.Op2, d, immediate, 0);
|
|
if ( c != -1 && !noop3 )
|
|
doRegisterOperand(c, insn.Op3, d, immediate, 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
insn.itype = ARC_nop;
|
|
insn.auxpref = 0;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void doBranchInstruction(insn_t &insn, uint32 code)
|
|
{
|
|
int i = (code >> 27) & 31;
|
|
|
|
int l = (code >> 7) & 0xFFFFF; // note: bits 21..2, so it's in WORDS
|
|
|
|
if ( l >= 0x80000 ) // sign-extend
|
|
l = l - 0x100000;
|
|
|
|
doBranchOperand(insn, insn.Op1, l);
|
|
|
|
switch ( i )
|
|
{
|
|
case 4: // Bcc
|
|
insn.itype = ARC_b;
|
|
break;
|
|
case 5: // BLcc
|
|
insn.itype = ARC_bl;
|
|
break;
|
|
case 6: // LPcc
|
|
insn.itype = ARC_lp;
|
|
break;
|
|
}
|
|
insn.auxpref = code & (aux_cmask | aux_nmask);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// analyze ARCTangent-A4 (32-bit) instruction
|
|
int arc_t::ana_old(insn_t &insn)
|
|
{
|
|
if ( insn.ea & 3 )
|
|
return 0;
|
|
|
|
insn.Op1.dtype = dt_dword;
|
|
insn.Op2.dtype = dt_dword;
|
|
insn.Op3.dtype = dt_dword;
|
|
|
|
uint32 code = insn.get_next_dword();
|
|
|
|
int i = (code >> 27) & 31;
|
|
|
|
insn.itype = 0;
|
|
|
|
switch ( i )
|
|
{
|
|
case 0: // LD register+register
|
|
case 1: // LD register+offset, LR
|
|
case 2: // ST, SR
|
|
case 3: // single operand instructions
|
|
doRegisterInstruction(insn, code);
|
|
break;
|
|
case 4: // Bcc
|
|
case 5: // BLcc
|
|
case 6: // LPcc
|
|
doBranchInstruction(insn, code);
|
|
break;
|
|
case 7: // Jcc, JLcc
|
|
case 8: // ADD
|
|
case 9: // ADC
|
|
case 10: // SUB
|
|
case 11: // ADC
|
|
case 12: // AND
|
|
case 13: // OR
|
|
case 14: // BIC
|
|
case 15: // XOR
|
|
default:
|
|
doRegisterInstruction(insn, code);
|
|
break;
|
|
}
|
|
|
|
return insn.size;
|
|
}
|
|
|
|
#define SUBTABLE(high, low, name) (0x80000000 | (high << 8) | low), 0, { 0,0,0 }, name
|
|
#define SUBTABLE2(high1, low1, high2, low2, name) (0x80000000 | (high1 << 24) | (low1 << 16) | (high2 << 8) | low2), 0, { 0,0,0 }, name
|
|
|
|
//----------------------------------------------------------------------
|
|
struct arcompact_opcode_t
|
|
{
|
|
uint32 mnem; // instruction itype, or indicator of sub-field decoding
|
|
uint32 aux; // auxpref and other flags
|
|
uint32 ops[3]; // description of operands
|
|
const arcompact_opcode_t *subtable; //lint !e958 padding is required to align members
|
|
};
|
|
|
|
enum aux_flags_t ENUM_SIZE(uint32)
|
|
{
|
|
AUX_B = 1, // implicit byte size access
|
|
AUX_W = 2, // implicit word size access
|
|
Q_4_0 = 4, // 4..0 QQQQQ condition code
|
|
AAZZXD_23_15 = 8, // 23..22,18..15 aa, ZZ, X, D flags (load reg+reg)
|
|
DAAZZX_11_6 = 0x10, // 11..6 Di, aa, ZZ, X flags (load)
|
|
DAAZZ_5_1 = 0x20, // 5..0 Di, aa, ZZ, R flags (store)
|
|
AUX_D = 0x40, // implicit delay slot (.d)
|
|
AUX_X = 0x80, // implicit sign extend (.x)
|
|
AUX_CND = 0x100, // implicit condition (in low 5 bits)
|
|
N_5 = 0x200, // 5..5 N delay slot bit
|
|
AUX_GEN = 0x400, // 4..0 = Q if 23..22=0x3, bit 15 = F
|
|
AUX_GEN2 = 0x800, // 4..0 = Q if 23..22=0x3
|
|
AUX_GEN3 =
|
|
AUX_GEN|AUX_GEN2, // 4..0 = Q if 23..22=0x3, bit 15 = Di
|
|
AUX_V2 = 0x1000, // only available on ARCv2
|
|
AUX_F = 0x2000, // use alternative instruction when F = 1
|
|
AUX_AS = 0x8000, // implicit scaled access
|
|
Q_5_0 = 0x10000, // 5..0 0QQQQQ condition code
|
|
Y_3 = 0x20000, // 3 Y static branch prediction bit
|
|
};
|
|
|
|
enum op_fields_t ENUM_SIZE(uint32)
|
|
{
|
|
fA32=1, // 5..0 a register operand (6 bits, r0-r63)
|
|
fA16, // 2..0 a register operand (3 bits, r0-r3, r12-r15)
|
|
fB32, // 14..12 & 26..24 b register operand (6 bits)
|
|
fB16, // 10..8 b register operand (3 bits)
|
|
fC32, // 11..6 c register operand (6 bits)
|
|
fC32_w6, // 11..6 & 0 c/w6 register/immediate operand (6 bits)
|
|
fC16, // 7..5 c register operand (3 bits)
|
|
fH16, // 2..0 & 7..5 h register operand (6 bits)
|
|
fH16v2, // 1..0 & 7..5 h register operand (5 bits)
|
|
fH16v2_U5, // 1..0 & 7..5, 10&4..3 [h, u5] (u5=u3*4)
|
|
fG16, // 4..3 & 10..8 g register operand (5 bits)
|
|
fR16_2, // 9..8 R register operand (2 bits)
|
|
fR16_1, // 7 R register operand (1 bit)
|
|
S25, // 15..6 & 26..17 & 0..3 s25 signed branch displacement
|
|
S21, // 15..6 & 26..17 s21 signed branch displacement
|
|
S25L, // 15..6 & 26..18 & 0..3 s25 signed branch displacement for branch and link
|
|
S21L, // 15..6 & 26..18 s21 signed branch displacement for branch and link
|
|
S10, // 8..0 s10 signed branch displacement
|
|
S9, // 15..15 & 23..17 s9 signed branch displacement
|
|
S8, // 6..0 s8 signed branch displacement
|
|
S7, // 5..0 s7 signed branch displacement
|
|
S13, // 10..0 s13 signed branch displacement
|
|
U3, // 2..0 u2 unsigned immediate
|
|
U5, // 4..0 u5 unsigned immediate
|
|
U6, // 11..6 u6 unsigned immediate
|
|
U6_SWI, // 10..5 u6 unsigned immediate
|
|
U7, // 6..0 u7 unsigned immediate
|
|
U7L, // 4..0 u7 unsigned immediate (u5*4)
|
|
U8, // 7..0 u8 unsigned immediate
|
|
U6_16, // 6..4 & 2..0 u6 unsigned immediate
|
|
U7_16, // 7..4 & 2..0 u7 unsigned immediate
|
|
U10_16, // 9..0 u10 unsigned immediate
|
|
SP_U7, // 4..0 [SP, u7] stack + offset (u7 = u5*4)
|
|
PCL_U10, // 7..0 [PCL, u10] PCL + offset (u8*4)
|
|
fB_U5, // 10..8 & 4..0 [b, u5]
|
|
fB_U6, // 10..8 & 4..0 [b, u6] (u6=u5*2)
|
|
fB_U7, // 10..8 & 4..0 [b, u7] (u6=u5*4)
|
|
fB_S9, // 14..12&26..26, 15&23..16 [b, s9]
|
|
GENA, // 5..0
|
|
GENB, // 14..12 & 26..24
|
|
GENC, // 11..6 or 5..0 & 11..6
|
|
GENC_PCREL, // 11..6 or 5..0 & 11..6
|
|
fBC_IND, // 14..12 & 26..24, 11..6 [b, c]
|
|
fBC16_IND, // 10..8, 7..5 [b, c]
|
|
R_SP, // implicit SP
|
|
R_BLINK, // implicit BLINK
|
|
O_ZERO, // implicit immediate 0
|
|
R_R0, // implicit R0
|
|
R_R1, // implicit R1
|
|
R_GP, // implicit GP
|
|
GP_S9, // 8..0 [GP, s9] GP + offset
|
|
GP_S10, // 8..0 [GP, s10] GP + offset (s10 = s9*2)
|
|
GP_S11, // 8..0 [GP, s11] GP + offset (s11 = s9*4)
|
|
S11, // 8..0 s11 signed immediate (s11 = s9*4)
|
|
GP_S11_16, // 10..5 & 4..2 [GP, s11] GP + offset (s11 = s9*4)
|
|
S3, // 10..8 s3 signed immediate
|
|
EL, // 4..1 & 10..8 enter / leave register set
|
|
|
|
O_IND = 0x80000000, // [reg], [imm] (jumps: only [reg])
|
|
O_WIDE = 0x40000000, // register pair rNrN+1 with N even
|
|
O_IDX = 0x20000000, // instruction specific index
|
|
|
|
O_FLAGS = O_IND|O_WIDE|O_IDX,
|
|
};
|
|
|
|
// indexed by bit 16 (maj = 0)
|
|
static const arcompact_opcode_t arcompact_maj0[2] =
|
|
{
|
|
{ ARC_b, Q_4_0 | N_5, {S21, 0, 0}, NULL }, // 0
|
|
{ ARC_b, N_5, {S25, 0, 0}, NULL }, // 1
|
|
};
|
|
|
|
// indexed by bit 17 (maj = 1, b16 = 0)
|
|
static const arcompact_opcode_t arcompact_bl[2] =
|
|
{
|
|
{ ARC_bl, Q_4_0 | N_5, {S21L, 0, 0}, NULL }, // 0
|
|
{ ARC_bl, N_5, {S25L, 0, 0}, NULL }, // 1
|
|
};
|
|
|
|
// indexed by bits 3..0 (maj = 1, b16 = 1, b4 = 0)
|
|
static const arcompact_opcode_t arcompact_br_regreg[0x10] =
|
|
{
|
|
{ ARC_br, AUX_CND|cEQ|N_5|Y_3, {fB32, fC32, S9}, NULL }, // 0x00
|
|
{ ARC_br, AUX_CND|cNE|N_5|Y_3, {fB32, fC32, S9}, NULL }, // 0x01
|
|
{ ARC_br, AUX_CND|cLT|N_5|Y_3, {fB32, fC32, S9}, NULL }, // 0x02
|
|
{ ARC_br, AUX_CND|cGE|N_5|Y_3, {fB32, fC32, S9}, NULL }, // 0x03
|
|
{ ARC_br, AUX_CND|cLO|N_5|Y_3, {fB32, fC32, S9}, NULL }, // 0x04
|
|
{ ARC_br, AUX_CND|cHS|N_5|Y_3, {fB32, fC32, S9}, NULL }, // 0x05
|
|
{ ARC_bbit0, N_5|Y_3|AUX_V2, {fB32, fC32, S9}, NULL }, // 0x06
|
|
{ ARC_bbit1, N_5|Y_3|AUX_V2, {fB32, fC32, S9}, NULL }, // 0x07
|
|
{ ARC_br, AUX_CND|cEQ|N_5|Y_3|AUX_V2, {fB32, fC32, S9}, NULL }, // 0x08
|
|
{ ARC_br, AUX_CND|cNE|N_5|Y_3|AUX_V2, {fB32, fC32, S9}, NULL }, // 0x09
|
|
{ ARC_br, AUX_CND|cLT|N_5|Y_3|AUX_V2, {fB32, fC32, S9}, NULL }, // 0x0A
|
|
{ ARC_br, AUX_CND|cGE|N_5|Y_3|AUX_V2, {fB32, fC32, S9}, NULL }, // 0x0B
|
|
{ ARC_br, AUX_CND|cLO|N_5|Y_3|AUX_V2, {fB32, fC32, S9}, NULL }, // 0x0C
|
|
{ ARC_br, AUX_CND|cHS|N_5|Y_3|AUX_V2, {fB32, fC32, S9}, NULL }, // 0x0D
|
|
{ ARC_bbit0, N_5|Y_3, {fB32, fC32, S9}, NULL }, // 0x0E
|
|
{ ARC_bbit1, N_5|Y_3, {fB32, fC32, S9}, NULL }, // 0x0F
|
|
};
|
|
|
|
// indexed by bits 3..0 (maj = 1, b16 = 1, b4 = 1)
|
|
static const arcompact_opcode_t arcompact_br_regimm[0x10] =
|
|
{
|
|
{ ARC_br, AUX_CND|cEQ|N_5|Y_3, {fB32, U6, S9}, NULL }, // 0x00
|
|
{ ARC_br, AUX_CND|cNE|N_5|Y_3, {fB32, U6, S9}, NULL }, // 0x01
|
|
{ ARC_br, AUX_CND|cLT|N_5|Y_3, {fB32, U6, S9}, NULL }, // 0x02
|
|
{ ARC_br, AUX_CND|cGE|N_5|Y_3, {fB32, U6, S9}, NULL }, // 0x03
|
|
{ ARC_br, AUX_CND|cLO|N_5|Y_3, {fB32, U6, S9}, NULL }, // 0x04
|
|
{ ARC_br, AUX_CND|cHS|N_5|Y_3, {fB32, U6, S9}, NULL }, // 0x05
|
|
{ ARC_bbit0, N_5|Y_3|AUX_V2, {fB32, U6, S9}, NULL }, // 0x06
|
|
{ ARC_bbit1, N_5|Y_3|AUX_V2, {fB32, U6, S9}, NULL }, // 0x07
|
|
{ ARC_br, AUX_CND|cEQ|N_5|Y_3|AUX_V2, {fB32, U6, S9}, NULL }, // 0x08
|
|
{ ARC_br, AUX_CND|cNE|N_5|Y_3|AUX_V2, {fB32, U6, S9}, NULL }, // 0x09
|
|
{ ARC_br, AUX_CND|cLT|N_5|Y_3|AUX_V2, {fB32, U6, S9}, NULL }, // 0x0A
|
|
{ ARC_br, AUX_CND|cGE|N_5|Y_3|AUX_V2, {fB32, U6, S9}, NULL }, // 0x0B
|
|
{ ARC_br, AUX_CND|cLO|N_5|Y_3|AUX_V2, {fB32, U6, S9}, NULL }, // 0x0C
|
|
{ ARC_br, AUX_CND|cHS|N_5|Y_3|AUX_V2, {fB32, U6, S9}, NULL }, // 0x0D
|
|
{ ARC_bbit0, N_5|Y_3, {fB32, U6, S9}, NULL }, // 0x0E
|
|
{ ARC_bbit1, N_5|Y_3, {fB32, U6, S9}, NULL }, // 0x0F
|
|
};
|
|
|
|
// indexed by bit 4 (maj = 1, b16 = 1)
|
|
static const arcompact_opcode_t arcompact_br[4] =
|
|
{
|
|
{ SUBTABLE( 3, 0, arcompact_br_regreg) }, // 0
|
|
{ SUBTABLE( 3, 0, arcompact_br_regimm) }, // 1
|
|
};
|
|
|
|
// indexed by bit 16 (maj = 1)
|
|
static const arcompact_opcode_t arcompact_maj1[0x40] =
|
|
{
|
|
{ SUBTABLE(17, 17, arcompact_bl) }, // 0
|
|
{ SUBTABLE( 4, 4, arcompact_br) }, // 1
|
|
};
|
|
|
|
// indexed by bits 14..12 & 26..24 (maj = 4, 21..16=0x2F, 5..0=0x3F)
|
|
static const arcompact_opcode_t arcompact_zop[0x40] =
|
|
{
|
|
{ 0 }, // 0x00
|
|
{ ARC_sleep, 0, {GENC, 0, 0}, NULL }, // 0x01
|
|
{ ARC_swi, 0, { 0, 0, 0}, NULL }, // 0x02
|
|
{ ARC_sync, 0, { 0, 0, 0}, NULL }, // 0x03
|
|
{ ARC_rtie, 0, { 0, 0, 0}, NULL }, // 0x04
|
|
{ ARC_brk, 0, { 0, 0, 0}, NULL }, // 0x05
|
|
{ ARC_seti,AUX_V2,{GENC, 0, 0}, NULL }, // 0x06
|
|
{ ARC_clri,AUX_V2,{GENC, 0, 0}, NULL }, // 0x07
|
|
{ ARC_wevt, 0, {GENC, 0, 0}, NULL }, // 0x08
|
|
{ 0 }, // 0x09
|
|
{ 0 }, // 0x0A
|
|
{ 0 }, // 0x0B
|
|
{ 0 }, // 0x0C
|
|
{ 0 }, // 0x0D
|
|
{ 0 }, // 0x0E
|
|
{ 0 }, // 0x0F
|
|
{ 0 }, // 0x20
|
|
{ 0 }, // 0x21
|
|
{ 0 }, // 0x22
|
|
{ 0 }, // 0x23
|
|
{ 0 }, // 0x24
|
|
{ 0 }, // 0x25
|
|
{ 0 }, // 0x26
|
|
{ 0 }, // 0x27
|
|
{ 0 }, // 0x28
|
|
{ 0 }, // 0x29
|
|
{ 0 }, // 0x2A
|
|
{ 0 }, // 0x2B
|
|
{ 0 }, // 0x2C
|
|
{ 0 }, // 0x2D
|
|
{ 0 }, // 0x2E
|
|
{ 0 }, // 0x2F
|
|
{ 0 }, // 0x30
|
|
{ 0 }, // 0x31
|
|
{ 0 }, // 0x32
|
|
{ 0 }, // 0x33
|
|
{ 0 }, // 0x34
|
|
{ 0 }, // 0x35
|
|
{ 0 }, // 0x36
|
|
{ 0 }, // 0x37
|
|
{ 0 }, // 0x38
|
|
{ 0 }, // 0x39
|
|
{ 0 }, // 0x3A
|
|
{ 0 }, // 0x3B
|
|
{ 0 }, // 0x3C
|
|
{ 0 }, // 0x3D
|
|
{ 0 }, // 0x3E
|
|
{ 0 }, // 0x3F
|
|
};
|
|
|
|
// indexed by bits 5..0 (maj = 4, 21..16=0x2F)
|
|
static const arcompact_opcode_t arcompact_sop[0x40] =
|
|
{
|
|
{ ARC_asl, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x00
|
|
{ ARC_asr, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x01
|
|
{ ARC_lsr, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x02
|
|
{ ARC_ror, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x03
|
|
{ ARC_rrc, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x04
|
|
{ ARC_sexb, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x05
|
|
{ ARC_sexw, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x06
|
|
{ ARC_extb, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x07
|
|
{ ARC_extw, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x08
|
|
{ ARC_abs, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x09
|
|
{ ARC_not, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x0A
|
|
{ ARC_rlc, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x0B
|
|
{ ARC_ex, AUX_GEN, {GENB, GENC|O_IND,0},NULL}, // 0x0C
|
|
{ ARC_rol, AUX_V2|AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x0D
|
|
{ 0 }, // 0x0E
|
|
{ 0 }, // 0x0F
|
|
{ ARC_llock,AUX_GEN, {GENB, GENC|O_IND, 0}, NULL }, // 0x10
|
|
{ ARC_scond,AUX_GEN, {GENB, GENC|O_IND, 0}, NULL }, // 0x11
|
|
{ 0 }, // 0x12
|
|
{ 0 }, // 0x13
|
|
{ 0 }, // 0x14
|
|
{ 0 }, // 0x15
|
|
{ 0 }, // 0x16
|
|
{ 0 }, // 0x17
|
|
{ 0 }, // 0x18
|
|
{ 0 }, // 0x19
|
|
{ 0 }, // 0x1A
|
|
{ 0 }, // 0x1B
|
|
{ 0 }, // 0x1C
|
|
{ 0 }, // 0x1D
|
|
{ 0 }, // 0x1E
|
|
{ 0 }, // 0x1F
|
|
{ 0 }, // 0x20
|
|
{ 0 }, // 0x21
|
|
{ 0 }, // 0x22
|
|
{ 0 }, // 0x23
|
|
{ 0 }, // 0x24
|
|
{ 0 }, // 0x25
|
|
{ 0 }, // 0x26
|
|
{ 0 }, // 0x27
|
|
{ 0 }, // 0x28
|
|
{ 0 }, // 0x29
|
|
{ 0 }, // 0x2A
|
|
{ 0 }, // 0x2B
|
|
{ 0 }, // 0x2C
|
|
{ 0 }, // 0x2D
|
|
{ 0 }, // 0x2E
|
|
{ 0 }, // 0x2F
|
|
{ 0 }, // 0x30
|
|
{ 0 }, // 0x31
|
|
{ 0 }, // 0x32
|
|
{ 0 }, // 0x33
|
|
{ 0 }, // 0x34
|
|
{ 0 }, // 0x35
|
|
{ 0 }, // 0x36
|
|
{ 0 }, // 0x37
|
|
{ 0 }, // 0x38
|
|
{ 0 }, // 0x39
|
|
{ 0 }, // 0x3A
|
|
{ 0 }, // 0x3B
|
|
{ 0 }, // 0x3C
|
|
{ 0 }, // 0x3D
|
|
{ 0 }, // 0x3E
|
|
{ SUBTABLE2(14, 12, 26, 24, arcompact_zop) },// 0x3F
|
|
};
|
|
|
|
// indexed by bits 21..16 (maj = 4)
|
|
static const arcompact_opcode_t arcompact_maj4[0x40] =
|
|
{
|
|
{ ARC_add, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x00
|
|
{ ARC_adc, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x01
|
|
{ ARC_sub, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x02
|
|
{ ARC_sbc, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x03
|
|
{ ARC_and, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x04
|
|
{ ARC_or, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x05
|
|
{ ARC_bic, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x06
|
|
{ ARC_xor, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x07
|
|
{ ARC_max, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x08
|
|
{ ARC_min, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x09
|
|
{ ARC_mov, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x0A
|
|
{ ARC_tst, AUX_GEN2, {GENB, GENC, 0}, NULL }, // 0x0B
|
|
{ ARC_cmp, AUX_GEN2, {GENB, GENC, 0}, NULL }, // 0x0C
|
|
{ ARC_rcmp, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x0D
|
|
{ ARC_rsub, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0E
|
|
{ ARC_bset, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0F
|
|
{ ARC_bclr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x10
|
|
{ ARC_btst, AUX_GEN2, {GENB, GENC, 0}, NULL }, // 0x11
|
|
{ ARC_bxor, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x12
|
|
{ ARC_bmsk, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x13
|
|
{ ARC_add1, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x14
|
|
{ ARC_add2, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x15
|
|
{ ARC_add3, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x16
|
|
{ ARC_sub1, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x17
|
|
{ ARC_sub2, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x18
|
|
{ ARC_sub3, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x19
|
|
{ ARC_mpy, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1A
|
|
{ ARC_mpyh, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1B
|
|
{ ARC_mpyhu,AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1C
|
|
{ ARC_mpyu, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1D
|
|
{ ARC_mpyw, AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1E
|
|
{ ARC_mpyuw,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1F
|
|
{ ARC_j, AUX_GEN, {GENC|O_IND, 0, 0}, NULL }, // 0x20
|
|
{ ARC_j, AUX_GEN|AUX_D, {GENC|O_IND, 0, 0}, NULL }, // 0x21
|
|
{ ARC_jl, AUX_GEN, {GENC|O_IND, 0, 0}, NULL }, // 0x22
|
|
{ ARC_jl, AUX_GEN|AUX_D, {GENC|O_IND, 0, 0}, NULL }, // 0x23
|
|
{ ARC_bi, AUX_V2, {fC32|O_IDX, 0, 0}, NULL }, // 0x24
|
|
{ ARC_bih, AUX_V2, {fC32|O_IDX, 0, 0}, NULL }, // 0x25
|
|
{ ARC_ldi, AUX_V2|Q_5_0, {GENB, GENC|O_IDX, 0}, NULL }, // 0x26
|
|
{ ARC_aex, AUX_V2|AUX_GEN2, {fB32, GENC|O_IND, 0}, NULL }, // 0x27
|
|
{ ARC_lp, AUX_GEN2, {GENC_PCREL, 0, 0}, NULL }, // 0x28
|
|
{ ARC_flag, AUX_GEN2, {GENC, 0, 0}, NULL }, // 0x29
|
|
{ ARC_lr, 0, {GENB, GENC|O_IND, 0}, NULL }, // 0x2A
|
|
{ ARC_sr, 0, {GENB, GENC|O_IND, 0}, NULL }, // 0x2B
|
|
{ ARC_bmskn,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2C
|
|
{ ARC_null, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1C
|
|
{ ARC_null, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1D
|
|
{ SUBTABLE(5, 0, arcompact_sop) }, // 0x2F
|
|
{ ARC_ld, AAZZXD_23_15, {fA32, fBC_IND, 0}, NULL }, // 0x30
|
|
{ ARC_ld, AAZZXD_23_15, {fA32, fBC_IND, 0}, NULL }, // 0x31
|
|
{ ARC_ld, AAZZXD_23_15, {fA32, fBC_IND, 0}, NULL }, // 0x32
|
|
{ ARC_ld, AAZZXD_23_15, {fA32, fBC_IND, 0}, NULL }, // 0x33
|
|
{ ARC_ld, AAZZXD_23_15, {fA32, fBC_IND, 0}, NULL }, // 0x34
|
|
{ ARC_ld, AAZZXD_23_15, {fA32, fBC_IND, 0}, NULL }, // 0x35
|
|
{ ARC_ld, AAZZXD_23_15, {fA32, fBC_IND, 0}, NULL }, // 0x36
|
|
{ ARC_ld, AAZZXD_23_15, {fA32, fBC_IND, 0}, NULL }, // 0x37
|
|
{ ARC_seteq,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x38
|
|
{ ARC_setne,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x39
|
|
{ ARC_setlt,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3A
|
|
{ ARC_setge,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3B
|
|
{ ARC_setlo,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3C
|
|
{ ARC_seths,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3D
|
|
{ ARC_setle,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3E
|
|
{ ARC_setgt,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3F
|
|
};
|
|
|
|
// indexed by bits 14..12 & 26..24 (maj = 5, 21..16=0x2F, 5..0=0x3F)
|
|
static const arcompact_opcode_t arcompact_zop5[0x40 * 2] =
|
|
{
|
|
{ ARC_aslacc, AUX_V2|AUX_F, {GENC, 0, 0}, NULL }, // 0x00
|
|
{ ARC_aslsacc, AUX_V2|AUX_F, {GENC, 0, 0}, NULL }, // 0x01
|
|
{ 0 }, // 0x02
|
|
{ 0 }, // 0x03
|
|
{ 0, AUX_F, {0, 0, 0}, NULL }, // 0x04(F=0)
|
|
{ ARC_modif, AUX_V2|AUX_F, {GENC, 0, 0}, NULL }, // 0x05
|
|
{ 0 }, // 0x06
|
|
{ 0 }, // 0x07
|
|
{ 0 }, // 0x08
|
|
{ 0 }, // 0x09
|
|
{ 0 }, // 0x0A
|
|
{ 0 }, // 0x0B
|
|
{ 0 }, // 0x0C
|
|
{ 0 }, // 0x0D
|
|
{ 0 }, // 0x0E
|
|
{ 0 }, // 0x0F
|
|
{ 0 }, // 0x10
|
|
{ 0 }, // 0x11
|
|
{ 0 }, // 0x12
|
|
{ 0 }, // 0x13
|
|
{ 0 }, // 0x14
|
|
{ 0 }, // 0x15
|
|
{ 0 }, // 0x16
|
|
{ 0 }, // 0x17
|
|
{ 0 }, // 0x18
|
|
{ 0 }, // 0x19
|
|
{ 0 }, // 0x1A
|
|
{ 0 }, // 0x1B
|
|
{ 0 }, // 0x1C
|
|
{ 0 }, // 0x1D
|
|
{ 0 }, // 0x1E
|
|
{ 0 }, // 0x1F
|
|
{ 0 }, // 0x20
|
|
{ 0 }, // 0x21
|
|
{ 0 }, // 0x22
|
|
{ 0 }, // 0x23
|
|
{ 0 }, // 0x24
|
|
{ 0 }, // 0x25
|
|
{ 0 }, // 0x26
|
|
{ 0 }, // 0x27
|
|
{ 0 }, // 0x28
|
|
{ 0 }, // 0x29
|
|
{ 0 }, // 0x2A
|
|
{ 0 }, // 0x2B
|
|
{ 0 }, // 0x2C
|
|
{ 0 }, // 0x2D
|
|
{ 0 }, // 0x2E
|
|
{ 0 }, // 0x2F
|
|
{ 0 }, // 0x30
|
|
{ 0 }, // 0x31
|
|
{ 0 }, // 0x32
|
|
{ 0 }, // 0x33
|
|
{ 0 }, // 0x34
|
|
{ 0 }, // 0x35
|
|
{ 0 }, // 0x36
|
|
{ 0 }, // 0x37
|
|
{ 0 }, // 0x38
|
|
{ 0 }, // 0x39
|
|
{ 0 }, // 0x3A
|
|
{ 0 }, // 0x3B
|
|
{ 0 }, // 0x3C
|
|
{ 0 }, // 0x3D
|
|
{ 0 }, // 0x3E
|
|
{ 0 }, // 0x3F
|
|
|
|
{ 0 }, // 0x00
|
|
{ 0 }, // 0x01
|
|
{ 0 }, // 0x02
|
|
{ 0 }, // 0x03
|
|
{ ARC_flagacc, AUX_V2, {GENC, 0, 0}, NULL }, // 0x04(F=1)
|
|
{ 0 }, // 0x05
|
|
{ 0 }, // 0x06
|
|
{ 0 }, // 0x07
|
|
{ 0 }, // 0x08
|
|
{ 0 }, // 0x09
|
|
{ 0 }, // 0x0A
|
|
{ 0 }, // 0x0B
|
|
{ 0 }, // 0x0C
|
|
{ 0 }, // 0x0D
|
|
{ 0 }, // 0x0E
|
|
{ 0 }, // 0x0F
|
|
{ 0 }, // 0x10
|
|
{ 0 }, // 0x11
|
|
{ 0 }, // 0x12
|
|
{ 0 }, // 0x13
|
|
{ 0 }, // 0x14
|
|
{ 0 }, // 0x15
|
|
{ 0 }, // 0x16
|
|
{ 0 }, // 0x17
|
|
{ 0 }, // 0x18
|
|
{ 0 }, // 0x19
|
|
{ 0 }, // 0x1A
|
|
{ 0 }, // 0x1B
|
|
{ 0 }, // 0x1C
|
|
{ 0 }, // 0x1D
|
|
{ 0 }, // 0x1E
|
|
{ 0 }, // 0x1F
|
|
{ 0 }, // 0x20
|
|
{ 0 }, // 0x21
|
|
{ 0 }, // 0x22
|
|
{ 0 }, // 0x23
|
|
{ 0 }, // 0x24
|
|
{ 0 }, // 0x25
|
|
{ 0 }, // 0x26
|
|
{ 0 }, // 0x27
|
|
{ 0 }, // 0x28
|
|
{ 0 }, // 0x29
|
|
{ 0 }, // 0x2A
|
|
{ 0 }, // 0x2B
|
|
{ 0 }, // 0x2C
|
|
{ 0 }, // 0x2D
|
|
{ 0 }, // 0x2E
|
|
{ 0 }, // 0x2F
|
|
{ 0 }, // 0x30
|
|
{ 0 }, // 0x31
|
|
{ 0 }, // 0x32
|
|
{ 0 }, // 0x33
|
|
{ 0 }, // 0x34
|
|
{ 0 }, // 0x35
|
|
{ 0 }, // 0x36
|
|
{ 0 }, // 0x37
|
|
{ 0 }, // 0x38
|
|
{ 0 }, // 0x39
|
|
{ 0 }, // 0x3A
|
|
{ 0 }, // 0x3B
|
|
{ 0 }, // 0x3C
|
|
{ 0 }, // 0x3D
|
|
{ 0 }, // 0x3E
|
|
{ 0 }, // 0x3F
|
|
};
|
|
|
|
// indexed by bits 5..0 (maj = 5, 21..16=0x2F)
|
|
static const arcompact_opcode_t arcompact_sop5[0x40] =
|
|
{
|
|
{ ARC_swap, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x00
|
|
{ ARC_norm, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x01
|
|
{ ARC_sat16, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x02
|
|
{ ARC_rnd16, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x03
|
|
{ ARC_abssw, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x04
|
|
{ ARC_abss, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x05
|
|
{ ARC_negsw, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x06
|
|
{ ARC_negs, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x07
|
|
{ ARC_normw, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x08
|
|
{ ARC_swape, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x09
|
|
{ ARC_lsl16, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x0A
|
|
{ ARC_lsr16, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x0B
|
|
{ ARC_asr16, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x0C
|
|
{ ARC_asr8, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x0D
|
|
{ ARC_lsr8, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x0E
|
|
{ ARC_lsl8, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x0F
|
|
{ ARC_rol8, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x10
|
|
{ ARC_ror8, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x11
|
|
{ ARC_ffs, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x12
|
|
{ ARC_fls, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x13
|
|
{ 0 }, // 0x14
|
|
{ 0 }, // 0x15
|
|
{ 0 }, // 0x16
|
|
{ 0 }, // 0x17
|
|
{ ARC_getacc, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x18
|
|
{ ARC_normacc, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x19
|
|
{ ARC_satf, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x1A
|
|
{ 0 }, // 0x1B
|
|
{ ARC_vpack2hbl, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x1C
|
|
{ ARC_vpack2hbm, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x1D
|
|
{ ARC_vpack2hblf,AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x1E
|
|
{ ARC_vpack2hbmf,AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x1F
|
|
{ ARC_vext2bhlf, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x20
|
|
{ ARC_vext2bhmf, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x21
|
|
{ ARC_vrep2hl, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x22
|
|
{ ARC_vrep2hm, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x23
|
|
{ ARC_vext2bhl, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x24
|
|
{ ARC_vext2bhm, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x25
|
|
{ ARC_vsext2bhl, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x26
|
|
{ ARC_vsext2bhm, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x27
|
|
{ ARC_vabs2h, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x28
|
|
{ ARC_vabss2h, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x29
|
|
{ ARC_vneg2h, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x2A
|
|
{ ARC_vnegs2h, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x2B
|
|
{ ARC_vnorm2h, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x2C
|
|
{ 0 }, // 0x2D
|
|
{ ARC_bspeek, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x2E
|
|
{ ARC_bspop, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x2F
|
|
{ ARC_sqrt, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x30
|
|
{ ARC_sqrtf, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x31
|
|
{ 0 }, // 0x32
|
|
{ 0 }, // 0x33
|
|
{ 0 }, // 0x34
|
|
{ 0 }, // 0x35
|
|
{ 0 }, // 0x36
|
|
{ 0 }, // 0x37
|
|
{ 0 }, // 0x38
|
|
{ 0 }, // 0x39
|
|
{ 0 }, // 0x3A
|
|
{ 0 }, // 0x3B
|
|
{ 0 }, // 0x3C
|
|
{ 0 }, // 0x3D
|
|
{ 0 }, // 0x3E
|
|
{ SUBTABLE2(14, 12, 26, 24, arcompact_zop5) }, // 0x3F
|
|
};
|
|
|
|
// indexed by bits 21..16 (maj = 5)
|
|
static const arcompact_opcode_t arcompact_maj5[0x40] =
|
|
{
|
|
{ ARC_asl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x00
|
|
{ ARC_lsr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x01
|
|
{ ARC_asr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x02
|
|
{ ARC_ror, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x03
|
|
{ ARC_mul64, AUX_GEN, {O_ZERO,GENB,GENC}, NULL }, // 0x04
|
|
{ ARC_mulu64, AUX_GEN, {O_ZERO,GENB,GENC}, NULL }, // 0x05
|
|
{ ARC_adds, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x06
|
|
{ ARC_subs, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x07
|
|
{ ARC_divaw, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x08
|
|
{ 0 }, // 0x09
|
|
{ ARC_asls, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0A
|
|
{ ARC_asrs, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x0B
|
|
{ ARC_muldw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x0C
|
|
{ ARC_muludw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x0D
|
|
{ ARC_mulrdw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x0E
|
|
{ 0 }, // 0x0F
|
|
{ ARC_macdw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x10
|
|
{ ARC_macudw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x11
|
|
{ ARC_macrdw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x12
|
|
{ 0 }, // 0x13
|
|
{ ARC_msubdw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x14
|
|
{ 0 }, // 0x15
|
|
{ 0 }, // 0x16
|
|
{ 0 }, // 0x17
|
|
{ 0 }, // 0x18
|
|
{ 0 }, // 0x19
|
|
{ 0 }, // 0x1A
|
|
{ 0 }, // 0x1B
|
|
{ 0 }, // 0x1C
|
|
{ 0 }, // 0x1D
|
|
{ 0 }, // 0x1E
|
|
{ 0 }, // 0x1F
|
|
{ 0 }, // 0x20
|
|
{ 0 }, // 0x21
|
|
{ 0 }, // 0x22
|
|
{ 0 }, // 0x23
|
|
{ 0 }, // 0x24
|
|
{ 0 }, // 0x25
|
|
{ 0 }, // 0x26
|
|
{ 0 }, // 0x27
|
|
{ ARC_addsdw, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x28
|
|
{ ARC_subsdw, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x29
|
|
{ 0 }, // 0x2A
|
|
{ 0 }, // 0x2B
|
|
{ 0 }, // 0x2C
|
|
{ 0 }, // 0x2D
|
|
{ 0 }, // 0x2E
|
|
{ SUBTABLE(5, 0, arcompact_sop5) }, // 0x2F
|
|
{ ARC_mululw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x30
|
|
{ ARC_mullw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x31
|
|
{ ARC_mulflw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x32
|
|
{ ARC_maclw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x33
|
|
{ ARC_macflw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x34
|
|
{ ARC_machulw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x35
|
|
{ ARC_machlw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x36
|
|
{ ARC_machflw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x37
|
|
{ ARC_mulhlw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x38
|
|
{ ARC_mulhflw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x39
|
|
{ 0 }, // 0x3A
|
|
{ 0 }, // 0x3B
|
|
{ 0 }, // 0x3C
|
|
{ 0 }, // 0x3D
|
|
{ 0 }, // 0x3E
|
|
{ 0 }, // 0x3F
|
|
};
|
|
|
|
// indexed by bits 21..16 (maj = 5)
|
|
static const arcompact_opcode_t arcv2_maj5[0x40 * 2] =
|
|
{
|
|
{ ARC_asl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x00
|
|
{ ARC_lsr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x01
|
|
{ ARC_asr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x02
|
|
{ ARC_ror, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x03
|
|
{ ARC_div, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x04
|
|
{ ARC_divu, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x05
|
|
{ ARC_adds, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x06
|
|
{ ARC_subs, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x07
|
|
{ ARC_rem, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x08
|
|
{ ARC_remu, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x09
|
|
{ ARC_asls, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0A
|
|
{ ARC_asrs, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0B
|
|
{ ARC_asrsr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0C
|
|
{ ARC_valgn2h, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x0D(F=0)
|
|
{ ARC_mac, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0E
|
|
{ ARC_macu, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0F
|
|
{ ARC_dmpyh, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x10
|
|
{ ARC_dmpyhu, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x11
|
|
{ ARC_dmach, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x12
|
|
{ ARC_dmachu, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x13
|
|
{ ARC_vadd2h, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x14(F=0)
|
|
{ ARC_vsub2h, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x15(F=0)
|
|
{ ARC_vaddsub2h,AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x16(F=0)
|
|
{ ARC_vsubadd2h,AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x17(F=0)
|
|
{ ARC_mpyd, AUX_GEN, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x18
|
|
{ ARC_mpydu, AUX_GEN, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x19
|
|
{ ARC_macd, AUX_GEN, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x1A
|
|
{ ARC_macdu, AUX_GEN, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x1B
|
|
{ ARC_vmpy2h, AUX_GEN|AUX_F, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x1C(F=0)
|
|
{ ARC_vmpy2hu, AUX_GEN|AUX_F, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x1D(F=0)
|
|
{ ARC_vmac2h, AUX_GEN|AUX_F, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x1E(F=0)
|
|
{ ARC_vmac2hu, AUX_GEN|AUX_F, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x1F(F=0)
|
|
{ ARC_vmpy2hwf, AUX_GEN|AUX_F, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x20(F=0)
|
|
{ ARC_vasl2h, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x21(F=0)
|
|
{ ARC_vasr2h, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x22(F=0)
|
|
{ ARC_vlsr2h, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x23(F=0)
|
|
{ ARC_vadd4b, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x24(F=0)
|
|
{ ARC_vsub4b, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x25(F=0)
|
|
{ ARC_adcs, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x26
|
|
{ ARC_sbcs, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x27
|
|
{ ARC_dmpyhwf, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x28
|
|
{ ARC_vpack2hl, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x29(F=0)
|
|
{ ARC_dmpyhf, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2A
|
|
{ ARC_dmpyhfr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2B
|
|
{ ARC_dmachf, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2C
|
|
{ ARC_dmachfr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2D
|
|
{ ARC_vperm, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x2E
|
|
{ SUBTABLE(5, 0, arcompact_sop5) }, // 0x2F
|
|
{ 0 }, // 0x30
|
|
{ 0 }, // 0x31
|
|
{ 0 }, // 0x32
|
|
{ 0 }, // 0x33
|
|
{ 0 }, // 0x34
|
|
{ 0 }, // 0x35
|
|
{ 0 }, // 0x36
|
|
{ 0 }, // 0x37
|
|
{ 0 }, // 0x38
|
|
{ 0 }, // 0x39
|
|
{ 0 }, // 0x3A
|
|
{ 0 }, // 0x3B
|
|
{ 0 }, // 0x3C
|
|
{ 0 }, // 0x3D
|
|
{ 0 }, // 0x3E
|
|
{ 0 }, // 0x3F
|
|
|
|
{ 0 }, // 0x00(F=1)
|
|
{ 0 }, // 0x01(F=1)
|
|
{ 0 }, // 0x02(F=1)
|
|
{ 0 }, // 0x03(F=1)
|
|
{ 0 }, // 0x04(F=1)
|
|
{ 0 }, // 0x05(F=1)
|
|
{ 0 }, // 0x06(F=1)
|
|
{ 0 }, // 0x07(F=1)
|
|
{ 0 }, // 0x08(F=1)
|
|
{ 0 }, // 0x09(F=1)
|
|
{ 0 }, // 0x0A(F=1)
|
|
{ 0 }, // 0x0B(F=1)
|
|
{ 0 }, // 0x0C(F=1)
|
|
{ ARC_setacc, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x0D(F=1)
|
|
{ 0 }, // 0x0E(F=1)
|
|
{ 0 }, // 0x0F(F=1)
|
|
{ 0 }, // 0x10(F=1)
|
|
{ 0 }, // 0x11(F=1)
|
|
{ 0 }, // 0x12(F=1)
|
|
{ 0 }, // 0x13(F=1)
|
|
{ ARC_vadds2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x14(F=1)
|
|
{ ARC_vsubs2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x15(F=1)
|
|
{ ARC_vaddsubs2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x16(F=1)
|
|
{ ARC_vsubadds2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x17(F=1)
|
|
{ 0 }, // 0x18(F=1)
|
|
{ 0 }, // 0x19(F=1)
|
|
{ 0 }, // 0x1A(F=1)
|
|
{ 0 }, // 0x1B(F=1)
|
|
{ ARC_vmpy2hf, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x1C(F=1)
|
|
{ ARC_vmpy2hfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x1D(F=1)
|
|
{ ARC_vmac2hf, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x1E(F=1)
|
|
{ ARC_vmac2hfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x1F(F=1)
|
|
{ 0 }, // 0x20(F=1)
|
|
{ ARC_vasls2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x21(F=1)
|
|
{ ARC_vasrs2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x22(F=1)
|
|
{ ARC_vasrsr2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x23(F=1)
|
|
{ ARC_vmax2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x24(F=1)
|
|
{ ARC_vmin2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x25(F=1)
|
|
{ 0 }, // 0x26(F=1)
|
|
{ 0 }, // 0x27(F=1)
|
|
{ 0 }, // 0x28(F=1)
|
|
{ ARC_vpack2hm, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x29(F=1)
|
|
{ 0 }, // 0x2A(F=1)
|
|
{ 0 }, // 0x2B(F=1)
|
|
{ 0 }, // 0x2C(F=1)
|
|
{ 0 }, // 0x2D(F=1)
|
|
{ ARC_bspush, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x2E(F=1)
|
|
{ 0 }, // 0x2F(F=1)
|
|
{ 0 }, // 0x30(F=1)
|
|
{ 0 }, // 0x31(F=1)
|
|
{ 0 }, // 0x32(F=1)
|
|
{ 0 }, // 0x33(F=1)
|
|
{ 0 }, // 0x34(F=1)
|
|
{ 0 }, // 0x35(F=1)
|
|
{ 0 }, // 0x36(F=1)
|
|
{ 0 }, // 0x37(F=1)
|
|
{ 0 }, // 0x38(F=1)
|
|
{ 0 }, // 0x39(F=1)
|
|
{ 0 }, // 0x3A(F=1)
|
|
{ 0 }, // 0x3B(F=1)
|
|
{ 0 }, // 0x3C(F=1)
|
|
{ 0 }, // 0x3D(F=1)
|
|
{ 0 }, // 0x3E(F=1)
|
|
{ 0 }, // 0x3F(F=1)
|
|
};
|
|
|
|
// indexed by bits 21..16
|
|
static const arcompact_opcode_t arcompact_maj6_1[0x40] =
|
|
{
|
|
{ ARC_fmul, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 00
|
|
{ ARC_fadd, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 01
|
|
{ ARC_fsub, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 02
|
|
{ 0 }, // 03
|
|
{ 0 }, // 04
|
|
{ 0 }, // 05
|
|
{ 0 }, // 06
|
|
{ 0 }, // 07
|
|
{ ARC_dmulh11, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 08
|
|
{ ARC_dmulh12, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 09
|
|
{ ARC_dmulh21, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0a
|
|
{ ARC_dmulh22, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0b
|
|
{ ARC_daddh11, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0c
|
|
{ ARC_daddh12, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0d
|
|
{ ARC_daddh21, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0e
|
|
{ ARC_daddh22, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0f
|
|
{ ARC_dsubh11, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 10
|
|
{ ARC_dsubh12, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 11
|
|
{ ARC_dsubh21, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 12
|
|
{ ARC_dsubh22, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 13
|
|
{ ARC_drsubh11, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 14
|
|
{ ARC_drsubh12, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 15
|
|
{ ARC_drsubh21, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 16
|
|
{ ARC_drsubh22, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 17
|
|
{ ARC_dexcl1, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 18
|
|
{ ARC_dexcl2, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 19
|
|
{ 0 }, // 1a
|
|
{ 0 }, // 1b
|
|
{ 0 }, // 1c
|
|
{ 0 }, // 1d
|
|
{ 0 }, // 1e
|
|
{ 0 }, // 1f
|
|
{ ARC_pkqb, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 20
|
|
{ ARC_upkqb, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 21
|
|
{ ARC_xpkqb, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 22
|
|
{ ARC_avgqb, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 23
|
|
{ ARC_addqbs, AUX_GEN, {GENA, GENB, GENC}, NULL },// 24
|
|
{ ARC_mpyqb, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 25
|
|
{ ARC_fxtr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 26
|
|
{ ARC_iaddr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 27
|
|
{ ARC_acm, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 28
|
|
{ ARC_sfxtr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 29
|
|
{ ARC_clamp, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 2a
|
|
{ 0 }, // 2b
|
|
{ 0 }, // 2c
|
|
{ 0 }, // 2d
|
|
{ 0 }, // 2e
|
|
{ 0 }, // 2f
|
|
{ 0 }, // 30
|
|
{ 0 }, // 31
|
|
{ 0 }, // 32
|
|
{ 0 }, // 33
|
|
{ 0 }, // 34
|
|
{ 0 }, // 35
|
|
{ 0 }, // 36
|
|
{ 0 }, // 37
|
|
{ 0 }, // 38
|
|
{ 0 }, // 39
|
|
{ 0 }, // 3a
|
|
{ 0 }, // 3b
|
|
{ 0 }, // 3c
|
|
{ 0 }, // 3d
|
|
{ 0 }, // 3e
|
|
{ 0 } // 3f
|
|
};
|
|
|
|
// indexed by bits 23..22
|
|
static const arcompact_opcode_t arcompact_maj6[4] =
|
|
{
|
|
{ SUBTABLE(21, 16, arcompact_maj6_1) }, // 00
|
|
{ SUBTABLE(21, 16, arcompact_maj6_1) }, // 01
|
|
{ SUBTABLE(21, 16, arcompact_maj6_1) }, // 02
|
|
{ 0 } // to be implemented
|
|
};
|
|
|
|
// indexed by bits 5..0 (maj = 6, 21..16=0x2F)
|
|
static const arcompact_opcode_t arcv2_sop6[0x40] =
|
|
{
|
|
{ ARC_fssqrt, AUX_GEN2, {GENB, GENC, 0}, NULL }, // 0x00(F=0) reference doesn't specify minor opcode
|
|
{ 0 }, // 0x01
|
|
{ 0 }, // 0x02
|
|
{ 0 }, // 0x03
|
|
{ 0 }, // 0x04
|
|
{ 0 }, // 0x05
|
|
{ 0 }, // 0x06
|
|
{ 0 }, // 0x07
|
|
{ 0 }, // 0x08
|
|
{ 0 }, // 0x09
|
|
{ 0 }, // 0x0A
|
|
{ 0 }, // 0x0B
|
|
{ 0 }, // 0x0C
|
|
{ 0 }, // 0x0D
|
|
{ 0 }, // 0x0E
|
|
{ 0 }, // 0x0F
|
|
{ 0 }, // 0x10
|
|
{ 0 }, // 0x11
|
|
{ 0 }, // 0x12
|
|
{ 0 }, // 0x13
|
|
{ 0 }, // 0x14
|
|
{ 0 }, // 0x15
|
|
{ 0 }, // 0x16
|
|
{ 0 }, // 0x17
|
|
{ 0 }, // 0x18
|
|
{ 0 }, // 0x18
|
|
{ 0 }, // 0x1A
|
|
{ ARC_cbflyhf1r, AUX_GEN2, {GENB, GENC, 0}, NULL }, // 0x1B(F=0) according to reference
|
|
{ 0 }, // 0x1C
|
|
{ 0 }, // 0x1D
|
|
{ 0 }, // 0x1E
|
|
{ 0 }, // 0x1F
|
|
{ 0 }, // 0x20
|
|
{ 0 }, // 0x21
|
|
{ 0 }, // 0x22
|
|
{ 0 }, // 0x23
|
|
{ 0 }, // 0x24
|
|
{ 0 }, // 0x25
|
|
{ 0 }, // 0x26
|
|
{ 0 }, // 0x27
|
|
{ 0 }, // 0x28
|
|
{ 0 }, // 0x29
|
|
{ 0 }, // 0x2A
|
|
{ 0 }, // 0x2B
|
|
{ 0 }, // 0x2C
|
|
{ 0 }, // 0x2D
|
|
{ 0 }, // 0x2E
|
|
{ 0 }, // 0x2F
|
|
{ 0 }, // 0x30
|
|
{ 0 }, // 0x31
|
|
{ 0 }, // 0x32
|
|
{ 0 }, // 0x33
|
|
{ 0 }, // 0x34
|
|
{ 0 }, // 0x35
|
|
{ 0 }, // 0x36
|
|
{ 0 }, // 0x37
|
|
{ 0 }, // 0x38
|
|
{ ARC_cbflyhf1r, AUX_GEN2, {GENB, GENC, 0}, NULL }, // 0x39(F=0) as encoded by the toolchain
|
|
{ 0 }, // 0x3A
|
|
{ 0 }, // 0x3B
|
|
{ 0 }, // 0x3C
|
|
{ 0 }, // 0x3D
|
|
{ 0 }, // 0x3E
|
|
{ 0 }, // 0x3F
|
|
};
|
|
|
|
static const arcompact_opcode_t arcv2_maj6[0x40 * 2] =
|
|
{
|
|
{ ARC_fmul, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x00(F=0)
|
|
{ ARC_fadd, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x01(F=0)
|
|
{ ARC_fsub, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x02(F=0)
|
|
{ ARC_vmsub2hfr, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x03(F=0)
|
|
{ ARC_vmsub2hf, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x04(F=0)
|
|
{ ARC_fsmadd, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x05(F=0)
|
|
{ ARC_fsmsub, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x06(F=0)
|
|
{ ARC_fsdiv, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x07(F=0)
|
|
{ ARC_fcvt32, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x08(F=0)
|
|
{ 0, AUX_F, {0, 0, 0}, NULL }, // 0x09(F=0)
|
|
{ ARC_mpyf, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0A
|
|
{ ARC_mpyfr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0B
|
|
{ ARC_macf, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0C
|
|
{ ARC_macfr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0D
|
|
{ ARC_msubf, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0E
|
|
{ ARC_msubfr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0F
|
|
{ ARC_divf, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x10
|
|
{ ARC_vmac2hnfr, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x11
|
|
{ ARC_mpydf, AUX_GEN, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x12
|
|
{ ARC_macdf, AUX_GEN, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x13
|
|
{ ARC_msubwhfl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x14
|
|
{ ARC_msubdf, AUX_GEN, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x15
|
|
{ ARC_dmpyhbl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x16
|
|
{ ARC_dmpyhbm, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x17
|
|
{ ARC_dmachbl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x18
|
|
{ ARC_dmachbm, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x19
|
|
{ ARC_msubwhflr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1A
|
|
{ ARC_cmpyhfmr, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x1B
|
|
{ ARC_mpywhl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1C
|
|
{ ARC_macwhl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1D
|
|
{ ARC_mpywhul, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1E
|
|
{ ARC_macwhul, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1F
|
|
{ ARC_mpywhfm, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x20
|
|
{ ARC_mpywhfmr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x21
|
|
{ ARC_macwhfm, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x22
|
|
{ ARC_macwhfmr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x23
|
|
{ ARC_mpywhfl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x24
|
|
{ ARC_mpywhflr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x25
|
|
{ ARC_macwhfl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x26
|
|
{ ARC_macwhflr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x27
|
|
{ ARC_macwhkl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x28
|
|
{ ARC_macwhkul, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x29
|
|
{ ARC_mpywhkl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2A
|
|
{ ARC_mpywhkul, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2B
|
|
{ ARC_msubwhfm, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2C
|
|
{ ARC_msubwhfmr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2D
|
|
{ 0 }, // 0x2E
|
|
{ SUBTABLE(5, 0, arcv2_sop6) }, // 0x2F
|
|
{ ARC_dmulh11, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x30
|
|
{ ARC_dmulh12, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x31
|
|
{ ARC_dmulh21, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x32
|
|
{ ARC_dmulh22, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x33
|
|
{ ARC_daddh11, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x34
|
|
{ ARC_daddh12, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x35
|
|
{ ARC_daddh21, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x36
|
|
{ ARC_daddh22, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x37
|
|
{ ARC_dsubh11, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x38
|
|
{ ARC_dsubh12, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x39
|
|
{ ARC_dsubh21, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3A
|
|
{ ARC_dsubh22, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3B
|
|
{ ARC_dexcl1, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3C
|
|
{ ARC_dexcl2, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3D
|
|
{ 0 }, // 0x3E
|
|
{ 0 }, // 0x3F
|
|
|
|
{ ARC_cmpyhnfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x00
|
|
{ ARC_cmpyhfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x01
|
|
{ ARC_cmpychnfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x02
|
|
{ ARC_fscmp, AUX_GEN2, {GENB, GENC, 0}, NULL }, // 0x03
|
|
{ ARC_fscmpf, AUX_GEN2, {GENB, GENC, 0}, NULL }, // 0x04
|
|
{ ARC_cmpychfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x05
|
|
{ ARC_cmachnfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x06
|
|
{ ARC_cmachfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x07
|
|
{ ARC_cmacchnfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x08
|
|
{ ARC_cmacchfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x09
|
|
{ 0 }, // 0x0A
|
|
{ 0 }, // 0x0B
|
|
{ 0 }, // 0x0C
|
|
{ 0 }, // 0x0D
|
|
{ 0 }, // 0x0E
|
|
{ 0 }, // 0x0F
|
|
{ 0 }, // 0x10
|
|
{ ARC_vmsub2hnfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x11
|
|
{ 0 }, // 0x12
|
|
{ 0 }, // 0x13
|
|
{ 0 }, // 0x14
|
|
{ 0 }, // 0x15
|
|
{ 0 }, // 0x16
|
|
{ 0 }, // 0x17
|
|
{ 0 }, // 0x18
|
|
{ 0 }, // 0x19
|
|
{ 0 }, // 0x1A
|
|
{ ARC_cbflyhf0r, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x1B
|
|
{ 0 }, // 0x1C
|
|
{ 0 }, // 0x1D
|
|
{ 0 }, // 0x1E
|
|
{ 0 }, // 0x1F
|
|
{ 0 }, // 0x20
|
|
{ 0 }, // 0x21
|
|
{ 0 }, // 0x22
|
|
{ 0 }, // 0x23
|
|
{ 0 }, // 0x24
|
|
{ 0 }, // 0x25
|
|
{ 0 }, // 0x26
|
|
{ 0 }, // 0x27
|
|
{ 0 }, // 0x28
|
|
{ 0 }, // 0x29
|
|
{ 0 }, // 0x2A
|
|
{ 0 }, // 0x2B
|
|
{ 0 }, // 0x2C
|
|
{ 0 }, // 0x2D
|
|
{ 0 }, // 0x2E
|
|
{ 0 }, // 0x2F
|
|
{ 0 }, // 0x30
|
|
{ 0 }, // 0x31
|
|
{ 0 }, // 0x32
|
|
{ 0 }, // 0x33
|
|
{ 0 }, // 0x34
|
|
{ 0 }, // 0x35
|
|
{ 0 }, // 0x36
|
|
{ 0 }, // 0x37
|
|
{ 0 }, // 0x38
|
|
{ 0 }, // 0x39
|
|
{ 0 }, // 0x3A
|
|
{ 0 }, // 0x3B
|
|
{ 0 }, // 0x3C
|
|
{ 0 }, // 0x3D
|
|
{ 0 }, // 0x3E
|
|
{ 0 }, // 0x3F
|
|
};
|
|
|
|
// indexed by bits 4..3 (maj = 0xC)
|
|
static const arcompact_opcode_t arcompact_maj0C[4] =
|
|
{
|
|
{ ARC_ld, 0, { fA16, fBC16_IND, 0}, NULL }, // 0x0
|
|
{ ARC_ld, AUX_B, { fA16, fBC16_IND, 0}, NULL }, // 0x1
|
|
{ ARC_ld, AUX_W, { fA16, fBC16_IND, 0}, NULL }, // 0x2
|
|
{ ARC_add, 0, { fA16, fB16, fC16 }, NULL }, // 0x3
|
|
};
|
|
|
|
// indexed by bits 4..3 (maj = 0xD)
|
|
static const arcompact_opcode_t arcompact_maj0D[4] =
|
|
{
|
|
{ ARC_add, 0, {fC16, fB16, U3 }, NULL }, // 0x00
|
|
{ ARC_sub, 0, {fC16, fB16, U3 }, NULL }, // 0x01
|
|
{ ARC_asl, 0, {fC16, fB16, U3 }, NULL }, // 0x02
|
|
{ ARC_asr, 0, {fC16, fB16, U3 }, NULL }, // 0x03
|
|
};
|
|
|
|
// indexed by bits 4..3 (maj = 0xE)
|
|
static const arcompact_opcode_t arcompact_maj0E[4] =
|
|
{
|
|
{ ARC_add, 0, {fB16, fB16, fH16}, NULL }, // 0x00
|
|
{ ARC_mov, 0, {fB16, fH16, 0 }, NULL }, // 0x01
|
|
{ ARC_cmp, 0, {fB16, fH16, 0 }, NULL }, // 0x02
|
|
{ ARC_mov, 0, {fH16, fB16, 0 }, NULL }, // 0x03
|
|
};
|
|
|
|
// indexed by bits 4..3 (maj = 0xE)
|
|
static const arcompact_opcode_t arcv2_maj0E[8] =
|
|
{
|
|
{ ARC_add, 0, {fB16, fB16, fH16v2}, NULL }, // 0x00
|
|
{ ARC_add, 0, {fH16v2, fH16v2, S3 }, NULL }, // 0x01
|
|
{ 0 }, // 0x02
|
|
{ ARC_mov, 0, {fH16v2, S3, 0 }, NULL }, // 0x03
|
|
{ ARC_cmp, 0, {fB16, fH16v2, 0 }, NULL }, // 0x04
|
|
{ ARC_cmp, 0, {fH16v2, S3, 0 }, NULL }, // 0x05
|
|
{ 0 }, // 0x06
|
|
{ ARC_mov, AUX_CND|cNE, {fB16, fH16v2, 0 }, NULL }, // 0x07
|
|
};
|
|
|
|
// indexed by bits 10..8 (maj = 0xF, 4..0 = 0x0, 7..5=0x7)
|
|
// 01111 iii 111 00000
|
|
static const arcompact_opcode_t arcompact_zop16[8] =
|
|
{
|
|
{ ARC_nop, 0, { 0, 0, 0}, NULL }, // 0x00
|
|
{ ARC_unimp, 0, { 0, 0, 0}, NULL }, // 0x01
|
|
{ ARC_swi, 0, { 0, 0, 0}, NULL }, // 0x02
|
|
{ 0 }, // 0x03
|
|
{ ARC_j, AUX_CND|cEQ, {R_BLINK|O_IND, 0, 0}, NULL }, // 0x04
|
|
{ ARC_j, AUX_CND|cNE, {R_BLINK|O_IND, 0, 0}, NULL }, // 0x05
|
|
{ ARC_j, 0, {R_BLINK|O_IND, 0, 0}, NULL }, // 0x06
|
|
{ ARC_j, AUX_D, {R_BLINK|O_IND, 0, 0}, NULL }, // 0x07
|
|
};
|
|
|
|
// indexed by bits 7..5 (maj = 0xF, 4..0 = 0x0)
|
|
// 01111 bbb iii 00000
|
|
static const arcompact_opcode_t arcompact_sop16[8] =
|
|
{
|
|
{ ARC_j, 0, {fB16|O_IND, 0, 0}, NULL }, // 0x00
|
|
{ ARC_j, AUX_D, {fB16|O_IND, 0, 0}, NULL }, // 0x01
|
|
{ ARC_jl, 0, {fB16|O_IND, 0, 0}, NULL }, // 0x02
|
|
{ ARC_jl, AUX_D, {fB16|O_IND, 0, 0}, NULL }, // 0x03
|
|
{ 0 }, // 0x04
|
|
{ 0 }, // 0x05
|
|
{ ARC_sub, AUX_CND|cNE, {fB16, fB16, fB16}, NULL }, // 0x06
|
|
{ SUBTABLE(10, 8, arcompact_zop16) }, // 0x07
|
|
};
|
|
|
|
// indexed by bits 4..0 (maj = 0xF)
|
|
// 01111 bbb ccc iiiii
|
|
static const arcompact_opcode_t arcompact_maj0F[0x20] =
|
|
{
|
|
{ SUBTABLE(7, 5, arcompact_sop16) }, // 0x00
|
|
{ 0 }, // 0x01
|
|
{ ARC_sub, 0, {fB16, fB16, fC16}, NULL }, // 0x02
|
|
{ 0 }, // 0x03
|
|
{ ARC_and, 0, {fB16, fB16, fC16}, NULL }, // 0x04
|
|
{ ARC_or, 0, {fB16, fB16, fC16}, NULL }, // 0x05
|
|
{ ARC_bic, 0, {fB16, fB16, fC16}, NULL }, // 0x06
|
|
{ ARC_xor, 0, {fB16, fB16, fC16}, NULL }, // 0x05
|
|
{ 0 }, // 0x08
|
|
{ 0 }, // 0x09
|
|
{ 0 }, // 0x0A
|
|
{ ARC_tst, 0, {fB16, fC16, 0 }, NULL }, // 0x0B
|
|
{ ARC_mul64, 0, {fB16, fC16, 0 }, NULL }, // 0x0C
|
|
{ ARC_sexb, 0, {fB16, fC16, 0 }, NULL }, // 0x0D
|
|
{ ARC_sexw, 0, {fB16, fC16, 0 }, NULL }, // 0x0E
|
|
{ ARC_extb, 0, {fB16, fC16, 0 }, NULL }, // 0x0F
|
|
{ ARC_extw, 0, {fB16, fC16, 0 }, NULL }, // 0x10
|
|
{ ARC_abs, 0, {fB16, fC16, 0 }, NULL }, // 0x11
|
|
{ ARC_not, 0, {fB16, fC16, 0 }, NULL }, // 0x12
|
|
{ ARC_neg, 0, {fB16, fC16, 0 }, NULL }, // 0x13
|
|
{ ARC_add1, 0, {fB16, fB16, fC16}, NULL }, // 0x14
|
|
{ ARC_add2, 0, {fB16, fB16, fC16}, NULL }, // 0x15
|
|
{ ARC_add3, 0, {fB16, fB16, fC16}, NULL }, // 0x16
|
|
{ 0 }, // 0x17
|
|
{ ARC_asl, 0, {fB16, fB16, fC16}, NULL }, // 0x18
|
|
{ ARC_lsr, 0, {fB16, fB16, fC16}, NULL }, // 0x19
|
|
{ ARC_asr, 0, {fB16, fB16, fC16}, NULL }, // 0x1A
|
|
{ ARC_asl, 0, {fB16, fC16, 0 }, NULL }, // 0x1B
|
|
{ ARC_asr, 0, {fB16, fC16, 0 }, NULL }, // 0x1C
|
|
{ ARC_lsr, 0, {fB16, fC16, 0 }, NULL }, // 0x1D
|
|
{ ARC_trap, 0, { 0, 0, 0 }, NULL }, // 0x1E
|
|
{ ARC_brk, 0, { 0, 0, 0 }, NULL }, // 0x1F
|
|
};
|
|
|
|
// indexed by bits 4..0 (maj = 0xF)
|
|
// 01111 bbb ccc iiiii
|
|
static const arcompact_opcode_t arcv2_maj0F[0x20] =
|
|
{
|
|
{ SUBTABLE(7, 5, arcompact_sop16) }, // 0x00
|
|
{ 0 }, // 0x01
|
|
{ ARC_sub, 0, {fB16, fB16, fC16}, NULL }, // 0x02
|
|
{ 0 }, // 0x03
|
|
{ ARC_and, 0, {fB16, fB16, fC16}, NULL }, // 0x04
|
|
{ ARC_or, 0, {fB16, fB16, fC16}, NULL }, // 0x05
|
|
{ ARC_bic, 0, {fB16, fB16, fC16}, NULL }, // 0x06
|
|
{ ARC_xor, 0, {fB16, fB16, fC16}, NULL }, // 0x05
|
|
{ 0 }, // 0x08
|
|
{ ARC_mpyw, 0, {fB16, fB16, fC16}, NULL }, // 0x09
|
|
{ ARC_mpyuw, 0, {fB16, fB16, fC16}, NULL }, // 0x0A
|
|
{ ARC_tst, 0, {fB16, fC16, 0 }, NULL }, // 0x0B
|
|
{ ARC_mpy, 0, {fB16, fB16, fC16}, NULL }, // 0x0C breaking change
|
|
{ ARC_sexb, 0, {fB16, fC16, 0 }, NULL }, // 0x0D
|
|
{ ARC_sexw, 0, {fB16, fC16, 0 }, NULL }, // 0x0E
|
|
{ ARC_extb, 0, {fB16, fC16, 0 }, NULL }, // 0x0F
|
|
{ ARC_extw, 0, {fB16, fC16, 0 }, NULL }, // 0x10
|
|
{ ARC_abs, 0, {fB16, fC16, 0 }, NULL }, // 0x11
|
|
{ ARC_not, 0, {fB16, fC16, 0 }, NULL }, // 0x12
|
|
{ ARC_neg, 0, {fB16, fC16, 0 }, NULL }, // 0x13
|
|
{ ARC_add1, 0, {fB16, fB16, fC16}, NULL }, // 0x14
|
|
{ ARC_add2, 0, {fB16, fB16, fC16}, NULL }, // 0x15
|
|
{ ARC_add3, 0, {fB16, fB16, fC16}, NULL }, // 0x16
|
|
{ 0 }, // 0x17
|
|
{ ARC_asl, 0, {fB16, fB16, fC16}, NULL }, // 0x18
|
|
{ ARC_lsr, 0, {fB16, fB16, fC16}, NULL }, // 0x19
|
|
{ ARC_asr, 0, {fB16, fB16, fC16}, NULL }, // 0x1A
|
|
{ ARC_asl, 0, {fB16, fC16, 0 }, NULL }, // 0x1B
|
|
{ ARC_asr, 0, {fB16, fC16, 0 }, NULL }, // 0x1C
|
|
{ ARC_lsr, 0, {fB16, fC16, 0 }, NULL }, // 0x1D
|
|
{ ARC_trap, 0, {U6_SWI, 0, 0 }, NULL }, // 0x1E
|
|
{ ARC_swi, 0, {U6_SWI, 0, 0 }, NULL }, // 0x1F
|
|
};
|
|
|
|
// indexed by bits 7..5 (maj = 0x17)
|
|
static const arcompact_opcode_t arcompact_maj17[8] =
|
|
{
|
|
{ ARC_asl, 0, {fB16, fB16, U5}, NULL }, // 0x00
|
|
{ ARC_lsr, 0, {fB16, fB16, U5}, NULL }, // 0x01
|
|
{ ARC_asr, 0, {fB16, fB16, U5}, NULL }, // 0x02
|
|
{ ARC_sub, 0, {fB16, fB16, U5}, NULL }, // 0x03
|
|
{ ARC_bset, 0, {fB16, fB16, U5}, NULL }, // 0x04
|
|
{ ARC_bclr, 0, {fB16, fB16, U5}, NULL }, // 0x05
|
|
{ ARC_bmsk, 0, {fB16, fB16, U5}, NULL }, // 0x06
|
|
{ ARC_btst, 0, {fB16, U5, 0}, NULL }, // 0x07
|
|
};
|
|
|
|
// indexed by bits 10..8 (maj = 0x18, i=5)
|
|
static const arcompact_opcode_t arcompact_sp_addsub[8] =
|
|
{
|
|
{ ARC_add, 0, {R_SP, R_SP, U7L }, NULL }, // 0x00
|
|
{ ARC_sub, 0, {R_SP, R_SP, U7L }, NULL }, // 0x01
|
|
{ 0 }, // 0x02
|
|
{ 0 }, // 0x03
|
|
{ 0 }, // 0x04
|
|
{ 0 }, // 0x05
|
|
{ 0 }, // 0x06
|
|
{ 0 }, // 0x07
|
|
};
|
|
|
|
// indexed by bits 4..0 (maj = 0x18, i=6)
|
|
static const arcompact_opcode_t arcompact_sp_pops[0x20] =
|
|
{
|
|
{ ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x00
|
|
{ ARC_pop, 0, {fB16, 0, 0}, NULL }, // 0x01
|
|
{ ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x02
|
|
{ 0 }, // 0x03
|
|
{ ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x04
|
|
{ 0 }, // 0x05
|
|
{ ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x06
|
|
{ 0 }, // 0x07
|
|
{ ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x08
|
|
{ 0 }, // 0x09
|
|
{ ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x0A
|
|
{ 0 }, // 0x0B
|
|
{ ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x0C
|
|
{ 0 }, // 0x0D
|
|
{ ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x0E
|
|
{ 0 }, // 0x0F
|
|
{ ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x10
|
|
{ ARC_pop, 0, {R_BLINK, 0, 0}, NULL }, // 0x11
|
|
{ ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x12
|
|
{ 0 }, // 0x13
|
|
{ ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x14
|
|
{ 0 }, // 0x15
|
|
{ ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x16
|
|
{ 0 }, // 0x17
|
|
{ ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x18
|
|
{ 0 }, // 0x19
|
|
{ ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x1A
|
|
{ 0 }, // 0x1B
|
|
{ ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x1C
|
|
{ 0 }, // 0x1D
|
|
{ ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x1E
|
|
{ 0 }, // 0x1F
|
|
};
|
|
|
|
// indexed by bits 4..0 (maj = 0x18, i=7)
|
|
static const arcompact_opcode_t arcompact_sp_pushs[0x20] =
|
|
{
|
|
{ ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x00
|
|
{ ARC_push, 0, {fB16, 0, 0}, NULL }, // 0x01
|
|
{ ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x02
|
|
{ 0 }, // 0x03
|
|
{ ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x04
|
|
{ 0 }, // 0x05
|
|
{ ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x06
|
|
{ 0 }, // 0x07
|
|
{ ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x08
|
|
{ 0 }, // 0x09
|
|
{ ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x0A
|
|
{ 0 }, // 0x0B
|
|
{ ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x0C
|
|
{ 0 }, // 0x0D
|
|
{ ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x0E
|
|
{ 0 }, // 0x0F
|
|
{ ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x10
|
|
{ ARC_push, 0, {R_BLINK, 0, 0}, NULL }, // 0x11
|
|
{ ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x12
|
|
{ 0 }, // 0x13
|
|
{ ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x14
|
|
{ 0 }, // 0x15
|
|
{ ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x16
|
|
{ 0 }, // 0x17
|
|
{ ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x18
|
|
{ 0 }, // 0x19
|
|
{ ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x1A
|
|
{ 0 }, // 0x1B
|
|
{ ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x1C
|
|
{ 0 }, // 0x1D
|
|
{ ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x1E
|
|
{ 0 }, // 0x1F
|
|
};
|
|
|
|
// indexed by bits 7..5 (maj = 0x18)
|
|
// sp-based instructions
|
|
static const arcompact_opcode_t arcompact_maj18[8] =
|
|
{
|
|
{ ARC_ld, 0, {fB16, SP_U7, 0 }, NULL }, // 0x00
|
|
{ ARC_ld, AUX_B, {fB16, SP_U7, 0 }, NULL }, // 0x01
|
|
{ ARC_st, 0, {fB16, SP_U7, 0 }, NULL }, // 0x02
|
|
{ ARC_st, AUX_B, {fB16, SP_U7, 0 }, NULL }, // 0x03
|
|
{ ARC_add, 0, {fB16, R_SP, U7L }, NULL }, // 0x04
|
|
{ SUBTABLE( 10, 8, arcompact_sp_addsub) }, // 0x05
|
|
{ SUBTABLE( 4, 0, arcompact_sp_pops) }, // 0x06
|
|
{ SUBTABLE( 4, 0, arcompact_sp_pushs) }, // 0x07
|
|
};
|
|
|
|
// indexed by bits 10..9 (maj = 0x19)
|
|
// gp-based ld/add (data aligned offset)
|
|
static const arcompact_opcode_t arcompact_maj19[4] =
|
|
{
|
|
{ ARC_ld, 0, {R_R0, GP_S11, 0 }, NULL }, // 0x00
|
|
{ ARC_ld, AUX_B, {R_R0, GP_S9, 0 }, NULL }, // 0x01
|
|
{ ARC_ld, AUX_W, {R_R0, GP_S10, 0 }, NULL }, // 0x02
|
|
{ ARC_add, 0, {R_R0, R_GP, S11 }, NULL }, // 0x03
|
|
};
|
|
|
|
// indexed by bits 7..7 (maj = 0x1C)
|
|
static const arcompact_opcode_t arcompact_maj1C[2] =
|
|
{
|
|
{ ARC_add, 0, { fB16, fB16, U7}, NULL }, // 0x00
|
|
{ ARC_cmp, 0, { fB16, U7, 0}, NULL }, // 0x01
|
|
};
|
|
|
|
// indexed by bits 7..7 (maj = 0x1D)
|
|
static const arcompact_opcode_t arcompact_maj1D[2] =
|
|
{
|
|
{ ARC_br, AUX_CND|cEQ, { fB16, O_ZERO, S8}, NULL }, // 0x00
|
|
{ ARC_br, AUX_CND|cNE, { fB16, O_ZERO, S8}, NULL }, // 0x01
|
|
};
|
|
|
|
// indexed by bits 8..6 (maj = 0x1E, 10..9=0x3)
|
|
static const arcompact_opcode_t arcompact_bcc16[8] =
|
|
{
|
|
{ ARC_b, AUX_CND|cGT, { S7, 0, 0}, NULL }, // 0x00
|
|
{ ARC_b, AUX_CND|cGE, { S7, 0, 0}, NULL }, // 0x01
|
|
{ ARC_b, AUX_CND|cLT, { S7, 0, 0}, NULL }, // 0x02
|
|
{ ARC_b, AUX_CND|cLE, { S7, 0, 0}, NULL }, // 0x03
|
|
{ ARC_b, AUX_CND|cHI, { S7, 0, 0}, NULL }, // 0x04
|
|
{ ARC_b, AUX_CND|cHS, { S7, 0, 0}, NULL }, // 0x05
|
|
{ ARC_b, AUX_CND|cLO, { S7, 0, 0}, NULL }, // 0x06
|
|
{ ARC_b, AUX_CND|cLS, { S7, 0, 0}, NULL }, // 0x07
|
|
};
|
|
|
|
// indexed by bits 10..9 (maj = 0x1E)
|
|
static const arcompact_opcode_t arcompact_maj1E[4] =
|
|
{
|
|
{ ARC_b, 0, { S10, 0, 0}, NULL }, // 0x00
|
|
{ ARC_b, AUX_CND|cEQ, { S10, 0, 0}, NULL }, // 0x01
|
|
{ ARC_b, AUX_CND|cNE, { S10, 0, 0}, NULL }, // 0x02
|
|
{ SUBTABLE(8, 6, arcompact_bcc16) }, // 0x03
|
|
};
|
|
|
|
// indexed by major opcode (bits 15..11)
|
|
static const arcompact_opcode_t arcompact_major[0x20] =
|
|
{
|
|
{ SUBTABLE(16, 16, arcompact_maj0) }, // 0x00
|
|
{ SUBTABLE(16, 16, arcompact_maj1) }, // 0x01
|
|
{ ARC_ld, DAAZZX_11_6, {fA32, fB_S9, 0}, NULL},// 0x02
|
|
{ ARC_st, DAAZZ_5_1, {fC32, fB_S9, 0}, NULL},// 0x03
|
|
{ SUBTABLE(21, 16, arcompact_maj4) }, // 0x04
|
|
{ SUBTABLE(21, 16, arcompact_maj5) }, // 0x05
|
|
{ SUBTABLE(23, 22, arcompact_maj6) }, // 0x06
|
|
{ 0 }, // 0x07
|
|
{ 0 }, // 0x08
|
|
{ 0 }, // 0x09
|
|
{ 0 }, // 0x0A
|
|
{ 0 }, // 0x0B
|
|
{ SUBTABLE( 4, 3, arcompact_maj0C) }, // 0x0C
|
|
{ SUBTABLE( 4, 3, arcompact_maj0D) }, // 0x0D
|
|
{ SUBTABLE( 4, 3, arcompact_maj0E) }, // 0x0E
|
|
{ SUBTABLE( 4, 0, arcompact_maj0F) }, // 0x0F
|
|
{ ARC_ld, 0, { fC16, fB_U7, 0}, NULL }, // 0x10
|
|
{ ARC_ld, AUX_B, { fC16, fB_U5, 0}, NULL }, // 0x11
|
|
{ ARC_ld, AUX_W, { fC16, fB_U6, 0}, NULL }, // 0x12
|
|
{ ARC_ld, AUX_W|AUX_X, { fC16, fB_U6, 0}, NULL },// 0x13
|
|
{ ARC_st, 0, { fC16, fB_U7, 0}, NULL }, // 0x14
|
|
{ ARC_st, AUX_B, { fC16, fB_U5, 0}, NULL }, // 0x15
|
|
{ ARC_st, AUX_W, { fC16, fB_U6, 0}, NULL }, // 0x16
|
|
{ SUBTABLE( 7, 5, arcompact_maj17) }, // 0x17
|
|
{ SUBTABLE( 7, 5, arcompact_maj18) }, // 0x18
|
|
{ SUBTABLE(10, 9, arcompact_maj19) }, // 0x19
|
|
{ ARC_ld, 0, { fB16, PCL_U10, 0}, NULL }, // 0x1A
|
|
{ ARC_mov, 0, { fB16, U8, 0}, NULL }, // 0x1B
|
|
{ SUBTABLE( 7, 7, arcompact_maj1C) }, // 0x1C
|
|
{ SUBTABLE( 7, 7, arcompact_maj1D) }, // 0x1D
|
|
{ SUBTABLE(10, 9, arcompact_maj1E) }, // 0x1E
|
|
{ ARC_bl, 0, { S13, 0, 0}, NULL }, // 0x1F
|
|
};
|
|
|
|
// indexed by bit 2 (maj = 8)
|
|
static const arcompact_opcode_t arcv2_maj8[2] =
|
|
{
|
|
{ ARC_mov, 0, {fG16, fH16v2, 0}, NULL }, // 0x00
|
|
{ ARC_ld, 0, {fR16_2, fH16v2_U5, 0}, NULL }, // 0x01
|
|
};
|
|
|
|
// indexed by bits 4..3 (maj = 8)
|
|
static const arcompact_opcode_t arcv2_maj9[4] =
|
|
{
|
|
{ ARC_ld, AUX_AS, {fA16, fBC16_IND, 0}, NULL }, // 0x00
|
|
{ ARC_add, 0, {fR16_1, fB16, U6_16}, NULL }, // 0x01
|
|
{ ARC_sub, 0, {fA16, fB16, fC16}, NULL }, // 0x02
|
|
{ ARC_add, 0, {fR16_1, fB16, U6_16}, NULL }, // 0x03
|
|
};
|
|
|
|
// indexed by bits 4..3 (maj = 0x0A)
|
|
static const arcompact_opcode_t arcv2_maj0A[4] =
|
|
{
|
|
{ ARC_ld, 0, {R_R1, GP_S11_16, 0}, NULL }, // 0x00
|
|
{ ARC_ldi, 0, {fB16, U7_16|O_IDX, 0}, NULL }, // 0x01
|
|
{ ARC_st, 0, {R_R0, GP_S11_16, 0}, NULL }, // 0x02
|
|
{ ARC_ldi, 0, {fB16, U7_16|O_IDX, 0}, NULL }, // 0x03
|
|
};
|
|
|
|
// indexed by bit 10 (maj = 0x0B)
|
|
static const arcompact_opcode_t arcv2_maj0B[2] =
|
|
{
|
|
{ ARC_jli, 0, {U10_16|O_IDX, 0, 0}, NULL }, // 0x00
|
|
{ ARC_ei, 0, {U10_16|O_IDX, 0, 0}, NULL }, // 0x01
|
|
};
|
|
|
|
|
|
// indexed by major opcode (bits 15..11)
|
|
static const arcompact_opcode_t arcv2_major[0x20] =
|
|
{
|
|
{ SUBTABLE(16, 16, arcompact_maj0) }, // 0x00
|
|
{ SUBTABLE(16, 16, arcompact_maj1) }, // 0x01
|
|
{ ARC_ld, DAAZZX_11_6, {fA32, fB_S9, 0}, NULL},// 0x02
|
|
{ ARC_st, DAAZZ_5_1, {fC32_w6, fB_S9, 0}, NULL},// 0x03
|
|
{ SUBTABLE(21, 16, arcompact_maj4) }, // 0x04
|
|
{ SUBTABLE(21, 16, arcv2_maj5) }, // 0x05
|
|
{ SUBTABLE(21, 16, arcv2_maj6) }, // 0x06
|
|
{ 0 }, // 0x07
|
|
{ SUBTABLE( 2, 2, arcv2_maj8) }, // 0x08
|
|
{ SUBTABLE( 4, 3, arcv2_maj9) }, // 0x09
|
|
{ SUBTABLE( 4, 3, arcv2_maj0A) }, // 0x0A
|
|
{ SUBTABLE(10, 10, arcv2_maj0B) }, // 0x0B
|
|
{ SUBTABLE( 4, 3, arcompact_maj0C) }, // 0x0C
|
|
{ SUBTABLE( 4, 3, arcompact_maj0D) }, // 0x0D
|
|
{ SUBTABLE( 4, 2, arcv2_maj0E) }, // 0x0E
|
|
{ SUBTABLE( 4, 0, arcv2_maj0F) }, // 0x0F
|
|
{ ARC_ld, 0, { fC16, fB_U7, 0}, NULL }, // 0x10
|
|
{ ARC_ld, AUX_B, { fC16, fB_U5, 0}, NULL }, // 0x11
|
|
{ ARC_ld, AUX_W, { fC16, fB_U6, 0}, NULL }, // 0x12
|
|
{ ARC_ld, AUX_W|AUX_X, { fC16, fB_U6, 0}, NULL }, // 0x13
|
|
{ ARC_st, 0, { fC16, fB_U7, 0}, NULL }, // 0x14
|
|
{ ARC_st, AUX_B, { fC16, fB_U5, 0}, NULL }, // 0x15
|
|
{ ARC_st, AUX_W, { fC16, fB_U6, 0}, NULL }, // 0x16
|
|
{ SUBTABLE( 7, 5, arcompact_maj17) }, // 0x17
|
|
{ SUBTABLE( 7, 5, arcompact_maj18) }, // 0x18
|
|
{ SUBTABLE(10, 9, arcompact_maj19) }, // 0x19
|
|
{ ARC_ld, 0, { fB16, PCL_U10, 0}, NULL }, // 0x1A
|
|
{ ARC_mov, 0, { fB16, U8, 0}, NULL }, // 0x1B
|
|
{ SUBTABLE( 7, 7, arcompact_maj1C) }, // 0x1C
|
|
{ SUBTABLE( 7, 7, arcompact_maj1D) }, // 0x1D
|
|
{ SUBTABLE(10, 9, arcompact_maj1E) }, // 0x1E
|
|
{ ARC_bl, 0, { S13, 0, 0}, NULL }, // 0x1F
|
|
};
|
|
|
|
// extract bit numbers high..low from val (inclusive, start from 0)
|
|
#define BITS(val, high, low) ( ((val)>>low) & ( (1<<(high-low+1))-1) )
|
|
// sign extend b low bits in x
|
|
// from "Bit Twiddling Hacks"
|
|
static sval_t SIGNEXT(sval_t x, int b)
|
|
{
|
|
uint32 m = 1 << (b - 1);
|
|
x &= ((sval_t(1) << b) - 1);
|
|
return (x ^ m) - m;
|
|
}
|
|
|
|
// extract bitfield with sign extension
|
|
#define SBITS(val, high, low) SIGNEXT(BITS(val, high, low), high-low+1)
|
|
|
|
//----------------------------------------------------------------------
|
|
int arc_t::get_limm(insn_t &insn)
|
|
{
|
|
if ( !got_limm )
|
|
{
|
|
g_limm = (insn.get_next_word() << 16);
|
|
g_limm |= insn.get_next_word();
|
|
got_limm = true;
|
|
}
|
|
return g_limm;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// register, or a reference to long immediate (r62)
|
|
inline void arc_t::opreg(insn_t &insn, op_t &x, int rgnum, int limm)
|
|
{
|
|
if ( rgnum != limm )
|
|
{
|
|
x.reg = uint16(rgnum);
|
|
x.type = o_reg;
|
|
}
|
|
else
|
|
{
|
|
x.type = o_imm;
|
|
// limm as destination is not used
|
|
// so check for instructions where first operand is source
|
|
if ( x.n == 0 && (insn.get_canon_feature(ph) & CF_CHG1) != 0 )
|
|
x.value = 0;
|
|
else
|
|
x.value = get_limm(insn);
|
|
}
|
|
x.dtype = dt_dword;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
inline void opimm(op_t &x, uval_t val)
|
|
{
|
|
x.value = val;
|
|
x.type = o_imm;
|
|
x.dtype = dt_dword;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
inline void arc_t::opdisp(insn_t &insn, op_t &x, int rgnum, ea_t disp)
|
|
{
|
|
if ( rgnum != LIMM )
|
|
{
|
|
x.type = o_displ;
|
|
x.addr = disp;
|
|
x.reg = rgnum;
|
|
}
|
|
else
|
|
{
|
|
x.type = o_mem;
|
|
x.immdisp = disp;
|
|
x.addr = get_limm(insn) + disp * get_scale_factor(insn);
|
|
}
|
|
x.dtype = dt_dword;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
inline int reg16(int rgnum)
|
|
{
|
|
// 0..3 r0-r3
|
|
// 4..7 r12-r15
|
|
return ( rgnum > 3 ) ? (rgnum + 8) : rgnum;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
inline void opbranch(const insn_t &insn, op_t &x, sval_t delta)
|
|
{
|
|
// cPC <- (cPCL+delta)
|
|
// PCL is current instruction address with 2 low bits set to 0
|
|
ea_t pcl = insn.ip & ~3ul;
|
|
x.type = o_near;
|
|
x.dtype = dt_code;
|
|
x.addr = pcl + delta;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
void arc_t::decode_operand(
|
|
insn_t &insn,
|
|
uint32 code,
|
|
int &op_pos,
|
|
uint32 opkind)
|
|
{
|
|
op_t &x = insn.ops[op_pos];
|
|
++op_pos;
|
|
if ( opkind == 0 )
|
|
{
|
|
x.type = o_void;
|
|
return;
|
|
}
|
|
int reg, p;
|
|
sval_t displ;
|
|
switch ( opkind & ~O_FLAGS )
|
|
{
|
|
case fA16:
|
|
opreg(insn, x, reg16(BITS(code, 2, 0)));
|
|
break;
|
|
case fB16:
|
|
opreg(insn, x, reg16(BITS(code, 10, 8)));
|
|
break;
|
|
case fC16:
|
|
opreg(insn, x, reg16(BITS(code, 7, 5)));
|
|
break;
|
|
|
|
case fA32: // 5..0 a register operand (6 bits, r0-r63)
|
|
opreg(insn, x, BITS(code, 5, 0));
|
|
break;
|
|
case fB32: // 14..12 & 26..24 b register operand (6 bits)
|
|
opreg(insn, x, (BITS(code, 14, 12)<<3) | BITS(code, 26, 24));
|
|
break;
|
|
case fC32: // 11..6 c register operand (6 bits)
|
|
opreg(insn, x, BITS(code, 11, 6));
|
|
break;
|
|
case fC32_w6: // 11..6 & 0 c/w6 register/immediate operand (6 bits)
|
|
if ( BITS(code, 0, 0) != 0 )
|
|
opimm(x, SBITS(code, 11, 6));
|
|
else
|
|
opreg(insn, x, BITS(code, 11, 6));
|
|
break;
|
|
case fH16: // 2..0 & 7..5 h register operand (6 bits)
|
|
reg = (BITS(code, 2, 0) << 3) | BITS(code, 7, 5);
|
|
opreg(insn, x, reg);
|
|
break;
|
|
case fH16v2: // 1..0 & 7..5 h register operand (5 bits)
|
|
reg = (BITS(code, 1, 0) << 3) | BITS(code, 7, 5);
|
|
opreg(insn, x, reg, LIMM5);
|
|
break;
|
|
case fH16v2_U5: // 1..0 & 7..5, 10&4..3 [h, u5] (u5=u3*4)
|
|
displ = ((BITS(code, 10, 10) << 2) | BITS(code, 4, 3)) * 4;
|
|
reg = (BITS(code, 1, 0) << 3) | BITS(code, 7, 5);
|
|
opdisp(insn, x, reg, displ);
|
|
break;
|
|
case fG16: // 4..3 & 10..8 g register operand (5 bits)
|
|
reg = (BITS(code, 4, 3) << 3) | BITS(code, 10, 8);
|
|
opreg(insn, x, reg, LIMM5);
|
|
break;
|
|
case fR16_2: // 9..8 R register operand (2 bits)
|
|
opreg(insn, x, BITS(code, 9, 8));
|
|
break;
|
|
case fR16_1: // 7 R register operand (1 bits)
|
|
opreg(insn, x, BITS(code, 7, 7));
|
|
break;
|
|
|
|
case S25L: // 15..6 & 26..18 & 0..3 s25 signed branch displacement for branch and link
|
|
case S21L: // 15..6 & 26..18 s21 signed branch displacement for branch and link
|
|
case S25: // 15..6 & 26..17 & 3..0 s25 signed branch displacement
|
|
case S21: // 15..6 & 26..17 s21 signed branch displacement
|
|
displ = (BITS(code, 15, 6) << 10) | BITS(code, 26, 17);
|
|
if ( opkind == S25 || opkind == S25L )
|
|
{
|
|
displ |= BITS(code, 3, 0) << 20;
|
|
if ( displ & (1ul<<23) )
|
|
displ -= (1ul<<24);
|
|
}
|
|
else
|
|
{
|
|
if ( displ & (1ul<<19) )
|
|
displ -= (1ul<<20);
|
|
}
|
|
if ( opkind == S25L || opkind == S21L )
|
|
{
|
|
// branch-and-link uses 32-bit aligned target
|
|
displ &= ~1ul;
|
|
}
|
|
opbranch(insn, x, displ * 2);
|
|
break;
|
|
|
|
case S9: // 15&23..17 s9 signed branch displacement (16-bit aligned)
|
|
displ = BITS(code, 23, 17);
|
|
if ( BITS(code, 15, 15) ) // sign bit
|
|
displ -= (1ul<<7);
|
|
opbranch(insn, x, displ * 2);
|
|
break;
|
|
|
|
case S7: // 5..0 s7 signed branch displacement (16-bit aligned)
|
|
displ = SBITS(code, 5, 0);
|
|
opbranch(insn, x, displ * 2);
|
|
break;
|
|
|
|
case S8: // 6..0 s8 signed branch displacement (16-bit aligned)
|
|
displ = SBITS(code, 6, 0);
|
|
opbranch(insn, x, displ * 2);
|
|
break;
|
|
|
|
case S10: // 8..0 s10 signed branch displacement (16-bit aligned)
|
|
displ = SBITS(code, 8, 0);
|
|
opbranch(insn, x, displ * 2);
|
|
break;
|
|
|
|
case S13: // 10..0 s13 signed branch displacement (32-bit aligned)
|
|
displ = SBITS(code, 10, 0);
|
|
opbranch(insn, x, displ * 4);
|
|
break;
|
|
|
|
case PCL_U10:
|
|
displ = BITS(code, 7, 0);
|
|
opdisp(insn, x, PCL, displ*4);
|
|
break;
|
|
|
|
case SP_U7: // 4..0 [SP, u7] stack + offset (u7 = u5*4)
|
|
displ = BITS(code, 4, 0);
|
|
opdisp(insn, x, SP, displ*4);
|
|
break;
|
|
|
|
case S3: // 10..8 s3 signed immediate
|
|
p = BITS(code, 10, 8);
|
|
opimm(x, p == 7 ? -1 : p);
|
|
break;
|
|
|
|
case U3: // 2..0 u2 unsigned immediate
|
|
opimm(x, BITS(code, 2, 0));
|
|
break;
|
|
|
|
case U7:
|
|
opimm(x, BITS(code, 6, 0));
|
|
break;
|
|
|
|
case U6:
|
|
opimm(x, BITS(code, 11, 6));
|
|
break;
|
|
|
|
case U6_SWI:
|
|
opimm(x, BITS(code, 10, 5));
|
|
break;
|
|
|
|
case U5:
|
|
case U7L:
|
|
displ = BITS(code, 4, 0);
|
|
if ( opkind == U7L )
|
|
displ *= 4;
|
|
opimm(x, displ);
|
|
break;
|
|
|
|
case U8:
|
|
opimm(x, BITS(code, 7, 0));
|
|
break;
|
|
|
|
case U6_16: // 6..4 & 2..0 u6 unsigned immediate
|
|
opimm(x, (BITS(code, 6, 4) << 3) | BITS(code, 2, 0));
|
|
break;
|
|
|
|
case U7_16: // 7..4 & 2..0 u7 unsigned immediate
|
|
opimm(x, (BITS(code, 7, 4) << 3) | BITS(code, 2, 0));
|
|
break;
|
|
|
|
case U10_16:
|
|
opimm(x, BITS(code, 9, 0));
|
|
break;
|
|
|
|
case fB_U5: // 10..8 & 4..0 [b, u5]
|
|
case fB_U6: // 10..8 & 4..0 [b, u6] (u6=u5*2)
|
|
case fB_U7: // 10..8 & 4..0 [b, u7] (u6=u5*4)
|
|
displ = BITS(code, 4, 0);
|
|
if ( opkind == fB_U6 )
|
|
displ *= 2;
|
|
else if ( opkind == fB_U7 )
|
|
displ *= 4;
|
|
reg = reg16(BITS(code, 10, 8));
|
|
opdisp(insn, x, reg, displ);
|
|
break;
|
|
|
|
case fB_S9: // 14..12&26..26, 15&23..16 [b, s9]
|
|
displ = BITS(code, 23, 16);
|
|
if ( BITS(code, 15, 15) ) // sign bit
|
|
displ -= (1ul<<8);
|
|
reg = (BITS(code, 14, 12)<<3) | BITS(code, 26, 24);
|
|
opdisp(insn, x, reg, displ);
|
|
break;
|
|
|
|
// handing of the "gen" format:
|
|
// P M
|
|
// REG_REG 00 N/A Destination and both sources are registers
|
|
// REG_U6IMM 01 N/A Source 2 is a 6-bit unsigned immediate
|
|
// REG_S12IMM 10 N/A Source 2 is a 12-bit signed immediate
|
|
// COND_REG 11 0 Conditional instruction. Destination (if any) is source 1. Source 2 is a register
|
|
// COND_REG_U6IMM 11 1 Conditional instruction. Destination (if any) is source 1. Source 2 is a 6-bit unsigned immediate
|
|
// P=23..22, M=5
|
|
// 0x04, [0x00 - 0x3F]
|
|
// 00100 bbb 00 iiiiii F BBB CCCCCC AAAAAA reg-reg op<.f> a,b,c
|
|
// 00100 bbb 01 iiiiii F BBB UUUUUU AAAAAA reg-u6imm op<.f> a,b,u6
|
|
// 00100 bbb 10 iiiiii F BBB ssssss SSSSSS reg-s12imm op<.f> b,b,s12
|
|
// 00100 bbb 11 iiiiii F BBB CCCCCC 0 QQQQQ cond reg-reg op<.cc><.f> b,b,c
|
|
// 00100 bbb 11 iiiiii F BBB UUUUUU 1 QQQQQ cond reg-u6 op<.cc><.f> b,b,u6
|
|
// 0x04, [0x30 - 0x37]
|
|
// 00100 bbb aa 110 ZZ X D BBB CCCCCC AAAAAA LD<zz><.x><.aa><.di> a,[b,c]
|
|
|
|
case GENA: // 5..0
|
|
p = BITS(code, 23, 22);
|
|
if ( p <= 1 )
|
|
reg = BITS(code, 5, 0);
|
|
else
|
|
reg = (BITS(code, 14, 12)<<3) | BITS(code, 26, 24);
|
|
opreg(insn, x, reg);
|
|
break;
|
|
|
|
case GENB: // 14..12 & 26..24
|
|
reg = (BITS(code, 14, 12)<<3) | BITS(code, 26, 24);
|
|
opreg(insn, x, reg);
|
|
break;
|
|
|
|
case GENC: // 11..6 reg/u6 or 0..5&11..6 s12
|
|
case GENC_PCREL: // 11..6 u6 or 0..5&11..6 s12 pc-relative displacement
|
|
p = BITS(code, 23, 22);
|
|
if ( p != 2 )
|
|
{
|
|
reg = BITS(code, 11, 6);
|
|
if ( p == 0 || (p == 3 && BITS(code, 5, 5) == 0) )
|
|
opreg(insn, x, reg);
|
|
else
|
|
opimm(x, reg);
|
|
}
|
|
else
|
|
{
|
|
// s12
|
|
reg = (BITS(code, 5, 0) << 6) | BITS(code, 11, 6);
|
|
reg = SIGNEXT(reg, 12);
|
|
opimm(x, reg);
|
|
}
|
|
if ( (opkind & ~O_IND) == GENC_PCREL && x.type == o_imm )
|
|
opbranch(insn, x, reg * 2);
|
|
break;
|
|
|
|
case fBC_IND:
|
|
{
|
|
int b = (BITS(code, 14, 12)<<3) | BITS(code, 26, 24);
|
|
int c = BITS(code, 11, 6);
|
|
int li = 0;
|
|
if ( b == LIMM || c == LIMM )
|
|
li = get_limm(insn);
|
|
doIndirectOperand(insn, b, c, x, 0, li, false);
|
|
}
|
|
break;
|
|
|
|
case fBC16_IND:
|
|
{
|
|
int b = BITS(code, 10, 8);
|
|
int c = BITS(code, 7, 5);
|
|
doIndirectOperand(insn, reg16(b), reg16(c), x, 0, 0, false);
|
|
}
|
|
break;
|
|
|
|
case O_ZERO:
|
|
opimm(x, 0);
|
|
break;
|
|
|
|
case R_SP: // implicit SP
|
|
opreg(insn, x, SP);
|
|
break;
|
|
|
|
case R_BLINK: // implicit BLINK
|
|
opreg(insn, x, BLINK);
|
|
break;
|
|
|
|
case R_R0: // implicit R0
|
|
opreg(insn, x, R0);
|
|
break;
|
|
|
|
case R_R1: // implicit R1
|
|
opreg(insn, x, R1);
|
|
break;
|
|
|
|
case R_GP: // implicit GP
|
|
opreg(insn, x, GP);
|
|
break;
|
|
|
|
case GP_S9: // 8..0 [GP, s9] GP + offset
|
|
case GP_S10: // 8..0 [GP, s10] GP + offset (s10 = s9*2)
|
|
case GP_S11: // 8..0 [GP, s11] GP + offset (s11 = s9*4)
|
|
case S11: // 8..0 s11 signed immediate (s11 = s9*4)
|
|
displ = SBITS(code, 8, 0);
|
|
if ( opkind == GP_S10 )
|
|
displ *= 2;
|
|
else if ( opkind != GP_S9 )
|
|
displ *= 4;
|
|
if ( opkind == S11 )
|
|
opimm(x, displ);
|
|
else
|
|
opdisp(insn, x, GP, displ);
|
|
break;
|
|
|
|
case GP_S11_16:
|
|
displ = (SBITS(code, 10, 5) << 5) | (BITS(code, 2, 0) << 2);
|
|
opdisp(insn, x, GP, displ);
|
|
break;
|
|
|
|
case EL: // 4..1 & 10..8 enter / leave register set
|
|
x.type = o_reglist;
|
|
x.reglist = BITS(code, 4, 1) | (BITS(code, 10, 8) << 4);
|
|
x.dtype = dt_dword;
|
|
break;
|
|
|
|
default:
|
|
msg("%a: cannot decode operand %d (opkind=%u)\n", insn.ea, x.n, opkind);
|
|
return;
|
|
}
|
|
if ( opkind & O_IND )
|
|
{
|
|
// indirect access
|
|
if ( x.type == o_reg )
|
|
{
|
|
x.type = o_displ;
|
|
x.addr = 0;
|
|
}
|
|
else if ( x.type == o_imm && insn.itype != ARC_lr && insn.itype != ARC_sr )
|
|
{
|
|
if ( insn.itype == ARC_j || insn.itype == ARC_jl )
|
|
x.type = o_near;
|
|
else
|
|
x.type = o_mem;
|
|
x.addr = x.value;
|
|
x.immdisp = 0;
|
|
}
|
|
}
|
|
if ( opkind & O_WIDE )
|
|
{
|
|
// register pair for 64-bit values
|
|
op_t &y = insn.ops[op_pos];
|
|
++op_pos;
|
|
if ( x.type == o_reg && (x.reg & 1) == 0 && x.reg <= R58 )
|
|
{
|
|
y.type = o_reg;
|
|
y.reg = x.reg + 1;
|
|
y.regpair = true;
|
|
}
|
|
else
|
|
{
|
|
y.type = o_void;
|
|
}
|
|
}
|
|
if ( opkind & O_IDX )
|
|
{
|
|
int base;
|
|
switch ( insn.itype )
|
|
{
|
|
case ARC_bi:
|
|
case ARC_bih:
|
|
base = NEXT_PC;
|
|
break;
|
|
|
|
case ARC_ldi:
|
|
base = LDI_BASE;
|
|
break;
|
|
|
|
case ARC_jli:
|
|
base = JLI_BASE;
|
|
break;
|
|
|
|
case ARC_ei:
|
|
base = EI_BASE;
|
|
break;
|
|
|
|
default:
|
|
msg("%a: unknown implicit base for indexed access\n", insn.ea);
|
|
return;
|
|
}
|
|
if ( x.type == o_reg )
|
|
{
|
|
x.type = o_phrase;
|
|
x.secreg = x.reg;
|
|
x.reg = base;
|
|
}
|
|
else if ( x.type == o_imm )
|
|
{
|
|
x.type = o_displ;
|
|
x.addr = x.value;
|
|
x.reg = base;
|
|
}
|
|
else
|
|
{
|
|
msg("%a: unknown operand type for indexed access\n", insn.ea);
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// decode non-operand bits of the instruction
|
|
static void decode_aux(insn_t &insn, uint32 code, uint32 aux)
|
|
{
|
|
aux &= ~AUX_V2 & ~AUX_F;
|
|
if ( aux & AUX_CND )
|
|
{
|
|
// condition in low bits of 'aux'
|
|
insn.auxpref = (insn.auxpref & ~aux_cmask) | (aux & aux_cmask);
|
|
aux &= ~(AUX_CND | aux_cmask);
|
|
}
|
|
if ( aux & Q_4_0 )
|
|
{
|
|
// condition in low bits of instruction
|
|
insn.auxpref = (insn.auxpref & ~aux_cmask) | (code & aux_cmask);
|
|
aux &= ~Q_4_0;
|
|
}
|
|
if ( aux & Q_5_0 )
|
|
{
|
|
// condition in low bits of instruction if the next higer bit is 1
|
|
if ( BITS(code, 5, 5) == 1 )
|
|
insn.auxpref = (insn.auxpref & ~aux_cmask) | (code & aux_cmask);
|
|
aux &= ~Q_5_0;
|
|
}
|
|
if ( aux & AUX_GEN3 )
|
|
{
|
|
// bit 15 = F/Di, 4..0 = Q if 23..22=0x3
|
|
if ( BITS(code, 15, 15) )
|
|
{
|
|
if ( (aux & AUX_GEN3) == AUX_GEN )
|
|
insn.auxpref |= aux_f;
|
|
else if ( (aux & AUX_GEN3) == AUX_GEN3 )
|
|
insn.auxpref |= aux_di;
|
|
}
|
|
if ( BITS(code, 23, 22) == 3 )
|
|
insn.auxpref = (insn.auxpref & ~aux_cmask) | (code & aux_cmask);
|
|
aux &= ~AUX_GEN3;
|
|
}
|
|
if ( aux & N_5 )
|
|
{
|
|
insn.auxpref = (insn.auxpref & ~aux_d) | (code & aux_d);
|
|
aux &= ~N_5;
|
|
}
|
|
if ( aux & AUX_W )
|
|
{
|
|
insn.auxpref = (insn.auxpref & ~aux_zmask) | aux_w;
|
|
aux &= ~AUX_W;
|
|
}
|
|
if ( aux & AUX_B )
|
|
{
|
|
insn.auxpref = (insn.auxpref & ~aux_zmask) | aux_b;
|
|
aux &= ~AUX_B;
|
|
}
|
|
if ( aux & AUX_X )
|
|
{
|
|
insn.auxpref |= aux_x;
|
|
aux &= ~AUX_X;
|
|
}
|
|
if ( aux & AUX_D )
|
|
{
|
|
insn.auxpref = (insn.auxpref & ~aux_nmask) | aux_d;
|
|
aux &= ~AUX_D;
|
|
}
|
|
if ( aux & DAAZZX_11_6 ) // 11..6 Di, aa, ZZ, X flags (load)
|
|
{
|
|
insn.auxpref = (insn.auxpref & ~0x3F) | (BITS(code, 11, 6));
|
|
aux &= ~DAAZZX_11_6;
|
|
}
|
|
if ( aux & DAAZZ_5_1 ) // 5..1 Di, aa, ZZ (store)
|
|
{
|
|
insn.auxpref = (insn.auxpref & ~0x3F) | (BITS(code, 5, 1) << 1);
|
|
aux &= ~DAAZZ_5_1;
|
|
}
|
|
if ( aux & AAZZXD_23_15 ) // 23..22,18..15 aa, ZZ, X, D flags (load reg+reg)
|
|
{
|
|
// load instructions flags: Di.AA.ZZ.X
|
|
insn.auxpref &= ~0x3F;
|
|
insn.auxpref |= BITS(code, 15, 15) << 5; // Di
|
|
insn.auxpref |= BITS(code, 23, 22) << 3; // aa
|
|
insn.auxpref |= BITS(code, 18, 17) << 1; // ZZ
|
|
insn.auxpref |= BITS(code, 16, 16) << 0; // X
|
|
aux &= ~AAZZXD_23_15;
|
|
}
|
|
if ( aux & AUX_AS )
|
|
{
|
|
insn.auxpref |= aux_as;
|
|
aux &= ~AUX_AS;
|
|
}
|
|
if ( aux & Y_3 )
|
|
{
|
|
// static prediction bit Y is bit 3
|
|
// in default case (no hint specified) it's 0 for BRcc and 1 for BBITn
|
|
if ( (BITS(code, 3, 3) == 0) != (insn.itype == ARC_br) )
|
|
{
|
|
insn.auxpref |= aux_bhint;
|
|
}
|
|
aux &= ~Y_3;
|
|
}
|
|
if ( aux != 0 )
|
|
msg("%a: unhandled aux bits: %08X\n", insn.ea, aux);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
int arc_t::analyze_compact(insn_t &insn, uint32 code, int idx, const arcompact_opcode_t *table)
|
|
{
|
|
const arcompact_opcode_t *line = &table[idx];
|
|
while ( (line->mnem & 0x80000000) != 0 )
|
|
{
|
|
// it's a pointer into subtable
|
|
// indexed by some of the instruction's bits
|
|
int high1 = (line->mnem >> 24) & 0x1F;
|
|
int low1 = (line->mnem >> 16) & 0x1F;
|
|
int high2 = (line->mnem >> 8) & 0x1F;
|
|
int low2 = (line->mnem >> 0) & 0x1F;
|
|
idx = BITS(code, high2, low2);
|
|
if ( high1 != 0 && low1 != 0 )
|
|
idx |= BITS(code, high1, low1) << (high2-low2+1);
|
|
line = &(line->subtable[idx]);
|
|
}
|
|
if ( line->aux & AUX_F && BITS(code, 15, 15) )
|
|
line += 0x40;
|
|
if ( (line->mnem == 0 && line->aux == 0) || !is_arcv2() && line->aux & AUX_V2 )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
insn.itype = line->mnem;
|
|
decode_aux(insn, code, line->aux);
|
|
|
|
if ( is_arcv2() && insn.itype == ARC_flag && BITS(code, 15, 15) )
|
|
insn.itype = ARC_kflag;
|
|
|
|
int j = 0;
|
|
for ( int i = 0; i < 3; i++ )
|
|
decode_operand(insn, code, j, line->ops[i]);
|
|
for ( ; j < PROC_MAXOP; ++j )
|
|
insn.ops[j].type = o_void;
|
|
|
|
if ( insn.itype == ARC_swi
|
|
&& insn.Op1.type == o_imm
|
|
&& insn.Op1.value == 0x3f )
|
|
{
|
|
insn.itype = ARC_brk;
|
|
insn.Op1.type = o_void;
|
|
}
|
|
|
|
return insn.size;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// analyze ARCompact instruction
|
|
int arc_t::ana_compact(insn_t &insn)
|
|
{
|
|
// must be 16-bit aligned
|
|
if ( insn.ea & 1 )
|
|
return 0;
|
|
uint32 code = insn.get_next_word();
|
|
got_limm = false;
|
|
// first 5 bits is the major opcode
|
|
int i = (code >> 11) & 0x1F;
|
|
if ( i < 0x8 )
|
|
{
|
|
// this is a 32-bit instruction
|
|
// get the full word
|
|
code = (code << 16) | insn.get_next_word();
|
|
}
|
|
else
|
|
{
|
|
insn.auxpref |= aux_s;
|
|
}
|
|
return analyze_compact(insn, code, i,
|
|
is_arcv2() ? arcv2_major : arcompact_major);
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
static void simplify(insn_t &insn)
|
|
{
|
|
for ( int i = 0; i < PROC_MAXOP; ++i )
|
|
{
|
|
if ( insn.ops[i].type == o_mem )
|
|
insn.ops[i].immdisp = 0;
|
|
}
|
|
|
|
switch ( insn.itype )
|
|
{
|
|
case ARC_st:
|
|
case ARC_ld:
|
|
// ld.as r1, [r2, delta] -> ld r1, [r2, delta*size]
|
|
if ( insn.Op2.type == o_displ
|
|
&& insn.Op2.membase == 0
|
|
&& (insn.auxpref & aux_amask) == aux_as )
|
|
{
|
|
insn.Op2.addr *= get_scale_factor(insn);
|
|
insn.auxpref &= ~aux_amask;
|
|
}
|
|
else if ( insn.Op2.type == o_mem
|
|
&& (insn.auxpref & aux_amask) == aux_as )
|
|
{
|
|
insn.Op2.immdisp = 0;
|
|
insn.auxpref &= ~aux_amask;
|
|
}
|
|
break;
|
|
case ARC_add1:
|
|
case ARC_add2:
|
|
case ARC_add3:
|
|
case ARC_sub1:
|
|
case ARC_sub2:
|
|
case ARC_sub3:
|
|
// addN a, b, c -> add a, b, c<<N
|
|
if ( insn.Op3.type == o_imm )
|
|
{
|
|
switch ( insn.itype )
|
|
{
|
|
case ARC_add1:
|
|
case ARC_sub1:
|
|
insn.Op3.value *= 2;
|
|
break;
|
|
case ARC_add2:
|
|
case ARC_sub2:
|
|
insn.Op3.value *= 4;
|
|
break;
|
|
case ARC_add3:
|
|
case ARC_sub3:
|
|
insn.Op3.value *= 8;
|
|
break;
|
|
}
|
|
switch ( insn.itype )
|
|
{
|
|
case ARC_add1:
|
|
case ARC_add2:
|
|
case ARC_add3:
|
|
insn.itype = ARC_add;
|
|
break;
|
|
case ARC_sub3:
|
|
case ARC_sub2:
|
|
case ARC_sub1:
|
|
insn.itype = ARC_sub;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
case ARC_sub:
|
|
// sub.f 0, a, b -> cmp a, b
|
|
if ( insn.Op1.is_imm(0) && (insn.auxpref & aux_f) != 0 )
|
|
{
|
|
insn.auxpref &= ~aux_f;
|
|
insn.itype = ARC_cmp;
|
|
insn.Op1 = insn.Op2;
|
|
insn.Op2 = insn.Op3;
|
|
insn.Op3.type = o_void;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// fix operand size for byte or word loads/stores
|
|
inline void fix_ldst(insn_t &insn)
|
|
{
|
|
if ( insn.itype == ARC_ld || insn.itype == ARC_st )
|
|
{
|
|
switch ( insn.auxpref & aux_zmask )
|
|
{
|
|
case aux_b:
|
|
insn.Op2.dtype = dt_byte;
|
|
break;
|
|
case aux_w:
|
|
insn.Op2.dtype = dt_word;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// convert pc-relative loads
|
|
// ld r1, [pc,#delta] -> ld r1, [memaddr]
|
|
static void inline_const(insn_t &insn)
|
|
{
|
|
if ( insn.itype == ARC_ld
|
|
&& insn.Op2.type == o_displ
|
|
&& insn.Op2.reg == PCL
|
|
&& (insn.auxpref & (aux_a|aux_zmask)) == 0 ) // no .a and 32-bit access
|
|
{
|
|
ea_t val_ea = (insn.ea & ~3ul) + insn.Op2.addr;
|
|
if ( is_mapped(val_ea) )
|
|
{
|
|
insn.Op2.type = o_mem;
|
|
insn.Op2.addr = val_ea;
|
|
insn.Op2.immdisp = 0;
|
|
insn.auxpref |= aux_pcload;
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// analyze an instruction
|
|
int arc_t::ana(insn_t *_insn)
|
|
{
|
|
insn_t &insn = *_insn;
|
|
int sz = is_a4() ? ana_old(insn) : ana_compact(insn);
|
|
if ( sz != 0 )
|
|
{
|
|
fix_ldst(insn);
|
|
if ( (idpflags & ARC_SIMPLIFY) != 0 )
|
|
simplify(insn);
|
|
if ( (idpflags & ARC_INLINECONST) != 0 )
|
|
inline_const(insn);
|
|
}
|
|
return insn.size;
|
|
}
|