update to ida 7.6, add builds
This commit is contained in:
1176
idasdk76/module/tms320c5/ana.cpp
Normal file
1176
idasdk76/module/tms320c5/ana.cpp
Normal file
File diff suppressed because it is too large
Load Diff
248
idasdk76/module/tms320c5/emu.cpp
Normal file
248
idasdk76/module/tms320c5/emu.cpp
Normal file
@@ -0,0 +1,248 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Version 3.05
|
||||
* Copyright (c) 1990-95 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* FIDO: 2:5020/209
|
||||
* E-mail: ig@estar.msk.su
|
||||
*/
|
||||
|
||||
#include "tms.hpp"
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static void set_immd_bit(const insn_t &insn)
|
||||
{
|
||||
set_immd(insn.ea);
|
||||
if ( is_defarg0(get_flags(insn.ea)) )
|
||||
return;
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case TMS_and:
|
||||
case TMS_bit:
|
||||
case TMS_bitt:
|
||||
case TMS_bsar:
|
||||
case TMS_cmpr:
|
||||
case TMS_in:
|
||||
case TMS_intr:
|
||||
case TMS_apl2:
|
||||
case TMS_opl2:
|
||||
case TMS_xpl2:
|
||||
case TMS_or:
|
||||
case TMS_rpt:
|
||||
case TMS_xc:
|
||||
case TMS_xor:
|
||||
case TMS_rptz:
|
||||
|
||||
case TMS2_bit:
|
||||
case TMS2_in:
|
||||
case TMS2_out:
|
||||
case TMS2_andk:
|
||||
case TMS2_ork:
|
||||
case TMS2_xork:
|
||||
case TMS2_rptk:
|
||||
op_num(insn.ea, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int tms320c5_t::find_ar(const insn_t &insn, ea_t *res) const
|
||||
{
|
||||
ea_t ea = insn.ea;
|
||||
for ( int i=0; i < get_lookback(); i++ )
|
||||
{
|
||||
ea = prevInstruction(ea);
|
||||
if ( !is_code(get_flags(ea)) )
|
||||
break;
|
||||
ushort _code = (ushort)get_wide_byte(ea);
|
||||
if ( isC2() )
|
||||
{
|
||||
switch ( _code >> 11 )
|
||||
{
|
||||
case 6: // LAR
|
||||
return 0;
|
||||
case 0x18: // LARK
|
||||
*res = map_data_ea(insn, _code & 0xFF);
|
||||
return 1;
|
||||
case 0x1A: // LRLK
|
||||
if ( (_code & 0xF8FF) == 0xD000 )
|
||||
{
|
||||
ushort b = (ushort)get_wide_byte(ea+1);
|
||||
*res = map_data_ea(insn, b);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
switch ( _code >> 11 )
|
||||
{
|
||||
case 0: // Load AR from addressed data
|
||||
return 0; // LAR found, unknown address
|
||||
case 0x16: // Load AR short immediate
|
||||
*res = map_data_ea(insn, _code & 0xFF);
|
||||
return 1;
|
||||
case 0x17: // Load AR long immediate
|
||||
if ( (_code & ~7) == 0xBF08 )
|
||||
{
|
||||
ushort b = (ushort)get_wide_byte(ea+1);
|
||||
*res = map_data_ea(insn, b);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void tms320c5_t::handle_operand(const insn_t &insn, const op_t &x, bool isload)
|
||||
{
|
||||
ea_t ea;
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_phrase: // 2 registers or indirect addressing
|
||||
if ( insn.itype != TMS_mar
|
||||
&& insn.itype != TMS2_mar
|
||||
&& find_ar(insn, &ea) )
|
||||
{
|
||||
goto SET_DREF;
|
||||
}
|
||||
case o_reg:
|
||||
case o_bit:
|
||||
case o_cond:
|
||||
break;
|
||||
case o_imm:
|
||||
{
|
||||
if ( !isload )
|
||||
goto badTouch;
|
||||
set_immd_bit(insn);
|
||||
flags_t F = get_flags(insn.ea);
|
||||
if ( op_adds_xrefs(F, x.n) )
|
||||
insn.add_off_drefs(x, dr_O, is_mpy(insn) ? OOF_SIGNED : 0);
|
||||
}
|
||||
break;
|
||||
case o_mem:
|
||||
ea = map_data_ea(insn, x);
|
||||
SET_DREF:
|
||||
insn.create_op_data(ea, x);
|
||||
insn.add_dref(ea, x.offb, isload ? dr_R : dr_W);
|
||||
if ( x.type == o_mem )
|
||||
{
|
||||
if ( insn.itype == TMS_dmov
|
||||
|| insn.itype == TMS_ltd
|
||||
|| insn.itype == TMS_macd
|
||||
|| insn.itype == TMS_madd
|
||||
|| insn.itype == TMS2_dmov
|
||||
|| insn.itype == TMS2_macd )
|
||||
{
|
||||
insn.add_dref(ea+1, x.offb, dr_W);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case o_near:
|
||||
{
|
||||
ea = map_code_ea(insn, x);
|
||||
if ( insn.itype == TMS_blpd
|
||||
|| insn.itype == TMS_mac
|
||||
|| insn.itype == TMS_macd
|
||||
|| insn.itype == TMS2_blkp
|
||||
|| insn.itype == TMS2_mac
|
||||
|| insn.itype == TMS2_macd )
|
||||
{
|
||||
goto SET_DREF;
|
||||
}
|
||||
ea_t segbase = (ea - x.addr) >> 4;
|
||||
uval_t thisseg = insn.cs;
|
||||
int iscall = has_insn_feature(insn.itype, CF_CALL);
|
||||
if ( insn.itype == TMS_rptb && is_tail(get_flags(ea)) )
|
||||
{
|
||||
// small hack to display end_loop-1 instead of before_end_loop+1
|
||||
ea++;
|
||||
}
|
||||
|
||||
cref_t xtype = iscall
|
||||
? (segbase == thisseg ? fl_CN : fl_CF)
|
||||
: (segbase == thisseg ? fl_JN : fl_JF);
|
||||
insn.add_cref(ea, x.offb, xtype);
|
||||
if ( iscall && !func_does_return(ea) )
|
||||
flow = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
badTouch:
|
||||
warning("%a: %s,%d: bad optype %d", insn.ea, insn.get_canon_mnem(ph), x.n, x.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static int isDelayedStop(ushort code)
|
||||
{
|
||||
switch ( code>>12 )
|
||||
{
|
||||
case 7:
|
||||
return (code & 0xFF00u) == 0x7D00u;
|
||||
case 0xB:
|
||||
return code == 0xBE21u;
|
||||
case 0xF:
|
||||
return (code & 0xEFFFu) == 0xEF00u;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool tms320c5_t::can_flow(const insn_t &insn) const
|
||||
{
|
||||
if ( isC2() )
|
||||
return true;
|
||||
flags_t F = get_flags(insn.ea);
|
||||
if ( !is_flow(F) )
|
||||
return true; // no previous instructions
|
||||
ea_t ea = prevInstruction(insn.ea);
|
||||
if ( insn.size == 2 ) // our instruction is long
|
||||
{
|
||||
; // nothing to do
|
||||
}
|
||||
else
|
||||
{ // our instruction short
|
||||
if ( (insn.ea-ea) == 2 ) // prev instruction long
|
||||
return true; // can flow always
|
||||
F = get_flags(ea);
|
||||
if ( !is_code(F) || !is_flow(F) )
|
||||
return true; // no prev instr...
|
||||
ea = prevInstruction(ea);
|
||||
}
|
||||
F = get_flags(ea);
|
||||
return !is_code(F) || !isDelayedStop((ushort)get_wide_byte(ea));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int tms320c5_t::emu(const insn_t &insn)
|
||||
{
|
||||
uint32 Feature = insn.get_canon_feature(ph);
|
||||
flow = ((Feature & CF_STOP) == 0);
|
||||
|
||||
if ( Feature & CF_USE1 ) handle_operand(insn, insn.Op1, true);
|
||||
if ( Feature & CF_USE2 ) handle_operand(insn, insn.Op2, true);
|
||||
if ( Feature & CF_JUMP )
|
||||
remember_problem(PR_JUMP, insn.ea);
|
||||
|
||||
if ( Feature & CF_CHG1 ) handle_operand(insn, insn.Op1, false);
|
||||
if ( Feature & CF_CHG2 ) handle_operand(insn, insn.Op2, false);
|
||||
|
||||
if ( flow && can_flow(insn) )
|
||||
add_cref(insn.ea, insn.ea+insn.size, fl_F);
|
||||
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case TMS_ldp: // change DP register
|
||||
case TMS2_ldp: // change DP register
|
||||
case TMS2_ldpk: // change DP register
|
||||
{
|
||||
uint v = (insn.Op1.type == o_imm) ? uint(insn.Op1.value) : -1u;
|
||||
split_sreg_range(get_item_end(insn.ea), rDP, v, SR_auto);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
297
idasdk76/module/tms320c5/ins.cpp
Normal file
297
idasdk76/module/tms320c5/ins.cpp
Normal file
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Version 3.05
|
||||
* Copyright (c) 1990-95 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* FIDO: 2:5020/209
|
||||
* E-mail: ig@estar.msk.su
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ida.hpp>
|
||||
#include <idp.hpp>
|
||||
#include "ins.hpp"
|
||||
|
||||
const instruc_t Instructions[] =
|
||||
{
|
||||
{ "", 0 }, // Unknown Operation
|
||||
{ "abs", 0 }, // Absolute value of Acc
|
||||
{ "adcb", 0 }, // Add ACCB to Acc With Carry
|
||||
{ "add", CF_USE1 }, // Add to Acc
|
||||
{ "addb", 0 }, // Add ACCB to Acc
|
||||
{ "addc", CF_USE1 }, // Add to Acc With Carry
|
||||
{ "adds", CF_USE1 }, // Add to Acc With Sign-Extension Suppressed
|
||||
{ "addt", CF_USE1 }, // Add to Acc With Shift Specified by TREG1
|
||||
{ "adrk", CF_USE1 }, // Add to Aux Register With Short Immediate
|
||||
{ "and", CF_USE1 }, // AND With Acc
|
||||
{ "andb", 0 }, // AND ACCD With Acc
|
||||
{ "apac", 0 }, // Add P Register to Acc
|
||||
{ "apl", CF_USE1|CF_CHG1 }, // AND Data Memory Value With DBMR or Long Constant
|
||||
{ "apl", CF_USE1|CF_USE2|CF_CHG2 }, // AND Data Memory Value With DBMR or Long Constant
|
||||
{ "b", CF_USE1|CF_STOP }, // Branch Unconditionally
|
||||
{ "bacc", CF_STOP|CF_JUMP }, // Branch to Location (Acc)
|
||||
{ "baccd", CF_JUMP }, // Branch to Location (Acc) Delayed
|
||||
{ "banz", CF_USE1 }, // Branch on Aux Register Not Zero
|
||||
{ "banzd", CF_USE1 }, // Branch on Aux Register Not Zero Delayed
|
||||
{ "bcnd", CF_USE1 }, // Branch Conditionally
|
||||
{ "bcndd", CF_USE1 }, // Branch Conditionally Delayed
|
||||
{ "bd", CF_USE1 }, // Branch Unconditionally Delayed
|
||||
{ "bit", CF_USE1|CF_USE2 }, // Test Bit
|
||||
{ "bitt", CF_USE1 }, // Test Bit Specified by TREG2
|
||||
{ "bldd", CF_USE1|CF_CHG2 }, // Block Move From Data Memory to Data Memory
|
||||
{ "bldp", CF_USE1 }, // Block Move From Data Memory to Program Memory
|
||||
{ "blpd", CF_USE1|CF_CHG2 }, // Block Move From Program Memory to Data Memory
|
||||
{ "bsar", CF_USE1 }, // Barrel Shift
|
||||
{ "cala", CF_CALL|CF_JUMP }, // Call Subroutine at (Acc)
|
||||
{ "calad", CF_CALL|CF_JUMP }, // Call Subroutine at (Acc) Delayed
|
||||
{ "call", CF_USE1|CF_CALL }, // Call Unconditionally
|
||||
{ "calld", CF_USE1|CF_CALL }, // Call Unconditionally Delayed
|
||||
{ "cc", CF_USE1|CF_CALL }, // Call Conditionally
|
||||
{ "ccd", CF_USE1|CF_CALL }, // Call Conditionally Delayed
|
||||
{ "clrc", CF_CHG1 }, // Clear Control Bit
|
||||
{ "cmpl", 0 }, // Complement Acc
|
||||
{ "cmpr", CF_USE1 }, // Compare Aux Register With ARCR
|
||||
{ "cpl", CF_USE1 }, // Compare DBMR or Long Immediate With Data Value
|
||||
{ "cpl", CF_USE1|CF_USE2 }, // Compare DBMR or Long Immediate With Data Value
|
||||
{ "crgt", 0 }, // Test for Acc Greater Than ACCB
|
||||
{ "crlt", 0 }, // Test for Acc Smaller Than ACCB
|
||||
{ "dmov", CF_USE1 }, // Data Move in Data Memory
|
||||
{ "estop", CF_STOP }, // Emulator Stop
|
||||
{ "exar", 0 }, // Exchange ACCB With Acc
|
||||
{ "idle", 0 }, // Idle Until Interrupt
|
||||
{ "idle2", 0 }, // Idle Until Interrupt - Low Power Mode
|
||||
{ "in", CF_CHG1|CF_USE2 }, // Input Data From Port
|
||||
{ "intr", CF_USE1 }, // Soft Interrupt
|
||||
{ "lacb", 0 }, // Load Acc With ACCB
|
||||
{ "lacc", CF_USE1 }, // Load Acc With Shift
|
||||
{ "lacl", CF_USE1 }, // Load Low Acc and Clear High Acc
|
||||
{ "lact", CF_USE1 }, // Load Acc With Shift Specified by TREG1
|
||||
{ "lamm", CF_USE1 }, // Load Acc With Memory-Mapped Register
|
||||
{ "lar", CF_CHG1|CF_USE2 }, // Load Aux Register
|
||||
{ "ldp", CF_USE1 }, // Load Data Memory Pointer
|
||||
{ "lmmr", CF_CHG1|CF_USE2 }, // Load Memory-Mapped Register
|
||||
{ "lph", CF_USE1 }, // Load Product High Register
|
||||
{ "lst", CF_USE1|CF_USE2 }, // Load Status Register
|
||||
{ "lt", CF_USE1 }, // Load TREG0
|
||||
{ "lta", CF_USE1 }, // Load TREG0 and Accumulate Previous Product
|
||||
{ "ltd", CF_USE1 }, // Load TREG0,Accumulate Previous Product and Move Data
|
||||
{ "ltp", CF_USE1 }, // Load TREG0 and Store P -> Acc
|
||||
{ "lts", CF_USE1 }, // Load TREG0 and Subtract Previous Product
|
||||
{ "mac", CF_USE1|CF_USE2 }, // Multiply and Accumulate
|
||||
{ "macd", CF_USE1|CF_USE2 }, // Multiply and Accumulate With Data Move
|
||||
{ "madd", CF_USE1 }, // Multiply and Accumulate With Data Move and Dynamic Addressing
|
||||
{ "mads", CF_USE1 }, // Multiply and Accumulate With Dynamic Addressing
|
||||
{ "mar", CF_USE1 }, // Modify Aux Register
|
||||
{ "mpy", CF_USE1 }, // Multiply
|
||||
{ "mpya", CF_USE1 }, // Multiply and Accumulate Previous Product
|
||||
{ "mpys", CF_USE1 }, // Multiply and Subtract Previous Product
|
||||
{ "mpyu", CF_USE1 }, // Multiply Unsigned
|
||||
{ "neg", 0 }, // Negate Acc
|
||||
{ "nmi", 0 }, // Nonmaskable Interrupt
|
||||
{ "nop", 0 }, // No Operation
|
||||
{ "norm", 0 }, // Normalize Contents of Acc
|
||||
{ "opl", CF_USE1|CF_CHG1 }, // OR With DBMS or Long Immediate
|
||||
{ "opl", CF_USE1|CF_USE2|CF_CHG2 }, // OR With DBMS or Long Immediate
|
||||
{ "or", CF_USE1 }, // OR With Acc
|
||||
{ "orb", 0 }, // OR ACCB With Accumulator
|
||||
{ "out", CF_USE1|CF_USE2 }, // Out Data to Port
|
||||
{ "pac", 0 }, // Load Acc <- P
|
||||
{ "pop", 0 }, // Pop Top of Stack to Low Acc
|
||||
{ "popd", CF_CHG1 }, // Pop Top of Stack to Data Memory
|
||||
{ "pshd", CF_USE1 }, // Push Data Memory Value Onto Stack
|
||||
{ "push", 0 }, // Push Low Acc Onto Stack
|
||||
{ "ret", CF_STOP }, // Return From Subroutine
|
||||
{ "retc", CF_USE1 }, // Return Conditionally
|
||||
{ "retcd", CF_USE1 }, // Return Conditionally Delayed
|
||||
{ "retd", 0 }, // Return From Subroutine Delayed
|
||||
{ "rete", CF_STOP }, // Enable Interrupts and Return From Interrupt
|
||||
{ "reti", CF_STOP }, // Return From Interrupt
|
||||
{ "rol", 0 }, // Rotate Acc Left
|
||||
{ "rolb", 0 }, // Rotate ACCB and Acc Left
|
||||
{ "ror", 0 }, // Rotate Acc Right
|
||||
{ "rorb", 0 }, // Rotate ACCB and Acc Right
|
||||
{ "rpt", CF_USE1 }, // Repeat Next Instruction
|
||||
{ "rptb", CF_USE1 }, // Repeat Block
|
||||
{ "rptz", CF_USE1 }, // Repeat Preceded by Clearing Acc and P
|
||||
{ "sacb", 0 }, // Store Acc in ACCB
|
||||
{ "sach", CF_CHG1 }, // Store High Acc With Shift
|
||||
{ "sacl", CF_CHG1 }, // Store Low Acc With Shift
|
||||
{ "samm", CF_CHG1 }, // Store Acc in Memory-Mapped Register
|
||||
{ "sar", CF_USE1|CF_CHG2 }, // Store Aux Register
|
||||
{ "sath", 0 }, // Barrel Shift Acc as Specified by TREG1(4)
|
||||
{ "satl", 0 }, // Barrel Shift Acc as Specified by TREG1(3-0)
|
||||
{ "sbb", 0 }, // Subtract ACCB From Acc
|
||||
{ "sbbb", 0 }, // Subtract ACCB From Acc With Borrow
|
||||
{ "sbrk", CF_USE1 }, // Subtract From Aux Register Short Immediate
|
||||
{ "setc", CF_CHG1 }, // Set Control Bit
|
||||
{ "sfl", 0 }, // Shift Acc Left
|
||||
{ "sflb", 0 }, // Shift ACCB and Acc Left
|
||||
{ "sfr", 0 }, // Shift Acc Right
|
||||
{ "sfrb", 0 }, // Shift ACCB and Acc Right
|
||||
{ "smmr", CF_USE1|CF_CHG2 }, // Store Memory-Mapped Register
|
||||
{ "spac", 0 }, // Subtract P From Acc
|
||||
{ "sph", CF_CHG1 }, // Store High P Register
|
||||
{ "spl", CF_CHG1 }, // Store Low P Register
|
||||
{ "splk", CF_USE1|CF_CHG2 }, // Store Parallel Long Immediate
|
||||
{ "spm", CF_USE1 }, // Store ACCB and Acc Right
|
||||
{ "sqra", CF_USE1 }, // Square and Accumulate Previous Product
|
||||
{ "sqrs", CF_USE1 }, // Square and Subtract Previous Product
|
||||
{ "sst", CF_USE1|CF_CHG2 }, // Store Status Register
|
||||
{ "sub", CF_USE1 }, // Subtract From Acc
|
||||
{ "subb", CF_USE1 }, // Subtract From Acc With Borrow
|
||||
{ "subc", CF_USE1 }, // Conditional Subtract
|
||||
{ "subs", CF_USE1 }, // Subtract From Acc With Sign-Extension Suppressed
|
||||
{ "subt", CF_USE1 }, // Subtract From Acc With Shift Specified by TREG1
|
||||
{ "tblr", CF_CHG1 }, // Table Read
|
||||
{ "tblw", CF_USE1 }, // Table Write
|
||||
{ "trap", 0 }, // Software Interrupt
|
||||
{ "xc", CF_USE1 }, // Execute Conditionally
|
||||
{ "xor", CF_USE1 }, // Exclusive-OR With Acc
|
||||
{ "xorb", 0 }, // Exclusive-OR of ACCB With Acc
|
||||
{ "xpl", CF_USE1|CF_CHG1 }, // Exclusive-OR Data Memory Value
|
||||
{ "xpl", CF_USE1|CF_USE2|CF_CHG2 }, // Exclusive-OR Data Memory Value
|
||||
{ "zalr", CF_USE1 }, // Zero Low Acc Load High Acc With Rounding
|
||||
{ "zap", 0 }, // Zero Acc and P
|
||||
{ "zpr", 0 }, // Zero P Register
|
||||
|
||||
//
|
||||
// TMS320C2x instructions
|
||||
//
|
||||
|
||||
{ "abs", 0 }, // Absolute value of accumulator
|
||||
{ "add", CF_USE1 }, // Add to accumulator with shift
|
||||
{ "addc", CF_USE1 }, // Add to accumulator with carry
|
||||
{ "addh", CF_USE1 }, // Add to high accumulator
|
||||
{ "addk", CF_USE1 }, // Add to accumulator short immediate
|
||||
{ "adds", CF_USE1 }, // Add to low accumulator with sign extension suppressed
|
||||
{ "addt", CF_USE1 }, // Add to accumulator with shift specified by T register
|
||||
{ "adlk", CF_USE1 }, // Add to accumulator long immediate with shift
|
||||
{ "adrk", CF_USE1 }, // Add to auxiliary register short immediate
|
||||
{ "and", CF_USE1 }, // And with accumulator
|
||||
{ "andk", CF_USE1 }, // And immediate with accumulator with shift
|
||||
{ "apac", 0 }, // Add P register to accumulator
|
||||
{ "b", CF_USE1|CF_STOP }, // Branch unconditionally
|
||||
{ "bacc", CF_JUMP|CF_STOP }, // Branch to address specified by accumulator
|
||||
{ "banz", CF_USE1 }, // Bnrach on auxiliary register not zero
|
||||
{ "bbnz", CF_USE1 }, // Branch if tc bit != 0
|
||||
{ "bbz", CF_USE1 }, // Branch if tc bit = 0
|
||||
{ "bc", CF_USE1 }, // Branch on carry
|
||||
{ "bgez", CF_USE1 }, // Branch if accumulator >= 0
|
||||
{ "bgz", CF_USE1 }, // Branch if accumulator > 0
|
||||
{ "bioz", CF_USE1 }, // Branch on i/o status = 0
|
||||
{ "bit", CF_USE1|CF_USE2 }, // Test bit
|
||||
{ "bitt", CF_USE1 }, // Test bit specifed by T register
|
||||
{ "blez", CF_USE1 }, // Branch if accumulator <= 0
|
||||
{ "blkd", CF_USE1|CF_CHG2 }, // Block move from data memory to data memory
|
||||
{ "blkp", CF_USE1|CF_CHG2 }, // Block move from program memory to data memory
|
||||
{ "blz", CF_USE1 }, // Branch if accumulator < 0
|
||||
{ "bnc", CF_USE1 }, // Branch on no carry
|
||||
{ "bnv", CF_USE1 }, // Branch if no overflow
|
||||
{ "bnz", CF_USE1 }, // Branch if accumulator != 0
|
||||
{ "bv", CF_USE1 }, // Branch on overflow
|
||||
{ "bz", CF_USE1 }, // Branch if accumulator = 0
|
||||
{ "cala", CF_CALL|CF_JUMP }, // Call subroutine indirect
|
||||
{ "call", CF_USE1|CF_CALL }, // Call subroutine
|
||||
{ "cmpl", 0 }, // Complement accumulator
|
||||
{ "cmpr", 0 }, // Compare auxiliary register with auxiliary register ar0
|
||||
{ "cnfd", 0 }, // Configure block as data memory
|
||||
{ "cnfp", 0 }, // Configure block as program memory
|
||||
{ "conf", 0 }, // Configure block as data/program memory
|
||||
{ "dint", 0 }, // Disable interrupt
|
||||
{ "dmov", CF_USE1 }, // Data move in data memory
|
||||
{ "eint", 0 }, // Enable interrupt
|
||||
{ "fort", 0 }, // Format serial port registers
|
||||
{ "idle", 0 }, // Idle until interrupt
|
||||
{ "in", CF_CHG1|CF_USE2 }, // Input data from port
|
||||
{ "lac", CF_USE1 }, // Load accumulator with shift
|
||||
{ "lack", CF_USE1 }, // Load accumulator short immediate
|
||||
{ "lact", CF_USE1 }, // Load accumulator with shift specified by T register
|
||||
{ "lalk", CF_USE1 }, // Load accumulator long immediate with shift
|
||||
{ "lar", 0 }, // Load auxiliary register
|
||||
{ "lark", CF_CHG1|CF_USE2 }, // Load auxiliary register short immediate
|
||||
{ "larp", 0 }, // Load auxiliary register pointer
|
||||
{ "ldp", CF_USE1 }, // Load data memory page pointer
|
||||
{ "ldpk", CF_USE1 }, // Load data memory page pointer immediate
|
||||
{ "lph", CF_USE1 }, // Load high P register
|
||||
{ "lrlk", CF_USE1 }, // Load auxiliary register long immediate
|
||||
{ "lst", CF_USE1 }, // Load status register ST0
|
||||
{ "lst1", CF_USE1 }, // Load status register ST1
|
||||
{ "lt", CF_USE1 }, // Load T register
|
||||
{ "lta", CF_USE1 }, // Load T register and accumulate previous product
|
||||
{ "ltd", CF_USE1 }, // Load T register, accumulate previous product and move data
|
||||
{ "ltp", CF_USE1 }, // Load T register and store P register in accumulator
|
||||
{ "lts", CF_USE1 }, // Load T register and subtract previous product
|
||||
{ "mac", CF_USE1|CF_USE2 }, // Multiply and accumulate
|
||||
{ "macd", CF_USE1|CF_USE2 }, // Multiply and accumulate with data move
|
||||
{ "mar", CF_USE1 }, // Modify auxiliary register
|
||||
{ "mpy", CF_USE1 }, // Multiply (with T register, store product in P register)
|
||||
{ "mpya", CF_USE1 }, // Multiply and accumulate previous product
|
||||
{ "mpyk", CF_USE1 }, // Multiply immediate
|
||||
{ "mpys", CF_USE1 }, // Multiply and subtract previous product
|
||||
{ "mpyu", CF_USE1 }, // Multiply unsigned
|
||||
{ "neg", 0 }, // Negate accumulator
|
||||
{ "nop", 0 }, // No operation
|
||||
{ "norm", 0 }, // Normalize contents of accumulator
|
||||
{ "or", CF_USE1 }, // Or with accumulator
|
||||
{ "ork", CF_USE1 }, // Or immediate with accumulator with shift
|
||||
{ "out", CF_USE1|CF_USE2 }, // Output data to port
|
||||
{ "pac", 0 }, // Load accumulator with P register
|
||||
{ "pop", 0 }, // Pop top of stack to low accumulator
|
||||
{ "popd", CF_CHG1 }, // Pop top of stack to data memory
|
||||
{ "pshd", CF_USE1 }, // Push data memory value onto stack
|
||||
{ "push", 0 }, // Push low accumulator onto stack
|
||||
{ "rc", 0 }, // Reset carry bit
|
||||
{ "ret", CF_STOP }, // Return from subroutine
|
||||
{ "rfsm", 0 }, // Reset serial port frame synchronization mode
|
||||
{ "rhm", 0 }, // Reset hold mode
|
||||
{ "rol", 0 }, // Rotate accumulator left
|
||||
{ "ror", 0 }, // Rotate acuumulator right
|
||||
{ "rovm", 0 }, // Reset overflow mode
|
||||
{ "rpt", CF_USE1 }, // Repeat instruction as specified by data memory value
|
||||
{ "rptk", CF_USE1 }, // Repeat instruction as specified by immediate value
|
||||
{ "rsxm", 0 }, // Reset sign extension mode
|
||||
{ "rtc", 0 }, // Reset test/control flag
|
||||
{ "rtxm", 0 }, // Reset serial port transmit mode
|
||||
{ "rxf", 0 }, // Reset external flag
|
||||
{ "sach", CF_CHG1 }, // Store high accumulator with shift
|
||||
{ "sacl", CF_CHG1 }, // Store low accumulator with shift
|
||||
{ "sar", CF_USE1|CF_CHG2 }, // Store auxiliary register
|
||||
{ "sblk", CF_USE1 }, // Subtract from accumulator long immediate with shift
|
||||
{ "sbrk", CF_USE1 }, // Subtract from auxiliary register short immediate
|
||||
{ "sc", 0 }, // Set carry bit
|
||||
{ "sfl", 0 }, // Shift accumulator left
|
||||
{ "sfr", 0 }, // Shift accumulator right
|
||||
{ "sfsm", 0 }, // Set serial port frame synchronization mode
|
||||
{ "shm", 0 }, // Set hold mode
|
||||
{ "sovm", 0 }, // Set overflow mode
|
||||
{ "spac", 0 }, // Subtract P register from accumulator
|
||||
{ "sph", CF_CHG1 }, // Store high P register
|
||||
{ "spl", CF_CHG1 }, // Store low P register
|
||||
{ "spm", CF_USE1 }, // Set P register output shift mode
|
||||
{ "sqra", CF_USE1 }, // Square and accumulate
|
||||
{ "sqrs", CF_USE1 }, // Square and subtract previous product
|
||||
{ "sst", CF_CHG1 }, // Store status register ST0
|
||||
{ "sst1", CF_CHG1 }, // Store status register ST1
|
||||
{ "ssxm", 0 }, // Set sign extension mode
|
||||
{ "stc", 0 }, // Set test/control flag
|
||||
{ "stxm", 0 }, // Set serial port transmit mode
|
||||
{ "sub", CF_USE1 }, // Subtract from accumulator with shift
|
||||
{ "subb", CF_USE1 }, // Subtract from accumulator with borrow
|
||||
{ "subc", CF_USE1 }, // Conditional subtract
|
||||
{ "subh", CF_USE1 }, // Subtract from high accumulator
|
||||
{ "subk", CF_USE1 }, // Subtract from accumulator shoft immediate
|
||||
{ "subs", CF_USE1 }, // Subtract from low accumulator with sign extension suppressed
|
||||
{ "subt", CF_USE1 }, // Subtract from accumulator with shift specified by T register
|
||||
{ "sxf", 0 }, // Set external flag
|
||||
{ "tblr", CF_CHG1 }, // Table read
|
||||
{ "tblw", CF_USE1 }, // Table write
|
||||
{ "trap", 0 }, // Software interrupt
|
||||
{ "xor", CF_USE1 }, // Exclusive or with accumulator
|
||||
{ "xork", CF_USE1 }, // Exclusive or immediate with accumulator with shift
|
||||
{ "zac", 0 }, // Zero accumulator
|
||||
{ "zalh", CF_USE1 }, // Zero low accumulator and load high accumulator
|
||||
{ "zalr", CF_USE1 }, // Zero low accumulator and load high accumulator with rounding
|
||||
{ "zals", CF_USE1 }, // Zero low accumulator and load high accumulator with sign extension suppressed
|
||||
};
|
||||
|
||||
CASSERT(qnumber(Instructions) == TMS_last);
|
||||
298
idasdk76/module/tms320c5/ins.hpp
Normal file
298
idasdk76/module/tms320c5/ins.hpp
Normal file
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-2021 Hex-Rays
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __INSTRS_HPP
|
||||
#define __INSTRS_HPP
|
||||
|
||||
extern const instruc_t Instructions[];
|
||||
|
||||
enum nameNum ENUM_SIZE(uint16)
|
||||
{
|
||||
TMS_null = 0, // Unknown Operation
|
||||
TMS_abs, // Absolute value of Acc
|
||||
TMS_adcb, // Add ACCB to Acc With Carry
|
||||
TMS_add, // Add to Acc
|
||||
TMS_addb, // Add ACCB to Acc
|
||||
TMS_addc, // Add to Acc With Carry
|
||||
TMS_adds, // Add to Acc With Sign-Extension Suppressed
|
||||
TMS_addt, // Add to Acc With Shift Specified by TREG1
|
||||
TMS_adrk, // Add to Aux Register With Short Immediate
|
||||
TMS_and, // AND With Acc
|
||||
TMS_andb, // AND ACCD With Acc
|
||||
TMS_apac, // Add P Register to Acc
|
||||
TMS_apl, // AND Data Memory Value With DBMR
|
||||
TMS_apl2, // AND Data Memory Value With Long Constant
|
||||
TMS_b, // Branch Unconditionally
|
||||
TMS_bacc, // Branch to Location (Acc)
|
||||
TMS_baccd, // Branch to Location (Acc) Delayed
|
||||
TMS_banz, // Branch on Aux Register Not Zero
|
||||
TMS_banzd, // Branch on Aux Register Not Zero Delayed
|
||||
TMS_bcnd, // Branch Conditionally
|
||||
TMS_bcndd, // Branch Conditionally Delayed
|
||||
TMS_bd, // Branch Unconditionally Delayed
|
||||
TMS_bit, // Test Bit
|
||||
TMS_bitt, // Test Bit Specified by TREG2
|
||||
TMS_bldd, // Block Move From Data Memory to Data Memory
|
||||
TMS_bldp, // Block Move From Data Memory to Program Memory
|
||||
TMS_blpd, // Block Move From Program Memory to Data Memory
|
||||
TMS_bsar, // Barrel Shift
|
||||
TMS_cala, // Call Subroutine at (Acc)
|
||||
TMS_calad, // Call Subroutine at (Acc) Delayed
|
||||
TMS_call, // Call Unconditionally
|
||||
TMS_calld, // Call Unconditionally Delayed
|
||||
TMS_cc, // Call Conditionally
|
||||
TMS_ccd, // Call Conditionally Delayed
|
||||
TMS_clrc, // Clear Control Bit
|
||||
TMS_cmpl, // Complement Acc
|
||||
TMS_cmpr, // Compare Aux Register With ARCR
|
||||
TMS_cpl, // Compare DBMR With Data Value
|
||||
TMS_cpl2, // Compare Long Immediate With Data Value
|
||||
TMS_crgt, // Test for Acc Greater Than ACCB
|
||||
TMS_crlt, // Test for Acc Smaller Than ACCB
|
||||
TMS_dmov, // Data Move in Data Memory
|
||||
TMS_estop, // Emulator Stop
|
||||
TMS_exar, // Exchange ACCB With Acc
|
||||
TMS_idle, // Idle Until Interrupt
|
||||
TMS_idle2, // Idle Until Interrupt - Low Power Mode
|
||||
TMS_in, // Input Data From Port
|
||||
TMS_intr, // Soft Interrupt
|
||||
TMS_lacb, // Load Acc With ACCB
|
||||
TMS_lacc, // Load Acc With Shift
|
||||
TMS_lacl, // Load Low Acc and Clear High Acc
|
||||
TMS_lact, // Load Acc With Shift Specified by TREG1
|
||||
TMS_lamm, // Load Acc With Memory-Mapped Register
|
||||
TMS_lar, // Load Aux Register
|
||||
TMS_ldp, // Load Data Memory Pointer
|
||||
TMS_lmmr, // Load Memory-Mapped Register
|
||||
TMS_lph, // Load Product High Register
|
||||
TMS_lst, // Load Status Register
|
||||
TMS_lt, // Load TREG0
|
||||
TMS_lta, // Load TREG0 and Accumulate Previous Product
|
||||
TMS_ltd, // Load TREG0,Accumulate Previous Product and Move Data
|
||||
TMS_ltp, // Load TREG0 and Store P -> Acc
|
||||
TMS_lts, // Load TREG0 and Subtract Previous Product
|
||||
TMS_mac, // Multiply and Accumulate
|
||||
TMS_macd, // Multiply and Accumulate With Data Move
|
||||
TMS_madd, // Multiply and Accumulate With Data Move and Dynamic Addressing
|
||||
TMS_mads, // Multiply and Accumulate With Dynamic Addressing
|
||||
TMS_mar, // Modify Aux Register
|
||||
TMS_mpy, // Multiply
|
||||
TMS_mpya, // Multiply and Accumulate Previous Product
|
||||
TMS_mpys, // Multiply and Subtract Previous Product
|
||||
TMS_mpyu, // Multiply Unsigned
|
||||
TMS_neg, // Negate Acc
|
||||
TMS_nmi, // Nonmaskable Interrupt
|
||||
TMS_nop, // No Operation
|
||||
TMS_norm, // Normalize Contents of Acc
|
||||
TMS_opl, // OR With DBMS
|
||||
TMS_opl2, // OR With Long Immediate
|
||||
TMS_or, // OR With Acc
|
||||
TMS_orb, // OR ACCB With Accumulator
|
||||
TMS_out, // Out Data to Port
|
||||
TMS_pac, // Load Acc <- P
|
||||
TMS_pop, // Pop Top of Stack to Low Acc
|
||||
TMS_popd, // Pop Top of Stack to Data Memory
|
||||
TMS_pshd, // Push Data Memory Value Onto Stack
|
||||
TMS_push, // Push Low Acc Onto Stack
|
||||
TMS_ret, // Return From Subroutine
|
||||
TMS_retc, // Return Conditionally
|
||||
TMS_retcd, // Return Conditionally Delayed
|
||||
TMS_retd, // Return From Subroutine Delayed
|
||||
TMS_rete, // Enable Interrupts and Return From Interrupt
|
||||
TMS_reti, // Return From Interrupt
|
||||
TMS_rol, // Rotate Acc Left
|
||||
TMS_rolb, // Rotate ACCB and Acc Left
|
||||
TMS_ror, // Rotate Acc Right
|
||||
TMS_rorb, // Rotate ACCB and Acc Right
|
||||
TMS_rpt, // Repeat Next Instruction
|
||||
TMS_rptb, // Repeat Block
|
||||
TMS_rptz, // Repeat Preceded by Clearing Acc and P
|
||||
TMS_sacb, // Store Acc in ACCB
|
||||
TMS_sach, // Store High Acc With Shift
|
||||
TMS_sacl, // Store Low Acc With Shift
|
||||
TMS_samm, // Store Acc in Memory-Mapped Register
|
||||
TMS_sar, // Store Aux Register
|
||||
TMS_sath, // Barrel Shift Acc as Specified by TREG1(4)
|
||||
TMS_satl, // Barrel Shift Acc as Specified by TREG1(3-0)
|
||||
TMS_sbb, // Subtract ACCB From Acc
|
||||
TMS_sbbb, // Subtract ACCB From Acc With Borrow
|
||||
TMS_sbrk, // Subtract From Aux Register Short Immediate
|
||||
TMS_setc, // Set Control Bit
|
||||
TMS_sfl, // Shift Acc Left
|
||||
TMS_sflb, // Shift ACCB and Acc Left
|
||||
TMS_sfr, // Shift Acc Right
|
||||
TMS_sfrb, // Shift ACCB and Acc Right
|
||||
TMS_smmr, // Store Memory-Mapped Register
|
||||
TMS_spac, // Subtract P From Acc
|
||||
TMS_sph, // Store High P Register
|
||||
TMS_spl, // Store Low P Register
|
||||
TMS_splk, // Store Parallel Long Immediate
|
||||
TMS_spm, // Store ACCB and Acc Right
|
||||
TMS_sqra, // Square and Accumulate Previous Product
|
||||
TMS_sqrs, // Square and Subtract Previous Product
|
||||
TMS_sst, // Store Status Register
|
||||
TMS_sub, // Subtract From Acc
|
||||
TMS_subb, // Subtract From Acc With Borrow
|
||||
TMS_subc, // Conditional Subtract
|
||||
TMS_subs, // Subtract From Acc With Sign-Extension Suppressed
|
||||
TMS_subt, // Subtract From Acc With Shift Specified by TREG1
|
||||
TMS_tblr, // Table Read
|
||||
TMS_tblw, // Table Write
|
||||
TMS_trap, // Software Interrupt
|
||||
TMS_xc, // Execute Conditionally
|
||||
TMS_xor, // Exclusive-OR With Acc
|
||||
TMS_xorb, // Exclusive-OR of ACCB With Acc
|
||||
TMS_xpl, // Exclusive-OR Data Memory Value
|
||||
TMS_xpl2, // Exclusive-OR Data Memory Value
|
||||
TMS_zalr, // Zero Low Acc Load High Acc With Rounding
|
||||
TMS_zap, // Zero Acc and P
|
||||
TMS_zpr, // Zero P Register
|
||||
|
||||
//
|
||||
// TMS320C2x instructions
|
||||
//
|
||||
|
||||
TMS2_abs, // Absolute value of accumulator
|
||||
TMS2_add, // Add to accumulator with shift
|
||||
TMS2_addc, // Add to accumulator with carry
|
||||
TMS2_addh, // Add to high accumulator
|
||||
TMS2_addk, // Add to accumulator short immediate
|
||||
TMS2_adds, // Add to low accumulator with sign extension suppressed
|
||||
TMS2_addt, // Add to accumulator with shift specified by T register
|
||||
TMS2_adlk, // Add to accumulator long immediate with shift
|
||||
TMS2_adrk, // Add to auxiliary register short immediate
|
||||
TMS2_and, // And with accumulator
|
||||
TMS2_andk, // And immediate with accumulator with shift
|
||||
TMS2_apac, // App P register to accumulator
|
||||
TMS2_b, // Branch unconditionally
|
||||
TMS2_bacc, // Branch to address specified by accumulator
|
||||
TMS2_banz, // Bnrach on auxiliary register not zero
|
||||
TMS2_bbnz, // Branch if tc bit != 0
|
||||
TMS2_bbz, // Branch if tc bit = 0
|
||||
TMS2_bc, // Branch on carry
|
||||
TMS2_bgez, // Branch if accumulator >= 0
|
||||
TMS2_bgz, // Branch if accumulator > 0
|
||||
TMS2_bioz, // Branch on i/o status = 0
|
||||
TMS2_bit, // Test bit
|
||||
TMS2_bitt, // Test bit specifed by T register
|
||||
TMS2_blez, // Branch if accumulator <= 0
|
||||
TMS2_blkd, // Block move from data memory to data memory
|
||||
TMS2_blkp, // Block move from program memory to data memory
|
||||
TMS2_blz, // Branch if accumulator < 0
|
||||
TMS2_bnc, // Branch on no carry
|
||||
TMS2_bnv, // Branch if no overflow
|
||||
TMS2_bnz, // Branch if accumulator != 0
|
||||
TMS2_bv, // Branch on overflow
|
||||
TMS2_bz, // Branch if accumulator = 0
|
||||
TMS2_cala, // Call subroutine indirect
|
||||
TMS2_call, // Call subroutine
|
||||
TMS2_cmpl, // Complement accumulator
|
||||
TMS2_cmpr, // Compare auxiliary register with auxiliary register ar0
|
||||
TMS2_cnfd, // Configure block as data memory
|
||||
TMS2_cnfp, // Configure block as program memory
|
||||
TMS2_conf, // Configure block as data/program memory
|
||||
TMS2_dint, // Disable interrupt
|
||||
TMS2_dmov, // Data move in data memory
|
||||
TMS2_eint, // Enable interrupt
|
||||
TMS2_fort, // Format serial port registers
|
||||
TMS2_idle, // Idle until interrupt
|
||||
TMS2_in, // Input data from port
|
||||
TMS2_lac, // Load accumulator with shift
|
||||
TMS2_lack, // Load accumulator short immediate
|
||||
TMS2_lact, // Load accumulator with shift specified by T register
|
||||
TMS2_lalk, // Load accumulator long immediate with shift
|
||||
TMS2_lar, // Load auxiliary register
|
||||
TMS2_lark, // Load auxiliary register short immediate
|
||||
TMS2_larp, // Load auxiliary register pointer
|
||||
TMS2_ldp, // Load data memory page pointer
|
||||
TMS2_ldpk, // Load data memory page pointer immediate
|
||||
TMS2_lph, // Load high P register
|
||||
TMS2_lrlk, // Load auxiliary register long immediate
|
||||
TMS2_lst, // Load status register ST0
|
||||
TMS2_lst1, // Load status register ST1
|
||||
TMS2_lt, // Load T register
|
||||
TMS2_lta, // Load T register and accumulate previous product
|
||||
TMS2_ltd, // Load T register, accumulate previous product and move data
|
||||
TMS2_ltp, // Load T register and store P register in accumulator
|
||||
TMS2_lts, // Load T register and subtract previous product
|
||||
TMS2_mac, // Multiply and accumulate
|
||||
TMS2_macd, // Multiply and accumulate with data move
|
||||
TMS2_mar, // Modify auxiliary register
|
||||
TMS2_mpy, // Multiply (with T register, store product in P register)
|
||||
TMS2_mpya, // Multiply and accumulate previous product
|
||||
TMS2_mpyk, // Multiply immediate
|
||||
TMS2_mpys, // Multiply and subtract previous product
|
||||
TMS2_mpyu, // Multiply unsigned
|
||||
TMS2_neg, // Negate accumulator
|
||||
TMS2_nop, // No operation
|
||||
TMS2_norm, // Normalize contents of accumulator
|
||||
TMS2_or, // Or with accumulator
|
||||
TMS2_ork, // Or immediate with accumulator with shift
|
||||
TMS2_out, // Output data to port
|
||||
TMS2_pac, // Load accumulator with P register
|
||||
TMS2_pop, // Pop top of stack to low accumulator
|
||||
TMS2_popd, // Pop top of stack to data memory
|
||||
TMS2_pshd, // Push data memory value onto stack
|
||||
TMS2_push, // Push low accumulator onto stack
|
||||
TMS2_rc, // Reset carry bit
|
||||
TMS2_ret, // Return from subroutine
|
||||
TMS2_rfsm, // Reset serial port frame synchronization mode
|
||||
TMS2_rhm, // Reset hold mode
|
||||
TMS2_rol, // Rotate accumulator left
|
||||
TMS2_ror, // Rotate acuumulator right
|
||||
TMS2_rovm, // Reset overflow mode
|
||||
TMS2_rpt, // Repeat instruction as specified by data memory value
|
||||
TMS2_rptk, // Repeat instruction as specified by immediate value
|
||||
TMS2_rsxm, // Reset sign extension mode
|
||||
TMS2_rtc, // Reset test/control flag
|
||||
TMS2_rtxm, // Reset serial port transmit mode
|
||||
TMS2_rxf, // Reset external flag
|
||||
TMS2_sach, // Store high accumulator with shift
|
||||
TMS2_sacl, // Store low accumulator with shift
|
||||
TMS2_sar, // Store auxiliary register
|
||||
TMS2_sblk, // Subtract from accumulator long immediate with shift
|
||||
TMS2_sbrk, // Subtract from auxiliary register short immediate
|
||||
TMS2_sc, // Set carry bit
|
||||
TMS2_sfl, // Shift accumulator left
|
||||
TMS2_sfr, // Shift accumulator right
|
||||
TMS2_sfsm, // Set serial port frame synchronization mode
|
||||
TMS2_shm, // Set hold mode
|
||||
TMS2_sovm, // Set overflow mode
|
||||
TMS2_spac, // Subtract P register from accumulator
|
||||
TMS2_sph, // Store high P register
|
||||
TMS2_spl, // Store low P register
|
||||
TMS2_spm, // Set P register output shift mode
|
||||
TMS2_sqra, // Square and accumulate
|
||||
TMS2_sqrs, // Square and subtract previous product
|
||||
TMS2_sst, // Store status register ST0
|
||||
TMS2_sst1, // Store status register ST1
|
||||
TMS2_ssxm, // Set sign extension mode
|
||||
TMS2_stc, // Set test/control flag
|
||||
TMS2_stxm, // Set serial port transmit mode
|
||||
TMS2_sub, // Subtract from accumulator with shift
|
||||
TMS2_subb, // Subtract from accumulator with borrow
|
||||
TMS2_subc, // Conditional subtract
|
||||
TMS2_subh, // Subtract from high accumulator
|
||||
TMS2_subk, // Subtract from accumulator shoft immediate
|
||||
TMS2_subs, // Subtract from low accumulator with sign extension suppressed
|
||||
TMS2_subt, // Subtract from accumulator with shift specified by T register
|
||||
TMS2_sxf, // Set external flag
|
||||
TMS2_tblr, // Table read
|
||||
TMS2_tblw, // Table write
|
||||
TMS2_trap, // Software interrupt
|
||||
TMS2_xor, // Exclusive or with accumulator
|
||||
TMS2_xork, // Exclusive or immediate with accumulator with shift
|
||||
TMS2_zac, // Zero accumulator
|
||||
TMS2_zalh, // Zero low accumulator and load high accumulator
|
||||
TMS2_zalr, // Zero low accumulator and load high accumulator with rounding
|
||||
TMS2_zals, // Zero low accumulator and load high accumulator with sign extension suppressed
|
||||
|
||||
TMS_last,
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
46
idasdk76/module/tms320c5/makefile
Normal file
46
idasdk76/module/tms320c5/makefile
Normal file
@@ -0,0 +1,46 @@
|
||||
PROC=tms320c5
|
||||
|
||||
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)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
|
||||
ana.cpp ins.hpp tms.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)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
|
||||
emu.cpp ins.hpp tms.hpp
|
||||
$(F)ins$(O) : $(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)nalt.hpp \
|
||||
$(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ins.cpp ins.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)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
|
||||
ins.hpp out.cpp tms.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)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
|
||||
ins.hpp reg.cpp tms.hpp
|
||||
458
idasdk76/module/tms320c5/out.cpp
Normal file
458
idasdk76/module/tms320c5/out.cpp
Normal file
@@ -0,0 +1,458 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Version 3.05
|
||||
* Copyright (c) 1990-95 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* FIDO: 2:5020/209
|
||||
* E-mail: ig@estar.msk.su
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tms.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_tms320c5_t : public outctx_t
|
||||
{
|
||||
out_tms320c5_t(void) = delete; // not used
|
||||
void set_has_phrase(void) { user_data = (void*)1; }
|
||||
bool has_phrase() const { return user_data != NULL; }
|
||||
const tms320c5_t &pm() const { return *static_cast<tms320c5_t *>(procmod); }
|
||||
|
||||
public:
|
||||
bool out_operand(const op_t &x);
|
||||
void out_insn(void);
|
||||
void outreg(int r) { out_register(ph.reg_names[r]); }
|
||||
void OutDecimal(uval_t x);
|
||||
int outnextar(const op_t &o, bool comma);
|
||||
bool shouldIndent(void) const;
|
||||
void outphraseAr(void);
|
||||
void OutImmVoid(const op_t &x);
|
||||
};
|
||||
CASSERT(sizeof(out_tms320c5_t) == sizeof(outctx_t));
|
||||
|
||||
DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_tms320c5_t)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static const char *const phrases[] =
|
||||
{
|
||||
"*", "*-", "*+", "?",
|
||||
"*br0-", "*0-", "*0+", "*br0+"
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_tms320c5_t::OutDecimal(uval_t x)
|
||||
{
|
||||
char buf[40];
|
||||
qsnprintf(buf, sizeof(buf), "%" FMT_EA "u", x);
|
||||
out_line(buf, COLOR_NUMBER);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool is_mpy(const insn_t &insn)
|
||||
{
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case TMS_mpy: // Multiply
|
||||
case TMS_mpya: // Multiply and Accumulate Previous Product
|
||||
case TMS_mpys: // Multiply and Subtract Previous Product
|
||||
case TMS2_mpy: // Multiply (with T register, store product in P register)
|
||||
case TMS2_mpya: // Multiply and accumulate previous product
|
||||
case TMS2_mpyk: // Multiply immediate
|
||||
case TMS2_mpys: // Multiply and subtract previous product
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool out_tms320c5_t::out_operand(const op_t &x)
|
||||
{
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_reg:
|
||||
outreg(x.reg);
|
||||
break;
|
||||
case o_phrase:
|
||||
QASSERT(10087, (x.phrase>>4) < qnumber(phrases));
|
||||
out_line(phrases[x.phrase>>4], COLOR_SYMBOL);
|
||||
set_has_phrase();
|
||||
break;
|
||||
case o_imm:
|
||||
switch ( x.sib )
|
||||
{
|
||||
default:
|
||||
{
|
||||
if ( !pm().isC2() )
|
||||
out_symbol('#');
|
||||
flags_t saved = F;
|
||||
if ( !is_defarg(F, x.n)
|
||||
&& (is_mpy(insn) || is_invsign(insn.ea, F, x.n)) )
|
||||
{
|
||||
F |= dec_flag();
|
||||
}
|
||||
int outflags = OOFW_16|(is_mpy(insn) ? OOF_SIGNED : 0);
|
||||
out_value(x, outflags);
|
||||
F = saved;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
out_value(x, OOF_NUMBER|OOFS_NOSIGN);
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
OutDecimal(x.value);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case o_near:
|
||||
if ( insn.itype == TMS_blpd )
|
||||
out_symbol('#');
|
||||
// fallthrough
|
||||
case o_mem:
|
||||
{
|
||||
if ( insn.itype == TMS_bldd && x.sib )
|
||||
out_symbol('#');
|
||||
ea_t v = map_ea(insn, x, x.type == o_near);
|
||||
bool rptb_tail = false;
|
||||
uval_t addr = x.addr;
|
||||
if ( insn.itype == TMS_rptb && is_tail(get_flags(v)) )
|
||||
{
|
||||
// small hack to display end_loop-1 instead of before_end_loop+1
|
||||
v++;
|
||||
addr++;
|
||||
rptb_tail = true;
|
||||
}
|
||||
bool ok = out_name_expr(x, v, addr);
|
||||
if ( !ok )
|
||||
{
|
||||
out_value(x, OOF_ADDR|OOF_NUMBER|OOFS_NOSIGN|OOFW_16);
|
||||
remember_problem(PR_NONAME, insn.ea);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( rptb_tail )
|
||||
{
|
||||
out_symbol('-');
|
||||
out_line("1", COLOR_NUMBER);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case o_void:
|
||||
return 0;
|
||||
case o_bit:
|
||||
{
|
||||
static const char *const bitnames[] =
|
||||
{
|
||||
"intm", "ovm", "cnf", "sxm",
|
||||
"hm", "tc", "xf", "c"
|
||||
};
|
||||
out_keyword(bitnames[uchar(x.value)]);
|
||||
}
|
||||
break;
|
||||
case o_cond:
|
||||
{
|
||||
int mask = int(x.value>>0) & 0xF;
|
||||
int cond = int(x.value>>4) & 0xF;
|
||||
int comma = 1;
|
||||
out_tagon(COLOR_KEYWORD);
|
||||
switch ( (mask>>2) & 3 ) // Z L
|
||||
{
|
||||
case 0:
|
||||
comma = 0;
|
||||
break;
|
||||
case 1:
|
||||
out_line((cond>>2)&1 ? "lt" : "gt");
|
||||
break;
|
||||
case 2:
|
||||
out_line((cond>>2)&2 ? "eq" : "neq");
|
||||
break;
|
||||
case 3:
|
||||
switch ( (cond>>2)&3 )
|
||||
{
|
||||
case 2: out_line("geq"); break;
|
||||
case 3: out_line("leq"); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ( mask & 1 ) // C
|
||||
{
|
||||
if ( comma )
|
||||
out_char(',');
|
||||
if ( (cond & 1) == 0 )
|
||||
out_char('n');
|
||||
out_char('c');
|
||||
comma = 1;
|
||||
}
|
||||
if ( mask & 2 ) // V
|
||||
{
|
||||
if ( comma )
|
||||
out_char(',');
|
||||
if ( (cond & 2) == 0 )
|
||||
out_char('n');
|
||||
out_char('o');
|
||||
out_char('v');
|
||||
comma = 1;
|
||||
}
|
||||
static const char *const TP[] = { "bio", "tc", "ntc", NULL };
|
||||
const char *ptr = TP[int(x.value>>8) & 3];
|
||||
if ( ptr != NULL )
|
||||
{
|
||||
if ( comma )
|
||||
out_char(',');
|
||||
out_line(ptr);
|
||||
}
|
||||
out_tagoff(COLOR_KEYWORD);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
warning("out: %a: bad optype %d", insn.ea, x.type);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int out_tms320c5_t::outnextar(const op_t &o, bool comma)
|
||||
{
|
||||
if ( o.type == o_phrase && (o.phrase & 8) != 0 )
|
||||
{
|
||||
if ( comma )
|
||||
{
|
||||
out_symbol(',');
|
||||
out_char(' ');
|
||||
}
|
||||
outreg(rAr0+(o.phrase&7));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static int isDelayed(ushort code)
|
||||
{
|
||||
// 7D?? BD 0111 1101 1AAA AAAA + 1 Branch unconditional with AR update delayed
|
||||
// 7E?? CALLD 0111 1110 1AAA AAAA + 1 Call unconditional with AR update delayed
|
||||
// 7F?? BANZD 0111 1111 1AAA AAAA + 1 Branch AR=0 with AR update delayed
|
||||
// BE3D CALAD 1011 1110 0011 1101 Call subroutine addressed by ACC delayed
|
||||
// BE21 BACCD 1011 1110 0010 0001 Branch addressed by ACC delayed
|
||||
// FF00 RETD 1111 1111 0000 0000 Return, delayed
|
||||
// F??? CCD 1111 10TP ZLVC ZLVC + 1 Call conditional delayed
|
||||
// F??? RETCD 1111 11TP ZLVC ZLVC Return conditional delayed
|
||||
// F??? BCNDD 1111 00TP ZLVC ZLVC + 1 Branch conditional delayed
|
||||
ushort subcode;
|
||||
switch ( code>>12 )
|
||||
{
|
||||
case 7:
|
||||
subcode = (code >> 7);
|
||||
return subcode == 0xFB || subcode == 0xFD || subcode == 0xFF;
|
||||
case 0xB:
|
||||
return code == 0xBE21u || code == 0xBE3Du;
|
||||
case 0xF:
|
||||
if ( code == 0xFF00 )
|
||||
return 1;
|
||||
subcode = (code & 0x0C00);
|
||||
return subcode != 0x400;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
ea_t prevInstruction(ea_t ea)
|
||||
{
|
||||
ea--;
|
||||
if ( !is_code(get_flags(ea)) )
|
||||
ea--;
|
||||
return ea;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool out_tms320c5_t::shouldIndent(void) const
|
||||
{
|
||||
if ( pm().isC2() )
|
||||
return false; // TMS320C2 - no indention
|
||||
if ( !is_flow(F) )
|
||||
return false; // no previous instructions
|
||||
ea_t ea = prevInstruction(insn.ea);
|
||||
flags_t flags = get_flags(ea);
|
||||
if ( !is_code(flags) )
|
||||
return false;
|
||||
if ( isDelayed((ushort)get_wide_byte(ea)) )
|
||||
return true;
|
||||
if ( insn.size == 2 ) // our instruction is long
|
||||
{
|
||||
; // nothing to do
|
||||
}
|
||||
else
|
||||
{ // our instruction short
|
||||
if ( (insn.ea-ea) == 2 ) // prev instruction long
|
||||
return false; // can't be executed in delayed manner
|
||||
if ( !is_flow(flags) )
|
||||
return false; // no prev instr...
|
||||
ea = prevInstruction(ea);
|
||||
flags = get_flags(ea);
|
||||
}
|
||||
return is_code(flags) && isDelayed((ushort)get_wide_byte(ea));
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_tms320c5_t::outphraseAr(void)
|
||||
{
|
||||
ea_t ar;
|
||||
if ( pm().find_ar(insn, &ar) )
|
||||
{
|
||||
char buf[MAXSTR];
|
||||
ea2str(buf, sizeof(buf), ar);
|
||||
out_printf(COLSTR(" %s(%s)", SCOLOR_AUTOCMT), ash.cmnt, buf);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_tms320c5_t::OutImmVoid(const op_t &x)
|
||||
{
|
||||
if ( !pm().tmsfunny )
|
||||
return;
|
||||
if ( x.type == o_imm )
|
||||
{
|
||||
if ( x.value != 0 )
|
||||
{
|
||||
int v = int(short(x.value) * 10000L / 0x7FFF);
|
||||
out_char(' ');
|
||||
out_tagon(COLOR_AUTOCMT);
|
||||
out_line(ash.cmnt);
|
||||
out_char(' ');
|
||||
if ( v < 0 )
|
||||
{
|
||||
out_char('-');
|
||||
v = -v;
|
||||
}
|
||||
char buf[10];
|
||||
if ( v == 10000 )
|
||||
qstrncpy(buf, "1.0000", sizeof(buf));
|
||||
else
|
||||
qsnprintf(buf, sizeof(buf), "0.%04d", v);
|
||||
out_line(buf);
|
||||
out_tagoff(COLOR_AUTOCMT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_tms320c5_t::out_insn(void)
|
||||
{
|
||||
if ( shouldIndent() )
|
||||
out_char(' ');
|
||||
out_mnemonic();
|
||||
|
||||
bool comma = insn.Op1.shown() && out_one_operand(0);
|
||||
|
||||
if ( insn.Op2.shown() && insn.Op2.type != o_void )
|
||||
{
|
||||
if ( comma )
|
||||
{
|
||||
out_tagon(COLOR_SYMBOL);
|
||||
out_char(',');
|
||||
out_tagoff(COLOR_SYMBOL);
|
||||
out_char(' ');
|
||||
}
|
||||
out_one_operand(1);
|
||||
}
|
||||
|
||||
if ( insn.Op1.type == o_phrase )
|
||||
if ( outnextar(insn.Op1, comma) )
|
||||
comma = true;
|
||||
if ( insn.Op2.type == o_phrase )
|
||||
outnextar(insn.Op2, comma);
|
||||
|
||||
out_immchar_cmts();
|
||||
|
||||
if ( has_phrase() )
|
||||
outphraseAr();
|
||||
|
||||
flush_outbuf();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void idaapi header(outctx_t &ctx)
|
||||
{
|
||||
ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//lint -e{818} seg could be const
|
||||
void tms320c5_t::segstart(outctx_t &ctx, segment_t *seg) const
|
||||
{
|
||||
qstring sname;
|
||||
get_visible_segm_name(&sname, seg);
|
||||
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR(".sect \"%s\"", SCOLOR_ASMDIR), sname.c_str());
|
||||
if ( (inf_get_outflags() & OFLG_GEN_ORG) != 0 )
|
||||
{
|
||||
ea_t org = seg->start_ea - get_segm_base(seg);
|
||||
if ( org != 0 )
|
||||
{
|
||||
char buf[MAX_NUMBUF];
|
||||
btoa(buf, sizeof(buf), org);
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s .org %s", SCOLOR_AUTOCMT),
|
||||
ash.cmnt, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void tms320c5_t::footer(outctx_t &ctx) const
|
||||
{
|
||||
if ( ash.end != NULL )
|
||||
{
|
||||
ctx.gen_empty_line();
|
||||
ctx.out_line(ash.end, COLOR_ASMDIR);
|
||||
qstring name;
|
||||
if ( get_colored_name(&name, inf_get_start_ea()) > 0 )
|
||||
{
|
||||
ctx.out_char(' ');
|
||||
ctx.out_line(name.begin());
|
||||
}
|
||||
ctx.flush_outbuf(DEFAULT_INDENT);
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.gen_cmt_line("end of file");
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//lint -e{1764} ctx could be const
|
||||
void tms320c5_t::tms_assumes(outctx_t &ctx) const
|
||||
{
|
||||
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);
|
||||
|
||||
if ( seg->type == SEG_XTRN
|
||||
|| seg->type == SEG_DATA
|
||||
|| (inf_get_outflags() & OFLG_GEN_ASSUME) == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
sreg_range_t sra;
|
||||
if ( !get_sreg_range(&sra, ea, rDP) )
|
||||
return;
|
||||
bool show = sra.start_ea == ea;
|
||||
if ( show )
|
||||
{
|
||||
sreg_range_t prev_sra;
|
||||
if ( get_prev_sreg_range(&prev_sra, ea, rDP) )
|
||||
show = sra.val != prev_sra.val;
|
||||
}
|
||||
if ( seg_started || show )
|
||||
ctx.gen_printf(DEFAULT_INDENT,
|
||||
COLSTR("%s --- assume DP %04a", SCOLOR_AUTOCMT),
|
||||
ash.cmnt, sra.val);
|
||||
}
|
||||
360
idasdk76/module/tms320c5/reg.cpp
Normal file
360
idasdk76/module/tms320c5/reg.cpp
Normal file
@@ -0,0 +1,360 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Version 3.05
|
||||
* Copyright (c) 1990-95 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* FIDO: 2:5020/209
|
||||
* E-mail: ig@estar.msk.su
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tms.hpp"
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const char *const RegNames[] =
|
||||
{
|
||||
"acc","p","bmar",
|
||||
"ar0","ar1","ar2","ar3","ar4","ar5","ar6","ar7",
|
||||
"cs","ds","dp"
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
const static predefined_t iregs[] =
|
||||
{
|
||||
{ 0x00, "Reserved_0", NULL },
|
||||
{ 0x01, "Reserved_1", NULL },
|
||||
{ 0x02, "Reserved_2", NULL },
|
||||
{ 0x03, "Reserved_3", NULL },
|
||||
{ 0x04, "imr", "Interrupt mask register" },
|
||||
{ 0x05, "greg", "Global memory allocation register" },
|
||||
{ 0x06, "ifr", "Interrupt flag register" },
|
||||
{ 0x07, "pmst", "Processor mode status register" },
|
||||
{ 0x08, "rptc", "Repeat counter register" },
|
||||
{ 0x09, "brcr", "Block repeat counter register" },
|
||||
{ 0x0A, "pasr", "Block repeat program address start register" },
|
||||
{ 0x0B, "paer", "Block repeat program address end register" },
|
||||
{ 0x0C, "treg0", "Temp reg - multiplicand" },
|
||||
{ 0x0D, "treg1", "Temp reg - dynamic shift count (5 bits)" },
|
||||
{ 0x0E, "treg2", "Temp reg - bit pointer in dynamic bit test (4 bits)" },
|
||||
{ 0x0F, "dbmr", "Dynamic bit manipulation register" },
|
||||
{ 0x10, "ar0", NULL },
|
||||
{ 0x11, "ar1", NULL },
|
||||
{ 0x12, "ar2", NULL },
|
||||
{ 0x13, "ar3", NULL },
|
||||
{ 0x14, "ar4", NULL },
|
||||
{ 0x15, "ar5", NULL },
|
||||
{ 0x16, "ar6", NULL },
|
||||
{ 0x17, "ar7", NULL },
|
||||
{ 0x18, "indx", "Index register" },
|
||||
{ 0x19, "arcr", "Auxiliary compare register" },
|
||||
{ 0x1A, "cbsr1", "Circular buffer 1 start" },
|
||||
{ 0x1B, "cber1", "Circular buffer 1 end" },
|
||||
{ 0x1C, "cbsr2", "Circular buffer 2 start" },
|
||||
{ 0x1D, "cber2", "Circular buffer 2 end" },
|
||||
{ 0x1E, "cbcr", "Circular buffer control register" },
|
||||
{ 0x1F, "bmar", "Block move address register" },
|
||||
{ 0x20, "drr", "Data receive register" },
|
||||
{ 0x21, "dxr", "Data transmit register" },
|
||||
{ 0x22, "spc", "Serial port control register" },
|
||||
{ 0x23, "Reserved_23", NULL },
|
||||
{ 0x24, "tim", "Timer register" },
|
||||
{ 0x25, "prd", "Period register" },
|
||||
{ 0x26, "tcr", "Timer control register" },
|
||||
{ 0x27, "Reserved_27", NULL },
|
||||
{ 0x28, "pdwsr", "Program/Data S/W Wait-State register" },
|
||||
{ 0x29, "iowsr", "I/O Port S/W Wait-State register" },
|
||||
{ 0x2A, "cwsr", "Control S/W Wait-State register" },
|
||||
{ 0x2B, "Reserved_2b", NULL },
|
||||
{ 0x2C, "Reserved_2c", NULL },
|
||||
{ 0x2D, "Reserved_2d", NULL },
|
||||
{ 0x2E, "Reserved_2e", NULL },
|
||||
{ 0x2F, "Reserved_2f", NULL },
|
||||
{ 0x30, "trcv", "TDM Data receive register" },
|
||||
{ 0x31, "tdxr", "TDM Data transmit register" },
|
||||
{ 0x32, "tspc", "TDM Serial port control register" },
|
||||
{ 0x33, "tcsr", "TDM channel select register" },
|
||||
{ 0x34, "trta", "TDM Receive/Transmit address register" },
|
||||
{ 0x35, "trad", "TDM Received address register" },
|
||||
{ 0x00, NULL, NULL }
|
||||
};
|
||||
|
||||
static const predefined_t c2_iregs[] =
|
||||
{
|
||||
{ 0x00, "drr", "Data receive register" },
|
||||
{ 0x01, "dxr", "Data transmit register" },
|
||||
{ 0x02, "tim", "Timer register" },
|
||||
{ 0x03, "prd", "Period register" },
|
||||
{ 0x04, "imr", "Interrupt mask register" },
|
||||
{ 0x05, "greg", "Global memory allocation register" },
|
||||
{ 0x00, NULL, NULL }
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// 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 tms320c5_t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
ssize_t idaapi tms320c5_t::on_event(ssize_t msgid, va_list va)
|
||||
{
|
||||
int retcode = 0;
|
||||
switch ( msgid )
|
||||
{
|
||||
case processor_t::ev_newfile:
|
||||
{
|
||||
inf_set_wide_high_byte_first(true);
|
||||
segment_t *sptr = get_first_seg();
|
||||
ea_t codeseg;
|
||||
if ( sptr != NULL )
|
||||
{
|
||||
codeseg = sptr->start_ea;
|
||||
if ( codeseg-get_segm_base(sptr) == 0 )
|
||||
{
|
||||
inf_set_start_ea(sptr->start_ea);
|
||||
inf_set_start_ip(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
codeseg = BADADDR;
|
||||
}
|
||||
set_segm_class(sptr, "CODE");
|
||||
set_segm_name(sptr,"cseg");
|
||||
sel_t sel;
|
||||
ea_t data_start;
|
||||
segment_t *s1 = get_next_seg(codeseg);
|
||||
if ( s1 == NULL )
|
||||
{
|
||||
segment_t s;
|
||||
uint32 size = 64 * 1024L;
|
||||
s.start_ea = free_chunk(0,size,0xF);
|
||||
s.end_ea = s.start_ea + size;
|
||||
s.sel = ushort(s.start_ea >> 4);
|
||||
s.align = saRelByte;
|
||||
s.comb = scPub;
|
||||
add_segm_ex(&s, "dseg", NULL, ADDSEG_NOSREG);
|
||||
sel = s.sel;
|
||||
data_start = s.start_ea;
|
||||
}
|
||||
else
|
||||
{
|
||||
sel = s1->sel;
|
||||
data_start = s1->start_ea;
|
||||
}
|
||||
set_default_sreg_value(getseg(codeseg), rVds, sel);
|
||||
split_sreg_range(inf_get_start_ea(), rDP, 0, SR_auto);
|
||||
inf_set_nametype(NM_NAM_OFF);
|
||||
|
||||
const predefined_t *ptr = isC2() ? c2_iregs : iregs;
|
||||
for ( ; ptr->name != NULL; ptr++ )
|
||||
{
|
||||
ea_t ea = data_start + ptr->addr;
|
||||
create_byte(ea,1);
|
||||
set_name(ea, ptr->name, SN_NODUMMY);
|
||||
if ( ptr->cmt != NULL )
|
||||
set_cmt(ea, ptr->cmt, true);
|
||||
}
|
||||
tmsfunny = qgetenv("TMSFIX");
|
||||
}
|
||||
break;
|
||||
|
||||
case processor_t::ev_newprc:
|
||||
nprc = va_arg(va, int);
|
||||
// bool keep_cfg = va_argi(va, bool);
|
||||
break;
|
||||
|
||||
case processor_t::ev_ending_undo:
|
||||
nprc = ph.get_proc_index();
|
||||
//fall through
|
||||
case processor_t::ev_oldfile:
|
||||
inf_set_wide_high_byte_first(true); // to be able to work with old bases
|
||||
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_assumes:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
tms_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;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return retcode;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// DSP Fixed Point COFF Assembler Version 6.20
|
||||
// Copyright (c) 1987-1991 Texas Instruments Incorporated
|
||||
//-----------------------------------------------------------------------
|
||||
static const char *const dspasm_header[] =
|
||||
{
|
||||
".mmregs",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const asm_t dspasm =
|
||||
{
|
||||
AS_COLON | ASH_HEXF0,
|
||||
0,
|
||||
"DSP Fixed Point COFF Assembler Version 6.20",
|
||||
0,
|
||||
dspasm_header, // header lines
|
||||
NULL, // org
|
||||
".end",
|
||||
|
||||
";", // comment string
|
||||
'"', // string delimiter
|
||||
'\'', // char delimiter
|
||||
"\\\"'", // special symbols in char and string constants
|
||||
|
||||
".string", // ascii string directive
|
||||
".word", // byte directive
|
||||
".long", // word directive
|
||||
NULL, // 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 16*%s",// uninited arrays
|
||||
".set", // equ
|
||||
NULL, // seg prefix
|
||||
NULL, // curip
|
||||
NULL, // func_header
|
||||
NULL, // func_footer
|
||||
NULL, // public
|
||||
NULL, // weak
|
||||
NULL, // extrn
|
||||
NULL, // comm
|
||||
NULL, // get_type_name
|
||||
NULL, // align
|
||||
'(', ')', // lbrace, rbrace
|
||||
NULL, // mod
|
||||
NULL, // and
|
||||
NULL, // or
|
||||
NULL, // xor
|
||||
NULL, // not
|
||||
NULL, // shl
|
||||
NULL, // shr
|
||||
NULL, // sizeof
|
||||
};
|
||||
|
||||
|
||||
static const asm_t *const asms[] = { &dspasm, NULL };
|
||||
//-----------------------------------------------------------------------
|
||||
#define FAMILY "TMS320C5x series:"
|
||||
static const char *const shnames[] = { "TMS320C5", "TMS320C2", NULL };
|
||||
static const char *const lnames[] =
|
||||
{
|
||||
FAMILY"Texas Instruments TMS320C5x",
|
||||
"Texas Instruments TMS320C2x",
|
||||
NULL
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const uchar retcode_1[] = { 0x00, 0xEF };
|
||||
static const uchar retcode_2[] = { 0x00, 0xFF };
|
||||
static const uchar retcode_3[] = { 0x3A, 0xBE };
|
||||
static const uchar retcode_4[] = { 0x38, 0xBE };
|
||||
|
||||
static const bytes_t retcodes[] =
|
||||
{
|
||||
{ sizeof(retcode_1), retcode_1 },
|
||||
{ sizeof(retcode_2), retcode_2 },
|
||||
{ sizeof(retcode_3), retcode_3 },
|
||||
{ sizeof(retcode_4), retcode_4 },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Processor Definition
|
||||
//-----------------------------------------------------------------------
|
||||
processor_t LPH =
|
||||
{
|
||||
IDP_INTERFACE_VERSION, // version
|
||||
PLFM_TMS, // id
|
||||
// flag
|
||||
PR_SEGS
|
||||
| PR_RNAMESOK // can use register names for byte names
|
||||
| PR_SEGTRANS,
|
||||
// flag2
|
||||
0,
|
||||
16, // 8 bits in a byte for code segments
|
||||
16, // 8 bits in a byte for other segments
|
||||
|
||||
shnames,
|
||||
lnames,
|
||||
|
||||
asms,
|
||||
|
||||
notify,
|
||||
|
||||
RegNames, // Register names
|
||||
qnumber(RegNames), // Number of registers
|
||||
|
||||
rVcs, // first
|
||||
rDP, // last
|
||||
2, // size of a segment register
|
||||
rVcs,rVds,
|
||||
|
||||
NULL, // No known code start sequences
|
||||
retcodes,
|
||||
|
||||
0,TMS_last,
|
||||
Instructions, // instruc
|
||||
};
|
||||
79
idasdk76/module/tms320c5/tms.hpp
Normal file
79
idasdk76/module/tms320c5/tms.hpp
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Version 3.05
|
||||
* Copyright (c) 1990-95 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* FIDO: 2:5020/209
|
||||
* E-mail: ig@estar.msk.su
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _TMS_HPP
|
||||
#define _TMS_HPP
|
||||
|
||||
#include "../idaidp.hpp"
|
||||
#include "ins.hpp"
|
||||
#include <segregs.hpp>
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// customization of cmd structure:
|
||||
#define o_bit o_idpspec0
|
||||
#define o_bitnot o_idpspec1
|
||||
#define o_cond o_idpspec2
|
||||
|
||||
#define sib specflag1
|
||||
#define Cond reg
|
||||
|
||||
#define PT_TMS320C5 0
|
||||
#define PT_TMS320C2 1
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct tms320c5_t : public procmod_t
|
||||
{
|
||||
int nprc = 0; // processor number
|
||||
int tmsfunny = -1;
|
||||
uint code;
|
||||
bool flow = false;
|
||||
|
||||
virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override;
|
||||
|
||||
int ana(insn_t *insn);
|
||||
int op_iaa(const insn_t &insn, op_t &o) const;
|
||||
int op_indir(op_t &o);
|
||||
int op_maa(const insn_t &insn, op_t &o) const;
|
||||
void op_short(op_t &o) const;
|
||||
int op_cond(op_t &o) const;
|
||||
void op_bit(op_t &o) const;
|
||||
int ana_c2(insn_t &insn);
|
||||
|
||||
int emu(const insn_t &insn);
|
||||
void handle_operand(const insn_t &insn, const op_t &x, bool isload);
|
||||
int find_ar(const insn_t &insn, ea_t *res) const;
|
||||
bool can_flow(const insn_t &insn) const;
|
||||
|
||||
bool isC2(void) const { return nprc == PT_TMS320C2; }
|
||||
|
||||
void segstart(outctx_t &ctx, segment_t *seg) const;
|
||||
void footer(outctx_t &ctx) const;
|
||||
void tms_assumes(outctx_t &ctx) const;
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
enum TMS_registers { rAcc,rP,rBMAR,rAr0,rAr1,rAr2,rAr3,rAr4,rAr5,rAr6,rAr7,rVcs,rVds,rDP };
|
||||
|
||||
enum TMS_bits { bit_intm,bit_ovm,bit_cnf,bit_sxm,bit_hm,bit_tc,bit_xf,bit_c };
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct predefined_t
|
||||
{
|
||||
uchar addr;
|
||||
const char *name;
|
||||
const char *cmt;
|
||||
};
|
||||
|
||||
bool is_mpy(const insn_t &insn);
|
||||
ea_t prevInstruction(ea_t ea);
|
||||
//------------------------------------------------------------------------
|
||||
void idaapi header(outctx_t &ctx);
|
||||
#endif
|
||||
Reference in New Issue
Block a user