1335 lines
36 KiB
C++
1335 lines
36 KiB
C++
/*
|
|
* Interactive disassembler (IDA).
|
|
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
|
* ALL RIGHTS RESERVED.
|
|
* E-mail: ig@datarescue.com
|
|
*
|
|
*/
|
|
|
|
#include "hppa.hpp"
|
|
|
|
//--------------------------------------------------------------------------
|
|
static void simplify(insn_t &insn, uint32 code)
|
|
{
|
|
switch ( insn.itype )
|
|
{
|
|
// B,L,n target, %r0 => B,n target
|
|
// B,L,n target, %r2 => CALL,n target
|
|
case HPPA_b:
|
|
{
|
|
int sub = (code>>13) & 7;
|
|
if ( sub == 1 || sub == 4 )
|
|
break; // ,gate or ,push
|
|
switch ( insn.Op2.reg )
|
|
{
|
|
case R0:
|
|
insn.Op2.type = o_void;
|
|
break;
|
|
case R2:
|
|
insn.itype = HPPA_call;
|
|
insn.Op2.type = o_void;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
// BVE,L,n (b), %r2 => CALL,n (b)
|
|
// BVE,n (%r2) => RET,n
|
|
case HPPA_bve:
|
|
if ( code & BIT31 )
|
|
break; // ,push or ,pop
|
|
if ( insn.Op2.type == o_reg )
|
|
{
|
|
insn.itype = HPPA_call;
|
|
insn.Op1.type = o_void;
|
|
break;
|
|
}
|
|
if ( insn.Op1.phrase == R2 )
|
|
{
|
|
insn.itype = HPPA_ret;
|
|
insn.Op1.type = o_void;
|
|
}
|
|
break;
|
|
|
|
// DEPD,Z,cond r,63-sa,64-sa,t => SHLD,cond r,sa,t
|
|
// DEPW,Z,cond r,31-sa,32-sa,t => SHLW,cond r,sa,t
|
|
case HPPA_depd:
|
|
case HPPA_depw:
|
|
if ( code & BIT21 )
|
|
break; // no Z flag
|
|
if ( insn.Op2.type == o_imm
|
|
&& insn.Op3.type == o_imm
|
|
&& (insn.Op2.value+1) == insn.Op3.value )
|
|
{
|
|
insn.itype += (HPPA_shld-HPPA_depd);
|
|
insn.Op2.value = (insn.itype == HPPA_shld ? 63 : 31) - insn.Op2.value;
|
|
insn.Op3 = insn.Op4;
|
|
insn.Op4.type = o_void;
|
|
}
|
|
break;
|
|
|
|
// DEPWI,Z,cond -1,31,x,t => LDI,cond (1<<x)-1,t
|
|
case HPPA_depwi:
|
|
if ( code & BIT21 )
|
|
break; // no Z flag
|
|
if ( insn.Op2.type == o_imm && insn.Op2.value == 31
|
|
&& insn.Op3.type == o_imm && insn.Op3.value <= 16 )
|
|
{
|
|
insn.itype = HPPA_ldi;
|
|
insn.Op1.value = (uval_t(1) << insn.Op3.value) - 1;
|
|
insn.Op2 = insn.Op4;
|
|
insn.Op3.type = o_void;
|
|
insn.Op4.type = o_void;
|
|
}
|
|
break;
|
|
// EXTRD,S,cond r,63-sa,64-sa,t => SHRD,S,cond r,sa,t
|
|
// EXTRD,U,cond r,63-sa,64-sa,t => SHRD,U,cond r,sa,t
|
|
// EXTRW,S,cond r,31-sa,32-sa,t => SHRW,S,cond r,sa,t
|
|
// EXTRW,U,cond r,31-sa,32-sa,t => SHRW,U,cond r,sa,t
|
|
case HPPA_extrd:
|
|
case HPPA_extrw:
|
|
if ( insn.Op2.type == o_imm
|
|
&& insn.Op3.type == o_imm
|
|
&& (insn.Op2.value+1) == insn.Op3.value )
|
|
{
|
|
insn.itype += HPPA_shrd - HPPA_extrd;
|
|
insn.Op2.value = (insn.itype == HPPA_shrd ? 63 : 31) - insn.Op2.value;
|
|
insn.Op3 = insn.Op4;
|
|
insn.Op4.type = o_void;
|
|
}
|
|
break;
|
|
|
|
// LDO i(%r0), t => LDI i, t
|
|
// LDO 0(r), t => COPY r, t
|
|
case HPPA_ldo:
|
|
if ( insn.Op1.reg == R0 )
|
|
{
|
|
insn.itype = HPPA_ldi;
|
|
insn.Op1.type = o_imm;
|
|
insn.Op1.value = insn.Op1.addr;
|
|
break;
|
|
}
|
|
if ( insn.Op1.addr == 0 )
|
|
{
|
|
insn.itype = HPPA_copy;
|
|
insn.Op1.type = o_reg;
|
|
}
|
|
break;
|
|
|
|
// MTCTL r, %sar => MTSAR r
|
|
case HPPA_mtctl:
|
|
if ( insn.Op2.reg == CR11 )
|
|
{
|
|
insn.itype = HPPA_mtsar;
|
|
insn.Op2.type = o_void;
|
|
}
|
|
break;
|
|
|
|
// OR %r0, %r0, %r0 => NOP
|
|
// OR %r, %r0, %t => COPY r, t
|
|
// OR %r0, %r, %t => COPY r, t
|
|
case HPPA_or:
|
|
if ( ((code>>13) & 7) )
|
|
break; // condition codes not zero
|
|
if ( insn.Op1.reg == R0 )
|
|
{
|
|
if ( insn.Op2.reg == R0 && insn.Op3.reg == R0 )
|
|
{
|
|
insn.itype = HPPA_nop;
|
|
insn.Op1.type = o_void;
|
|
insn.Op2.type = o_void;
|
|
insn.Op3.type = o_void;
|
|
break;
|
|
}
|
|
insn.itype = HPPA_copy;
|
|
insn.Op1 = insn.Op2;
|
|
insn.Op2 = insn.Op3;
|
|
insn.Op3.type = o_void;
|
|
break;
|
|
}
|
|
if ( insn.Op2.reg == R0 )
|
|
{
|
|
insn.itype = HPPA_copy;
|
|
insn.Op2 = insn.Op3;
|
|
insn.Op3.type = o_void;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
struct table1_t
|
|
{
|
|
ushort itype;
|
|
char dtype;
|
|
};
|
|
|
|
static const table1_t C1[] =
|
|
{
|
|
{ 0, dt_qword }, // 00
|
|
{ 0, dt_qword }, // 01
|
|
{ 0, dt_qword }, // 02
|
|
{ 0, dt_qword }, // 03
|
|
{ 0, dt_qword }, // 04
|
|
{ HPPA_diag, dt_qword }, // 05
|
|
{ HPPA_fmpyadd, dt_qword }, // 06
|
|
{ HPPA_null, dt_qword }, // 07
|
|
{ HPPA_ldil, dt_qword }, // 08
|
|
{ 0, dt_qword }, // 09
|
|
{ HPPA_addil, dt_qword }, // 0A
|
|
{ 0, dt_qword }, // 0B
|
|
{ HPPA_copr, dt_qword }, // 0C
|
|
{ HPPA_ldo, dt_dword }, // 0D
|
|
{ 0, dt_qword }, // 0E
|
|
{ HPPA_null, dt_qword }, // 0F
|
|
{ HPPA_ldb, dt_byte }, // 10
|
|
{ HPPA_ldh, dt_word }, // 11
|
|
{ HPPA_ldw, dt_dword }, // 12
|
|
{ HPPA_ldw, dt_dword }, // 13
|
|
{ 0, dt_qword }, // 14
|
|
{ HPPA_null, dt_dword }, // 15
|
|
{ HPPA_fldw, dt_dword }, // 16
|
|
{ 0, dt_dword }, // 17
|
|
{ HPPA_stb, dt_byte }, // 18
|
|
{ HPPA_sth, dt_word }, // 19
|
|
{ HPPA_stw, dt_dword }, // 1A
|
|
{ HPPA_stw, dt_dword }, // 1B
|
|
{ 0, dt_qword }, // 1C
|
|
{ HPPA_null, dt_dword }, // 1D
|
|
{ HPPA_fstw, dt_dword }, // 1E
|
|
{ 0, dt_dword }, // 1F
|
|
{ HPPA_cmpb, dt_byte }, // 20
|
|
{ HPPA_cmpib, dt_byte }, // 21
|
|
{ HPPA_cmpb, dt_byte }, // 22
|
|
{ HPPA_cmpib, dt_dword }, // 23
|
|
{ HPPA_cmpiclr, dt_qword }, // 24
|
|
{ HPPA_subi, dt_dword }, // 25
|
|
{ HPPA_fmpysub, dt_dword }, // 26
|
|
{ HPPA_cmpb, dt_byte }, // 27
|
|
{ HPPA_addb, dt_byte }, // 28
|
|
{ HPPA_addib, dt_byte }, // 29
|
|
{ HPPA_addb, dt_byte }, // 2A
|
|
{ HPPA_addib, dt_byte }, // 2B
|
|
{ HPPA_addi, dt_dword }, // 2C
|
|
{ HPPA_addi, dt_dword }, // 2D
|
|
{ 0, dt_dword }, // 2E
|
|
{ HPPA_cmpb, dt_byte }, // 2F
|
|
{ HPPA_bb, dt_dword }, // 30
|
|
{ HPPA_bb, dt_dword }, // 31
|
|
{ HPPA_movb, dt_byte }, // 32
|
|
{ HPPA_movib, dt_byte }, // 33
|
|
{ 0, dt_dword }, // 34
|
|
{ 0, dt_dword }, // 35
|
|
{ HPPA_extrd, dt_qword }, // 36
|
|
{ HPPA_null, dt_dword }, // 37
|
|
{ HPPA_be, dt_dword }, // 38
|
|
{ HPPA_be, dt_dword }, // 39
|
|
{ 0, dt_dword }, // 3A
|
|
{ HPPA_cmpib, dt_byte }, // 3B
|
|
{ 0, dt_dword }, // 3C
|
|
{ 0, dt_dword }, // 3D
|
|
{ 0, dt_dword }, // 3E
|
|
{ HPPA_null, dt_dword }, // 3F
|
|
};
|
|
|
|
struct ldst_t
|
|
{
|
|
ushort itype;
|
|
char dtype;
|
|
};
|
|
|
|
static const ldst_t C6[] =
|
|
{
|
|
{ HPPA_ldb, dt_byte }, // 0
|
|
{ HPPA_ldh, dt_word }, // 1
|
|
{ HPPA_ldw, dt_dword }, // 2
|
|
{ HPPA_ldd, dt_qword }, // 3
|
|
{ HPPA_ldda, dt_qword }, // 4
|
|
{ HPPA_ldcd, dt_qword }, // 5
|
|
{ HPPA_ldwa, dt_dword }, // 6
|
|
{ HPPA_ldcw, dt_dword }, // 7
|
|
{ HPPA_stb, dt_byte }, // 8
|
|
{ HPPA_sth, dt_word }, // 9
|
|
{ HPPA_stw, dt_dword }, // A
|
|
{ HPPA_std, dt_qword }, // B
|
|
{ HPPA_stby, dt_byte }, // C
|
|
{ HPPA_stdby, dt_qword }, // D
|
|
{ HPPA_stwa, dt_dword }, // E
|
|
{ HPPA_stda, dt_qword }, // F
|
|
};
|
|
|
|
//--------------------------------------------------------------------------
|
|
static void opr(op_t &x, uint32 rgnum)
|
|
{
|
|
x.reg = (uint16)rgnum;
|
|
/* if ( rgnum == 0 )
|
|
{
|
|
x.type = o_imm;
|
|
x.value = 0;
|
|
x.dtype = dt_dword;
|
|
}
|
|
else*/
|
|
{
|
|
x.type = o_reg;
|
|
x.dtype = dt_qword;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
inline void opi(op_t &x, uval_t v)
|
|
{
|
|
x.type = o_imm;
|
|
x.value = v;
|
|
x.dtype = dt_dword;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
inline void opb(op_t &x, int r)
|
|
{
|
|
x.type = o_based;
|
|
x.phrase = (uint16)r;
|
|
x.dtype = dt_dword;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
inline void opbs(insn_t &insn, op_t &x, int sr, int r)
|
|
{
|
|
opb(x, r);
|
|
x.sid = uchar(SR0+sr);
|
|
if ( sr != 0 )
|
|
insn.auxpref |= aux_space;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
inline void opx(op_t &x, int b, int xx, char dtype)
|
|
{
|
|
x.type = o_phrase;
|
|
x.phrase = uint16(b);
|
|
x.secreg = uchar(xx);
|
|
x.dtype = dtype;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
inline void opxs(insn_t &insn, op_t &x, int sr, int b, int xx, char dtype)
|
|
{
|
|
opx(x, b, xx, dtype);
|
|
x.sid = uchar(SR0+sr);
|
|
if ( sr != 0 )
|
|
insn.auxpref |= aux_space;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
inline void opd(op_t &x, int b, uval_t value, char dtype)
|
|
{
|
|
x.type = o_displ;
|
|
x.phrase = uint16(b);
|
|
x.addr = value;
|
|
x.dtype = dtype;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
inline void opds(insn_t &insn, op_t &x, int sr, int b, uval_t value, char dtype)
|
|
{
|
|
opd(x, b, value, dtype);
|
|
x.sid = uchar(SR0+sr);
|
|
if ( sr != 0 )
|
|
insn.auxpref |= aux_space;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
struct table_t
|
|
{
|
|
char code;
|
|
ushort itype; //lint !e958 padding is required to align members
|
|
};
|
|
|
|
static const table_t C5[] =
|
|
{
|
|
{ 0x18, HPPA_add },
|
|
{ 0x28, HPPA_add },
|
|
{ 0x38, HPPA_add },
|
|
{ 0x1C, HPPA_add },
|
|
{ 0x3C, HPPA_add },
|
|
{ 0x19, HPPA_shladd },
|
|
{ 0x29, HPPA_shladd },
|
|
{ 0x39, HPPA_shladd },
|
|
{ 0x1A, HPPA_shladd },
|
|
{ 0x2A, HPPA_shladd },
|
|
{ 0x3A, HPPA_shladd },
|
|
{ 0x1B, HPPA_shladd },
|
|
{ 0x2B, HPPA_shladd },
|
|
{ 0x3B, HPPA_shladd },
|
|
{ 0x10, HPPA_sub },
|
|
{ 0x30, HPPA_sub },
|
|
{ 0x13, HPPA_sub },
|
|
{ 0x33, HPPA_sub },
|
|
{ 0x14, HPPA_sub },
|
|
{ 0x34, HPPA_sub },
|
|
{ 0x11, HPPA_ds },
|
|
{ 0x00, HPPA_andcm },
|
|
{ 0x08, HPPA_and },
|
|
{ 0x09, HPPA_or },
|
|
{ 0x0A, HPPA_xor },
|
|
{ 0x0E, HPPA_uxor },
|
|
{ 0x22, HPPA_cmpclr },
|
|
{ 0x26, HPPA_uaddcm },
|
|
{ 0x27, HPPA_uaddcm },
|
|
{ 0x2E, HPPA_dcor },
|
|
{ 0x2F, HPPA_dcor },
|
|
{ 0x0F, HPPA_hadd },
|
|
{ 0x0D, HPPA_hadd },
|
|
{ 0x0C, HPPA_hadd },
|
|
{ 0x07, HPPA_hsub },
|
|
{ 0x05, HPPA_hsub },
|
|
{ 0x04, HPPA_hsub },
|
|
{ 0x0B, HPPA_havg },
|
|
{ 0x1D, HPPA_hshladd },
|
|
{ 0x1E, HPPA_hshladd },
|
|
{ 0x1F, HPPA_hshladd },
|
|
{ 0x15, HPPA_hshladd },
|
|
{ 0x16, HPPA_hshladd },
|
|
{ 0x17, HPPA_hshladd },
|
|
{ 0, HPPA_null },
|
|
};
|
|
|
|
static ushort find_itype(const table_t *table, int code)
|
|
{
|
|
while ( table->itype )
|
|
{
|
|
if ( table->code == code )
|
|
return table->itype;
|
|
table++;
|
|
}
|
|
return HPPA_null;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
inline sval_t ls5(int i5) { return (( i5>>1)&15) | (( i5 & 1) ? ~sval_t(15) : 0); }
|
|
inline sval_t ls11(int i11) { return ((i11>>1)&0x3FF) | ((i11 & 1) ? ~sval_t(0x1FF) : 0); }
|
|
inline sval_t s12(int imm12) { return (imm12 & 0x0800) ? (imm12 | ~sval_t(0x0FFF)) : imm12; }
|
|
inline sval_t s16(int imm16) { return (imm16 & 0x8000) ? (imm16 | ~sval_t(0xFFFF)) : imm16; }
|
|
inline sval_t s17(uint32 i17) { return (i17 & 0x10000) ? (i17 | ~sval_t(0x1FFFF)) : i17; }
|
|
inline sval_t s22(uint32 i22) { return (i22 & 0x200000) ? (i22 | ~sval_t(0x3FFFFF)) : i22; }
|
|
inline int mfr(int r, bool d) { return (d ? F0 : F16L) + r; }
|
|
inline int as3(int s)
|
|
{
|
|
return ((s>>1) & 3) | ((s&1) << 2);
|
|
}
|
|
inline int fr(int r, int y)
|
|
{
|
|
return F0 + r + ((y&1)<<5);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
static void handle_float_0C(insn_t &insn, uint32 code)
|
|
{
|
|
int uid = (code>> 6) & 7;
|
|
if ( uid == 2 ) // performance coprocessor
|
|
{
|
|
int sub = (code>>9) & 0x1F;
|
|
switch ( sub )
|
|
{
|
|
case 1:
|
|
insn.itype = HPPA_pmdis;
|
|
break;
|
|
case 3:
|
|
insn.itype = (code & BIT26) ? HPPA_null : HPPA_pmenb;
|
|
break;
|
|
default:
|
|
insn.itype = HPPA_null;
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
if ( uid != 0 )
|
|
return; // other coprocessors
|
|
|
|
// floating-point coprocessor
|
|
int cls = (code>>9) & 3;
|
|
switch ( cls )
|
|
{
|
|
case 0:
|
|
{
|
|
static const ushort itypes[] =
|
|
{
|
|
HPPA_fid, HPPA_null, HPPA_fcpy, HPPA_fabs,
|
|
HPPA_fsqrt, HPPA_frnd, HPPA_fneg, HPPA_fnegabs
|
|
};
|
|
insn.itype = itypes[(code>>13)&7];
|
|
if ( insn.itype != HPPA_fid )
|
|
{
|
|
opr(insn.Op1, F0 + r06(code));
|
|
opr(insn.Op2, F0 + r27(code));
|
|
}
|
|
}
|
|
break;
|
|
case 1:
|
|
insn.itype = HPPA_fcnv;
|
|
opr(insn.Op1, F0 + r06(code));
|
|
opr(insn.Op2, F0 + r27(code));
|
|
break;
|
|
case 2:
|
|
if ( code & BIT26 )
|
|
{
|
|
insn.itype = HPPA_ftest;
|
|
int y = (code>>13) & 7;
|
|
if ( y != 1 )
|
|
opr(insn.Op1, CA0+(y^1)-1);
|
|
}
|
|
else
|
|
{
|
|
insn.itype = HPPA_fcmp;
|
|
opr(insn.Op1, F0 + r06(code));
|
|
opr(insn.Op2, F0 + r11(code));
|
|
int y = (code>>13) & 7;
|
|
if ( y )
|
|
opr(insn.Op3, CA0+y-1);
|
|
}
|
|
break;
|
|
case 3:
|
|
{
|
|
static const ushort itypes[] =
|
|
{
|
|
HPPA_fadd, HPPA_fsub, HPPA_fmpy, HPPA_fdiv,
|
|
HPPA_frem, HPPA_null, HPPA_null, HPPA_null
|
|
};
|
|
int sub = (code>>13) & 7;
|
|
insn.itype = (code & BIT26) ? HPPA_null : itypes[sub];
|
|
opr(insn.Op1, F0 + r06(code));
|
|
opr(insn.Op2, F0 + r11(code));
|
|
opr(insn.Op3, F0 + r27(code));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
static void handle_float_0E(insn_t &insn, uint32 code)
|
|
{
|
|
int cls = (code>>9) & 3;
|
|
switch ( cls )
|
|
{
|
|
case 0:
|
|
{
|
|
static const ushort itypes[] =
|
|
{
|
|
HPPA_null, HPPA_null, HPPA_fcpy, HPPA_fabs,
|
|
HPPA_fsqrt, HPPA_frnd, HPPA_fneg, HPPA_fnegabs
|
|
};
|
|
insn.itype = itypes[(code>>13)&7];
|
|
opr(insn.Op1, fr(r06(code), (code>>7)&1));
|
|
opr(insn.Op2, fr(r27(code), (code>>6)&1));
|
|
}
|
|
break;
|
|
case 1:
|
|
insn.itype = HPPA_fcnv;
|
|
opr(insn.Op1, fr(r06(code), (code>>7)&1));
|
|
opr(insn.Op2, fr(r27(code), (code>>6)&1));
|
|
break;
|
|
case 2:
|
|
{
|
|
insn.itype = HPPA_fcmp;
|
|
opr(insn.Op1, fr(r06(code), (code>>7)&1));
|
|
opr(insn.Op2, fr(r11(code), (code>>12)&1));
|
|
int y = (code>>13) & 7;
|
|
if ( y )
|
|
opr(insn.Op3, CA0+y-1);
|
|
}
|
|
break;
|
|
case 3:
|
|
{
|
|
static const ushort itypes[] =
|
|
{
|
|
HPPA_fadd, HPPA_fsub, HPPA_fmpy, HPPA_fdiv,
|
|
HPPA_null, HPPA_null, HPPA_null, HPPA_null
|
|
};
|
|
int sub = (code>>13) & 7;
|
|
insn.itype = itypes[sub];
|
|
if ( code & BIT23 )
|
|
{
|
|
insn.itype = (sub == 2) ? HPPA_xmpyu : HPPA_null;
|
|
}
|
|
opr(insn.Op1, fr(r06(code), (code>>7)&1));
|
|
opr(insn.Op2, fr(r11(code), (code>>12)&1));
|
|
opr(insn.Op3, fr(r27(code), (code>>6)&1));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
inline void opn(op_t &x, sval_t disp, ea_t ip)
|
|
{
|
|
disp <<= 2;
|
|
x.type = o_near;
|
|
x.addr = ip + 8 + disp;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
int hppa_t::ana(insn_t *_insn)
|
|
{
|
|
if ( _insn == NULL )
|
|
return 0;
|
|
insn_t &insn = *_insn;
|
|
if ( insn.ip & 3 )
|
|
return 0; // alignment error
|
|
|
|
uint32 code = insn.get_next_dword();
|
|
|
|
int op = opcode(code);
|
|
insn.itype = C1[op].itype;
|
|
char dtype = C1[op].dtype;
|
|
switch ( op )
|
|
{
|
|
case 0x00:
|
|
switch ( (code>>5) & 0xFF )
|
|
{
|
|
case 0x00:
|
|
insn.itype = HPPA_break;
|
|
opi(insn.Op1, r27(code));
|
|
opi(insn.Op2, (code>>13) & 0x1FFF);
|
|
break;
|
|
case 0x20:
|
|
insn.itype = (code & BIT11) ? HPPA_syncdma : HPPA_sync;
|
|
break;
|
|
case 0x60:
|
|
case 0x65:
|
|
insn.itype = HPPA_rfi;
|
|
break;
|
|
case 0x6B:
|
|
insn.itype = HPPA_ssm;
|
|
RSM_SSM:
|
|
opi(insn.Op1, (code>>16)&0x3FF);
|
|
opr(insn.Op2, r27(code));
|
|
break;
|
|
case 0x73:
|
|
insn.itype = HPPA_rsm;
|
|
goto RSM_SSM;
|
|
case 0xC3:
|
|
insn.itype = HPPA_mtsm;
|
|
opr(insn.Op1, r11(code));
|
|
break;
|
|
case 0x85:
|
|
insn.itype = HPPA_ldsid;
|
|
opbs(insn, insn.Op1, (code>>14)&3, r06(code));
|
|
opr(insn.Op2, r27(code));
|
|
break;
|
|
case 0xC1:
|
|
insn.itype = HPPA_mtsp;
|
|
opr(insn.Op1, r11(code));
|
|
opr(insn.Op2, SR0+((code>>13)&7));
|
|
break;
|
|
case 0x25:
|
|
insn.itype = HPPA_mfsp;
|
|
opr(insn.Op1, SR0+((code>>13)&7));
|
|
opr(insn.Op2, r27(code));
|
|
break;
|
|
case 0xA5:
|
|
insn.itype = HPPA_mfia;
|
|
opr(insn.Op1, r27(code));
|
|
break;
|
|
case 0xC2:
|
|
insn.itype = HPPA_mtctl;
|
|
opr(insn.Op1, r11(code));
|
|
opr(insn.Op2, CR0+r06(code));
|
|
break;
|
|
case 0xC6:
|
|
if ( r06(code) != 0xB )
|
|
return 0;
|
|
insn.itype = HPPA_mtsarcm;
|
|
opr(insn.Op1, r11(code));
|
|
break;
|
|
case 0x45:
|
|
insn.itype = HPPA_mfctl;
|
|
opr(insn.Op1, CR0+r06(code));
|
|
opr(insn.Op2, r27(code));
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
break;
|
|
|
|
case 0x01:
|
|
if ( code & BIT19 )
|
|
{
|
|
switch ( (code>>6) & 0xFF )
|
|
{
|
|
case 0x60:
|
|
insn.itype = HPPA_idtlbt;
|
|
opr(insn.Op1, CR0+r06(code));
|
|
opr(insn.Op2, r27(code));
|
|
break;
|
|
case 0x48:
|
|
case 0x58:
|
|
insn.itype = HPPA_pdtlb;
|
|
goto PDT;
|
|
case 0x49:
|
|
insn.itype = HPPA_pdtlbe;
|
|
PDT:
|
|
opxs(insn, insn.Op1, (code>>14)&3, r06(code), r11(code), dt_dword);
|
|
break;
|
|
case 0x4A:
|
|
insn.itype = HPPA_fdc;
|
|
opxs(insn, insn.Op1, (code>>14)&3, r06(code), r11(code), dt_dword);
|
|
break;
|
|
case 0xCA:
|
|
insn.itype = HPPA_fdc;
|
|
opds(insn, insn.Op1, (code>>14)&3, r06(code), ls5(r11(code)), dt_dword);
|
|
if ( code & BIT26 )
|
|
return 0;
|
|
break;
|
|
case 0x4B:
|
|
insn.itype = HPPA_fdce;
|
|
opxs(insn, insn.Op1, (code>>14)&3, r06(code), r11(code), dt_dword);
|
|
break;
|
|
case 0x4E:
|
|
insn.itype = HPPA_pdc;
|
|
opxs(insn, insn.Op1, (code>>14)&3, r06(code), r11(code), dt_dword);
|
|
break;
|
|
case 0x4F:
|
|
insn.itype = HPPA_fic;
|
|
opxs(insn, insn.Op1, (code>>14)&3, r06(code), r11(code), dt_dword);
|
|
break;
|
|
case 0x46:
|
|
case 0x47:
|
|
insn.itype = HPPA_probe;
|
|
opbs(insn, insn.Op1, (code>>14)&3, r06(code));
|
|
opr(insn.Op2, r11(code));
|
|
opr(insn.Op3, r27(code));
|
|
break;
|
|
case 0xC6:
|
|
case 0xC7:
|
|
insn.itype = HPPA_probei;
|
|
opbs(insn, insn.Op1, (code>>14)&3, r06(code));
|
|
opi(insn.Op2, r11(code));
|
|
opr(insn.Op3, r27(code));
|
|
break;
|
|
case 0x4D:
|
|
insn.itype = HPPA_lpa;
|
|
MAKE_LPA:
|
|
opxs(insn, insn.Op1, (code>>14)&3, r06(code), r11(code), dt_dword);
|
|
opr(insn.Op2, r27(code));
|
|
break;
|
|
case 0x4C:
|
|
insn.itype = HPPA_lci;
|
|
if ( code & BIT26 )
|
|
return 0;
|
|
goto MAKE_LPA;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch ( (code>>6) & 0x7F )
|
|
{
|
|
case 0x20:
|
|
insn.itype = HPPA_iitlbt;
|
|
opr(insn.Op1, r11(code));
|
|
opr(insn.Op2, r06(code));
|
|
break;
|
|
case 0x18:
|
|
case 0x08:
|
|
insn.itype = HPPA_pitlb;
|
|
PIT:
|
|
opxs(insn, insn.Op1, as3((code>>13)&7), r06(code), r11(code), dt_dword);
|
|
insn.auxpref |= aux_space;
|
|
break;
|
|
case 0x09:
|
|
insn.itype = HPPA_pitlbe;
|
|
goto PIT;
|
|
case 0x0A:
|
|
insn.itype = HPPA_fic;
|
|
goto PIT;
|
|
case 0x0B:
|
|
insn.itype = HPPA_fice;
|
|
goto PIT;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 0x02:
|
|
insn.auxpref = (code>>13) & aux_cndc; // condition
|
|
insn.itype = find_itype(C5, (code>>6)&0x3F);
|
|
switch ( insn.itype )
|
|
{
|
|
default:
|
|
// case HPPA_add:
|
|
// case HPPA_sub:
|
|
// case HPPA_ds:
|
|
// case HPPA_and:
|
|
// case HPPA_andcm:
|
|
// case HPPA_or:
|
|
// case HPPA_xor:
|
|
// case HPPA_uxor:
|
|
// case HPPA_cmpclr:
|
|
// case HPPA_uaddcm:
|
|
// case HPPA_hadd:
|
|
// case HPPA_hsub:
|
|
// case HPPA_havg:
|
|
opr(insn.Op1, r11(code));
|
|
opr(insn.Op2, r06(code));
|
|
opr(insn.Op3, r27(code));
|
|
break;
|
|
case HPPA_dcor:
|
|
opr(insn.Op1, r06(code));
|
|
opr(insn.Op2, r27(code));
|
|
break;
|
|
case HPPA_shladd:
|
|
opr(insn.Op1, r11(code));
|
|
opi(insn.Op2, (code>>6)&3);
|
|
if ( ((code>>6) & 3) == 0 )
|
|
return 0;
|
|
opr(insn.Op3, r06(code));
|
|
opr(insn.Op4, r27(code));
|
|
break;
|
|
case HPPA_hshladd:
|
|
opr(insn.Op1, r11(code));
|
|
opr(insn.Op2, r06(code));
|
|
if ( ((code>>6) & 3) == 0 )
|
|
return 0;
|
|
if ( insn.auxpref )
|
|
return 0; // condition should be never
|
|
opi(insn.Op3, (code>>6)&3);
|
|
opr(insn.Op4, r27(code));
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 0x03:
|
|
{
|
|
int idx = (code>>6) & 0xF;
|
|
if ( (code & BIT19) == 0 && idx > 7 )
|
|
return 0;
|
|
insn.itype = C6[idx].itype;
|
|
dtype = C6[idx].dtype;
|
|
if ( code & BIT19 ) // short
|
|
{
|
|
if ( idx > 7 ) // store
|
|
{
|
|
opr(insn.Op1, r11(code));
|
|
opds(insn, insn.Op2, (code>>14)&3, r06(code), ls5(r27(code)), dtype);
|
|
}
|
|
else // load
|
|
{
|
|
opds(insn, insn.Op1, (code>>14)&3, r06(code), ls5(r11(code)), dtype);
|
|
opr(insn.Op2, r27(code));
|
|
}
|
|
}
|
|
else // index
|
|
{
|
|
opxs(insn, insn.Op1, (code>>14)&3, r06(code), r11(code), dtype);
|
|
opr(insn.Op2, r27(code));
|
|
}
|
|
if ( (idx & 7) == 6 )
|
|
insn.auxpref &= ~aux_space; // ldwa, stwa
|
|
}
|
|
break;
|
|
|
|
case 0x04:
|
|
switch ( (code>>9) & 3 )
|
|
{
|
|
case 0:
|
|
insn.itype = HPPA_spop0;
|
|
break;
|
|
case 1:
|
|
insn.itype = HPPA_spop1;
|
|
opr(insn.Op1, r27(code));
|
|
break;
|
|
case 2:
|
|
insn.itype = HPPA_spop2;
|
|
opr(insn.Op1, r06(code));
|
|
break;
|
|
case 3:
|
|
insn.itype = HPPA_spop3;
|
|
opr(insn.Op1, r11(code));
|
|
opr(insn.Op2, r06(code));
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 0x05: // diag
|
|
opi(insn.Op1, code & 0x3FFFFFF);
|
|
break;
|
|
|
|
case 0x06: // fmpyadd
|
|
case 0x26: // fmpysub
|
|
{
|
|
bool d = !((code>>5) & 1);
|
|
opr(insn.Op1, mfr(r06(code),d));
|
|
opr(insn.Op2, mfr(r11(code),d));
|
|
opr(insn.Op3, mfr(r27(code),d));
|
|
opr(insn.Op4, mfr((code>>6)&0x1F,d));
|
|
opr(insn.Op5, mfr((code>>11)&0x1F,d));
|
|
}
|
|
break;
|
|
|
|
case 0x07:
|
|
return 0;
|
|
|
|
case 0x08: // ldil
|
|
opi(insn.Op1, as21(code & 0x1FFFFF));
|
|
opr(insn.Op2, r06(code));
|
|
break;
|
|
|
|
case 0x09: // cldw, cstw, fstd, fstw
|
|
case 0x0B: // cldd, cstd, fldd, fldw
|
|
{
|
|
op_t *x;
|
|
int uid = (code>> 6) & 7;
|
|
if ( code & BIT22 )
|
|
{
|
|
insn.itype = HPPA_cstd;
|
|
opr(insn.Op1, r27(code));
|
|
x = &insn.Op2;
|
|
if ( uid < 2 )
|
|
{
|
|
insn.itype = HPPA_fstd;
|
|
insn.Op1.reg += F0 + ((code>>1)&0x20);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
insn.itype = HPPA_cldd;
|
|
opr(insn.Op2, r27(code));
|
|
x = &insn.Op1;
|
|
if ( uid < 2 )
|
|
{
|
|
insn.itype = HPPA_fldd;
|
|
insn.Op2.reg += F0 + ((code>>1)&0x20);
|
|
}
|
|
}
|
|
dtype = dt_qword;
|
|
if ( op == 0x09 )
|
|
{
|
|
insn.itype++; // cldw, cstw
|
|
dtype = dt_dword;
|
|
}
|
|
if ( code & BIT19 )
|
|
opds(insn, *x, (code>>14)&3, r06(code), ls5(r11(code)), dtype);
|
|
else
|
|
opxs(insn, *x, (code>>14)&3, r06(code), r11(code), dtype);
|
|
}
|
|
break;
|
|
|
|
case 0x0A: // addil
|
|
opi(insn.Op1, as21(code & 0x1FFFFF));
|
|
opr(insn.Op2, r06(code));
|
|
opr(insn.Op3, R1);
|
|
break;
|
|
|
|
case 0x0C: // copr
|
|
handle_float_0C(insn, code);
|
|
break;
|
|
|
|
case 0x0D: // ldo
|
|
if ( getseg(insn.ea)->is_64bit() )
|
|
dtype = dt_qword;
|
|
opd(insn.Op1, r06(code), s16(get_ldo(code)), dtype);
|
|
opr(insn.Op2, r11(code));
|
|
break;
|
|
|
|
case 0x0E:
|
|
handle_float_0E(insn, code);
|
|
break;
|
|
|
|
case 0x0F:
|
|
return 0;
|
|
|
|
case 0x10: // ldb
|
|
case 0x11: // ldh
|
|
case 0x12: // ldw
|
|
case 0x13: // ldw (mod)
|
|
{
|
|
int s = (code>>14) & 3;
|
|
opds(insn, insn.Op1, s, r06(code), s16(assemble_16(s,code & 0x3FFF)), dtype);
|
|
opr(insn.Op2, r11(code));
|
|
}
|
|
break;
|
|
|
|
case 0x14:
|
|
{
|
|
int s = (code>>14) & 3;
|
|
insn.itype = (code & BIT30) ? HPPA_fldd : HPPA_ldd;
|
|
int im10a = ((code>>3) & 0x7FE) | (code & 1);
|
|
opds(insn, insn.Op1, s, r06(code), s16(assemble_16(s,im10a)), dtype);
|
|
opr(insn.Op2, r11(code));
|
|
if ( code & BIT30 )
|
|
insn.Op2.reg += F0;
|
|
}
|
|
break;
|
|
|
|
case 0x1C:
|
|
{
|
|
int s = (code>>14) & 3;
|
|
insn.itype = (code & BIT30) ? HPPA_fstd : HPPA_std;
|
|
int im10a = ((code>>3) & 0x7FE) | (code & 1);
|
|
opr(insn.Op1, r11(code));
|
|
if ( code & BIT30 )
|
|
insn.Op1.reg += F0;
|
|
opds(insn, insn.Op2, s, r06(code), s16(assemble_16(s,im10a)), dtype);
|
|
}
|
|
break;
|
|
|
|
case 0x16:
|
|
case 0x17:
|
|
{
|
|
int s = (code>>14) & 3;
|
|
insn.itype = op & 1 && (code & BIT29) ? HPPA_ldw : HPPA_fldw;
|
|
int im11a = ((code>>3) & 0xFFE) | (code & 1);
|
|
opds(insn, insn.Op1, s, r06(code), s16(assemble_16(s,im11a)), dtype);
|
|
opr(insn.Op2, r11(code));
|
|
if ( code & BIT29 )
|
|
insn.Op2.reg += F0 + ((code<<4) & 0x20);
|
|
}
|
|
break;
|
|
|
|
case 0x1E:
|
|
case 0x1F:
|
|
{
|
|
int s = (code>>14) & 3;
|
|
insn.itype = op & 1 && (code & BIT29) ? HPPA_stw : HPPA_fstw;
|
|
int im11a = ((code>>3) & 0xFFE) | (code & 1);
|
|
opr(insn.Op1, r11(code));
|
|
if ( code & BIT29 )
|
|
insn.Op1.reg += F0 + ((code<<4) & 0x20);
|
|
opds(insn, insn.Op2, s, r06(code), s16(assemble_16(s,im11a)), dtype);
|
|
}
|
|
break;
|
|
|
|
case 0x18: // stb
|
|
case 0x19: // sth
|
|
case 0x1A: // stw
|
|
case 0x1B: // stw (mod)
|
|
{
|
|
int s = (code>>14) & 3;
|
|
opr(insn.Op1, r11(code));
|
|
opds(insn, insn.Op2, s, r06(code), s16(assemble_16(s,code & 0x3FFF)), dtype);
|
|
}
|
|
break;
|
|
|
|
case 0x15:
|
|
case 0x1D:
|
|
return 0;
|
|
|
|
case 0x20: // cmpb
|
|
case 0x22: // cmpb
|
|
case 0x27: // cmpb
|
|
case 0x2F: // cmpb
|
|
case 0x28: // addb
|
|
case 0x2A: // addb
|
|
case 0x32: // movb
|
|
insn.auxpref = (code>>13) & aux_cndc; // condition
|
|
opr(insn.Op1, r11(code));
|
|
opr(insn.Op2, r06(code));
|
|
opn(insn.Op3, s12(get11(code)|((code&1)<<11)), insn.ip);
|
|
break;
|
|
|
|
case 0x21: // cmpib
|
|
case 0x23: // cmpib
|
|
case 0x3B: // cmpib
|
|
case 0x29: // addib
|
|
case 0x2B: // addib
|
|
case 0x33: // movib
|
|
insn.auxpref = (code>>13) & aux_cndc; // condition
|
|
opi(insn.Op1, ls5(r11(code)));
|
|
opr(insn.Op2, r06(code));
|
|
opn(insn.Op3, s12(get11(code)|((code&1)<<11)), insn.ip);
|
|
break;
|
|
|
|
case 0x24: // cmpiclr
|
|
case 0x25: // subi
|
|
case 0x2C: // addi
|
|
case 0x2D: // addi
|
|
insn.auxpref = (code>>13) & aux_cndc; // condition
|
|
opi(insn.Op1, ls11(code & 0x7FF));
|
|
opr(insn.Op2, r06(code));
|
|
opr(insn.Op3, r11(code));
|
|
break;
|
|
|
|
case 0x2E:
|
|
{
|
|
insn.itype = (code & BIT26) ? HPPA_fmpynfadd : HPPA_fmpyfadd;
|
|
bool d = (code>>11) & 1;
|
|
opr(insn.Op1, mfr(r06(code),d));
|
|
opr(insn.Op2, mfr(r11(code),d));
|
|
int ra = ((code>>10) & 0x38) | ((code>>8) & 0x7);
|
|
opr(insn.Op3, F0+ra);
|
|
opr(insn.Op4, mfr(r27(code),d));
|
|
}
|
|
break;
|
|
|
|
case 0x30: // bb
|
|
case 0x31:
|
|
opr(insn.Op1, r11(code));
|
|
if ( op & 1 )
|
|
{
|
|
int pos = r06(code) | ((code>>8) & 0x20);
|
|
opi(insn.Op2, pos);
|
|
}
|
|
else
|
|
{
|
|
opr(insn.Op2, CR11);
|
|
}
|
|
opn(insn.Op3, s12(get11(code)|((code&1)<<11)), insn.ip);
|
|
break;
|
|
|
|
case 0x34:
|
|
insn.auxpref = (code>>13) & aux_cndc; // condition
|
|
switch ( (code>>11) & 3 ) // bits 19, 20
|
|
{
|
|
case 0:
|
|
if ( (code & BIT21) == 0 ) // format 11
|
|
{
|
|
insn.itype = (code & BIT22) ? HPPA_shrpd : HPPA_shrpw;
|
|
opr(insn.Op1, r11(code));
|
|
opr(insn.Op2, r06(code));
|
|
opr(insn.Op3, CR11);
|
|
opr(insn.Op4, r27(code));
|
|
break;
|
|
}
|
|
// no break
|
|
case 1: // format 14
|
|
{
|
|
insn.itype = (code & BIT21) ? HPPA_shrpd : HPPA_shrpw;
|
|
opr(insn.Op1, r11(code));
|
|
opr(insn.Op2, r06(code));
|
|
int sa = (insn.itype == HPPA_shrpd ? 63 : 31) - (r22(code)|((code>>10)&1));
|
|
opi(insn.Op3, sa);
|
|
opr(insn.Op4, r27(code));
|
|
}
|
|
break;
|
|
case 2: // format 12
|
|
{
|
|
insn.itype = (code & BIT22) ? HPPA_extrd : HPPA_extrw;
|
|
opr(insn.Op1, r06(code));
|
|
opr(insn.Op2, CR11);
|
|
int cl = (code>>3) & 0x20;
|
|
if ( (code & BIT22) == 0 && cl )
|
|
return 0;
|
|
opi(insn.Op3, (32-r27(code))|cl);
|
|
opr(insn.Op4, r11(code));
|
|
}
|
|
break;
|
|
case 3: // format 15
|
|
insn.itype = HPPA_extrw;
|
|
opr(insn.Op1, r06(code));
|
|
opi(insn.Op2, r22(code));
|
|
opi(insn.Op3, 32-r27(code));
|
|
opr(insn.Op4, r11(code));
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 0x35:
|
|
insn.auxpref = (code>>13) & aux_cndc; // condition
|
|
if ( code & BIT20 ) // format 16
|
|
{
|
|
if ( code & BIT19 )
|
|
{
|
|
insn.itype = HPPA_depwi;
|
|
opi(insn.Op1, ls5(r11(code)));
|
|
}
|
|
else
|
|
{
|
|
insn.itype = HPPA_depw;
|
|
opr(insn.Op1, r11(code));
|
|
}
|
|
opi(insn.Op2, 31-r22(code));
|
|
opi(insn.Op3, 32-r27(code));
|
|
opr(insn.Op4, r06(code));
|
|
}
|
|
else // format 13
|
|
{
|
|
if ( code & BIT19 )
|
|
{
|
|
insn.itype = (code & BIT22) ? HPPA_depdi : HPPA_depwi;
|
|
opi(insn.Op1, ls5(r11(code)));
|
|
opr(insn.Op2, CR11);
|
|
}
|
|
else
|
|
{
|
|
insn.itype = (code & BIT22) ? HPPA_depd : HPPA_depw;
|
|
opr(insn.Op1, r11(code));
|
|
opr(insn.Op2, CR11);
|
|
}
|
|
int cl = (code>>3) & 0x20;
|
|
if ( (code & BIT22) == 0 && cl )
|
|
return 0;
|
|
opi(insn.Op3, (32-r27(code))|cl);
|
|
opr(insn.Op4, r06(code));
|
|
}
|
|
break;
|
|
|
|
case 0x36: // extrd
|
|
{
|
|
insn.auxpref = (code>>13) & aux_cndc; // condition
|
|
opr(insn.Op1, r06(code));
|
|
opi(insn.Op2, ((code>>6)&0x20)|r22(code));
|
|
int cl = (code>>7) & 0x20;
|
|
opi(insn.Op3, (32-r27(code))|cl);
|
|
opr(insn.Op4, r11(code));
|
|
}
|
|
break;
|
|
|
|
case 0x37:
|
|
return 0;
|
|
|
|
case 0x38: // be
|
|
case 0x39: // be
|
|
{
|
|
int32 w = get17(code);
|
|
opds(insn, insn.Op1, as3((code>>13)&7), r06(code), s17(w)<<2, dt_code);
|
|
insn.auxpref |= aux_space;
|
|
if ( op & 1 )
|
|
{
|
|
opr(insn.Op2, SR0);
|
|
opr(insn.Op3, R31);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 0x3A:
|
|
{
|
|
int sub = (code>>13) & 7;
|
|
switch ( sub )
|
|
{
|
|
case 0x2:
|
|
if ( code & BIT19 )
|
|
return 0;
|
|
insn.itype = HPPA_blr;
|
|
opr(insn.Op1, r11(code));
|
|
opr(insn.Op2, r06(code));
|
|
break;
|
|
case 0x6:
|
|
insn.itype = (code & BIT19) ? HPPA_bve : HPPA_bv;
|
|
if ( insn.itype == HPPA_bv )
|
|
opx(insn.Op1, r06(code), r11(code), dt_code);
|
|
else
|
|
opb(insn.Op1, r06(code));
|
|
break;
|
|
case 0x7:
|
|
if ( !(code & BIT19) )
|
|
return 0;
|
|
insn.itype = HPPA_bve;
|
|
opb(insn.Op1, r06(code));
|
|
opr(insn.Op1, R2);
|
|
break;
|
|
case 0x0:
|
|
case 0x1:
|
|
{
|
|
insn.itype = HPPA_b;
|
|
int32 w = get17(code);
|
|
opn(insn.Op1, s17(w), insn.ip);
|
|
opr(insn.Op2, r06(code));
|
|
}
|
|
break;
|
|
case 0x4:
|
|
case 0x5:
|
|
{
|
|
insn.itype = HPPA_b;
|
|
int32 w = ((code&1) << 21)
|
|
| (r06(code) << 16)
|
|
| (r11(code) << 11)
|
|
| get11(code);
|
|
opn(insn.Op1, s22(w), insn.ip);
|
|
opr(insn.Op2, R2);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 0x3C:
|
|
insn.itype = HPPA_depd;
|
|
opr(insn.Op1, r11(code));
|
|
DEPD:
|
|
opi(insn.Op2, (32-r22(code))|((code>>7)&0x20));
|
|
opi(insn.Op3, r27(code));
|
|
opr(insn.Op4, r06(code));
|
|
insn.auxpref = (code>>13) & aux_cndc; // condition
|
|
break;
|
|
|
|
case 0x3D:
|
|
insn.itype = HPPA_depdi;
|
|
opi(insn.Op1, ls5(r11(code)));
|
|
goto DEPD;
|
|
|
|
case 0x3E:
|
|
if ( code & BIT16 )
|
|
{
|
|
switch ( (code>>10) & 3 )
|
|
{
|
|
case 0:
|
|
insn.itype = HPPA_mixw;
|
|
opr(insn.Op1, r11(code));
|
|
opr(insn.Op2, r06(code));
|
|
opr(insn.Op3, r27(code));
|
|
break;
|
|
case 1:
|
|
insn.itype = HPPA_mixh;
|
|
opr(insn.Op1, r11(code));
|
|
opr(insn.Op2, r06(code));
|
|
opr(insn.Op3, r27(code));
|
|
break;
|
|
case 2:
|
|
if ( ((code>>13)&3) == 0 )
|
|
{
|
|
insn.itype = HPPA_hshl;
|
|
opr(insn.Op1, r11(code));
|
|
opi(insn.Op2, (code>>6) & 0xF);
|
|
opr(insn.Op3, r27(code));
|
|
break;
|
|
}
|
|
// no break;
|
|
case 3:
|
|
insn.itype = HPPA_hshr;
|
|
opr(insn.Op1, r06(code));
|
|
opi(insn.Op2, (code>>6) & 0xF);
|
|
opr(insn.Op3, r27(code));
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
insn.itype = HPPA_permh;
|
|
if ( r06(code) != r11(code) )
|
|
return 0;
|
|
opr(insn.Op1, r06(code));
|
|
opr(insn.Op2, r27(code));
|
|
}
|
|
break;
|
|
|
|
case 0x3F:
|
|
return 0;
|
|
|
|
default:
|
|
interr(insn, "ana");
|
|
}
|
|
if ( insn.itype == 0 )
|
|
return 0;
|
|
|
|
if ( dosimple() )
|
|
simplify(insn, code);
|
|
|
|
char buf[80];
|
|
if ( !build_insn_completer(insn, code, buf, sizeof(buf)) )
|
|
return 0;
|
|
|
|
return insn.size;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
void interr(const insn_t &insn, const char *module)
|
|
{
|
|
const char *name = NULL;
|
|
if ( insn.itype < HPPA_last )
|
|
name = Instructions[insn.itype].name;
|
|
warning("%a(%s): internal error in %s", insn.ea, name, module);
|
|
}
|
|
|