update to ida 7.6, add builds
This commit is contained in:
539
idasdk76/module/cr16/ana.cpp
Normal file
539
idasdk76/module/cr16/ana.cpp
Normal file
@@ -0,0 +1,539 @@
|
||||
|
||||
/*
|
||||
* National Semiconductor Corporation CR16 processor module for IDA.
|
||||
* Copyright (c) 2002-2006 Konstantin Norvatoff, <konnor@bk.ru>
|
||||
* Freeware.
|
||||
*/
|
||||
|
||||
#include "cr16.hpp"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static uchar Rproc(uchar code)
|
||||
{
|
||||
switch ( code )
|
||||
{
|
||||
case 0x1:
|
||||
return rPSR;
|
||||
case 0x3:
|
||||
return rINTBASE;
|
||||
case 0x4:
|
||||
return rINTBASEH;
|
||||
case 0x5:
|
||||
return rCFG;
|
||||
case 0x7:
|
||||
return rDSR;
|
||||
case 0x9:
|
||||
return rDCR;
|
||||
case 0xB:
|
||||
return rISP;
|
||||
case 0xD:
|
||||
return rCARL;
|
||||
case 0xE:
|
||||
return rCARH;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// immediate operands
|
||||
static void SetImmData(op_t &op, int32 code, int bits)
|
||||
{
|
||||
// extend sign
|
||||
if ( code & (1 << bits) )
|
||||
code -= 1L << (bits + 1);
|
||||
op.type = o_imm;
|
||||
// always in the second byte
|
||||
op.offb = 1;
|
||||
// data size
|
||||
op.dtype = bits > 8 ? (bits > 16 ? dt_dword : dt_word) : dt_byte;
|
||||
// value
|
||||
op.addr = op.value = code;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// register operand
|
||||
static void SetReg(op_t &op, uchar reg_n)
|
||||
{
|
||||
op.type = o_reg;
|
||||
op.reg = reg_n;
|
||||
op.dtype = dt_word;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// relative jump
|
||||
static void SetRelative(op_t &op, int32 disp, int bits, const insn_t &insn)
|
||||
{
|
||||
op.type = o_near;
|
||||
op.dtype = dt_word;
|
||||
op.offb = 0;
|
||||
// sign extend
|
||||
if ( disp & (1 << bits) )
|
||||
disp -= 1L << (bits + 1);
|
||||
op.addr = insn.ip + disp;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static ushort GetWord(insn_t &insn)
|
||||
{
|
||||
ushort wrd = insn.get_next_byte();
|
||||
wrd |= ((ushort) insn.get_next_byte()) << 8;
|
||||
return wrd;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// store/load operands
|
||||
static void SetSL(insn_t &insn, op_t &op, ushort code)
|
||||
{
|
||||
op.reg = rR0 + ((code >> 1) & 0x0F);
|
||||
op.dtype = (code & 0x2000) ? dt_word : dt_byte;
|
||||
if ( code & 1 )
|
||||
{
|
||||
if ( code & 0x1000 )
|
||||
{
|
||||
if ( code & 0x800 )
|
||||
{
|
||||
if ( (code & 0x1F) == 0x1F )
|
||||
{
|
||||
// absolute addr
|
||||
op.type = o_mem;
|
||||
op.addr = op.value = GetWord(insn) | (((uint32) code & 0x600) << 11);
|
||||
}
|
||||
else
|
||||
{ // reg pair
|
||||
op.type = o_displ;
|
||||
op.addr = op.value = GetWord(insn) | (((uint32) code & 0x600) << 11);
|
||||
op.specflag1 |= URR_PAIR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // reg base
|
||||
op.type = o_displ;
|
||||
op.addr = op.value = GetWord(insn) | (((uint32) code & 0x600) << 11);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // Offset
|
||||
op.type = o_displ;
|
||||
op.addr = op.value = ((code >> 8) & 0x1E) | 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
op.type = o_displ;
|
||||
op.addr = op.value = (code >> 8) & 0x1E;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
#define EXTOPS uint16(-2)
|
||||
static const uint16 Ops[16] =
|
||||
{
|
||||
CR16_addb, CR16_addub, EXTOPS, CR16_mulb,
|
||||
CR16_ashub, CR16_lshb, CR16_xorb, CR16_cmpb,
|
||||
CR16_andb, CR16_addcb, CR16_br, CR16_tbit,
|
||||
CR16_movb, CR16_subcb, CR16_orb, CR16_subb,
|
||||
};
|
||||
|
||||
static const uint16 ExtOps[16] =
|
||||
{
|
||||
CR16_cbitb, CR16_sbitb, CR16_tbitb, CR16_storb,
|
||||
};
|
||||
|
||||
// extended instructions
|
||||
// register-relative with no displacement:
|
||||
// 54 3 2109 8 76 5 4321 d
|
||||
// 01 i 0010 bs1 ex-op bs0 bit-num/Imm 1
|
||||
// register-relative with 16-bit displacement:
|
||||
// 54 3 2109 8 76 5 4321 d
|
||||
// 00 i 0010 bs1 ex-op bs0 bit-num/Imm 1
|
||||
// 18-bit absolute memory:
|
||||
// 54 3 2109 8 76 5 4321 d
|
||||
// 00 i 0010 bs1 ex-op bs0 bit-num/Imm 0
|
||||
static void SetExtOp(insn_t &insn, ushort code)
|
||||
{
|
||||
if ( code & 1 )
|
||||
{
|
||||
// Register-relative
|
||||
insn.Op2.reg = rR0 + ((code >> 5) & 9);
|
||||
insn.Op2.type = o_displ;
|
||||
insn.Op2.dtype = (code & 0x2000) ? dt_word : dt_byte;
|
||||
if ( (code >> 14) & 1 )
|
||||
{
|
||||
// no displacement
|
||||
insn.Op2.addr = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
insn.Op2.addr = GetWord(insn);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 18-bit absolute memory
|
||||
insn.Op2.type = o_mem;
|
||||
insn.Op2.dtype = (code & 0x2000) ? dt_word : dt_byte;
|
||||
int adext = ((code >> 7) & 2) | ((code >> 5) & 1);
|
||||
insn.Op2.addr = GetWord(insn) | (adext<<16);
|
||||
}
|
||||
insn.Op1.type = o_imm;
|
||||
insn.Op1.value = (code >> 1) & 0xF;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// analyzer
|
||||
int idaapi CR16_ana(insn_t *_insn)
|
||||
{
|
||||
if ( _insn == NULL )
|
||||
return 0;
|
||||
insn_t &insn = *_insn;
|
||||
if ( insn.ip & 1 )
|
||||
return 0;
|
||||
|
||||
// get instruction word
|
||||
ushort code = GetWord(insn);
|
||||
|
||||
uchar WordFlg = (code >> 13) & 1;
|
||||
uchar OpCode = (code >> 9) & 0x0F;
|
||||
uchar Oper1 = (code >> 5) & 0x0F;
|
||||
uchar Oper2 = (code >> 1) & 0x0F;
|
||||
|
||||
|
||||
switch ( (code >> 14) & 3 )
|
||||
{
|
||||
// register-register op and special OP
|
||||
case 0x01:
|
||||
if ( code & 1 )
|
||||
{
|
||||
// 01xxxxxxxxxxxxx1
|
||||
insn.itype = Ops[OpCode];
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case 0:
|
||||
return 0;
|
||||
case EXTOPS:
|
||||
{
|
||||
int exop = (Oper1 >> 1) & 3;
|
||||
insn.itype = ExtOps[exop] + WordFlg;
|
||||
SetExtOp(insn, code);
|
||||
}
|
||||
break;
|
||||
// branch's
|
||||
case CR16_br:
|
||||
if ( WordFlg )
|
||||
{
|
||||
insn.itype = CR16_jal;
|
||||
SetReg(insn.Op1, rR0 + Oper1);
|
||||
SetReg(insn.Op2, rR0 + Oper2);
|
||||
}
|
||||
else
|
||||
{
|
||||
insn.itype = CR16_jeq + Oper1;
|
||||
SetReg(insn.Op1, rR0 + Oper2);
|
||||
}
|
||||
break;
|
||||
// Special tbit
|
||||
case CR16_tbit:
|
||||
if ( WordFlg == 0 )
|
||||
return 0;
|
||||
insn.itype--;
|
||||
// fallthrough
|
||||
// all other cmds
|
||||
default: // fix word operations
|
||||
if ( WordFlg )
|
||||
insn.itype++;
|
||||
// Setup register OP
|
||||
SetReg(insn.Op2, rR0 + Oper1);
|
||||
// Setup register OP
|
||||
SetReg(insn.Op1, rR0 + Oper2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // 01xxxxxxxxxxxxx0
|
||||
if ( WordFlg )
|
||||
{
|
||||
// 011xxxxxxxxxxxx0
|
||||
static const uchar SCmd[16] =
|
||||
{
|
||||
CR16_mulsb, CR16_mulsw, CR16_movd, CR16_movd,
|
||||
CR16_movxb, CR16_movzb, CR16_push, CR16_seq,
|
||||
CR16_lpr, CR16_spr, CR16_beq, CR16_bal,
|
||||
CR16_retx, CR16_excp, CR16_di, CR16_wait
|
||||
};
|
||||
insn.itype = SCmd[OpCode];
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case 0:
|
||||
return 0;
|
||||
|
||||
case CR16_beq:
|
||||
{
|
||||
// 01 1 1010 cond d16,d19-d17 0
|
||||
insn.itype = CR16_beq + Oper1;
|
||||
int disp = GetWord(insn);
|
||||
disp |= (Oper2 & 8) << (16-3);
|
||||
disp |= (Oper2 & 7) << 17;
|
||||
SetRelative(insn.Op1, disp, 20, insn);
|
||||
}
|
||||
break;
|
||||
|
||||
case CR16_push:
|
||||
{
|
||||
static const uchar PQ[4] =
|
||||
{
|
||||
CR16_push, CR16_pop,
|
||||
CR16_popret, CR16_popret
|
||||
};
|
||||
insn.itype = PQ[Oper1 >> 2];
|
||||
SetReg(insn.Op2, rR0 + Oper2);
|
||||
SetImmData(insn.Op1, (Oper1 & 3) + 1, 4);
|
||||
break;
|
||||
}
|
||||
|
||||
case CR16_mulsw:
|
||||
SetReg(insn.Op2, rR0 + Oper1);
|
||||
SetReg(insn.Op1, rR0 + Oper2);
|
||||
insn.Op2.specflag1 |= URR_PAIR;
|
||||
break;
|
||||
|
||||
case CR16_movd:
|
||||
SetReg(insn.Op2, rR0 + Oper2);
|
||||
insn.Op2.specflag1 |= URR_PAIR;
|
||||
// !!!! ADD HIIIII ?!?!?!?
|
||||
SetImmData(insn.Op1, GetWord(insn), 20);
|
||||
break;
|
||||
case CR16_excp:
|
||||
if ( Oper1 != 0x0F )
|
||||
return 0;
|
||||
SetImmData(insn.Op1, Oper2, 4);
|
||||
break;
|
||||
|
||||
case CR16_retx:
|
||||
if ( Oper1 != 0x0F )
|
||||
return 0;
|
||||
if ( Oper2 != 0x0F )
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case CR16_wait:
|
||||
if ( Oper1 == 0x0F )
|
||||
{
|
||||
if ( Oper2 == 0x0F )
|
||||
break;
|
||||
if ( Oper2 == 0x03 )
|
||||
{
|
||||
insn.itype = CR16_eiwait;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( (code & 0x19E) == 0x84 )
|
||||
{
|
||||
insn.itype = CR16_storm;
|
||||
SetImmData(insn.Op1, (Oper2 & 3) + 1, 8);
|
||||
break;
|
||||
}
|
||||
if ( (code & 0x19E) == 0x04 )
|
||||
{
|
||||
insn.itype = CR16_loadm;
|
||||
SetImmData(insn.Op1, (Oper2 & 3) + 1, 8);
|
||||
break;
|
||||
}
|
||||
if ( (Oper2 & 0x6) == 0 )
|
||||
{
|
||||
insn.itype = CR16_muluw;
|
||||
SetReg(insn.Op2, rR0 + Oper1);
|
||||
SetReg(insn.Op1, rR0 + Oper2);
|
||||
insn.Op2.specflag1 |= URR_PAIR;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
case CR16_di:
|
||||
if ( Oper2 != 0x0F )
|
||||
return 0;
|
||||
switch ( Oper1 )
|
||||
{
|
||||
case 0x0F:
|
||||
insn.itype = CR16_ei;
|
||||
case 0x0E:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case CR16_seq:
|
||||
SetReg(insn.Op1, rR0 + Oper2);
|
||||
if ( Oper1 > 0x0D )
|
||||
return 0;
|
||||
insn.itype = CR16_seq + Oper1;
|
||||
break;
|
||||
|
||||
case CR16_lpr:
|
||||
SetReg(insn.Op1, rR0 + Oper2);
|
||||
Oper1 = Rproc(Oper1);
|
||||
if ( Oper1 == 0 )
|
||||
return 0;
|
||||
SetReg(insn.Op2, Oper1);
|
||||
break;
|
||||
|
||||
case CR16_spr:
|
||||
SetReg(insn.Op2, rR0 + Oper2);
|
||||
Oper1 = Rproc(Oper1);
|
||||
if ( Oper1 == 0 )
|
||||
return 0;
|
||||
SetReg(insn.Op1, Oper1);
|
||||
break;
|
||||
|
||||
case CR16_bal:
|
||||
{
|
||||
// 01 1 1011 lnk-pair d16,d19-d17 0
|
||||
SetReg(insn.Op1, rR0 + Oper1);
|
||||
insn.Op1.specflag1 |= URR_PAIR;
|
||||
int disp = GetWord(insn);
|
||||
disp |= (Oper2 & 8) << (16-3);
|
||||
disp |= (Oper2 & 7) << 17;
|
||||
SetRelative(insn.Op2, disp, 20, insn);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
SetReg(insn.Op2, rR0 + Oper1);
|
||||
SetReg(insn.Op1, rR0 + Oper2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // jump's
|
||||
// 010xxxxxxxxxxxx0
|
||||
insn.itype = CR16_beq + Oper1;
|
||||
SetRelative(insn.Op1, (code & 0x1E) | (OpCode << 5), 8, insn);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// short immediate-register (two word)
|
||||
case 0x00:
|
||||
insn.itype = Ops[OpCode];
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case 0:
|
||||
return 0;
|
||||
// branch's
|
||||
case CR16_br:
|
||||
if ( code & 1 )
|
||||
{
|
||||
static const uchar BQ[4] =
|
||||
{
|
||||
CR16_beq0b, CR16_beq1b,
|
||||
CR16_bne0b, CR16_bne1b
|
||||
};
|
||||
insn.itype = BQ[(Oper1 >> 1) & 3];
|
||||
if ( WordFlg )
|
||||
insn.itype++;
|
||||
SetReg(insn.Op1, rR0 + (Oper1 & 0x9));
|
||||
SetRelative(insn.Op1, code & 0x1E, 5, insn);
|
||||
}
|
||||
else if ( WordFlg )
|
||||
{
|
||||
insn.itype = CR16_bal;
|
||||
SetReg(insn.Op1, rR0 + Oper1);
|
||||
if ( (code & 0x0F) == 0x0E )
|
||||
{
|
||||
SetRelative(insn.Op2,
|
||||
GetWord(insn) | (((uint32) code & 0x10) << 12), 16, insn);
|
||||
insn.Op2.addr = insn.Op2.value = insn.Op2.addr & 0x1FFFF;
|
||||
}
|
||||
else
|
||||
SetRelative(insn.Op2, code & 0x1F, 4, insn);
|
||||
}
|
||||
else
|
||||
{
|
||||
insn.itype = CR16_beq + Oper1;
|
||||
if ( (code & 0x0F) == 0x0E )
|
||||
{
|
||||
SetRelative(insn.Op1,
|
||||
GetWord(insn) | (((uint32) code & 0x10) << 12), 16, insn);
|
||||
insn.Op1.addr = insn.Op1.value = insn.Op2.addr & 0x1FFFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetRelative(insn.Op1, code & 0x1F, 4, insn);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EXTOPS:
|
||||
{
|
||||
// 54 3 2109 8 76 5 4321 d
|
||||
// 00 i 0010 bs1 ex-op bs0 bit-num/Imm d
|
||||
int exop = (Oper1 >> 1) & 3;
|
||||
insn.itype = ExtOps[exop] + WordFlg;
|
||||
SetExtOp(insn, code);
|
||||
}
|
||||
break;
|
||||
|
||||
// Special tbit
|
||||
case CR16_tbit:
|
||||
if ( WordFlg == 0 )
|
||||
{
|
||||
// jcond large format
|
||||
// 00 0 1011 cond target-pair 1
|
||||
// jal large format
|
||||
// 00 0 1011 link-pair target-pair 0
|
||||
if ( code & 1 )
|
||||
{
|
||||
insn.itype = CR16_jeq + Oper1;
|
||||
SetReg(insn.Op1, rR0 + Oper2);
|
||||
insn.Op1.specflag1 |= URR_PAIR;
|
||||
}
|
||||
else
|
||||
{
|
||||
insn.itype = CR16_jal;
|
||||
SetReg(insn.Op1, rR0 + Oper1);
|
||||
insn.Op1.specflag1 |= URR_PAIR;
|
||||
SetReg(insn.Op2, rR0 + Oper2);
|
||||
insn.Op2.specflag1 |= URR_PAIR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
insn.itype--;
|
||||
// fallthrough
|
||||
|
||||
// all other cmds
|
||||
default:
|
||||
if ( code == 0x200 )
|
||||
{
|
||||
insn.itype = CR16_nop;
|
||||
break;
|
||||
}
|
||||
if ( WordFlg ) // fix word operations
|
||||
insn.itype++;
|
||||
// Setup register OP
|
||||
SetReg(insn.Op2, rR0 + Oper1);
|
||||
// Setup immediate
|
||||
if ( (code & 0x1F) == 0x11 )
|
||||
SetImmData(insn.Op1, GetWord(insn), 15);
|
||||
else
|
||||
SetImmData(insn.Op1, code & 0x1F, 4);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
// LOADi
|
||||
case 0x02:
|
||||
insn.itype = WordFlg ? CR16_loadw : CR16_loadb;
|
||||
SetReg(insn.Op2, rR0 + Oper1);
|
||||
SetSL(insn, insn.Op1, code);
|
||||
break;
|
||||
// STORi
|
||||
case 0x3:
|
||||
insn.itype = WordFlg ? CR16_storw : CR16_storb;
|
||||
SetReg(insn.Op1, rR0 + Oper1);
|
||||
SetSL(insn, insn.Op2, code);
|
||||
break;
|
||||
}
|
||||
return insn.size;
|
||||
}
|
||||
Reference in New Issue
Block a user