update to ida 7.6, add builds

This commit is contained in:
2021-10-31 21:20:46 +02:00
parent e0e0f2be99
commit b1809fe2d9
1408 changed files with 279193 additions and 302468 deletions

View File

@@ -0,0 +1,251 @@
/*
* Interactive disassembler (IDA).
* Version 3.05
* Copyright (c) 1990-95 by Ilfak Guilfanov.
* ALL RIGHTS RESERVED.
* FIDO: 2:5020/209
* E-mail: ig@estar.msk.su
*
*/
#ifndef _MITSUBISHI7900_HPP
#define _MITSUBISHI7900_HPP
#include "../idaidp.hpp"
#include "ins.hpp"
#include <segregs.hpp>
#include "../iohandler.hpp"
#define PROCMOD_NAME m7900
#define PROCMOD_NODE_NAME "$ " QSTRINGIZE(PROCMOD_NAME)
#define UAS_NOSPA 0x0001 // no space after comma
#define UAS_SEGM 0x0002 // segments are named "segment XXX"
// flags for insn.auxpref
// operand prefix
// 0x1 - .b
// 0x2 - .w
// 0x4 - .d
#define INSN_PREF_U 0x0000
#define INSN_PREF_B 0x0001
#define INSN_PREF_W 0x0002
#define INSN_PREF_D 0x0004
#define RAZOPER insn.auxpref
// Detect status value
#define getFlag_M get_sreg(insn.ea, rfM)
#define getFlag_X get_sreg(insn.ea, rfX)
#define getDT get_sreg(insn.ea, rDT)
#define getPG get_sreg(insn.ea, rPG)
#define getDPReg get_sreg(insn.ea, rDPReg)
#define getDPR0 get_sreg(insn.ea, rDPR0)
#define getDPR1 get_sreg(insn.ea, rDPR1)
#define getDPR2 get_sreg(insn.ea, rDPR2)
#define getDPR3 get_sreg(insn.ea, rDPR3)
//----------------------------------------------------------------------
// Redefine temporary names
//
#define xmode specflag1
#define TypeOper specflag2
#define o_sr o_idpspec0
#define o_ab o_idpspec1
#define o_stk o_idpspec2
//
//
enum mitsubishi_bit_PUL { bPS, bb, bDT, bDPR0, bY, bX, bB, bA };
// ======= mitsubishi_bit_CPU ========================================
/*
__________________________
|... |IPL|N|V|m|x|D|I|Z|C|
__________________________
*/
//
// Bit 0: Carry flag (C)
// Bit 1: Zero flag (Z)
// Bit 2: Interrupt disable flag (I)
// Bit 3: Decimal mode flag (D)
// Bit 4: Index register length flag (x)
// Bit 5: Data length flag (m)
// Bit 6: Overflow flag (V)
// Bit 7: Negative flag (N)
// Bits 10 to 8: Processor interrupt priority level (IPL)
//
enum mitsubishi_bit_CPU { bIPL, bN, bV, bm, bx, bD, bI, bZ, bC };
enum mitsubishi_registers { rA, rB, rE, rX, rY, rPC,
rPS,
rfIPL, rfN, rfV, rfD, rfI, rfZ, rfC,
rDT, rPG, rDPReg, rDPR0, rDPR1, rDPR2, rDPR3,rfM, rfX,
Rcs, Rds };
/*
15____________________0
| Ah | AL | - Accumulator A
_____________________
15____________________0
| Bh | BL | - Accumulator B
| ____________________|
31___________________________________________0
| Eh | EL | - Accumulator E
_____________________________________________
15____________________0
| Xh | XL | - Index registr X
_____________________
15____________________0
| Yh | YL | - Index registr Y
_____________________
15____________________0
| Sh | SL | - Stack pointer S
_____________________
8_________0
| DT | - Data bank registr(DT)
_________
23_________15___________________0
| PG | PCh | PCl | - Program counter(PC)
_______________________________
|_____________________________________________________ - Program bank registr()PG
15____________________0
| DPR0h | DPR0L | - Direct page registr 0(DPR0)
_____________________
15____________________0
| DPR1h | DPR1L | - Direct page registr 1(DPR1)
_____________________
15____________________0
| DPR2h | DPR2L | - Direct page registr 2(DPR2)
_____________________
15____________________0
| DPR3h | DPR3L | - Direct page registr 3(DPR3)
_____________________
15____________________0
| PSh | PS L | - Procesor status register(PS)
_____________________
*/
enum eMode { IMM_8=0, IMM_16, IMM_32, DIR_32, DIR_16, DIR_8 };
// TDIR_DIR - Direct addressing mode DIR
// TDIR_DIR_X - Direct index X addressing DIR,X
// TDIR_DIR_Y - Direct index Y addressing DIR,Y
// TDIR_INDIRECT_DIR - Direct indirect addressing mode (DIR)
// TDIR_INDIRECT_DIR_X - Direct index X indirect addressing mode (DIR,X)
// TDIR_INDIRECT_DIR_Y - Direct index Y indirect addressing mode (DIR,Y)
// TDIR_L_INDIRECT_DIR - Direct indirect long addressing mode L(DIR)
// TDIR_L_INDIRECT_DIR_Y - Direct indirect long indexed Y addressing mode L(DIR),Y
enum eTypeDIR { TDIR_DIR=0, TDIR_DIR_X, TDIR_DIR_Y, TDIR_INDIRECT_DIR,
TDIR_INDIRECT_DIR_X, TDIR_INDIRECT_DIR_Y, TDIR_L_INDIRECT_DIR, TDIR_L_INDIRECT_DIR_Y };
// TSP_SP - Stack pointer relative addressing mode(SR)
// TSP_INDEX_SP_Y - Stack pointer relative indexed Y addressing mode((SR),Y)
enum eTypeSP { TSP_SP=0, TSP_INDEX_SP_Y };
// TAB_ABS - Absolute addressing mode(ABS)
// TAB_ABS_X - Absolute indexed X addressing mode(ABS,X)
// TAB_ABS_Y - Absolute indexed Y addressing mode(ABS,Y)
// TAB_ABL - Absolute long addressing mode(ABL)
// TAB_ABL_X - Absolute long indexed X addressing mode(ABS,X)
// TAB_INDIRECTED_ABS - Absolute indirect addressing mode((ABS))
// TAB_L_INDIRECTED_ABS - Absolute indirect long addressing mode(L(ABS))
// TAB_INDIRECTED_ABS_X - Absolute indexed X indirect addressing mode((ABS,X))
enum eTypeAB { TAB_ABS=0, TAB_ABS_X, TAB_ABS_Y, TAB_ABL, TAB_ABL_X,
TAB_INDIRECTED_ABS, TAB_L_INDIRECTED_ABS, TAB_INDIRECTED_ABS_X };
//------------------------------------------------------------------------
struct ioport_bit_t;
//------------------------------------------------------------------------
int idaapi ana(insn_t *_insn);
inline void TRACE1(const char *szStr)
{
msg("%s\n", szStr);
}
inline void TRACE1(uint32 Data)
{
msg("DATA - %X\n", Data);
}
inline void TRACE(const char * /*szStr*/)
{
// msg("%s\n", szStr);
}
inline void TRACE(uint32 /*Data*/)
{
// msg("DATA - %X\n", Data);
}
inline int GETBIT(uval_t Data, int bit)
{
uint32 TempByte = (uint32)Data;
return (TempByte>>bit)&0x01;
}
//------------------------------------------------------------------
DECLARE_PROC_LISTENER(idb_listener_t, struct m7900_t);
struct m7900_t : public procmod_t
{
netnode helper;
iohandler_t ioh = iohandler_t(helper);
idb_listener_t idb_listener = idb_listener_t(*this);
bool flow = false;
virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override;
const char *set_idp_options(
const char *keyword,
int /*value_type*/,
const void * /*value*/,
bool /*idb_loaded*/);
bool choose_device();
void handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload);
int emu(const insn_t &insn);
void m7900_header(outctx_t &ctx);
void m7900_segstart(outctx_t &ctx, segment_t *Srange) const;
void m7900_footer(outctx_t &ctx) const;
void load_from_idb();
};
extern int data_id;
#endif

10062
idasdk76/module/m7900/ana.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,235 @@
/*
* Interactive disassembler (IDA).
* Version 3.05
* Copyright (c) 1990-95 by Ilfak Guilfanov.
* ALL RIGHTS RESERVED.
* FIDO: 2:5020/209
* E-mail: ig@estar.msk.su
*
*/
#include "7900.hpp"
//------------------------------------------------------------------------
// convert to data and add cross-ref
static void DataSet(const insn_t &insn, const op_t &x, ea_t EA, int isload)
{
insn.create_op_data(EA, x);
insn.add_dref(EA, x.offb, isload ? dr_R : dr_W);
}
//----------------------------------------------------------------------
void m7900_t::handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload)
{
flags_t F = get_flags(insn.ea);
switch ( x.type )
{
case o_phrase:
//remember_problem(PR_JUMP, insn.ea);
case o_void:
case o_reg:
break;
case o_sr:
case o_displ:
set_immd(insn.ea);
if ( !is_forced )
{
ushort addr = ushort(x.addr);
if ( x.type == o_displ )
{
addr += (ushort)insn.ip;
addr += insn.size;
uint32 offb = map_code_ea(insn, addr, x.n);
DataSet(insn, x, offb, isload);
}
else if ( op_adds_xrefs(F, x.n) )
{
insn.add_off_drefs(x, dr_O, 0);
}
}
break;
case o_stk:
case o_imm:
set_immd(insn.ea);
if ( op_adds_xrefs(F, x.n) )
insn.add_off_drefs(x, dr_O, 0);
break;
case o_ab:
if ( x.TypeOper == TAB_INDIRECTED_ABS_X )
{
ea_t ea = to_ea(insn.cs, x.addr);
insn.create_op_data(ea, x.offb, dt_word);
insn.add_dref(ea, x.offb, isload ? dr_R : dr_W);
// get data
uint32 Addr;
Addr = get_word(ea);
Addr = uint32(Addr | (getPG<<16));
insn.add_cref(Addr, 2, fl_JF);
}
else
{
DataSet(insn, x, map_code_ea(insn, x), isload);
}
break;
case o_mem:
// convert to data, add cross ref
switch ( x.TypeOper )
{
case TDIR_DIR_Y:
case TDIR_DIR_X:
case TDIR_DIR:
case TDIR_INDIRECT_DIR:
case TDIR_INDIRECT_DIR_X:
case TDIR_INDIRECT_DIR_Y:
case TDIR_L_INDIRECT_DIR:
case TDIR_L_INDIRECT_DIR_Y:
if ( getDPReg == 1 )
{
insn_t tmp = insn;
op_t &tmpx = tmp.ops[x.n];
tmpx.addr &= 0xFF3F;
DataSet(tmp, tmpx, map_code_ea(tmp, tmpx), isload);
}
else
{
DataSet(insn, x, map_code_ea(insn, x), isload);
}
break;
default:
DataSet(insn, x, map_code_ea(insn, x), isload);
break;
}
break;
case o_near:
{
ea_t ea = to_ea(insn.cs, x.addr);
switch ( insn.itype )
{
case m7900_jsr:
insn.add_cref(ea, x.offb, fl_CN);
if ( !func_does_return(ea) )
flow = false;
break;
case m7900_jsrl:
insn.add_cref(ea, x.offb, fl_CF);
if ( !func_does_return(ea) )
flow = false;
break;
case m7900_jmpl:
insn.add_cref(ea, x.offb, fl_JF);
break;
default:
insn.add_cref(ea, x.offb, fl_JN);
break;
}
}
break;
default:
// warning("%a: %s,%d: bad optype %d", insn.ea, insn.get_canon_mnem(ph), x.n, x.type);
break;
}
}
//----------------------------------------------------------------------
static void LDD(const insn_t &ins)
{
static const int DPR[] = { rDPR0, rDPR1, rDPR2, rDPR3 };
for ( int i=0; i < 4; i++ )
if ( GETBIT(ins.Op1.value, i) == 1 )
split_sreg_range(ins.ea+ins.size, DPR[i], ins.ops[1+i].value, SR_auto);
}
//----------------------------------------------------------------------
int m7900_t::emu(const insn_t &insn)
{
// Set PG
split_sreg_range(insn.ea, rPG, ( insn.ea & 0xFF0000 ) >> 16, SR_auto);
uint32 Feature = insn.get_canon_feature(ph);
flow = (Feature & CF_STOP) == 0;
bool flag1 = is_forced_operand(insn.ea, 0);
bool flag2 = is_forced_operand(insn.ea, 1);
bool flag3 = is_forced_operand(insn.ea, 2);
bool flag4 = is_forced_operand(insn.ea, 3);
bool flag5 = is_forced_operand(insn.ea, 4);
if ( Feature & CF_USE1 ) handle_operand(insn, insn.Op1, flag1, true);
if ( Feature & CF_USE2 ) handle_operand(insn, insn.Op2, flag2, true);
if ( Feature & CF_USE3 ) handle_operand(insn, insn.Op3, flag3, true);
if ( Feature & CF_USE4 ) handle_operand(insn, insn.Op4, flag4, true);
if ( Feature & CF_USE5 ) handle_operand(insn, insn.Op5, flag5, true);
if ( Feature & CF_JUMP )
remember_problem(PR_JUMP, insn.ea);
if ( Feature & CF_CHG1 ) handle_operand(insn, insn.Op1, flag1, false);
if ( Feature & CF_CHG2 ) handle_operand(insn, insn.Op2, flag2, false);
if ( Feature & CF_CHG3 ) handle_operand(insn, insn.Op3, flag3, false);
if ( Feature & CF_CHG4 ) handle_operand(insn, insn.Op4, flag4, false);
if ( Feature & CF_CHG5 ) handle_operand(insn, insn.Op5, flag5, false);
if ( flow )
add_cref(insn.ea, insn.ea + insn.size, fl_F);
switch ( insn.itype )
{
case m7900_lddn:
//split_sreg_range(insn.ea + insn.size, GetDPR(), insn.Op1.value, SR_auto);
LDD(insn);
break;
case m7900_ldt:
split_sreg_range(insn.ea + insn.size, rDT, insn.Op1.value, SR_auto);
break;
// clear m flag
case m7900_clm:
split_sreg_range(insn.ea + insn.size, rfM, 0, SR_auto);
break;
// set m flag
case m7900_sem:
split_sreg_range(insn.ea + insn.size, rfM, 1, SR_auto);
break;
// clear processor status
case m7900_clp:
// clear m flag
if ( ((insn.Op1.value & 0x20) >> 5) == 1 )
split_sreg_range(insn.ea + insn.size, rfM, 0, SR_auto);
// clear x flag
if ( ((insn.Op1.value & 0x10) >> 4) == 1 )
split_sreg_range(insn.ea + insn.size, rfX, 0, SR_auto);
break;
// set processor status
case m7900_sep:
// set m flag
if ( ((insn.Op1.value & 0x20) >> 5) == 1 )
split_sreg_range(insn.ea + insn.size, rfM, 1, SR_auto);
// set x flag
if ( ((insn.Op1.value & 0x10) >> 4) == 1 )
split_sreg_range(insn.ea + insn.size, rfX, 1, SR_auto);
break;
// pull processor status from stack
case m7900_plp:
split_sreg_range(insn.ea + insn.size, rfM, BADSEL, SR_auto);
split_sreg_range(insn.ea + insn.size, rfX, BADSEL, SR_auto);
break;
}
return 1;
}

View File

@@ -0,0 +1,297 @@
/*
* Interactive disassembler (IDA).
* Version 3.05
* Copyright (c) 1990-95 by Ilfak Guilfanov.
* ALL RIGHTS RESERVED.
* FIDO: 2:5020/209
* E-mail: ig@estar.msk.su
*
*/
#include <ida.hpp>
#include <idp.hpp>
#include "ins.hpp"
const instruc_t Instructions[] =
{
{ "", 0 }, // Unknown Operation
{ "abs", CF_CHG1 }, // ABSolute
{ "absd", CF_CHG1 }, // ABSolute at Double-word
{ "adc", CF_CHG1 | CF_USE2 }, // ADd with Carry
{ "adcb", CF_CHG1 | CF_USE2 }, // ADd with Carry at Byte
{ "adcd", CF_CHG1 | CF_USE2 }, // ADd with Carry at Double-word
{ "add", CF_CHG1 | CF_USE2 }, // Addition
{ "addb", CF_CHG1 | CF_USE2 }, // ADD at Byte
{ "addd", CF_CHG1 | CF_USE2 }, // ADD at Double-word
{ "addm", CF_CHG1 | CF_USE2 }, // ADD immediate and Memory
{ "addmb", CF_CHG1 | CF_USE2 }, // ADD immediate and Memory at Byte
{ "addmd", CF_CHG1 | CF_USE2 }, // ADD immediate and Memory at Double-word
{ "adds", CF_USE1 }, // ADD Stack pointer and immediate
{ "addx", CF_USE1 }, // ADD index register X and immediate
{ "addy", CF_USE1 }, // ADD index register Y and immediate
{ "and", CF_CHG1 | CF_USE2 }, // Logical AND
{ "andb", CF_CHG1 | CF_USE2 }, // logical AND between immediate (Byte)
{ "andm", CF_CHG1 | CF_USE2 }, // logical AND between immediate value and Memory
{ "andmb", CF_CHG1 | CF_USE2 }, // logical AND between immediate value and Memory (Byte)
{ "andmd", CF_CHG1 | CF_USE2 }, // logical AND between immediate value and Memory (Double word)
{ "asl", CF_CHG1 }, // Arithmetic Shift to Left
{ "asl", CF_CHG1 | CF_USE2 }, // Arithmetic Shift to Left by n bits
{ "asld", CF_CHG1 | CF_USE2 }, // Arithmetic Shift to Left by n bits (Double word)
{ "asr", CF_CHG1 }, // Arithmetic Shift to Right
{ "asr", CF_CHG1 | CF_USE2 }, // Arithmetic Shift to Right by n bits
{ "asrd", CF_CHG1 | CF_USE2 }, // Arithmetic Shift to Right by n bits (Double word)
{ "bbc", CF_USE1 | CF_USE2 | CF_USE3 }, // Branch on Bit Clear
{ "bbcb", CF_USE1 | CF_USE2 | CF_USE3 }, // Branch on Bit Clear (Byte)
{ "bbs", CF_USE1 | CF_USE2 | CF_USE3 }, // Branch on Bit Set
{ "bbsb", CF_USE1 | CF_USE2 | CF_USE3 }, // Branch on Bit Set (Byte)
{ "bcc", CF_USE1 }, // Branch on Carry Clear
{ "bcs", CF_USE1 }, // Branch on Carry Set
{ "beq", CF_USE1 }, // Branch on EQual
{ "bge", CF_USE1 }, // Branch on Greater or Equal
{ "bgt", CF_USE1 }, // Branch on Greater Than
{ "bgtu", CF_USE1 }, // Branch on Greater Than with Unsign
{ "ble", CF_USE1 }, // Branch on Less or Equal
{ "bleu", CF_USE1 }, // Branch on Less Equal with Unsign
{ "blt", CF_USE1 }, // Branch on Less Than
{ "bmi", CF_USE1 }, // Branch on result MInus
{ "bne", CF_USE1 }, // Branch on Not Equal
{ "bpl", CF_USE1 }, // Branch on result PLus
{ "bra", CF_USE1 | CF_JUMP | CF_STOP }, // BRanch Always
{ "bral", CF_USE1 | CF_JUMP | CF_STOP }, // BRanch Always
{ "brk", 0 }, // run int 0xFFFA
{ "bsc", CF_USE1 | CF_USE2 | CF_USE3 }, // Branch on Single bit Clear
{ "bsr", CF_USE1 | CF_CALL }, // Branch to SubRoutine
{ "bss", CF_USE1 | CF_USE2 | CF_USE3 }, // Branch on Single bit Set
{ "bvc", CF_USE1 }, // Branch on oVerflow Clear
{ "bvs", CF_USE1 }, // Branch on oVerflow Set
{ "cbeq", CF_USE1 | CF_USE2 | CF_USE3 }, // Compare immediate and Branch on EQual
{ "cbeqb", CF_USE1 | CF_USE2 | CF_USE3 }, // Compare immediate and Branch on EQual at Byte
{ "cbne", CF_USE1 | CF_USE2 | CF_USE3 }, // Compare immediate and Branch on Not Equal
{ "cbneb", CF_USE1 | CF_USE2 | CF_USE3 }, // Compare immediate and Branch on Not Equal at Byte
{ "clc", 0 }, // CLear Carry flag
{ "cli", 0 }, // CLear Interrupt disable status
{ "clm", 0 }, // CLear M flag
{ "clp", CF_USE1 }, // CLear Processor status
{ "clr", CF_CHG1 }, // CLeaR accumulator
{ "clrb", CF_CHG1 }, // CLeaR accumulator at Byte
{ "clrm", CF_CHG1 }, // CLeaR Memory
{ "clrmb", CF_CHG1 }, // CLeaR Memory at Byte
{ "clrx", 0 }, // CLeaR index register X
{ "clry", 0 }, // CLeaR index register Y
{ "clv", 0 }, // CLear oVerflow flag
{ "cmp", CF_USE1 | CF_USE2 }, // CoMPare
{ "cmpb", CF_USE1 | CF_USE2 }, // CoMPare at Byte
{ "cmpd", CF_USE1 | CF_USE2 }, // CoMPare at Double-word
{ "cmpm", CF_USE1 | CF_USE2 }, // CoMPare immediate with Memory
{ "cmpmb", CF_USE1 | CF_USE2 }, // CoMPare immediate with Memory at Byte
{ "cmpmd", CF_USE1 | CF_USE2 }, // CoMPare immediate with Memory at Double-word
{ "cpx", CF_USE1 }, // ComPare memory and index register X
{ "cpy", CF_USE1 }, // ComPare memory and index register Y
{ "debne", CF_USE1 | CF_USE2 | CF_USE3 }, // DEcrement memory and Branch on Not Equal
{ "dec", CF_CHG1 }, // DECrement by one
{ "dex", 0 }, // DEcrement index register X by one
{ "dey", 0 }, // DEcrement index register Y by one
{ "div", CF_USE1 }, // DIVide unsigned
{ "divs", CF_USE1 }, // DIVide with Sign
{ "dxbne", CF_USE1 | CF_USE2 }, // Decrement index register X and Branch on Not Equal
{ "dybne", CF_USE1 | CF_USE2 }, // Decrement index register Y and Branch on Not Equal
{ "eor", CF_CHG1 | CF_USE2 }, // Exclusive OR memory with accumulator
{ "eorb", CF_CHG1 | CF_USE2 }, // Exclusive OR immediate with accumulator at Byte
{ "eorm", CF_CHG1 | CF_USE2 }, // Exclusive OR immediate with Memory
{ "eormb", CF_CHG1 | CF_USE2 }, // Exclusive OR immediate with Memory at Byte
{ "eormd", CF_CHG1 | CF_USE2 }, // Exclusive OR immediate with Memory at Double-word
{ "exts", CF_CHG1 }, // EXTension Sign
{ "extsd", CF_CHG1 }, // EXTension Sign at Double-word
{ "extz", CF_CHG1 }, // EXTension Zero
{ "extzd", CF_CHG1 }, // EXTension Zero at Double-word
{ "inc", CF_CHG1 }, // INCrement by one
{ "inx", 0 }, // INcrement index register X by one
{ "iny", 0 }, // INcrement index register y by one
{ "jmp", CF_USE1 | CF_JUMP | CF_STOP }, // JuMP16
{ "jmpl", CF_USE1 | CF_JUMP | CF_STOP }, // Jump24
{ "jsr", CF_USE1 | CF_CALL }, // Jump to SubRoutine16
{ "jsrl", CF_USE1 | CF_CALL }, // Jump to SubRoutine24
{ "lda", CF_CHG1 | CF_USE2 }, // LoaD Accumulator from memory
{ "ldab", CF_CHG1 | CF_USE2 }, // LoaD Accumulator from memory at Byte
{ "ldad", CF_CHG1 | CF_USE2 }, // LoaD Accumulator from memory at Double-word
{ "ldd", CF_USE1 | CF_USE2 | CF_USE3 | CF_USE4 | CF_USE5 }, // LoaD immediate to Direct page register n
{ "ldt", CF_USE1 }, // LoaD immediate to DaTa bank register
{ "ldx", CF_USE1 }, // LoaD index register X from memory
{ "ldxb", CF_USE1 }, // LoaD index register X from memory at Byte
{ "ldy", CF_USE1 }, // LoaD index register Y from memory
{ "ldyb", CF_USE1 }, // LoaD index register Y from memory at Byte
{ "lsr", CF_CHG1 }, // Logical Shift Right
{ "lsr", CF_USE2 | CF_CHG1 }, // Logical n bits Shift Right
{ "lsrd", CF_USE2 | CF_CHG1 }, // Logical n bits Shift Right at Double-word
{ "movm", CF_USE2 | CF_CHG1 }, // MOVe Memory to memory
{ "movmb", CF_USE2 | CF_CHG1 }, // MOVe Memory to memory at Byte
{ "movr", CF_USE1 | CF_HLL }, // MOVe Repeat memory to memory
{ "movrb", CF_USE1 | CF_HLL }, // MOVe Repeat memory to memory at Byte
{ "mpy", CF_USE1 }, // MultiPlY
{ "mpys", CF_USE1 }, // MultiPlY with Sign
{ "mvn", CF_USE1 | CF_USE2 }, // MoVe Negative
{ "mvp", CF_USE1 | CF_USE2 }, // MoVe Positive
{ "neg", CF_CHG1 }, // NEGative
{ "negd", CF_CHG1 }, // NEGative at Double-word
{ "nop", 0 }, // No OPeration
{ "ora", CF_CHG1 | CF_USE2 }, // OR memory with Accumulator
{ "orab", CF_CHG1 | CF_USE2 }, // OR immediate with Accumulator at Byte
{ "oram", CF_CHG1 | CF_USE2 }, // OR immediAte with Memory
{ "oramb", CF_CHG1 | CF_USE2 }, // OR immediAte with Memory at Byte
{ "oramd", CF_CHG1 | CF_USE2 }, // OR immediAte with Memory at Double-word
{ "pea", CF_USE1 }, // Push Effective Address
{ "pei", CF_USE1 }, // Push Effective Indirect address
{ "per", CF_USE1 }, // Push Effective program counter Relative address
{ "pha", 0 }, // PusH accumulator A on stack
{ "phb", 0 }, // PusH accumulator B on stack
{ "phd", 0 }, // PusH Direct page register on stack
{ "phd", CF_USE1 }, // PusH Direct page register n on stack
{ "phg", 0 }, // PusH proGram bank register on stack
{ "phld", CF_USE1 | CF_HLL }, // PusH dpr n to stack and Load immediate to Dpr n
{ "php", 0 }, // PusH Processor status on stack
{ "pht", 0 }, // PusH daTa bank register on stack
{ "phx", 0 }, // PusH index register X on stack
{ "phy", 0 }, // PusH index register Y on stack
{ "pla", 0 }, // PuLl accumulator A from stack
{ "plb", 0 }, // PuLl accumulator B from stack
{ "pld", 0 }, // PuLl Direct page register from stack
{ "pld", CF_USE1 }, // PuLl Direct page register n from stack
{ "plp", 0 }, // PuLl Processor status from stack
{ "plt", 0 }, // PuLl daTa bank register from stack
{ "plx", 0 }, // PuLl index register X from stack
{ "ply", 0 }, // PuLl index register Y from stack
{ "psh", CF_USE1 }, // PuSH
{ "pul", CF_USE1 }, // PuLl
{ "rla", CF_USE1 }, // Rotate Left accumulator A
{ "rmpa", CF_USE1 }, // Repeat Multiply and Accumulate
{ "rol", CF_CHG1 }, // ROtate one bit Left
{ "rol", CF_USE2 | CF_CHG1 }, // n bits ROtate Left
{ "rold", CF_USE2 | CF_CHG1 }, // n bits ROtate Left at Double-word
{ "ror", CF_CHG1 }, // ROtate one bit Right
{ "ror", CF_USE2 | CF_CHG1 }, // n bits ROtate Right
{ "rord", CF_USE2 | CF_CHG1 }, // n bits ROtate Right at Double-word
{ "rti", CF_STOP }, // Return from Interrupt
{ "rtl", CF_STOP }, // ReTurn from subroutine Long
{ "rtld", CF_USE1 | CF_STOP }, // ReTurn from subroutine Long and pull Direct page register n
{ "rts", CF_STOP }, // ReTurn from Subroutine
{ "rtsd", CF_USE1 | CF_STOP }, // ReTurn from Subroutine and pull Direct page register n
{ "sbc", CF_USE1 | CF_USE2 }, // SuBtract with Carry
{ "sbcb", CF_USE1 | CF_USE2 }, // SuBtract with Carry at Byte
{ "sbcd", CF_USE1 | CF_USE2 }, // SuBtract with Carry at Double-word
{ "sec", 0 }, // SEt Carry flag
{ "sei", 0 }, // SEt Interrupt disable status
{ "sem", 0 }, // SEt M flag
{ "sep", CF_USE1 }, // SEt Processor status
{ "sta", CF_CHG2 | CF_USE1 }, // STore Accumulator in memory
{ "stab", CF_CHG2 | CF_USE1 }, // STore Accumulator in memory at Byte
{ "stad", CF_CHG2 | CF_USE1 }, // STore Accumulator in memory at Double-word
{ "stp", 0 }, // SToP
{ "stx", CF_CHG1 }, // STore index register X in memory
{ "sty", CF_CHG1 }, // STore index register Y in memory
{ "sub", CF_CHG1 | CF_USE2 }, // SUBtract
{ "subb", CF_CHG1 | CF_USE2 }, // SUBtract at Byte
{ "subd", CF_CHG1 | CF_USE2 }, // SUBtract at Double-word
{ "subm", CF_CHG1 | CF_USE2 }, // SUBtract immediate from Memory
{ "submb", CF_CHG1 | CF_USE2 }, // SUBtract immediate from Memory at Byte
{ "submd", CF_CHG1 | CF_USE2 }, // SUBtract immediate from Memory at Double-word
{ "subs", CF_USE1 }, // SUBtract Stack pointer
{ "subx", CF_USE1 }, // SUBtract immediate from index register X
{ "suby", CF_USE1 }, // SUBtract immediate from index register Y
{ "tad", CF_USE1 }, // Transfer accumulator A to Direct page register n
{ "tas", 0 }, // Transfer accumulator A to Stack pointer
{ "tax", 0 }, // Transfer accumulator A to index register X
{ "tay", 0 }, // Transfer accumulator A to index register Y
{ "tbd", CF_USE1 }, // Transfer accumulator B to Direct page register n
{ "tbs", 0 }, // Transfer accumulator B to Stack pointer
{ "tbx", 0 }, // Transfer accumulator B to index register X
{ "tby", 0 }, // Transfer accumulator B to index register Y
{ "tda", CF_USE1 }, // Transfer Direct page register n to accumulator A
{ "tdb", CF_USE1 }, // Transfer Direct page register n to accumulator B
{ "tds", 0 }, // Transfer Direct page register to Stack pointer
{ "tsa", 0 }, // Transfer Stack pointer to accumulator A
{ "tsb", 0 }, // Transfer Stack pointer to accumulator B
{ "tsd", 0 }, // Transfer Stack pointer to Direct page register
{ "tsx", 0 }, // Transfer Stack pointer to index register X
{ "txa", 0 }, // Transfer index register X to accumulator A
{ "txb", 0 }, // Transfer index register X to accumulator B
{ "txs", 0 }, // Transfer index register X to Stack pointer
{ "txy", 0 }, // Transfer index register X to Y
{ "tya", 0 }, // Transfer index register Y to accumulator A
{ "tyb", 0 }, // Transfer index register Y to accumulator B
{ "tyx", 0 }, // Transfer index register Y to X
{ "wit", CF_STOP }, // WaIT
{ "xab", 0 }, // eXchange accumulator A and B
};
CASSERT(qnumber(Instructions) == m7900_last);

View File

@@ -0,0 +1,299 @@
/*
* Interactive disassembler (IDA).
* Copyright (c) 1990-2021 Hex-Rays
* ALL RIGHTS RESERVED.
*
* MITSUBISHI 7900 Family
*/
#ifndef __INSTRS_HPP
#define __INSTRS_HPP
extern const instruc_t Instructions[];
enum nameNum ENUM_SIZE(uint16)
{
m7900_null = 0, // Unknown Operation
m7900_abs, // ABSolute
m7900_absd, // ABSolute at Double-word
m7900_adc, // ADd with Carry
m7900_adcb, // ADd with Carry at Byte
m7900_adcd, // ADd with Carry at Double-word
m7900_add, // Addition
m7900_addb, // ADD at Byte
m7900_addd, // ADD at Double-word
m7900_addm, // ADD immediate and Memory
m7900_addmb, // ADD immediate and Memory at Byte
m7900_addmd, // ADD immediate and Memory at Double-word
m7900_adds, // ADD Stack pointer and immediate
m7900_addx, // ADD index register X and immediate
m7900_addy, // ADD index register Y and immediate
m7900_and, // Logical AND
m7900_andb, // logical AND between immediate (Byte)
m7900_andm, // logical AND between immediate value and Memory
m7900_andmb, // logical AND between immediate value and Memory (Byte)
m7900_andmd, // logical AND between immediate value and Memory (Double word)
m7900_asl, // Arithmetic Shift to Left
m7900_asln, // Arithmetic Shift to Left by n bits
m7900_asldn, // Arithmetic Shift to Left by n bits (Double word)
m7900_asr, // Arithmeticshift to the right
m7900_asrn, // Arithmetic Shift to Right by n bits
m7900_asrdn, // Arithmetic Shift to Right by n bits (Double word)
m7900_bbc, // Branch on Bit Clear
m7900_bbcb, // Branch on Bit Clear (Byte)
m7900_bbs, // Branch on Bit Set
m7900_bbsb, // Branch on Bit Set (Byte)
m7900_bcc, // Branch on Carry Clear
m7900_bcs, // Branch on Carry Set
m7900_beq, // Branch on EQual
m7900_bge, // Branch on Greater or Equal
m7900_bgt, // Branch on Greater Than
m7900_bgtu, // Branch on Greater Than with Unsign
m7900_ble, // Branch on Less or Equal
m7900_bleu, // Branch on Less Equal with Unsign
m7900_blt, // Branch on Less Than
m7900_bmi, // Branch on result MInus
m7900_bne, // Branch on Not Equal
m7900_bpl, // Branch on result PLus
m7900_bra, // BRanch Always
m7900_bral, // BRanch Always
m7900_brk, // force BReaK
m7900_bsc, // Branch on Single bit Clear
m7900_bsr, // Branch to SubRoutine
m7900_bss, // Branch on Single bit Set
m7900_bvc, // Branch on oVerflow Clear
m7900_bvs, // Branch on oVerflow Set
m7900_cbeq, // Compare immediate and Branch on EQual
m7900_cbeqb, // Compare immediate and Branch on EQual at Byte
m7900_cbne, // Compare immediate and Branch on Not Equal
m7900_cbneb, // Compare immediate and Branch on Not Equal at Byte
m7900_clc, // CLear Carry flag
m7900_cli, // CLear Interrupt disable status
m7900_clm, // CLear M flag
m7900_clp, // CLear Processor status
m7900_clr, // CLeaR accumulator
m7900_clrb, // CLeaR accumulator at Byte
m7900_clrm, // CLeaR Memory
m7900_clrmb, // CLeaR Memory at Byte
m7900_clrx, // CLeaR index register X
m7900_clry, // CLeaR index register Y
m7900_clv, // CLear oVerflow flag
m7900_cmp, // CoMPare
m7900_cmpb, // CoMPare at Byte
m7900_cmpd, // CoMPare at Double-word
m7900_cmpm, // CoMPare immediate with Memory
m7900_cmpmb, // CoMPare immediate with Memory at Byte
m7900_cmpmd, // CoMPare immediate with Memory at Double-word
m7900_cpx, // ComPare memory and index register X
m7900_cpy, // ComPare memory and index register Y
m7900_debne, // DEcrement memory and Branch on Not Equal
m7900_dec, // DECrement by one
m7900_dex, // DEcrement index register X by one
m7900_dey, // DEcrement index register Y by one
m7900_div, // DIVide unsigned
m7900_divs, // DIVide with Sign
m7900_dxbne, // Decrement index register X and Branch on Not Equal
m7900_dybne, // Decrement index register Y and Branch on Not Equal
m7900_eor, // Exclusive OR memory with accumulator
m7900_eorb, // Exclusive OR immediate with accumulator at Byte
m7900_eorm, // Exclusive OR immediate with Memory
m7900_eormb, // Exclusive OR immediate with Memory at Byte
m7900_eormd, // Exclusive OR immediate with Memory at Double-word
m7900_exts, // EXTension Sign
m7900_extsd, // EXTension Sign at Double-word
m7900_extz, // EXTension Zero
m7900_extzd, // EXTension Zero at Double-word
m7900_inc, // INCrement by one
m7900_inx, // INcrement index register X by one
m7900_iny, // INcrement index register y by one
m7900_jmp, // Jump
m7900_jmpl, // Jump
m7900_jsr, // Jump to SubRoutine
m7900_jsrl, // Jump to SubRoutine
m7900_lda, // LoaD Accumulator from memory
m7900_ldab, // LoaD Accumulator from memory at Byte
m7900_ldad, // LoaD Accumulator from memory at Double-word
m7900_lddn, // LoaD immediate to Direct page register n
m7900_ldt, // LoaD immediate to DaTa bank register
m7900_ldx, // LoaD index register X from memory
m7900_ldxb, // LoaD index register X from memory at Byte
m7900_ldy, // LoaD index register Y from memory
m7900_ldyb, // LoaD index register Y from memory at Byte
m7900_lsr, // Logical Shift Right
m7900_lsrn, // Logical n bits Shift Right
m7900_lsrdn, // Logical n bits Shift Right at Double-word
m7900_movm, // MOVe Memory to memory
m7900_movmb, // MOVe Memory to memory at Byte
m7900_movr, // MOVe Repeat memory to memory
m7900_movrb, // MOVe Repeat memory to memory at Byte
m7900_mpy, // MultiPlY
m7900_mpys, // MultiPlY with Sign
m7900_mvn, // MoVe Negative
m7900_mvp, // MoVe Positive
m7900_neg, // NEGative
m7900_negd, // NEGative at Double-word
m7900_nop, // No OPeration
m7900_ora, // OR memory with Accumulator
m7900_orab, // OR immediate with Accumulator at Byte
m7900_oram, // OR immediAte with Memory
m7900_oramb, // OR immediAte with Memory at Byte
m7900_oramd, // OR immediAte with Memory at Double-word
m7900_pea, // Push Effective Address
m7900_pei, // Push Effective Indirect address
m7900_per, // Push Effective program counter Relative address
m7900_pha, // PusH accumulator A on stack
m7900_phb, // PusH accumulator B on stack
m7900_phd, // PusH Direct page register on stack
m7900_phdn, // PusH Direct page register n on stack
m7900_phg, // PusH proGram bank register on stack
m7900_phldn, // PusH dpr n to stack and Load immediate to Dpr n
m7900_php, // PusH Processor status on stack
m7900_pht, // PusH daTa bank register on stack
m7900_phx, // PusH index register X on stack
m7900_phy, // PusH index register Y on stack
m7900_pla, // PuLl accumulator A from stack
m7900_plb, // PuLl accumulator B from stack
m7900_pld, // PuLl Direct page register from stack
m7900_pldn, // PuLl Direct page register n from stack
m7900_plp, // PuLl Processor status from stack
m7900_plt, // PuLl daTa bank register from stack
m7900_plx, // PuLl index register X from stack
m7900_ply, // PuLl index register Y from stack
m7900_psh, // PuSH
m7900_pul, // PuLl
m7900_rla, // Rotate Left accumulator A
m7900_rmpa, // Repeat Multiply and Accumulate
m7900_rol, // ROtate one bit Left
m7900_roln, // n bits ROtate Left
m7900_roldn, // n bits ROtate Left at Double-word
m7900_ror, // ROtate one bit Right
m7900_rorn, // n bits ROtate Right
m7900_rordn, // n bits ROtate Right at Double-word
m7900_rti, // Return from Interrupt
m7900_rtl, // ReTurn from subroutine Long
m7900_rtld, // ReTurn from subroutine Long and pull Direct page register n
m7900_rts, // ReTurn from Subroutine
m7900_rtsdn, // ReTurn from Subroutine and pull Direct page register n
m7900_sbc, // SuBtract with Carry
m7900_sbcb, // SuBtract with Carry at Byte
m7900_sbcd, // SuBtract with Carry at Double-word
m7900_sec, // SEt Carry flag
m7900_sei, // SEt Interrupt disable status
m7900_sem, // SEt M flag
m7900_sep, // SEt Processor status
m7900_sta, // STore Accumulator in memory
m7900_stab, // STore Accumulator in memory at Byte
m7900_stad, // STore Accumulator in memory at Double-word
m7900_stp, // SToP
m7900_stx, // STore index register X in memory
m7900_sty, // STore index register Y in memory
m7900_sub, // SUBtract
m7900_subb, // SUBtract at Byte
m7900_subd, // SUBtract at Double-word
m7900_subm, // SUBtract immediate from Memory
m7900_submb, // SUBtract immediate from Memory at Byte
m7900_submd, // SUBtract immediate from Memory at Double-word
m7900_subs, // SUBtract Stack pointer
m7900_subx, // SUBtract immediate from index register X
m7900_suby, // SUBtract immediate from index register Y
m7900_tadn, // Transfer accumulator A to Direct page register n
m7900_tas, // Transfer accumulator A to Stack pointer
m7900_tax, // Transfer accumulator A to index register X
m7900_tay, // Transfer accumulator A to index register Y
m7900_tbdn, // Transfer accumulator B to Direct page register n
m7900_tbs, // Transfer accumulator B to Stack pointer
m7900_tbx, // Transfer accumulator B to index register X
m7900_tby, // Transfer accumulator B to index register Y
m7900_tdan, // Transfer Direct page register n to accumulator A
m7900_tdbn, // Transfer Direct page register n to accumulator B
m7900_tds, // Transfer Direct page register to Stack pointer
m7900_tsa, // Transfer Stack pointer to accumulator A
m7900_tsb, // Transfer Stack pointer to accumulator B
m7900_tsd, // Transfer Stack pointer to Direct page register
m7900_tsx, // Transfer Stack pointer to index register X
m7900_txa, // Transfer index register X to accumulator A
m7900_txb, // Transfer index register X to accumulator B
m7900_txs, // Transfer index register X to Stack pointer
m7900_txy, // Transfer index register X to Y
m7900_tya, // Transfer index register Y to accumulator A
m7900_tyb, // Transfer index register Y to accumulator B
m7900_tyx, // Transfer index register Y to X
m7900_wit, // WaIT
m7900_xab, // eXchange accumulator A and B
m7900_last //
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,52 @@
PROC=m7900
CONFIGS=m7900.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)ieee.h $(I)kernwin.hpp $(I)lines.hpp \
$(I)llong.hpp $(I)loader.hpp \
$(I)nalt.hpp $(I)name.hpp \
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
$(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
../iohandler.hpp 7900.hpp ana.cpp 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)funcs.hpp $(I)ida.hpp \
$(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \
$(I)llong.hpp $(I)loader.hpp \
$(I)nalt.hpp $(I)name.hpp \
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
$(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
../iohandler.hpp 7900.hpp emu.cpp ins.hpp
$(F)ins$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \
$(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \
$(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp \
$(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \
$(I)ua.hpp $(I)xref.hpp ins.cpp ins.hpp
$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.hpp $(I)diskio.hpp \
$(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \
$(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \
$(I)llong.hpp $(I)loader.hpp \
$(I)nalt.hpp $(I)name.hpp \
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
$(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
../iohandler.hpp 7900.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)ieee.h $(I)kernwin.hpp $(I)lines.hpp \
$(I)llong.hpp $(I)loader.hpp \
$(I)nalt.hpp $(I)name.hpp \
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
$(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
../iohandler.hpp 7900.hpp ins.hpp reg.cpp

View File

@@ -0,0 +1,846 @@
/*
* Interactive disassembler (IDA).
* Version 3.05
* Copyright (c) 1990-95 by Ilfak Guilfanov.
* ALL RIGHTS RESERVED.
* FIDO: 2:5020/209
* E-mail: ig@estar.msk.su
*
*/
#include "7900.hpp"
static const char *const BitNamesCPU[] = { "IPL", "N", "V", "m", "x", "D", "I", "Z", "C" };
static const char *const BitNamesPUL[] = { "PS", "0", "DT", "DP0", "Y", "X", "B", "A" };
//----------------------------------------------------------------------
class out_m7900_t : public outctx_t
{
out_m7900_t(void) = delete; // not used
public:
void OutReg(int rgnum) { out_register(ph.reg_names[rgnum]); }
int OutVarName(const op_t &x);
void SetDP0Plus(const op_t &x) { out_value(x, OOFW_IMM | OOFW_16); }
void GetNumPUL(uval_t data);
void GetNumDPRn(uval_t data);
void GetCLPFlags(uval_t data);
ea_t OutDPRReg(ea_t Addr, uval_t gDPReg);
void OutDPR(uint32 Data);
void OutDT(uint32 Data);
void OutIMM(uint32 Data);
void MOVRB(void);
void MOVR(void);
void MOV(const op_t &x);
bool out_operand(const op_t &x);
void out_insn(void);
void out_proc_mnem(void);
};
CASSERT(sizeof(out_m7900_t) == sizeof(outctx_t));
DECLARE_OUT_FUNCS(out_m7900_t)
//----------------------------------------------------------------------
void out_m7900_t::GetNumPUL(uval_t data)
{
int bitOut = 0;
for ( int i=0; i < 8; i++ )
{
if ( GETBIT(data, i) == 1 )
{
if ( bitOut != 0 )
out_symbol(',');
out_register(BitNamesPUL[7-i]);
if ( bitOut == 0 )
bitOut++;
}
}
}
//----------------------------------------------------------------------
void out_m7900_t::GetNumDPRn(uval_t data)
{
switch ( data )
{
case 0x1:
out_symbol('0');
break;
case 0x2:
out_symbol('1');
break;
case 0x4:
out_symbol('2');
break;
case 0x8:
out_symbol('3');
break;
default:
out_symbol('(');
bool add_comma = false;
for ( int i=0; i < 4; ++i )
{
if ( GETBIT(data, i) == 1 )
{
if ( add_comma )
out_symbol(',');
out_long(i, 10);
add_comma = true;
}
}
out_symbol(')');
break;
}
}
//----------------------------------------------------------------------
void out_m7900_t::GetCLPFlags(uval_t data)
{
int bitOut = 0;
for ( int i=0; i < 8; i++ )
{
if ( GETBIT(data, i) == 1 )
{
if ( bitOut != 0 )
out_symbol(',');
out_register(BitNamesCPU[8-i]);
if ( bitOut == 0 )
bitOut++;
}
}
}
//----------------------------------------------------------------------
int out_m7900_t::OutVarName(const op_t &x)
{
return out_name_expr(x, to_ea(insn.cs, x.addr), x.addr);
}
//----------------------------------------------------------------------
static int getNumDPR(uval_t iDPR )
{
switch ( iDPR )
{
case 0x0: return 0;
case 0x40: return 1;
case 0x80: return 2;
case 0xC0: return 3;
}
return 0;
}
//----------------------------------------------------------------------
ea_t out_m7900_t::OutDPRReg(ea_t Addr, uval_t gDPReg)
{
if ( gDPReg == 1 )
{
char szTemp[5];
uval_t Data = Addr;
Data &= 0xC0;
qsnprintf(szTemp, sizeof(szTemp), "DP%d", getNumDPR(Data));
out_register(szTemp);
Addr &= 0xFF3F;
}
else
{
out_keyword("DP0");
}
return Addr;
}
//----------------------------------------------------------------------
static sel_t GetValueDP(const insn_t &insn, int DPR )
{
if ( getDPReg == 1 )
{
switch ( DPR )
{
case 0x0: return getDPR0;
case 0x40: return getDPR1;
case 0x80: return getDPR2;
case 0xC0: return getDPR3;
}
}
return 0;
}
//----------------------------------------------------------------------
void out_m7900_t::OutDPR(uint32 Data)
{
ea_t Val = Data;
Val = OutDPRReg(Val, getDPReg);
out_symbol(':');
out_printf(COLSTR("%a",SCOLOR_NUMBER), Val+GetValueDP(insn, Data&0xC0));
}
//----------------------------------------------------------------------
void out_m7900_t::OutDT(uint32 Data)
{
out_register("DT");
out_symbol('+');
out_symbol(':');
out_printf(COLSTR("%X",SCOLOR_NUMBER), Data);
}
//----------------------------------------------------------------------
void out_m7900_t::OutIMM(uint32 Data)
{
out_symbol('#');
out_printf(COLSTR("%x",SCOLOR_NUMBER), Data);
}
//----------------------------------------------------------------------
void out_m7900_t::MOVRB(void)
{
int i;
uint32 Val1, Val2;
uchar code = get_byte(insn.ea+1);
uchar nib = (code >> 4) & 0xF;
uchar count = code & 0x0F;
switch ( nib )
{
case 0x0:
for ( i=0; i < count; i++ )
{
Val1 = get_byte(insn.ea+2+(i*2));// imm
Val2 = get_byte(insn.ea+2+(i*2)+1);// dd
// DPRxx
OutDPR(Val2);
out_symbol(',');
// imm
OutIMM(Val1);
if ( i != (count-1) )
out_symbol(',');
}
break;
case 0x1:
for ( i=0; i < count; i++ )
{
Val2 = get_word(insn.ea+2+(i*3));// mmll
Val1 = get_byte(insn.ea+2+(i*3)+2);// dd
// DPRxx
OutDPR(Val1);
out_symbol(',');
// DPR
OutDT(Val2);
out_symbol(',');
OutReg(rX);
if ( i != (count-1) )
out_symbol(',');
}
break;
case 0x2:
for ( i=0; i < count; i++ )
{
Val1 = get_byte(insn.ea+2+(i*3));// imm
Val2 = get_word(insn.ea+2+(i*3)+1);// mmll
// DPRxx
OutDT(Val2);
out_symbol(',');
// IMM
OutIMM(Val1);
if ( i != (count-1) )
out_symbol(',');
}
break;
case 0x4:
for ( i=0; i < count; i++ )
{
Val1 = get_byte(insn.ea+2+(i*2));// dd1
Val2 = get_byte(insn.ea+2+(i*2)+1);// dd2
// DPRxx
OutDPR(Val2);
out_symbol(',');
// DPRxx
OutDPR(Val1);
if ( i != (count-1) )
out_symbol(',');
}
break;
case 0x6:
for ( i=0; i < count; i++ )
{
Val1 = get_byte(insn.ea+2+(i*3));// imm
Val2 = get_word(insn.ea+2+(i*3)+1);// mmll
// DPRxx
OutDT(Val2);
out_symbol(',');
// DPR
OutDPR(Val1);
if ( i != (count-1) )
out_symbol(',');
}
break;
case 0x7:
for ( i=0; i < count; i++ )
{
Val2 = get_byte(insn.ea+2+(i*3));// mmll
Val1 = get_word(insn.ea+2+(i*3)+1);// dd
// DPRxx
OutDT(Val1);
out_symbol(',');
// DPR
OutDPR(Val2);
out_symbol(',');
OutReg(rX);
if ( i != (count-1) )
out_symbol(',');
}
break;
case 0x8:
for ( i=0; i < count; i++ )
{
Val2 = get_word(insn.ea+2+(i*3));// mmll
Val1 = get_byte(insn.ea+2+(i*3)+2);// dd
// DPRxx
OutDPR(Val1);
out_symbol(',');
// DT
OutDT(Val2);
if ( i != (count-1) )
out_symbol(',');
}
break;
case 0xA:
for ( i=0; i < count; i++ )
{
Val1 = get_word(insn.ea+2+(i*4));// imm
Val2 = get_word(insn.ea+2+(i*4)+2);// mmll
// DPRxx
OutDT(Val2);
out_symbol(',');
// DT
OutDT(Val1);
if ( i != (count-1) )
out_symbol(',');
}
break;
}
}
//----------------------------------------------------------------------
void out_m7900_t::MOVR(void)
{
int i;
uint32 Val1, Val2;
uchar code = get_byte(insn.ea+1);
uchar nib = (code >> 4) & 0xF;
uchar count = code & 0x0F;
switch ( nib )
{
case 0x0:
for ( i=0; i < count; i++ )
{
Val2 = get_word(insn.ea+2+(i*3));// mmll
Val1 = get_byte(insn.ea+2+(i*3)+2);// dd
// DPRxx
OutDPR(Val1);
out_symbol(',');
// DT
OutDT(Val2);
out_symbol(',');
OutReg(rX);
if ( i != (count-1) )
out_symbol(',');
}
break;
case 0x1:
for ( i=0; i < count; i++ )
{
if ( getFlag_M == 0 )
{
Val2 = get_word(insn.ea+2+(i*3));// imm
Val1 = get_byte(insn.ea+2+(i*3)+2);// dd
}
else
{
Val2 = get_byte(insn.ea+2+(i*2));// imm
Val1 = get_byte(insn.ea+2+(i*2)+1);// dd
}
// DPRxx
OutDPR(Val1);
out_symbol(',');
// imm
OutIMM(Val2);
if ( i != (count-1) )
out_symbol(',');
}
break;
case 0x3:
for ( i=0; i < count; i++ )
{
if ( getFlag_M == 0 )
{
Val2 = get_word(insn.ea+2+(i*4));// imm
Val1 = get_word(insn.ea+2+(i*4)+2);// llmm
}
else
{
Val2 = get_byte(insn.ea+2+(i*3));// imm
Val1 = get_word(insn.ea+2+(i*3)+1);// llmm
}
// DPRxx
OutDT(Val1);
out_symbol(',');
// IMM
OutIMM(Val2);
if ( i != (count-1) )
out_symbol(',');
}
break;
case 0x5:
for ( i=0; i < count; i++ )
{
Val2 = get_byte(insn.ea+2+(i*2));// dd
Val1 = get_byte(insn.ea+2+(i*2)+1);// dd
// DPRxx
OutDPR(Val1);
out_symbol(',');
// DPR
OutDPR(Val2);
if ( i != (count-1) )
out_symbol(',');
}
break;
case 0x6:
for ( i=0; i < count; i++ )
{
Val1 = get_byte(insn.ea+2+(i*3));// imm
Val2 = get_word(insn.ea+2+(i*3)+1);// mmll
// DPRxx
OutDT(Val2);
out_symbol(',');
// DPR
OutDPR(Val1);
out_symbol(',');
OutReg(rX);
if ( i != (count-1) )
out_symbol(',');
}
break;
case 0x7:
for ( i=0; i < count; i++ )
{
Val2 = get_byte(insn.ea+2+(i*3));// mmll
Val1 = get_word(insn.ea+2+(i*3)+1);// dd
// DPRxx
OutDT(Val1);
out_symbol(',');
// DPR
OutDPR(Val2);
if ( i != (count-1) )
out_symbol(',');
}
break;
case 0x9:
for ( i=0; i < count; i++ )
{
Val2 = get_word(insn.ea+2+(i*3));// mmll
Val1 = get_byte(insn.ea+2+(i*3)+2);// dd
// DPRxx
OutDPR(Val1);
out_symbol(',');
// DPR
OutDT(Val2);
if ( i != (count-1) )
out_symbol(',');
}
break;
case 0xB:
for ( i=0; i < count; i++ )
{
Val2 = get_word(insn.ea+2+(i*4));// imm
Val1 = get_word(insn.ea+2+(i*4)+2);// llmm
// DT
OutDT(Val1);
out_symbol(',');
// DT
OutDT(Val2);
if ( i != (count-1) )
out_symbol(',');
}
break;
}
}
//----------------------------------------------------------------------
void out_m7900_t::MOV(const op_t &x)
{
switch ( x.TypeOper )
{
case m7900_movrb: MOVRB(); break;
case m7900_movr: MOVR(); break;
default:
// msg("out: %a: bad prefix %d\n", insn.ip, RAZOPER);
break;
}
}
//----------------------------------------------------------------------
bool out_m7900_t::out_operand(const op_t &x)
{
switch ( x.type )
{
case o_void:
return 0;
case o_reg:
OutReg(x.reg);
break;
case o_phrase:
out_line(ph.reg_names[x.reg]);
break;
case o_ab:
switch ( x.TypeOper )
{
case TAB_L_INDIRECTED_ABS:
out_symbol('L');
// fallthrough
case TAB_INDIRECTED_ABS:
out_symbol('(');
if ( !OutVarName(x) )
out_value(x, OOF_ADDR | OOFS_NOSIGN);
out_symbol(')');
break;
case TAB_INDIRECTED_ABS_X:
out_symbol('(');
if ( !OutVarName(x) )
out_value(x, OOF_ADDR | OOFS_NOSIGN);
out_symbol(',');
OutReg(rX);
out_symbol(')');
break;
case TAB_ABS_Y:
case TAB_ABS_X:
case TAB_ABS:
out_register("DT");
out_symbol(':');
if ( !OutVarName(x) )
out_value(x, OOF_ADDR | OOFS_NOSIGN | OOFW_32);
break;
case TAB_ABL_X:
case TAB_ABL:
out_register("LG");
out_symbol(':');
if ( !OutVarName(x) )
out_value(x, OOF_ADDR | OOFS_NOSIGN | OOFW_32);
break;
}
break;
case o_sr:
if ( x.TypeOper == TSP_INDEX_SP_Y )
out_symbol('(');
if ( x.xmode == IMM_32 )
out_value(x, OOFW_IMM | OOFW_32);
else if ( x.xmode == IMM_16 )
out_value(x, OOFW_IMM | OOFW_16);
else
out_value(x, OOFW_IMM);
if ( x.TypeOper == TSP_INDEX_SP_Y )
{
out_symbol(',');
OutReg(rPS);
out_symbol(')');
}
break;
case o_stk:
// there are special cases
switch ( insn.itype )
{
case m7900_pei: SetDP0Plus(x); break;
case m7900_psh:
case m7900_pul: GetNumPUL(x.value); break;
default:
out_symbol('#');
out_value(x, OOFW_IMM | OOFS_NOSIGN);
break;
}
break;
case o_imm:
// there are special cases
switch ( insn.itype )
{
case m7900_sep:// Set Processor status
case m7900_clp:// CLear Processor status
GetCLPFlags(x.value);
break;
case m7900_lddn:
case m7900_tdan:
case m7900_phdn:
case m7900_rtsdn:
case m7900_pldn:
case m7900_rtld:
case m7900_phldn:
GetNumDPRn(x.value);
break;
case m7900_bsc:
case m7900_bss:
out_value(x, OOFW_IMM);
break;
default:
out_symbol('#');
out_value(x, OOFW_IMM);
break;
}
break;// case o_imm
case o_mem:
// output memory variable name (for example 'byte_98')
if ( x.TypeOper == m7900_movr || x.TypeOper == m7900_movrb )
{
MOV(x);
break;
}
switch ( x.TypeOper )
{
case TDIR_DIR_Y:
case TDIR_DIR_X:
case TDIR_DIR:
{
op_t y = x;
y.addr = OutDPRReg(y.addr, getDPReg);
out_symbol(':');
if ( !OutVarName(y) )
out_value(y, OOF_ADDR |OOF_NUMBER| OOFS_NOSIGN);
}
break;
case TDIR_L_INDIRECT_DIR_Y:
case TDIR_L_INDIRECT_DIR:
out_symbol('L');
// fallthrough
case TDIR_INDIRECT_DIR_Y:
case TDIR_INDIRECT_DIR:
out_symbol('(');
{
op_t y = x;
y.addr = OutDPRReg(y.addr, getDPReg);
out_symbol(':');
if ( !OutVarName(y) )
out_value(y, OOF_ADDR |OOF_NUMBER| OOFS_NOSIGN);
}
out_symbol(')');
break;
case TDIR_INDIRECT_DIR_X:
out_symbol('(');
{
op_t y = x;
y.addr = OutDPRReg(y.addr, getDPReg);
out_symbol(':');
if ( !OutVarName(y) )
out_value(y, OOF_ADDR |OOF_NUMBER| OOFS_NOSIGN);
}
out_symbol(',');
OutReg(rX);
out_symbol(')');
break;
}
break;
case o_near:
{
ea_t v = to_ea(insn.cs,x.addr);
if ( !out_name_expr(x, v, x.addr) )
{
out_value(x, OOF_ADDR | OOFS_NOSIGN);
// remember_problem(PR_NONAME, insn.ea);
}
}
break;
default:
// warning("out: %a: bad optype %d", insn.ip, x.type);
break;
}
return 1;
}
//----------------------------------------------------------------------
static const char *GetPrefics(int Raz)
{
switch ( Raz )
{
case INSN_PREF_B: return ".b";
case INSN_PREF_W: return "";
case INSN_PREF_D: return ".d";
case INSN_PREF_U: return "";
default:
// msg("out: %a: bad prefix %d\n", insn.ip, RAZOPER);
break;
}
return "";
}
//----------------------------------------------------------------------
void out_m7900_t::out_proc_mnem(void)
{
out_mnem(8, GetPrefics(RAZOPER)); // output instruction mnemonics
}
//----------------------------------------------------------------------
void out_m7900_t::out_insn(void)
{
out_mnemonic();
out_one_operand(0); // output the first operand
if ( insn.Op2.type != o_void )
{
out_symbol(','); // operand sep
if ( (ash.uflag & UAS_NOSPA) == 0 )
out_char(' ');
out_one_operand(1);
}
if ( insn.Op3.type != o_void )
{
out_symbol(',');
if ( (ash.uflag & UAS_NOSPA) == 0 )
out_char(' ');
out_one_operand(2);
}
if ( insn.Op4.type != o_void )
{
out_symbol(',');
if ( (ash.uflag & UAS_NOSPA) == 0 )
out_char(' ');
out_one_operand(3);
}
if ( insn.Op5.type != o_void )
{
out_symbol(',');
if ( (ash.uflag & UAS_NOSPA) == 0 )
out_char(' ');
out_one_operand(4);
}
out_immchar_cmts();
flush_outbuf();
}
//--------------------------------------------------------------------------
void m7900_t::m7900_header(outctx_t &ctx)
{
ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX, NULL, ioh.device.c_str());
}
//--------------------------------------------------------------------------
// generate segment header
//lint -esym(1764, ctx) could be made const
//lint -esym(818, Srange) could be made const
void m7900_t::m7900_segstart(outctx_t &ctx, segment_t *Srange) const
{
qstring sname;
get_visible_segm_name(&sname, Srange);
if ( ash.uflag & UAS_SEGM )
ctx.gen_printf(DEFAULT_INDENT, COLSTR("SEGMENT %s", SCOLOR_ASMDIR), sname.c_str());
else
ctx.gen_printf(DEFAULT_INDENT, COLSTR(".SECTION %s", SCOLOR_ASMDIR), sname.c_str());
ea_t orgbase = ctx.insn_ea - get_segm_para(Srange);
if ( orgbase != 0 )
{
char buf[MAX_NUMBUF];
btoa(buf, sizeof(buf), orgbase);
ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf);
}
}
//--------------------------------------------------------------------------
void m7900_t::m7900_footer(outctx_t &ctx) const
{
if ( ash.end != NULL )
{
ctx.gen_empty_line();
ctx.out_line(ash.end, COLOR_ASMDIR);
qstring name;
if ( get_colored_name(&name, inf_get_start_ea()) > 0 )
{
size_t i = strlen(ash.end);
do
ctx.out_char(' ');
while ( ++i < 8 );
ctx.out_line(name.begin());
}
ctx.flush_outbuf(DEFAULT_INDENT);
}
else
{
ctx.gen_cmt_line("end of file");
}
}

View File

@@ -0,0 +1,441 @@
/*
* Interactive disassembler (IDA).
* Version 3.05
* Copyright (c) 1990-95 by Ilfak Guilfanov.
* ALL RIGHTS RESERVED.
* FIDO: 2:5020/209
* E-mail: ig@estar.msk.su
*
*/
#include <ctype.h>
#include "7900.hpp"
#include <diskio.hpp>
#include <entry.hpp>
int data_id;
//----------------------------------------------------------------------
static const char *const RegNames[] =
{
"A", "B", "E", "X", "Y", "PC", "S",
"fIPL", "fN", "fV", "fD", "fI", "fZ", "fC",
"DT", "PG", "DPReg", "DPR0","DPR1", "DPR2","DPR3","fM", "fX",
"cs", "ds"
};
//----------------------------------------------------------------------
static const asm_t AS79 =
{
AS_COLON // create colons after data names ?
// ASCII directives:
|AS_1TEXT // 1 text per line, no bytes
|ASH_HEXF0 // format of hex numbers:// 34h
|ASD_DECF0 // format of dec numbers:// 34
|ASB_BINF0 // format of binary numbers:// 010101b
|AS_ONEDUP, // One array definition per line
UAS_NOSPA | UAS_SEGM,
"Mitsubishi AS79 V4.10",
0,
NULL, // header
".org",
".end",
";", // comment string
'"', // string delimiter
'\'', // char delimiter
"'\"", // special symbols in char and string constants
".BYTE", // ascii string directive
".BYTE", // byte directive
".WORD", // word directive
".DWORD", // no double words
NULL, // no qwords
NULL, // oword (16 bytes)
NULL, // no float
NULL, // no double
NULL, // no tbytes
NULL, // no packreal
NULL, //".db.#s(b,w) #d,#v", // #h - header(.byte,.word)
// #d - size of array
// #v - value of array elements
// #s - size specifier
".rs %s", // uninited data (reserve space)
".equ",
NULL, // seg prefix
"*", // a_curip
NULL, // returns function header line
NULL, // returns function footer line
NULL, // public
NULL, // weak
NULL, // extrn
NULL, // comm
NULL, // get_type_name
NULL, // align
'(', ')', // lbrace, rbrace
NULL, // mod
NULL, // and
NULL, // or
NULL, // xor
NULL, // not
NULL, // shl
NULL, // shr
NULL, // sizeof
};
//----------------------------------------------------------------------
//----------------------------------------------------------------------
#define FAMILY "Mitsubishi series:"
static const char *const shnames[] =
{
"m7900",
NULL
};
static const char *const lnames[] =
{
FAMILY"Mitsubishi 7700 Family / 7900 Series",
NULL
};
static const asm_t *const asms[] =
{
&AS79,
NULL
};
//--------------------------------------------------------------------------
static const uchar retc_0[] = { 0xF1 }; // rti
static const uchar retc_1[] = { 0x94 }; // rtl
static const uchar retc_2[] = { 0x1C, 0x77 }; // rtld 0
static const uchar retc_3[] = { 0x2C, 0x77 }; // rtld 1
static const uchar retc_4[] = { 0x4C, 0x77 }; // rtld 2
static const uchar retc_5[] = { 0x8C, 0x77 }; // rtld 3
static const uchar retc_6[] = { 0x84 }; // rts
static const uchar retc_7[] = { 0x18, 0x77 }; // rtsd 0
static const uchar retc_8[] = { 0x28, 0x77 }; // rtsd 1
static const uchar retc_9[] = { 0x48, 0x77 }; // rtsd 2
static const uchar retc_10[] = { 0x88, 0x77 }; // rtsd 3
static const uchar retc_11[] = { 0x00, 0x74 }; // brk
static const bytes_t retcodes[] =
{
{ sizeof(retc_0), retc_0 },
{ sizeof(retc_1), retc_1 },
{ sizeof(retc_2), retc_2 },
{ sizeof(retc_3), retc_3 },
{ sizeof(retc_4), retc_4 },
{ sizeof(retc_5), retc_5 },
{ sizeof(retc_6), retc_6 },
{ sizeof(retc_6), retc_7 },
{ sizeof(retc_6), retc_8 },
{ sizeof(retc_9), retc_9 },
{ sizeof(retc_10), retc_10 },
{ sizeof(retc_11), retc_11 },
{ 0, NULL }
};
//----------------------------------------------------------------------
#define ADDRRESET 0xFFFE
const char *m7900_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)
&& ioh.device == NONEPROC )
{
warning("No devices are defined in the configuration file %s", cfgfile);
}
ioh.set_device_name(ioh.device.c_str(), IORESP_PORT|IORESP_INT);
return IDPOPT_OK;
}
//------------------------------------------------------------------
bool m7900_t::choose_device()
{
char cfgfile[QMAXFILE];
ioh.get_cfg_filename(cfgfile, sizeof(cfgfile));
iohandler_t::parse_area_line0_t cb(ioh);
bool ok = choose_ioport_device2(&ioh.device, cfgfile, &cb);
if ( !ok )
{
ioh.device = NONEPROC;
segment_t *sptr = get_first_seg();
if ( sptr != NULL )
{
//inf_set_start_ea(sptr->start_ea);
//inf_set_start_ip(0);
// No processor selected, so create RESET.
// According to 7900 manual RESET resides at 0xFFFE address
create_word(ADDRRESET, 2);
ea_t proc = get_word(ADDRRESET);
if ( proc != 0xFFFF && is_mapped(proc) )
{
op_plain_offset(ADDRRESET, 0, 0);
add_entry(proc, proc, "__RESET", true);
set_cmt(ADDRRESET, "RESET", false);
}
}
}
return ok;
}
//--------------------------------------------------------------------------
void m7900_t::load_from_idb()
{
ioh.restore_device(IORESP_NONE);
}
//--------------------------------------------------------------------------
ssize_t idaapi idb_listener_t::on_event(ssize_t notification_code, va_list va)
{
switch ( notification_code )
{
case idb_event::sgr_changed:
// In case of fM or fX segment registers undefine data above current address
{
int reg = va_arg(va, int);
if ( reg == rfM || reg == rfX || reg == rDT || reg == rPG )
{
// msg("Deleting instructions in range %08a..%08a\n",ea1, ea2);
// for (ea_t x = ea1; x < ea2; x = next_that(x, ea2, is_code))
// del_items(x, DELIT_SIMPLE);
}
}
break;
}
return 0;
}
//--------------------------------------------------------------------------
static const char *const m7900_help_message =
"AUTOHIDE REGISTRY\n"
"You have loaded a file for the Mitsubishi 7900 family processor.\n\n"\
"This processor can be used in two different 'length modes' : 8-bit and 16-bit.\n"\
"IDA allows to specify the encoding mode for every single instruction.\n"\
"For this, IDA uses two virtual segment registers : \n"\
" - rDPReg(1), - rDPR0(0), rDPR1(0), rDPR2(0), rDPR3(0) \n"\
" - rDT(0), rPG(0), rPC(0), rPS(0) \n"\
" - fM, used to specify the data length;(0)\n"\
" - fX, used to specify the index register length.(0)\n\n"\
"Switching their state from 0 to 1 will switch the disassembly from 16-bit to 8-bit.\n"\
"You can change their value using the 'change segment register value' command"\
"(the canonical hotkey is Alt-G).\n\n"\
"Note : in the real design, those registers are represented as flags in the\n"\
"processor status register.\n";
//----------------------------------------------------------------------
// 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(SET_MODULE_DATA(m7900_t));
return 0;
}
//----------------------------------------------------------------------
ssize_t idaapi m7900_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(PROCMOD_NODE_NAME);
break;
case processor_t::ev_newfile:
if ( choose_device() )
ioh.set_device_name(ioh.device.c_str(), IORESP_ALL);
// Set the default segment register values :
// -1 (badsel) for DR
// 0 for fM and fX
for ( segment_t *s=get_first_seg(); s != NULL; s=get_next_seg(s->start_ea) )
{
set_default_sreg_value(s, rDPR0, 0x0);
set_default_sreg_value(s, rDPR1, 0x0);
set_default_sreg_value(s, rDPR2, 0x0);
set_default_sreg_value(s, rDPR3, 0x0);
set_default_sreg_value(s, rDT, 0x0);
set_default_sreg_value(s, rPG, 0x0);
set_default_sreg_value(s, rPC, 0xFFFE);
set_default_sreg_value(s, rPS, 0x0FFF);
set_default_sreg_value(s, rfI, 1);
set_default_sreg_value(s, rfD, 0);
set_default_sreg_value(s, rfX, 0);
set_default_sreg_value(s, rfM, 0);
set_default_sreg_value(s, rfIPL, 0);
set_default_sreg_value(s, rDPReg, 1);
}
info(m7900_help_message);
break;
case processor_t::ev_term:
unhook_event_listener(HT_IDB, &idb_listener);
clr_module_data(data_id);
break;
case processor_t::ev_ending_undo:
case processor_t::ev_oldfile:
load_from_idb();
break;
case processor_t::ev_creating_segm: // new segment
{
segment_t *s = va_arg(va, segment_t *);
// Set default value of DS register for all segments
set_default_dataseg(s->sel);
}
break;
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 *);
m7900_header(*ctx);
return 1;
}
case processor_t::ev_out_footer:
{
outctx_t *ctx = va_arg(va, outctx_t *);
m7900_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 *);
m7900_segstart(*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_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;
}
default:
break;
}
return code;
}
//-----------------------------------------------------------------------
// Processor Definition
//-----------------------------------------------------------------------
processor_t LPH =
{
IDP_INTERFACE_VERSION, // version
PLFM_M7900, // id
// flag
PR_RNAMESOK // can use register names for byte names
| PR_BINMEM // The module creates RAM/ROM segments for binary files
// (the kernel shouldn't ask the user about their sizes and addresses)
| PR_SEGS // has segment registers?
| PR_SGROTHER, // the segment registers don't contain
// the segment selectors, something else
// flag2
PR2_IDP_OPTS, // the module has processor-specific configuration options
8, // 8 bits in a byte for code segments
8, // 8 bits in a byte for other segments
shnames,
lnames,
asms,
notify,
RegNames, // Regsiter names
qnumber(RegNames), // Number of registers
rDT,
Rds,
0, // size of a segment register
Rcs,Rds,
NULL, // No known code start sequences
retcodes,
0,
m7900_last,
Instructions, // instruc
3, // int tbyte_size; -- doesn't exist
{ 0, 0, 0, 0 }, // char real_width[4];
// number of symbols after decimal point
// 2byte float (0-does not exist)
// normal float
// normal double
// long double
m7900_rts, // Icode of return instruction. It is ok to give any of possible return instructions
};