This commit is contained in:
olari
2021-06-05 21:10:25 +03:00
parent 807cffd9de
commit e0e0f2be99
923 changed files with 911857 additions and 15 deletions

View 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];
}

View 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;
}

View 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);

View 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

View 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

View 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());
}

View 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
};

View 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

View 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