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

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,64 @@
; This file describes the standard addresses for Motorola DSP561xx
.default 561xx
entry HRESET 0x0000 Hardware RESET
entry ILLEGAL 0x0002 Illegal Instruction
entry STACKERROR 0x0004 Stack Error
entry SWI 0x0008 Software Interrupt
entry IRQA 0x000A IRQA
entry IRQB 0x000C IRQB
entry SSI0RxwExcept 0x0010 SSI0 Receive Data with Exception
entry SSI0Rx 0x0012 SSI0 Receive Data
entry SSI0TxwExcept 0x0014 SSI0 Transmit Data with Exception
entry SSI0Tx 0x0016 SSI0 Transmit Data
entry SSI1RxwExcept 0x0018 SSI1 Receive Data with Exception
entry SSI1Rx 0x001A SSI1 Receive Data
entry SSI1TxwExcept 0x001C SSI1 Transmit Data with Exception
entry SSI1Tx 0x001E SSI1 Transmit Data
entry TimerOVF 0x0020 Timer Overflow
entry TimerCMP 0x0022 Timer Compare
entry HostDMARx 0x0024 Host DMA Receive Data
entry HostDMATx 0x0026 Host DMA Transmit Data
entry HostRx 0x0028 Host Receive Data
entry HostTx 0x002A Host Transmit Data
entry HostCMD 0x002C Host Command (default)
entry CodecTxRx 0x002E Codec Receive/Transmit
.561xx
PBC 0xFFC0
PCC 0xFFC1
PBDD 0xFFC2
PCDD 0xFFC3
HCR 0xFFC4
COCR 0xFFC8
CRASSI0 0xFFD0
CRBSSI0 0xFFD1
CRASSI1 0xFFD8
CRBSSI1 0xFFD9
PLCR 0xFFDC
BCR 0xFFDE
IPR 0xFFDF
PBD 0xFFE2
PCD 0xFFE3
HSR 0xFFE4
HTXRX 0xFFE5
COSR 0xFFE9
CRXTX 0xFFEA
TCR 0xFFEC
TCTR 0xFFED
TCPR 0xFFEE
TPR 0xFFEF
SRSSI0 0xFFF0
TXRXSSI0 0xFFF1
RSMA0 0xFFF2
RSMB0 0xFFF3
TSMA0 0xFFF4
TSMB0 0xFFF5
SRSSI1 0xFFF8
TXRXSSI1 0xFFF9
RSMA1 0xFFFA
RSMB1 0xFFFB
TSMA1 0xFFFC
TSMB1 0xFFFD

View File

@@ -0,0 +1,169 @@
; This file describes the standard addresses for Motorola DSP563xx
.default 56301
entry HRESET 0x0000 Hardware RESET
entry STKERR 0x0002 Stack Error
entry ILLEGAL 0x0004 Illegal Instruction
entry DEBUG 0x0006 Debug Request Interrupt
entry TRAP 0x0008 Trap
entry NMI 0x000A Non-Maskable Interrupt
entry IRQA 0x0010 IRQA
entry IRQB 0x0012 IRQB
entry IRQC 0x0014 IRQC
entry IRQD 0x0016 IRQD
entry DMA0 0x0018 DMA Channel 0
entry DMA1 0x001A DMA Channel 1
entry DMA2 0x001C DMA Channel 2
entry DMA3 0x001E DMA Channel 3
entry DMA4 0x0020 DMA Channel 4
entry DMA5 0x0022 DMA Channel 5
entry TIMER0CMP 0x0024 TIMER 0 compare
entry TIMER0OWL 0x0026 TIMER 0 overflow
entry TIMER1CMP 0x0028 TIMER 1 compare
entry TIMER1OWL 0x002A TIMER 1 overflow
entry TIMER2CMP 0x002C TIMER 2 compare
entry TIMER2OWL 0x002E TIMER 2 overflow
entry ESSI0Rxd 0x0030 ESSI0 receive data
entry ESSI0RxdwExcept 0x0032 ESSI0 receive data with exception status
entry ESSI0RxdLL 0x0034 ESSI0 receive last slot
entry ESSI0Txd 0x0036 ESSI0 transmit data
entry ESSI0TxdwExcept 0x0038 ESSI0 transmit data with exception status
entry ESSI0TxdLL 0x003A ESSI0 transmit last slot
entry ESSI1Rxd 0x0040 ESSI1 receive data
entry ESSI1RxdwExcept 0x0042 ESSI1 receive data with exception status
entry ESSI1RxdLL 0x0044 ESSI1 receive last slot
entry ESSI1Txd 0x0046 ESSI1 transmit data
entry ESSI1TxdwExcept 0x0048 ESSI1 transmit data with exception status
entry ESSI1TxdLL 0x004A ESSI1 transmit last slot
entry SCIRxData 0x0050 SCI receive data
entry SCIRxDatawExcept 0x0052 SCI receive data with exception status
entry SCITxData 0x0054 SCI transmit data
entry SCIidle 0x0056 SCI idle line
entry SCItimer 0x0058 SCI timer
entry HostPCITransTerm 0x0060 Host PCI transaction termination
entry HostPCITransAbort 0x0062 Host PCI transaction abort
entry HostPCIP_error 0x0064 Host PCI parity error
entry HostPCITransCompl 0x0066 Host PCI transfer complete
entry HostPCIMasterRcvReq 0x0068 Host PCI master receive request
entry HostSlaveRcvReq 0x006A Host slave receive request
entry HostPCIMasterTrxReq 0x006C Host PCI master transmit request
entry HostSlaveTrxReq 0x006E Host slave transmit request
entry HostPCIMasterAddrReq 0x0070 Host PCI master address request
entry HostCommand 0x0072 Host command
IPRC 0xFFFFFF
IPRP 0xFFFFFE
PLLCTL 0xFFFFFD
OGDB 0xFFFFFC
BCR 0xFFFFFB
DCR 0xFFFFFA
AAR0 0xFFFFF9
AAR1 0xFFFFF8
AAR2 0xFFFFF7
AAR3 0xFFFFF6
IDR 0xFFFFF5
DSTR 0xFFFFF4
DOR0 0xFFFFF3
DOR1 0xFFFFF2
DOR2 0xFFFFF1
DOR3 0xFFFFF0
DSR0 0xFFFFEF
DDR0 0xFFFFEE
DCO0 0xFFFFED
DCR0 0xFFFFEC
DSR1 0xFFFFEB
DDR1 0xFFFFEA
DCO1 0xFFFFE9
DCR1 0xFFFFE8
DSR2 0xFFFFE7
DDR2 0xFFFFE6
DCO2 0xFFFFE5
DCR2 0xFFFFE4
DSR3 0xFFFFE3
DDR3 0xFFFFE2
DCO3 0xFFFFE1
DCR3 0xFFFFE0
DSR4 0xFFFFDF
DDR4 0xFFFFDE
DCO4 0xFFFFDD
DCR4 0xFFFFDC
DSR5 0xFFFFDB
DDR5 0xFFFFDA
DCO5 0xFFFFD9
DCR5 0xFFFFD8
DATH 0xFFFFCF
DIRH 0xFFFFCE
DTXS 0xFFFFCD
DTXM 0xFFFFCC
DRXR 0xFFFFCB
DPSR 0xFFFFCA
DSR 0xFFFFC9
DPAR 0xFFFFC8
DPMC 0xFFFFC7
DPCR 0xFFFFC6
DCTR 0xFFFFC5
PCRC 0xFFFFBF
PRRC 0xFFFFBE
PDRC 0xFFFFBD
TX00 0xFFFFBC
TX01 0xFFFFBB
TX02 0xFFFFBA
TSR0 0xFFFFB9
RX0 0xFFFFB8
SSISR0 0xFFFFB7
CRB0 0xFFFFB6
CRA0 0xFFFFB5
TSMA0 0xFFFFB4
TSMB0 0xFFFFB3
RSMA0 0xFFFFB2
RSMB0 0xFFFFB1
PCRD 0xFFFFAF
PRRD 0xFFFFAE
PDRD 0xFFFFAD
TX10 0xFFFFAC
TX11 0xFFFFAB
TX12 0xFFFFAA
TSR1 0xFFFFA9
RX1 0xFFFFA8
SSISR1 0xFFFFA7
CRB1 0xFFFFA6
CRA1 0xFFFFA5
TSMA1 0xFFFFA4
TSMB1 0xFFFFA3
RSMA1 0xFFFFA2
RSMB1 0xFFFFA1
PCRE 0xFFFF9F
PRRE 0xFFFF9E
PDRE 0xFFFF9D
SCR 0xFFFF9C
SCCR 0xFFFF9B
SRXH 0xFFFF9A
SRXM 0xFFFF99
SRXL 0xFFFF98
STXH 0xFFFF97
STXM 0xFFFF96
STXL 0xFFFF95
STXA 0xFFFF94
SSR 0xFFFF93
TCSR0 0xFFFF8F
TLR0 0xFFFF8E
TCPR0 0xFFFF8D
TCR0 0xFFFF8C
TCSR1 0xFFFF8B
TLR1 0xFFFF8A
TCPR1 0xFFFF89
TCR1 0xFFFF88
TCSR2 0xFFFF87
TLR2 0xFFFF86
TCPR2 0xFFFF85
TCR2 0xFFFF84
TPLR 0xFFFF83
TPCR 0xFFFF82
.56301
XMEMSIZE = 0x20000
YMEMSIZE = 0x20000

View File

@@ -0,0 +1,45 @@
; This file describes the standard addresses for Motorola DSP566xx
.default 56600
entry HRESET 0x0000 Hardware RESET
entry STKERR 0x0002 Stack Error
entry ILLEGAL 0x0004 Illegal Instruction
entry DEBUG 0x0006 Debug Request Interrupt
entry TRAP 0x0008 Trap
entry NMI 0x000A Non-Maskable Interrupt
entry IRQA 0x0010 IRQA
entry IRQB 0x0012 IRQB
entry IRQC 0x0014 IRQC
entry IRQD 0x0016 IRQD
entry DMA0 0x0018 DMA Channel 0
entry DMA1 0x001A DMA Channel 1
entry DMA2 0x001C DMA Channel 2
entry DMA3 0x001E DMA Channel 3
entry DMA4 0x0020 DMA Channel 4
entry DMA5 0x0022 DMA Channel 5
IPRC 0xFFFF Interrupt Priority Register-Core
IPRP 0xFFFE Interrupt Priority Register Peripheral
PCTL0 0xFFFD PLL Control Register 0
PCTL1 0xFFFC PLL Control Register 1
OGDB 0xFFFB ONCE GDB Register
BCR 0xFFFA Bus Control Register
IDR 0xFFF9 ID Register
PAR0 0xFFF8 Patch 0 Register
PAR1 0xFFF7 Patch 1 Register
PAR2 0xFFF6 Patch 2 Register
PAR3 0xFFF5 Patch 3 Register
BPMRG 0xFFF4 BPMRG (24 bits)
BPMRL 0xFFF3 BPMRL (16 bits)
BPMRH 0xFFF2 BPMRH (16 bits)
XMEMSIZE = 0x10000
YMEMSIZE = 0x10000
.56600
; no .56600 specific parameters are specified yet

View File

@@ -0,0 +1,58 @@
; This file describes the standard addresses for Motorola DSP56K
.default 56000x
entry HRESET 0x0000 Hardware RESET
entry STKERR 0x0002 Stack Error
entry TRACE 0x0004 Trace
entry SWI 0x0006 SWI
entry IRQA 0x0008 IRQA
entry IRQB 0x000A IRQB
entry SSIRD 0x000C SSI Receive Data
entry SSIRDEXP 0x000E SSI Receive Data with Exception Status
entry SSITD 0x0010 SSI Transmit Data
entry SSITDEXP 0x0012 SSI Transmit Data with Exception Status
entry SCIRD 0x0014 SCI Receive Data
entry SCIRDEXP 0x0016 SCI Receive Data with Exception Status
entry SCITD 0x0018 SCI Transmit Data
entry SCIIDLE 0x001A SCI Idle Line
entry SCITIMER 0x001C SCI Timer
entry NMI 0x001E NMI
entry HRDATA 0x0020 Host Receive Data
entry HTDATA 0x0022 Host Transmit Data
entry HCMD 0x0024 Host Command (default)
entry TIMER 0x003C Timer
entry ILLINST 0x003E Illegal Instruction
IPR 0xFFFF
BCR 0xFFFE
PLLCTL 0xFFFD
GDB 0xFFFC
SCI_HI 0xFFF6
SCI_MID 0xFFF5
SCI_LOW 0xFFF4
STXA 0xFFF3
SCCR 0xFFF2
SSR 0xFFF1
SCR 0xFFF0
SSI_RXTX 0xFFEF
SSISR 0xFFEE
CRB 0xFFED
CRA 0xFFEC
HRTX 0xFFEB
HSR 0xFFE9
HCR 0xFFE8
PCD 0xFFE5
PBD 0xFFE4
PCDDR 0xFFE3
PBDDR 0xFFE2
PCC 0xFFE1
PBC 0xFFE0
TCR 0xFFDF
TCSR 0xFFDE
.56000x
XMEMSIZE = 0x10000
YMEMSIZE = 0x10000

View File

@@ -0,0 +1,346 @@
#ifndef _DSP56K_HPP
#define _DSP56K_HPP
#include "../idaidp.hpp"
#include "ins.hpp"
#include <diskio.hpp>
#include "../iohandler.hpp"
//------------------------------------------------------------------
// DSP56K instruction may have many operands. We keep them separately
// in the following structure.
struct addargs_t
{
ea_t ea;
int nargs;
op_t args[4][2];
addargs_t() : ea(BADADDR), nargs(0) { memset(args, 0, sizeof(args)); }
};
//------------------------------------------------------------------
struct dsp56k_iohandler_t : public iohandler_t
{
struct dsp56k_t &pm;
dsp56k_iohandler_t(dsp56k_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {}
virtual const char *iocallback(const ioports_t &iop, const char *line) override;
};
DECLARE_PROC_LISTENER(idb_listener_t, struct dsp56k_t);
struct dsp56k_t : public procmod_t
{
netnode helper;
dsp56k_iohandler_t ioh = dsp56k_iohandler_t(*this, helper);
idb_listener_t idb_listener = idb_listener_t(*this);
ea_t xmem = BADADDR;
ea_t ymem = BADADDR;
op_t *op = nullptr; // current operand
addargs_t aa;
int xmemsize = 0x10000;
int ymemsize = 0x10000;
int procnum = -1; // 0 - dsp56k, 1 - dsp561xx, 2 - dsp563xx, 3 - dsp566xx
bool flow = false;
inline bool is561xx(void) const { return procnum == 1; }
inline bool is563xx(void) const { return procnum == 2; }
inline bool is566xx(void) const { return procnum == 3; }
virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override;
const ioport_t *find_port(ea_t address);
void create_xmem_ymem(void);
void select_device(const char *dname, int resp_info);
const char *set_idp_options(
const char *keyword,
int /*value_type*/,
const void * /*value*/,
bool /*idb_loaded*/);
ea_t calc_mem(const insn_t &insn, const op_t &x) const;
ea_t AdditionalSegment(asize_t size, int offset, const char *name) const;
void handle_operand(
const insn_t &insn,
const op_t &x,
flags_t F,
bool is_forced,
bool isload);
int emu(const insn_t &insn);
void header(outctx_t &ctx);
void set_cpu(int procno);
bool D_EE(insn_t &insn, int value);
bool D_DDDDD(insn_t &insn, int value);
bool D_ff(const insn_t &insn, int value, int reg_bank);
bool D_df(insn_t &insn, int value, int reg_bank);
bool S_xi(insn_t &, int value);
bool D_ximm(insn_t &insn, int /*value*/);
bool S_ximm(insn_t &insn, int value);
bool S_sssss(insn_t &, int value);
bool S_ssss(insn_t &, int value);
bool D_xih(insn_t &, int value);
bool S_xih(insn_t &insn, int value);
bool SD_d(insn_t &insn, int value);
bool SS_JJJd(insn_t &insn, int value);
bool SD_JJJd(insn_t &insn, int value);
bool SD_Jd(insn_t &insn, int value);
bool D_d(insn_t &insn, int value);
bool S_S(insn_t &insn, int value);
bool SD_JJd(insn_t &insn, int value);
bool D_dddd(insn_t &insn, int value);
bool D_ddddd(insn_t &insn, int value);
bool S_ddddd(insn_t &insn, int value);
bool D_LLL(insn_t &insn, int value);
bool D_sss(insn_t &insn, int value);
bool S_sss(insn_t &insn, int value);
bool D_qqq(insn_t &insn, int value);
bool S_qqq(insn_t &insn, int value);
bool S_qq(insn_t &insn, int value);
bool S_QQ(insn_t &insn, int value);
bool S_gggd(insn_t &insn, int value);
bool D_MMRRR(insn_t &, int value);
bool S_MMRRR(insn_t &insn, int value);
bool D_MMRRR_XY(insn_t &, int value);
bool D_pppppp(insn_t &, int value);
bool S_pppppp(insn_t &insn, int value);
bool D_qqqqqq(insn_t &, int value);
bool S_qqqqqq(insn_t &insn, int value);
bool D_qXqqqqq(insn_t &insn, int value);
bool D_DDDDDD(insn_t &insn, int value);
bool S_DDDDDD(insn_t &insn, int value);
bool D_DDDD(insn_t &insn, int value);
bool D_RRR(insn_t &insn, int value);
bool S_RRR(insn_t &insn, int value);
void make_o_mem(insn_t &insn);
bool D_mMMMRRR(insn_t &insn, int value);
bool S_mMMMRRR(insn_t &insn, int value);
bool D_aaaaaa(insn_t &insn, int value);
bool S_aaaaaa(insn_t &insn, int value);
bool D_MMMRRR(insn_t &insn, int value);
bool S_MMMRRR(insn_t &insn, int value);
bool P_type(insn_t &, int);
bool AAE(insn_t &insn, int);
bool D_PC_dispL(insn_t &insn, int value);
bool S_PC_dispL(insn_t &insn, int value);
bool D_PC_dispS(insn_t &insn, int value);
bool D_PC_RRR(insn_t &, int value);
bool D_RRR_dispL(insn_t &insn, int value);
bool D_RRR_dispS(insn_t &, int value);
bool S_RR_dispS(insn_t &, int value);
bool AA(insn_t &, int value);
bool D_F(insn_t &insn, int value);
bool S_F(insn_t &insn, int value);
bool CCCC(insn_t &insn, int value);
bool s(insn_t &insn, int value);
bool ss(insn_t &insn, int value);
bool SD_IIII(insn_t &insn, int value);
bool D_zRR(insn_t &, int value);
bool D_mRR(insn_t &, int value);
bool D_RRm(insn_t &insn, int value);
bool D_RR11m(insn_t &insn, int value);
bool D_MMRR(insn_t &, int value);
bool S_MMRR(insn_t &insn, int value);
bool D_RR0MM(insn_t &insn, int value);
bool D_qRR(insn_t &, int value);
bool D_HHH(insn_t &, int value);
bool D_HH(insn_t &, int value);
bool SD_mWRRHHH(insn_t &insn, int value);
bool S_FJJJ(insn_t &insn, int value);
bool S_QQQ(insn_t &, int value);
bool S_QQ2(insn_t &, int value);
bool S_QQQQ(insn_t &, int value);
bool S_Fh0h(insn_t &insn, int value);
bool S_uFuuu_add(insn_t &insn, int value);
bool S_uFuuu_sub(insn_t &insn, int value);
bool D_RR(insn_t &insn, int value);
bool D_NN(insn_t &insn, int value);
bool DB_RR(insn_t &, int value);
bool D_PC_RR(insn_t &, int value);
bool DX_RR(insn_t &insn, int value);
bool S_RR(insn_t &insn, int value);
bool m_A_B(insn_t &, int /*value*/);
bool IF(insn_t &, int /*value*/);
bool IFU(insn_t &, int /*value*/);
bool S_i(insn_t &insn, int value);
bool SD_TT(insn_t &insn, int value);
bool S_BBBiiiiiiii(insn_t &, int value);
bool D_Pppppp(insn_t &insn, int value);
bool D_ppppp(insn_t &insn, int value);
bool D_aaaaa(insn_t &insn, int value);
bool S_DDDDD(insn_t &insn, int value);
bool D_xi(insn_t &, int value);
bool D_xi16(insn_t &, int value);
bool D_xi_adr_16(insn_t &insn, int value);
bool D_DD(insn_t &insn, int value);
bool S_DD(insn_t &insn, int value);
bool D_Z(insn_t &, int value);
bool D_t(insn_t &insn, int value);
bool SD_F00J(insn_t &insn, int value);
bool D_PC_eeeeee(insn_t &insn, int value);
bool D_PC_aaaaaaaa(insn_t &insn, int value);
bool D_BBBBBBBB(insn_t &, int value);
bool is_valid_insn(ushort proc);
bool disassemble_parallel_move(insn_t &insn, int i, int value);
bool decode_XY_R_mem(insn_t &insn, int value);
bool recognize_parallel_move_class1(insn_t &insn, int value);
bool recognize_parallel_move_class1_3(insn_t &insn, int value);
bool recognize_parallel_move_class2(insn_t &insn, int value);
bool recognize_parallel_move_class3(insn_t &insn, int value);
bool is_parallel_move(insn_t &insn, int value);
bool use_table(
insn_t &insn,
const struct opcode_t *table,
uint32 code,
int entry,
int start,
int end);
int ana_61(insn_t &insn);
int ana_6x(insn_t &insn);
int ana(insn_t *_insn);
bool X_type(insn_t &, int);
bool Y_type(insn_t &, int);
bool mem_type(insn_t &, int value);
bool space(insn_t &insn, int);
bool sign(insn_t &, int value);
int is_sane_insn(const insn_t &insn, int /*nocrefs*/) const;
void fill_additional_args(const insn_t &insn) const;
void switch_to_additional_args(insn_t &);
inline void opreg(insn_t &, int reg);
void reset_ops(insn_t &insn);
void add_near_ref(const insn_t &insn, const op_t &x, ea_t ea);
void segstart(outctx_t &ctx, segment_t *seg) const;
void segend(outctx_t &ctx, segment_t *seg) const;
void footer(outctx_t &ctx) const;
};
//------------------------------------------------------------------
#define aux_cc 0x000F // condition code
#define aux_su 0x0003 // sign/unsing code
#define phtype specflag1 // o_phrase: phrase type
// 0 (Rn)-n
// 1 (Rn)+Nn
// 2 (Rn)-
// 3 (Rn)+
// 4 (Rn)
// 5 (Rn+Nn)
// 7 -(Rn)
// 8 $+Rn
// 9 (a1)
// 10 (b1)
#define amode specflag2 // addressing mode
#define amode_ioshort 0x01 // <<
#define amode_short 0x02 // <
#define amode_long 0x04 // >
#define amode_neg 0x08 // -
#define amode_x 0x10 // X:
#define amode_y 0x20 // Y:
#define amode_p 0x40 // P:
#define amode_l 0x80 // L:
#define imode specflag3 // IF mode
#define imode_if 0x01 // IFcc
#define imode_ifu 0x02 // IFUcc
#define o_iftype o_idpspec0 //IF type
#define o_vsltype o_idpspec1 //VSL 2-nd operand type
//------------------------------------------------------------------
#define UAS_GNU 0x0001 // GNU assembler
//------------------------------------------------------------------
enum RegNo ENUM_SIZE(uint16)
{
// data arithmetic logic unit
X, X0, X1,
Y, Y0, Y1,
// accumulator registers
A, A0, A1, A2,
B, B0, B1, B2,
AB, // a1:b1
BA, // b1:a1
A10, // a1:a0
B10, // b1:b0
// address generation unit (AGU)
R0, R1, R2, R3, R4, R5, R6, R7, // pointers
N0, N1, N2, N3, N4, N5, N6, N7, // offsets
M0, M1, M2, M3, M4, M5, M6, M7, // modifiers
// Program Control Unit
PC, // Program Counter (16 Bits)
MR, // Mode Register (8 Bits)
CCR, // Condition Code Register (8 Bits)
SR, // Status Register (MR:CCR, 16 Bits)
OMR, // Operating Mode Register (8 Bits)
LA, // Hardware Loop Address Register (16 Bits)
LC, // Hardware Loop Counter (16 Bits)
SP, // System Stack Pointer (6 Bits)
SS, // System Stack RAM (15X32 Bits)
SSH, // Upper 16 Bits of the Contents of the Current Top of Stack
SSL, // Lower 16 Bits of the Contents of the Current Top of Stack
SZ, // Stack Size register
SC, // Stack Counter register
EP, // Extension Pointer register
VBA, // Vector Base Address Register
vCS, vDS, // virtual registers for code and data segments
};
//------------------------------------------------------------------
// condition codes
enum cc_t
{
cc_CC, // carry clear (higher or same) C=0
cc_GE, // greater than or equal N xor V=0
cc_NE, // not equal Z=0
cc_PL, // plus N=0
cc_NN, // not normalized Z+(^U&^E)=0
cc_EC, // extension clear E=0
cc_LC, // limit clear L=0
cc_GT, // greater than Z+(N xor V)=0
cc_CS, // carry set (lower) C=1
cc_LT, // less than N xor V=1
cc_EQ, // equal Z=1
cc_MI, // minus N=1
cc_NR, // normalized Z+(^U&^E)=1
cc_ES, // extension set E=1
cc_LS, // limit set L=1
cc_LE, // less than or equal Z+(N xor V)=1
};
//------------------------------------------------------------------
enum PMoveClass
{
cl_0 = 0, //No Parallel move
cl_1, //X Memory Data Move (common)
cl_1_3, //X Memory Data Move with short displacement
cl_2, //Dual X Memory Data Read
cl_3, //X Memory Data Write and Register Data Move
};
//------------------------------------------------------------------
// signed/unsigned codes
enum su_t
{
s_SS, // signed * signed
s_SU, // signed * unsigned
s_UU, // unsigned * unsigned
};
// Make sure that the 'aa' structure is up to date.
void fill_additional_args(const insn_t &insn);
//------------------------------------------------------------------
void interr(const insn_t *insn, const char *module);
int idaapi ana(insn_t *insn);
int idaapi emu(const insn_t &insn);
int idaapi is_align_insn(ea_t ea);
int idaapi is_sp_based(const insn_t &insn, const op_t &x);
#endif // _DSP56K_HPP

View File

@@ -0,0 +1,222 @@
#include "dsp56k.hpp"
#include <frame.hpp>
//----------------------------------------------------------------------
ea_t dsp56k_t::calc_mem(const insn_t &insn, const op_t &x) const
{
if ( x.amode & (amode_x|amode_l) )
return xmem == BADADDR ? BADADDR : xmem+x.addr;
if ( x.amode & amode_y )
return ymem == BADADDR ? BADADDR : ymem+x.addr;
return to_ea(insn.cs, x.addr);
}
//------------------------------------------------------------------------
inline bool is_stkreg(int r)
{
return r == SP;
}
//------------------------------------------------------------------------
int idaapi is_sp_based(const insn_t &, const op_t &x)
{
return OP_SP_ADD | (x.phrase == SP ? OP_SP_BASED : OP_FP_BASED);
}
//------------------------------------------------------------------------
static void process_immediate_number(const insn_t &insn, int n, flags_t F)
{
set_immd(insn.ea);
if ( is_defarg(F, n) )
return;
switch ( insn.itype )
{
// case DSP56_asl:
// case DSP56_asr:
case DSP56_bchg:
case DSP56_bclr:
case DSP56_brclr:
case DSP56_brset:
case DSP56_bsclr:
case DSP56_bset:
case DSP56_bsset:
case DSP56_btst:
case DSP56_jclr:
case DSP56_jset:
case DSP56_jsclr:
case DSP56_jsset:
// case DSP56_lsl:
// case DSP56_lsr:
op_dec(insn.ea, n);
break;
case DSP56_add:
case DSP56_and:
case DSP56_andi:
case DSP56_cmp:
case DSP56_eor:
case DSP56_extract:
case DSP56_extractu:
case DSP56_insert:
case DSP56_mac:
case DSP56_maci:
case DSP56_macr:
case DSP56_macri:
case DSP56_mpy:
case DSP56_mpyi:
case DSP56_mpyr:
case DSP56_mpyri:
case DSP56_or:
case DSP56_ori:
case DSP56_sub:
case DSP56_do:
case DSP56_dor:
case DSP56_rep:
op_num(insn.ea, n);
break;
}
}
//----------------------------------------------------------------------
void dsp56k_t::add_near_ref(const insn_t &insn, const op_t &x, ea_t ea)
{
cref_t ftype = fl_JN;
if ( has_insn_feature(insn.itype, CF_CALL) )
{
if ( !func_does_return(ea) )
flow = false;
ftype = fl_CN;
}
insn.add_cref(ea, x.offb, ftype);
}
//----------------------------------------------------------------------
void dsp56k_t::handle_operand(
const insn_t &insn,
const op_t &x,
flags_t F,
bool is_forced,
bool isload)
{
switch ( x.type )
{
case o_reg:
break;
default:
break;
case o_imm:
process_immediate_number(insn, x.n, F);
if ( op_adds_xrefs(F, x.n) )
insn.add_off_drefs(x, dr_O, OOFS_IFSIGN);
break;
case o_phrase:
if ( !is_forced && op_adds_xrefs(F, x.n) )
{
ea_t ea = insn.add_off_drefs(x, isload ? dr_R : dr_W, OOF_ADDR);
if ( ea != BADADDR )
insn.create_op_data(ea, x);
}
break;
case o_mem:
{
ea_t ea = calc_mem(insn, x);
insn.add_dref(ea, x.offb, isload ? dr_R : dr_W);
insn.create_op_data(ea, x);
if ( x.amode & amode_l )
{
ea = ymem + x.addr;
insn.add_dref(ea, x.offb, isload ? dr_R : dr_W);
insn.create_op_data(ea, x);
}
}
break;
case o_near:
add_near_ref(insn, x, calc_mem(insn, x));
break;
}
}
//----------------------------------------------------------------------
int dsp56k_t::emu(const insn_t &insn)
{
if ( segtype(insn.ea) == SEG_XTRN )
return 1;
uint32 Feature = insn.get_canon_feature(ph);
bool flag1 = is_forced_operand(insn.ea, 0);
bool flag2 = is_forced_operand(insn.ea, 1);
bool flag3 = is_forced_operand(insn.ea, 2);
flow = ((Feature & CF_STOP) == 0);
flags_t F = get_flags(insn.ea);
if ( Feature & CF_USE1 ) handle_operand(insn, insn.Op1, F, flag1, true);
if ( Feature & CF_USE2 ) handle_operand(insn, insn.Op2, F, flag2, true);
if ( Feature & CF_USE3 ) handle_operand(insn, insn.Op3, F, flag3, true);
if ( Feature & CF_CHG1 ) handle_operand(insn, insn.Op1, F, flag1, false);
if ( Feature & CF_CHG2 ) handle_operand(insn, insn.Op2, F, flag2, false);
if ( Feature & CF_CHG3 ) handle_operand(insn, insn.Op3, F, flag3, false);
insn_t copy = insn;
fill_additional_args(copy);
for ( int i=0; i < aa.nargs; i++ )
{
op_t *x = aa.args[i];
for ( int j=0; j < 2; j++,x++ )
{
if ( x->type == o_void )
break;
handle_operand(insn, *x, F, 0, j == 0);
}
}
//
// Determine if the next instruction should be executed
//
if ( Feature & CF_STOP )
flow = false;
if ( flow )
add_cref(insn.ea, insn.ea+insn.size, fl_F);
return 1;
}
//----------------------------------------------------------------------
int dsp56k_t::is_sane_insn(const insn_t &insn, int /*nocrefs*/) const
{
// disallow jumps to nowhere
if ( insn.Op1.type == o_near && !is_mapped(calc_mem(insn, insn.Op1)) )
return 0;
// disallow many nops in a now
int i = 0;
for ( ea_t ea=insn.ea; i < 32; i++,ea++ )
if ( get_byte(ea) != 0 )
break;
if ( i == 32 )
return 0;
return 1;
}
//----------------------------------------------------------------------
int idaapi is_align_insn(ea_t ea)
{
insn_t insn;
if ( decode_insn(&insn, ea) < 1 )
return 0;
switch ( insn.itype )
{
case DSP56_nop:
break;
default:
return 0;
}
return insn.size;
}

View File

@@ -0,0 +1,144 @@
#include "dsp56k.hpp"
const instruc_t Instructions[] =
{
{ "", 0 }, // Unknown Operation
{ "abs", CF_USE1|CF_CHG1 }, // Absolute Value
{ "adc", CF_USE1|CF_USE2|CF_CHG2 }, // Add Long with Carry
{ "add", CF_USE1|CF_USE2|CF_CHG2 }, // Addition
{ "addl", CF_USE1|CF_USE2|CF_CHG2 }, // Shift Left and Add
{ "addr", CF_USE1|CF_USE2|CF_CHG2 }, // Shift Right and Add
{ "and", CF_USE1|CF_USE2|CF_CHG2 }, // Logical AND
{ "andi", CF_USE1|CF_USE2|CF_CHG2 }, // AND Immediate to Control Register
{ "asl", CF_USE1|CF_CHG1 }, // Arithmetic Shift Left
{ "asl4", CF_USE1|CF_CHG1 }, // Arithmetic Shift Left
{ "asr", CF_USE1|CF_CHG1 }, // Arithmetic Shift Right
{ "asr4", CF_USE1|CF_CHG1 }, // Arithmetic Shift Right
{ "asr16", CF_USE1|CF_CHG1 }, // Arithmetic Shift Right
{ "bfchg", CF_USE1|CF_USE2|CF_CHG2 }, // Bit Test and Change
{ "bfclr", CF_USE1|CF_USE2|CF_CHG2 }, // Bit Test and Clear
{ "bfset", CF_USE1|CF_USE2|CF_CHG2 }, // Bit Test and Set
{ "bftsth", CF_USE1|CF_USE2|CF_CHG2 }, // Test Bit Field High
{ "bftstl", CF_USE1|CF_USE2|CF_CHG2 }, // Test Bit Field Low
{ "b", CF_USE1|CF_JUMP }, // Branch Conditionally
{ "bchg", CF_USE1|CF_USE2|CF_CHG2 }, // Bit Test and Change
{ "bclr", CF_USE1|CF_USE2|CF_CHG2 }, // Bit Test and Clear
{ "bra", CF_USE1|CF_STOP|CF_JUMP }, // Branch Always
{ "brclr", CF_USE1|CF_USE2|CF_USE3|CF_JUMP }, // Branch if Bit Clear
{ "brk", CF_USE1 }, // Exit Current DO Loop Conditionally
{ "brset", CF_USE1|CF_USE2|CF_USE3|CF_JUMP }, // Branch if Bit Set
{ "bs", CF_USE1|CF_CALL }, // Branch to Subroutine Conditionally
{ "bsclr", CF_USE1|CF_USE2|CF_USE3|CF_CALL }, // Branch to Subroutine if Bit Clear
{ "bset", CF_USE1|CF_USE2|CF_CHG2 }, // Bit Test and Set
{ "bsr", CF_USE1|CF_CALL }, // Branch to Subroutine
{ "bsset", CF_USE1|CF_USE2|CF_USE3|CF_CALL }, // Branch to Subroutine if Bit Set
{ "btst", CF_USE1|CF_USE2|CF_CHG2 }, // Bit Test on Memory and Registers
{ "chkaau", 0 }, // Check address ALU result
{ "clb", CF_USE1|CF_CHG2 }, // Count Leading Bits
{ "clr", CF_USE1|CF_CHG1 }, // Clear an Operand
{ "clr24", CF_USE1|CF_CHG1 }, // Clear 24 MS-bits of Accumulator
{ "cmp", CF_USE1|CF_USE2 }, // Compare
{ "cmpm", CF_USE1|CF_USE2 }, // Compare Magnitude
{ "cmpu", CF_USE1|CF_USE2 }, // Compare Unsigned
{ "debug", 0 }, // Enter Debug Mode
{ "debug", 0 }, // Enter Debug Mode Conditionally
{ "dec", CF_USE1|CF_CHG1 }, // Decrement by One
{ "dec24", CF_USE1|CF_CHG1 }, // Decrement 24 MS-bit of Accumulator
{ "div", CF_USE1|CF_USE2|CF_CHG2 }, // Divide Iteration
{ "dmac", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, // Double-Precision Multiply-Accumulate With Right Shift
{ "do", CF_USE1|CF_USE2|CF_JUMP }, // Start Hardware Loop
{ "do forever,", CF_USE1|CF_JUMP }, // Start Infinite Loop
{ "dor", CF_USE1|CF_USE2|CF_JUMP }, // Start PC-Relative Hardware Loop
{ "dor forever,", CF_USE1|CF_JUMP }, // Start PC-Relative Infinite Loop
{ "enddo", 0 }, // Exit from Hardware Loop
{ "eor", CF_USE1|CF_USE2|CF_CHG2 }, // Logical Exclusive OR
{ "extract", CF_USE1|CF_USE2|CF_CHG3 }, // Extract Bit Field
{ "extractu", CF_USE1|CF_USE2|CF_CHG3 }, // Extract Unsigned Bit Field
{ "ext", CF_USE1|CF_CHG1 }, // Sign Extend Accumulator
{ "illegal", 0 }, // Illegal Instruction
{ "imac", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, // Integer Multiply-Accumulate
{ "impy", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, // Integer Multiply
{ "inc", CF_USE1|CF_CHG1 }, // Increment by One
{ "inc24", CF_USE1|CF_CHG1 }, // Increment 24 MS-bit of Accumulator
{ "insert", CF_USE1|CF_USE2|CF_CHG3 }, // Insert Bit Field
{ "j", CF_USE1|CF_JUMP }, // Jump Conditionally
{ "jclr", CF_USE1|CF_USE2|CF_USE3|CF_JUMP }, // Jump if Bit Clear
{ "jmp", CF_USE1|CF_STOP|CF_JUMP }, // Jump
{ "js", CF_USE1|CF_CALL }, // Jump to Subroutine Conditionally
{ "jsclr", CF_USE1|CF_USE2|CF_USE3|CF_CALL }, // Jump to Subroutine if Bit Clear
{ "jset", CF_USE1|CF_USE2|CF_USE3|CF_JUMP }, // Jump if Bit Set
{ "jsr", CF_USE1|CF_CALL }, // Jump to Subroutine
{ "jsset", CF_USE1|CF_USE2|CF_USE3|CF_CALL }, // Jump to Subroutine if Bit Set
{ "lra", CF_USE1|CF_CHG2 }, // Load PC-Reliative Address
{ "lsl", CF_USE1|CF_CHG1 }, // Logical Shift Left
{ "lsr", CF_USE1|CF_CHG1 }, // Logical Shift Right
{ "lua", CF_USE1|CF_CHG2 }, // Load Updated Address
{ "lea", CF_USE1|CF_CHG2 }, // Load Updated Address
{ "mac", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, // Signed Multiply-Accumulate
{ "maci", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, // Signed Multiply-Accumulate With Immediate Operand
{ "mac", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, // Mixed Multiply-Accumulate
{ "macr", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, // Signed Multiply-Accumulate and Round
{ "macri", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, // Signed Multiply-Accumulate and Round With Immediate Operand
{ "max", CF_USE1|CF_USE2|CF_CHG2 }, // Transfer by Signed Value
{ "maxm", CF_USE1|CF_USE2|CF_CHG2 }, // Transfer by Magnitude
{ "merge", CF_USE1|CF_USE2|CF_CHG2 }, // Merge Two Half Words
{ "move", CF_USE1|CF_CHG2 }, // Move Data Register
{ "movec", CF_USE1|CF_CHG2 }, // Move Control Register
{ "movei", CF_USE1|CF_CHG2 }, // Move Immediate Short
{ "movem", CF_USE1|CF_CHG2 }, // Move Program Memory
{ "movep", CF_USE1|CF_CHG2 }, // Move Peripheral Data
{ "moves", CF_USE1|CF_CHG2 }, // Move Absolute Short
{ "mpy", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, // Signed Multiply
{ "mpyi", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, // Signed Multiply With Immediate Operand
{ "mpy", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, // Mixed Multiply
{ "mpyr", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, // Signed Multiply and Round
{ "mpyri", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, // Signed Multiply and Round With Immediate Operand
{ "neg", CF_USE1|CF_CHG1 }, // Negate Accumulator
{ "negc", CF_USE1|CF_CHG1 }, // Negate Accumulator
{ "nop", 0 }, // No Operation
{ "norm", CF_USE1|CF_USE2|CF_CHG2 }, // Norm Accumulator Iteration
{ "normf", CF_USE1|CF_USE2|CF_CHG2 }, // Fast Accumulator Normalization
{ "not", CF_USE1|CF_CHG1 }, // Logical Complement
{ "or", CF_USE1|CF_USE2|CF_CHG2 }, // Logical Inclusive OR
{ "ori", CF_USE1|CF_USE2|CF_CHG2 }, // OR Immediate to Control Register
{ "pflush", 0 }, // Program Cache Flush
{ "pflushun", 0 }, // Program Cache Flush Unlocked Sectors
{ "pfree", 0 }, // Program Cache Global Unlock
{ "plock", 0 }, // Lock Instruction Cache Sector
{ "plockr", 0 }, // Lock Instruction Cache Relative Sector
{ "punlock", 0 }, // Unlock Instruction Cache Sector
{ "punlockr", 0 }, // Unlock Instruction Cache Relative Sector
{ "rep", CF_USE1 }, // Repeat Next Instruction
{ "rep", CF_USE1 }, // Repeat Next Instruction
{ "reset", 0 }, // Reset On-Chip Peripheral Devices
{ "rnd", CF_USE1|CF_CHG1 }, // Round
{ "rol", CF_USE1|CF_CHG1 }, // Rotate Left
{ "ror", CF_USE1|CF_CHG1 }, // Rotate Right
{ "rti", CF_STOP }, // Return from Interrupt
{ "rts", CF_STOP }, // Return from Subroutine
{ "sbc", CF_USE1|CF_USE2|CF_CHG2 }, // Subtract Long with Carry
{ "stop", CF_STOP }, // Stop Processing (Low-Power Standby)
{ "sub", CF_USE1|CF_USE2|CF_CHG2 }, // Subtract
{ "subl", CF_USE1|CF_USE2|CF_CHG2 }, // Shift Left and Subtract
{ "subr", CF_USE1|CF_USE2|CF_CHG2 }, // Shift Right and Subtract
{ "swap", CF_USE1|CF_CHG1 }, // Swap Accumulator Words
{ "t", CF_USE1|CF_USE2 }, // Transfer Conditionally
{ "tfr", CF_USE1|CF_USE2 }, // Transfer Data ALU Register
{ "tfr2", CF_USE1|CF_USE2|CF_CHG2 }, // Transfer Data ALU Register
{ "tfr3", CF_USE1|CF_USE2|CF_CHG2 }, // Transfer Data ALU Register
{ "trap", 0 }, // Software Interrupt
{ "trap", 0 }, // Software Interrupt Conditionally
{ "tst", CF_USE1 }, // Test an Operand
{ "tst2", CF_USE1 }, // Test an Operand
{ "vsl", CF_USE1|CF_USE2|CF_CHG3 }, // Viterbi Shift Left
{ "wait", 0 }, // Wait for Interrupt or DMA Request (Low-Power Standby)
{ "zero", 0 }, // Zero Extend Accumulator
{ "swi", 0 }, // Software Interrupt
{ "pmov", 0 }, // Pseudo insn
};
CASSERT(qnumber(Instructions) == DSP56_last);

View File

@@ -0,0 +1,147 @@
#ifndef __INSTRS_HPP
#define __INSTRS_HPP
extern const instruc_t Instructions[];
enum nameNum
{
DSP56_null = 0, // Unknown Operation
DSP56_abs, // Absolute Value
DSP56_adc, // Add Long with Carry
DSP56_add, // Addition
DSP56_addl, // Shift Left and Add
DSP56_addr, // Shift Right and Add
DSP56_and, // Logical AND
DSP56_andi, // AND Immediate to Control Register
DSP56_asl, // Arithmetic Shift Left
DSP56_asl4, // Arithmetic Shift Left 4
DSP56_asr, // Arithmetic Shift Right
DSP56_asr4, // Arithmetic Shift Right 4
DSP56_asr16, // Arithmetic Shift Right 16
DSP56_bfchg, // Test Bit Field and Change
DSP56_bfclr, // Clear Bit Field
DSP56_bfset, // Set Bit Field
DSP56_bftsth, // Test Bit Field High
DSP56_bftstl, // Test Bit Field Low
DSP56_bcc, // Branch Conditionaly
DSP56_bchg, // Bit Test and Change
DSP56_bclr, // Bit Test and Clear
DSP56_bra, // Branch Always
DSP56_brclr, // Branch if Bit Clear
DSP56_brkcc, // Exit Current DO Loop Conditionally
DSP56_brset, // Branch if Bit Set
DSP56_bscc, // Branch to Subroutine Conditionaly
DSP56_bsclr, // Branch to Subroutine if Bit Clear
DSP56_bset, // Bit Test and Set
DSP56_bsr, // Branch to Subroutine
DSP56_bsset, // Branch to Subroutine if Bit Set
DSP56_btst, // Bit Test on Memory and Registers
DSP56_chkaau, // Check address ALU result
DSP56_clb, // Count Leading Bits
DSP56_clr, // Clear an Operand
DSP56_clr24, // Clear 24 MS-bits of Accumulator
DSP56_cmp, // Compare
DSP56_cmpm, // Compare Magnitude
DSP56_cmpu, // Compare Unsigned
DSP56_debug, // Enter Debug Mode
DSP56_debugcc, // Enter Debug Mode Conditionally
DSP56_dec, // Decrement by One
DSP56_dec24, // Decrement 24 MS-bit of Accumulator
DSP56_div, // Divide Iteration
DSP56_dmac, // Double-Precision Multiply-Accumulate With Right Shift
DSP56_do, // Start Hardware Loop
DSP56_do_f, // Start Infinite Loop
DSP56_dor, // Start PC-Relative Hardware Loop
DSP56_dor_f, // Start PC-Relative Infinite Loop
DSP56_enddo, // Exit from Hardware Loop
DSP56_eor, // Logical Exclusive OR
DSP56_extract, // Extract Bit Field
DSP56_extractu, // Extract Unsigned Bit Field
DSP56_ext, // Sign Extend Accumulator
DSP56_ill, // Illegal Instruction
DSP56_imac, // Integer Multiply-Accumulate
DSP56_impy, // Integer Multiply
DSP56_inc, // Increment by One
DSP56_inc24, // Increment 24 MS-bit of Accumulator
DSP56_insert, // Insert Bit Field
DSP56_jcc, // Jump Conditionally
DSP56_jclr, // Jump if Bit Clear
DSP56_jmp, // Jump
DSP56_jscc, // Jump to Subroutine Conditionally
DSP56_jsclr, // Jump to Subroutine if Bit Clear
DSP56_jset, // Jump if Bit Set
DSP56_jsr, // Jump to Subroutine
DSP56_jsset, // Jump to Subroutine if Bit Set
DSP56_lra, // Load PC-Reliative Address
DSP56_lsl, // Logical Shift Left
DSP56_lsr, // Logical Shift Right
DSP56_lua, // Load Updated Address
DSP56_lea, // Load Updated Address
DSP56_mac, // Signed Multiply-Accumulate
DSP56_maci, // Signed Multiply-Accumulate With Immediate Operand
DSP56_mac_s_u, // Mixed Multiply-Accumulate
DSP56_macr, // Signed Multiply-Accumulate and Round
DSP56_macri, // Signed Multiply-Accumulate and Round With Immediate Operand
DSP56_max, // Transfer by Signed Value
DSP56_maxm, // Transfer by Magnitude
DSP56_merge, // Merge Two Half Words
DSP56_move, // Move Data
DSP56_movec, // Move Control Register
DSP56_movei, // Move Immediate Short
DSP56_movem, // Move Program Memory
DSP56_movep, // Move Peripheral Data
DSP56_moves, // Move Absolute Short
DSP56_mpy, // Signed Multiply
DSP56_mpyi, // Signed Multiply With Immediate Operand
DSP56_mpy_s_u, // Mixed Multiply
DSP56_mpyr, // Signed Multiply and Round
DSP56_mpyri, // Signed Multiply and Round With Immediate Operand
DSP56_neg, // Negate Accumulator
DSP56_negc, // Negate Accumulator
DSP56_nop, // No Operation
DSP56_norm, // Norm Accumulator Iteration
DSP56_normf, // Fast Accumulator Normalization
DSP56_not, // Logical Complement
DSP56_or, // Logical Inclusive OR
DSP56_ori, // OR Immediate to Control Register
DSP56_pflush, // Program Cache Flush
DSP56_pflushun, // Program Cache Flush Unlocked Sectors
DSP56_pfree, // Program Cache Global Unlock
DSP56_plock, // Lock Instruction Cache Sector
DSP56_plockr, // Lock Instruction Cache Relative Sector
DSP56_punlock, // Unlock Instruction Cache Sector
DSP56_punlockr, // Unlock Instruction Cache Relative Sector
DSP56_rep, // Repeat Next Instruction
DSP56_repcc, // Repeat Next Instruction
DSP56_reset, // Reset On-Chip Peripheral Devices
DSP56_rnd, // Round Accumulator
DSP56_rol, // Rotate Left
DSP56_ror, // Rotate Right
DSP56_rti, // Return from Interrupt
DSP56_rts, // Return from Subroutine
DSP56_sbc, // Subtract Long with Carry
DSP56_stop, // Stop Processing (Low-Power Standby)
DSP56_sub, // Subtract
DSP56_subl, // Shift Left and Subtract
DSP56_subr, // Shift Right and Subtract
DSP56_swap, // Swap Accumulator Words
DSP56_tcc, // Transfer Conditionally
DSP56_tfr, // Transfer Data ALU Register
DSP56_tfr2, // Transfer Data ALU Register
DSP56_tfr3, // Transfer Data ALU Register
DSP56_trap, // Software Interrupt
DSP56_trapcc, // Software Interrupt Conditionally
DSP56_tst, // Test an Operand
DSP56_tst2, // Test an Operand
DSP56_vsl, // Viterbi Shift Left
DSP56_wait, // Wait for Interrupt or DMA Request (Low-Power Standby)
DSP56_zero, // Zero Extend Accumulator
DSP56_swi, // Software Interrupt (only for 56000)
DSP56_pmov, // Pseudo insn
DSP56_last,
};
#endif

View File

@@ -0,0 +1,46 @@
PROC=dsp56k
CONFIGS=dsp56k.cfg dsp563xx.cfg dsp566xx.cfg dsp561xx.cfg
include ../module.mak
# MAKEDEP dependency list ------------------
$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \
$(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \
$(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \
ana.cpp dsp56k.hpp ins.hpp
$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \
$(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \
$(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \
$(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \
$(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \
$(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
../iohandler.hpp dsp56k.hpp emu.cpp ins.hpp
$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \
$(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \
$(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \
dsp56k.hpp ins.cpp ins.hpp
$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \
$(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \
$(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \
dsp56k.hpp ins.hpp out.cpp
$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \
$(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \
$(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \
dsp56k.hpp ins.hpp reg.cpp

View File

@@ -0,0 +1,397 @@
#include "dsp56k.hpp"
// simple wrapper class for syntactic sugar of member functions
// this class may have only simple member functions.
// virtual functions and data fields are forbidden, otherwise the class
// layout may change
class out_dsp56k_t : public outctx_t
{
out_dsp56k_t(void) = delete; // not used
public:
bool out_operand(const op_t &x);
void out_insn(void);
void out_proc_mnem(void);
void outreg(int r) { out_register(ph.reg_names[r]); }
bool out_port_address(ea_t addr);
void out_bad_address(ea_t addr);
void out_ip_rel(int displ);
void out_operand_group(int idx, const op_t *x);
};
CASSERT(sizeof(out_dsp56k_t) == sizeof(outctx_t));
DECLARE_OUT_FUNCS(out_dsp56k_t)
//--------------------------------------------------------------------------
static const char *const cc_text[] =
{
"cc", // carry clear (higher or same) C=0
"ge", // greater than or equal N & V=0
"ne", // not equal Z=0
"pl", // plus N=0
"nn", // not normalized Z+(U.E)=0
"ec", // extension clear E=0
"lc", // limit clear L=0
"gt", // greater than Z+(N & V)=0
"cs", // carry set (lower) C=1
"lt", // less than N & V=1
"eq", // equal Z=1
"mi", // minus N=1
"nr", // normalized Z+(U.E)=1
"es", // extension set E=1
"ls", // limit set L=1
"le", // less than or equal Z+(N & V)=1
};
//--------------------------------------------------------------------------
static const char *const su_text[] =
{
"ss", // signed * signed
"su", // signed * unsigned
"uu", // unsigned * unsigned
};
static const char *const formats[] =
{
COLSTR("(", SCOLOR_SYMBOL) COLSTR("r%d", SCOLOR_REG) COLSTR(")-", SCOLOR_SYMBOL) COLSTR("n%d", SCOLOR_REG),
COLSTR("(", SCOLOR_SYMBOL) COLSTR("r%d", SCOLOR_REG) COLSTR(")+", SCOLOR_SYMBOL) COLSTR("n%d", SCOLOR_REG),
COLSTR("(", SCOLOR_SYMBOL) COLSTR("r%d", SCOLOR_REG) COLSTR(")-", SCOLOR_SYMBOL),
COLSTR("(", SCOLOR_SYMBOL) COLSTR("r%d", SCOLOR_REG) COLSTR(")+", SCOLOR_SYMBOL),
COLSTR("(", SCOLOR_SYMBOL) COLSTR("r%d", SCOLOR_REG) COLSTR(")", SCOLOR_SYMBOL),
COLSTR("(", SCOLOR_SYMBOL) COLSTR("r%d", SCOLOR_REG) COLSTR("+", SCOLOR_SYMBOL) COLSTR("n%d", SCOLOR_REG) COLSTR(")", SCOLOR_SYMBOL),
"internal error with o_phrase",
COLSTR("-(", SCOLOR_SYMBOL) COLSTR("r%d", SCOLOR_REG) COLSTR(")", SCOLOR_SYMBOL),
COLSTR("$+", SCOLOR_SYMBOL) COLSTR("r%d", SCOLOR_REG),
COLSTR("(", SCOLOR_SYMBOL) COLSTR("a1", SCOLOR_REG) COLSTR(")", SCOLOR_SYMBOL),
COLSTR("(", SCOLOR_SYMBOL) COLSTR("b1", SCOLOR_REG) COLSTR(")", SCOLOR_SYMBOL),
};
// 0 (Rn)-Nn
// 1 (Rn)+Nn
// 2 (Rn)-
// 3 (Rn)+
// 4 (Rn)
// 5 (Rn+Nn)
// 7 -(Rn)
// 8 $+Rn
// 9 (a1)
// 10 (b1)
static const char *const formats2[] =
{
COLSTR("(", SCOLOR_SYMBOL) COLSTR("r%d", SCOLOR_REG) COLSTR("+", SCOLOR_SYMBOL) COLSTR("$%X", SCOLOR_NUMBER) COLSTR(")", SCOLOR_SYMBOL),
COLSTR("(", SCOLOR_SYMBOL) COLSTR("r%d", SCOLOR_REG) COLSTR("-", SCOLOR_SYMBOL) COLSTR("$%X", SCOLOR_NUMBER) COLSTR(")", SCOLOR_SYMBOL),
};
//----------------------------------------------------------------------
bool out_dsp56k_t::out_port_address(ea_t addr)
{
dsp56k_t &pm = *static_cast<dsp56k_t *>(procmod);
const ioport_t *port = pm.find_port(addr);
if ( port != NULL && !port->name.empty() )
{
out_line(port->name.c_str(), COLOR_IMPNAME);
return true;
}
return false;
}
//----------------------------------------------------------------------
void out_dsp56k_t::out_bad_address(ea_t addr)
{
if ( !out_port_address(addr) )
{
out_tagon(COLOR_ERROR);
out_btoa(addr, 16);
out_tagoff(COLOR_ERROR);
remember_problem(PR_NONAME, insn.ea);
}
}
//----------------------------------------------------------------------
void out_dsp56k_t::out_ip_rel(int displ)
{
out_printf(COLSTR("%s+", SCOLOR_SYMBOL) COLSTR("%d", SCOLOR_NUMBER),
ash.a_curip, displ);
}
//----------------------------------------------------------------------
bool out_dsp56k_t::out_operand(const op_t &x)
{
dsp56k_t &pm = *static_cast<dsp56k_t *>(procmod);
if ( x.type == o_imm )
{
out_symbol('#');
}
else
{
if ( x.amode & amode_x )
{
out_register("x");
out_symbol(':');
}
if ( x.amode & amode_y )
{
out_register("y");
out_symbol(':');
}
if ( x.amode & amode_p )
{
out_register("p");
out_symbol(':');
}
if ( x.amode & amode_l )
{
out_register("l");
out_symbol(':');
}
}
if ( x.amode & amode_ioshort )
{
out_symbol('<');
out_symbol('<');
}
if ( x.amode & amode_short )
out_symbol('<');
if ( x.amode & amode_long )
out_symbol('>');
if ( x.amode & amode_neg )
out_symbol('-');
switch ( x.type )
{
case o_void:
return 0;
case o_imm:
out_value(x, OOFS_IFSIGN|OOFW_IMM);
break;
case o_reg:
outreg(x.reg);
break;
case o_mem:
// no break;
case o_near:
{
ea_t ea = pm.calc_mem(insn, x);
// xmem ioports
if ( x.amode & (amode_x|amode_l) && out_port_address(x.addr) )
{
const ioport_t *port = pm.find_port(x.addr);
if ( port != NULL && !has_user_name(get_flags(ea)) )
set_name(ea, port->name.c_str(), SN_NODUMMY);
break;
}
if ( ea == insn.ea+insn.size )
out_ip_rel(insn.size);
else if ( !out_name_expr(x, ea, x.addr) )
out_bad_address(x.addr);
}
break;
case o_phrase:
{
char buf[MAXSTR];
nowarn_qsnprintf(buf, sizeof(buf), formats[uchar(x.phtype)], x.phrase, x.phrase);
out_colored_register_line(buf);
}
break;
case o_displ:
{
char buf[MAXSTR];
nowarn_qsnprintf(buf, sizeof(buf), formats2[uchar(x.phtype)], x.phrase, x.addr);
out_colored_register_line(buf);
}
break;
case o_iftype:
{
char postfix[4];
qstrncpy(postfix, cc_text[insn.auxpref & aux_cc], sizeof(postfix));
if ( x.imode == imode_if )
out_printf(COLSTR("IF%s", SCOLOR_SYMBOL), postfix);
else
out_printf(COLSTR("IF%s.U", SCOLOR_SYMBOL), postfix);
}
break;
case o_vsltype:
out_symbol((insn.auxpref & 1) + '0');
break;
default:
interr(&insn, "out");
break;
}
return 1;
}
//----------------------------------------------------------------------
void out_dsp56k_t::out_operand_group(int idx, const op_t *x)
{
for ( int i=0; i < 2; i++,x++ )
{
if ( x->type == o_void )
break;
if ( i != 0 )
{
out_symbol(',');
}
else if ( insn.itype != DSP56_move || idx != 0 )
{
size_t n = 16;
if ( idx == (insn.itype == DSP56_move) )
n = tag_strlen(outbuf.c_str());
do
out_char(' ');
while ( ++n < 20 );
}
out_operand(*x);
}
}
//----------------------------------------------------------------------
void out_dsp56k_t::out_proc_mnem(void)
{
// output instruction mnemonics
char postfix[4];
postfix[0] = '\0';
switch ( insn.itype )
{
case DSP56_tcc:
case DSP56_debugcc:
case DSP56_jcc:
case DSP56_jscc:
case DSP56_bcc:
case DSP56_bscc:
case DSP56_trapcc:
qstrncpy(postfix, cc_text[insn.auxpref & aux_cc], sizeof(postfix));
break;
case DSP56_dmac:
case DSP56_mac_s_u:
case DSP56_mpy_s_u:
qstrncpy(postfix, su_text[insn.auxpref & aux_su], sizeof(postfix));
break;
}
out_mnem(8, postfix);
}
//----------------------------------------------------------------------
void out_dsp56k_t::out_insn(void)
{
dsp56k_t &pm = *static_cast<dsp56k_t *>(procmod);
out_mnemonic();
bool comma = out_one_operand(0);
if ( insn.Op2.type != o_void )
{
if ( comma )
out_symbol(',');
out_one_operand(1);
}
if ( insn.Op3.type != o_void )
{
out_symbol(',');
out_one_operand(2);
}
pm.fill_additional_args(insn);
for ( int i=0; i < pm.aa.nargs; i++ )
out_operand_group(i, pm.aa.args[i]);
out_immchar_cmts();
flush_outbuf();
}
//--------------------------------------------------------------------------
//lint -e{818} seg could be made const
void dsp56k_t::segstart(outctx_t &ctx, segment_t *seg) const
{
if ( is_spec_segm(seg->type) )
return;
qstring sname;
qstring sclas;
get_segm_name(&sname, seg);
get_segm_class(&sclas, seg);
if ( ash.uflag & UAS_GNU )
{
const char *predefined[] =
{
".text", // Text section
".data", // Data sections
".rdata",
".comm",
};
if ( !print_predefined_segname(ctx, &sname, predefined, qnumber(predefined)) )
ctx.gen_printf(DEFAULT_INDENT,
COLSTR(".section %s", SCOLOR_ASMDIR) " " COLSTR("%s %s", SCOLOR_AUTOCMT),
sname.c_str(),
ash.cmnt,
sclas.c_str());
}
else
{
validate_name(&sname, VNT_IDENT);
if ( sname == "XMEM" || sname == "YMEM" )
{
char buf[MAX_NUMBUF];
btoa(buf, sizeof(buf), seg->start_ea-get_segm_base(seg));
ctx.gen_printf(DEFAULT_INDENT,
COLSTR("%s %c:%s", SCOLOR_ASMDIR),
ash.origin,
qtolower(sname[0]),
buf);
}
else
{
ctx.gen_printf(DEFAULT_INDENT,
COLSTR("section %s", SCOLOR_ASMDIR) " " COLSTR("%s %s", SCOLOR_AUTOCMT),
sname.c_str(),
ash.cmnt,
sclas.c_str());
}
}
}
//--------------------------------------------------------------------------
//lint -e{818} seg could be made const
void dsp56k_t::segend(outctx_t &ctx, segment_t *seg) const
{
if ( is_spec_segm(seg->type) )
return;
if ( (ash.uflag & UAS_GNU) == 0 )
{
qstring sname;
get_segm_name(&sname, seg);
if ( sname != "XMEM" && sname != "YMEM" )
ctx.gen_printf(DEFAULT_INDENT, "endsec");
}
}
//--------------------------------------------------------------------------
void dsp56k_t::header(outctx_t &ctx)
{
ctx.gen_header(GH_PRINT_ALL, NULL, ioh.device.c_str());
}
//--------------------------------------------------------------------------
void dsp56k_t::footer(outctx_t &ctx) const
{
qstring nbuf = get_colored_name(inf_get_start_ea());
const char *name = nbuf.c_str();
const char *end = ash.end;
if ( end == NULL )
ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s end %s",SCOLOR_AUTOCMT), ash.cmnt, name);
else
ctx.gen_printf(DEFAULT_INDENT,
COLSTR("%s",SCOLOR_ASMDIR) " " COLSTR("%s %s",SCOLOR_AUTOCMT),
ash.end, ash.cmnt, name);
}

View File

@@ -0,0 +1,566 @@
#include "dsp56k.hpp"
#include <diskio.hpp>
//--------------------------------------------------------------------------
static const char *const register_names[] =
{
// data arithmetic logic unit
"x", "x0", "x1",
"y", "y0", "y1",
// accumulator registers
"a", "a0", "a1", "a2",
"b", "b0", "b1", "b2",
"ab", // a1:b1
"ba", // b1:a1
"a10", // a1:a0
"b10", // b1:b0
// address generation unit (AGU)
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", // pointers
"n0", "n1", "n2", "n3", "n4", "n5", "n6", "n7", // offsets
"m0", "m1", "m2", "m3", "m4", "m5", "m6", "m7", // modifiers
// Program Control Unit
"pc", // Program Counter (16 Bits)
"mr", // Mode Register (8 Bits)
"ccr", // Condition Code Register (8 Bits)
"sr", // Status Register (MR:CCR, 16 Bits)
"omr", // Operating Mode Register (8 Bits)
"la", // Hardware Loop Address Register (16 Bits)
"lc", // Hardware Loop Counter (16 Bits)
"sp", // System Stack Pointer (6 Bits)
"ss", // System Stack RAM (15X32 Bits)
"ssh", // Upper 16 Bits of the Contents of the Current Top of Stack
"ssl", // Lower 16 Bits of the Contents of the Current Top of Stack
"sz", // Stack Size register
"sc", // Stack Counter register
"ep", // Extension Pointer register
"vba", // Vector Base Address Register
"cs","ds", // virtual registers for code and data segments
};
//--------------------------------------------------------------------------
//6x
static const uchar retcode_0[] = { 0x0C, 0x00, 0x00 };
static const uchar retcode_1[] = { 0x04, 0x00, 0x00 };
//61
static const uchar retcode_2[] = { 0x06, 0x00 };
static const uchar retcode_3[] = { 0x07, 0x00 };
static const bytes_t retcodes6x[] =
{
{ sizeof(retcode_0), retcode_0 },
{ sizeof(retcode_1), retcode_1 },
{ 0, NULL }
};
static const bytes_t retcodes61[] =
{
{ sizeof(retcode_2), retcode_2 },
{ sizeof(retcode_3), retcode_3 },
{ 0, NULL }
};
//-----------------------------------------------------------------------
// Motorola DSP56000 Assembler
//-----------------------------------------------------------------------
static const asm_t motasm =
{
// AS_ASCIIC
ASH_HEXF4 // $34
|ASD_DECF0 // 34
|ASB_BINF2 // %01010
|ASO_OCTF1 // 0123
|AS_COLON
|AS_N2CHR
|AS_NCMAS
|AS_ONEDUP,
0,
"Motorola DSP56K Assembler",
0,
NULL, // header lines
"org", // org
"end", // end
";", // comment string
'"', // string delimiter
'\'', // char delimiter
"\"'", // special symbols in char and string constants
"dc", // ascii string directive
"dcb", // byte directive
"dc", // word directive
NULL, // double words
NULL, // qwords
NULL, // oword (16 bytes)
NULL, // float (4 bytes)
NULL, // double (8 bytes)
NULL, // tbyte (10/12 bytes)
NULL, // packed decimal real
"bs#s(c,) #d, #v", // arrays (#h,#d,#v,#s(...)
"ds %s", // uninited arrays
"equ", // equ
NULL, // 'seg' prefix (example: push seg seg001)
"*", // current IP (instruction pointer)
NULL, // func_header
NULL, // func_footer
"global", // "public" name keyword
NULL, // "weak" name keyword
"xref", // "extrn" name keyword
// .extern directive requires an explicit object size
NULL, // "comm" (communal variable)
NULL, // get_type_name
NULL, // "align" keyword
'(', ')', // lbrace, rbrace
"%", // mod
"&", // and
"|", // or
"^", // xor
"~", // not
"<<", // shl
">>", // shr
NULL, // sizeof
AS2_BYTE1CHAR,// One symbol per processor byte
};
//-----------------------------------------------------------------------
// GNU ASM
//-----------------------------------------------------------------------
static const asm_t gas =
{
AS_ASCIIC
|ASH_HEXF4 // $34
|ASD_DECF0 // 34
|ASB_BINF3 // 0b01010
|ASO_OCTF1 // 0123
|AS_COLON
|AS_N2CHR
|AS_NCMAS
|AS_ONEDUP,
UAS_GNU,
"GNU-like hypothetical assembler",
0,
NULL, // header lines
".org", // org
NULL, // end
";", // comment string
'"', // string delimiter
'\'', // char delimiter
"\"'", // special symbols in char and string constants
".string", // ascii string directive
".byte", // byte directive
".short", // word directive
".long", // double words
NULL, // qwords
NULL, // oword (16 bytes)
NULL, // float (4 bytes)
NULL, // double (8 bytes)
NULL, // tbyte (10/12 bytes)
NULL, // packed decimal real
".ds.#s(b,w,l,d) #d, #v", // arrays (#h,#d,#v,#s(...)
".space %s", // uninited arrays
"=", // equ
NULL, // 'seg' prefix (example: push seg seg001)
".", // current IP (instruction pointer)
NULL, // func_header
NULL, // func_footer
".global", // "public" name keyword
NULL, // "weak" name keyword
".extern", // "extrn" name keyword
// .extern directive requires an explicit object size
".comm", // "comm" (communal variable)
NULL, // get_type_name
".align", // "align" keyword
'(', ')', // lbrace, rbrace
"mod", // mod
"and", // and
"or", // or
"xor", // xor
"not", // not
"shl", // shl
"shr", // shr
NULL, // sizeof
AS2_BYTE1CHAR,// One symbol per processor byte
NULL, // cmnt2
NULL, // low8
NULL, // high8
NULL, // low16
NULL, // high16
"#include \"%s\"", // a_include_fmt
};
static const asm_t *const asms[] = { &motasm, &gas, NULL };
//----------------------------------------------------------------------
ea_t dsp56k_t::AdditionalSegment(asize_t size, int offset, const char *name) const
{
segment_t s;
int step = is561xx() ? 0xF : 0x1000000-1;
s.start_ea = free_chunk(0x1000000, size, step);
s.end_ea = s.start_ea + size;
s.sel = allocate_selector((s.start_ea-offset) >> 4);
s.type = SEG_DATA;
s.bitness = ph.dnbits > 16;
add_segm_ex(&s, name, "DATA", ADDSEG_NOSREG|ADDSEG_OR_DIE);
return s.start_ea - offset;
}
inline ea_t get_start(const segment_t *s)
{
return s ? s->start_ea : BADADDR;
}
//--------------------------------------------------------------------------
const char *dsp56k_iohandler_t::iocallback(const ioports_t &iop, const char *line)
{
int size;
if ( qsscanf(line, "XMEMSIZE = %i", &size) == 1 )
{
pm.xmemsize = size;
RETOK:
pm.ioh.deviceparams.sprnt("XMEM=0x%X YMEM=0x%X", pm.xmemsize, pm.ymemsize);
return NULL;
}
if ( !pm.is561xx() && qsscanf(line, "YMEMSIZE = %i", &size) == 1 )
{
pm.ymemsize = size;
goto RETOK;
}
return pm.ioh.standard_callback(iop, line);
}
const ioport_t *dsp56k_t::find_port(ea_t address)
{
return find_ioport(ioh.ports, address);
}
//--------------------------------------------------------------------------
void dsp56k_t::create_xmem_ymem(void)
{
if ( xmem == BADADDR )
{
xmem = AdditionalSegment(xmemsize, 0, "XMEM");
if ( !is561xx() )
ymem = AdditionalSegment(ymemsize, 0, "YMEM");
}
}
//--------------------------------------------------------------------------
void dsp56k_t::select_device(const char *dname, int resp_info)
{
ioh.set_device_name(dname, resp_info);
create_xmem_ymem();
for ( int i=0; i < ioh.ports.size(); i++ )
{
const ioport_t &p = ioh.ports[i];
ea_t ea = xmem + p.address;
const char *name = p.name.c_str();
ea_t nameea = get_name_ea(BADADDR, name);
if ( nameea != ea )
{
set_name(nameea, "");
if ( !set_name(ea, name, SN_NOCHECK|SN_NOWARN|SN_NODUMMY) )
set_cmt(ea, name, 0);
}
}
}
//--------------------------------------------------------------------------
const char *dsp56k_t::set_idp_options(
const char *keyword,
int /*value_type*/,
const void * /*value*/,
bool /*idb_loaded*/)
{
if ( keyword != NULL )
return IDPOPT_BADKEY;
char cfgfile[QMAXFILE];
ioh.get_cfg_filename(cfgfile, sizeof(cfgfile));
if ( choose_ioport_device(&ioh.device, cfgfile) )
select_device(ioh.device.c_str(), IORESP_INT);
return IDPOPT_OK;
}
//-----------------------------------------------------------------------
// We always return "yes" because of the messy problem that
// there are additional operands with a wrong operand number (always 1)
static bool idaapi can_have_type(const op_t &)
{
return true;
}
//--------------------------------------------------------------------------
ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list)
{
switch ( code )
{
case idb_event::closebase:
case idb_event::savebase:
pm.helper.supset(0, pm.ioh.device.c_str());
break;
}
return 0;
}
//--------------------------------------------------------------------------
void dsp56k_t::set_cpu(int procno)
{
procnum = procno;
ph.cnbits = (is561xx() ) ? 16 : 24;
ph.dnbits = (is561xx() || is566xx()) ? 16 : 24;
ph.retcodes = (is561xx() ) ? retcodes61 : retcodes6x;
}
//----------------------------------------------------------------------
// 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 dsp56k_t);
return 0;
}
//--------------------------------------------------------------------------
ssize_t idaapi dsp56k_t::on_event(ssize_t msgid, va_list va)
{
int code = 0;
switch ( msgid )
{
case processor_t::ev_init:
hook_event_listener(HT_IDB, &idb_listener, &LPH);
helper.create("$ dsp56k");
break;
case processor_t::ev_term:
ioh.ports.clear();
unhook_event_listener(HT_IDB, &idb_listener);
break;
case processor_t::ev_newfile: // new file loaded
{
// data memory could already be present, check it
xmem = get_start(get_segm_by_name("XMEM"));
if ( !is561xx() )
ymem = get_start(get_segm_by_name("YMEM"));
char cfgfile[QMAXFILE];
ioh.get_cfg_filename(cfgfile, sizeof(cfgfile));
iohandler_t::parse_area_line0_t cb(ioh);
if ( choose_ioport_device2(&ioh.device, cfgfile, &cb) )
select_device(ioh.device.c_str(), IORESP_AREA|IORESP_INT);
else
create_xmem_ymem();
}
break;
case processor_t::ev_ending_undo:
// restore ptype
set_cpu(ph.get_proc_index());
//fall through
case processor_t::ev_oldfile: // old file loaded
xmem = get_start(get_segm_by_name("XMEM"));
if ( !is561xx() )
ymem = get_start(get_segm_by_name("YMEM"));
ioh.restore_device();
break;
case processor_t::ev_newprc: // new processor type
{
int n = va_arg(va, int);
// bool keep_cfg = va_argi(va, bool);
if ( procnum == -1 )
{
set_cpu(n);
}
else if ( procnum != n ) // can't change the processor type
{ // after the initial set up
warning("Sorry, processor type cannot be changed after loading");
code = -1;
break;
}
}
break;
case processor_t::ev_is_sane_insn:
{
const insn_t &insn = *va_arg(va, const insn_t *);
int nocrefs = va_arg(va, int);
return is_sane_insn(insn, nocrefs) == 1 ? 1 : -1;
}
case processor_t::ev_out_mnem:
{
outctx_t *ctx = va_arg(va, outctx_t *);
out_mnem(*ctx);
return 1;
}
case processor_t::ev_out_header:
{
outctx_t *ctx = va_arg(va, outctx_t *);
header(*ctx);
return 1;
}
case processor_t::ev_out_footer:
{
outctx_t *ctx = va_arg(va, outctx_t *);
footer(*ctx);
return 1;
}
case processor_t::ev_out_segstart:
{
outctx_t *ctx = va_arg(va, outctx_t *);
segment_t *seg = va_arg(va, segment_t *);
segstart(*ctx, seg);
return 1;
}
case processor_t::ev_out_segend:
{
outctx_t *ctx = va_arg(va, outctx_t *);
segment_t *seg = va_arg(va, segment_t *);
segend(*ctx, seg);
return 1;
}
case processor_t::ev_ana_insn:
{
insn_t *out = va_arg(va, insn_t *);
return ana(out);
}
case processor_t::ev_emu_insn:
{
const insn_t *insn = va_arg(va, const insn_t *);
return emu(*insn) ? 1 : -1;
}
case processor_t::ev_out_insn:
{
outctx_t *ctx = va_arg(va, outctx_t *);
out_insn(*ctx);
return 1;
}
case processor_t::ev_out_operand:
{
outctx_t *ctx = va_arg(va, outctx_t *);
const op_t *_op = va_arg(va, const op_t *);
return out_opnd(*ctx, *_op) ? 1 : -1;
}
case processor_t::ev_can_have_type:
{
const op_t *_op = va_arg(va, const op_t *);
return can_have_type(*_op) ? 1 : -1;
}
case processor_t::ev_is_sp_based:
{
int *mode = va_arg(va, int *);
const insn_t *insn = va_arg(va, const insn_t *);
const op_t *_op = va_arg(va, const op_t *);
*mode = is_sp_based(*insn, *_op);
return 1;
}
case processor_t::ev_set_idp_options:
{
const char *keyword = va_arg(va, const char *);
int value_type = va_arg(va, int);
const char *value = va_arg(va, const char *);
const char **errmsg = va_arg(va, const char **);
bool idb_loaded = va_argi(va, bool);
const char *ret = set_idp_options(keyword, value_type, value, idb_loaded);
if ( ret == IDPOPT_OK )
return 1;
if ( errmsg != NULL )
*errmsg = ret;
return -1;
}
case processor_t::ev_is_align_insn:
{
ea_t ea = va_arg(va, ea_t);
return is_align_insn(ea);
}
default:
break;
}
return code;
}
//-----------------------------------------------------------------------
#define FAMILY "Motorola DSP 5600x:"
static const char *const shnames[] =
{
"dsp56k",
"dsp561xx",
"dsp563xx",
"dsp566xx",
NULL
};
static const char *const lnames[] =
{
FAMILY"Motorola DSP 5600x",
"Motorola DSP 561xx",
"Motorola DSP 563xx",
"Motorola DSP 566xx",
NULL
};
//-----------------------------------------------------------------------
// Processor Definition
//-----------------------------------------------------------------------
processor_t LPH =
{
IDP_INTERFACE_VERSION, // version
PLFM_DSP56K, // id
// flag
PRN_HEX
| PR_ALIGN
| PR_BINMEM,
// flag2
PR2_IDP_OPTS, // the module has processor-specific configuration options
24, // 24 bits in a byte for code segments
24, // 24 bits in a byte for other segments
shnames,
lnames,
asms,
notify,
register_names, // Register names
qnumber(register_names), // Number of registers
vCS, // first
vDS, // last
0, // size of a segment register
vCS, vDS,
NULL, // No known code start sequences
retcodes6x,
DSP56_null,
DSP56_last,
Instructions, // instruc
0, // int tbyte_size; -- doesn't exist
{ 0, 7, 15, 0 }, // char real_width[4];
// number of symbols after decimal point
// 2byte float (0-does not exist)
// normal float
// normal double
// long double
DSP56_rts, // Icode of return instruction. It is ok to give any of possible return instructions
};