update to ida 7.6, add builds

This commit is contained in:
2021-10-31 21:20:46 +02:00
parent e0e0f2be99
commit b1809fe2d9
1408 changed files with 279193 additions and 302468 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,375 @@
/*
* Interactive disassembler (IDA).
* Copyright (c) 1990-98 by Ilfak Guilfanov.
* ALL RIGHTS RESERVED.
* E-mail: ig@estar.msk.su
* FIDO: 2:5020/209
*
*
* TMS320C6xx - VLIW (very long instruction word) architecture
*
*/
#include "tms6.hpp"
//------------------------------------------------------------------------
static void set_immd_bit(const insn_t &insn, int n, flags_t F)
{
set_immd(insn.ea);
if ( is_defarg(F, n) )
return;
switch ( insn.itype )
{
case TMS6_mvk:
if ( is_mvk_scst16_form(insn.ea) )
{
op_hex(insn.ea, n);
break;
}
// fallthrough for scst5 form
case TMS6_addk:
case TMS6_and: // Rd = Op1 & Op2
case TMS6_xor: // Rd = Op1 ^ Op2
case TMS6_or: // Rd = Op2 | Op1
case TMS6_cmpeq:
case TMS6_cmpgt:
case TMS6_cmplt:
case TMS6_mpy:
case TMS6_mpyi:
case TMS6_mpyid:
case TMS6_mpysu:
case TMS6_sadd:
case TMS6_ssub:
case TMS6_sub:
case TMS6_set: // Rd = Op1 & ~Op2
case TMS6_clr: // Rd = Op1 & ~Op2
case TMS6_ext: // Rd = Op1 & ~Op2
case TMS6_extu: // Rd = Op1 & ~Op2
op_dec(insn.ea, n);
break;
}
}
//----------------------------------------------------------------------
static void handle_operand(const insn_t &insn, const op_t &x, flags_t F, bool isload)
{
switch ( x.type )
{
case o_regpair:
case o_reg:
case o_phrase:
case o_spmask:
case o_stgcyc:
break;
case o_imm:
if ( !isload )
goto badTouch;
/* no break */
case o_displ:
set_immd_bit(insn, x.n, F);
if ( op_adds_xrefs(F, x.n) )
{
int outf = x.type != o_imm ? OOF_ADDR : 0;
if ( x.dtype == dt_word )
outf |= OOF_SIGNED;
insn.add_off_drefs(x, dr_O, outf);
}
break;
case o_near:
{
ea_t ea = to_ea(insn.cs, x.addr);
ea_t ref = find_first_insn_in_packet(ea);
insn.add_cref(ref, x.offb, fl_JN);
}
break;
default:
badTouch:
INTERR(10380);
}
}
//----------------------------------------------------------------------
ea_t find_first_insn_in_packet(ea_t ea)
{
if ( !is_spec_ea(ea) )
{
while ( (ea & 0x1F) != 0 )
{
ea_t ea2 = prev_not_tail(ea);
if ( ea2 == BADADDR
|| !is_code(get_flags(ea2))
|| (get_dword(ea2) & BIT0) == 0 )
{
break;
}
ea = ea2;
}
}
return ea;
}
//----------------------------------------------------------------------
inline bool is_tms6_nop(uint32 code)
{
return (code & 0x21FFEL) == 0;
}
//----------------------------------------------------------------------
inline bool is_tms6_bnop(uint32 code)
{
return (code & 0x00001FFC) == 0x00000120 // Branch Using a Displacement With NOP
|| (code & 0x0F830FFE) == 0x00800362; // Branch Using a Register With NOP
}
//----------------------------------------------------------------------
static int get_delay(uint32 code)
{
if ( is_tms6_nop(code) ) // NOP
return int((code >> 13) & 0xF) + 1;
if ( is_tms6_bnop(code) ) // BNOP
return int((code >> 13) & 0x7);
return 1;
}
//----------------------------------------------------------------------
struct call_info_t
{
ea_t mvk;
ea_t mvkh;
uint32 next;
int reg;
call_info_t(ea_t n) : mvk(BADADDR), mvkh(BADADDR), next(n), reg(rB3) {}
bool call_is_present(void) const { return mvk != BADADDR && mvkh != BADADDR; }
void test(ea_t ea, uint32 code);
};
//----------------------------------------------------------------------
inline ushort get_mvk_op(uint32 code) { return ushort(code >> 7); }
void call_info_t::test(ea_t ea, uint32 code)
{
if ( (code & 0xF000007CL) == 0x28 && mvk == BADADDR )
{ // unconditional MVK.S
int mvk_reg = int(code >> 23) & 0x1F;
if ( code & BIT1 )
mvk_reg += rB0;
if ( (reg == -1 || reg == mvk_reg) && ushort(next) == get_mvk_op(code) )
{
reg = mvk_reg;
mvk = ea;
}
}
else if ( (code & 0xF000007CL) == 0x68 && mvkh == BADADDR )
{ // unconditional MVKH.S
int mvk_reg = int(code >> 23) & 0x1F;
if ( code & BIT1 )
mvk_reg += rB0;
if ( (reg == -1 || reg == mvk_reg) && ushort(next>>16) == get_mvk_op(code) )
{
reg = mvk_reg;
mvkh = ea;
}
}
}
//----------------------------------------------------------------------
static int calc_packet_delay(ea_t ea, call_info_t *ci)
{
int delay = 1;
while ( true )
{
uint32 code = get_dword(ea);
int d2 = get_delay(code);
if ( d2 > delay )
delay = d2;
ci->test(ea, code);
if ( (code & BIT0) == 0 )
break;
ea += 4;
if ( !is_code(get_flags(ea)) )
break;
}
return delay;
}
//----------------------------------------------------------------------
static ea_t find_prev_packet(ea_t ea)
{
ea_t res = BADADDR;
while ( 1 )
{
ea_t ea2 = prev_not_tail(res != BADADDR ? res : ea);
if ( ea2 == BADADDR )
break;
if ( !is_code(get_flags(ea2)) )
break;
res = ea2;
if ( (get_dword(ea2) & BIT0) == 0 )
break;
}
return res;
}
//----------------------------------------------------------------------
static ea_t get_branch_ea(ea_t ea)
{
while ( 1 )
{
uint32 code = get_dword(ea);
if ( (code >> 28) == cAL )
{
switch ( (code >> 2) & 0x1F )
{
case 0x04: // bcond()
return ea;
case 0x08: // S unit
case 0x18:
{
int opcode = int(code >> 6) & 0x3F;
switch ( opcode )
{
case 0: // bdec/bpos
case 3: // b irp
case 4: // bnop
case 13: // b
return ea;
}
}
break;
}
}
if ( (code & BIT0) == 0 )
break;
ea += 4;
if ( !is_code(get_flags(ea)) )
break;
}
return BADADDR;
}
//----------------------------------------------------------------------
int tms6_t::emu(const insn_t &insn)
{
uint32 Feature = insn.get_canon_feature(ph);
flow = ((Feature & CF_STOP) == 0);
if ( segtype(insn.ea) == SEG_XTRN )
{
flow = false;
}
else if ( (insn.cflags & aux_para) == 0 ) // the last instruction of packet
{
// From spru732j.pdf:
// Although branch instructions take one execute phase, there are five
// delay slots between the execution of the branch and execution of the
// target code.
// We look backwards for five delay slots to check for an unconditionnal
// branch instruction.
ea_t ea = find_first_insn_in_packet(insn.ea);
int delay = 0;
call_info_t ci(insn.ea+insn.size);
while ( 1 )
{
// If there are any crefs to this address, we cannot guarantee that
// the branch instruction really got executed.
if ( has_xref(get_flags(ea)) )
break;
// Increment delay count for this packet.
delay += calc_packet_delay(ea, &ci);
if ( delay > 5 )
break;
// Unless we have a bnop instruction, seek to the previous packet.
bool is_bnop = is_tms6_bnop(get_dword(ea));
if ( !is_bnop )
{
ea = find_prev_packet(ea);
if ( ea == BADADDR )
break;
ea = find_first_insn_in_packet(ea);
}
ea_t brea;
if ( delay == 5 && (brea=get_branch_ea(ea)) != BADADDR )
{
// We seeked to the previous packet and it was a bnop. The check
// for delay == 5 is no longer correct, since we did not take into
// account the delays of the bnop instruction itself.
if ( is_tms6_bnop(get_dword(ea)) && !is_bnop )
break;
insn_t brins;
calc_packet_delay(ea, &ci); // just to test for MVK/MVKH
bool iscall = ci.call_is_present();
decode_insn(&brins, brea);
tgtinfo_t tgt;
if ( brins.Op1.type == o_near )
{
ea_t target = to_ea(brins.cs, brins.Op1.addr);
if ( iscall )
{
target = find_first_insn_in_packet(target);
brins.add_cref(target, brins.Op1.offb, fl_CN);
if ( !func_does_return(target) )
flow = false;
}
tgt.type = iscall ? tgtinfo_t::CALL : tgtinfo_t::BRANCH;
tgt.target = target;
}
else
{
tgt.type = iscall ? tgtinfo_t::IND_CALL : tgtinfo_t::IND_BRANCH;
}
if ( !iscall )
flow = false;
tgt.save_to_idb(*this, insn.ea);
if ( iscall )
{
if ( !is_off0(get_flags(ci.mvk)) )
op_offset(ci.mvk, 0, REF_LOW16, ci.next, brins.cs, 0);
if ( !is_off0(get_flags(ci.mvkh)) )
op_offset(ci.mvkh, 0, REF_HIGH16, ci.next, brins.cs, 0);
}
break;
}
// We don't check past one bnop instruction.
if ( is_bnop )
break;
}
}
flags_t F = get_flags(insn.ea);
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);
if ( flow )
add_cref(insn.ea, insn.ea + insn.size, fl_F);
return 1;
}
//----------------------------------------------------------------------
int idaapi is_align_insn(ea_t ea)
{
insn_t insn;
decode_insn(&insn, ea);
switch ( insn.itype )
{
case TMS6_mv:
if ( insn.Op1.reg == insn.Op2.reg )
break;
default:
return 0;
case TMS6_nop:
break;
}
return insn.size;
}

View File

@@ -0,0 +1,256 @@
/*
* Interactive disassembler (IDA).
* Copyright (c) 1990-98 by Ilfak Guilfanov.
* ALL RIGHTS RESERVED.
* E-mail: ig@estar.msk.su
* FIDO: 2:5020/209
*
*
* TMS320C6xx - VLIW (very long instruction word) architecture
*
*/
#include "tms6.hpp"
const instruc_t Instructions[] =
{
// Original TMS320C62x instructions
{ "", 0 }, // Unknown Operation
{ "ABS", CF_USE1|CF_CHG2 }, // Absolute value
{ "ADD", CF_USE1|CF_USE2|CF_CHG3 }, // Integer addition without saturation (signed)
{ "ADDU", CF_USE1|CF_USE2|CF_CHG3 }, // Integer addition without saturation (unsigned)
{ "ADDAB", CF_USE1|CF_USE2|CF_CHG3 }, // Integer addition using addressing mode (byte)
{ "ADDAH", CF_USE1|CF_USE2|CF_CHG3 }, // Integer addition using addressing mode (halfword)
{ "ADDAW", CF_USE1|CF_USE2|CF_CHG3 }, // Integer addition using addressing mode (word)
{ "ADDK", CF_USE1|CF_CHG2 }, // Integer addition 16bit signed constant
{ "ADD2", CF_USE1|CF_USE2|CF_CHG3 }, // Two 16bit Integer adds on register halves
{ "AND", CF_USE1|CF_USE2|CF_CHG3 }, // Logical AND
{ "B", CF_USE1 }, // Branch
{ "CLR", CF_USE1|CF_USE2|CF_CHG3 }, // Clear a bit field
{ "CMPEQ", CF_USE1|CF_USE2|CF_CHG3 }, // Compare for equality
{ "CMPGT", CF_USE1|CF_USE2|CF_CHG3 }, // Compare for greater than (signed)
{ "CMPGTU", CF_USE1|CF_USE2|CF_CHG3 }, // Compare for greater than (unsigned)
{ "CMPLT", CF_USE1|CF_USE2|CF_CHG3 }, // Compare for less than (signed)
{ "CMPLTU", CF_USE1|CF_USE2|CF_CHG3 }, // Compare for less than (unsigned)
{ "EXT", CF_USE1|CF_USE2|CF_CHG3 }, // Extract and sign-extend a bit filed
{ "EXTU", CF_USE1|CF_USE2|CF_CHG3 }, // Extract an unsigned bit field
{ "IDLE", CF_STOP }, // Multicycle NOP with no termination until interrupt
{ "LDB", CF_USE1|CF_CHG2 }, // Load from memory (signed 8bit)
{ "LDBU", CF_USE1|CF_CHG2 }, // Load from memory (unsigned 8bit)
{ "LDH", CF_USE1|CF_CHG2 }, // Load from memory (signed 16bit)
{ "LDHU", CF_USE1|CF_CHG2 }, // Load from memory (unsigned 16bit)
{ "LDW", CF_USE1|CF_CHG2 }, // Load from memory (32bit)
{ "LMBD", CF_USE1|CF_USE2|CF_CHG3 }, // Leftmost bit detection
{ "MPY", CF_USE1|CF_USE2|CF_CHG3 }, // Signed Integer Multiply (LSB16 x LSB16)
{ "MPYU", CF_USE1|CF_USE2|CF_CHG3 }, // Unsigned Integer Multiply (LSB16 x LSB16)
{ "MPYUS", CF_USE1|CF_USE2|CF_CHG3 }, // Integer Multiply Signed*Unsigned (LSB16 x LSB16)
{ "MPYSU", CF_USE1|CF_USE2|CF_CHG3 }, // Integer Multiply Unsigned*Signed (LSB16 x LSB16)
{ "MPYH", CF_USE1|CF_USE2|CF_CHG3 }, // Signed Integer Multiply (MSB16 x MSB16)
{ "MPYHU", CF_USE1|CF_USE2|CF_CHG3 }, // Unsigned Integer Multiply (MSB16 x MSB16)
{ "MPYHUS", CF_USE1|CF_USE2|CF_CHG3 }, // Integer Multiply Unsigned*Signed (MSB16 x MSB16)
{ "MPYHSU", CF_USE1|CF_USE2|CF_CHG3 }, // Integer Multiply Signed*Unsigned (MSB16 x MSB16)
{ "MPYHL", CF_USE1|CF_USE2|CF_CHG3 }, // Signed Integer Multiply (MSB16 x LSB16)
{ "MPYHLU", CF_USE1|CF_USE2|CF_CHG3 }, // Unsigned Integer Multiply (MSB16 x LSB16)
{ "MPYHULS", CF_USE1|CF_USE2|CF_CHG3 }, // Integer Multiply Signed*Unsigned (MSB16 x LSB16)
{ "MPYHSLU", CF_USE1|CF_USE2|CF_CHG3 }, // Integer Multiply Unsigned*Signed (MSB16 x LSB16)
{ "MPYLH", CF_USE1|CF_USE2|CF_CHG3 }, // Signed Integer Multiply (LSB16 x MB16)
{ "MPYLHU", CF_USE1|CF_USE2|CF_CHG3 }, // Unsigned Integer Multiply (LSB16 x MSB16)
{ "MPYLUHS", CF_USE1|CF_USE2|CF_CHG3 }, // Integer Multiply Signed*Unsigned (LSB16 x MSB16)
{ "MPYLSHU", CF_USE1|CF_USE2|CF_CHG3 }, // Integer Multiply Unsigned*Signed (LSB16 x MSB16)
{ "MV", CF_USE1|CF_CHG2 }, // Move from register to register
{ "MVC", CF_USE1|CF_CHG2 }, // Move between the control file & register file
{ "MVK", CF_USE1|CF_CHG2 }, // Move a 16bit signed constant into register
{ "MVKH", CF_USE1|CF_CHG2 }, // Move a 16bit constant into the upper bits of a register
{ "MVKLH", CF_USE1|CF_CHG2 }, // Move a 16bit constant into the upper bits of a register
{ "NEG", CF_USE1|CF_CHG2 }, // Negate
{ "NOP", CF_USE1 }, // No operation
{ "NORM", CF_USE1|CF_CHG2 }, // Normalize
{ "NOT", CF_USE1|CF_CHG2 }, // Bitwise NOT
{ "OR", CF_USE1|CF_USE2|CF_CHG3 }, // Logical or
{ "SADD", CF_USE1|CF_USE2|CF_CHG3 }, // Integer addition with saturation
{ "SAT", CF_USE1|CF_CHG2 }, // Saturate 40bit value to 32bits
{ "SET", CF_USE1|CF_USE2|CF_CHG3 }, // Set a bit field
{ "SHL", CF_USE1|CF_USE2|CF_CHG3 }, // Arithmetic shift left
{ "SHR", CF_USE1|CF_USE2|CF_CHG3 }, // Arithmetic shift right
{ "SHRU", CF_USE1|CF_USE2|CF_CHG3 }, // Logical shift left
{ "SMPY", CF_USE1|CF_USE2|CF_CHG3 }, // Integer multiply with left shift & saturation (LSB16*LSB16)
{ "SMPYHL", CF_USE1|CF_USE2|CF_CHG3 }, // Integer multiply with left shift & saturation (MSB16*LSB16)
{ "SMPYLH", CF_USE1|CF_USE2|CF_CHG3 }, // Integer multiply with left shift & saturation (LSB16*MSB16)
{ "SMPYH", CF_USE1|CF_USE2|CF_CHG3 }, // Integer multiply with left shift & saturation (MSB16*MSB16)
{ "SSHL", CF_USE1|CF_USE2|CF_CHG3 }, // Shift left with saturation
{ "SSUB", CF_USE1|CF_USE2|CF_CHG3 }, // Integer substraction with saturation
{ "STB", CF_USE1|CF_CHG2 }, // Store to memory (signed 8bit)
{ "STBU", CF_USE1|CF_CHG2 }, // Store to memory (unsigned 8bit)
{ "STH", CF_USE1|CF_CHG2 }, // Store to memory (signed 16bit)
{ "STHU", CF_USE1|CF_CHG2 }, // Store to memory (unsigned 16bit)
{ "STW", CF_USE1|CF_CHG2 }, // Store to memory (32bit)
{ "SUB", CF_USE1|CF_USE2|CF_CHG3 }, // Integer substaraction without saturation (signed)
{ "SUBU", CF_USE1|CF_USE2|CF_CHG3 }, // Integer substaraction without saturation (unsigned)
{ "SUBAB", CF_USE1|CF_USE2|CF_CHG3 }, // Integer subtraction using addressing mode (byte)
{ "SUBAH", CF_USE1|CF_USE2|CF_CHG3 }, // Integer subtraction using addressing mode (halfword)
{ "SUBAW", CF_USE1|CF_USE2|CF_CHG3 }, // Integer subtraction using addressing mode (word)
{ "SUBC", CF_USE1|CF_USE2|CF_CHG3 }, // Conditional subtract & shift (for division)
{ "SUB2", CF_USE1|CF_USE2|CF_CHG3 }, // Two 16bit integer subtractions on register halves
{ "XOR", CF_USE1|CF_USE2|CF_CHG3 }, // Exclusive OR
{ "ZERO", CF_CHG1 }, // Zero a register
// New TMS320C674x instructions
{ "ABS2", CF_USE1|CF_CHG2 }, // Absolute Value With Saturation, Signed, Packed 16-bit
{ "ABSDP", CF_USE1|CF_CHG2 }, // Absolute Value, Double-Precision Floating-Point
{ "ABSSP", CF_USE1|CF_CHG2 }, // Absolute Value, Single-Precision Floating-Point
{ "ADD4", CF_USE1|CF_USE2|CF_CHG3 }, // Add Without Saturation, Four 8-Bit Pairs for Four 8-Bit Results
{ "ADDAD", CF_USE1|CF_USE2|CF_CHG3 }, // Add Using Doubleword Addressing Mode
{ "ADDDP", CF_USE1|CF_USE2|CF_CHG3 }, // Add Two Double-Precision Floating-Point Values
{ "ADDKPC", CF_USE1|CF_CHG2|CF_USE3 }, // Add Signed 7-bit Constant to Program Counter
{ "ADDSP", CF_USE1|CF_USE2|CF_CHG3 }, // Add Two Single-Precision Floating-Point Values
{ "ADDSUB", CF_USE1|CF_USE2|CF_CHG3 }, // Parallel ADD and SUB Operations On Common Inputs
{ "ADDSUB2", CF_USE1|CF_USE2|CF_CHG3 }, // Parallel ADD2 and SUB2 Operations On Common Inputs
{ "ANDN", CF_USE1|CF_USE2|CF_CHG3 }, // Bitwise AND Invert
{ "AVG2", CF_USE1|CF_USE2|CF_CHG3 }, // Average, Signed, Packed 16-bit
{ "AVGU4", CF_USE1|CF_USE2|CF_CHG3 }, // Average, Unsigned, Packed 16-bit
{ "BDEC", CF_USE1|CF_CHG2 }, // Branch and Decrement
{ "BITC4", CF_USE1|CF_CHG2 }, // Bit Count, Packed 8-bit
{ "BITR", CF_USE1|CF_CHG2 }, // Bit Reverse
{ "BNOP", CF_USE1|CF_USE2 }, // Branch With NOP
{ "BPOS", CF_USE1|CF_CHG2 }, // Branch Positive
{ "CALLP", CF_USE1|CF_CHG2 }, // Call Using a Displacement
{ "CMPEQ2", CF_USE1|CF_USE2|CF_CHG3 }, // Compare for Equality, Packed 16-bit
{ "CMPEQ4", CF_USE1|CF_USE2|CF_CHG3 }, // Compare for Equality, Packed 8-bit
{ "CMPEQDP", CF_USE1|CF_USE2|CF_CHG3 }, // Compare for Equality, Double-Precision Floating-Point Values
{ "CMPEQSP", CF_USE1|CF_USE2|CF_CHG3 }, // Compare for Equality, Single-Precision Floating-Point Values
{ "CMPGT2", CF_USE1|CF_USE2|CF_CHG3 }, // Compare for Greater Than, Packed 16-bit
{ "CMPGTDP", CF_USE1|CF_USE2|CF_CHG3 }, // Compare for Greater Than, Double-Precision Floating-Point Values
{ "CMPGTSP", CF_USE1|CF_USE2|CF_CHG3 }, // Compare for Greater Than, Single-Precision Floating-Point Values
{ "CMPGTU4", CF_USE1|CF_USE2|CF_CHG3 }, // Compare for Greater Than, Unsigned, Packed 8-bit
{ "CMPLT2", CF_USE1|CF_USE2|CF_CHG3 }, // Compare for Less Than, Packed 16-bit
{ "CMPLTDP", CF_USE1|CF_USE2|CF_CHG3 }, // Compare for Less Than, Double-Precision Floating-Point Values
{ "CMPLTSP", CF_USE1|CF_USE2|CF_CHG3 }, // Compare for Less Than, Single-Precision Floating-Point Values
{ "CMPLTU4", CF_USE1|CF_USE2|CF_CHG3 }, // Compare for Less Than, Unsigned, Packed 8-bit
{ "CMPY", CF_USE1|CF_USE2|CF_CHG3 }, // Complex Multiply Two Pairs, Signed, Packed 16-bit
{ "CMPYR", CF_USE1|CF_USE2|CF_CHG3 }, // Complex Multiply Two Pairs, Signed, Packed 16-bit With Rounding
{ "CMPYR1", CF_USE1|CF_USE2|CF_CHG3 }, // Complex Multiply Two Pairs, Signed, Packed 16-bit With Rounding
{ "DDOTP4", CF_USE1|CF_USE2|CF_CHG3 }, // Double Dot Product, Signed, Packed 16-Bit and Signed, Packed 8-Bit
{ "DDOTPH2", CF_USE1|CF_USE2|CF_CHG3 }, // Double Dot Product, Two Pairs, Signed, Packed 16-Bit
{ "DDOTPH2R", CF_USE1|CF_USE2|CF_CHG3 }, // Double Dot Product With Rounding, Two Pairs, Signed, Packed 16-Bit
{ "DDOTPL2", CF_USE1|CF_USE2|CF_CHG3 }, // Double Dot Product, Two Pairs, Signed, Packed 16-Bit
{ "DDOTPL2R", CF_USE1|CF_USE2|CF_CHG3 }, // Double Dot Product With Rounding, Two Pairs, Signed Packed 16-Bit
{ "DEAL", CF_USE1|CF_CHG2 }, // Deinterleave and Pack
{ "DINT", 0 }, // Disable Interrupts and Save Previous Enable State
{ "DMV", CF_USE1|CF_USE2|CF_CHG3 }, // Move Two Independent Registers to Register Pair
{ "DOTP2", CF_USE1|CF_USE2|CF_CHG3 }, // Dot Product, Signed, Packed 16-Bit
{ "DOTPN2", CF_USE1|CF_USE2|CF_CHG3 }, // Dot Product With Negate, Signed, Packed 16-Bit
{ "DOTPNRSU2", CF_USE1|CF_USE2|CF_CHG3 }, // Dot Product With Negate, Shift and Round, Signed by Unsigned, Packed 16-Bit
{ "DOTPNRUS2", CF_USE1|CF_USE2|CF_CHG3 }, // Dot Product With Negate, Shift and Round, Unsigned by Signed, Packed 16-Bit
{ "DOTPRSU2", CF_USE1|CF_USE2|CF_CHG3 }, // Dot Product With Shift and Round, Signed by Unsigned, Packed 16-Bit
{ "DOTPRUS2", CF_USE1|CF_USE2|CF_CHG3 }, // Dot Product With Shift and Round, Unsigned by Signed, Packed 16-Bit
{ "DOTPSU4", CF_USE1|CF_USE2|CF_CHG3 }, // Dot Product, Signed by Unsigned, Packed 8-Bit
{ "DOTPU4", CF_USE1|CF_USE2|CF_CHG3 }, // Dot Product, Unsigned, Packed 8-Bit
{ "DOTPUS4", CF_USE1|CF_USE2|CF_CHG3 }, // Dot Product, Unsigned by Signed, Packed 8-Bit
{ "DPACK2", CF_USE1|CF_USE2|CF_CHG3 }, // Parallel PACK2 and PACKH2 Operations
{ "DPACKX2", CF_USE1|CF_USE2|CF_CHG3 }, // Parallel PACKLH2 Operations
{ "DPINT", CF_USE1|CF_CHG2 }, // Convert Double-Precision Floating-Point Value to Integer
{ "DPSP", CF_USE1|CF_CHG2 }, // Convert Double-Precision Floating-Point Value to Single-Precision Floating-Point Value
{ "DPTRUNC", CF_USE1|CF_CHG2 }, // Convert Double-Precision Floating-Point Value to Integer With Truncation
{ "GMPY", CF_USE1|CF_USE2|CF_CHG3 }, // Galois Field Multiply
{ "GMPY4", CF_USE1|CF_USE2|CF_CHG3 }, // Galois Field Multiply, Packed 8-Bit
{ "INTDP", CF_USE1|CF_CHG2 }, // Convert Signed Integer to Double-Precision Floating-Point Value
{ "INTDPU", CF_USE1|CF_CHG2 }, // Convert Unsigned Integer to Double-Precision Floating-Point Value
{ "INTSP", CF_USE1|CF_CHG2 }, // Convert Signed Integer to Single-Precision Floating-Point Value
{ "INTSPU", CF_USE1|CF_CHG2 }, // Convert Unsigned Integer to Single-Precision Floating-Point Value
{ "LDDW", CF_USE1|CF_CHG2 }, // Load Doubleword From Memory With a 5-Bit Unsigned Constant Offset or Register Offset
{ "LDNDW", CF_USE1|CF_CHG2 }, // Load Nonaligned Doubleword From Memory With Constant or Register Offset
{ "LDNW", CF_USE1|CF_CHG2 }, // Load Nonaligned Word From Memory With Constant or Register Offset
{ "MAX2", CF_USE1|CF_USE2|CF_CHG3 }, // Maximum, Signed, Packed 16-Bit
{ "MAXU4", CF_USE1|CF_USE2|CF_CHG3 }, // Maximum, Unsigned, Packed 8-Bit
{ "MIN2", CF_USE1|CF_USE2|CF_CHG3 }, // Minimum, Signed, Packed 16-Bit
{ "MINU4", CF_USE1|CF_USE2|CF_CHG3 }, // Minimum, Unsigned, Packed 8-Bit
{ "MPY2", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Signed by Signed, 16 LSB x 16 LSB and 16 MSB x 16 MSB
{ "MPY2IR", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Two 16-Bit x 32-Bit, Shifted by 15 to Produce a Rounded 32-Bit Result
{ "MPY32", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Signed 32-Bit x Signed 32-Bit Into 32-Bit Result
{ "MPY32SU", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Signed 32-Bit x Unsigned 32-Bit Into Signed 64-Bit Result
{ "MPY32U", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Unsigned 32-Bit x Unsigned 32-Bit Into Unsigned 64-Bit Result
{ "MPY32US", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Unsigned 32-Bit x Signed 32-Bit Into Signed 64-Bit Result
{ "MPYDP", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Two Double-Precision Floating-Point Values
{ "MPYHI", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply 16 MSB x 32-Bit Into 64-Bit Result
{ "MPYHIR", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply 16 MSB x 32-Bit, Shifted by 15 to Produce a Rounded 32-Bit Result
{ "MPYI", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply 32-Bit x 32-Bit Into 32-Bit Result
{ "MPYID", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply 32-Bit x 32-Bit Into 64-Bit Result
{ "MPYIH", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply 32-Bit x 16-MSB Into 64-Bit Result
{ "MPYIHR", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply 32-Bit x 16 MSB, Shifted by 15 to Produce a Rounded 32-Bit Result
{ "MPYIL", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply 32-Bit x 16 LSB Into 64-Bit Result
{ "MPYILR", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply 32-Bit x 16 LSB, Shifted by 15 to Produce a Rounded 32-Bit Result
{ "MPYLI", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply 16 LSB x 32-Bit Into 64-Bit Result
{ "MPYLIR", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply 16 LSB x 32-Bit, Shifted by 15 to Produce a Rounded 32-Bit Result
{ "MPYSP", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Two Single-Precision Floating-Point Values
{ "MPYSP2DP", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Two Single-Precision Floating-Point Values for Double-Precision Result
{ "MPYSPDP", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Single-Precision Floating-Point Value x Double-Precision Floating-Point Value
{ "MPYSU4", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Signed x Unsigned, Four 8-Bit Pairs for Four 8-Bit Results
{ "MPYU4", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Unsigned x Unsigned, Four 8-Bit Pairs for Four 8-Bit Results
{ "MPYUS4", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Unsigned x Signed, Four 8-Bit Pairs for Four 8-Bit Results
{ "MVD", CF_USE1|CF_CHG2 }, // Move From Register to Register, Delayed
{ "MVKL", CF_USE1|CF_CHG2 }, // Move Signed Constant Into Register and Sign Extend
{ "PACK2", CF_USE1|CF_USE2|CF_CHG3 }, // Pack Two 16 LSBs Into Upper and Lower Register Halves
{ "PACKH2", CF_USE1|CF_USE2|CF_CHG3 }, // Pack Two 16 MSBs Into Upper and Lower Register Halves
{ "PACKH4", CF_USE1|CF_USE2|CF_CHG3 }, // Pack Four High Bytes Into Four 8-Bit Halfwords
{ "PACKHL2", CF_USE1|CF_USE2|CF_CHG3 }, // Pack 16 MSB Into Upper and 16 LSB Into Lower Register Halves
{ "PACKL4", CF_USE1|CF_USE2|CF_CHG3 }, // Pack Four Low Bytes Into Four 8-Bit Halfwords
{ "PACKLH2", CF_USE1|CF_USE2|CF_CHG3 }, // Pack 16 LSB Into Upper and 16 MSB Into Lower Register Halves
{ "RCPDP", CF_USE1|CF_CHG2 }, // Double-Precision Floating-Point Reciprocal Approximation
{ "RCPSP", CF_USE1|CF_CHG2 }, // Single-Precision Floating-Point Reciprocal Approximation
{ "RINT", 0 }, // Restore Previous Enable State
{ "ROTL", CF_USE1|CF_USE2|CF_CHG3 }, // Rotate Left
{ "RPACK2", CF_USE1|CF_USE2|CF_CHG3 }, // Shift With Saturation and Pack Two 16 MSBs Into Upper and Lower Register Halves
{ "RSQRDP", CF_USE1|CF_CHG2 }, // Double-Precision Floating-Point Square-Root Reciprocal Approximation
{ "RSQRSP", CF_USE1|CF_CHG2 }, // Single-Precision Floating-Point Square-Root Reciprocal Approximation
{ "SADD2", CF_USE1|CF_USE2|CF_CHG3 }, // Add Two Signed 16-Bit Integers on Upper and Lower Register Halves With Saturation
{ "SADDSU2", CF_USE1|CF_USE2|CF_CHG3 }, // Add Two Signed and Unsigned 16-Bit Integers on Register Halves With Saturation
{ "SADDSUB", CF_USE1|CF_USE2|CF_CHG3 }, // Parallel SADD and SSUB Operations On Common Inputs
{ "SADDSUB2", CF_USE1|CF_USE2|CF_CHG3 }, // Parallel SADD2 and SSUB2 Operations On Common Inputs
{ "SADDU4", CF_USE1|CF_USE2|CF_CHG3 }, // Add With Saturation, Four Unsigned 8-Bit Pairs for Four 8-Bit Results
{ "SADDUS2", CF_USE1|CF_USE2|CF_CHG3 }, // Add Two Unsigned and Signed 16-Bit Integers on Register Halves With Saturation
{ "SHFL", CF_USE1|CF_CHG2 }, // Shuffle
{ "SHFL3", CF_USE1|CF_USE2|CF_CHG3 }, // 3-Way Bit Interleave On Three 16-Bit Values Into a 48-Bit Result
{ "SHLMB", CF_USE1|CF_USE2|CF_CHG3 }, // Shift Left and Merge Byte
{ "SHR2", CF_USE1|CF_USE2|CF_CHG3 }, // Arithmetic Shift Right, Signed, Packed 16-Bit
{ "SHRMB", CF_USE1|CF_USE2|CF_CHG3 }, // Shift Right and Merge Byte
{ "SHRU2", CF_USE1|CF_USE2|CF_CHG3 }, // Arithmetic Shift Right, Unsigned, Packed 16-Bit
{ "SMPY2", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Signed by Signed, 16 LSB x 16 LSB and 16 MSB x 16 MSB With Left Shift and Saturation
{ "SMPY32", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Signed 32-Bit x Signed 32-Bit Into 64-Bit Result With Left Shift and Saturation
{ "SPACK2", CF_USE1|CF_USE2|CF_CHG3 }, // Saturate and Pack Two 16 LSBs Into Upper and Lower Register Halves
{ "SPACKU4", CF_USE1|CF_USE2|CF_CHG3 }, // Saturate and Pack Four Signed 16-Bit Integers Into Four Unsigned 8-Bit Halfwords
{ "SPDP", CF_USE1|CF_CHG2 }, // Convert Single-Precision Floating-Point Value to Double-Precision Floating-Point Value
{ "SPINT", CF_USE1|CF_CHG2 }, // Convert Single-Precision Floating-Point Value to Integer
{ "SPKERNEL", CF_USE1 }, // Software Pipelined Loop (SPLOOP) Buffer Operation Code Boundary
{ "SPKERNELR", 0 }, // Software Pipelined Loop (SPLOOP) Buffer Operation Code Boundary
{ "SPLOOP", CF_USE1 }, // Software Pipelined Loop (SPLOOP) Buffer Operation
{ "SPLOOPD", CF_USE1 }, // Software Pipelined Loop (SPLOOP) Buffer Operation With Delayed Testing
{ "SPLOOPW", CF_USE1 }, // Software Pipelined Loop (SPLOOP) Buffer Operation With Delayed Testing and No Epilog
{ "SPMASK", CF_USE1 }, // Software Pipelined Loop (SPLOOP) Buffer Operation Load/Execution Control
{ "SPMASKR", CF_USE1 }, // Software Pipelined Loop (SPLOOP) Buffer Operation Load/Execution Control
{ "SPTRUNC", CF_USE1|CF_CHG2 }, // Convert Single-Precision Floating-Point Value to Integer With Truncation
{ "SSHVL", CF_USE1|CF_USE2|CF_CHG3 }, // Variable Shift Left
{ "SSHVR", CF_USE1|CF_USE2|CF_CHG3 }, // Variable Shift Right
{ "SSUB2", CF_USE1|CF_USE2|CF_CHG3 }, // Subtract Two Signed 16-Bit Integers on Upper and Lower Register Halves With Saturation
{ "STDW", CF_USE1|CF_CHG2 }, // Store Doubleword to Memory With a 5-Bit Unsigned Constant Offset or Register Offset
{ "STNDW", CF_USE1|CF_CHG2 }, // Store Nonaligned Doubleword to Memory With a 5-Bit Unsigned Constant Offset or Register Offset
{ "STNW", CF_USE1|CF_CHG2 }, // Store Nonaligned Word to Memory With a 5-Bit Unsigned Constant Offset or Register Offset
{ "SUB4", CF_USE1|CF_USE2|CF_CHG3 }, // Subtract Without Saturation, Four 8-Bit Pairs for Four 8-Bit Results
{ "SUBABS4", CF_USE1|CF_USE2|CF_CHG3 }, // Subtract With Absolute Value, Four 8-Bit Pairs for Four 8-Bit Results
{ "SUBDP", CF_USE1|CF_USE2|CF_CHG3 }, // Subtract Two Double-Precision Floating-Point Values
{ "SUBSP", CF_USE1|CF_USE2|CF_CHG3 }, // Subtract Two Single-Precision Floating-Point Values
{ "SWAP2", CF_USE1|CF_CHG2 }, // Swap Bytes in Upper and Lower Register Halves
{ "SWAP4", CF_USE1|CF_CHG2 }, // Swap Byte Pairs in Upper and Lower Register Halves
{ "SWE", 0 }, // Software Exception
{ "SWENR", 0 }, // Software Exception, No Return
{ "UNPKHU4", CF_USE1|CF_CHG2 }, // Unpack 16 MSB Into Two Lower 8-Bit Halfwords of Upper and Lower Register Halves
{ "UNPKLU4", CF_USE1|CF_CHG2 }, // Unpack 16 LSB Into Two Lower 8-Bit Halfwords of Upper and Lower Register Halves
{ "XORMPY", CF_USE1|CF_USE2|CF_CHG3 }, // Galois Field Multiply With Zero Polynomial
{ "XPND2", CF_USE1|CF_CHG2 }, // Expand Bits to Packed 16-Bit Masks
{ "XPND4", CF_USE1|CF_CHG2 }, // Expand Bits to Packed 8-Bit Masks
};
CASSERT(qnumber(Instructions) == TMS6_last);

View File

@@ -0,0 +1,257 @@
/*
* Interactive disassembler (IDA).
* Copyright (c) 1990-2021 Hex-Rays
* ALL RIGHTS RESERVED.
*
* TMS320C6xx - VLIW (very long instruction word) architecture
*
*/
#ifndef __INSTRS_HPP
#define __INSTRS_HPP
extern const instruc_t Instructions[];
enum nameNum ENUM_SIZE(uint16)
{
// Original TMS320C62x instructions
TMS6_null = 0, // Unknown Operation
TMS6_abs, // Absolute value
TMS6_add, // Integer addition without saturation (signed)
TMS6_addu, // Integer addition without saturation (unsigned)
TMS6_addab, // Integer addition using addressing mode (byte)
TMS6_addah, // Integer addition using addressing mode (halfword)
TMS6_addaw, // Integer addition using addressing mode (word)
TMS6_addk, // Integer addition 16bit signed constant
TMS6_add2, // Two 16bit Integer adds on register halves
TMS6_and, // Logical AND
TMS6_b, // Branch
TMS6_clr, // Clear a bit field
TMS6_cmpeq, // Compare for equality
TMS6_cmpgt, // Compare for greater than (signed)
TMS6_cmpgtu, // Compare for greater than (unsigned)
TMS6_cmplt, // Compare for less than (signed)
TMS6_cmpltu, // Compare for less than (unsigned)
TMS6_ext, // Extract and sign-extend a bit filed
TMS6_extu, // Extract an unsigned bit field
TMS6_idle, // Multicycle NOP with no termination until interrupt
TMS6_ldb, // Load from memory (signed 8bit)
TMS6_ldbu, // Load from memory (unsigned 8bit)
TMS6_ldh, // Load from memory (signed 16bit)
TMS6_ldhu, // Load from memory (unsigned 16bit)
TMS6_ldw, // Load from memory (32bit)
TMS6_lmbd, // Leftmost bit detection
TMS6_mpy, // Signed Integer Multiply (LSB16 x LSB16)
TMS6_mpyu, // Unsigned Integer Multiply (LSB16 x LSB16)
TMS6_mpyus, // Integer Multiply Signed*Unsigned (LSB16 x LSB16)
TMS6_mpysu, // Integer Multiply Unsigned*Signed (LSB16 x LSB16)
TMS6_mpyh, // Signed Integer Multiply (MSB16 x MSB16)
TMS6_mpyhu, // Unsigned Integer Multiply (MSB16 x MSB16)
TMS6_mpyhus, // Integer Multiply Unsigned*Signed (MSB16 x MSB16)
TMS6_mpyhsu, // Integer Multiply Signed*Unsigned (MSB16 x MSB16)
TMS6_mpyhl, // Signed Integer Multiply (MSB16 x LSB16)
TMS6_mpyhlu, // Unsigned Integer Multiply (MSB16 x LSB16)
TMS6_mpyhuls, // Integer Multiply Signed*Unsigned (MSB16 x LSB16)
TMS6_mpyhslu, // Integer Multiply Unsigned*Signed (MSB16 x LSB16)
TMS6_mpylh, // Signed Integer Multiply (LSB16 x MB16)
TMS6_mpylhu, // Unsigned Integer Multiply (LSB16 x MSB16)
TMS6_mpyluhs, // Integer Multiply Signed*Unsigned (LSB16 x MSB16)
TMS6_mpylshu, // Integer Multiply Unsigned*Signed (LSB16 x MSB16)
TMS6_mv, // Move from register to register
TMS6_mvc, // Move between the control file & register file
TMS6_mvk, // Move a 16bit signed constant into register
TMS6_mvkh, // Move a 16bit constant into the upper bits of a register
TMS6_mvklh, // Move a 16bit constant into the upper bits of a register
TMS6_neg, // Negate
TMS6_nop, // No operation
TMS6_norm, // Normalize
TMS6_not, // Bitwise NOT
TMS6_or, // Logical or
TMS6_sadd, // Integer addition with saturation
TMS6_sat, // Saturate 40bit value to 32bits
TMS6_set, // Set a bit field
TMS6_shl, // Arithmetic shift left
TMS6_shr, // Arithmetic shift right
TMS6_shru, // Logical shift left
TMS6_smpy, // Integer multiply with left shift & saturation (LSB16*LSB16)
TMS6_smpyhl, // Integer multiply with left shift & saturation (MSB16*LSB16)
TMS6_smpylh, // Integer multiply with left shift & saturation (LSB16*MSB16)
TMS6_smpyh, // Integer multiply with left shift & saturation (MSB16*MSB16)
TMS6_sshl, // Shift left with saturation
TMS6_ssub, // Integer substraction with saturation
TMS6_stb, // Store to memory (signed 8bit)
TMS6_stbu, // Store to memory (unsigned 8bit)
TMS6_sth, // Store to memory (signed 16bit)
TMS6_sthu, // Store to memory (unsigned 16bit)
TMS6_stw, // Store to memory (32bit)
TMS6_sub, // Integer substaraction without saturation (signed)
TMS6_subu, // Integer substaraction without saturation (unsigned)
TMS6_subab, // Integer subtraction using addressing mode (byte)
TMS6_subah, // Integer subtraction using addressing mode (halfword)
TMS6_subaw, // Integer subtraction using addressing mode (word)
TMS6_subc, // Conditional subtract & shift (for division)
TMS6_sub2, // Two 16bit integer subtractions on register halves
TMS6_xor, // Exclusive OR
TMS6_zero, // Zero a register
// New TMS320C674x instructions
TMS6_abs2, // Absolute Value With Saturation, Signed, Packed 16-bit
TMS6_absdp, // Absolute Value, Double-Precision Floating-Point
TMS6_abssp, // Absolute Value, Single-Precision Floating-Point
TMS6_add4, // Add Without Saturation, Four 8-Bit Pairs for Four 8-Bit Results
TMS6_addad, // Add Using Doubleword Addressing Mode
TMS6_adddp, // Add Two Double-Precision Floating-Point Values
TMS6_addkpc, // Add Signed 7-bit Constant to Program Counter
TMS6_addsp, // Add Two Single-Precision Floating-Point Values
TMS6_addsub, // Parallel ADD and SUB Operations On Common Inputs
TMS6_addsub2, // Parallel ADD2 and SUB2 Operations On Common Inputs
TMS6_andn, // Bitwise AND Invert
TMS6_avg2, // Average, Signed, Packed 16-bit
TMS6_avgu4, // Average, Unsigned, Packed 16-bit
TMS6_bdec, // Branch and Decrement
TMS6_bitc4, // Bit Count, Packed 8-bit
TMS6_bitr, // Bit Reverse
TMS6_bnop, // Branch With NOP
TMS6_bpos, // Branch Positive
TMS6_callp, // Call Using a Displacement
TMS6_cmpeq2, // Compare for Equality, Packed 16-bit
TMS6_cmpeq4, // Compare for Equality, Packed 8-bit
TMS6_cmpeqdp, // Compare for Equality, Double-Precision Floating-Point Values
TMS6_cmpeqsp, // Compare for Equality, Single-Precision Floating-Point Values
TMS6_cmpgt2, // Compare for Greater Than, Packed 16-bit
TMS6_cmpgtdp, // Compare for Greater Than, Double-Precision Floating-Point Values
TMS6_cmpgtsp, // Compare for Greater Than, Single-Precision Floating-Point Values
TMS6_cmpgtu4, // Compare for Greater Than, Unsigned, Packed 8-bit
TMS6_cmplt2, // Compare for Less Than, Packed 16-bit
TMS6_cmpltdp, // Compare for Less Than, Double-Precision Floating-Point Values
TMS6_cmpltsp, // Compare for Less Than, Single-Precision Floating-Point Values
TMS6_cmpltu4, // Compare for Less Than, Unsigned, Packed 8-bit
TMS6_cmpy, // Complex Multiply Two Pairs, Signed, Packed 16-bit
TMS6_cmpyr, // Complex Multiply Two Pairs, Signed, Packed 16-bit With Rounding
TMS6_cmpyr1, // Complex Multiply Two Pairs, Signed, Packed 16-bit With Rounding
TMS6_ddotp4, // Double Dot Product, Signed, Packed 16-Bit and Signed, Packed 8-Bit
TMS6_ddotph2, // Double Dot Product, Two Pairs, Signed, Packed 16-Bit
TMS6_ddotph2r, // Double Dot Product With Rounding, Two Pairs, Signed, Packed 16-Bit
TMS6_ddotpl2, // Double Dot Product, Two Pairs, Signed, Packed 16-Bit
TMS6_ddotpl2r, // Double Dot Product With Rounding, Two Pairs, Signed Packed 16-Bit
TMS6_deal, // Deinterleave and Pack
TMS6_dint, // Disable Interrupts and Save Previous Enable State
TMS6_dmv, // Move Two Independent Registers to Register Pair
TMS6_dotp2, // Dot Product, Signed, Packed 16-Bit
TMS6_dotpn2, // Dot Product With Negate, Signed, Packed 16-Bit
TMS6_dotpnrsu2, // Dot Product With Negate, Shift and Round, Signed by Unsigned, Packed 16-Bit
TMS6_dotpnrus2, // Dot Product With Negate, Shift and Round, Unsigned by Signed, Packed 16-Bit
TMS6_dotprsu2, // Dot Product With Shift and Round, Signed by Unsigned, Packed 16-Bit
TMS6_dotprus2, // Dot Product With Shift and Round, Unsigned by Signed, Packed 16-Bit
TMS6_dotpsu4, // Dot Product, Signed by Unsigned, Packed 8-Bit
TMS6_dotpu4, // Dot Product, Unsigned, Packed 8-Bit
TMS6_dotpus4, // Dot Product, Unsigned by Signed, Packed 8-Bit
TMS6_dpack2, // Parallel PACK2 and PACKH2 Operations
TMS6_dpackx2, // Parallel PACKLH2 Operations
TMS6_dpint, // Convert Double-Precision Floating-Point Value to Integer
TMS6_dpsp, // Convert Double-Precision Floating-Point Value to Single-Precision Floating-Point Value
TMS6_dptrunc, // Convert Double-Precision Floating-Point Value to Integer With Truncation
TMS6_gmpy, // Galois Field Multiply
TMS6_gmpy4, // Galois Field Multiply, Packed 8-Bit
TMS6_intdp, // Convert Signed Integer to Double-Precision Floating-Point Value
TMS6_intdpu, // Convert Unsigned Integer to Double-Precision Floating-Point Value
TMS6_intsp, // Convert Signed Integer to Single-Precision Floating-Point Value
TMS6_intspu, // Convert Unsigned Integer to Single-Precision Floating-Point Value
TMS6_lddw, // Load Doubleword From Memory With a 5-Bit Unsigned Constant Offset or Register Offset
TMS6_ldndw, // Load Nonaligned Doubleword From Memory With Constant or Register Offset
TMS6_ldnw, // Load Nonaligned Word From Memory With Constant or Register Offset
TMS6_max2, // Maximum, Signed, Packed 16-Bit
TMS6_maxu4, // Maximum, Unsigned, Packed 8-Bit
TMS6_min2, // Minimum, Signed, Packed 16-Bit
TMS6_minu4, // Minimum, Unsigned, Packed 8-Bit
TMS6_mpy2, // Multiply Signed by Signed, 16 LSB x 16 LSB and 16 MSB x 16 MSB
TMS6_mpy2ir, // Multiply Two 16-Bit x 32-Bit, Shifted by 15 to Produce a Rounded 32-Bit Result
TMS6_mpy32, // Multiply Signed 32-Bit x Signed 32-Bit Into 32-Bit Result
TMS6_mpy32su, // Multiply Signed 32-Bit x Unsigned 32-Bit Into Signed 64-Bit Result
TMS6_mpy32u, // Multiply Unsigned 32-Bit x Unsigned 32-Bit Into Unsigned 64-Bit Result
TMS6_mpy32us, // Multiply Unsigned 32-Bit x Signed 32-Bit Into Signed 64-Bit Result
TMS6_mpydp, // Multiply Two Double-Precision Floating-Point Values
TMS6_mpyhi, // Multiply 16 MSB x 32-Bit Into 64-Bit Result
TMS6_mpyhir, // Multiply 16 MSB x 32-Bit, Shifted by 15 to Produce a Rounded 32-Bit Result
TMS6_mpyi, // Multiply 32-Bit x 32-Bit Into 32-Bit Result
TMS6_mpyid, // Multiply 32-Bit x 32-Bit Into 64-Bit Result
TMS6_mpyih, // Multiply 32-Bit x 16-MSB Into 64-Bit Result
TMS6_mpyihr, // Multiply 32-Bit x 16 MSB, Shifted by 15 to Produce a Rounded 32-Bit Result
TMS6_mpyil, // Multiply 32-Bit x 16 LSB Into 64-Bit Result
TMS6_mpyilr, // Multiply 32-Bit x 16 LSB, Shifted by 15 to Produce a Rounded 32-Bit Result
TMS6_mpyli, // Multiply 16 LSB x 32-Bit Into 64-Bit Result
TMS6_mpylir, // Multiply 16 LSB x 32-Bit, Shifted by 15 to Produce a Rounded 32-Bit Result
TMS6_mpysp, // Multiply Two Single-Precision Floating-Point Values
TMS6_mpysp2dp, // Multiply Two Single-Precision Floating-Point Values for Double-Precision Result
TMS6_mpyspdp, // Multiply Single-Precision Floating-Point Value x Double-Precision Floating-Point Value
TMS6_mpysu4, // Multiply Signed x Unsigned, Four 8-Bit Pairs for Four 8-Bit Results
TMS6_mpyu4, // Multiply Unsigned x Unsigned, Four 8-Bit Pairs for Four 8-Bit Results
TMS6_mpyus4, // Multiply Unsigned x Signed, Four 8-Bit Pairs for Four 8-Bit Results
TMS6_mvd, // Move From Register to Register, Delayed
TMS6_mvkl, // Move Signed Constant Into Register and Sign Extend
TMS6_pack2, // Pack Two 16 LSBs Into Upper and Lower Register Halves
TMS6_packh2, // Pack Two 16 MSBs Into Upper and Lower Register Halves
TMS6_packh4, // Pack Four High Bytes Into Four 8-Bit Halfwords
TMS6_packhl2, // Pack 16 MSB Into Upper and 16 LSB Into Lower Register Halves
TMS6_packl4, // Pack Four Low Bytes Into Four 8-Bit Halfwords
TMS6_packlh2, // Pack 16 LSB Into Upper and 16 MSB Into Lower Register Halves
TMS6_rcpdp, // Double-Precision Floating-Point Reciprocal Approximation
TMS6_rcpsp, // Single-Precision Floating-Point Reciprocal Approximation
TMS6_rint, // Restore Previous Enable State
TMS6_rotl, // Rotate Left
TMS6_rpack2, // Shift With Saturation and Pack Two 16 MSBs Into Upper and Lower Register Halves
TMS6_rsqrdp, // Double-Precision Floating-Point Square-Root Reciprocal Approximation
TMS6_rsqrsp, // Single-Precision Floating-Point Square-Root Reciprocal Approximation
TMS6_sadd2, // Add Two Signed 16-Bit Integers on Upper and Lower Register Halves With Saturation
TMS6_saddsu2, // Add Two Signed and Unsigned 16-Bit Integers on Register Halves With Saturation
TMS6_saddsub, // Parallel SADD and SSUB Operations On Common Inputs
TMS6_saddsub2, // Parallel SADD2 and SSUB2 Operations On Common Inputs
TMS6_saddu4, // Add With Saturation, Four Unsigned 8-Bit Pairs for Four 8-Bit Results
TMS6_saddus2, // Add Two Unsigned and Signed 16-Bit Integers on Register Halves With Saturation
TMS6_shfl, // Shuffle
TMS6_shfl3, // 3-Way Bit Interleave On Three 16-Bit Values Into a 48-Bit Result
TMS6_shlmb, // Shift Left and Merge Byte
TMS6_shr2, // Arithmetic Shift Right, Signed, Packed 16-Bit
TMS6_shrmb, // Shift Right and Merge Byte
TMS6_shru2, // Arithmetic Shift Right, Unsigned, Packed 16-Bit
TMS6_smpy2, // Multiply Signed by Signed, 16 LSB x 16 LSB and 16 MSB x 16 MSB With Left Shift and Saturation
TMS6_smpy32, // Multiply Signed 32-Bit x Signed 32-Bit Into 64-Bit Result With Left Shift and Saturation
TMS6_spack2, // Saturate and Pack Two 16 LSBs Into Upper and Lower Register Halves
TMS6_spacku4, // Saturate and Pack Four Signed 16-Bit Integers Into Four Unsigned 8-Bit Halfwords
TMS6_spdp, // Convert Single-Precision Floating-Point Value to Double-Precision Floating-Point Value
TMS6_spint, // Convert Single-Precision Floating-Point Value to Integer
TMS6_spkernel, // Software Pipelined Loop (SPLOOP) Buffer Operation Code Boundary
TMS6_spkernelr, // Software Pipelined Loop (SPLOOP) Buffer Operation Code Boundary
TMS6_sploop, // Software Pipelined Loop (SPLOOP) Buffer Operation
TMS6_sploopd, // Software Pipelined Loop (SPLOOP) Buffer Operation With Delayed Testing
TMS6_sploopw, // Software Pipelined Loop (SPLOOP) Buffer Operation With Delayed Testing and No Epilog
TMS6_spmask, // Software Pipelined Loop (SPLOOP) Buffer Operation Load/Execution Control
TMS6_spmaskr, // Software Pipelined Loop (SPLOOP) Buffer Operation Load/Execution Control
TMS6_sptrunc, // Convert Single-Precision Floating-Point Value to Integer With Truncation
TMS6_sshvl, // Variable Shift Left
TMS6_sshvr, // Variable Shift Right
TMS6_ssub2, // Subtract Two Signed 16-Bit Integers on Upper and Lower Register Halves With Saturation
TMS6_stdw, // Store Doubleword to Memory With a 5-Bit Unsigned Constant Offset or Register Offset
TMS6_stndw, // Store Nonaligned Doubleword to Memory With a 5-Bit Unsigned Constant Offset or Register Offset
TMS6_stnw, // Store Nonaligned Word to Memory With a 5-Bit Unsigned Constant Offset or Register Offset
TMS6_sub4, // Subtract Without Saturation, Four 8-Bit Pairs for Four 8-Bit Results
TMS6_subabs4, // Subtract With Absolute Value, Four 8-Bit Pairs for Four 8-Bit Results
TMS6_subdp, // Subtract Two Double-Precision Floating-Point Values
TMS6_subsp, // Subtract Two Single-Precision Floating-Point Values
TMS6_swap2, // Swap Bytes in Upper and Lower Register Halves
TMS6_swap4, // Swap Byte Pairs in Upper and Lower Register Halves
TMS6_swe, // Software Exception
TMS6_swenr, // Software Exception, no Return
TMS6_unpkhu4, // Unpack 16 MSB Into Two Lower 8-Bit Halfwords of Upper and Lower Register Halves
TMS6_unpklu4, // Unpack 16 LSB Into Two Lower 8-Bit Halfwords of Upper and Lower Register Halves
TMS6_xormpy, // Galois Field Multiply With Zero Polynomial
TMS6_xpnd2, // Expand Bits to Packed 16-Bit Masks
TMS6_xpnd4, // Expand Bits to Packed 8-Bit Masks
TMS6_last,
};
#endif

View File

@@ -0,0 +1,51 @@
PROC=tms320c6
include ../module.mak
# MAKEDEP dependency list ------------------
$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.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)ua.hpp $(I)xref.hpp ../idaidp.hpp ana.cpp ins.hpp \
tms6.hpp
$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.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)ua.hpp $(I)xref.hpp ../idaidp.hpp emu.cpp ins.hpp \
tms6.hpp
$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.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)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.cpp ins.hpp \
tms6.hpp
$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.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)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.hpp out.cpp \
tms6.hpp
$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.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)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.hpp reg.cpp \
tms6.hpp

View File

@@ -0,0 +1,505 @@
/*
* Interactive disassembler (IDA).
* Copyright (c) 1990-98 by Ilfak Guilfanov.
* ALL RIGHTS RESERVED.
* E-mail: ig@estar.msk.su
* FIDO: 2:5020/209
*
*
* TMS320C6xx - VLIW (very long instruction word) architecture
*
*/
#include "tms6.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_tms320c6_t : public outctx_t
{
out_tms320c6_t(void) = delete; // not used
public:
bool out_operand(const op_t &x);
void out_insn(void);
void outreg(int r) { out_register(ph.reg_names[r]); }
void out_pre_mode(int mode);
void out_post_mode(int mode);
void print_stg_cyc(ea_t ea, int stgcyc);
bool tms6_out_name_expr(const op_t &x, uval_t opval);
};
CASSERT(sizeof(out_tms320c6_t) == sizeof(outctx_t));
DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_tms320c6_t)
//----------------------------------------------------------------------
static bool is_first_insn_in_exec_packet(ea_t ea)
{
// if ( (ea & 0x1F) == 0 )
// return 1;
ea = prev_not_tail(ea);
return ea == BADADDR
|| !is_code(get_flags(ea))
|| (get_dword(ea) & BIT0) == 0;
}
//----------------------------------------------------------------------
static bool prev_complex(const insn_t &insn)
{
ea_t ea = prev_not_tail(insn.ea);
if ( ea == BADADDR || !is_code(get_flags(ea)) )
return 0;
return !is_first_insn_in_exec_packet(ea);
}
//----------------------------------------------------------------------
void out_tms320c6_t::out_pre_mode(int mode)
{
out_symbol('*');
switch ( mode )
{
case 0x08: // 1000 *--R[cst]
case 0x0C: // 1100 *--Rb[Ro]
out_symbol('-');
// fallthrough
case 0x00: // 0000 *-R[cst]
case 0x04: // 0100 *-Rb[Ro]
out_symbol('-');
break;
case 0x09: // 1001 *++R[cst]
case 0x0D: // 1101 *++Rb[Ro]
out_symbol('+');
out_symbol('+');
break;
case 0x01: // 0001 *+R[cst]
case 0x05: // 0101 *+Rb[Ro]
// out_symbol('+');
break;
case 0x0A: // 1010 *R--[cst]
case 0x0B: // 1011 *R++[cst]
case 0x0E: // 1110 *Rb--[Ro]
case 0x0F: // 1111 *Rb++[Ro]
break;
}
}
//----------------------------------------------------------------------
void out_tms320c6_t::out_post_mode(int mode)
{
switch ( mode )
{
case 0x08: // 1000 *--R[cst]
case 0x0C: // 1100 *--Rb[Ro]
case 0x00: // 0000 *-R[cst]
case 0x04: // 0100 *-Rb[Ro]
case 0x09: // 1001 *++R[cst]
case 0x0D: // 1101 *++Rb[Ro]
case 0x01: // 0001 *+R[cst]
case 0x05: // 0101 *+Rb[Ro]
break;
case 0x0A: // 1010 *R--[cst]
case 0x0E: // 1110 *Rb--[Ro]
out_symbol('-');
out_symbol('-');
break;
case 0x0B: // 1011 *R++[cst]
case 0x0F: // 1111 *Rb++[Ro]
out_symbol('+');
out_symbol('+');
break;
}
}
//----------------------------------------------------------------------
struct ii_info_t
{
char ii;
char cyc;
};
static const ii_info_t ii_info[] =
{
{ 1, 0 },
{ 2, 1 },
{ 4, 2 },
{ 8, 3 },
{ 14, 4 },
};
void out_tms320c6_t::print_stg_cyc(ea_t ea, int stgcyc)
{
int ii = 1;
insn_t prev;
for ( int i=0; i < 14 && decode_prev_insn(&prev, ea) != BADADDR; i++ )
{
if ( prev.itype == TMS6_sploop
|| prev.itype == TMS6_sploopd
|| prev.itype == TMS6_sploopw )
{
ii = prev.Op1.value;
break;
}
ea = prev.ea;
}
for ( int i=0; i < qnumber(ii_info); i++ )
{
if ( ii_info[i].ii >= ii )
{
int cyc = ii_info[i].cyc;
int stg = 0;
int stgbits = 6 - cyc;
int bit = 1 << cyc;
for ( int j=0; j < stgbits; j++, bit<<=1 )
{
stg <<= 1;
if ( stgcyc & bit )
stg |= 1;
}
cyc = stgcyc & ((1<<cyc)-1);
out_long(stg, 10);
out_symbol(',');
out_long(cyc, 10);
break;
}
}
}
//----------------------------------------------------------------------
bool out_tms320c6_t::tms6_out_name_expr(const op_t &x, uval_t opval)
{
ea_t ea = to_ea(insn.cs, opval);
ea_t safe = find_first_insn_in_packet(ea);
adiff_t delta = ea - safe;
if ( !out_name_expr(x, safe, opval - delta) )
return false;
if ( delta > 0 )
{
out_symbol('+');
out_long(delta, 16);
}
return true;
}
//----------------------------------------------------------------------
bool out_tms320c6_t::out_operand(const op_t &x)
{
switch ( x.type )
{
case o_void:
return 0;
case o_reg:
outreg(x.reg);
break;
case o_regpair:
outreg(x.reg + 1);
out_symbol(':');
outreg(x.reg);
break;
case o_imm:
{
uchar sign = insn.itype == TMS6_mvkh
|| insn.itype == TMS6_mvklh
|| (insn.itype == TMS6_mvk && is_mvk_scst16_form(insn.ea))
? 0
: OOF_SIGNED;
out_value(x, OOFS_IFSIGN|OOFW_IMM|sign);
break;
}
case o_stgcyc:
print_stg_cyc(insn.ea, x.value);
break;
case o_near:
if ( !tms6_out_name_expr(x, x.addr) )
{
out_tagon(COLOR_ERROR);
out_btoa(x.addr, 16);
out_tagoff(COLOR_ERROR);
remember_problem(PR_NONAME, insn.ea);
}
break;
case o_phrase:
out_pre_mode(x.mode);
outreg(x.reg);
out_post_mode(x.mode);
out_symbol('[');
outreg(x.secreg);
out_symbol(']');
break;
case o_displ:
out_pre_mode(x.mode);
outreg(x.reg);
out_post_mode(x.mode);
{
if ( x.addr != 0 || is_off(F, x.n) )
{
if ( is_off(F, x.n) )
{
out_symbol('(');
out_value(x, OOF_ADDR|OOFS_IFSIGN|OOFW_IMM|OOF_SIGNED|OOFW_32);
out_symbol(')');
}
else
{
out_symbol('[');
out_value(x, OOF_ADDR|OOFS_IFSIGN|OOFW_IMM|OOF_SIGNED|OOFW_32);
out_symbol(']');
}
}
}
break;
case o_spmask:
{
static const char units[] = "LLSSDDMM";
uchar mask = x.reg;
bool need_comma = false;
for ( int i=0; i < 8; i++, mask>>=1 )
{
if ( mask & 1 )
{
if ( need_comma )
out_symbol(',');
out_tagon(COLOR_KEYWORD);
out_char(units[i]);
out_char('1'+(i&1));
out_tagoff(COLOR_KEYWORD);
need_comma = true;
}
}
}
break;
default:
warning("out: %a: bad optype %d", insn.ea, x.type);
break;
}
return 1;
}
//----------------------------------------------------------------------
void out_tms320c6_t::out_insn(void)
{
//
// Parallel instructions
//
ea_t ea = insn.ea;
if ( !is_first_insn_in_exec_packet(ea) )
{
out_symbol('|');
out_symbol('|');
}
else
{
if ( !has_any_name(F)
&& (prev_complex(insn) || insn.cflags & aux_para) )
{
gen_empty_line();
}
out_char(' ');
out_char(' ');
}
//
// Condition code
//
static const char *const conds[] =
{
" ", " ", "[B0] ", "[!B0]",
"[B1] ", "[!B1]", "[B2] ", "[!B2]",
"[A1] ", "[!A1]", "[A2] ", "[!A2]",
"[A0] ", "[!A0]", " ", " "
};
out_keyword(conds[insn.cond]);
out_char(' ');
//
// Instruction name
//
out_mnemonic();
//
// Functional unit
//
static const char *const units[] =
{
NULL,
".L1", ".L2",
".S1", ".S2",
".M1", ".M2",
".D1", ".D2",
};
if ( insn.funit != FU_NONE )
out_keyword(units[uchar(insn.funit)]);
else
out_line(" ");
if ( insn.cflags & aux_xp )
out_keyword("X");
else
out_char(' ');
out_line(" ");
//
// Operands
//
if ( (insn.cflags & aux_src2) != 0 )
{
outreg(insn.Op1.src2);
out_symbol(',');
out_char(' ');
}
if ( insn.Op1.shown() )
out_one_operand(0);
if ( insn.Op2.type != o_void && insn.Op2.shown() )
{
out_symbol(',');
out_char(' ');
out_one_operand(1);
}
if ( insn.Op3.type != o_void && insn.Op3.shown() )
{
out_symbol(',');
out_char(' ');
out_one_operand(2);
}
out_immchar_cmts();
int indent = inf_get_indent() - 8; // reserve space for conditions
if ( indent <= 1 ) // too little space?
indent = 2; // pass -2, which means one space
// (-1 would mean 'use DEFAULT_INDENT')
flush_outbuf(-indent); // negative value means 'print opcodes here'
if ( (insn.cflags & aux_para) == 0 )
{
tms6_t &pm = *static_cast<tms6_t *>(procmod);
tgtinfo_t tgt;
if ( tgt.restore_from_idb(pm, ea) )
{
qstring buf = tgt.get_type_name();
if ( tgt.has_target() )
{
qstring name = get_colored_name(tgt.target);
buf.append(" ");
buf.append(name);
}
gen_printf(DEFAULT_INDENT,
COLSTR("; %s OCCURS", SCOLOR_AUTOCMT),
buf.c_str());
}
}
}
//--------------------------------------------------------------------------
//lint -e{818} seg could be const
void idaapi segstart(outctx_t &ctx, segment_t *seg)
{
if ( is_spec_segm(seg->type) )
return;
qstring sname;
get_segm_name(&sname, seg);
if ( sname == ".bss" )
return;
if ( sname == ".text" || sname == ".data" )
{
ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s", SCOLOR_ASMDIR), sname.c_str());
}
else
{
validate_name(&sname, VNT_IDENT);
ctx.gen_printf(DEFAULT_INDENT, COLSTR(".sect \"%s\"", SCOLOR_ASMDIR), sname.c_str());
}
}
//--------------------------------------------------------------------------
void idaapi segend(outctx_t &, segment_t *)
{
}
//--------------------------------------------------------------------------
void idaapi header(outctx_t &ctx)
{
ctx.gen_header(GH_PRINT_ALL);
}
//--------------------------------------------------------------------------
void tms6_t::footer(outctx_t &ctx) const
{
qstring nbuf = get_colored_name(inf_get_start_ea());
const char *name = nbuf.c_str();
const char *end = ash.end;
if ( end == NULL )
ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s end %s", SCOLOR_AUTOCMT), ash.cmnt, name);
else
ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s", SCOLOR_ASMDIR)
" "
COLSTR("%s %s", SCOLOR_AUTOCMT), ash.end, ash.cmnt, name);
}
//--------------------------------------------------------------------------
void idaapi data(outctx_t &ctx, bool analyze_only)
{
ea_t ea = ctx.insn_ea;
segment_t *s = getseg(ea);
if ( s != NULL )
{
qstring sname;
if ( get_segm_name(&sname, s) > 0 && sname == ".bss" )
{
qstring name;
if ( get_colored_name(&name, ea) <= 0 )
name.sprnt(COLSTR("bss_dummy_name_%a", SCOLOR_UNKNAME), ea);
char num[MAX_NUMBUF];
btoa(num, sizeof(num), get_item_size(ea), get_radix(ctx.F, 0));
ctx.ctxflags |= CTXF_LABEL_OK;
ctx.gen_printf(-1,
COLSTR(".bss", SCOLOR_KEYWORD)
" %s, "
COLSTR("%s", SCOLOR_DNUM),
name.begin(),
num);
return;
}
}
ctx.out_data(analyze_only);
}
//--------------------------------------------------------------------------
//lint -e{1764} ctx could be const
bool tms6_t::outspec(outctx_t &ctx, uchar stype) const
{
ea_t ea = ctx.insn_ea;
qstring nbuf;
if ( get_colored_name(&nbuf, ea) <= 0 )
return false;
const char *name = nbuf.begin();
char buf[MAX_NUMBUF];
switch ( stype )
{
case SEG_XTRN:
return ctx.gen_printf(-1, COLSTR("%s %s", SCOLOR_ASMDIR), ash.a_extrn,name);
case SEG_ABSSYM:
// i don't know how to declare absolute symbols.
// perhaps, like this?
btoa(buf, sizeof(buf), get_dword(ea));
return ctx.gen_printf(-1, COLSTR("%s = %s", SCOLOR_ASMDIR), name, buf);
case SEG_COMM:
btoa(buf, sizeof(buf), get_dword(ea));
ctx.gen_printf(-1,
COLSTR("%s \"%s\", %s", SCOLOR_ASMDIR),
ash.a_comdef, name, buf);
}
return false;
}

View File

@@ -0,0 +1,415 @@
/*
* Interactive disassembler (IDA).
* Copyright (c) 1990-98 by Ilfak Guilfanov.
* ALL RIGHTS RESERVED.
* E-mail: ig@estar.msk.su
* FIDO: 2:5020/209
*
*
* TMS320C6xx - VLIW (very long instruction word) architecture
*
*/
#include "tms6.hpp"
int data_id;
//--------------------------------------------------------------------------
// B14 - data page pointer
// B15 - stack pointer
static const char *const RegNames[] =
{
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7",
"A8", "A9", "A10", "A11", "A12", "A13", "A14", "A15",
"A16", "A17", "A18", "A19", "A20", "A21", "A22", "A23",
"A24", "A25", "A26", "A27", "A28", "A29", "A30", "A31",
"B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7",
"B8", "B9", "B10", "B11", "B12", "B13", "B14", "B15",
"B16", "B17", "B18", "B19", "B20", "B21", "B22", "B23",
"B24", "B25", "B26", "B27", "B28", "B29", "B30", "B31",
"AMR",
"CSR",
"IFR",
"ISR",
"ICR",
"IER",
"ISTP",
"IRP",
"NRP",
"ACR", // undocumented, info from Jeff Bailey <jeff_bailey@infinitek.com>
"ADR", // undocumented, info from Jeff Bailey <jeff_bailey@infinitek.com>
"PCE1",
"FADCR",
"FAUCR",
"FMCR",
"TSCL",
"TSCH",
"ILC",
"RILC",
"REP",
"DNUM",
"SSR",
"GPLYA",
"GPLYB",
"GFPGFR",
"TSR",
"ITSR",
"NTSR",
"ECR",
"EFR",
"IERR",
"CS", "DS"
};
//--------------------------------------------------------------------------
ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list va)
{
switch ( code )
{
case idb_event::segm_moved: // A segment is moved
// Fix processor dependent address sensitive information
{
ea_t from = va_arg(va, ea_t);
ea_t to = va_arg(va, ea_t);
asize_t size = va_arg(va, asize_t);
bool changed_netmap = va_argi(va, bool);
if ( !changed_netmap )
{
nodeidx_t ndx1 = ea2node(from);
nodeidx_t ndx2 = ea2node(to);
pm.helper.altshift(ndx1, ndx2, size);
// like altadjust()
for ( nodeidx_t ndx = pm.helper.supfirst();
ndx != BADADDR;
ndx = pm.helper.supnext(ndx) )
{
tgtinfo_t tgt;
ea_t ea = node2ea(ndx);
tgt.restore_from_idb(pm, ea);
if ( tgt.has_target() )
{
tgt.target = correct_address(tgt.target, from, to, size);
tgt.save_to_idb(pm, ea);
}
}
}
}
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(SET_MODULE_DATA(tms6_t));
return 0;
}
//--------------------------------------------------------------------------
ssize_t idaapi tms6_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(PROCMOD_NODE_NAME);
break;
case processor_t::ev_term:
unhook_event_listener(HT_IDB, &idb_listener);
clr_module_data(data_id);
break;
case processor_t::ev_oldfile:
{
netnode old_tnode("$ tms node");
if ( old_tnode != BADNODE )
{
upgrade_tnode(old_tnode);
old_tnode.kill();
}
}
// no break
case processor_t::ev_ending_undo:
case processor_t::ev_newfile:
break;
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_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_out_data:
{
outctx_t *ctx = va_arg(va, outctx_t *);
bool analyze_only = va_argi(va, bool);
data(*ctx, analyze_only);
return 1;
}
case processor_t::ev_out_special_item:
{
outctx_t *ctx = va_arg(va, outctx_t *);
uchar seg_type = va_argi(va, uchar);
outspec(*ctx, seg_type);
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;
}
//-------------------------------------------------------------------------
void tms6_t::upgrade_tnode(const netnode &old_tnode)
{
// copy branch/call info to HELPER
for ( nodeidx_t ndx = old_tnode.altfirst();
ndx != BADADDR;
ndx = old_tnode.altnext(ndx) )
{
nodeidx_t ndx2 = old_tnode.altval(ndx);
if ( ndx2 == 0 )
continue;
tgtinfo_t tgt;
switch ( ndx2 )
{
case 1:
tgt.type = tgtinfo_t::IND_BRANCH;
break;
case 2:
tgt.type = tgtinfo_t::IND_CALL;
break;
default:
{
ea_t target = node2ea(ndx2);
tgt.type = (target & 1) != 0
? tgtinfo_t::BRANCH
: tgtinfo_t::CALL;
tgt.target = target & ~1;
}
break;
}
tgt.save_to_idb(*this, node2ea(ndx));
}
}
//-------------------------------------------------------------------------
const char *tgtinfo_t::get_type_name() const
{
switch ( type )
{
case tgtinfo_t::CALL: return "CALL";
case tgtinfo_t::BRANCH: return "BRANCH";
case tgtinfo_t::IND_CALL: return "INDIRECT CALL";
case tgtinfo_t::IND_BRANCH: return "INDIRECT BRANCH";
}
return "";
}
//-------------------------------------------------------------------------
#define TGTINFO_MAX_SIZE (1 + ea_packed_size)
void tgtinfo_t::save_to_idb(tms6_t &pm, ea_t ea) const
{
uchar buf[TGTINFO_MAX_SIZE];
uchar *ptr = buf;
uchar *end = buf + sizeof(buf);
ptr = pack_db(ptr, end, uchar(type));
if ( has_target() )
ptr = pack_ea(ptr, end, ea2node(target));
pm.helper.supset_ea(ea, buf, ptr - buf);
}
//-------------------------------------------------------------------------
bool tgtinfo_t::restore_from_idb(const tms6_t &pm, ea_t ea)
{
uchar buf[TGTINFO_MAX_SIZE];
ssize_t code = pm.helper.supval_ea(ea, buf, sizeof(buf));
if ( code < 1 )
return false;
memory_deserializer_t mmdsr(buf, code);
uchar t = mmdsr.unpack_db();
if ( t > IND_BRANCH )
return false;
type = type_t(t);
if ( has_target() )
target = node2ea(mmdsr.unpack_ea());
return true;
}
//-----------------------------------------------------------------------
// TMS320C6x COFF Assembler
//-----------------------------------------------------------------------
static const asm_t dspasm =
{
AS_COLON | ASH_HEXF0 | ASD_DECF0 | ASB_BINF0 | ASO_OCTF5,
0,
"TMS320C6x COFF Assembler",
0,
NULL, // header lines
NULL, // org
".end",
";", // comment string
'"', // string delimiter
'\'', // char delimiter
"\\\"'", // special symbols in char and string constants
".string", // ascii string directive
".char", // byte directive
".short", // word directive
".long", // double words
NULL, // no qwords
NULL, // oword (16 bytes)
NULL, // float (4 bytes)
NULL, // double (8 bytes)
NULL, // tbyte (10/12 bytes)
NULL, // packed decimal real
NULL, // arrays (#h,#d,#v,#s(...)
".space %s", // uninited arrays
".set", // equ
NULL, // 'seg' prefix (example: push seg seg001)
"$", // current IP (instruction pointer)
NULL, // func_header
NULL, // func_footer
".def", // "public" name keyword
NULL, // "weak" name keyword
".ref", // "extrn" name keyword
".usect", // "comm" (communal variable)
NULL, // get_type_name
".align", // "align" keyword
'(', ')', // lbrace, rbrace
NULL, // mod
"&", // and
"|", // or
"^", // xor
"!", // not
"<<", // shl
">>", // shr
NULL, // sizeof
};
static const asm_t *const asms[] = { &dspasm, NULL };
//-----------------------------------------------------------------------
#define FAMILY "TMS320C6 series:"
static const char *const shnames[] = { "TMS320C6", NULL };
static const char *const lnames[] =
{
FAMILY"Texas Instruments TMS320C6xxx",
NULL
};
//--------------------------------------------------------------------------
static const uchar retcode_1[] = { 0x62, 0x63, 0x0C, 0x00 };
static const bytes_t retcodes[] =
{
{ sizeof(retcode_1), retcode_1 },
{ 0, NULL }
};
//-----------------------------------------------------------------------
// Processor Definition
//-----------------------------------------------------------------------
processor_t LPH =
{
IDP_INTERFACE_VERSION, // version
PLFM_TMSC6, // id
// flag
PR_USE32
| PR_DEFSEG32
| PR_DELAYED
| PR_ALIGN_INSN, // allow align instructions
// flag2
0,
8, // 8 bits in a byte for code segments
8, // 8 bits in a byte for other segments
shnames,
lnames,
asms,
notify,
RegNames, // Register names
qnumber(RegNames), // Number of registers
rVcs, // first
rVds, // last
0, // size of a segment register
rVcs, rVds,
NULL, // No known code start sequences
retcodes,
TMS6_null,
TMS6_last,
Instructions, // instruc
0, // int tbyte_size;
{ 2, 4, 8, 12 }, // char real_width[4];
TMS6_null, // Icode of return instruction. It is ok to give any of possible return instructions
};

View File

@@ -0,0 +1,225 @@
/*
* Interactive disassembler (IDA).
* Copyright (c) 1990-98 by Ilfak Guilfanov.
* ALL RIGHTS RESERVED.
* E-mail: ig@estar.msk.su
* FIDO: 2:5020/209
*
*
* TMS320C6xx - VLIW (very long instruction word) architecture
*
*/
#ifndef _TMS6_HPP
#define _TMS6_HPP
#include "../idaidp.hpp"
#include "ins.hpp"
#define PROCMOD_NAME tms6
#define PROCMOD_NODE_NAME "$ tms"
//-------------------------------------------------------------------------
DECLARE_PROC_LISTENER(idb_listener_t, struct tms6_t);
struct tms6_t : public procmod_t
{
netnode helper; // supval(ea) -> branch/call info, see tgtinfo_t
idb_listener_t idb_listener = idb_listener_t(*this);
bool flow = false;
ssize_t idaapi on_event(ssize_t msgid, va_list va);
int emu(const insn_t &insn);
void footer(outctx_t &ctx) const;
bool outspec(outctx_t &ctx, uchar stype) const;
void upgrade_tnode(const netnode &old_tnode);
};
extern int data_id;
//-------------------------------------------------------------------------
struct tgtinfo_t
{
enum type_t { CALL, BRANCH, IND_CALL, IND_BRANCH };
type_t type;
ea_t target;
bool has_target() const { return type == CALL || type == BRANCH; }
const char *get_type_name() const;
void save_to_idb(tms6_t &pm, ea_t ea) const;
bool restore_from_idb(const tms6_t &pm, ea_t ea);
};
//---------------------------------
// Functional units:
#ifdef _MSC_VER
#define ENUM8BIT : uint8
#else
#define ENUM8BIT
#endif
enum funit_t ENUM8BIT
{
FU_NONE, // No unit (NOP, IDLE)
FU_L1, FU_L2, // 32/40-bit arithmetic and compare operations
// Leftmost 1 or 0 bit counting for 32 bits
// Normalization count for 32 and 40 bits
// 32-bit logical operations
FU_S1, FU_S2, // 32-bit arithmetic operations
// 32/40-bit shifts and 32-bit bit-field operations
// 32-bit logical operations
// Branches
// Constant generation
// Register transfers to/from the control register file (.S2 only)
FU_M1, FU_M2, // 16 x 16 bit multiply operations
FU_D1, FU_D2, // 32-bit add, subtract, linear and circular address calculation
// Loads and stores with a 5-bit constant offset
// Loads and stores with 15-bit constant offset (.D2 only)
};
//---------------------------------
// Operand types:
#define o_regpair o_idpspec0 // Register pair (A1:A0..B15:B14)
// Register pair is denoted by its
// even register in op.reg
// (Odd register keeps MSB)
#define o_spmask o_idpspec1 // unit mask (reg)
#define o_stgcyc o_idpspec2 // fstg/fcyc (value)
// o_phrase: the second register is held in secreg (specflag1)
#define secreg specflag1
// o_phrase, o_displ: mode
#define mode specflag2
#define src2 specflag2 // for field instructions
//------------------------------------------------------------------
#define funit segpref // Functional unit for insn
#define cond auxpref_u8[0] // The condition code of instruction
#define cflags auxpref_u8[1] // Various bit definitions:
# define aux_para 0x0001 // parallel execution with the next insn
# define aux_src2 0x0002 // src2 register for immediate form of
// field instructions is present at "Op1.src2"
# define aux_xp 0x0004 // X path is used
# define aux_pseudo 0x0008 // Pseudo instruction
//------------------------------------------------------------------
// condition codes:
#define cAL 0x0 // unconditional
#define cB0 0x2 // B0
#define cnB0 0x3 // !B0
#define cB1 0x4 // B1
#define cnB1 0x5 // !B1
#define cB2 0x6 // B2
#define cnB2 0x7 // !B2
#define cA1 0x8 // A1
#define cnA1 0x9 // !A1
#define cA2 0xA // A2
#define cnA2 0xB // !A2
//------------------------------------------------------------------
// Bit definitions. Just for convenience:
#define BIT0 0x00000001L
#define BIT1 0x00000002L
#define BIT2 0x00000004L
#define BIT3 0x00000008L
#define BIT4 0x00000010L
#define BIT5 0x00000020L
#define BIT6 0x00000040L
#define BIT7 0x00000080L
#define BIT8 0x00000100L
#define BIT9 0x00000200L
#define BIT10 0x00000400L
#define BIT11 0x00000800L
#define BIT12 0x00001000L
#define BIT13 0x00002000L
#define BIT14 0x00004000L
#define BIT15 0x00008000L
#define BIT16 0x00010000L
#define BIT17 0x00020000L
#define BIT18 0x00040000L
#define BIT19 0x00080000L
#define BIT20 0x00100000L
#define BIT21 0x00200000L
#define BIT22 0x00400000L
#define BIT23 0x00800000L
#define BIT24 0x01000000L
#define BIT25 0x02000000L
#define BIT26 0x04000000L
#define BIT27 0x08000000L
#define BIT28 0x10000000L
#define BIT29 0x20000000L
#define BIT30 0x40000000L
#define BIT31 0x80000000L
//------------------------------------------------------------------
enum RegNo ENUM8BIT
{
rA0, rA1, rA2, rA3, rA4, rA5, rA6, rA7,
rA8, rA9, rA10, rA11, rA12, rA13, rA14, rA15,
rA16, rA17, rA18, rA19, rA20, rA21, rA22, rA23,
rA24, rA25, rA26, rA27, rA28, rA29, rA30, rA31,
rB0, rB1, rB2, rB3, rB4, rB5, rB6, rB7,
rB8, rB9, rB10, rB11, rB12, rB13, rB14, rB15,
rB16, rB17, rB18, rB19, rB20, rB21, rB22, rB23,
rB24, rB25, rB26, rB27, rB28, rB29, rB30, rB31,
rAMR,
rCSR,
rIFR,
rISR,
rICR,
rIER,
rISTP,
rIRP,
rNRP,
rACR,
rADR,
rPCE1,
rFADCR,
rFAUCR,
rFMCR,
rTSCL,
rTSCH,
rILC,
rRILC,
rREP,
rDNUM,
rSSR,
rGPLYA,
rGPLYB,
rGFPGFR,
rTSR,
rITSR,
rNTSR,
rECR,
rEFR,
rIERR,
rVcs, rVds, // virtual registers for code and data segments
};
//------------------------------------------------------------------
// XXX this assumes the non-compact encoding
inline bool is_mvk_scst16_form(ea_t ea)
{
return ((get_dword(ea) >> 2) & 0x1F) == 0xA;
}
//------------------------------------------------------------------
void idaapi header(outctx_t &ctx);
void idaapi segstart(outctx_t &ctx, segment_t *seg);
void idaapi segend(outctx_t &ctx, segment_t *seg);
void idaapi data(outctx_t &ctx, bool analyze_only);
int idaapi ana(insn_t *insn);
int idaapi is_align_insn(ea_t ea);
ea_t find_first_insn_in_packet(ea_t ea);
#endif // _TMS6_HPP