update
This commit is contained in:
932
idasdk75/module/tms320c3/ana.cpp
Normal file
932
idasdk75/module/tms320c3/ana.cpp
Normal file
@@ -0,0 +1,932 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
* Texas Instruments's TMS5320C3X
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tms320c3x.hpp"
|
||||
|
||||
#define FUNCS_COUNT 3
|
||||
|
||||
struct ctx_t
|
||||
{
|
||||
insn_t &insn;
|
||||
op_t *op;
|
||||
ctx_t(insn_t *i) : insn(*i) { op = &i->Op1; }
|
||||
};
|
||||
|
||||
struct funcdesc_t
|
||||
{
|
||||
bool (*func)(ctx_t &ctx, int);
|
||||
uint32 mask;
|
||||
uint32 shift;
|
||||
};
|
||||
|
||||
struct opcode_t
|
||||
{
|
||||
uint16 itype;
|
||||
unsigned int insnidx; //lint !e958 padding is required to align members
|
||||
funcdesc_t funcs[FUNCS_COUNT];
|
||||
uchar itype2;
|
||||
funcdesc_t funcs2[FUNCS_COUNT]; //lint !e958 padding is required to align members
|
||||
bool ispar;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
//lint -esym(1764, ctx) could be declared const
|
||||
inline void opreg(ctx_t &ctx, uint16 reg)
|
||||
{
|
||||
ctx.op->type = o_reg;
|
||||
ctx.op->dtype = dt_byte;
|
||||
ctx.op->reg = reg;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static void make_o_mem(ctx_t &ctx)
|
||||
{
|
||||
switch ( ctx.insn.itype )
|
||||
{
|
||||
case TMS320C3X_BR:
|
||||
case TMS320C3X_BRD:
|
||||
case TMS320C3X_CALL:
|
||||
case TMS320C3X_RPTB:
|
||||
case TMS320C3X_Bcond:
|
||||
case TMS320C3X_DBcond:
|
||||
case TMS320C3X_CALLcond:
|
||||
ctx.op->type = o_near;
|
||||
ctx.op->dtype = dt_code;
|
||||
return;
|
||||
}
|
||||
ctx.op->type = o_mem;
|
||||
ctx.op->dtype = dt_byte;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool D_adr24(ctx_t &ctx, int value)
|
||||
{
|
||||
ctx.op->addr = value & 0xffffff;
|
||||
make_o_mem(ctx);
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool D_PC_Displ(ctx_t &ctx, int value)
|
||||
{
|
||||
int16 disp = value & 0xffff;
|
||||
|
||||
if ( value & 0x200000 )
|
||||
D_adr24(ctx, ctx.insn.ea + disp + 3); // delayed branch
|
||||
else
|
||||
D_adr24(ctx, ctx.insn.ea + disp + 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool imm8(ctx_t &ctx, int value)
|
||||
{
|
||||
ctx.op->type = o_imm;
|
||||
ctx.op->dtype = dt_byte;
|
||||
ctx.op->value = value & 0xff;
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool D_regs(ctx_t &ctx, int value) // interpret register numbers
|
||||
{
|
||||
if ( (value & 0x1f) > 0x1b )
|
||||
return false;
|
||||
|
||||
if ( (value & 0x1f) == 0x10 )
|
||||
value = 0x1b; //remap DP reg
|
||||
else if ( (value & 0x1f) > 0x10 )
|
||||
value = (value & 0x1f) - 1;
|
||||
opreg(ctx, value & 0x1f);
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool S_regs(ctx_t &ctx, int value)
|
||||
{
|
||||
if ( D_regs(ctx, value) )
|
||||
{
|
||||
ctx.op++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
static bool D_R(ctx_t &ctx, int value) // interpret Rx register numbers
|
||||
{
|
||||
if ( D_regs(ctx, value & 0x07) )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool S_R(ctx_t &ctx, int value)
|
||||
{
|
||||
if ( D_R(ctx, value) )
|
||||
{
|
||||
ctx.op++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool D_R2(ctx_t &ctx, int value)
|
||||
{
|
||||
return D_regs(ctx, r2 + (value & 0x07));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool D_ar(ctx_t &ctx, int value)
|
||||
{
|
||||
return D_regs(ctx, ar0 + (value & 0x07));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool S_ar(ctx_t &ctx, int value) // interpret ARx register numbers
|
||||
{
|
||||
if ( D_ar(ctx, value) )
|
||||
{
|
||||
ctx.op++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool D_indir(ctx_t &ctx, int value) // indirect addressing
|
||||
{
|
||||
ctx.op->type = o_phrase;
|
||||
ctx.op->dtype = dt_byte;
|
||||
ctx.op->phrase = ( value & 0xf800 ) >> 11;
|
||||
ctx.op->phtype = ar0 + ((value >> 8) & 0x07);
|
||||
ctx.op->addr = value & 0xff;
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool S_indir(ctx_t &ctx, int value)
|
||||
{
|
||||
if ( D_indir(ctx, value) )
|
||||
{
|
||||
ctx.op++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool D_indir3(ctx_t &ctx, int value) // indirect addressing for 3-operand and parallel instructions
|
||||
{
|
||||
ctx.op->type = o_phrase;
|
||||
ctx.op->dtype = dt_byte;
|
||||
ctx.op->phrase = ( value & 0xf8 ) >> 3; // indirect addressing type
|
||||
ctx.op->phtype = ar0 + (value & 0x07); // register no
|
||||
ctx.op->addr = 1; // offset (if present)
|
||||
return true;
|
||||
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
static bool S_indir3(ctx_t &ctx, int value)
|
||||
{
|
||||
if ( D_indir3(ctx, value) )
|
||||
{
|
||||
ctx.op++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool SSD_src3(ctx_t &ctx, int value) // 3-operand instructions parsing
|
||||
{
|
||||
switch ( (value >> 16) & 0x60 )
|
||||
{
|
||||
case 0x00:
|
||||
S_regs(ctx, value & 0xff);
|
||||
S_regs(ctx, (value >> 8) & 0xff);
|
||||
D_regs(ctx, (value >> 16) & 0x1f);
|
||||
break;
|
||||
|
||||
case 0x20:
|
||||
S_regs(ctx, value & 0xff);
|
||||
S_indir3(ctx, (value >> 8) & 0xff);
|
||||
D_regs(ctx, (value >> 16) & 0x1f);
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
S_indir3(ctx, value & 0xff);
|
||||
S_regs(ctx, (value >> 8) & 0xff);
|
||||
D_regs(ctx, (value >> 16) & 0x1f);
|
||||
break;
|
||||
|
||||
case 0x60:
|
||||
S_indir3(ctx, value & 0xff);
|
||||
S_indir3(ctx, (value >> 8) & 0xff);
|
||||
D_regs(ctx, (value >> 16) & 0x1f);
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool SD_src3_2op(ctx_t &ctx, int value) // parsing of 3-operand instructions which use only two
|
||||
{
|
||||
switch ( (value >> 16) & 0x60 )
|
||||
{
|
||||
case 0x00:
|
||||
S_regs(ctx, value & 0xff);
|
||||
D_regs(ctx, (value >> 8) & 0xff);
|
||||
break;
|
||||
case 0x20:
|
||||
S_regs(ctx, value & 0xff);
|
||||
D_indir3(ctx, (value >> 8) & 0xff);
|
||||
break;
|
||||
case 0x40:
|
||||
S_indir3(ctx, value & 0xff);
|
||||
D_regs(ctx, (value >> 8) & 0xff);
|
||||
break;
|
||||
case 0x60:
|
||||
S_indir3(ctx, value & 0xff);
|
||||
D_indir3(ctx, (value >> 8) & 0xff);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool DBranch(ctx_t &ctx, int /*value*/) // set delayed branch flag
|
||||
{
|
||||
ctx.insn.auxpref |= DBrFlag;
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool ImmFlt(ctx_t &ctx, int /*value*/) // set floating-point constand flag
|
||||
{
|
||||
ctx.insn.auxpref |= ImmFltFlag;
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool cond(ctx_t &ctx, int value) // parse condition codes
|
||||
{
|
||||
if ( ((value & 0x1f) > 0x14 ) || ((value & 0x1f) == 0x0b ) )
|
||||
return false;
|
||||
|
||||
ctx.insn.auxpref |= value & 0x1f;
|
||||
|
||||
if ( (ctx.insn.auxpref & 0x1f) == 0 ) // Upgrade retscond to retsu
|
||||
{
|
||||
switch ( ctx.insn.itype )
|
||||
{
|
||||
case TMS320C3X_RETIcond:
|
||||
ctx.insn.itype = TMS320C3X_RETIU;
|
||||
break;
|
||||
|
||||
case TMS320C3X_RETScond:
|
||||
ctx.insn.itype = TMS320C3X_RETSU;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( value & 0x20 )
|
||||
DBranch(ctx, 0); //delayed branch
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
static bool SD_adres(ctx_t &ctx, int value) // main addressing
|
||||
{
|
||||
switch ( (value >> 16) & 0x60 )
|
||||
{
|
||||
case 0x00:
|
||||
S_regs(ctx, value & 0xff);
|
||||
D_regs(ctx, (value >> 16) & 0x1f);
|
||||
break;
|
||||
|
||||
case 0x20:
|
||||
ctx.op->addr = value & 0xffff;
|
||||
make_o_mem(ctx);
|
||||
ctx.op++;
|
||||
D_regs(ctx, (value >> 16) & 0x1f);
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
S_indir(ctx, value & 0xffff);
|
||||
D_regs(ctx, (value >> 16) & 0x1f);
|
||||
break;
|
||||
|
||||
case 0x60:
|
||||
ctx.op->type = o_imm;
|
||||
ctx.op->dtype = dt_byte;
|
||||
ctx.op->value = value & 0xffff;
|
||||
ctx.op++;
|
||||
D_regs(ctx, (value >> 16) & 0x1f);
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool SD_adresRev(ctx_t &ctx, int value) // main addressing with reversed operands
|
||||
{
|
||||
switch ( (value >> 16) & 0x60 )
|
||||
{
|
||||
case 0x00:
|
||||
S_regs(ctx, (value >> 16) & 0x1f);
|
||||
D_regs(ctx, value & 0xff);
|
||||
break;
|
||||
|
||||
case 0x20:
|
||||
S_regs(ctx, (value >> 16) & 0x1f);
|
||||
ctx.op->addr = value & 0xffff;
|
||||
make_o_mem(ctx);
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
S_regs(ctx, (value >> 16) & 0x1f);
|
||||
D_indir(ctx, value & 0xffff);
|
||||
break;
|
||||
|
||||
case 0x60:
|
||||
S_regs(ctx, (value >> 16) & 0x1f);
|
||||
ctx.op->type = o_imm;
|
||||
ctx.op->dtype = dt_byte;
|
||||
ctx.op->value = value & 0xffff;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
static bool D_adres_1Op(ctx_t &ctx, int value) // main addressing using only one operand
|
||||
{
|
||||
switch ( (value >> 16) & 0x60 )
|
||||
{
|
||||
case 0x00:
|
||||
D_regs(ctx, value & 0xffff);
|
||||
break;
|
||||
case 0x20:
|
||||
ctx.op->addr = value & 0xffff;
|
||||
make_o_mem(ctx);
|
||||
break;
|
||||
case 0x40:
|
||||
D_indir(ctx, value & 0xffff);
|
||||
break;
|
||||
case 0x60:
|
||||
ctx.op->type = o_imm;
|
||||
ctx.op->dtype = dt_byte;
|
||||
ctx.op->value = value & 0xffff;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool idle_1_2(ctx_t &ctx, int value)
|
||||
{
|
||||
if ( value & 0x01 )
|
||||
ctx.insn.itype = TMS320C3X_IDLE2;
|
||||
else
|
||||
ctx.insn.itype = TMS320C3X_IDLE;
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool speedctrl(ctx_t &ctx, int value)
|
||||
{
|
||||
if ( value & 0x01 )
|
||||
ctx.insn.itype = TMS320C3X_LOPOWER;
|
||||
else
|
||||
ctx.insn.itype = TMS320C3X_MAXSPEED;
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool nopcases(ctx_t &ctx, int value)
|
||||
{
|
||||
if ( ((value>>16) & 0x60) == 0x40 )
|
||||
D_adres_1Op(ctx, value);
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
static const opcode_t table_pattern[] =
|
||||
{
|
||||
{ TMS320C3X_ABSF, 0x000, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }},
|
||||
{ TMS320C3X_ABSI, 0x001, {{ SD_adres, 0x007fffff } }},
|
||||
{ TMS320C3X_ADDC, 0x002, {{ SD_adres, 0x007fffff } }},
|
||||
{ TMS320C3X_ADDF, 0x003, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }},
|
||||
{ TMS320C3X_ADDI, 0x004, {{ SD_adres, 0x007fffff } }},
|
||||
{ TMS320C3X_AND, 0x005, {{ SD_adres, 0x007fffff } }},
|
||||
{ TMS320C3X_ANDN, 0x006, {{ SD_adres, 0x007fffff } }},
|
||||
{ TMS320C3X_ASH, 0x007, {{ SD_adres, 0x007fffff } }},
|
||||
{ TMS320C3X_CMPF, 0x008, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }},
|
||||
{ TMS320C3X_CMPI, 0x009, {{ SD_adres, 0x007fffff } }},
|
||||
{ TMS320C3X_FIX, 0x00a, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }},
|
||||
{ TMS320C3X_FLOAT, 0x00b, {{ SD_adres, 0x007fffff } }},
|
||||
{ TMS320C3X_NONE, 0x00c, {{ idle_1_2, 0xffffffff } }},//multiple case, mask should be checked further
|
||||
{ TMS320C3X_LDE, 0x00d, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }},
|
||||
{ TMS320C3X_LDF, 0x00e, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }},
|
||||
{ TMS320C3X_LDFI, 0x00f, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }},
|
||||
{ TMS320C3X_LDI, 0x010, {{ SD_adres, 0x007fffff } }},
|
||||
{ TMS320C3X_LDII, 0x011, {{ SD_adres, 0x007fffff } }},
|
||||
{ TMS320C3X_LDM, 0x012, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }},
|
||||
{ TMS320C3X_LSH, 0x013, {{ SD_adres, 0x007fffff } }},
|
||||
{ TMS320C3X_MPYF, 0x014, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }},
|
||||
{ TMS320C3X_MPYI, 0x015, {{ SD_adres, 0x007fffff } }},
|
||||
{ TMS320C3X_NEGB, 0x016, {{ SD_adres, 0x007fffff } }},
|
||||
{ TMS320C3X_NEGF, 0x017, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }},
|
||||
{ TMS320C3X_NEGI, 0x018, {{ SD_adres, 0x007fffff } }},
|
||||
{ TMS320C3X_NOP, 0x019, {{ nopcases, 0x007fffff } }},// possible update registers case
|
||||
{ TMS320C3X_NORM, 0x01a, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }},
|
||||
{ TMS320C3X_NOT, 0x01b, {{ SD_adres, 0x007fffff } }},
|
||||
{ TMS320C3X_POP, 0x01c, {{ D_regs, 0x001f0000 } }},
|
||||
{ TMS320C3X_POPF, 0x01d, {{ D_regs, 0x001f0000 } }},
|
||||
{ TMS320C3X_PUSH, 0x01e, {{ D_regs, 0x001f0000 } }},
|
||||
{ TMS320C3X_PUSHF, 0x01f, {{ D_regs, 0x001f0000 } }},
|
||||
{ TMS320C3X_OR, 0x020, {{ SD_adres, 0x007fffff } }},
|
||||
{ TMS320C3X_NONE, 0x021, {{ speedctrl, 0xffffffff } }},//multiple case, mask should be checked further
|
||||
{ TMS320C3X_RND, 0x022, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }},
|
||||
{ TMS320C3X_ROL, 0x023, {{ D_regs, 0x001f0000 } }},
|
||||
{ TMS320C3X_ROLC, 0x024, {{ D_regs, 0x001f0000 } }},
|
||||
{ TMS320C3X_ROR, 0x025, {{ D_regs, 0x001f0000 } }},
|
||||
{ TMS320C3X_RORC, 0x026, {{ D_regs, 0x001f0000 } }},
|
||||
{ TMS320C3X_RPTS, 0x027, {{ D_adres_1Op, 0x007fffff } }},
|
||||
{ TMS320C3X_STF, 0x028, {{ SD_adresRev, 0x007fffff } }},
|
||||
{ TMS320C3X_STFI, 0x029, {{ SD_adresRev, 0x007fffff } }},
|
||||
{ TMS320C3X_STI, 0x02a, {{ SD_adresRev, 0x007fffff } }},
|
||||
{ TMS320C3X_STII, 0x02b, {{ SD_adresRev, 0x007fffff } }},
|
||||
{ TMS320C3X_SIGI, 0x02c },
|
||||
{ TMS320C3X_SUBB, 0x02d, {{ SD_adres, 0x007fffff } }},
|
||||
{ TMS320C3X_SUBC, 0x02e, {{ SD_adres, 0x007fffff } }},
|
||||
{ TMS320C3X_SUBF, 0x02f, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }},
|
||||
{ TMS320C3X_SUBI, 0x030, {{ SD_adres, 0x007fffff } }},
|
||||
{ TMS320C3X_SUBRB, 0x031, {{ SD_adres, 0x007fffff } }},
|
||||
{ TMS320C3X_SUBRF, 0x032, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }},
|
||||
{ TMS320C3X_SUBRI, 0x033, {{ SD_adres, 0x007fffff } }},
|
||||
{ TMS320C3X_TSTB, 0x034, {{ SD_adres, 0x007fffff } }},
|
||||
{ TMS320C3X_XOR, 0x035, {{ SD_adres, 0x007fffff } }},
|
||||
{ TMS320C3X_IACK, 0x036 },
|
||||
{ TMS320C3X_null, 0x037 },{ TMS320C3X_null, 0x038 }, { TMS320C3X_null, 0x039 }, { TMS320C3X_null, 0x03a },// invalid
|
||||
{ TMS320C3X_null, 0x03b },{ TMS320C3X_null, 0x03c }, { TMS320C3X_null, 0x03d }, { TMS320C3X_null, 0x03e },// invalid
|
||||
{ TMS320C3X_null, 0x03f },// invalid
|
||||
// 3 operand insns
|
||||
{ TMS320C3X_ADDC3, 0x040, {{ SSD_src3, 0x007fffff } }},
|
||||
{ TMS320C3X_ADDF3, 0x041, {{ SSD_src3, 0x007fffff } }},
|
||||
{ TMS320C3X_ADDI3, 0x042, {{ SSD_src3, 0x007fffff } }},
|
||||
{ TMS320C3X_AND3, 0x043, {{ SSD_src3, 0x007fffff } }},
|
||||
{ TMS320C3X_ANDN3, 0x044, {{ SSD_src3, 0x007fffff } }},
|
||||
{ TMS320C3X_ASH3, 0x045, {{ SSD_src3, 0x007fffff } }},
|
||||
{ TMS320C3X_CMPF3, 0x046, {{ SD_src3_2op, 0x007fffff } }},
|
||||
{ TMS320C3X_CMPI3, 0x047, {{ SD_src3_2op, 0x007fffff } }},
|
||||
{ TMS320C3X_LSH3, 0x048, {{ SSD_src3, 0x007fffff } }},
|
||||
{ TMS320C3X_MPYF3, 0x049, {{ SSD_src3, 0x007fffff } }},
|
||||
{ TMS320C3X_MPYI3, 0x04a, {{ SSD_src3, 0x007fffff } }},
|
||||
{ TMS320C3X_OR3, 0x04b, {{ SSD_src3, 0x007fffff } }},
|
||||
{ TMS320C3X_SUBB3, 0x04c, {{ SSD_src3, 0x007fffff } }},
|
||||
{ TMS320C3X_SUBF3, 0x04d, {{ SSD_src3, 0x007fffff } }},
|
||||
{ TMS320C3X_SUBI3, 0x04e, {{ SSD_src3, 0x007fffff } }},
|
||||
{ TMS320C3X_TSTB3, 0x04f, {{ SD_src3_2op, 0x007fffff } }},
|
||||
{ TMS320C3X_XOR3, 0x050, {{ SSD_src3, 0x007fffff } }},
|
||||
{ TMS320C3X_null, 0x051 },{ TMS320C3X_null, 0x052 },{ TMS320C3X_null, 0x053 },{ TMS320C3X_null, 0x054 },// invalid
|
||||
{ TMS320C3X_null, 0x055 },{ TMS320C3X_null, 0x056 },{ TMS320C3X_null, 0x057 },{ TMS320C3X_null, 0x058 },// invalid
|
||||
{ TMS320C3X_null, 0x059 },{ TMS320C3X_null, 0x05a },{ TMS320C3X_null, 0x05b },{ TMS320C3X_null, 0x05c },// invalid
|
||||
{ TMS320C3X_null, 0x05d },{ TMS320C3X_null, 0x05e },{ TMS320C3X_null, 0x05f },{ TMS320C3X_null, 0x060 },// invalid
|
||||
{ TMS320C3X_null, 0x061 },{ TMS320C3X_null, 0x062 },{ TMS320C3X_null, 0x063 },{ TMS320C3X_null, 0x064 },// invalid
|
||||
{ TMS320C3X_null, 0x065 },{ TMS320C3X_null, 0x066 },{ TMS320C3X_null, 0x067 },{ TMS320C3X_null, 0x068 },// invalid
|
||||
{ TMS320C3X_null, 0x069 },{ TMS320C3X_null, 0x06a },{ TMS320C3X_null, 0x06b },{ TMS320C3X_null, 0x06c },// invalid
|
||||
{ TMS320C3X_null, 0x06d },{ TMS320C3X_null, 0x06e },{ TMS320C3X_null, 0x06f },{ TMS320C3X_null, 0x070 },// invalid
|
||||
{ TMS320C3X_null, 0x071 },{ TMS320C3X_null, 0x072 },{ TMS320C3X_null, 0x073 },{ TMS320C3X_null, 0x074 },// invalid
|
||||
{ TMS320C3X_null, 0x075 },{ TMS320C3X_null, 0x076 },{ TMS320C3X_null, 0x077 },{ TMS320C3X_null, 0x078 },// invalid
|
||||
{ TMS320C3X_null, 0x079 },{ TMS320C3X_null, 0x07a },{ TMS320C3X_null, 0x07b },{ TMS320C3X_null, 0x07c },// invalid
|
||||
{ TMS320C3X_null, 0x07d },{ TMS320C3X_null, 0x07e },{ TMS320C3X_null, 0x07f },// invalid
|
||||
//0x80 - 0x8f LDFcond
|
||||
{ TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f },
|
||||
{ TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f },
|
||||
{ TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f },
|
||||
{ TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f },
|
||||
//0x90 - 0x9f LDFcond
|
||||
{ TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f },
|
||||
{ TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f },
|
||||
{ TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f },
|
||||
{ TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, { TMS320C3X_MV_IDX, 0x09f },
|
||||
{ TMS320C3X_LDFcond, 0x09f, {{ cond, 0x0f800000 }, { SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }},
|
||||
//0xa0 - 0xaf LDIcond
|
||||
{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },
|
||||
{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },
|
||||
{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },
|
||||
{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },
|
||||
//0xb0 - 0xbf LDIcond
|
||||
{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },
|
||||
{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },
|
||||
{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },
|
||||
{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },
|
||||
{ TMS320C3X_LDIcond, 0x0bf, {{ cond, 0x0f800000 }, { SD_adres, 0x007fffff } }},
|
||||
//0xc0 - 0xc1 BR
|
||||
{ TMS320C3X_MV_IDX, 0x0c1 },
|
||||
{ TMS320C3X_BR, 0x0c1, {{ D_adr24, 0x00ffffff } }},
|
||||
//0xc2 - 0xc3 BR
|
||||
{ TMS320C3X_MV_IDX, 0x0c3 },
|
||||
{ TMS320C3X_BRD, 0x0c3, {{ DBranch, 0x00000000 }, { D_adr24, 0x00ffffff } }},
|
||||
//0xc4 - 0xc5 CALL
|
||||
{ TMS320C3X_MV_IDX, 0x0c5 },
|
||||
{ TMS320C3X_CALL, 0x0c5, {{ D_adr24, 0x00ffffff } }},
|
||||
{ TMS320C3X_null, 0x0c6 },// invalid
|
||||
{ TMS320C3X_null, 0x0c7 },// invalid
|
||||
//0xc8 - 0xc9 RPTB
|
||||
{ TMS320C3X_MV_IDX, 0x0c9 },
|
||||
{ TMS320C3X_RPTB, 0x0c9, {{ D_adr24, 0x00ffffff } }},
|
||||
{ TMS320C3X_null, 0x0ca },// invalid
|
||||
{ TMS320C3X_null, 0x0cb },// invalid
|
||||
{ TMS320C3X_SWI, 0x0cc },
|
||||
{ TMS320C3X_null, 0x0cd },// invalid
|
||||
{ TMS320C3X_null, 0x0ce },// invalid
|
||||
{ TMS320C3X_null, 0x0cf },// invalid
|
||||
{ TMS320C3X_Bcond, 0x0d0, {{ cond, 0x003f0000 }, { D_regs, 0x0000ffff } }},
|
||||
{ TMS320C3X_null, 0x0d1 },// invalid
|
||||
{ TMS320C3X_null, 0x0d2 },// invalid
|
||||
{ TMS320C3X_null, 0x0d3 },// invalid
|
||||
{ TMS320C3X_Bcond, 0x0d4, {{ cond, 0x003f0000 }, { D_PC_Displ, 0x0020ffff } }},
|
||||
{ TMS320C3X_null, 0x0d5 },// invalid
|
||||
{ TMS320C3X_null, 0x0d6 },// invalid
|
||||
{ TMS320C3X_null, 0x0d7 },// invalid
|
||||
//0xd8 - 0xdb DBcond
|
||||
{ TMS320C3X_MV_IDX, 0x0db },
|
||||
{ TMS320C3X_MV_IDX, 0x0db },
|
||||
{ TMS320C3X_MV_IDX, 0x0db },
|
||||
{ TMS320C3X_DBcond, 0x0db, {{ cond, 0x003f0000 }, { S_ar, 0x01c00000 }, { D_regs, 0x0000ffff } }},
|
||||
//0xdc - 0xdf DBcond
|
||||
{ TMS320C3X_MV_IDX, 0x0df },
|
||||
{ TMS320C3X_MV_IDX, 0x0df },
|
||||
{ TMS320C3X_MV_IDX, 0x0df },
|
||||
{ TMS320C3X_DBcond, 0x0df, {{ cond, 0x003f0000 }, { S_ar, 0x01c00000 }, { D_PC_Displ, 0x0020ffff } }},
|
||||
{ TMS320C3X_CALLcond, 0x0e0, {{ cond, 0x001f0000 }, { D_regs, 0x0000ffff } }},
|
||||
{ TMS320C3X_null, 0x0e1 },// invalid
|
||||
{ TMS320C3X_null, 0x0e2 },// invalid
|
||||
{ TMS320C3X_null, 0x0e3 },// invalid
|
||||
{ TMS320C3X_CALLcond, 0x0e4, {{ cond, 0x001f0000 }, { D_PC_Displ, 0x0000ffff } }},
|
||||
{ TMS320C3X_null, 0x0e5 },// invalid
|
||||
{ TMS320C3X_null, 0x0e6 },// invalid
|
||||
{ TMS320C3X_null, 0x0e7 },// invalid
|
||||
{ TMS320C3X_TRAPcond, 0x0e8, {{ cond, 0x001f0000 }, { imm8, 0x0000001f } }},
|
||||
{ TMS320C3X_null, 0x0e9 },// invalid
|
||||
{ TMS320C3X_null, 0x0ea },// invalid
|
||||
{ TMS320C3X_null, 0x0eb },// invalid
|
||||
{ TMS320C3X_null, 0x0ec },// invalid
|
||||
{ TMS320C3X_null, 0x0ed },// invalid
|
||||
{ TMS320C3X_null, 0x0ee },// invalid
|
||||
{ TMS320C3X_null, 0x0ef },// invalid
|
||||
{ TMS320C3X_RETIcond, 0x0f0, {{ cond, 0x001f0000 } }},
|
||||
{ TMS320C3X_RETScond, 0x0f1, {{ cond, 0x001f0000 } }},
|
||||
{ TMS320C3X_null, 0x0f2 }, { TMS320C3X_null, 0x0f3 }, { TMS320C3X_null, 0x0f4 }, { TMS320C3X_null, 0x0f5 },// invalid
|
||||
{ TMS320C3X_null, 0x0f6 }, { TMS320C3X_null, 0x0f7 }, { TMS320C3X_null, 0x0f8 }, { TMS320C3X_null, 0x0f9 },// invalid
|
||||
{ TMS320C3X_null, 0x0fa }, { TMS320C3X_null, 0x0fb }, { TMS320C3X_null, 0x0fc }, { TMS320C3X_null, 0x0fd },// invalid
|
||||
{ TMS320C3X_null, 0x0fe }, { TMS320C3X_null, 0x0ff },// invalid
|
||||
{ TMS320C3X_MV_IDX, 0x101 },
|
||||
{ TMS320C3X_MPYF3, 0x101, {{ S_indir3, 0x0000ff00 }, { S_indir3, 0x000000ff }, { D_R, 0x00800000 }},
|
||||
TMS320C3X_ADDF3, {{ S_R, 0x00380000 }, { S_R, 0x00070000 }, { D_R2, 0x00400000 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x103 },
|
||||
{ TMS320C3X_MPYF3, 0x103, {{ S_indir3, 0x0000ff00 }, { S_R, 0x00380000 }, { D_R, 0x00800000 }},
|
||||
TMS320C3X_ADDF3, {{ S_indir3, 0x000000ff }, { S_R, 0x00070000 }, { D_R2, 0x00400000 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x105 },
|
||||
{ TMS320C3X_MPYF3, 0x105, {{ S_R, 0x00380000 }, { S_R, 0x00070000 }, { D_R, 0x00800000 }},
|
||||
TMS320C3X_ADDF3, {{ S_indir3, 0x0000ff00 }, { S_indir3, 0x000000ff }, { D_R2, 0x00400000 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x107 },
|
||||
{ TMS320C3X_MPYF3, 0x107, {{ S_indir3, 0x0000ff00 }, { S_R, 0x00380000 }, { D_R, 0x00800000 }},
|
||||
TMS320C3X_ADDF3, {{ S_R, 0x00070000 }, { S_indir3, 0x000000ff }, { D_R2, 0x00400000 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x109 },
|
||||
{ TMS320C3X_MPYF3, 0x109, {{ S_indir3, 0x0000ff00 }, { S_indir3, 0x000000ff }, { D_R, 0x00800000 }},
|
||||
TMS320C3X_SUBF3, {{ S_R, 0x00380000 }, { S_R, 0x00070000 }, { D_R2, 0x00400000 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x10b },
|
||||
{ TMS320C3X_MPYF3, 0x10b, {{ S_indir3, 0x0000ff00 }, { S_R, 0x00380000 }, { D_R, 0x00800000 }},
|
||||
TMS320C3X_SUBF3, {{ S_indir3, 0x000000ff }, { S_R, 0x00070000 }, { D_R2, 0x00400000 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x10d },
|
||||
{ TMS320C3X_MPYF3, 0x10d, {{ S_R, 0x00380000 }, { S_R, 0x00070000 }, { D_R, 0x00800000 }},
|
||||
TMS320C3X_SUBF3, {{ S_indir3, 0x0000ff00 }, { S_indir3, 0x000000ff }, { D_R2, 0x00400000 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x10f },
|
||||
{ TMS320C3X_MPYF3, 0x10f, {{ S_indir3, 0x0000ff00 }, { S_R, 0x00380000 }, { D_R, 0x00800000 }},
|
||||
TMS320C3X_SUBF3, {{ S_R, 0x00070000 }, { S_indir3, 0x000000ff }, { D_R2, 0x00400000 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x111 },
|
||||
{ TMS320C3X_MPYI3, 0x111, {{ S_indir3, 0x0000ff00 }, { S_indir3, 0x000000ff }, { D_R, 0x00800000 }},
|
||||
TMS320C3X_ADDI3, {{ S_R, 0x00380000 }, { S_R, 0x00070000 }, { D_R2, 0x00400000 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x113 },
|
||||
{ TMS320C3X_MPYI3, 0x113, {{ S_indir3, 0x0000ff00 }, { S_R, 0x00380000 }, { D_R, 0x00800000 }},
|
||||
TMS320C3X_ADDI3, {{ S_indir3, 0x000000ff }, { S_R, 0x00070000 }, { D_R2, 0x00400000 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x115 },
|
||||
{ TMS320C3X_MPYI3, 0x115, {{ S_R, 0x00380000 }, { S_R, 0x00070000 }, { D_R, 0x00800000 }},
|
||||
TMS320C3X_ADDI3, {{ S_indir3, 0x0000ff00 }, { S_indir3, 0x000000ff }, { D_R2, 0x00400000 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x117 },
|
||||
{ TMS320C3X_MPYI3, 0x117, {{ S_indir3, 0x0000ff00 }, { S_R, 0x00380000 }, { D_R, 0x00800000 }},
|
||||
TMS320C3X_ADDI3, {{ S_R, 0x00070000 }, { S_indir3, 0x000000ff }, { D_R2, 0x00400000 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x119 },
|
||||
{ TMS320C3X_MPYI3, 0x119, {{ S_indir3, 0x0000ff00 }, { S_indir3, 0x000000ff }, { D_R, 0x00800000 }},
|
||||
TMS320C3X_SUBI3, {{ S_R, 0x00380000 }, { S_R, 0x00070000 }, { D_R2, 0x00400000 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x11b },
|
||||
{ TMS320C3X_MPYI3, 0x11b, {{ S_indir3, 0x0000ff00 }, { S_R, 0x00380000 }, { D_R, 0x00800000 }},
|
||||
TMS320C3X_SUBI3, {{ S_indir3, 0x000000ff }, { S_R, 0x00070000 }, { D_R2, 0x00400000 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x11d },
|
||||
{ TMS320C3X_MPYI3, 0x11d, {{ S_R, 0x00380000 }, { S_R, 0x00070000 }, { D_R, 0x00800000 }},
|
||||
TMS320C3X_SUBI3, {{ S_indir3, 0x0000ff00 }, { S_indir3, 0x000000ff }, { D_R2, 0x00400000 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x11f },
|
||||
{ TMS320C3X_MPYI3, 0x11f, {{ S_indir3, 0x0000ff00 }, { S_R, 0x00380000 }, { D_R, 0x00800000 }},
|
||||
TMS320C3X_SUBI3, {{ S_R, 0x00070000 }, { S_indir3, 0x000000ff }, { D_R2, 0x00400000 }}},
|
||||
|
||||
{ TMS320C3X_null, 0x120 }, { TMS320C3X_null, 0x121 }, { TMS320C3X_null, 0x122 }, { TMS320C3X_null, 0x123 },// invalid
|
||||
{ TMS320C3X_null, 0x124 }, { TMS320C3X_null, 0x125 }, { TMS320C3X_null, 0x126 }, { TMS320C3X_null, 0x127 },// invalid
|
||||
{ TMS320C3X_null, 0x128 }, { TMS320C3X_null, 0x129 }, { TMS320C3X_null, 0x12a }, { TMS320C3X_null, 0x12b },// invalid
|
||||
{ TMS320C3X_null, 0x12c }, { TMS320C3X_null, 0x12d }, { TMS320C3X_null, 0x12e }, { TMS320C3X_null, 0x12f },// invalid
|
||||
{ TMS320C3X_null, 0x130 }, { TMS320C3X_null, 0x131 }, { TMS320C3X_null, 0x132 }, { TMS320C3X_null, 0x133 },// invalid
|
||||
{ TMS320C3X_null, 0x134 }, { TMS320C3X_null, 0x135 }, { TMS320C3X_null, 0x136 }, { TMS320C3X_null, 0x137 },// invalid
|
||||
{ TMS320C3X_null, 0x138 }, { TMS320C3X_null, 0x139 }, { TMS320C3X_null, 0x13a }, { TMS320C3X_null, 0x13b },// invalid
|
||||
{ TMS320C3X_null, 0x13c }, { TMS320C3X_null, 0x13d }, { TMS320C3X_null, 0x13e }, { TMS320C3X_null, 0x13f },// invalid
|
||||
{ TMS320C3X_null, 0x140 }, { TMS320C3X_null, 0x141 }, { TMS320C3X_null, 0x142 }, { TMS320C3X_null, 0x143 },// invalid
|
||||
{ TMS320C3X_null, 0x144 }, { TMS320C3X_null, 0x145 }, { TMS320C3X_null, 0x146 }, { TMS320C3X_null, 0x147 },// invalid
|
||||
{ TMS320C3X_null, 0x148 }, { TMS320C3X_null, 0x149 }, { TMS320C3X_null, 0x14a }, { TMS320C3X_null, 0x14b },// invalid
|
||||
{ TMS320C3X_null, 0x14c }, { TMS320C3X_null, 0x14d }, { TMS320C3X_null, 0x14e }, { TMS320C3X_null, 0x14f },// invalid
|
||||
{ TMS320C3X_null, 0x150 }, { TMS320C3X_null, 0x151 }, { TMS320C3X_null, 0x152 }, { TMS320C3X_null, 0x153 },// invalid
|
||||
{ TMS320C3X_null, 0x154 }, { TMS320C3X_null, 0x155 }, { TMS320C3X_null, 0x156 }, { TMS320C3X_null, 0x157 },// invalid
|
||||
{ TMS320C3X_null, 0x158 }, { TMS320C3X_null, 0x159 }, { TMS320C3X_null, 0x15a }, { TMS320C3X_null, 0x15b },// invalid
|
||||
{ TMS320C3X_null, 0x15c }, { TMS320C3X_null, 0x15d }, { TMS320C3X_null, 0x15e }, { TMS320C3X_null, 0x15f },// invalid
|
||||
{ TMS320C3X_null, 0x160 }, { TMS320C3X_null, 0x161 }, { TMS320C3X_null, 0x162 }, { TMS320C3X_null, 0x163 },// invalid
|
||||
{ TMS320C3X_null, 0x164 }, { TMS320C3X_null, 0x165 }, { TMS320C3X_null, 0x166 }, { TMS320C3X_null, 0x167 },// invalid
|
||||
{ TMS320C3X_null, 0x168 }, { TMS320C3X_null, 0x169 }, { TMS320C3X_null, 0x16a }, { TMS320C3X_null, 0x16b },// invalid
|
||||
{ TMS320C3X_null, 0x16c }, { TMS320C3X_null, 0x16d }, { TMS320C3X_null, 0x16e }, { TMS320C3X_null, 0x16f },// invalid
|
||||
{ TMS320C3X_null, 0x170 }, { TMS320C3X_null, 0x171 }, { TMS320C3X_null, 0x172 }, { TMS320C3X_null, 0x123 },// invalid
|
||||
{ TMS320C3X_null, 0x174 }, { TMS320C3X_null, 0x175 }, { TMS320C3X_null, 0x176 }, { TMS320C3X_null, 0x127 },// invalid
|
||||
{ TMS320C3X_null, 0x178 }, { TMS320C3X_null, 0x179 }, { TMS320C3X_null, 0x17a }, { TMS320C3X_null, 0x12b },// invalid
|
||||
{ TMS320C3X_null, 0x17c }, { TMS320C3X_null, 0x17d }, { TMS320C3X_null, 0x17e }, { TMS320C3X_null, 0x12f },// invalid
|
||||
|
||||
{ TMS320C3X_MV_IDX, 0x183 },
|
||||
{ TMS320C3X_MV_IDX, 0x183 },
|
||||
{ TMS320C3X_MV_IDX, 0x183 },
|
||||
{ TMS320C3X_STF, 0x183, {{ S_R, 0x01c00000 }, { D_indir3, 0x000000ff }},
|
||||
TMS320C3X_STF, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x187 },
|
||||
{ TMS320C3X_MV_IDX, 0x187 },
|
||||
{ TMS320C3X_MV_IDX, 0x187 },
|
||||
{ TMS320C3X_STI, 0x187, {{ S_R, 0x01c00000 }, { D_indir3, 0x000000ff }},
|
||||
TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x18b },
|
||||
{ TMS320C3X_MV_IDX, 0x18b },
|
||||
{ TMS320C3X_MV_IDX, 0x18b },
|
||||
{ TMS320C3X_LDF, 0x18b, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }},
|
||||
TMS320C3X_LDF, {{ S_indir3, 0x0000ff00 }, { D_R, 0x00380000 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x18f },
|
||||
{ TMS320C3X_MV_IDX, 0x18f },
|
||||
{ TMS320C3X_MV_IDX, 0x18f },
|
||||
{ TMS320C3X_LDI, 0x18f, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }},
|
||||
TMS320C3X_LDI, {{ S_indir3, 0x0000ff00 }, { D_R, 0x00380000 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x193 },
|
||||
{ TMS320C3X_MV_IDX, 0x193 },
|
||||
{ TMS320C3X_MV_IDX, 0x193 },
|
||||
{ TMS320C3X_ABSF, 0x193, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }},
|
||||
TMS320C3X_STF, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x197 },
|
||||
{ TMS320C3X_MV_IDX, 0x197 },
|
||||
{ TMS320C3X_MV_IDX, 0x197 },
|
||||
{ TMS320C3X_ABSI, 0x197, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }},
|
||||
TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x19b },
|
||||
{ TMS320C3X_MV_IDX, 0x19b },
|
||||
{ TMS320C3X_MV_IDX, 0x19b },
|
||||
{ TMS320C3X_ADDF3, 0x19b, {{ S_indir3, 0x000000ff }, { S_R, 0x00380000 }, { D_R, 0x01c00000 }},
|
||||
TMS320C3X_STF, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x19f },
|
||||
{ TMS320C3X_MV_IDX, 0x19f },
|
||||
{ TMS320C3X_MV_IDX, 0x19f },
|
||||
{ TMS320C3X_ADDI3, 0x19f, {{ S_indir3, 0x000000ff }, { S_R, 0x00380000 }, { D_R, 0x01c00000 }},
|
||||
TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x1a3 },
|
||||
{ TMS320C3X_MV_IDX, 0x1a3 },
|
||||
{ TMS320C3X_MV_IDX, 0x1a3 },
|
||||
{ TMS320C3X_AND3, 0x1a3, {{ S_indir3, 0x000000ff }, { S_R, 0x00380000 }, { D_R, 0x01c00000 }},
|
||||
TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x1a7 },
|
||||
{ TMS320C3X_MV_IDX, 0x1a7 },
|
||||
{ TMS320C3X_MV_IDX, 0x1a7 },
|
||||
{ TMS320C3X_ASH3, 0x1a7, {{ S_R, 0x00380000 }, { S_indir3, 0x000000ff }, { D_R, 0x01c00000 }},
|
||||
TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x1ab },
|
||||
{ TMS320C3X_MV_IDX, 0x1ab },
|
||||
{ TMS320C3X_MV_IDX, 0x1ab },
|
||||
{ TMS320C3X_FIX, 0x1ab, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }},
|
||||
TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x1af },
|
||||
{ TMS320C3X_MV_IDX, 0x1af },
|
||||
{ TMS320C3X_MV_IDX, 0x1af },
|
||||
{ TMS320C3X_FLOAT, 0x1af, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }},
|
||||
TMS320C3X_STF, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x1b3 },
|
||||
{ TMS320C3X_MV_IDX, 0x1b3 },
|
||||
{ TMS320C3X_MV_IDX, 0x1b3 },
|
||||
{ TMS320C3X_LDF, 0x1b3, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }},
|
||||
TMS320C3X_STF, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x1b7 },
|
||||
{ TMS320C3X_MV_IDX, 0x1b7 },
|
||||
{ TMS320C3X_MV_IDX, 0x1b7 },
|
||||
{ TMS320C3X_LDI, 0x1b7, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }},
|
||||
TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x1bb },
|
||||
{ TMS320C3X_MV_IDX, 0x1bb },
|
||||
{ TMS320C3X_MV_IDX, 0x1bb },
|
||||
{ TMS320C3X_LSH3, 0x1bb, {{ S_R, 0x00380000 }, { S_indir3, 0x000000ff }, { D_R, 0x01c00000 }},
|
||||
TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x1bf },
|
||||
{ TMS320C3X_MV_IDX, 0x1bf },
|
||||
{ TMS320C3X_MV_IDX, 0x1bf },
|
||||
{ TMS320C3X_MPYF3, 0x1bf, {{ S_indir3, 0x000000ff }, { S_R, 0x00380000 }, { D_R, 0x01c00000 }},
|
||||
TMS320C3X_STF, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x1c3 },
|
||||
{ TMS320C3X_MV_IDX, 0x1c3 },
|
||||
{ TMS320C3X_MV_IDX, 0x1c3 },
|
||||
{ TMS320C3X_MPYI3, 0x1c3, {{ S_indir3, 0x000000ff }, { S_R, 0x00380000 }, { D_R, 0x01c00000 }},
|
||||
TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x1c7 },
|
||||
{ TMS320C3X_MV_IDX, 0x1c7 },
|
||||
{ TMS320C3X_MV_IDX, 0x1c7 },
|
||||
{ TMS320C3X_NEGF, 0x1c7, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }},
|
||||
TMS320C3X_STF, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x1cb },
|
||||
{ TMS320C3X_MV_IDX, 0x1cb },
|
||||
{ TMS320C3X_MV_IDX, 0x1cb },
|
||||
{ TMS320C3X_NEGI, 0x1cb, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }},
|
||||
TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x1cf },
|
||||
{ TMS320C3X_MV_IDX, 0x1cf },
|
||||
{ TMS320C3X_MV_IDX, 0x1cf },
|
||||
{ TMS320C3X_NOT, 0x1cf, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }},
|
||||
TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x1d3 },
|
||||
{ TMS320C3X_MV_IDX, 0x1d3 },
|
||||
{ TMS320C3X_MV_IDX, 0x1d3 },
|
||||
{ TMS320C3X_OR3, 0x1d3, {{ S_indir3, 0x000000ff }, { S_R, 0x00380000 }, { D_R, 0x01c00000 }},
|
||||
TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x1d7 },
|
||||
{ TMS320C3X_MV_IDX, 0x1d7 },
|
||||
{ TMS320C3X_MV_IDX, 0x1d7 },
|
||||
{ TMS320C3X_SUBF3, 0x1d7, {{ S_R, 0x00380000 }, { S_indir3, 0x000000ff }, { D_R, 0x01c00000 }},
|
||||
TMS320C3X_STF, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x1db },
|
||||
{ TMS320C3X_MV_IDX, 0x1db },
|
||||
{ TMS320C3X_MV_IDX, 0x1db },
|
||||
{ TMS320C3X_SUBI3, 0x1db, {{ S_R, 0x00380000 }, { S_indir3, 0x000000ff }, { D_R, 0x01c00000 }},
|
||||
TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}},
|
||||
{ TMS320C3X_MV_IDX, 0x1df },
|
||||
{ TMS320C3X_MV_IDX, 0x1df },
|
||||
{ TMS320C3X_MV_IDX, 0x1df },
|
||||
{ TMS320C3X_XOR3, 0x1df, {{ S_indir3, 0x000000ff }, { S_R, 0x00380000 }, { D_R, 0x01c00000 }},
|
||||
TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}},
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
int tms320c3x_t::run_functions(ctx_t &ctx, int value, int entry, int start, int end)
|
||||
{
|
||||
const opcode_t &opcode = table[entry];
|
||||
for ( int j = start; j <= end; j++ )
|
||||
{
|
||||
const funcdesc_t &fd = opcode.funcs[j];
|
||||
if ( fd.func == NULL )
|
||||
break;
|
||||
if ( !fd.func(ctx, (value & fd.mask) >> fd.shift) )
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
int tms320c3x_t::run_functions2(ctx_t &ctx, int value, int entry, int start, int end)
|
||||
{
|
||||
const opcode_t &opcode = table[entry];
|
||||
for ( int j = start; j <= end; j++ )
|
||||
{
|
||||
const funcdesc_t &fd = opcode.funcs2[j];
|
||||
if ( fd.func == NULL )
|
||||
break;
|
||||
if ( !fd.func(ctx, (value & fd.mask) >> fd.shift) )
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
int tms320c3x_t::ana(insn_t *insn)
|
||||
{
|
||||
ctx_t ctx(insn);
|
||||
|
||||
int value = get_wide_byte(insn->ea);
|
||||
insn->size++;
|
||||
|
||||
int idx = (value >> 23) & 0x1ff;
|
||||
|
||||
// check for known opcode
|
||||
insn->itype = idx >= table.size ? TMS320C3X_null : table[idx].itype;
|
||||
|
||||
if ( insn->itype == TMS320C3X_MV_IDX ) // for this opcode use the next table line
|
||||
insn->itype = table[ idx = table[idx].insnidx ].itype;
|
||||
|
||||
if ( insn->itype != TMS320C3X_null )
|
||||
{
|
||||
if ( !run_functions(ctx, value, idx, 0, FUNCS_COUNT - 1) )
|
||||
return 0;
|
||||
|
||||
if ( table[idx].ispar )
|
||||
{
|
||||
ctx.op++;
|
||||
insn->itype2 = table[ idx = table[idx].insnidx ].itype2; // second (parallel) insn opcode
|
||||
insn->i2op = ctx.op->n; // location for operand of the second insn
|
||||
|
||||
if ( !run_functions2(ctx, value, idx, 0, FUNCS_COUNT - 1) )
|
||||
return 0;
|
||||
}
|
||||
return insn->size; // length is always 1
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void tms320c3x_t::gen_masks(void)
|
||||
{
|
||||
for ( int i = 0; i < table.size; i++ )
|
||||
{
|
||||
table[i].ispar = (table[i].insnidx & 0x100) != 0;
|
||||
for ( int j = 0; j < FUNCS_COUNT; j++ )
|
||||
{
|
||||
if ( table[i].funcs[j].func != NULL )
|
||||
{
|
||||
for ( int b = 0; b < 32; b++ )
|
||||
{
|
||||
if ( table[i].funcs[j].mask & (1 << b) )
|
||||
break;
|
||||
else
|
||||
table[i].funcs[j].shift++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( table[i].insnidx & 0x100 )
|
||||
for ( int j = 0; j < FUNCS_COUNT; j++ )
|
||||
{
|
||||
if ( table[i].funcs2[j].func != NULL )
|
||||
{
|
||||
for ( int b = 0; b < 32; b++ )
|
||||
{
|
||||
if ( table[i].funcs2[j].mask & (1 << b) )
|
||||
break;
|
||||
else
|
||||
table[i].funcs2[j].shift++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void tms320c3x_t::init_analyzer(void)
|
||||
{
|
||||
table.create(table_pattern, qnumber(table_pattern));
|
||||
gen_masks();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void tms320c3_table_t::create(const opcode_t src_table[], int src_table_size)
|
||||
{
|
||||
size = src_table_size;
|
||||
entries = qalloc_array<opcode_t>(size);
|
||||
memcpy(entries, src_table, sizeof(opcode_t) * size);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
tms320c3_table_t::~tms320c3_table_t()
|
||||
{
|
||||
qfree(entries);
|
||||
entries = nullptr;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
opcode_t &tms320c3_table_t::operator[](size_t i)
|
||||
{
|
||||
return entries[i];
|
||||
}
|
||||
374
idasdk75/module/tms320c3/emu.cpp
Normal file
374
idasdk75/module/tms320c3/emu.cpp
Normal file
@@ -0,0 +1,374 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tms320c3x.hpp"
|
||||
#include <segregs.hpp>
|
||||
#include <frame.hpp>
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
ea_t calc_code_mem(const insn_t &insn, const op_t &x)
|
||||
{
|
||||
return to_ea(insn.cs, x.addr);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
ea_t calc_data_mem(const insn_t &insn, const op_t &x)
|
||||
{
|
||||
sel_t dpage = get_sreg(insn.ea, dp);
|
||||
if ( dpage == BADSEL )
|
||||
return BADSEL;
|
||||
return ((dpage & 0xFF) << 16) | (x.addr);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static void process_imm(const insn_t &insn, const op_t &x, flags_t F)
|
||||
{
|
||||
set_immd(insn.ea);
|
||||
if ( !is_defarg(F, x.n) )
|
||||
op_num(insn.ea, x.n);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void tms320c3x_t::handle_operand(const insn_t &insn, const op_t &x, flags_t F, bool use)
|
||||
{
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_reg:
|
||||
return;
|
||||
|
||||
case o_near:
|
||||
if ( insn.itype != TMS320C3X_RPTB )
|
||||
{
|
||||
cref_t ftype = fl_JN;
|
||||
ea_t ea = calc_code_mem(insn, x);
|
||||
if ( has_insn_feature(insn.itype, CF_CALL) )
|
||||
{
|
||||
if ( !func_does_return(ea) )
|
||||
flow = false;
|
||||
ftype = fl_CN;
|
||||
}
|
||||
insn.add_cref(ea, x.offb, ftype);
|
||||
}
|
||||
else // evaluate RPTB loops as dref
|
||||
{
|
||||
insn.add_dref(calc_code_mem(insn, x), x.offb, dr_I);
|
||||
}
|
||||
break;
|
||||
|
||||
case o_imm:
|
||||
QASSERT(10112, use);
|
||||
process_imm(insn, x, F);
|
||||
if ( op_adds_xrefs(F, x.n) )
|
||||
insn.add_off_drefs(x, dr_O, 0);
|
||||
break;
|
||||
|
||||
case o_mem:
|
||||
{
|
||||
ea_t ea = calc_data_mem(insn, x);
|
||||
if ( ea != BADADDR )
|
||||
{
|
||||
insn.add_dref(ea, x.offb, use ? dr_R : dr_W);
|
||||
insn.create_op_data(ea, x);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case o_phrase:
|
||||
break;
|
||||
|
||||
case o_displ:
|
||||
set_immd(insn.ea);
|
||||
break;
|
||||
|
||||
default:
|
||||
if ( x.type == o_void )
|
||||
{
|
||||
if ( insn.itype == TMS320C3X_ABSF )
|
||||
break;
|
||||
if ( insn.itype == TMS320C3X_ABSI )
|
||||
break;
|
||||
}
|
||||
warning("interr: emu2 address:%a operand:%d type:%d", insn.ea, x.n, x.type);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// is the previous instruction unconditional delayed jump ?
|
||||
//
|
||||
// The following array shows all delayed instructions (xxx[D])
|
||||
// who are required to always stop.
|
||||
//
|
||||
// BRANCH INSTRUCTIONS
|
||||
|
||||
// TMS320C3X_BRD, // Branch unconditionally (delayed) 0110 0001 xxxx xxxx xxxx xxxx xxxx xxxx
|
||||
// TMS320C3X_Bcond, // Branch conditionally 0110 10x0 001x xxxx xxxx xxxx xxxx xxxx
|
||||
// TMS320C3X_DBcond, // Decrement and branch conditionally 0110 11xx xx1x xxxx xxxx xxxx xxxx xxxx
|
||||
|
||||
|
||||
static bool delayed_stop(const insn_t &insn, flags_t F)
|
||||
{
|
||||
if ( !is_flow(F) )
|
||||
return false; // Does the previous instruction exist and pass execution flow to the current byte?
|
||||
|
||||
if ( insn.size == 0 )
|
||||
return false;
|
||||
|
||||
int sub = 3; // backward offset to skip 3 previous 1-word instruction
|
||||
|
||||
ea_t ea = insn.ea - sub;
|
||||
|
||||
if ( is_code(get_flags(ea)) ) // Does flag denote start of an instruction?
|
||||
{
|
||||
int code = get_wide_byte(ea); // get the instruction word
|
||||
|
||||
if ( (code & 0xff000000) == 0x61000000 )
|
||||
return true; // Branch unconditionally delayed 0110 0001 xxxx xxxx xxxx xxxx xxxx xxxx
|
||||
if ( (code & 0xfdff0000) == 0x68200000 )
|
||||
return true; // Branch conditionally delayed (with U cond ) 0110 10x0 001x xxxx xxxx xxxx xxxx xxxx
|
||||
//if ( (code & 0xfc3f0000) == 0x6c200000) return true; // Decrement and branch conditionally (with U cond ) 0110 11xx xx1x xxxx xxxx xxxx xxxx xxxx
|
||||
// removed since it's only use for loop
|
||||
// and loops don't leave functions
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// if previous instruction is delayed jump return jump adr, else -1
|
||||
static ea_t GetDelayedBranchAdr(const insn_t &insn, flags_t F)
|
||||
{
|
||||
int16 disp;
|
||||
|
||||
if ( !is_flow(F) )
|
||||
return BADADDR; // Does the previous instruction exist and pass execution flow to the current byte?
|
||||
|
||||
if ( insn.size == 0 )
|
||||
return BADADDR;
|
||||
|
||||
int sub = 3; // backward offset to skip 3 previous 1-word instruction
|
||||
|
||||
ea_t ea = insn.ea - sub;
|
||||
|
||||
if ( is_code(get_flags(ea)) ) // Does flag denote start of an instruction?
|
||||
{
|
||||
int code = get_wide_byte(ea); // get the instruction word
|
||||
|
||||
if ( (code & 0xff000000) == 0x61000000 ) // Branch unconditionally (delayed )
|
||||
return code & 0xffffff;
|
||||
|
||||
if ( (code & 0xffe00000) == 0x6a200000 ) // BranchD conditionally
|
||||
{
|
||||
disp = code & 0xffff;
|
||||
return insn.ea + disp;
|
||||
}
|
||||
|
||||
if ( (code & 0xfe200000) == 0x6e200000 ) // DecrementD and branch conditionally
|
||||
{
|
||||
disp = code & 0xffff;
|
||||
return insn.ea + disp;
|
||||
}
|
||||
}
|
||||
return BADADDR;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool is_basic_block_end(const insn_t &insn)
|
||||
{
|
||||
flags_t F = get_flags(insn.ea);
|
||||
if ( delayed_stop(insn, F) )
|
||||
return true;
|
||||
return !is_flow(get_flags(insn.ea+insn.size));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static bool add_stkpnt(const insn_t &insn, sval_t delta)
|
||||
{
|
||||
func_t *pfn = get_func(insn.ea);
|
||||
if ( pfn == NULL )
|
||||
return false;
|
||||
|
||||
return add_auto_stkpnt(pfn, insn.ea+insn.size, delta);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static void trace_sp(const insn_t &insn)
|
||||
{
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case TMS320C3X_RETIcond:
|
||||
add_stkpnt(insn, -2);
|
||||
break;
|
||||
case TMS320C3X_RETScond:
|
||||
add_stkpnt(insn, -1);
|
||||
break;
|
||||
case TMS320C3X_POP:
|
||||
case TMS320C3X_POPF:
|
||||
add_stkpnt(insn, -1);
|
||||
break;
|
||||
case TMS320C3X_PUSH:
|
||||
case TMS320C3X_PUSHF:
|
||||
add_stkpnt(insn, 1);
|
||||
break;
|
||||
case TMS320C3X_SUBI:
|
||||
if ( insn.Op2.is_reg(sp) && insn.Op1.type == o_imm )
|
||||
add_stkpnt(insn, -insn.Op1.value);
|
||||
break;
|
||||
case TMS320C3X_ADDI:
|
||||
if ( insn.Op2.is_reg(sp) && insn.Op1.type == o_imm )
|
||||
add_stkpnt(insn, insn.Op1.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int tms320c3x_t::emu(const insn_t &insn)
|
||||
{
|
||||
uint32 feature = insn.get_canon_feature(ph);
|
||||
flow = (feature & CF_STOP) == 0;
|
||||
|
||||
flags_t F = get_flags(insn.ea);
|
||||
if ( (insn.auxpref & DBrFlag) == 0 ) // no need to process operands of delayed branches
|
||||
// branch address will be processed 3 instructions later
|
||||
{
|
||||
if ( feature & CF_USE1 ) handle_operand(insn, insn.Op1, F, true);
|
||||
if ( feature & CF_USE2 ) handle_operand(insn, insn.Op2, F, true);
|
||||
if ( feature & CF_USE3 ) handle_operand(insn, insn.Op3, F, true);
|
||||
|
||||
if ( feature & CF_CHG1 ) handle_operand(insn, insn.Op1, F, false);
|
||||
if ( feature & CF_CHG2 ) handle_operand(insn, insn.Op2, F, false);
|
||||
if ( feature & CF_CHG3 ) handle_operand(insn, insn.Op3, F, false);
|
||||
}
|
||||
|
||||
|
||||
ea_t dbaddr = GetDelayedBranchAdr(insn, F);
|
||||
if ( dbaddr != BADADDR ) // add xref to the delayed target
|
||||
add_cref(insn.ea, to_ea(insn.cs, dbaddr), fl_JN);
|
||||
|
||||
if ( insn.itype == TMS320C3X_RETScond ) // add xref to conditional exit
|
||||
add_cref(insn.ea, insn.ea, fl_JN);
|
||||
|
||||
// check for DP changes
|
||||
if ( (insn.itype == TMS320C3X_LDIcond || insn.itype == TMS320C3X_LDI)
|
||||
&& insn.Op1.type == o_imm
|
||||
&& insn.Op2.type == o_reg
|
||||
&& insn.Op2.reg == dp )
|
||||
{
|
||||
split_sreg_range(get_item_end(insn.ea), dp, insn.Op1.value & 0xFF, SR_auto);
|
||||
}
|
||||
|
||||
// determine if the next instruction should be executed
|
||||
if ( segtype(insn.ea) == SEG_XTRN )
|
||||
flow = false;
|
||||
if ( flow && delayed_stop(insn, F) )
|
||||
flow = false;
|
||||
if ( flow )
|
||||
add_cref(insn.ea, insn.ea+insn.size, fl_F);
|
||||
|
||||
if ( may_trace_sp() )
|
||||
{
|
||||
if ( !flow )
|
||||
recalc_spd(insn.ea); // recalculate SP register for the next insn
|
||||
else
|
||||
trace_sp(insn);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool idaapi create_func_frame(func_t *pfn) // create frame of newly created function
|
||||
{
|
||||
if ( pfn != NULL )
|
||||
{
|
||||
if ( pfn->frame == BADNODE )
|
||||
{
|
||||
insn_t insn;
|
||||
ea_t ea = pfn->start_ea;
|
||||
ushort regsize = 0;
|
||||
while ( ea < pfn->end_ea ) // check for register pushs
|
||||
{
|
||||
decode_insn(&insn, ea);
|
||||
ea += insn.size; // count pushes
|
||||
if ( (insn.itype == TMS320C3X_PUSH || insn.itype == TMS320C3X_PUSHF)
|
||||
&& insn.Op1.type == o_reg )
|
||||
{
|
||||
regsize++;
|
||||
}
|
||||
else if ( insn.Op1.type == o_reg && insn.Op1.reg == sp
|
||||
|| insn.Op2.type == o_reg && insn.Op2.reg == sp )
|
||||
{ // ignore manipulations of this kind:
|
||||
// LDI SP,AR3 ADDI #0001,SP
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ea = pfn->start_ea;
|
||||
int localsize = 0;
|
||||
while ( ea < pfn->end_ea ) // check for frame creation
|
||||
{
|
||||
decode_insn(&insn, ea);
|
||||
ea += insn.size; // try to find ADDI #0001,SP
|
||||
if ( insn.itype == TMS320C3X_ADDI
|
||||
&& insn.Op1.type == o_imm
|
||||
&& insn.Op2.type == o_reg
|
||||
&& insn.Op2.reg == sp )
|
||||
{
|
||||
localsize = (int)insn.Op1.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
add_frame(pfn, localsize, regsize, 0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Is the instruction created only for alignment purposes?
|
||||
// returns: number of bytes in the instruction
|
||||
int idaapi is_align_insn(ea_t ea)
|
||||
{
|
||||
insn_t insn;
|
||||
if ( decode_insn(&insn, ea) < 1 )
|
||||
return 0;
|
||||
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case TMS320C3X_NOP:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return insn.size;
|
||||
}
|
||||
|
||||
//#processor_t.can_have_type
|
||||
//----------------------------------------------------------------------
|
||||
bool idaapi can_have_type(const op_t &op)
|
||||
{
|
||||
switch ( op.type )
|
||||
{
|
||||
case o_imm:
|
||||
case o_displ:
|
||||
case o_mem:
|
||||
return 1;
|
||||
|
||||
case o_phrase:
|
||||
if ( op.phrase < 8 || op.phrase == 0x18 ) // uses address field, or *arN
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
112
idasdk75/module/tms320c3/ins.cpp
Normal file
112
idasdk75/module/tms320c3/ins.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tms320c3x.hpp"
|
||||
|
||||
|
||||
const struct instruc_t Instructions[] =
|
||||
{
|
||||
|
||||
{ "", 0 }, // Unknown Operation
|
||||
{ "absf", CF_USE1|CF_CHG2 }, // Absolute value of a floating-point number
|
||||
{ "absi", CF_USE1|CF_CHG2 }, // Absolute value of an integer
|
||||
{ "addc", CF_USE1|CF_USE2|CF_CHG2 }, // Add integers with carry
|
||||
{ "addf", CF_USE1|CF_USE2|CF_CHG2 }, // Add Floating-Point Values
|
||||
{ "addi", CF_USE1|CF_USE2|CF_CHG2 }, // Add Integer
|
||||
{ "and", CF_USE1|CF_USE2|CF_CHG2 }, // Bitwise-Logical AND
|
||||
{ "andn", CF_USE1|CF_USE2|CF_CHG2 }, // Bitwise-Logical AND With Complement
|
||||
{ "ash", CF_USE1|CF_USE2|CF_CHG2|CF_SHFT }, // Arithmetic Shift
|
||||
{ "cmpf", CF_USE1|CF_USE2 }, // Compare Floating-Point Value
|
||||
{ "cmpi", CF_USE1|CF_USE2 }, // Compare Integer
|
||||
{ "fix", CF_USE1|CF_CHG2 }, // Floating-Point-to-Integer Conversion
|
||||
{ "float", CF_USE1|CF_CHG2 }, // Integer-to-Floating-Point Conversion
|
||||
{ "idle", CF_STOP }, // Idle Until Interrupt
|
||||
{ "idle2", CF_STOP }, // Low-Power Idle
|
||||
{ "lde", CF_USE1|CF_CHG2 }, // Load Floating-Point Exponent
|
||||
{ "ldf", CF_USE1|CF_CHG2 }, // Load Floating-Point Value
|
||||
{ "ldfi", CF_USE1|CF_CHG2 }, // Load Floating-Point Value, Interlocked
|
||||
{ "ldi", CF_USE1|CF_CHG2 }, // Load Integer
|
||||
{ "ldii", CF_USE1|CF_CHG2 }, // Load Integer, Interlocked
|
||||
{ "ldm", CF_USE1|CF_CHG2 }, // Load Floating-Point Mantissa
|
||||
{ "lsh", CF_USE1|CF_USE2|CF_CHG2|CF_SHFT }, // Logical Shift
|
||||
{ "mpyf", CF_USE1|CF_USE2|CF_CHG2 }, // Multiply Floating-Point Value
|
||||
{ "mpyi", CF_USE1|CF_USE2|CF_CHG2 }, // Multiply Integer
|
||||
{ "negb", CF_USE1|CF_CHG2 }, // Negative Integer With Borrow
|
||||
{ "negf", CF_USE1|CF_CHG2 }, // Negate Floating-Point Value
|
||||
{ "negi", CF_USE1|CF_CHG2 }, // Negate Integer
|
||||
{ "nop", 0 }, // No Operation
|
||||
{ "norm", CF_USE1|CF_CHG2 }, // Normalize
|
||||
{ "not", CF_USE1|CF_CHG2 }, // Bitwise-Logical Complement
|
||||
{ "pop", CF_CHG1 }, // Pop Integer
|
||||
{ "popf", CF_CHG1 }, // Pop Floating-Point Value
|
||||
{ "push", CF_USE1 }, // PUSH Integer
|
||||
{ "pushf", CF_USE1 }, // PUSH Floating-Point Value
|
||||
{ "or", CF_USE1|CF_USE2|CF_CHG2 }, // Bitwise-Logical OR
|
||||
{ "lopower", 0 }, // Divide Clock by 16
|
||||
{ "maxspeed", 0 }, // Restore Clock to Regular Speed
|
||||
{ "rnd", CF_USE1|CF_CHG2 }, // Round Floating-Point Value
|
||||
{ "rol", CF_USE1|CF_CHG1 }, // Rotate Left
|
||||
{ "rolc", CF_USE1|CF_CHG1 }, // Rotate Left Through Carry
|
||||
{ "ror", CF_USE1|CF_CHG1 }, // Rotate Right
|
||||
{ "rorc", CF_USE1|CF_CHG1 }, // Rotate Right Through Carry
|
||||
{ "rpts", CF_USE1 }, // Repeat Single Instruction
|
||||
{ "stf", CF_USE1|CF_CHG2 }, // Store Floating-Point Value
|
||||
{ "stfi", CF_USE1|CF_CHG2 }, // Store Floating-Point Value, Interlocked
|
||||
{ "sti", CF_USE1|CF_CHG2 }, // Store Integer
|
||||
{ "stii", CF_USE1|CF_CHG2 }, // Store Integer, Interlocked
|
||||
{ "sigi", 0 }, // Signal, Interlocked
|
||||
{ "subb", CF_USE1|CF_USE2|CF_CHG2 }, // Subtract Integer With Borrow
|
||||
{ "subc", CF_USE1|CF_USE2|CF_CHG2 }, // Subtract Integer Conditionally
|
||||
{ "subf", CF_USE1|CF_USE2|CF_CHG2 }, // Subtract Floating-Point Value
|
||||
{ "subi", CF_USE1|CF_USE2|CF_CHG2 }, // Subtract Integer
|
||||
{ "subrb", CF_USE1|CF_USE2|CF_CHG2 }, // Subtract Reverse Integer With Borrow
|
||||
{ "subrf", CF_USE1|CF_USE2|CF_CHG2 }, // Subtract Reverse Floating-Point Value
|
||||
{ "subri", CF_USE1|CF_USE2|CF_CHG2 }, // Subtract Reverse Integer
|
||||
{ "tstb", CF_USE1|CF_USE2 }, // Test Bit Fields
|
||||
{ "xor", CF_USE1|CF_USE2|CF_CHG2 }, // Bitwise-Exclusive OR
|
||||
{ "iack", 0 }, // Interrupt acknowledge
|
||||
{ "addc3", CF_USE1|CF_USE2|CF_CHG3 }, // Add integers with carry (3-operand)
|
||||
{ "addf3", CF_USE1|CF_USE2|CF_CHG3 }, // Add floating-point values (3-operand)
|
||||
{ "addi3", CF_USE1|CF_USE2|CF_CHG3 }, // Add integers (3 operand)
|
||||
{ "and3", CF_USE1|CF_USE2|CF_CHG3 }, // Bitwise-logical AND (3-operand)
|
||||
{ "andn3", CF_USE1|CF_USE2|CF_CHG3 }, // Bitwise-logical ANDN (3-operand)
|
||||
{ "ash3", CF_USE1|CF_USE2|CF_CHG3|CF_SHFT }, // Arithmetic shift (3-operand)
|
||||
{ "cmpf3", CF_USE1|CF_USE2 }, // Compare floating-point values (3-operand)
|
||||
{ "cmpi3", CF_USE1|CF_USE2 }, // Compare integers (3-operand)
|
||||
{ "lsh3", CF_USE1|CF_USE2|CF_CHG3|CF_SHFT }, // Logical shift (3-operand)
|
||||
{ "mpyf3", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply floating-point value (3-operand)
|
||||
{ "mpyi3", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply integers (3-operand)
|
||||
{ "or3", CF_USE1|CF_USE2|CF_CHG3 }, // Bitwise-logical OR (3-operand)
|
||||
{ "subb3", CF_USE1|CF_USE2|CF_CHG3 }, // Subtract integers with borrow (3-operand)
|
||||
{ "subf3", CF_USE1|CF_USE2|CF_CHG3 }, // Subtract floating-point values (3-operand)
|
||||
{ "subi3", CF_USE1|CF_USE2|CF_CHG3 }, // Subtract integers (3-operand)
|
||||
{ "tstb3", CF_USE1|CF_USE2 }, // Test Bit Fields, 3-Operand
|
||||
{ "xor3", CF_USE1|CF_USE2|CF_CHG3 }, // Bitwise-Exclusive OR, 3-Operand
|
||||
{ "ldf", CF_USE1|CF_CHG2 }, // Load floating-point value conditionally
|
||||
{ "ldi", CF_USE1|CF_CHG2 }, // Load integer conditionally
|
||||
{ "br", CF_USE1|CF_JUMP|CF_STOP }, // Branch unconditionally (standard)
|
||||
{ "brd", CF_USE1|CF_JUMP }, // Branch unconditionally (delayed)
|
||||
{ "call", CF_USE1|CF_CALL }, // Call subroutine
|
||||
{ "rptb", CF_USE1 }, // Repeat block of instructions
|
||||
{ "swi", CF_JUMP }, // Software Interrupt
|
||||
{ "b", CF_USE1 }, // Branch conditionally
|
||||
{ "db", CF_USE1|CF_USE2 }, // Decrement and branch conditionally
|
||||
{ "call", CF_USE1|CF_CALL }, // Call subroutine conditionally
|
||||
{ "trap", CF_USE1|CF_JUMP }, // Trap Conditionally
|
||||
{ "reti", 0 }, // Return from interrupt conditionally
|
||||
{ "rets", 0 }, // Return from subroutine conditionally
|
||||
{ "retiu", CF_STOP }, // Return from interrupt unconditionally
|
||||
{ "retsu", CF_STOP }, // Return from subroutine unconditionally
|
||||
|
||||
{ "", 0 }, // Pseudo insn (more accurate definition need)
|
||||
{ "", 0 }, // Pseudo insn (move to next index need)
|
||||
};
|
||||
|
||||
|
||||
CASSERT(qnumber(Instructions) == TMS320C3X_last);
|
||||
116
idasdk75/module/tms320c3/ins.hpp
Normal file
116
idasdk75/module/tms320c3/ins.hpp
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-2020 Hex-Rays
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __INSTRS_HPP
|
||||
#define __INSTRS_HPP
|
||||
|
||||
extern const instruc_t Instructions[];
|
||||
|
||||
enum nameNum
|
||||
{
|
||||
TMS320C3X_null = 0, // Unknown Operation
|
||||
|
||||
TMS320C3X_ABSF, // Absolute value of a floating-point number
|
||||
TMS320C3X_ABSI, // Absolute value of an integer
|
||||
TMS320C3X_ADDC, // Add integers with carry
|
||||
TMS320C3X_ADDF, // Add Floating-Point Values
|
||||
TMS320C3X_ADDI, // Add Integer
|
||||
TMS320C3X_AND, // Bitwise-Logical AND
|
||||
TMS320C3X_ANDN, // Bitwise-Logical AND With Complement
|
||||
TMS320C3X_ASH, // Arithmetic Shift
|
||||
TMS320C3X_CMPF, // Compare Floating-Point Value
|
||||
TMS320C3X_CMPI, // Compare Integer
|
||||
TMS320C3X_FIX, // Floating-Point-to-Integer Conversion
|
||||
TMS320C3X_FLOAT, // Integer-to-Floating-Point Conversion
|
||||
TMS320C3X_IDLE, // Idle Until Interrupt
|
||||
TMS320C3X_IDLE2, // Low-Power Idle
|
||||
TMS320C3X_LDE, // Load Floating-Point Exponent
|
||||
TMS320C3X_LDF, // Load Floating-Point Value
|
||||
TMS320C3X_LDFI, // Load Floating-Point Value, Interlocked
|
||||
TMS320C3X_LDI, // Load Integer
|
||||
TMS320C3X_LDII, // Load Integer, Interlocked
|
||||
TMS320C3X_LDM, // Load Floating-Point Mantissa
|
||||
TMS320C3X_LSH, // Logical Shift
|
||||
TMS320C3X_MPYF, // Multiply Floating-Point Value
|
||||
TMS320C3X_MPYI, // Multiply Integer
|
||||
TMS320C3X_NEGB, // Negative Integer With Borrow
|
||||
TMS320C3X_NEGF, // Negate Floating-Point Value
|
||||
TMS320C3X_NEGI, // Negate Integer
|
||||
TMS320C3X_NOP, // No Operation
|
||||
TMS320C3X_NORM, // Normalize
|
||||
TMS320C3X_NOT, // Bitwise-Logical Complement
|
||||
TMS320C3X_POP, // Pop Integer
|
||||
TMS320C3X_POPF, // Pop Floating-Point Value
|
||||
TMS320C3X_PUSH, // PUSH Integer
|
||||
TMS320C3X_PUSHF, // PUSH Floating-Point Value
|
||||
TMS320C3X_OR, // Bitwise-Logical OR
|
||||
TMS320C3X_LOPOWER, // Divide Clock by 16
|
||||
TMS320C3X_MAXSPEED, // Restore Clock to Regular Speed
|
||||
TMS320C3X_RND, // Round Floating-Point Value
|
||||
TMS320C3X_ROL, // Rotate Left
|
||||
TMS320C3X_ROLC, // Rotate Left Through Carry
|
||||
TMS320C3X_ROR, // Rotate Right
|
||||
TMS320C3X_RORC, // Rotate Right Through Carry
|
||||
TMS320C3X_RPTS, // Repeat Single Instruction
|
||||
TMS320C3X_STF, // Store Floating-Point Value
|
||||
TMS320C3X_STFI, // Store Floating-Point Value, Interlocked
|
||||
TMS320C3X_STI, // Store Integer
|
||||
TMS320C3X_STII, // Store Integer, Interlocked
|
||||
TMS320C3X_SIGI, // Signal, Interlocked
|
||||
TMS320C3X_SUBB, // Subtract Integer With Borrow
|
||||
TMS320C3X_SUBC, // Subtract Integer Conditionally
|
||||
TMS320C3X_SUBF, // Subtract Floating-Point Value
|
||||
TMS320C3X_SUBI, // Subtract Integer
|
||||
TMS320C3X_SUBRB, // Subtract Reverse Integer With Borrow
|
||||
TMS320C3X_SUBRF, // Subtract Reverse Floating-Point Value
|
||||
TMS320C3X_SUBRI, // Subtract Reverse Integer
|
||||
TMS320C3X_TSTB, // Test Bit Fields
|
||||
TMS320C3X_XOR, // Bitwise-Exclusive OR
|
||||
TMS320C3X_IACK, // Interrupt acknowledge
|
||||
|
||||
TMS320C3X_ADDC3, // Add integers with carry (3-operand)
|
||||
TMS320C3X_ADDF3, // Add floating-point values (3-operand)
|
||||
TMS320C3X_ADDI3, // Add integers (3 operand)
|
||||
TMS320C3X_AND3, // Bitwise-logical AND (3-operand)
|
||||
TMS320C3X_ANDN3, // Bitwise-logical ANDN (3-operand)
|
||||
TMS320C3X_ASH3, // Arithmetic shift (3-operand)
|
||||
TMS320C3X_CMPF3, // Compare floating-point values (3-operand)
|
||||
TMS320C3X_CMPI3, // Compare integers (3-operand)
|
||||
TMS320C3X_LSH3, // Logical shift (3-operand)
|
||||
TMS320C3X_MPYF3, // Multiply floating-point value (3-operand)
|
||||
TMS320C3X_MPYI3, // Multiply integers (3-operand)
|
||||
TMS320C3X_OR3, // Bitwise-logical OR (3-operand)
|
||||
TMS320C3X_SUBB3, // Subtract integers with borrow (3-operand)
|
||||
TMS320C3X_SUBF3, // Subtract floating-point values (3-operand)
|
||||
TMS320C3X_SUBI3, // Subtract integers (3-operand)
|
||||
TMS320C3X_TSTB3, // Test Bit Fields, 3-Operand
|
||||
TMS320C3X_XOR3, // Bitwise-Exclusive OR, 3-Operand
|
||||
|
||||
TMS320C3X_LDFcond, // Load floating-point value conditionally
|
||||
TMS320C3X_LDIcond, // Load integer conditionally
|
||||
TMS320C3X_BR, // Branch unconditionally (standard)
|
||||
TMS320C3X_BRD, // Branch unconditionally (delayed)
|
||||
TMS320C3X_CALL, // Call subroutine
|
||||
TMS320C3X_RPTB, // Repeat block of instructions
|
||||
TMS320C3X_SWI, // Software Interrupt
|
||||
TMS320C3X_Bcond, // Branch conditionally
|
||||
TMS320C3X_DBcond, // Decrement and branch conditionally
|
||||
TMS320C3X_CALLcond, // Call subroutine conditionally
|
||||
TMS320C3X_TRAPcond, // Trap Conditionally
|
||||
TMS320C3X_RETIcond, // Return from interrupt conditionally
|
||||
TMS320C3X_RETScond, // Return from subroutine conditionally
|
||||
TMS320C3X_RETIU, // Return from interrupt unconditionally
|
||||
TMS320C3X_RETSU, // Return from subroutine unconditionally
|
||||
|
||||
TMS320C3X_NONE, // Pseudo insn (more accurate definition need)
|
||||
TMS320C3X_MV_IDX, // Pseudo insn (move to next index need)
|
||||
TMS320C3X_last, // last ID
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
49
idasdk75/module/tms320c3/makefile
Normal file
49
idasdk75/module/tms320c3/makefile
Normal file
@@ -0,0 +1,49 @@
|
||||
PROC=tms320c3
|
||||
CONFIGS=tms320c3.cfg
|
||||
|
||||
include ../module.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \
|
||||
$(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \
|
||||
$(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \
|
||||
ana.cpp ins.hpp tms320c3x.hpp
|
||||
$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \
|
||||
$(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \
|
||||
$(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \
|
||||
$(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \
|
||||
$(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \
|
||||
$(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \
|
||||
../idaidp.hpp ../iohandler.hpp emu.cpp ins.hpp \
|
||||
tms320c3x.hpp
|
||||
$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \
|
||||
$(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \
|
||||
$(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \
|
||||
ins.cpp ins.hpp tms320c3x.hpp
|
||||
$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \
|
||||
$(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \
|
||||
$(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \
|
||||
$(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \
|
||||
$(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \
|
||||
$(I)segment.hpp $(I)segregs.hpp $(I)struct.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \
|
||||
ins.hpp out.cpp tms320c3x.hpp
|
||||
$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \
|
||||
$(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \
|
||||
$(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \
|
||||
$(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \
|
||||
$(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \
|
||||
$(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \
|
||||
../idaidp.hpp ../iohandler.hpp ins.hpp reg.cpp \
|
||||
tms320c3x.hpp
|
||||
418
idasdk75/module/tms320c3/out.cpp
Normal file
418
idasdk75/module/tms320c3/out.cpp
Normal file
@@ -0,0 +1,418 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tms320c3x.hpp"
|
||||
#include <frame.hpp>
|
||||
#include <segregs.hpp>
|
||||
#include <struct.hpp>
|
||||
|
||||
// simple wrapper class for syntactic sugar of member functions
|
||||
// this class may have only simple member functions.
|
||||
// virtual functions and data fields are forbidden, otherwise the class
|
||||
// layout may change
|
||||
class out_tms320c3_t : public outctx_t
|
||||
{
|
||||
out_tms320c3_t(void) = delete; // not used
|
||||
public:
|
||||
bool out_operand(const op_t &x);
|
||||
void out_insn(void);
|
||||
void out_proc_mnem(void);
|
||||
void out_address(ea_t ea, const op_t &x, bool at);
|
||||
};
|
||||
CASSERT(sizeof(out_tms320c3_t) == sizeof(outctx_t));
|
||||
|
||||
DECLARE_OUT_FUNCS(out_tms320c3_t)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
#define SYM(x) COLSTR(x, SCOLOR_SYMBOL)
|
||||
#define REG(x) COLSTR(x, SCOLOR_REG)
|
||||
#define REGP(x) SYM("(") REG(x) SYM(")")
|
||||
|
||||
// o_phrase output format strings, indexed by phtype
|
||||
static const char *const formats[0x1a] =
|
||||
{
|
||||
SYM("*+") REG("%s"), //0 "*+arn(NN)"
|
||||
SYM("*-") REG("%s"), //1 "*-arn(NN)"
|
||||
SYM("*++") REG("%s"), //2 "*++arn(NN)"
|
||||
SYM("*--") REG("%s"), //3 "*--arn(NN)"
|
||||
SYM("*") REG("%s") SYM("++"), //4 "*arn++(NN)"
|
||||
SYM("*") REG("%s") SYM("--"), //5 "*arn--(NN)"
|
||||
SYM("*") REG("%s") SYM("++"), //6 "*arn++(NN)%"
|
||||
SYM("*") REG("%s") SYM("--"), //7 "*arn--(NN)%"
|
||||
SYM("*+") REG("%s") REGP("ir0"), //8 "*+arn(ir0)"
|
||||
SYM("*-") REG("%s") REGP("ir0"), //9 "*-arn(ir0)"
|
||||
SYM("*++") REG("%s") REGP("ir0"), //a "*++arn(ir0)"
|
||||
SYM("*--") REG("%s") REGP("ir0"), //b "*--arn(ir0)"
|
||||
SYM("*") REG("%s") SYM("++") REGP("ir0"), //c "*arn++(ir0)"
|
||||
SYM("*") REG("%s") SYM("--") REGP("ir0"), //d "*arn--(ir0)"
|
||||
SYM("*") REG("%s") SYM("++") REGP("ir0") SYM("%%"), //e "*arn++(ir0)%"
|
||||
SYM("*") REG("%s") SYM("--") REGP("ir0") SYM("%%"), //f "*arn--(ir0)%"
|
||||
SYM("*+") REG("%s") REGP("ir1"), //10 "*+arn(ir1)"
|
||||
SYM("*-") REG("%s") REGP("ir1"), //11 "*-arn(ir1)"
|
||||
SYM("*++") REG("%s") REGP("ir1"), //12 "*++arn(ir1)"
|
||||
SYM("*--") REG("%s") REGP("ir1"), //13 "*--arn(ir1)"
|
||||
SYM("*") REG("%s") SYM("++") REGP("ir1"), //14 "*arn++(ir1)"
|
||||
SYM("*") REG("%s") SYM("--") REGP("ir1"), //15 "*arn--(ir1)"
|
||||
SYM("*") REG("%s") SYM("++") REGP("ir1") SYM("%%"), //16 "*arn++(ir1)%"
|
||||
SYM("*") REG("%s") SYM("--") REGP("ir1") SYM("%%"), //17 "*arn--(ir1)%"
|
||||
SYM("*") REG("%s"), //18 "*arn"
|
||||
SYM("*") REG("%s") SYM("++") REGP("ir0") SYM("B"), //19 "*arn++(ir0)B"
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const char *const cc_text[] =
|
||||
{
|
||||
//Unconditional compares
|
||||
"u", //Unconditional
|
||||
|
||||
//Unsigned compares
|
||||
"lo", //Lower than
|
||||
"ls", //Lower than or same as
|
||||
"hi", //Higher than
|
||||
"hs", //Higher than or same as
|
||||
"e", //Equal to
|
||||
"ne", //Not equal to
|
||||
|
||||
//Signed compares
|
||||
"lt", //Less than
|
||||
"le", //Less than or equal to
|
||||
"gt", //Greater than
|
||||
"ge", //Greater than or equal to
|
||||
|
||||
//Unknown
|
||||
"?", //Unknown
|
||||
|
||||
//Compare to condition flags
|
||||
"nv", //No overflow
|
||||
"v", //Overflow
|
||||
"nuf", //No underflow
|
||||
"uf", //Underflow
|
||||
"nlv", //No latched overflow
|
||||
"lv", //Latched overflow
|
||||
"nluf", //No latched floating-point underflow
|
||||
"luf", //Latched floating-point underflow
|
||||
"zuf" //Zero or floating-point underflow
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_tms320c3_t::out_address(ea_t ea, const op_t &x, bool at)
|
||||
{
|
||||
qstring qbuf;
|
||||
if ( get_name_expr(&qbuf, insn.ea+x.offb, x.n, ea, ea) > 0 )
|
||||
{
|
||||
if ( at )
|
||||
out_symbol('@');
|
||||
out_line(qbuf.begin());
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( at )
|
||||
out_symbol('@');
|
||||
out_tagon(COLOR_ERROR);
|
||||
out_value(x, OOFW_IMM|OOF_ADDR|OOFW_16);
|
||||
out_printf(" (ea = %a)", ea);
|
||||
out_tagoff(COLOR_ERROR);
|
||||
remember_problem(PR_NONAME, insn.ea);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool out_tms320c3_t::out_operand(const op_t &x)
|
||||
{
|
||||
ea_t ea;
|
||||
char buf[MAXSTR];
|
||||
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_void:
|
||||
return 0;
|
||||
|
||||
case o_reg:
|
||||
out_register(ph.reg_names[x.reg]);
|
||||
break;
|
||||
|
||||
case o_near:
|
||||
out_address(calc_code_mem(insn, x), x, false);
|
||||
break;
|
||||
|
||||
case o_imm:
|
||||
if ( insn.itype != TMS320C3X_TRAPcond )
|
||||
out_symbol('#');
|
||||
|
||||
if ( insn.auxpref & ImmFltFlag )
|
||||
{
|
||||
int16 v = int16(x.value);
|
||||
print_fpval(buf, sizeof(buf), &v, 2);
|
||||
out_line(buf[0] == ' ' ? &buf[1] : buf, COLOR_NUMBER);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_value(x, OOFW_IMM);
|
||||
}
|
||||
break;
|
||||
|
||||
case o_mem:
|
||||
ea = calc_data_mem(insn, x);
|
||||
if ( ea != BADADDR )
|
||||
{
|
||||
out_address(ea, x, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_tagon(COLOR_ERROR);
|
||||
out_value(x, OOFW_IMM|OOF_ADDR|OOFW_16);
|
||||
out_tagoff(COLOR_ERROR);
|
||||
}
|
||||
break;
|
||||
|
||||
case o_phrase: // Indirect addressing mode
|
||||
{
|
||||
if ( x.phrase < qnumber(formats) )
|
||||
{
|
||||
op_t y = x;
|
||||
bool outdisp = x.phrase < 8;
|
||||
bool printmod = x.phrase >= 6;
|
||||
if ( x.phrase == 0x18 )
|
||||
{
|
||||
// this is *arn phrase
|
||||
// check if we need to print the displacement
|
||||
int n = x.n;
|
||||
if ( is_off(F, n) || is_stkvar(F, n) || is_enum(F, n) || is_stroff(F, n) )
|
||||
{
|
||||
outdisp = true;
|
||||
y.addr = 0;
|
||||
printmod = false;
|
||||
y.phrase = 0; // use '*+arn(NN)' syntax
|
||||
}
|
||||
}
|
||||
|
||||
// print the base part
|
||||
const char *reg = ph.reg_names[uchar(y.phtype)];
|
||||
nowarn_qsnprintf(buf, sizeof(buf), formats[uchar(y.phrase)], reg);
|
||||
out_colored_register_line(buf);
|
||||
|
||||
// print the displacement
|
||||
if ( outdisp )
|
||||
{
|
||||
out_symbol('(');
|
||||
out_value(y, OOFS_IFSIGN|OOF_ADDR|OOFW_32);
|
||||
out_symbol(')');
|
||||
if ( printmod )
|
||||
out_symbol('%'); // %: circular modify
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
out_line("<bad indirect>", COLOR_ERROR);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
INTERR(10261);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_tms320c3_t::out_proc_mnem(void)
|
||||
{
|
||||
char postfix[8];
|
||||
postfix[0] = '\0';
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case TMS320C3X_LDFcond:
|
||||
case TMS320C3X_LDIcond:
|
||||
case TMS320C3X_Bcond:
|
||||
case TMS320C3X_DBcond:
|
||||
case TMS320C3X_CALLcond:
|
||||
case TMS320C3X_TRAPcond:
|
||||
case TMS320C3X_RETIcond:
|
||||
case TMS320C3X_RETScond:
|
||||
qstrncpy(postfix, cc_text[insn.auxpref & 0x1f ], sizeof(postfix));
|
||||
if ( insn.auxpref & DBrFlag ) // delayed branch?
|
||||
qstrncat(postfix, "d", sizeof(postfix));
|
||||
break;
|
||||
}
|
||||
|
||||
out_mnem(8, postfix);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_tms320c3_t::out_insn(void)
|
||||
{
|
||||
out_mnemonic();
|
||||
|
||||
// following operand combinations exist:
|
||||
// 0, 1, 2, 3 for non-parallel
|
||||
// 2+2, 3+2, 3+3 for parallel
|
||||
|
||||
out_one_operand(0); // two operands can be printed always
|
||||
if ( insn.Op2.type != o_void )
|
||||
{
|
||||
out_symbol(',');
|
||||
out_one_operand(1);
|
||||
}
|
||||
if ( insn.itype2 ) // Parallel
|
||||
{
|
||||
if ( insn.i2op > 2 ) // 3rd operand is for first instruction half
|
||||
{
|
||||
out_symbol(',');
|
||||
out_one_operand(2);
|
||||
}
|
||||
flush_outbuf();
|
||||
|
||||
char insn2[MAXSTR];
|
||||
qsnprintf(insn2, sizeof(insn2), "||%s", ph.instruc[uchar(insn.itype2)].name);
|
||||
::add_spaces(insn2, sizeof(insn2), 8);
|
||||
out_line(insn2, COLOR_INSN);
|
||||
|
||||
if ( insn.i2op == 2 ) // 3rd operand is for second instruction half
|
||||
{
|
||||
out_one_operand(2);
|
||||
out_symbol(',');
|
||||
}
|
||||
|
||||
if ( insn.Op4.type != o_void )
|
||||
out_one_operand(3);
|
||||
|
||||
if ( insn.Op5.type != o_void )
|
||||
{
|
||||
out_symbol(',');
|
||||
out_one_operand(4);
|
||||
}
|
||||
|
||||
if ( insn.Op6.type != o_void )
|
||||
{
|
||||
out_symbol(',');
|
||||
out_one_operand(5);
|
||||
}
|
||||
}
|
||||
else if ( insn.Op3.type != o_void )
|
||||
{
|
||||
out_symbol(',');
|
||||
out_one_operand(2);
|
||||
}
|
||||
|
||||
out_immchar_cmts();
|
||||
|
||||
flush_outbuf();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void tms320c3x_t::print_segment_register(outctx_t &ctx, int reg, sel_t value)
|
||||
{
|
||||
if ( reg == ph.reg_data_sreg )
|
||||
return;
|
||||
if ( value != BADADDR )
|
||||
{
|
||||
char buf[MAX_NUMBUF];
|
||||
btoa(buf, sizeof(buf), value);
|
||||
ctx.gen_cmt_line("assume %s = %s", ph.reg_names[reg], buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.gen_cmt_line("drop %s", ph.reg_names[reg]);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// function to produce assume directives
|
||||
//lint -e{1764} ctx could be const
|
||||
void tms320c3x_t::assumes(outctx_t &ctx)
|
||||
{
|
||||
ea_t ea = ctx.insn_ea;
|
||||
segment_t *seg = getseg(ea);
|
||||
if ( (inf_get_outflags() & OFLG_GEN_ASSUME) == 0 || seg == NULL )
|
||||
return;
|
||||
bool seg_started = (ea == seg->start_ea);
|
||||
|
||||
for ( int i = ph.reg_first_sreg; i <= ph.reg_last_sreg; ++i )
|
||||
{
|
||||
if ( i == ph.reg_code_sreg )
|
||||
continue;
|
||||
sreg_range_t sra;
|
||||
if ( !get_sreg_range(&sra, ea, i) )
|
||||
continue;
|
||||
if ( seg_started || sra.start_ea == ea )
|
||||
{
|
||||
sel_t now = get_sreg(ea, i);
|
||||
sreg_range_t prev;
|
||||
bool prev_exists = get_sreg_range(&prev, ea-1, i);
|
||||
if ( seg_started || (prev_exists && get_sreg(prev.start_ea, i) != now) )
|
||||
print_segment_register(ctx, i, now);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//lint -e{818} seg could be const
|
||||
void tms320c3x_t::segstart(outctx_t &ctx, segment_t *seg) const
|
||||
{
|
||||
if ( is_spec_segm(seg->type) )
|
||||
return;
|
||||
|
||||
qstring sclas;
|
||||
get_segm_class(&sclas, seg);
|
||||
|
||||
if ( sclas == "CODE" )
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR(".text", SCOLOR_ASMDIR));
|
||||
else if ( sclas == "DATA" )
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR(".data", SCOLOR_ASMDIR));
|
||||
|
||||
if ( seg->orgbase != 0 )
|
||||
{
|
||||
char buf[MAX_NUMBUF];
|
||||
btoa(buf, sizeof(buf), seg->orgbase);
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void idaapi segend(outctx_t &, segment_t *)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void tms320c3x_t::header(outctx_t &ctx)
|
||||
{
|
||||
ctx.gen_header(GH_PRINT_ALL | GH_BYTESEX_HAS_HIGHBYTE, NULL, ioh.device.c_str());
|
||||
ctx.gen_empty_line();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void tms320c3x_t::footer(outctx_t &ctx) const
|
||||
{
|
||||
ctx.gen_printf(DEFAULT_INDENT,COLSTR("%s",SCOLOR_ASMDIR),ash.end);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void tms320c3x_t::gen_stkvar_def(outctx_t &ctx, const member_t *mptr, sval_t v) const
|
||||
{
|
||||
char sign = ' ';
|
||||
if ( v < 0 )
|
||||
{
|
||||
sign = '-';
|
||||
v = -v;
|
||||
}
|
||||
|
||||
qstring name = get_member_name(mptr->id);
|
||||
|
||||
char vstr[MAX_NUMBUF];
|
||||
btoa(vstr, sizeof(vstr), v);
|
||||
ctx.out_printf(COLSTR("%s",SCOLOR_KEYWORD)
|
||||
COLSTR("%c%s",SCOLOR_DNUM)
|
||||
COLSTR(",",SCOLOR_SYMBOL) " "
|
||||
COLSTR("%s",SCOLOR_LOCNAME),
|
||||
ash.a_equ,
|
||||
sign,
|
||||
vstr,
|
||||
name.c_str());
|
||||
}
|
||||
621
idasdk75/module/tms320c3/reg.cpp
Normal file
621
idasdk75/module/tms320c3/reg.cpp
Normal file
@@ -0,0 +1,621 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include "tms320c3x.hpp"
|
||||
#include <diskio.hpp>
|
||||
#include <segregs.hpp>
|
||||
#include <ieee.h>
|
||||
|
||||
static const char *const register_names[] =
|
||||
{
|
||||
// Extended-precision registers
|
||||
"r0",
|
||||
"r1",
|
||||
"r2",
|
||||
"r3",
|
||||
"r4",
|
||||
"r5",
|
||||
"r6",
|
||||
"r7",
|
||||
// Auxiliary registers
|
||||
"ar0",
|
||||
"ar1",
|
||||
"ar2",
|
||||
"ar3",
|
||||
"ar4",
|
||||
"ar5",
|
||||
"ar6",
|
||||
"ar7",
|
||||
|
||||
// Index register n
|
||||
"ir0",
|
||||
"ir1",
|
||||
|
||||
"bk", // Block-size register
|
||||
"sp", // System-stack pointer
|
||||
"st", // Status register
|
||||
"ie", // CPU/DMA interrupt-enable register
|
||||
"if", // CPU interrupt flag
|
||||
"iof", // I/O flag
|
||||
"rs", // Repeat start-address
|
||||
"re", // Repeat end-address
|
||||
"rc", // Repeat counter
|
||||
|
||||
// segment registers
|
||||
"dp", // Data-page pointer
|
||||
"cs","ds", // virtual registers for code and data segments
|
||||
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const uchar retcode_0[] = { 0x78, 0x80, 0x00, 0x00 }; // 0x78800000 //retsu
|
||||
static const uchar retcode_1[] = { 0x78, 0x00, 0x00, 0x00 }; // 0x78000000 //retiu
|
||||
|
||||
static const bytes_t retcodes[] =
|
||||
{
|
||||
{ sizeof(retcode_0), retcode_0 },
|
||||
{ sizeof(retcode_1), retcode_1 },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// TMS320C3X ASM
|
||||
//-----------------------------------------------------------------------
|
||||
static const asm_t fasm =
|
||||
{
|
||||
AS_N2CHR|ASH_HEXF0|ASD_DECF0|ASO_OCTF5|ASB_BINF0|AS_ONEDUP|AS_COLON,
|
||||
0,
|
||||
"ASM500",
|
||||
0,
|
||||
NULL, // header lines
|
||||
NULL, // org
|
||||
".end", // end
|
||||
|
||||
";", // comment string
|
||||
'"', // string delimiter
|
||||
'\'', // char delimiter
|
||||
"'\"", // special symbols in char and string constants
|
||||
|
||||
".pstring", // ascii string directive
|
||||
".word", // byte directive
|
||||
".long", // word directive
|
||||
NULL, // double words
|
||||
NULL, // qwords
|
||||
NULL, // oword (16 bytes)
|
||||
".float", // float (4 bytes)
|
||||
NULL, // double (8 bytes)
|
||||
NULL, // tbyte (10/12 bytes)
|
||||
NULL, // packed decimal real
|
||||
NULL, // arrays (#h,#d,#v,#s(...)
|
||||
".space 32*%s",// uninited arrays
|
||||
".asg", // equ
|
||||
NULL, // 'seg' prefix (example: push seg seg001)
|
||||
"$", // current IP (instruction pointer)
|
||||
NULL, // func_header
|
||||
NULL, // func_footer
|
||||
".global", // "public" name keyword
|
||||
NULL, // "weak" name keyword
|
||||
".ref", // "extrn" name keyword
|
||||
NULL, // "comm" (communal variable)
|
||||
NULL, // get_type_name
|
||||
".align", // "align" keyword
|
||||
'(', ')', // lbrace, rbrace
|
||||
"%", // mod
|
||||
"&", // and
|
||||
"|", // or
|
||||
"^", // xor
|
||||
"~", // not
|
||||
"<<", // shl
|
||||
">>", // shr
|
||||
NULL, // sizeof
|
||||
AS2_BYTE1CHAR,// one character per byte
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// GNU ASM
|
||||
//-----------------------------------------------------------------------
|
||||
static const asm_t gnuasm =
|
||||
{
|
||||
AS_N2CHR|ASH_HEXF3|ASD_DECF0|ASO_OCTF5|ASB_BINF0|AS_ONEDUP|AS_COLON|AS_ASCIIC,
|
||||
0,
|
||||
"GNU assembler",
|
||||
0,
|
||||
NULL, // header lines
|
||||
NULL, // org
|
||||
".end", // end
|
||||
|
||||
";", // comment string
|
||||
'"', // string delimiter
|
||||
'\'', // char delimiter
|
||||
"'\"", // special symbols in char and string constants
|
||||
|
||||
".pstring", // ascii string directive
|
||||
".word", // byte directive
|
||||
".long", // word directive
|
||||
NULL, // double words
|
||||
NULL, // qwords
|
||||
NULL, // oword (16 bytes)
|
||||
".float", // float (4 bytes)
|
||||
NULL, // double (8 bytes)
|
||||
NULL, // tbyte (10/12 bytes)
|
||||
NULL, // packed decimal real
|
||||
NULL, // arrays (#h,#d,#v,#s(...)
|
||||
".zero 2*%s", // uninited arrays
|
||||
".asg", // equ
|
||||
NULL, // 'seg' prefix (example: push seg seg001)
|
||||
"$", // current IP (instruction pointer)
|
||||
NULL, // func_header
|
||||
NULL, // func_footer
|
||||
".global", // "public" name keyword
|
||||
".weak", // "weak" name keyword
|
||||
".extern", // "extrn" name keyword
|
||||
NULL, // "comm" (communal variable)
|
||||
NULL, // get_type_name
|
||||
".align", // "align" keyword
|
||||
'(', ')', // lbrace, rbrace
|
||||
"%", // mod
|
||||
"&", // and
|
||||
"|", // or
|
||||
"^", // xor
|
||||
"~", // not
|
||||
"<<", // shl
|
||||
">>", // shr
|
||||
NULL, // sizeof
|
||||
AS2_BYTE1CHAR,// one character per byte
|
||||
NULL, // cmnt2
|
||||
NULL, // low8
|
||||
NULL, // high8
|
||||
NULL, // low16
|
||||
NULL, // high16
|
||||
"#include \"%s\"", // a_include_fmt
|
||||
};
|
||||
|
||||
static const asm_t *const asms[] = { &fasm, &gnuasm, NULL };
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool tms320c3x_iohandler_t::entry_processing(ea_t &ea, const char *name, const char *cmt)
|
||||
{
|
||||
set_name(ea, name, SN_NODUMMY);
|
||||
set_cmt(ea, cmt, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool tms320c3x_t::select_device(int lrespect_info)
|
||||
{
|
||||
char cfgfile[QMAXFILE];
|
||||
ioh.get_cfg_filename(cfgfile, sizeof(cfgfile));
|
||||
if ( !choose_ioport_device(&ioh.device, cfgfile) )
|
||||
{
|
||||
ioh.device = NONEPROC;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !ioh.display_infotype_dialog(IORESP_ALL, &lrespect_info, cfgfile) )
|
||||
return false;
|
||||
|
||||
ioh.set_device_name(ioh.device.c_str(), lrespect_info);
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static float conv32(int32 A) // convertion of 32 bit TMS float -> double
|
||||
{
|
||||
int32 mask, f, i, s;
|
||||
float mant;
|
||||
int8 e;
|
||||
|
||||
// exponent, signed 8 bit
|
||||
e = A >> 24;
|
||||
|
||||
// sign, boolean 1 bit
|
||||
s = (A & 0x00800000) >> 23;
|
||||
|
||||
// fraction, unsigned 23 bit
|
||||
f = A & 0x007FFFFF;
|
||||
|
||||
// NaN, Inf
|
||||
if ( (e & 0xFF) == 0xFF )
|
||||
{
|
||||
uint32 i32 = (s << 31) | (0xFF << 23) | f;
|
||||
|
||||
return *reinterpret_cast<float*>(&i32);
|
||||
}
|
||||
|
||||
if ( s )
|
||||
{
|
||||
f ^= 0x007FFFFF;
|
||||
f++;
|
||||
}
|
||||
|
||||
mant = 1; // mantissa (1<M<2)
|
||||
mask = 0x00800000; // bit mask of the current bit,
|
||||
// started from the sign position
|
||||
|
||||
for ( i = 0; i <= 23; i++ )
|
||||
{
|
||||
if ( f & mask )
|
||||
mant += (float)pow(double(2), -i);
|
||||
mask >>= 1;
|
||||
}
|
||||
|
||||
if ( e == -128 && f == 0 && s == 0 )
|
||||
mant = 0;
|
||||
|
||||
return float(pow(double(-1), s) * mant * pow(double(2), e));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// A short floating-point format for immediate floating-point operands, consisting
|
||||
// of a 4-bit exponent, a sign bit, and an 11-bit fraction
|
||||
// x = 01.f * 2^e if s = 0
|
||||
// x = 10.f * 2^e if s = 1
|
||||
// x = 0 if e = -8
|
||||
static float conv16(int16 A) // Convertion of 16 bit TMS float to double
|
||||
{
|
||||
int16 mask, f, i, s;
|
||||
float mant;
|
||||
int8 e;
|
||||
|
||||
// exponent, signed 4 bit
|
||||
e = A >> 12;
|
||||
|
||||
// sign, boolean 1 bit
|
||||
s = (A & 0x0800) >> 11;
|
||||
|
||||
// fraction, unsigned 11 bit
|
||||
f = A & 0x07FF;
|
||||
|
||||
// Apparently the 16-bit format does not include
|
||||
// NaN of Inf at all (the exponent is too small anyway);
|
||||
// though this is a guess by omission (the documentation
|
||||
// mention appropriate conversions for 32-bits but not for 16-bits).
|
||||
// I think the 16-bit format is intended for short immediate values
|
||||
// rather than FPU operations, so it makes some sense.
|
||||
//
|
||||
// Therefore, no account for NaN of Inf is done in the 16-bit format.
|
||||
|
||||
if ( s )
|
||||
{
|
||||
f ^= 0x07FF;
|
||||
f++;
|
||||
}
|
||||
|
||||
mant = 1; // mantissa (1<M<2)
|
||||
mask = 0x0800; // bit mask for the current bit
|
||||
|
||||
for ( i = 0; i <= 11; i++ )
|
||||
{
|
||||
if ( f & mask )
|
||||
mant += (float)pow(double(2), -i);
|
||||
mask >>= 1;
|
||||
}
|
||||
|
||||
if ( e == -8 && f == 0 && s == 0 )
|
||||
mant = 0;
|
||||
|
||||
return float(pow(double(-1), s) * mant * pow(double(2), e));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//lint -esym(818,m)
|
||||
int idaapi tms_realcvt(void *m, ushort *e, ushort swt)
|
||||
{
|
||||
int ret;
|
||||
int32 A;
|
||||
int16 B;
|
||||
|
||||
union
|
||||
{
|
||||
float pfl;
|
||||
int32 pint;
|
||||
};
|
||||
|
||||
switch ( swt )
|
||||
{
|
||||
case 0: // TmsFloat 16bit to e
|
||||
memcpy(&B, m, 2);
|
||||
pfl = conv16(B);
|
||||
pint = swap32(pint);
|
||||
ret = ieee_realcvt(&pint, e, 1);
|
||||
break;
|
||||
|
||||
case 1: // TmsFloat 32bit to e
|
||||
memcpy(&A, m, 4);
|
||||
pfl = conv32(A);
|
||||
pint = swap32(pint);
|
||||
ret = ieee_realcvt(&pint, e, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
msg("real_cvt_error swt = %d \n", swt);
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
const char *tms320c3x_t::set_idp_options(
|
||||
const char *keyword,
|
||||
int /*value_type*/,
|
||||
const void * /*value*/,
|
||||
bool /*idb_loaded*/)
|
||||
{
|
||||
if ( keyword != NULL )
|
||||
return IDPOPT_BADKEY;
|
||||
select_device(IORESP_PORT|IORESP_INT);
|
||||
return IDPOPT_OK;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list /*va*/)
|
||||
{
|
||||
switch ( code )
|
||||
{
|
||||
case idb_event::closebase:
|
||||
case idb_event::savebase:
|
||||
pm.helper.altset(-1, pm.idpflags);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// This old-style callback only returns the processor module object.
|
||||
static ssize_t idaapi notify(void *, int msgid, va_list)
|
||||
{
|
||||
if ( msgid == processor_t::ev_get_procmod )
|
||||
return size_t(new tms320c3x_t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
ssize_t idaapi tms320c3x_t::on_event(ssize_t msgid, va_list va)
|
||||
{
|
||||
int code = 0;
|
||||
switch ( msgid )
|
||||
{
|
||||
case processor_t::ev_init:
|
||||
hook_event_listener(HT_IDB, &idb_listener, &LPH);
|
||||
helper.create("$ tms320c3x");
|
||||
inf_set_be(true); // MSB first
|
||||
inf_set_wide_high_byte_first(true);
|
||||
init_analyzer();
|
||||
break;
|
||||
|
||||
case processor_t::ev_term:
|
||||
ioh.ports.clear();
|
||||
unhook_event_listener(HT_IDB, &idb_listener);
|
||||
break;
|
||||
|
||||
case processor_t::ev_newfile: // new file loaded
|
||||
inf_set_wide_high_byte_first(false);
|
||||
if ( inf_like_binary() )
|
||||
{
|
||||
segment_t *s0 = get_first_seg();
|
||||
if ( s0 != NULL )
|
||||
{
|
||||
set_segm_name(s0, "CODE");
|
||||
segment_t *s1 = get_next_seg(s0->start_ea);
|
||||
for ( int i = dp; i <= rVds; i++ )
|
||||
{
|
||||
set_default_sreg_value(s0, i, BADSEL);
|
||||
set_default_sreg_value(s1, i, BADSEL);
|
||||
}
|
||||
}
|
||||
select_device(IORESP_ALL);
|
||||
}
|
||||
break;
|
||||
|
||||
case processor_t::ev_ending_undo:
|
||||
case processor_t::ev_oldfile: // old file loaded
|
||||
inf_set_wide_high_byte_first(false);
|
||||
idpflags = (ushort)helper.altval(-1);
|
||||
ioh.restore_device();
|
||||
break;
|
||||
|
||||
case processor_t::ev_is_basic_block_end:
|
||||
{
|
||||
const insn_t &insn = *va_arg(va, const insn_t *);
|
||||
return is_basic_block_end(insn) ? 1 : 0;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_mnem:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
out_mnem(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_header:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
header(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_footer:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
footer(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_segstart:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
segment_t *seg = va_arg(va, segment_t *);
|
||||
segstart(*ctx, seg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_segend:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
segment_t *seg = va_arg(va, segment_t *);
|
||||
segend(*ctx, seg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_assumes:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
assumes(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_ana_insn:
|
||||
{
|
||||
insn_t *out = va_arg(va, insn_t *);
|
||||
return ana(out);
|
||||
}
|
||||
|
||||
case processor_t::ev_emu_insn:
|
||||
{
|
||||
const insn_t *insn = va_arg(va, const insn_t *);
|
||||
return emu(*insn) ? 1 : -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_insn:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
out_insn(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_operand:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
const op_t *op = va_arg(va, const op_t *);
|
||||
return out_opnd(*ctx, *op) ? 1 : -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_can_have_type:
|
||||
{
|
||||
const op_t *op = va_arg(va, const op_t *);
|
||||
return can_have_type(*op) ? 1 : -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_realcvt:
|
||||
{
|
||||
void *m = va_arg(va, void *);
|
||||
uint16 *e = va_arg(va, uint16 *);
|
||||
uint16 swt = va_argi(va, uint16);
|
||||
int code1 = tms_realcvt(m, e, swt);
|
||||
return code1 == 0 ? 1 : code1;
|
||||
}
|
||||
|
||||
case processor_t::ev_create_func_frame:
|
||||
{
|
||||
func_t *pfn = va_arg(va, func_t *);
|
||||
create_func_frame(pfn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_gen_stkvar_def:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
const member_t *mptr = va_arg(va, const member_t *);
|
||||
sval_t v = va_arg(va, sval_t);
|
||||
gen_stkvar_def(*ctx, mptr, v);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_set_idp_options:
|
||||
{
|
||||
const char *keyword = va_arg(va, const char *);
|
||||
int value_type = va_arg(va, int);
|
||||
const char *value = va_arg(va, const char *);
|
||||
const char **errmsg = va_arg(va, const char **);
|
||||
bool idb_loaded = va_argi(va, bool);
|
||||
const char *ret = set_idp_options(keyword, value_type, value, idb_loaded);
|
||||
if ( ret == IDPOPT_OK )
|
||||
return 1;
|
||||
if ( errmsg != NULL )
|
||||
*errmsg = ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_is_align_insn:
|
||||
{
|
||||
ea_t ea = va_arg(va, ea_t);
|
||||
return is_align_insn(ea);
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
#define FAMILY "TMS320C3x Series:"
|
||||
static const char *const shnames[] =
|
||||
{
|
||||
"TMS320C3",
|
||||
NULL
|
||||
};
|
||||
static const char *const lnames[] =
|
||||
{
|
||||
FAMILY"Texas Instruments TMS320C3X",
|
||||
NULL
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Processor Definition
|
||||
//-----------------------------------------------------------------------
|
||||
processor_t LPH =
|
||||
{
|
||||
IDP_INTERFACE_VERSION, // version
|
||||
PLFM_TMS320C3, // id
|
||||
// flag
|
||||
PRN_HEX
|
||||
| PR_SEGS
|
||||
| PR_SGROTHER
|
||||
| PR_ALIGN
|
||||
| PR_USE32
|
||||
| PR_DEFSEG32
|
||||
| PR_DELAYED,
|
||||
// flag2
|
||||
PR2_REALCVT // the module has 'realcvt' event implementation
|
||||
| PR2_IDP_OPTS, // the module has processor-specific configuration options
|
||||
32, // 32 bits in a byte for code segments
|
||||
32, // 32 bits in a byte for other segments
|
||||
|
||||
shnames,
|
||||
lnames,
|
||||
|
||||
asms,
|
||||
|
||||
notify,
|
||||
|
||||
register_names, // Register names
|
||||
qnumber(register_names), // Number of registers
|
||||
|
||||
dp, // first
|
||||
rVds, // last
|
||||
1, // size of a segment register
|
||||
rVcs, rVds,
|
||||
|
||||
NULL, // No known code start sequences
|
||||
retcodes,
|
||||
|
||||
TMS320C3X_null,
|
||||
TMS320C3X_last,
|
||||
Instructions, // instruc
|
||||
0, // int tbyte_size; -- doesn't exist
|
||||
{ 4,7,15,19 }, // char real_width[4];
|
||||
// number of symbols after decimal point
|
||||
// 2byte float (0-does not exist)
|
||||
// normal float
|
||||
// normal double
|
||||
// long double
|
||||
TMS320C3X_RETSU, // Icode of return instruction. It is ok to give any of possible return instructions
|
||||
};
|
||||
214
idasdk75/module/tms320c3/tms320c3.cfg
Normal file
214
idasdk75/module/tms320c3/tms320c3.cfg
Normal file
@@ -0,0 +1,214 @@
|
||||
;
|
||||
; This file defines SFR names and bit names for TMS320C3X processors.
|
||||
;
|
||||
; This file can be configured for different devices.
|
||||
; At the beginning of the file there are definitions common for all devices
|
||||
; Device-specific definitions are introduced by
|
||||
;
|
||||
; .devicename
|
||||
;
|
||||
; line. Also an optional directive
|
||||
;
|
||||
; .default=devicename
|
||||
;
|
||||
; designates the default device name.
|
||||
;
|
||||
|
||||
.default C30AllModes
|
||||
|
||||
; definitions common for all devices
|
||||
|
||||
|
||||
;-------------------------------
|
||||
; Device specific definitions
|
||||
|
||||
.C30AllModes
|
||||
|
||||
; MicroComputer Mode
|
||||
; MicroProcessor Mode
|
||||
|
||||
|
||||
area DATA SYSDEV 0x808000:0x8097FF System devices
|
||||
area DATA INTRAM 0x809800:0x809FFF Internal (on chip) RAM
|
||||
|
||||
entry RESET 0x00 External reset signal input on the RESET pin
|
||||
entry INT0 0x01 External interrupt on the INT0 pin
|
||||
entry INT1 0x02 External interrupt on the INT1 pin
|
||||
entry INT2 0x03 External interrupt on the INT2 pin
|
||||
entry INT3 0x04 External interrupt on the INT3 pin
|
||||
entry XINT0 0x05 Internal interrupt generated when serial-port 0 transmit buffer is empty
|
||||
entry RINT0 0x06 Internal interrupt generated when serial-port 0 receive buffer is full
|
||||
entry XINT1 0x07 Internal interrupt generated when serial-port 1 transmit buffer is empty
|
||||
entry RINT1 0x08 Internal interrupt generated when serial-port 1 receive buffer is full
|
||||
entry TINT0 0x09 Internal interrupt generated by timer0
|
||||
entry TINT1 0x0A Internal interrupt generated by timer1
|
||||
entry DINT0 0x0B Internal interrupt generated by DMA channel 0
|
||||
entry DINT1 0x0C Internal interrupt generated by DMA channel 1
|
||||
|
||||
DMActl 0x808000 DMA global control
|
||||
DMAsrc 0x808004 DMA source address
|
||||
DMAdst 0x808006 DMA destination address
|
||||
DMAcnt 0x808008 DMA transfer counter
|
||||
|
||||
T0ctrl 0x808020 Timer 0 global control
|
||||
T0cnt 0x808024 Timer 0 counter
|
||||
T0per 0x808028 Timer 0 period
|
||||
T1ctrl 0x808030 Timer 1 global control
|
||||
T1cnt 0x808034 Timer 1 counter
|
||||
T1per 0x808038 Timer 1 period register
|
||||
|
||||
SER0ctl 0x808040 Serial port 0 global control
|
||||
SER0FSX 0x808042 FSX/DX/CLKX serial port 0 control
|
||||
SER0FSR 0x808043 FSR/DR/CLKR serial port 0 control
|
||||
SER0Tctl 0x808044 Serial port 0 R/X timer control
|
||||
SER0Tcnt 0x808045 Serial port 0 R/X timer counter
|
||||
SER0Tper 0x808046 Serial port 0 R/X timer period
|
||||
SER0Tx 0x808048 Serial port 0 data transmit
|
||||
SER0Rx 0x80804C Serial port 0 data receive
|
||||
|
||||
SER1ctl 0x808050 Serial port 1 global control
|
||||
SER1FSX 0x808052 FSX/DX/CLKX serial port 1 control
|
||||
SER1FSR 0x808053 FSR/DR/CLKR serial port 1 control
|
||||
SER1Tctl 0x808054 Serial port 1 R/X timer control
|
||||
SER1Tcnt 0x808055 Serial port 1 R/X timer counter
|
||||
SER1Tper 0x808056 Serial port 1 R/X timer period
|
||||
SER1Tx 0x808058 Serial port 1 data transmit
|
||||
SER1Rx 0x80805C Serial port 1 data receive
|
||||
|
||||
ExpBusCtl 0x808060 Expansion-buscontrol
|
||||
PriBusCtl 0x808064 Primary-buscontrol
|
||||
|
||||
; insert definitions here
|
||||
|
||||
.C31MicroProcessorMode
|
||||
; MicroProcessor Mode
|
||||
|
||||
area DATA SYSDEV 0x808000:0x8097FF System devices
|
||||
area DATA INTRAM 0x809800:0x809FFF Internal (on chip) RAM
|
||||
|
||||
entry RESET 0x00 External reset signal input on the RESET pin
|
||||
entry INT0 0x01 External interrupt on the INT0 pin
|
||||
entry INT1 0x02 External interrupt on the INT1 pin
|
||||
entry INT2 0x03 External interrupt on the INT2 pin
|
||||
entry INT3 0x04 External interrupt on the INT3 pin
|
||||
entry XINT0 0x05 Internal interrupt generated when serial-port 0 transmit buffer is empty
|
||||
entry RINT0 0x06 Internal interrupt generated when serial-port 0 receive buffer is full
|
||||
entry XINT1 0x07 Internal interrupt generated when serial-port 1 transmit buffer is empty
|
||||
entry RINT1 0x08 Internal interrupt generated when serial-port 1 receive buffer is full
|
||||
entry TINT0 0x09 Internal interrupt generated by timer0
|
||||
entry TINT1 0x0A Internal interrupt generated by timer1
|
||||
entry DINT0 0x0B Internal interrupt generated by DMA channel 0
|
||||
entry DINT1 0x0C Internal interrupt generated by DMA channel 1
|
||||
|
||||
|
||||
DMActl 0x808000 DMA global control
|
||||
DMAsrc 0x808004 DMA source address
|
||||
DMAdst 0x808006 DMA destination address
|
||||
DMAcnt 0x808008 DMA transfer counter
|
||||
T0ctrl 0x808020 Timer 0 global control
|
||||
T0cnt 0x808024 Timer 0 counter
|
||||
T0per 0x808028 Timer 0 period
|
||||
T1ctrl 0x808030 Timer 1 global control
|
||||
T1cnt 0x808034 Timer 1 counter
|
||||
T1per 0x808038 Timer 1 period register
|
||||
|
||||
SERctl 0x808040 Serial port global control
|
||||
SERFSX 0x808042 FSX/DX/CLKX serial port control
|
||||
SERFSR 0x808043 FSR/DR/CLKR serial port control
|
||||
SERTctl 0x808044 Serial port R/X timer control
|
||||
SERTcnt 0x808045 Serial port R/X timer counter
|
||||
SERTper 0x808046 Serial port R/X timer period
|
||||
SERTx 0x808048 Serial port data transmit
|
||||
SERRx 0x80804C Serial port data receive
|
||||
|
||||
ExpBusCtl 0x808060 Expansion-buscontrol
|
||||
PriBusCtl 0x808064 Primary-buscontrol
|
||||
|
||||
; insert definitions here
|
||||
|
||||
|
||||
.C31MicroComputerMode
|
||||
; MicroComputer Mode
|
||||
|
||||
area DATA SYSDEV 0x808000:0x8097FF System devices
|
||||
area DATA INTRAM 0x809800:0x809FFF Internal (on chip) RAM
|
||||
|
||||
entry INT0 0x809FC1 External interrupt on the INT0 pin
|
||||
entry INT1 0x809FC2 External interrupt on the INT1 pin
|
||||
entry INT2 0x809FC3 External interrupt on the INT2 pin
|
||||
entry INT3 0x809FC4 External interrupt on the INT3 pin
|
||||
entry XINT0 0x809FC5 Internal interrupt generated when serial-port 0 transmit buffer is empty
|
||||
entry RINT0 0x809FC6 Internal interrupt generated when serial-port 0 receive buffer is full
|
||||
entry XINT1 0x809FC7 Internal interrupt generated when serial-port 1 transmit buffer is empty
|
||||
entry RINT1 0x809FC8 Internal interrupt generated when serial-port 1 receive buffer is full
|
||||
entry TINT0 0x809FC9 Internal interrupt generated by timer0
|
||||
entry TINT1 0x809FCA Internal interrupt generated by timer1
|
||||
entry DINT0 0x809FCB Internal interrupt generated by DMA channel 0
|
||||
entry DINT1 0x809FCC Internal interrupt generated by DMA channel 1
|
||||
|
||||
|
||||
DMActl 0x808000 DMA global control
|
||||
DMAsrc 0x808004 DMA source address
|
||||
DMAdst 0x808006 DMA destination address
|
||||
DMAcnt 0x808008 DMA transfer counter
|
||||
T0ctrl 0x808020 Timer 0 global control
|
||||
T0cnt 0x808024 Timer 0 counter
|
||||
T0per 0x808028 Timer 0 period
|
||||
T1ctrl 0x808030 Timer 1 global control
|
||||
T1cnt 0x808034 Timer 1 counter
|
||||
T1per 0x808038 Timer 1 period register
|
||||
|
||||
SERctl 0x808040 Serial port global control
|
||||
SERFSX 0x808042 FSX/DX/CLKX serial port control
|
||||
SERFSR 0x808043 FSR/DR/CLKR serial port control
|
||||
SERTctl 0x808044 Serial port R/X timer control
|
||||
SERTcnt 0x808045 Serial port R/X timer counter
|
||||
SERTper 0x808046 Serial port R/X timer period
|
||||
SERTx 0x808048 Serial port data transmit
|
||||
SERRx 0x80804C Serial port data receive
|
||||
|
||||
ExpBusCtl 0x808060 Expansion-buscontrol
|
||||
PriBusCtl 0x808064 Primary-buscontrol
|
||||
|
||||
; insert definitions here
|
||||
|
||||
.C32AllModes
|
||||
; MicroComputer Mode
|
||||
; MicroProcessor Mode
|
||||
|
||||
area DATA SYSDEV 0x808000:0x8097FF System devices
|
||||
area DATA INTRAM 0x87FE00:0x87FFFF Internal (on chip) RAM
|
||||
|
||||
|
||||
DMA0ctl 0x808000 DMA 0 global control
|
||||
DMA0src 0x808004 DMA 0 source address
|
||||
DMA0dst 0x808006 DMA 0 destination address
|
||||
DMA0cnt 0x808008 DMA 0 transfer counter
|
||||
|
||||
DMA1ctl 0x808010 DMA 1 global control
|
||||
DMA1src 0x808014 DMA 1 source address
|
||||
DMA1dst 0x808016 DMA 1 destination address
|
||||
DMA1cnt 0x808018 DMA 1 transfer counter
|
||||
|
||||
T0ctrl 0x808020 Timer 0 global control
|
||||
T0cnt 0x808024 Timer 0 counter
|
||||
T0per 0x808028 Timer 0 period
|
||||
T1ctrl 0x808030 Timer 1 global control
|
||||
T1cnt 0x808034 Timer 1 counter
|
||||
T1per 0x808038 Timer 1 period register
|
||||
|
||||
SERctl 0x808040 Serial port global control
|
||||
SERFSX 0x808042 FSX/DX/CLKX serial port control
|
||||
SERFSR 0x808043 FSR/DR/CLKR serial port control
|
||||
SERTctl 0x808044 Serial port R/X timer control
|
||||
SERTcnt 0x808045 Serial port R/X timer counter
|
||||
SERTper 0x808046 Serial port R/X timer period
|
||||
SERTx 0x808048 Serial port data transmit
|
||||
SERRx 0x80804C Serial port data receive
|
||||
|
||||
IOSTRB 0x808060 IOSTRB bus control
|
||||
STRB0 0x808064 STRB0 bus control
|
||||
STRB1 0x808068 STRB1 bus control
|
||||
|
||||
|
||||
|
||||
170
idasdk75/module/tms320c3/tms320c3x.hpp
Normal file
170
idasdk75/module/tms320c3/tms320c3x.hpp
Normal file
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _TMS320C3X_HPP
|
||||
#define _TMS320C3X_HPP
|
||||
|
||||
#include "../idaidp.hpp"
|
||||
#include <diskio.hpp>
|
||||
#include "ins.hpp"
|
||||
|
||||
|
||||
enum regnum_t
|
||||
{
|
||||
// Extended-precision registers
|
||||
r0 = 0,
|
||||
r1,
|
||||
r2,
|
||||
r3,
|
||||
r4,
|
||||
r5,
|
||||
r6,
|
||||
r7,
|
||||
// Auxiliary registers
|
||||
ar0,
|
||||
ar1,
|
||||
ar2,
|
||||
ar3,
|
||||
ar4,
|
||||
ar5,
|
||||
ar6,
|
||||
ar7,
|
||||
|
||||
// Index register n
|
||||
ir0,
|
||||
ir1,
|
||||
bk, // Block-size register
|
||||
sp, // System-stack pointer
|
||||
st, // Status register
|
||||
ie, // CPU/DMA interrupt-enable register
|
||||
if_reg, // CPU interrupt flag
|
||||
iof, // I/O flag
|
||||
rs, // Repeat start-address
|
||||
re, // Repeat end-address
|
||||
rc, // Repeat counter
|
||||
// segment registers
|
||||
dp, // DP register
|
||||
rVcs, rVds // virtual registers for code and data segments
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// specific processor records
|
||||
|
||||
#define phtype specflag1 // o_phrase: phrase type
|
||||
//0 "*+arn(NN)"
|
||||
//1 "*-arn(NN)"
|
||||
//2 "*++arn(NN)"
|
||||
//3 "*--arn(NN)"
|
||||
//4 "*arn++(NN)"
|
||||
//5 "*arn--(NN)"
|
||||
//6 "*arn++(NN)%%"
|
||||
//7 "*arn--(NN)%%"
|
||||
//8 "*+arn(ir0)"
|
||||
//9 "*-arn(ir0)"
|
||||
//a "*++arn(ir0)"
|
||||
//b "*--arn(ir0)"
|
||||
//c "*arn++(ir0)"
|
||||
//d "*arn--(ir0)"
|
||||
//e "*arn++(ir0)%%"
|
||||
//f "*arn--(ir0)%%"
|
||||
//10 "*+arn(ir1)"
|
||||
//11 "*-arn(ir1)"
|
||||
//12 "*++arn(ir1)"
|
||||
//13 "*--arn(ir1)"
|
||||
//14 "*arn++(ir1)"
|
||||
//15 "*arn--(ir1)"
|
||||
//16 "*arn++(ir1)%%"
|
||||
//17 "*arn--(ir1)%%"
|
||||
//18 "*arn"
|
||||
//19 "*arn++(ir0)B"
|
||||
|
||||
#define itype2 segpref // 2-nd command type (within parallel instruction)
|
||||
#define i2op insnpref // number of first operand that belong to 2-nd insn of parallel instruction
|
||||
// auxpref flags:
|
||||
#define DBrFlag 0x80 // Delayed branch flag
|
||||
#define ImmFltFlag 0x40 // Imm float Value
|
||||
|
||||
#include "../iohandler.hpp"
|
||||
|
||||
//------------------------------------------------------------------
|
||||
struct tms320c3x_iohandler_t : public iohandler_t
|
||||
{
|
||||
tms320c3x_iohandler_t(netnode &nn) : iohandler_t(nn) {}
|
||||
virtual bool entry_processing(ea_t &ea, const char *name, const char *cmt) override;
|
||||
};
|
||||
|
||||
DECLARE_PROC_LISTENER(idb_listener_t, struct tms320c3x_t);
|
||||
|
||||
struct ctx_t;
|
||||
struct opcode_t;
|
||||
struct tms320c3_table_t
|
||||
{
|
||||
opcode_t *entries;
|
||||
int size;
|
||||
opcode_t &operator[](size_t i);
|
||||
void create(const opcode_t src_table[], int src_table_size);
|
||||
~tms320c3_table_t();
|
||||
};
|
||||
|
||||
struct tms320c3x_t : public procmod_t
|
||||
{
|
||||
netnode helper;
|
||||
tms320c3x_iohandler_t ioh = tms320c3x_iohandler_t(helper);
|
||||
idb_listener_t idb_listener = idb_listener_t(*this);
|
||||
|
||||
tms320c3_table_t table;
|
||||
ushort idpflags; // not used?
|
||||
bool flow = false;
|
||||
|
||||
virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override;
|
||||
|
||||
bool select_device(int lrespect_info);
|
||||
const char *idaapi set_idp_options(
|
||||
const char *keyword,
|
||||
int /*value_type*/,
|
||||
const void * /*value*/,
|
||||
bool /*idb_loaded*/);
|
||||
|
||||
int ana(insn_t *insn);
|
||||
void init_analyzer(void);
|
||||
void gen_masks(void);
|
||||
int run_functions(ctx_t &ctx, int value, int entry, int start, int end);
|
||||
int run_functions2(ctx_t &ctx, int value, int entry, int start, int end);
|
||||
|
||||
int emu(const insn_t &insn);
|
||||
void handle_operand(const insn_t &insn, const op_t &x, flags_t F, bool use);
|
||||
|
||||
void header(outctx_t &ctx);
|
||||
void assumes(outctx_t &ctx);
|
||||
void print_segment_register(outctx_t &ctx, int reg, sel_t value);
|
||||
void segstart(outctx_t &ctx, segment_t *seg) const;
|
||||
void footer(outctx_t &ctx) const;
|
||||
void gen_stkvar_def(outctx_t &ctx, const member_t *mptr, sval_t v) const;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------
|
||||
ea_t calc_code_mem(const insn_t &insn, const op_t &x);
|
||||
ea_t calc_data_mem(const insn_t &insn, const op_t &x);
|
||||
|
||||
regnum_t get_mapped_register(ea_t ea);
|
||||
const char *get_cond8(char value);
|
||||
int get_signed(int byte,int mask);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
void idaapi segend(outctx_t &, segment_t *seg);
|
||||
|
||||
void idaapi data(outctx_t &ctx);
|
||||
|
||||
bool idaapi create_func_frame(func_t *pfn);
|
||||
int idaapi is_align_insn(ea_t ea);
|
||||
bool is_basic_block_end(const insn_t &insn);
|
||||
bool idaapi can_have_type(const op_t &op);
|
||||
|
||||
#endif // _TMS320C3X_HPP
|
||||
Reference in New Issue
Block a user