update to ida 7.6, add builds
This commit is contained in:
650
idasdk76/module/tms320c1/ana.cpp
Normal file
650
idasdk76/module/tms320c1/ana.cpp
Normal file
@@ -0,0 +1,650 @@
|
||||
// $Id: ana.cpp,v 1.13 2000/11/06 22:11:16 jeremy Exp $
|
||||
//
|
||||
// Copyright (c) 2000 Jeremy Cooper. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// 3. All advertising materials mentioning features or use of this software
|
||||
// must display the following acknowledgement:
|
||||
// This product includes software developed by Jeremy Cooper.
|
||||
// 4. The name of the author may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// TMS320C1X Processor module
|
||||
// Instruction decode.
|
||||
//
|
||||
#include "../idaidp.hpp"
|
||||
#include "tms320c1.hpp"
|
||||
#include "ins.hpp"
|
||||
#include "reg.hpp"
|
||||
|
||||
//
|
||||
// After determining an instruction's opcode, ana() calls one of the
|
||||
// functions below to decode its operands.
|
||||
//
|
||||
static int ana_di(insn_t &insn, uint16); // direct/indirect instruction
|
||||
static int ana_di_shift(insn_t &insn, uint16); // direct/indirect w/ shift instruction
|
||||
static int ana_di_port(insn_t &insn, uint16); // direct/indirect to/from I/O port
|
||||
static int ana_di_aux(insn_t &insn, uint16); // direct/indirect to AR register
|
||||
static int ana_imm_1(insn_t &insn, uint16); // immediate 1 bit
|
||||
static int ana_imm_8(insn_t &insn, uint16); // immediate 8 bits
|
||||
static int ana_imm_13(insn_t &insn, uint16); // immediate 13 bits
|
||||
static int ana_imm_8_aux(insn_t &insn, uint16); // immediate 8 bits into AR register
|
||||
static int ana_flow(insn_t &insn); // flow control
|
||||
inline int ana_empty(const insn_t &insn); // no operands
|
||||
|
||||
//
|
||||
// These functions in turn may call one of the functions below to help
|
||||
// decode the individual operands within the instruction.
|
||||
//
|
||||
static int ana_op_di(const insn_t &insn, op_t &, op_t &, uint16); // direct/indirect operand
|
||||
static int ana_op_narp(const insn_t &insn, op_t &, uint16); // new ARP operand
|
||||
|
||||
//
|
||||
// Due to limitations that IDA's some of IDA's helper functions have,
|
||||
// they don't work well with processors whose byte size is greater
|
||||
// than 8 bits. (This processor has a 16-bit byte). Therefore we
|
||||
// have to make our own replacements for these functions.
|
||||
//
|
||||
// Simulates the effect of the IDA kernel helper function insn.get_next_byte(),
|
||||
// but works with our 16-bit byte environment.
|
||||
//
|
||||
static uint16 tms320c1x_get_next_insn_byte(insn_t &insn)
|
||||
{
|
||||
//
|
||||
// Fetch a 16 bit value from the (global) current instruction decode
|
||||
// pointer.
|
||||
//
|
||||
uint16 value = get_wide_byte(insn.ea+insn.size);
|
||||
|
||||
//
|
||||
// Increment the size of the current instruction, to reflect the fact
|
||||
// that it contains the byte that we just read.
|
||||
//
|
||||
insn.size++;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
//lint -esym(714,ana)
|
||||
int idaapi ana(insn_t *_insn)
|
||||
{
|
||||
insn_t &insn = *_insn;
|
||||
|
||||
//
|
||||
// Fetch the first 16 bits of the instruction.
|
||||
// (All instructions are at least 16 bits long).
|
||||
//
|
||||
uint16 opcode = tms320c1x_get_next_insn_byte(insn);
|
||||
|
||||
//
|
||||
// Decode the instruction in the opcode by sifting through the
|
||||
// various instruction bit masks.
|
||||
//
|
||||
|
||||
//
|
||||
// 3-bit mask instructions:
|
||||
// MPYK
|
||||
//
|
||||
switch ( opcode & ISN_3_BIT_MASK )
|
||||
{
|
||||
case ISN3_MPYK : insn.itype = I_MPYK; return ana_imm_13(insn, opcode);
|
||||
}
|
||||
|
||||
//
|
||||
// 4-bit mask instructions:
|
||||
// ADD, LAC, SUB
|
||||
//
|
||||
switch ( opcode & ISN_4_BIT_MASK )
|
||||
{
|
||||
case ISN4_ADD : insn.itype = I_ADD; return ana_di_shift(insn, opcode);
|
||||
case ISN4_LAC : insn.itype = I_LAC; return ana_di_shift(insn, opcode);
|
||||
case ISN4_SUB : insn.itype = I_SUB; return ana_di_shift(insn, opcode);
|
||||
}
|
||||
|
||||
//
|
||||
// 5-bit mask instructions:
|
||||
// SACH, IN, OUT
|
||||
//
|
||||
switch ( opcode & ISN_5_BIT_MASK )
|
||||
{
|
||||
case ISN5_SACH : insn.itype = I_SACH; return ana_di(insn, opcode);
|
||||
case ISN5_IN : insn.itype = I_IN; return ana_di_port(insn, opcode);
|
||||
case ISN5_OUT : insn.itype = I_OUT; return ana_di_port(insn, opcode);
|
||||
}
|
||||
|
||||
//
|
||||
// 7-bit mask instructions:
|
||||
// LAR, LARK, SAR
|
||||
//
|
||||
switch ( opcode & ISN_7_BIT_MASK )
|
||||
{
|
||||
case ISN7_LAR : insn.itype = I_LAR; return ana_di_aux(insn, opcode);
|
||||
case ISN7_LARK : insn.itype = I_LARK; return ana_imm_8_aux(insn, opcode);
|
||||
case ISN7_SAR : insn.itype = I_SAR; return ana_di_aux(insn, opcode);
|
||||
}
|
||||
|
||||
//
|
||||
// 8-bit mask instructions:
|
||||
// ADDH, ADDS, AND, LACK, OR, SACL, SUBC, SUBH, XOR, ZALH, LDP, MAR,
|
||||
// LT, LTA, LTD, MPY, LST, SST, DMOV, TBLR, TBLW
|
||||
//
|
||||
switch ( opcode & ISN_8_BIT_MASK )
|
||||
{
|
||||
case ISN8_ADDH : insn.itype = I_ADDH; return ana_di(insn, opcode);
|
||||
case ISN8_ADDS : insn.itype = I_ADDS; return ana_di(insn, opcode);
|
||||
case ISN8_AND : insn.itype = I_AND; return ana_di(insn, opcode);
|
||||
case ISN8_LACK : insn.itype = I_LACK; return ana_imm_8(insn, opcode);
|
||||
case ISN8_OR : insn.itype = I_OR; return ana_di(insn, opcode);
|
||||
case ISN8_SACL : insn.itype = I_SACL; return ana_di(insn, opcode);
|
||||
case ISN8_SUBC : insn.itype = I_SUBC; return ana_di(insn, opcode);
|
||||
case ISN8_SUBH : insn.itype = I_SUBH; return ana_di(insn, opcode);
|
||||
case ISN8_SUBS : insn.itype = I_SUBS; return ana_di(insn, opcode);
|
||||
case ISN8_XOR : insn.itype = I_XOR; return ana_di(insn, opcode);
|
||||
case ISN8_ZALH : insn.itype = I_ZALH; return ana_di(insn, opcode);
|
||||
case ISN8_ZALS : insn.itype = I_ZALS; return ana_di(insn, opcode);
|
||||
case ISN8_LDP : insn.itype = I_LDP; return ana_di(insn, opcode);
|
||||
case ISN8_MAR : insn.itype = I_MAR; return ana_di(insn, opcode);
|
||||
case ISN8_LT : insn.itype = I_LT; return ana_di(insn, opcode);
|
||||
case ISN8_LTA : insn.itype = I_LTA; return ana_di(insn, opcode);
|
||||
case ISN8_LTD : insn.itype = I_LTD; return ana_di(insn, opcode);
|
||||
case ISN8_MPY : insn.itype = I_MPY; return ana_di(insn, opcode);
|
||||
case ISN8_LST : insn.itype = I_LST; return ana_di(insn, opcode);
|
||||
case ISN8_SST : insn.itype = I_SST; return ana_di(insn, opcode);
|
||||
case ISN8_DMOV : insn.itype = I_DMOV; return ana_di(insn, opcode);
|
||||
case ISN8_TBLR : insn.itype = I_TBLR; return ana_di(insn, opcode);
|
||||
case ISN8_TBLW : insn.itype = I_TBLW; return ana_di(insn, opcode);
|
||||
}
|
||||
|
||||
//
|
||||
// 15-bit mask instructions:
|
||||
// LARP, LDPK
|
||||
//
|
||||
switch ( opcode & ISN_15_BIT_MASK )
|
||||
{
|
||||
// LARP is a synonym for a special case of MAR
|
||||
// case ISN15_LARP: insn.itype = I_LARP; return ana_ar(opcode);
|
||||
case ISN15_LDPK: insn.itype = I_LDPK; return ana_imm_1(insn, opcode);
|
||||
}
|
||||
|
||||
//
|
||||
// 16-bit mask instructions:
|
||||
// ABS, ZAC, APAC, PAC, SPAC, B, BANZ, BGEZ, BGZ, BIOZ, BLEZ, BLZ,
|
||||
// BNZ, BV, BZ, CALA, CALL, RET, DINT, EINT, NOP, POP, PUSH, ROVM,
|
||||
// SOVM
|
||||
//
|
||||
switch ( opcode & ISN_16_BIT_MASK )
|
||||
{
|
||||
case ISN16_ABS: insn.itype = I_ABS; return ana_empty(insn);
|
||||
case ISN16_ZAC: insn.itype = I_ZAC; return ana_empty(insn);
|
||||
case ISN16_APAC: insn.itype = I_APAC; return ana_empty(insn);
|
||||
case ISN16_PAC: insn.itype = I_PAC; return ana_empty(insn);
|
||||
case ISN16_SPAC: insn.itype = I_SPAC; return ana_empty(insn);
|
||||
case ISN16_B: insn.itype = I_B; return ana_flow(insn);
|
||||
case ISN16_BANZ: insn.itype = I_BANZ; return ana_flow(insn);
|
||||
case ISN16_BGEZ: insn.itype = I_BGEZ; return ana_flow(insn);
|
||||
case ISN16_BGZ: insn.itype = I_BGZ; return ana_flow(insn);
|
||||
case ISN16_BIOZ: insn.itype = I_BIOZ; return ana_flow(insn);
|
||||
case ISN16_BLEZ: insn.itype = I_BLEZ; return ana_flow(insn);
|
||||
case ISN16_BLZ: insn.itype = I_BLZ; return ana_flow(insn);
|
||||
case ISN16_BNZ: insn.itype = I_BNZ; return ana_flow(insn);
|
||||
case ISN16_BV: insn.itype = I_BV; return ana_flow(insn);
|
||||
case ISN16_BZ: insn.itype = I_BZ; return ana_flow(insn);
|
||||
case ISN16_CALA: insn.itype = I_CALA; return ana_empty(insn);
|
||||
case ISN16_CALL: insn.itype = I_CALL; return ana_flow(insn);
|
||||
case ISN16_RET: insn.itype = I_RET; return ana_empty(insn);
|
||||
case ISN16_DINT: insn.itype = I_DINT; return ana_empty(insn);
|
||||
case ISN16_EINT: insn.itype = I_EINT; return ana_empty(insn);
|
||||
case ISN16_NOP: insn.itype = I_NOP; return ana_empty(insn);
|
||||
case ISN16_POP: insn.itype = I_POP; return ana_empty(insn);
|
||||
case ISN16_PUSH: insn.itype = I_PUSH; return ana_empty(insn);
|
||||
case ISN16_ROVM: insn.itype = I_ROVM; return ana_empty(insn);
|
||||
case ISN16_SOVM: insn.itype = I_SOVM; return ana_empty(insn);
|
||||
}
|
||||
|
||||
//
|
||||
// If control reaches this point, then the opcode does not represent
|
||||
// any known instruction.
|
||||
//
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// ana_empty()
|
||||
//
|
||||
// Called to decode an 'empty' instruction's operands.
|
||||
// (Very trivial, because an empty instruction has no operands).
|
||||
//
|
||||
inline int ana_empty(const insn_t &insn)
|
||||
{
|
||||
//
|
||||
// Successful decode.
|
||||
// Return the instruction size.
|
||||
//
|
||||
return insn.size;
|
||||
}
|
||||
|
||||
//
|
||||
// ana_flow()
|
||||
//
|
||||
// Called to decode a flow control instruction's operands.
|
||||
// Decodes the branch address of the instruction.
|
||||
//
|
||||
// (Some flow control instructions have no arguments and are thus
|
||||
// decoded by calling ana_empty()).
|
||||
//
|
||||
static int ana_flow(insn_t &insn)
|
||||
{
|
||||
//
|
||||
// Fetch the next 16 bits from the instruction; they
|
||||
// constitute the branch address.
|
||||
//
|
||||
uint16 addr = tms320c1x_get_next_insn_byte(insn);
|
||||
|
||||
//
|
||||
// Fill in the insn structure to reflect the first (and only)
|
||||
// operand of this instruction as being a reference to the CODE segment.
|
||||
//
|
||||
insn.Op1.type = o_near;
|
||||
insn.Op1.addr = addr;
|
||||
|
||||
//
|
||||
// Set the operand type to reflect the size of the address
|
||||
// in the instruction. Technically this instructions address
|
||||
// value is one processor byte (16 bits), but when it comes to defining
|
||||
// operand value sizes, IDA thinks in terms of 8-bit bytes.
|
||||
// Therefore, we specify this value as a word.
|
||||
//
|
||||
insn.Op1.dtype = dt_word;
|
||||
|
||||
//
|
||||
// Successful decode.
|
||||
// Return the instruction size.
|
||||
//
|
||||
return insn.size;
|
||||
}
|
||||
|
||||
//
|
||||
// ana_di(opcode)
|
||||
//
|
||||
// Called to decode a direct/indirect memory reference instruction's
|
||||
// operands.
|
||||
//
|
||||
static int ana_di(insn_t &insn, uint16 opcode)
|
||||
{
|
||||
//
|
||||
// Decode the direct or indirect memory reference made
|
||||
// by the instruction as its first operand and the new arp value
|
||||
// (if it exists) as its second operand.
|
||||
//
|
||||
if ( ana_op_di(insn, insn.Op1, insn.Op2, opcode) == 0 )
|
||||
{
|
||||
//
|
||||
// The operand was invalid.
|
||||
//
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Successful decode.
|
||||
// Return the instruction size.
|
||||
//
|
||||
return insn.size;
|
||||
}
|
||||
|
||||
//
|
||||
// ana_di_shift(opcode)
|
||||
//
|
||||
// Called to decode a direct/indirect memory reference plus shift
|
||||
// instruction's operands.
|
||||
//
|
||||
static int ana_di_shift(insn_t &insn, uint16 opcode)
|
||||
{
|
||||
//
|
||||
// First, decode the direct or indirect memory reference made
|
||||
// by the instruction as its first operand, and the new arp
|
||||
// value (if it exists) as its third operand.
|
||||
//
|
||||
if ( ana_op_di(insn, insn.Op1, insn.Op3, opcode) == 0 )
|
||||
{
|
||||
//
|
||||
// The operand was invalid.
|
||||
//
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Finally, decode the shift value as the instruction's second operand.
|
||||
//
|
||||
insn.Op2.type = o_imm;
|
||||
insn.Op2.value = ISN_SHIFT(opcode);
|
||||
|
||||
//
|
||||
// Successful decode.
|
||||
// Return the instruction size.
|
||||
//
|
||||
return insn.size;
|
||||
}
|
||||
|
||||
//
|
||||
// ana_di_port(opcode)
|
||||
//
|
||||
// Called to decode a direct/indirect memory reference to/from I/O port
|
||||
// instruction's operands.
|
||||
//
|
||||
static int ana_di_port(insn_t &insn, uint16 opcode)
|
||||
{
|
||||
//
|
||||
// First, decode the direct or indirect memory reference made
|
||||
// by the instruction as its first operand and the new arp value
|
||||
// (if it exists) as its third operand.
|
||||
//
|
||||
if ( ana_op_di(insn, insn.Op1, insn.Op3, opcode) == 0 )
|
||||
{
|
||||
//
|
||||
// The operand was invalid.
|
||||
//
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Next, decode the port number as the instruction's second operand.
|
||||
//
|
||||
insn.Op2.type = o_imm;
|
||||
insn.Op2.value = ISN_PORT(opcode);
|
||||
|
||||
//
|
||||
// Successful decode.
|
||||
// Return the instruction size.
|
||||
//
|
||||
return insn.size;
|
||||
}
|
||||
|
||||
//
|
||||
// ana_di_aux(opcode)
|
||||
//
|
||||
// Called to decode a direct/indirect memory reference to/from auxiliary
|
||||
// register instruction's operands.
|
||||
//
|
||||
static int ana_di_aux(insn_t &insn, uint16 opcode)
|
||||
{
|
||||
//
|
||||
// First, decode the auxiliary register number as the instruction's
|
||||
// first operand.
|
||||
//
|
||||
insn.Op1.type = o_reg;
|
||||
insn.Op1.reg = (ISN_AUX_AR(opcode) ? IREG_AR1 : IREG_AR0);
|
||||
|
||||
//
|
||||
// Finally, decode the direct or indirect memory reference made
|
||||
// by the instruction as its second operand and the new arp
|
||||
// value (if it exists) as its third operand.
|
||||
//
|
||||
if ( ana_op_di(insn, insn.Op2, insn.Op3, opcode) == 0 )
|
||||
{
|
||||
//
|
||||
// The operand was invalid.
|
||||
//
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Successful decode.
|
||||
// Return the instruction size.
|
||||
//
|
||||
return insn.size;
|
||||
}
|
||||
|
||||
//
|
||||
// ana_imm_1(opcode)
|
||||
//
|
||||
// Called to decode a 1 bit immediate value instruction's operands.
|
||||
//
|
||||
static int ana_imm_1(insn_t &insn, uint16 opcode)
|
||||
{
|
||||
//
|
||||
// Decode the 1 bit immediate value in this instruction's opcode
|
||||
// and make an immediate value operand out of it.
|
||||
//
|
||||
insn.Op1.type = o_imm;
|
||||
insn.Op1.value = ISN_IMM1(opcode);
|
||||
insn.Op1.dtype = dt_byte; // This means an 8 bit value, rather than 16.
|
||||
|
||||
//
|
||||
// Successful decode.
|
||||
// Return the instruction size.
|
||||
//
|
||||
return insn.size;
|
||||
}
|
||||
|
||||
//
|
||||
// ana_imm_8(opcode)
|
||||
//
|
||||
// Called to decode an 8 bit immediate value instruction's operands.
|
||||
//
|
||||
static int ana_imm_8(insn_t &insn, uint16 opcode)
|
||||
{
|
||||
//
|
||||
// Decode the 8 bit immediate value in this instruction's opcode
|
||||
// and make an immediate value operand out of it.
|
||||
//
|
||||
insn.Op1.type = o_imm;
|
||||
insn.Op1.value = ISN_IMM8(opcode);
|
||||
insn.Op1.dtype = dt_byte; // This means an 8 bit value, rather than 16.
|
||||
|
||||
//
|
||||
// Successful decode.
|
||||
// Return the instruction size.
|
||||
//
|
||||
return insn.size;
|
||||
}
|
||||
|
||||
//
|
||||
// ana_imm_13(opcode)
|
||||
//
|
||||
// Called to decode a 13 bit immediate value instruction's operands.
|
||||
//
|
||||
static int ana_imm_13(insn_t &insn, uint16 opcode)
|
||||
{
|
||||
//
|
||||
// Decode the 13 bit immediate value in this instruction's opcode
|
||||
// and make an immediate value operand out of it.
|
||||
//
|
||||
insn.Op1.type = o_imm;
|
||||
insn.Op1.value = ISN_IMM13(opcode);
|
||||
insn.Op1.dtype = dt_word; // This means an 8 bit value, rather than 16.
|
||||
|
||||
//
|
||||
// Successful decode.
|
||||
// Return the instruction size.
|
||||
//
|
||||
return insn.size;
|
||||
}
|
||||
|
||||
//
|
||||
// ana_imm_8_aux(opcode)
|
||||
//
|
||||
// Called upon to decode an immediate 8 bit to aux register instruction's
|
||||
// operands.
|
||||
//
|
||||
static int ana_imm_8_aux(insn_t &insn, uint16 opcode)
|
||||
{
|
||||
//
|
||||
// Decode the AR bit of the instruction to determine which auxiliary
|
||||
// register is being loaded. Make this register the first operand.
|
||||
//
|
||||
insn.Op1.type = o_reg;
|
||||
insn.Op1.reg = (ISN_AUX_AR(opcode) ? IREG_AR1 : IREG_AR0);
|
||||
|
||||
//
|
||||
// Next, decode the 8 bit immediate value in the instruction and
|
||||
// make it the second operand.
|
||||
//
|
||||
insn.Op2.type = o_imm;
|
||||
insn.Op2.value = ISN_IMM8(opcode);
|
||||
insn.Op2.dtype = dt_word; // This means an 8 bit value, rather than 16.
|
||||
|
||||
//
|
||||
// Successful decode.
|
||||
// Return the instruction size.
|
||||
//
|
||||
return insn.size;
|
||||
}
|
||||
|
||||
//
|
||||
// ana_op_di(addr_op, narp_op, opcode)
|
||||
//
|
||||
// Decodes the direct or indirect memory reference made in the instruction
|
||||
// contained in 'opcode' and places the decoded information into the operand
|
||||
// address operand 'operand' and the new ARP operand 'narp_op'.
|
||||
//
|
||||
// Returns instruction size on successful decode, 0 on illegal condition.
|
||||
//
|
||||
static int ana_op_di(const insn_t &insn, op_t &addr_op, op_t &narp_op, uint16 opcode)
|
||||
{
|
||||
//
|
||||
// Check the direct/indirect bit. This determines whether the
|
||||
// opcode makes a direct memory reference via an immediate value,
|
||||
// or an indirect memory reference via the current auxiliary
|
||||
// register.
|
||||
//
|
||||
if ( ISN_DIRECT(opcode) )
|
||||
{
|
||||
//
|
||||
// The direct bit is set. This instruction makes a direct
|
||||
// memory reference to the memory location specified in its
|
||||
// immediate operand.
|
||||
//
|
||||
addr_op.type = o_mem;
|
||||
addr_op.dtype = dt_byte; // This means an 8 bit value, rather than 16.
|
||||
addr_op.addr = ISN_DIR_ADDR(opcode);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// The direct bit is reset. This instruction makes an
|
||||
// indirect memory reference.
|
||||
//
|
||||
// Determine whether this is an AR post-increment,
|
||||
// post-decrement, or no change reference.
|
||||
//
|
||||
if ( ISN_INDIR_INCR(opcode) && ISN_INDIR_DECR(opcode) )
|
||||
{
|
||||
//
|
||||
// Both the AR increment and AR decrement flags are
|
||||
// set. This is an illegal instruction.
|
||||
//
|
||||
return 0;
|
||||
}
|
||||
else if ( ISN_INDIR_INCR(opcode) )
|
||||
{
|
||||
//
|
||||
// The AR increment flag is set.
|
||||
// This is an AR increment reference.
|
||||
//
|
||||
addr_op.type = o_phrase;
|
||||
addr_op.phrase = IPH_AR_INCR;
|
||||
}
|
||||
else if ( ISN_INDIR_DECR(opcode) )
|
||||
{
|
||||
//
|
||||
// The AR decrement flag is set.
|
||||
// This is an AR decrement reference.
|
||||
//
|
||||
addr_op.type = o_phrase;
|
||||
addr_op.phrase = IPH_AR_DECR;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Neither the AR auto-increment or auto-decrement
|
||||
// flags is set. That makes this a regular AR
|
||||
// indirect reference.
|
||||
//
|
||||
addr_op.type = o_phrase;
|
||||
addr_op.phrase = IPH_AR;
|
||||
}
|
||||
//
|
||||
// Next, decode the auxiliary register pointer change command,
|
||||
// if present, as the instruction's second operand. If no
|
||||
// change is requested in this instruction, then the second operand
|
||||
// will not be filled in.
|
||||
//
|
||||
if ( ana_op_narp(insn, narp_op, opcode) == 0 )
|
||||
{
|
||||
//
|
||||
// The operand was invalid.
|
||||
//
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Successful operand decode.
|
||||
// Return the instruction size.
|
||||
//
|
||||
return insn.size;
|
||||
}
|
||||
|
||||
//
|
||||
// ana_op_narp(operand, opcode)
|
||||
//
|
||||
// Decodes the 'auxiliary-register-pointer-change' command that may
|
||||
// be embededded in the opcode 'opcode' and places the information
|
||||
// about the change in the operand 'operand'. If the instruction does
|
||||
// not have a pointer change request, then 'operand' is left alone.
|
||||
//
|
||||
// Returns instruction size on successful decode, 0 on illegal condition.
|
||||
//
|
||||
static int ana_op_narp(const insn_t &insn, op_t &op, uint16 opcode)
|
||||
{
|
||||
//
|
||||
// Determine if the instruction contains a request
|
||||
// to change the ARP register after execution.
|
||||
//
|
||||
if ( ISN_INDIR_NARP(opcode) )
|
||||
{
|
||||
//
|
||||
// The instruction contains the request.
|
||||
// Reflect the request in the operand provided.
|
||||
//
|
||||
op.type = o_reg;
|
||||
if ( ISN_INDIR_ARP(opcode) )
|
||||
{
|
||||
// Change to AR1
|
||||
op.reg = IREG_AR1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Change to AR0
|
||||
op.reg = IREG_AR0;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Successful operand decode.
|
||||
// Return the instruction size.
|
||||
//
|
||||
return insn.size;
|
||||
}
|
||||
|
||||
45
idasdk76/module/tms320c1/ana.hpp
Normal file
45
idasdk76/module/tms320c1/ana.hpp
Normal file
@@ -0,0 +1,45 @@
|
||||
// $Id: ana.hpp,v 1.3 2000/11/06 22:11:16 jeremy Exp $
|
||||
//
|
||||
// Copyright (c) 2000 Jeremy Cooper. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// 3. All advertising materials mentioning features or use of this software
|
||||
// must display the following acknowledgement:
|
||||
// This product includes software developed by Jeremy Cooper.
|
||||
// 4. The name of the author may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// TMS320C1X Processor module
|
||||
// Instruction decode.
|
||||
//
|
||||
#ifndef _IDP_TMS320C1X_ANA_H
|
||||
#define _IDP_TMS320C1X_ANA_H
|
||||
|
||||
int idaapi ana(insn_t *insn);
|
||||
|
||||
#endif // _IDP_TMS320C1X_ANA_H
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
101
idasdk76/module/tms320c1/asms.cpp
Normal file
101
idasdk76/module/tms320c1/asms.cpp
Normal file
@@ -0,0 +1,101 @@
|
||||
// $Id: asms.cpp,v 1.2 2000/11/06 22:11:16 jeremy Exp $
|
||||
//
|
||||
// Copyright (c) 2000 Jeremy Cooper. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// 3. All advertising materials mentioning features or use of this software
|
||||
// must display the following acknowledgement:
|
||||
// This product includes software developed by Jeremy Cooper.
|
||||
// 4. The name of the author may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// IDA TMS320C1X processor module.
|
||||
// TMS320C1X assembler types and implementations
|
||||
//
|
||||
#include "../idaidp.hpp"
|
||||
|
||||
#include "asms.hpp"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// TI Assembler
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
const asm_t tiAssembler =
|
||||
{
|
||||
// Assembler features:
|
||||
AS_ASCIIC // ASCII directive support C escape sequences
|
||||
|AS_ASCIIZ // ASCII directive appends implicit null character
|
||||
|ASH_HEXF3 // Hexidecimal constant format: 0x<nn...>
|
||||
|ASD_DECF0 // Decimal constant format : 34
|
||||
|ASO_OCTF1 // Octal format : 0<nn..>
|
||||
|ASB_BINF0 // Binary format : <nn...>b
|
||||
|AS_ONEDUP, // One array directive per line
|
||||
0, // Assembler-defined flags (for local use)
|
||||
"TI", // Assembler name
|
||||
0, // Help screen number
|
||||
NULL, // Array of automatically generated header lines
|
||||
".org", // Origin directive
|
||||
NULL, // End directive
|
||||
";", // Comment string
|
||||
'"', // ASCII string delimiter
|
||||
'\'', // ASCII character constant delimiter
|
||||
"\"", // Characters that cannot appear inside a string
|
||||
".asciiz", // ASCII string directive
|
||||
".byte", // Byte (8-bit) directive
|
||||
".short", // Word (16-bit) directive
|
||||
".word", // Dword (32-bit) directive
|
||||
".quad", // Qword (64-bit) directive
|
||||
NULL, // Oword (128-bit) directive
|
||||
".float", // IEEE single directive
|
||||
".double", // IEEE double directive
|
||||
NULL, // IEEE tbyte directive
|
||||
NULL, // IEEE packed-real directive
|
||||
".fill #d, #sb, #v",// Array (dup) directive
|
||||
".bss", // BSS directive
|
||||
NULL, // EQU directive to use if AS_UNEQU is set
|
||||
NULL, // Segment operand keyword
|
||||
".", // Symbol for current assembly location
|
||||
NULL, // Function header generating function
|
||||
NULL, // Function footer generating function
|
||||
".global", // Public name keyword
|
||||
NULL, // Weak keyword
|
||||
".extern", // Extern keyword
|
||||
".comm", // Communal keyword
|
||||
NULL, // 'get_type_name()' function
|
||||
".align", // Align keyword
|
||||
'(', // Left delimiter for complex expressions
|
||||
')', // Right delimiter for complex expressions
|
||||
"%", // Remainder (MOD) operator
|
||||
"&", // Bit-wise AND operator
|
||||
"|", // Bit-wise OR operator
|
||||
"^", // Bit-wise XOR operator
|
||||
"~", // Bit-wise NOT operator
|
||||
"<<", // Left shift operator
|
||||
">>", // Right shift operator
|
||||
NULL, // Sizeof() keyword
|
||||
};
|
||||
|
||||
const asm_t *const tms320c1x_Assemblers[] =
|
||||
{
|
||||
&tiAssembler,
|
||||
NULL
|
||||
};
|
||||
41
idasdk76/module/tms320c1/asms.hpp
Normal file
41
idasdk76/module/tms320c1/asms.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
// $Id: asms.hpp,v 1.2 2000/11/06 22:11:16 jeremy Exp $
|
||||
//
|
||||
// Copyright (c) 2000 Jeremy Cooper. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// 3. All advertising materials mentioning features or use of this software
|
||||
// must display the following acknowledgement:
|
||||
// This product includes software developed by Jeremy Cooper.
|
||||
// 4. The name of the author may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
//
|
||||
// IDA TMS320C1X processor module.
|
||||
// TMS320C1X assembler types
|
||||
//
|
||||
#ifndef _IDP_TMS320C1X_ASMS_HPP
|
||||
#define _IDP_TMS320C1X_ASMS_HPP
|
||||
|
||||
extern const asm_t *const tms320c1x_Assemblers[];
|
||||
|
||||
#endif // _IDP_TMS320C1X_ASMS_HPP
|
||||
263
idasdk76/module/tms320c1/emu.cpp
Normal file
263
idasdk76/module/tms320c1/emu.cpp
Normal file
@@ -0,0 +1,263 @@
|
||||
// $Id: emu.cpp,v 1.6 2000/11/06 22:11:16 jeremy Exp $
|
||||
//
|
||||
// Copyright (c) 2000 Jeremy Cooper. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// 3. All advertising materials mentioning features or use of this software
|
||||
// must display the following acknowledgement:
|
||||
// This product includes software developed by Jeremy Cooper.
|
||||
// 4. The name of the author may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// TMS320C1X Processor module
|
||||
// Instruction emulation.
|
||||
//
|
||||
#include "../idaidp.hpp"
|
||||
#include <segregs.hpp>
|
||||
|
||||
#include "tms320c1.hpp"
|
||||
#include "ins.hpp"
|
||||
#include "reg.hpp"
|
||||
|
||||
int tms320c1_t::emu(const insn_t &insn) const
|
||||
{
|
||||
//
|
||||
// Determine the current instruction's features.
|
||||
//
|
||||
int features = insn.get_canon_feature(ph);
|
||||
bool flow = (features & CF_STOP) == 0;
|
||||
|
||||
//
|
||||
// Examine each operand and determine what effect, if any,
|
||||
// it makes on the environment.
|
||||
//
|
||||
// Operands that are read
|
||||
if ( features & CF_USE1 )
|
||||
flow &= handle_operand(insn, insn.Op1, hop_READ);
|
||||
if ( features & CF_USE2 )
|
||||
flow &= handle_operand(insn, insn.Op2, hop_READ);
|
||||
if ( features & CF_USE3 )
|
||||
flow &= handle_operand(insn, insn.Op3, hop_READ);
|
||||
// Operands that are written
|
||||
if ( features & CF_CHG1 )
|
||||
flow &= handle_operand(insn, insn.Op1, hop_WRITE);
|
||||
if ( features & CF_CHG2 )
|
||||
flow &= handle_operand(insn, insn.Op2, hop_WRITE);
|
||||
if ( features & CF_CHG3 )
|
||||
flow &= handle_operand(insn, insn.Op3, hop_WRITE);
|
||||
|
||||
//
|
||||
// Determine whether the instruction stops the execution flow.
|
||||
//
|
||||
if ( flow )
|
||||
{
|
||||
//
|
||||
// This instruction doesn't stop execution flow.
|
||||
// Add a cross reference to the next instrction.
|
||||
//
|
||||
add_cref(insn.ea, insn.ea+insn.size, fl_F);
|
||||
}
|
||||
|
||||
//
|
||||
// If the instruction makes a branch, let the IDA kernel
|
||||
// know.
|
||||
//
|
||||
if ( features & CF_JUMP )
|
||||
remember_problem(PR_JUMP, insn.ea);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool tms320c1_t::handle_operand(const insn_t &insn, const op_t &op, opRefType ref_type) const
|
||||
{
|
||||
ea_t ea;
|
||||
sel_t data_selector;
|
||||
bool flow = true;
|
||||
|
||||
switch ( op.type )
|
||||
{
|
||||
case o_reg:
|
||||
//
|
||||
// Register operand.
|
||||
//
|
||||
//
|
||||
// Nothing needs to be calculated or examined for this
|
||||
// operand.
|
||||
//
|
||||
break;
|
||||
case o_imm:
|
||||
//
|
||||
// Immediate operand.
|
||||
//
|
||||
// Make sure that this operand reference isn't a write reference.
|
||||
// (Writing to an immediate value is not allowed and is a sure
|
||||
// sign of a badly decoded instruction).
|
||||
//
|
||||
if ( ref_type == hop_WRITE )
|
||||
{
|
||||
//
|
||||
// Attempt to write to an immediate value.
|
||||
// Error.
|
||||
//
|
||||
warning("%a: %s,%d: bad optype %d", insn.ea, insn.get_canon_mnem(ph), op.n, op.type);
|
||||
break;
|
||||
}
|
||||
//
|
||||
// SPECIAL INSTRUCTION CASE:
|
||||
//
|
||||
// The LDPK instruction is decoded by ana() to have an immediate
|
||||
// value as an operand. However, this immediate value is to be
|
||||
// the new data page pointer, which we must track for proper
|
||||
// memory referencing.
|
||||
//
|
||||
if ( insn.itype == I_LDPK )
|
||||
{
|
||||
//
|
||||
// This is an LDPK instruction. Let the kernel know that
|
||||
// we are changing the current data page pointer. We track
|
||||
// this bit as though it were a virtual segment register named
|
||||
// I_VDS, although it is not a true register in the CPU.
|
||||
//
|
||||
// Determine into which data page the instruction is attempting
|
||||
// to point.
|
||||
//
|
||||
if ( op.value == 0 )
|
||||
{
|
||||
//
|
||||
// Data page 0 is being loaded.
|
||||
//
|
||||
data_selector = tms320c1x_dpage0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Data page 1 is being loaded.
|
||||
//
|
||||
data_selector = tms320c1x_dpage1;
|
||||
}
|
||||
//
|
||||
// Notify the IDA kernel of the change.
|
||||
//
|
||||
split_sreg_range(
|
||||
insn.ea, // The current instruction's address
|
||||
IREG_VDS, // The segment register being modified
|
||||
data_selector, // The new selector value being loaded
|
||||
SR_auto); // How the new value was determined
|
||||
}
|
||||
//
|
||||
// Let the kernel know that the instruction's address should
|
||||
// be marked with a 'has immediate value' flag.
|
||||
// (Useful during search?)
|
||||
//
|
||||
set_immd(insn.ea);
|
||||
break;
|
||||
case o_phrase:
|
||||
//
|
||||
// Processor-specific phrase.
|
||||
//
|
||||
// These operands have no currently trackable side effect.
|
||||
//
|
||||
break;
|
||||
case o_mem:
|
||||
//
|
||||
// Direct memory reference.
|
||||
//
|
||||
|
||||
//
|
||||
// Ask the IDA kernel for the current data page pointer selector.
|
||||
//
|
||||
data_selector = get_sreg(insn.ea, IREG_VDS);
|
||||
|
||||
//
|
||||
// Is it known?
|
||||
//
|
||||
if ( data_selector == BADSEL )
|
||||
{
|
||||
//
|
||||
// The current data page pointer is unknown.
|
||||
// There is nothing to do.
|
||||
//
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// The current data page pointer is known.
|
||||
// Calculate the full effective address being referenced
|
||||
// by this operand.
|
||||
//
|
||||
ea = sel2ea(data_selector) + op.addr;
|
||||
|
||||
//
|
||||
// Generate a data cross reference from this instruction
|
||||
// to the target address.
|
||||
//
|
||||
insn.add_dref(ea, op.offb, ref_type == hop_READ ? dr_R : dr_W);
|
||||
}
|
||||
|
||||
//
|
||||
// TODO: DMOV, ...
|
||||
// These instructions read from the address in their operands
|
||||
// and write to the address ADJACENT to it.
|
||||
//
|
||||
break;
|
||||
case o_near:
|
||||
//
|
||||
// Code reference in current segment.
|
||||
//
|
||||
//
|
||||
// Determine the effective address of the reference.
|
||||
//
|
||||
ea = to_ea(insn.cs, op.addr);
|
||||
|
||||
//
|
||||
// Is this a 'CALL' type reference, or a branch type reference?
|
||||
//
|
||||
if ( has_insn_feature(insn.itype, CF_CALL) )
|
||||
{
|
||||
//
|
||||
// This is a CALL type reference. Make a cross reference
|
||||
// that notes it.
|
||||
//
|
||||
insn.add_cref(ea, op.offb, fl_CN);
|
||||
if ( !func_does_return(ea) )
|
||||
flow = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// This is a branch type reference. Make a cross reference
|
||||
// that notes it.
|
||||
//
|
||||
insn.add_cref(ea, op.offb, fl_JN);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
//
|
||||
// Unhandled operand type.
|
||||
// Error.
|
||||
//
|
||||
warning("%a: %s,%d: bad optype %d", insn.ea, insn.get_canon_mnem(ph), op.n, op.type);
|
||||
break;
|
||||
}
|
||||
return flow;
|
||||
}
|
||||
40
idasdk76/module/tms320c1/emu.hpp
Normal file
40
idasdk76/module/tms320c1/emu.hpp
Normal file
@@ -0,0 +1,40 @@
|
||||
// $Id: emu.hpp,v 1.2 2000/11/06 22:11:16 jeremy Exp $
|
||||
//
|
||||
// Copyright (c) 2000 Jeremy Cooper. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// 3. All advertising materials mentioning features or use of this software
|
||||
// must display the following acknowledgement:
|
||||
// This product includes software developed by Jeremy Cooper.
|
||||
// 4. The name of the author may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// IDA TMS320C1X processor module.
|
||||
// Instruction emulation/flow routines.
|
||||
//
|
||||
#ifndef _IDP_TMS320C1X_EMU_CPP
|
||||
#define _IDP_TMS320C1X_EMU_CPP
|
||||
|
||||
extern int idaapi emu(const insn_t &insn);
|
||||
|
||||
#endif // _IDP_TMS320C1X_EMU_CPP
|
||||
330
idasdk76/module/tms320c1/idp.cpp
Normal file
330
idasdk76/module/tms320c1/idp.cpp
Normal file
@@ -0,0 +1,330 @@
|
||||
// $Id: idp.cpp,v 1.9 2000/11/06 22:11:16 jeremy Exp $
|
||||
//
|
||||
// Copyright (c) 2000 Jeremy Cooper. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// 3. All advertising materials mentioning features or use of this software
|
||||
// must display the following acknowledgement:
|
||||
// This product includes software developed by Jeremy Cooper.
|
||||
// 4. The name of the author may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// IDA TMS320C1X processor module.
|
||||
// IDP module entry structure
|
||||
//
|
||||
#include "../idaidp.hpp"
|
||||
#include "tms320c1.hpp"
|
||||
#include "ana.hpp"
|
||||
#include "reg.hpp"
|
||||
#include "out.hpp"
|
||||
#include "ins.hpp"
|
||||
#include "asms.hpp"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// 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 tms320c1_t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//
|
||||
// This function is the entry point that is called to notify the processor
|
||||
// module of an important event.
|
||||
//
|
||||
ssize_t idaapi tms320c1_t::on_event(ssize_t msgid, va_list va)
|
||||
{
|
||||
int code = 1;
|
||||
switch ( msgid )
|
||||
{
|
||||
case processor_t::ev_init:
|
||||
//
|
||||
// Initialize the processor module.
|
||||
//
|
||||
tms320c1x_Init();
|
||||
break;
|
||||
case processor_t::ev_newfile:
|
||||
//
|
||||
// Prepare for decoding of the file that has just been
|
||||
// loaded.
|
||||
//
|
||||
tms320c1x_NewFile();
|
||||
break;
|
||||
case processor_t::ev_out_header:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
outHeader(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_footer:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
outFooter(*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 *);
|
||||
outSegStart(*ctx, seg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_ana_insn:
|
||||
{
|
||||
insn_t *out_ins = va_arg(va, insn_t *);
|
||||
return ana(out_ins);
|
||||
}
|
||||
|
||||
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:
|
||||
code = 0;
|
||||
break;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
//
|
||||
// tms320c1x_Init()
|
||||
//
|
||||
// Initialize the processor module.
|
||||
//
|
||||
// (Called from on_event()).
|
||||
//
|
||||
void tms320c1_t::tms320c1x_Init() const
|
||||
{
|
||||
//
|
||||
// Have the IDA kernel interpret the data within the virtual
|
||||
// address space in a big-endian manner.
|
||||
//
|
||||
inf_set_be(true);
|
||||
}
|
||||
|
||||
//
|
||||
// tms320c1x_NewFile()
|
||||
//
|
||||
// Make any preparations needed to interpret the file that has
|
||||
// just been loaded.
|
||||
//
|
||||
// (Called from on_event()).
|
||||
//
|
||||
void tms320c1_t::tms320c1x_NewFile()
|
||||
{
|
||||
ea_t data_start;
|
||||
segment_t dpage0, dpage1;
|
||||
|
||||
//
|
||||
// There are no known executable file formats for TMS320C1X executables.
|
||||
// Therefore, we will assume in this processor module that the user
|
||||
// has loaded a program ROM image into IDA. This image lacks any
|
||||
// definitions for data RAM, so we must create an area in IDA's virtual
|
||||
// address space to represent this RAM, thus enabling us to make
|
||||
// and track cross-references made to data RAM by TMS320C1X instructions.
|
||||
//
|
||||
// The TMS320C1X accesses data RAM in two discrete ways, the first of
|
||||
// which has a major impact on the strategy we must use to represent
|
||||
// data RAM.
|
||||
//
|
||||
// The first kind of access occurs during the execution of instructions
|
||||
// with immediate address operands. The 7-bit immediate address operand
|
||||
// is combined with the current data page pointer bit in the processor
|
||||
// status register to give an 8-bit final address. We will simulate this
|
||||
// behavior by keeping track of the data page pointer bit from instruction
|
||||
// to instruction, in effect acting as though it were a segment register.
|
||||
// We will then treat the 7-bit immediate address operand in each
|
||||
// instruction as though it were an offset into one of two data RAM
|
||||
// segments, depending on the current value of the data page pointer bit.
|
||||
// To do this, we need to create and define those two data segments here.
|
||||
//
|
||||
// The second manner in which the TMS320C1X access data RAM is during the
|
||||
// execution of instructions with indirect address operands. An indirect
|
||||
// address operand is one which identifies a location in data RAM
|
||||
// indirectly through the current value in one of the accumulator or
|
||||
// auxiliary registers. These memory references are fully qualified
|
||||
// since all three of these registers are spacious enough to hold all
|
||||
// 8-bits of addressing information. Therefore, we needn't do anything
|
||||
// special here to accomodate these instructions.
|
||||
//
|
||||
|
||||
//
|
||||
// Find a suitable place in IDA's virtual address space to place
|
||||
// the TMS320C1X's data RAM. Make sure it is aligned on a 16 byte
|
||||
// boundary.
|
||||
//
|
||||
data_start = free_chunk(0, TMS320C1X_DATA_RAM_SIZE, 15);
|
||||
|
||||
////
|
||||
//// Create the first data segment, otherwise known as 'data page 0'.
|
||||
////
|
||||
|
||||
//
|
||||
// Define its start and ending virtual address.
|
||||
//
|
||||
dpage0.start_ea = data_start;
|
||||
dpage0.end_ea = data_start + (TMS320C1X_DATA_RAM_SIZE / 2);
|
||||
//
|
||||
// Assign it a unique selector value.
|
||||
//
|
||||
dpage0.sel = allocate_selector(dpage0.start_ea >> 4);
|
||||
//
|
||||
// Let the kernel know that it is a DATA segment.
|
||||
//
|
||||
dpage0.type = SEG_DATA;
|
||||
//
|
||||
// Create the segment in the address space.
|
||||
//
|
||||
add_segm_ex(&dpage0, "dp0", NULL, ADDSEG_OR_DIE);
|
||||
|
||||
////
|
||||
//// Create the second data segment, otherwise known as 'data page 1'.
|
||||
////
|
||||
|
||||
//
|
||||
// Define its start and ending virtual address.
|
||||
//
|
||||
dpage1.start_ea = data_start + (TMS320C1X_DATA_RAM_SIZE / 2);
|
||||
dpage1.end_ea = data_start + TMS320C1X_DATA_RAM_SIZE;
|
||||
//
|
||||
// Assign it a unique selector value.
|
||||
//
|
||||
dpage1.sel = allocate_selector(dpage1.start_ea >> 4);
|
||||
//
|
||||
// Let the kernel know that it is a DATA segment.
|
||||
//
|
||||
dpage1.type = SEG_DATA;
|
||||
//
|
||||
// Create the segment in the address space.
|
||||
//
|
||||
add_segm_ex(&dpage1, "dp1", NULL, ADDSEG_OR_DIE);
|
||||
|
||||
//
|
||||
// Store the selectors of these two data segments in the global
|
||||
// variables tms320c1x_dpage0 and tms320c1x_dpage1.
|
||||
//
|
||||
tms320c1x_dpage0 = dpage0.sel;
|
||||
tms320c1x_dpage1 = dpage1.sel;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Short supported processor names.
|
||||
//
|
||||
// [ This array is named in our processor_t.psnames member ]
|
||||
//
|
||||
static const char *const shnames[] =
|
||||
{
|
||||
"tms320c1x",
|
||||
NULL
|
||||
};
|
||||
|
||||
//
|
||||
// Descriptive supported processor names.
|
||||
//
|
||||
// [ This array is named in our processor_t.plnames member ]
|
||||
//
|
||||
#define FAMILY "TMS320C1X Series:"
|
||||
static const char *const lnames[] =
|
||||
{
|
||||
FAMILY"Texas Instruments TMS320C1X DSP",
|
||||
NULL
|
||||
};
|
||||
|
||||
//
|
||||
// Array of opcode streams that represent a function return
|
||||
// instruction.
|
||||
//
|
||||
// [ This array is named in our processor_t.retcodes member ]
|
||||
//
|
||||
const bytes_t tms320c1x_retCodes[] =
|
||||
{
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// PROCESSOR MODULE DEFINITION
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
processor_t LPH =
|
||||
{
|
||||
IDP_INTERFACE_VERSION,// version
|
||||
PLFM_TMS320C1X, // id
|
||||
// flag
|
||||
//
|
||||
// processor module capablilty flags:
|
||||
//
|
||||
PR_RNAMESOK // A register name can be used to name a location
|
||||
| PR_BINMEM // The module creates segments for binary files
|
||||
| PR_SEGS, // We'd like to use the segment register tracking
|
||||
// features of IDA.
|
||||
// flag2
|
||||
0,
|
||||
//
|
||||
16, // Bits in a byte for code segments
|
||||
16, // Bits in a byte for other segments
|
||||
shnames, // Array of short processor names
|
||||
// the short names are used to specify the processor
|
||||
// with the -p command line switch)
|
||||
lnames, // array of long processor names
|
||||
// the long names are used to build the processor
|
||||
// selection menu type
|
||||
tms320c1x_Assemblers, // array of target assemblers
|
||||
|
||||
notify, // Callback function for kernel event notification
|
||||
|
||||
registerNames, // Regsiter names
|
||||
nregisterNames, // Number of registers
|
||||
|
||||
IREG_VCS, // First segment-register number
|
||||
IREG_VDS, // Last segment-register number
|
||||
1, // size of a segment register
|
||||
IREG_VCS, // CS segment-register number
|
||||
IREG_VDS, // DS segment-register number
|
||||
|
||||
NULL, // Known code start sequences
|
||||
tms320c1x_retCodes, // Known return opcodes
|
||||
|
||||
I__FIRST, // First instruction number
|
||||
I__LAST, // Last instruction number
|
||||
Instructions, // instruc
|
||||
};
|
||||
114
idasdk76/module/tms320c1/ins.cpp
Normal file
114
idasdk76/module/tms320c1/ins.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
// $Id: ins.cpp,v 1.2 2000/11/06 22:11:16 jeremy Exp $
|
||||
//
|
||||
// Copyright (c) 2000 Jeremy Cooper. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// 3. All advertising materials mentioning features or use of this software
|
||||
// must display the following acknowledgement:
|
||||
// This product includes software developed by Jeremy Cooper.
|
||||
// 4. The name of the author may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// TMS320C1X processor module.
|
||||
// Software representation of TMS320C1X instructions.
|
||||
//
|
||||
#include "../idaidp.hpp"
|
||||
|
||||
#include "ins.hpp"
|
||||
|
||||
//
|
||||
// Names and side-effect features of all instructions.
|
||||
// Used by the emu() function to determine instruction side effects
|
||||
// and report them to the kernel.
|
||||
//
|
||||
const instruc_t Instructions[] =
|
||||
{
|
||||
// Accumulator Memory Reference Instructions
|
||||
{ "ABS", 0 },
|
||||
{ "ADD", CF_USE1 },
|
||||
{ "ADDH", CF_USE1 },
|
||||
{ "ADDS", CF_USE1 },
|
||||
{ "AND", CF_USE1 },
|
||||
{ "LAC", CF_USE1 },
|
||||
{ "LACK", CF_USE1 },
|
||||
{ "OR", CF_USE1 },
|
||||
{ "SACH", CF_CHG1 },
|
||||
{ "SACL", CF_CHG1 },
|
||||
{ "SUB", CF_USE1 },
|
||||
{ "SUBC", CF_USE1 },
|
||||
{ "SUBH", CF_USE1 },
|
||||
{ "SUBS", CF_USE1 },
|
||||
{ "XOR", CF_USE1 },
|
||||
{ "ZAC", 0 },
|
||||
{ "ZALH", CF_USE1 },
|
||||
{ "ZALS", CF_USE1 },
|
||||
// Auxiliary Register and Data Page Pointer Instructions
|
||||
{ "LAR", CF_USE1 },
|
||||
{ "LARK", CF_USE1 },
|
||||
{ "LARP", CF_USE1 },
|
||||
{ "LDP", CF_USE1 },
|
||||
{ "LDPK", CF_USE1 },
|
||||
{ "MAR", 0 }, // no memory access occurs, just ARP and AR change
|
||||
{ "SAR", CF_CHG1 },
|
||||
// T Register, P Register, and Multiply Instructions
|
||||
{ "APAC", 0 },
|
||||
{ "LT", CF_USE1 },
|
||||
{ "LTA", CF_USE1 },
|
||||
{ "LTD", CF_USE1|CF_CHG1 }, // changes [Op1 + 1]!
|
||||
{ "MPY", CF_USE1 },
|
||||
{ "MPYK", CF_USE1 },
|
||||
{ "PAC", 0 },
|
||||
{ "SPAC", 0 },
|
||||
// Branch/Call Instructions
|
||||
{ "B", CF_USE1|CF_JUMP|CF_STOP },
|
||||
{ "BANZ", CF_USE1|CF_JUMP },
|
||||
{ "BGEZ", CF_USE1|CF_JUMP },
|
||||
{ "BGZ", CF_USE1|CF_JUMP },
|
||||
{ "BIOZ", CF_USE1|CF_JUMP },
|
||||
{ "BLEZ", CF_USE1|CF_JUMP },
|
||||
{ "BLZ", CF_USE1|CF_JUMP },
|
||||
{ "BNZ", CF_USE1|CF_JUMP },
|
||||
{ "BV", CF_USE1|CF_JUMP },
|
||||
{ "BZ", CF_USE1|CF_JUMP },
|
||||
{ "CALA", CF_CALL },
|
||||
{ "CALL", CF_USE1|CF_CALL },
|
||||
{ "RET", CF_STOP },
|
||||
// Control Instructions
|
||||
{ "DINT", 0 },
|
||||
{ "EINT", 0 },
|
||||
{ "LST", CF_USE1 },
|
||||
{ "NOP", 0 },
|
||||
{ "POP", 0 },
|
||||
{ "PUSH", 0 },
|
||||
{ "ROVM", 0 },
|
||||
{ "SOVM", 0 },
|
||||
{ "SST", CF_CHG1 }, // Operates in page 1 ONLY if direct
|
||||
// I/O and Data Memory Instructions
|
||||
{ "DMOV", CF_CHG1 }, // changes [Op1 + 1]!
|
||||
{ "IN", CF_CHG1 },
|
||||
{ "OUT", CF_USE1 },
|
||||
{ "TBLR", CF_CHG1 },
|
||||
{ "TBLW", CF_USE1 },
|
||||
};
|
||||
|
||||
CASSERT(qnumber(Instructions) == I__LAST);
|
||||
134
idasdk76/module/tms320c1/ins.hpp
Normal file
134
idasdk76/module/tms320c1/ins.hpp
Normal file
@@ -0,0 +1,134 @@
|
||||
// $Id: ins.hpp,v 1.6 2000/11/06 22:11:16 jeremy Exp $
|
||||
//
|
||||
// Copyright (c) 2000 Jeremy Cooper. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// 3. All advertising materials mentioning features or use of this software
|
||||
// must display the following acknowledgement:
|
||||
// This product includes software developed by Jeremy Cooper.
|
||||
// 4. The name of the author may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// IDA TMS320C1X processor module.
|
||||
// Software representation of TMS320C1X instructions.
|
||||
//
|
||||
#ifndef _IDP_TMS320C1X_INS_H
|
||||
#define _IDP_TMS320C1X_INS_H
|
||||
|
||||
enum nameNum
|
||||
{
|
||||
// Accumulator Memory Reference Instructions
|
||||
I__FIRST = 0,
|
||||
I_ABS = 0,
|
||||
I_ADD,
|
||||
I_ADDH,
|
||||
I_ADDS,
|
||||
I_AND,
|
||||
I_LAC,
|
||||
I_LACK,
|
||||
I_OR,
|
||||
I_SACH,
|
||||
I_SACL,
|
||||
I_SUB,
|
||||
I_SUBC,
|
||||
I_SUBH,
|
||||
I_SUBS,
|
||||
I_XOR,
|
||||
I_ZAC,
|
||||
I_ZALH,
|
||||
I_ZALS,
|
||||
// Auxiliary Register and Data Page Pointer Instructions
|
||||
I_LAR,
|
||||
I_LARK,
|
||||
I_LARP,
|
||||
I_LDP,
|
||||
I_LDPK,
|
||||
I_MAR,
|
||||
I_SAR,
|
||||
// T Register, P Register, and Multiply Instructions
|
||||
I_APAC,
|
||||
I_LT,
|
||||
I_LTA,
|
||||
I_LTD,
|
||||
I_MPY,
|
||||
I_MPYK,
|
||||
I_PAC,
|
||||
I_SPAC,
|
||||
// Branch/Call Instructions
|
||||
I_B,
|
||||
I_BANZ,
|
||||
I_BGEZ,
|
||||
I_BGZ,
|
||||
I_BIOZ,
|
||||
I_BLEZ,
|
||||
I_BLZ,
|
||||
I_BNZ,
|
||||
I_BV,
|
||||
I_BZ,
|
||||
I_CALA,
|
||||
I_CALL,
|
||||
I_RET,
|
||||
// Control Instructions
|
||||
I_DINT,
|
||||
I_EINT,
|
||||
I_LST,
|
||||
I_NOP,
|
||||
I_POP,
|
||||
I_PUSH,
|
||||
I_ROVM,
|
||||
I_SOVM,
|
||||
I_SST,
|
||||
// I/O and Data Memory Instructions
|
||||
I_DMOV,
|
||||
I_IN,
|
||||
I_OUT,
|
||||
I_TBLR,
|
||||
I_TBLW,
|
||||
I__LAST
|
||||
};
|
||||
|
||||
//
|
||||
// TMS320C1X register phrases.
|
||||
// These are used to represent instruction operands that are not either
|
||||
// immediate values or registers.
|
||||
//
|
||||
enum regPhrase
|
||||
{
|
||||
IPH_AR, // Dereference current aux register
|
||||
IPH_AR_INCR, // Dereference current aux register and post-increment
|
||||
IPH_AR_DECR, // Dereference current aux register and post-decrement
|
||||
};
|
||||
|
||||
//
|
||||
// Auxilliary instruction information.
|
||||
// This is information that this processor module can add to the instruction,
|
||||
// only to be examined and consumed by the processor module itself.
|
||||
//
|
||||
#define IX_DATA_PAGE_KNOWN 0x8000 // The current data page is known
|
||||
#define IX_DATA_PAGE(x) ((x) & 0x1) // Retrieves the known data page
|
||||
|
||||
extern const instruc_t Instructions[];
|
||||
|
||||
#endif // _IDP_TMS320C1X_INS_H
|
||||
|
||||
|
||||
60
idasdk76/module/tms320c1/makefile
Normal file
60
idasdk76/module/tms320c1/makefile
Normal file
@@ -0,0 +1,60 @@
|
||||
PROC=tms320c1
|
||||
O1=idp
|
||||
O2=asms
|
||||
|
||||
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 \
|
||||
reg.hpp tms320c1.hpp
|
||||
$(F)asms$(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 asms.cpp asms.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 reg.hpp tms320c1.hpp
|
||||
$(F)idp$(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.hpp asms.hpp \
|
||||
idp.cpp ins.hpp out.hpp reg.hpp tms320c1.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
|
||||
$(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 out.hpp reg.hpp
|
||||
$(F)reg$(O) : reg.cpp reg.hpp
|
||||
333
idasdk76/module/tms320c1/out.cpp
Normal file
333
idasdk76/module/tms320c1/out.cpp
Normal file
@@ -0,0 +1,333 @@
|
||||
// $Id: out.cpp,v 1.7 2000/11/06 22:11:16 jeremy Exp $
|
||||
//
|
||||
// Copyright (c) 2000 Jeremy Cooper. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// 3. All advertising materials mentioning features or use of this software
|
||||
// must display the following acknowledgement:
|
||||
// This product includes software developed by Jeremy Cooper.
|
||||
// 4. The name of the author may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// IDA TMS320C1X processor module.
|
||||
// Instruction display routines
|
||||
//
|
||||
#include "../idaidp.hpp"
|
||||
|
||||
#include <segregs.hpp>
|
||||
|
||||
#include "ins.hpp"
|
||||
#include "out.hpp"
|
||||
#include "reg.hpp"
|
||||
|
||||
//
|
||||
// outSegStart()
|
||||
//
|
||||
// [ This function is named in our processor_t.segstart member ]
|
||||
//
|
||||
// Generate assembly text before the start of a segment.
|
||||
//
|
||||
void idaapi outSegStart(outctx_t &ctx, segment_t *)
|
||||
{
|
||||
ctx.gen_cmt_line("A segment starts here.");
|
||||
}
|
||||
|
||||
//
|
||||
// outSegEnd()
|
||||
//
|
||||
// [ This function is named in our processor_t.segend member ]
|
||||
//
|
||||
// Generate assembly text after the end of a segment.
|
||||
//
|
||||
void idaapi outSegEnd(outctx_t &ctx, segment_t *)
|
||||
{
|
||||
ctx.gen_cmt_line("A segment ends here.");
|
||||
}
|
||||
|
||||
//
|
||||
// outHeader()
|
||||
//
|
||||
// [ This function is named in our processor_t.header member ]
|
||||
//
|
||||
// Generate an assembly header for the top of the file.
|
||||
//
|
||||
void idaapi outHeader(outctx_t &ctx)
|
||||
{
|
||||
ctx.gen_header(GH_PRINT_PROC_AND_ASM);
|
||||
}
|
||||
|
||||
//
|
||||
// outFooter()
|
||||
//
|
||||
// [ This function is named in our processor_t.footer member ]
|
||||
//
|
||||
// Generate an assembly footer for the bottom of the file.
|
||||
//
|
||||
void idaapi outFooter(outctx_t &ctx)
|
||||
{
|
||||
ctx.gen_cmt_line("End of file");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DISASSEMBLY OPERAND HELPER FUNCTIONS
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_tms320c1_t)
|
||||
|
||||
//
|
||||
// outPhrase(phrase)
|
||||
// Output a TMS320C1X-specific operand phrase.
|
||||
//
|
||||
void out_tms320c1_t::outPhrase(int phrase)
|
||||
{
|
||||
//
|
||||
// Complex phrase operand.
|
||||
// (Processor specific)
|
||||
//
|
||||
switch ( phrase )
|
||||
{
|
||||
case IPH_AR:
|
||||
//
|
||||
// Current address register, indirect.
|
||||
//
|
||||
out_symbol('*');
|
||||
break;
|
||||
case IPH_AR_INCR:
|
||||
//
|
||||
// Current address register, indirect, post-increment.
|
||||
//
|
||||
out_symbol('*');
|
||||
out_symbol('+');
|
||||
break;
|
||||
case IPH_AR_DECR:
|
||||
//
|
||||
// Current address register, indirect, post-decrement.
|
||||
//
|
||||
out_symbol('*');
|
||||
out_symbol('-');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// outNear(operand)
|
||||
//
|
||||
// Display an operand that is known to reference another piece of
|
||||
// of code.
|
||||
//
|
||||
void out_tms320c1_t::outNear(const op_t &op)
|
||||
{
|
||||
//
|
||||
// Calculate the effective address of this code reference.
|
||||
//
|
||||
ea_t ea = to_ea(insn.cs, op.addr);
|
||||
|
||||
//
|
||||
// Find or create a name for the code address that this operand
|
||||
// references so that we can output that name in the operand's
|
||||
// place.
|
||||
//
|
||||
if ( !out_name_expr(op, ea, op.addr) )
|
||||
//
|
||||
// The code address didn't have a name. Default to
|
||||
// displaying the address as a number.
|
||||
//
|
||||
out_value(op, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN);
|
||||
|
||||
//
|
||||
// Let the user know that he or she should look at this
|
||||
// instruction and attempt to name the address that it
|
||||
// references.
|
||||
//
|
||||
remember_problem(PR_NONAME, insn.ea);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// outNear(operand)
|
||||
//
|
||||
// Display an operand that is known to reference data RAM.
|
||||
//
|
||||
void out_tms320c1_t::outMem(const op_t &op)
|
||||
{
|
||||
//
|
||||
// Ask the IDA kernel for the value of the current data page
|
||||
// pointer for execution of this instruction.
|
||||
//
|
||||
sel_t data_selector = get_sreg(insn.ea, IREG_VDS);
|
||||
|
||||
//
|
||||
// Is it known?
|
||||
//
|
||||
if ( data_selector == BADSEL )
|
||||
{
|
||||
//
|
||||
// The current data page pointer is not known.
|
||||
//
|
||||
//
|
||||
// Display the current operand as a regular number and
|
||||
// return.
|
||||
//
|
||||
out_value(op, OOF_ADDR);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// The current data page pointer is known. Use it to calculate the
|
||||
// effective address of the memory being referenced by this
|
||||
// operand.
|
||||
//
|
||||
ea_t ea = sel2ea(data_selector) + op.addr;
|
||||
|
||||
//
|
||||
// Find or create a name for the data address that this operand
|
||||
// references so that we can output that name in the operand's
|
||||
// place.
|
||||
//
|
||||
if ( !out_name_expr(op, ea, op.addr) )
|
||||
{
|
||||
//
|
||||
// No name was found and no name was created.
|
||||
// Display the current operand as a regular number.
|
||||
//
|
||||
out_value(op, OOF_ADDR);
|
||||
|
||||
//
|
||||
// Let the user know that he or she should look at this
|
||||
// instruction and attempt to name the address that it
|
||||
// references.
|
||||
//
|
||||
remember_problem(PR_NONAME, insn.ea);
|
||||
}
|
||||
}
|
||||
|
||||
bool out_tms320c1_t::out_operand(const op_t &op)
|
||||
{
|
||||
switch ( op.type )
|
||||
{
|
||||
case o_reg:
|
||||
//
|
||||
// Register operand.
|
||||
//
|
||||
outreg(op.reg);
|
||||
break;
|
||||
case o_phrase:
|
||||
//
|
||||
// Complex phrase.
|
||||
// (Processor specific)
|
||||
//
|
||||
outPhrase(op.phrase);
|
||||
break;
|
||||
case o_imm:
|
||||
//
|
||||
// Immediate value.
|
||||
//
|
||||
out_value(op, 0);
|
||||
break;
|
||||
case o_near:
|
||||
//
|
||||
// Code reference.
|
||||
//
|
||||
outNear(op);
|
||||
break;
|
||||
case o_mem:
|
||||
//
|
||||
// Data memory reference.
|
||||
//
|
||||
outMem(op);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void out_tms320c1_t::out_insn()
|
||||
{
|
||||
//
|
||||
// An unseen parameter to this function is the 'insn' structure
|
||||
// which holds all the information about the instruction that we
|
||||
// are being asked to display.
|
||||
//
|
||||
|
||||
// This call to out_mnemonic() is a helper function in the IDA kernel that
|
||||
// displays an instruction mnemonic for the current instruction.
|
||||
// It does so by taking the integer value in insn.itype and using it
|
||||
// as an index into the array that we named in this processor module's
|
||||
// processor_t.instruc member. From this indexed element comes the
|
||||
// instruction mnemonic to be displayed.
|
||||
//
|
||||
out_mnemonic();
|
||||
|
||||
//
|
||||
// If the current instruction has a non-empty first operand,
|
||||
// then display it.
|
||||
//
|
||||
if ( insn.Op1.type != o_void )
|
||||
{
|
||||
//
|
||||
// This call to out_one_operand() is another IDA kernel function that
|
||||
// is mandatory for a properly behaved processor module.
|
||||
//
|
||||
// Normally, this helper function turns around and calls the function
|
||||
// named in our processor_t.u_outop member with a reference to
|
||||
// the current instruction's operand numbered in the first argument.
|
||||
// However, if through the course of interacting with the
|
||||
// disassembly the user chooses to manually override the specified
|
||||
// operand in this instruction, the IDA kernel will forego the call
|
||||
// to u_outop() -- instead calling an internal IDA routine to
|
||||
// display the user's manually entered operand.
|
||||
//
|
||||
out_one_operand(0);
|
||||
}
|
||||
//
|
||||
// Display the second operand, if non-empty.
|
||||
//
|
||||
if ( insn.Op2.type != o_void )
|
||||
{
|
||||
//
|
||||
// This call to out_symbol() is another helper function in the
|
||||
// IDA kernel. It writes the specified character to the current
|
||||
// buffer, using the user-configurable 'symbol' color.
|
||||
//
|
||||
out_symbol(',');
|
||||
out_char(' ');
|
||||
out_one_operand(1);
|
||||
}
|
||||
//
|
||||
// Finally, display the third operand, if non-empty.
|
||||
//
|
||||
if ( insn.Op3.type != o_void )
|
||||
{
|
||||
out_symbol(',');
|
||||
out_char(' ');
|
||||
out_one_operand(2);
|
||||
}
|
||||
|
||||
//
|
||||
// Tell IDA to display our constructed line.
|
||||
//
|
||||
flush_outbuf();
|
||||
}
|
||||
67
idasdk76/module/tms320c1/out.hpp
Normal file
67
idasdk76/module/tms320c1/out.hpp
Normal file
@@ -0,0 +1,67 @@
|
||||
// $Id: out.hpp,v 1.4 2000/11/06 22:11:17 jeremy Exp $
|
||||
//
|
||||
// Copyright (c) 2000 Jeremy Cooper. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// 3. All advertising materials mentioning features or use of this software
|
||||
// must display the following acknowledgement:
|
||||
// This product includes software developed by Jeremy Cooper.
|
||||
// 4. The name of the author may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// IDA TMS320C1X processor module.
|
||||
// Instruction display routines
|
||||
//
|
||||
#ifndef _IDP_TMS320C1X_OUT_H
|
||||
#define _IDP_TMS320C1X_OUT_H
|
||||
|
||||
void idaapi outSegStart(outctx_t &, segment_t *);
|
||||
void idaapi outSegEnd(outctx_t &, segment_t *);
|
||||
void idaapi outHeader(outctx_t &);
|
||||
void idaapi outFooter(outctx_t &);
|
||||
bool idaapi outOp(outctx_t &ctx, const op_t &op);
|
||||
void idaapi out(outctx_t &ctx);
|
||||
|
||||
// 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_tms320c1_t : public outctx_t
|
||||
{
|
||||
out_tms320c1_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 outPhrase(int phrase);
|
||||
void outNear(const op_t &op);
|
||||
void outMem(const op_t &op);
|
||||
};
|
||||
CASSERT(sizeof(out_tms320c1_t) == sizeof(outctx_t));
|
||||
|
||||
|
||||
#endif // _IDP_TMS320C1X_OUT_H
|
||||
|
||||
|
||||
|
||||
|
||||
52
idasdk76/module/tms320c1/reg.cpp
Normal file
52
idasdk76/module/tms320c1/reg.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
// $Id: reg.cpp,v 1.3 2000/11/06 22:11:17 jeremy Exp $
|
||||
//
|
||||
// Copyright (c) 2000 Jeremy Cooper. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// 3. All advertising materials mentioning features or use of this software
|
||||
// must display the following acknowledgement:
|
||||
// This product includes software developed by Jeremy Cooper.
|
||||
// 4. The name of the author may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// IDA TMS320C1X processor module.
|
||||
// TMS320C1X register names.
|
||||
//
|
||||
#include "reg.hpp"
|
||||
|
||||
//
|
||||
// The following doesn't represent all of the TMS320C1X's registers.
|
||||
// It only represents those registers that are explicitly specified
|
||||
// in instruction mnemonics.
|
||||
//
|
||||
const char *const registerNames[] =
|
||||
{
|
||||
"AR0", // Address register zero
|
||||
"AR1", // Address register one.
|
||||
//
|
||||
// Special registers required by IDA kernel.
|
||||
//
|
||||
"VCS",
|
||||
"VDS"
|
||||
};
|
||||
const int nregisterNames = sizeof(registerNames) / sizeof(*registerNames);
|
||||
58
idasdk76/module/tms320c1/reg.hpp
Normal file
58
idasdk76/module/tms320c1/reg.hpp
Normal file
@@ -0,0 +1,58 @@
|
||||
// $Id: reg.hpp,v 1.2 2000/11/06 22:11:17 jeremy Exp $
|
||||
//
|
||||
// Copyright (c) 2000 Jeremy Cooper. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// 3. All advertising materials mentioning features or use of this software
|
||||
// must display the following acknowledgement:
|
||||
// This product includes software developed by Jeremy Cooper.
|
||||
// 4. The name of the author may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// IDA TMS320C1X processor module.
|
||||
// Constants used for representing TMS320C1X registers in instructions.
|
||||
//
|
||||
#ifndef _IDP_TMS320C1X_REG_H
|
||||
#define _IDP_TMS320C1X_REG_H
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define ENUM8BIT : unsigned char
|
||||
#else
|
||||
#define ENUM8BIT
|
||||
#endif
|
||||
enum tms320c1x_register ENUM8BIT
|
||||
{
|
||||
IREG_AR0, // Address register zero
|
||||
IREG_AR1, // Address register one
|
||||
//
|
||||
// Virtual registers required by IDA kernel
|
||||
//
|
||||
IREG_VCS,
|
||||
IREG_VDS,
|
||||
IREG__LAST
|
||||
};
|
||||
|
||||
extern const char *const registerNames[];
|
||||
extern const int nregisterNames;
|
||||
|
||||
#endif // _IDP_TMS320C1X_REG_H
|
||||
210
idasdk76/module/tms320c1/tms320c1.hpp
Normal file
210
idasdk76/module/tms320c1/tms320c1.hpp
Normal file
@@ -0,0 +1,210 @@
|
||||
// $Id: tms320c1.hpp,v 1.8 2000/11/06 22:11:17 jeremy Exp $
|
||||
//
|
||||
// Copyright (c) 2000 Jeremy Cooper. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// 3. All advertising materials mentioning features or use of this software
|
||||
// must display the following acknowledgement:
|
||||
// This product includes software developed by Jeremy Cooper.
|
||||
// 4. The name of the author may not be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//
|
||||
// IDA TMS320C1X processor module.
|
||||
// TMS320C1X constants, etc.
|
||||
//
|
||||
#ifndef _IDP_TMS320C1X_H
|
||||
#define _IDP_TMS320C1X_H
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// TMS320C1X Instruction Opcodes
|
||||
//
|
||||
// To ease decoding requirements, we have classified each TMS320C1X
|
||||
// instruction by the number of significant bits that need to be scanned in
|
||||
// the instruction opcode in order to uniquely identify it.
|
||||
//
|
||||
|
||||
//
|
||||
// Bit scanning masks
|
||||
//
|
||||
#define ISN_3_BIT_MASK 0xe000 // 111x xxxx xxxx xxxx
|
||||
#define ISN_4_BIT_MASK 0xf000 // 1111 xxxx xxxx xxxx
|
||||
#define ISN_5_BIT_MASK 0xf800 // 1111 1xxx xxxx xxxx
|
||||
#define ISN_7_BIT_MASK 0xfe00 // 1111 111x xxxx xxxx
|
||||
#define ISN_8_BIT_MASK 0xff00 // 1111 1111 xxxx xxxx
|
||||
#define ISN_15_BIT_MASK 0xfffe // 1111 1111 1111 111x
|
||||
#define ISN_16_BIT_MASK 0xffff // 1111 1111 1111 1111
|
||||
|
||||
//
|
||||
// 3 bit Opcodes
|
||||
//
|
||||
enum isn_3bit
|
||||
{
|
||||
ISN3_MPYK = 0x8000, // 100...
|
||||
};
|
||||
//
|
||||
// 4 bit Opcodes
|
||||
//
|
||||
enum isn_4bit
|
||||
{
|
||||
ISN4_ADD = 0x0000, // 0000...
|
||||
ISN4_LAC = 0x2000, // 0100...
|
||||
ISN4_SUB = 0x1000, // 0001...
|
||||
};
|
||||
//
|
||||
// 5 bit Opcodes
|
||||
//
|
||||
enum isn_5bit
|
||||
{
|
||||
ISN5_SACH = 0x5800, // 0101 1...
|
||||
ISN5_IN = 0x4000, // 0100 0...
|
||||
ISN5_OUT = 0x4800, // 0100 1...
|
||||
};
|
||||
//
|
||||
// 7 bit Opcodes
|
||||
//
|
||||
enum isn_7bit
|
||||
{
|
||||
ISN7_LAR = 0x3800, // 0011 100...
|
||||
ISN7_LARK = 0x7000, // 0111 000...
|
||||
ISN7_SAR = 0x3000, // 0011 000...
|
||||
};
|
||||
//
|
||||
// 8 bit Opcodes
|
||||
//
|
||||
enum isn_8bit
|
||||
{
|
||||
ISN8_ADDH = 0x6000, // 0110 0000 ...
|
||||
ISN8_ADDS = 0x6100, // 0110 0001 ...
|
||||
ISN8_AND = 0x7900, // 0111 1001 ...
|
||||
ISN8_LACK = 0x7e00, // 0111 1110 ...
|
||||
ISN8_OR = 0x7a00, // 0111 1010 ...
|
||||
ISN8_SACL = 0x5000, // 0101 0000 ...
|
||||
ISN8_SUBC = 0x6400, // 0110 0100 ...
|
||||
ISN8_SUBH = 0x6200, // 0110 0010 ...
|
||||
ISN8_SUBS = 0x6300, // 0110 0011 ...
|
||||
ISN8_XOR = 0x7800, // 0111 1000 ...
|
||||
ISN8_ZALH = 0x6500, // 0110 0101 ...
|
||||
ISN8_ZALS = 0x6600, // 0110 0110 ...
|
||||
ISN8_LDP = 0x6f00, // 0110 1111 ...
|
||||
ISN8_MAR = 0x6800, // 0110 1000 ...
|
||||
ISN8_LT = 0x6a00, // 0110 1010 ...
|
||||
ISN8_LTA = 0x6c00, // 0110 1100 ...
|
||||
ISN8_LTD = 0x6b00, // 0110 1011 ...
|
||||
ISN8_MPY = 0x6d00, // 0110 1101 ...
|
||||
ISN8_LST = 0x7b00, // 0111 1101 ...
|
||||
ISN8_SST = 0x7c00, // 0111 1100 ...
|
||||
ISN8_DMOV = 0x6900, // 0110 1001 ...
|
||||
ISN8_TBLR = 0x6700, // 0110 0111 ...
|
||||
ISN8_TBLW = 0x7d00, // 0111 1101 ...
|
||||
};
|
||||
//
|
||||
// 15 bit Opcodes
|
||||
//
|
||||
enum isn_15bit
|
||||
{
|
||||
// LARP is a synonym for a special case of MAR
|
||||
// ISN15_LARP = 0x6880, // 0110 1000 1000 000.
|
||||
ISN15_LDPK = 0x6e00, // 0110 1110 0000 000.
|
||||
};
|
||||
//
|
||||
// 16 bit Opcodes
|
||||
//
|
||||
enum isn_16bit
|
||||
{
|
||||
ISN16_ABS = 0x7f88, // 0111 1111 1000 1000
|
||||
ISN16_ZAC = 0x7f89, // 0111 1111 1000 0101
|
||||
ISN16_APAC = 0x7f8f, // 0111 1111 1000 1111
|
||||
ISN16_PAC = 0x7f8e, // 0111 1111 1000 1110
|
||||
ISN16_SPAC = 0x7f90, // 0111 1111 1001 0000
|
||||
ISN16_B = 0xf900, // 1111 1001 0000 0000
|
||||
ISN16_BANZ = 0xf400, // 1111 0100 0000 0000
|
||||
ISN16_BGEZ = 0xfd00, // 1111 1101 0000 0000
|
||||
ISN16_BGZ = 0xfc00, // 1111 1100 0000 0000
|
||||
ISN16_BIOZ = 0xf600, // 1111 0110 0000 0000
|
||||
ISN16_BLEZ = 0xfb00, // 1111 1011 0000 0000
|
||||
ISN16_BLZ = 0xfa00, // 1111 1010 0000 0000
|
||||
ISN16_BNZ = 0xfe00, // 1111 1110 0000 0000
|
||||
ISN16_BV = 0xf500, // 1111 0101 0000 0000
|
||||
ISN16_BZ = 0xff00, // 1111 1111 0000 0000
|
||||
ISN16_CALA = 0x7f8c, // 0111 1111 1000 1100
|
||||
ISN16_CALL = 0xf800, // 1111 1000 0000 0000
|
||||
ISN16_RET = 0x7f8d, // 0111 1111 1000 1101
|
||||
ISN16_DINT = 0x7f81, // 0111 1111 1000 0001
|
||||
ISN16_EINT = 0x7f82, // 0111 1111 1000 0010
|
||||
ISN16_NOP = 0x7f80, // 0111 1111 1000 0000
|
||||
ISN16_POP = 0x7f9d, // 0111 1111 1001 1101
|
||||
ISN16_PUSH = 0x7f9c, // 0111 1111 1001 1100
|
||||
ISN16_ROVM = 0x7f8a, // 0111 1111 1000 1010
|
||||
ISN16_SOVM = 0x7f8b, // 0111 1111 1000 1011
|
||||
};
|
||||
|
||||
//
|
||||
// Instruction property macros.
|
||||
// These macros deduce certain facts about the instruction.
|
||||
//
|
||||
#define ISN_IMM1(op) ((op) & 0x0001) // Immediate 1 bit value
|
||||
#define ISN_IMM8(op) ((op) & 0x00ff) // Immediate 8 bit value
|
||||
#define ISN_IMM13(op) ((op) & 0x1fff) // Immediate 13 bit value
|
||||
#define ISN_DIRECT(op) (!((op) & 0x0080)) // Direct/Indirect reference flag
|
||||
#define ISN_DIR_ADDR(op) ((op) & 0x007f) // Direct memory location
|
||||
#define ISN_INDIR_INCR(op) ((op) & 0x0020) // Aux reg. post-increment flag
|
||||
#define ISN_INDIR_DECR(op) ((op) & 0x0010) // Aux reg. post-decrement flag
|
||||
#define ISN_INDIR_NARP(op) ((op) & 0x0008) // Aux reg. change flag
|
||||
#define ISN_INDIR_ARP(op) ((op) & 0x0001) // New aux reg. pointer value
|
||||
#define ISN_AUX_AR(op) ((op) & 0x0100) // Aux register index
|
||||
#define ISN_SHIFT(o) (((o)&0x0f00)>>8) // Data bit shift amount
|
||||
#define ISN_PORT(o) (((o)&0x0700)>>8) // I/O port number
|
||||
|
||||
//
|
||||
// TMS320C1X environment facts.
|
||||
// These macros define the size of the TMS320C1X's addressable
|
||||
// data RAM.
|
||||
//
|
||||
#define TMS320C1X_DATA_RAM_SIZE 256 // 256 bytes
|
||||
|
||||
//
|
||||
// Reference type. Used between emu() and handle_operand() to
|
||||
// flag whether an operand is written to or read from.
|
||||
//
|
||||
enum opRefType
|
||||
{
|
||||
hop_READ,
|
||||
hop_WRITE,
|
||||
};
|
||||
|
||||
struct tms320c1_t : public procmod_t
|
||||
{
|
||||
sel_t tms320c1x_dpage0; // Data page 0 selector
|
||||
sel_t tms320c1x_dpage1; // Data page 1 selector
|
||||
|
||||
virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override;
|
||||
|
||||
// Kernel message handlers.
|
||||
void tms320c1x_Init() const;
|
||||
void tms320c1x_NewFile();
|
||||
|
||||
int emu(const insn_t &insn) const;
|
||||
bool handle_operand(const insn_t &insn, const op_t &op, opRefType ref_type) const;
|
||||
};
|
||||
|
||||
#endif // IDP_TMS320C1X_H
|
||||
Reference in New Issue
Block a user