update to ida 7.6, add builds
This commit is contained in:
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
|
||||
};
|
||||
Reference in New Issue
Block a user