update
This commit is contained in:
2945
idasdk75/module/dsp56k/ana.cpp
Normal file
2945
idasdk75/module/dsp56k/ana.cpp
Normal file
File diff suppressed because it is too large
Load Diff
64
idasdk75/module/dsp56k/dsp561xx.cfg
Normal file
64
idasdk75/module/dsp56k/dsp561xx.cfg
Normal 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
|
||||
169
idasdk75/module/dsp56k/dsp563xx.cfg
Normal file
169
idasdk75/module/dsp56k/dsp563xx.cfg
Normal 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
|
||||
|
||||
45
idasdk75/module/dsp56k/dsp566xx.cfg
Normal file
45
idasdk75/module/dsp56k/dsp566xx.cfg
Normal 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
|
||||
|
||||
|
||||
58
idasdk75/module/dsp56k/dsp56k.cfg
Normal file
58
idasdk75/module/dsp56k/dsp56k.cfg
Normal 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
|
||||
346
idasdk75/module/dsp56k/dsp56k.hpp
Normal file
346
idasdk75/module/dsp56k/dsp56k.hpp
Normal 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 ±
|
||||
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
|
||||
222
idasdk75/module/dsp56k/emu.cpp
Normal file
222
idasdk75/module/dsp56k/emu.cpp
Normal 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;
|
||||
}
|
||||
|
||||
144
idasdk75/module/dsp56k/ins.cpp
Normal file
144
idasdk75/module/dsp56k/ins.cpp
Normal 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);
|
||||
147
idasdk75/module/dsp56k/ins.hpp
Normal file
147
idasdk75/module/dsp56k/ins.hpp
Normal 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
|
||||
46
idasdk75/module/dsp56k/makefile
Normal file
46
idasdk75/module/dsp56k/makefile
Normal 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
|
||||
397
idasdk75/module/dsp56k/out.cpp
Normal file
397
idasdk75/module/dsp56k/out.cpp
Normal 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);
|
||||
}
|
||||
566
idasdk75/module/dsp56k/reg.cpp
Normal file
566
idasdk75/module/dsp56k/reg.cpp
Normal 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
|
||||
};
|
||||
Reference in New Issue
Block a user