update to ida 7.6, add builds
This commit is contained in:
1217
idasdk76/module/f2mc/ana.cpp
Normal file
1217
idasdk76/module/f2mc/ana.cpp
Normal file
File diff suppressed because it is too large
Load Diff
297
idasdk76/module/f2mc/emu.cpp
Normal file
297
idasdk76/module/f2mc/emu.cpp
Normal file
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "f2mc.hpp"
|
||||
#include <segregs.hpp>
|
||||
#include <frame.hpp>
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static int get_reglist_size(ushort reglist)
|
||||
{
|
||||
int size = 0;
|
||||
for ( int i = 0; i < 8; i++ )
|
||||
if ( (reglist >> i) & 1 )
|
||||
size++;
|
||||
return size;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static bool is_bank(const op_t &op)
|
||||
{
|
||||
if ( op.type != o_reg )
|
||||
return false;
|
||||
|
||||
return op.reg == DTB
|
||||
|| op.reg == ADB
|
||||
|| op.reg == SSB
|
||||
|| op.reg == USB
|
||||
|| op.reg == DPR
|
||||
|| op.reg == PCB;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static void process_imm(const insn_t &insn, const op_t &x)
|
||||
{
|
||||
set_immd(insn.ea);
|
||||
|
||||
if ( op_adds_xrefs(get_flags(insn.ea), x.n) )
|
||||
insn.add_off_drefs(x, dr_O, calc_outf(x));
|
||||
|
||||
if ( is_defarg(get_flags(insn.ea), x.n) )
|
||||
return; // if already defined by user
|
||||
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case F2MC_add:
|
||||
case F2MC_addl:
|
||||
case F2MC_addsp:
|
||||
case F2MC_addw2:
|
||||
case F2MC_and:
|
||||
case F2MC_andw2:
|
||||
case F2MC_callv:
|
||||
case F2MC_cbne:
|
||||
case F2MC_cmp2:
|
||||
case F2MC_cmpl:
|
||||
case F2MC_cmpw2:
|
||||
case F2MC_cwbne:
|
||||
case F2MC_int:
|
||||
case F2MC_link:
|
||||
case F2MC_mov:
|
||||
case F2MC_movl:
|
||||
case F2MC_movn:
|
||||
case F2MC_movw:
|
||||
case F2MC_movx:
|
||||
case F2MC_or:
|
||||
case F2MC_orw2:
|
||||
case F2MC_sub:
|
||||
case F2MC_subl:
|
||||
case F2MC_subw2:
|
||||
case F2MC_xor:
|
||||
case F2MC_xorw2:
|
||||
op_num(insn.ea, x.n);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void f2mc_t::handle_operand(const insn_t &insn, const op_t &x, bool use)
|
||||
{
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_reg:
|
||||
case o_phrase:
|
||||
case o_reglist:
|
||||
return;
|
||||
|
||||
case o_near:
|
||||
case o_far:
|
||||
{
|
||||
cref_t ftype = fl_JN;
|
||||
ea_t ea = x.addr;
|
||||
// 24-bit (far) operands store the full address.
|
||||
// so this calculation is needed only for near jumps/calls
|
||||
if ( x.type == o_near )
|
||||
ea = calc_code_mem(insn, x.addr);
|
||||
|
||||
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);
|
||||
}
|
||||
break;
|
||||
|
||||
case o_imm:
|
||||
QASSERT(10102, use);
|
||||
process_imm(insn, x);
|
||||
break;
|
||||
|
||||
case o_mem:
|
||||
{
|
||||
ea_t ea = calc_data_mem(x.addr);
|
||||
insn.add_dref(ea, x.offb, use ? dr_R : dr_W);
|
||||
insn.create_op_data(ea, x);
|
||||
}
|
||||
break;
|
||||
case o_displ:
|
||||
process_imm(insn, x);
|
||||
if ( may_create_stkvars() && x.reg == RW3 )
|
||||
{
|
||||
func_t *pfn = get_func(insn.ea);
|
||||
if ( pfn != NULL
|
||||
&& (pfn->flags & FUNC_FRAME) != 0
|
||||
&& insn.create_stkvar(x, x.addr, STKVAR_VALID_SIZE) )
|
||||
{
|
||||
op_stkvar(insn.ea, x.n);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
warning("%a: %s,%d: bad optype %d", insn.ea, insn.get_canon_mnem(ph), x.n, x.type);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
inline bool add_stkpnt(func_t *pfn, sval_t delta, const insn_t &insn)
|
||||
{
|
||||
return add_auto_stkpnt(pfn, insn.ea + insn.size, delta);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static void trace_sp(const insn_t &insn)
|
||||
{
|
||||
func_t *pfn = get_func(insn.ea);
|
||||
if ( pfn == NULL )
|
||||
return;
|
||||
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case F2MC_int:
|
||||
case F2MC_intp:
|
||||
case F2MC_int9:
|
||||
add_stkpnt(pfn, -6*2, insn);
|
||||
break;
|
||||
case F2MC_reti:
|
||||
add_stkpnt(pfn, 6*2, insn);
|
||||
break;
|
||||
case F2MC_link:
|
||||
add_stkpnt(pfn, -2-insn.Op1.value, insn);
|
||||
break;
|
||||
case F2MC_unlink:
|
||||
add_stkpnt(pfn, -get_spd(pfn, insn.ea), insn);
|
||||
break;
|
||||
case F2MC_ret:
|
||||
add_stkpnt(pfn, 2, insn);
|
||||
break;
|
||||
case F2MC_retp:
|
||||
add_stkpnt(pfn, 2*2, insn);
|
||||
break;
|
||||
case F2MC_pushw:
|
||||
if ( insn.Op1.type == o_reglist )
|
||||
add_stkpnt(pfn, -get_reglist_size(insn.Op1.reg)*2, insn);
|
||||
else
|
||||
add_stkpnt(pfn, -2, insn);
|
||||
break;
|
||||
case F2MC_popw:
|
||||
if ( insn.Op1.type == o_reglist )
|
||||
add_stkpnt(pfn, get_reglist_size(insn.Op1.reg)*2, insn);
|
||||
else
|
||||
add_stkpnt(pfn, 2, insn);
|
||||
break;
|
||||
case F2MC_addsp:
|
||||
add_stkpnt(pfn, insn.Op1.value, insn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
int f2mc_t::emu(const insn_t &insn)
|
||||
{
|
||||
uint32 feature = insn.get_canon_feature(ph);
|
||||
flow = (feature & CF_STOP) == 0;
|
||||
|
||||
if ( feature & CF_USE1 ) handle_operand(insn, insn.Op1, true);
|
||||
if ( feature & CF_USE2 ) handle_operand(insn, insn.Op2, true);
|
||||
if ( feature & CF_USE3 ) handle_operand(insn, insn.Op3, true);
|
||||
|
||||
if ( feature & CF_CHG1 ) handle_operand(insn, insn.Op1, false);
|
||||
if ( feature & CF_CHG2 ) handle_operand(insn, insn.Op2, false);
|
||||
if ( feature & CF_CHG3 ) handle_operand(insn, insn.Op3, false);
|
||||
|
||||
// check for CCR changes
|
||||
if ( insn.Op1.type == o_reg && insn.Op1.reg == CCR )
|
||||
{
|
||||
op_bin(insn.ea, 1);
|
||||
|
||||
sel_t ccr = get_sreg(insn.ea, CCR);
|
||||
if ( ccr == BADSEL )
|
||||
ccr = 0;
|
||||
|
||||
if ( insn.itype == F2MC_and )
|
||||
ccr &= insn.Op2.value; // and ccr,imm8
|
||||
else if ( insn.itype == F2MC_or )
|
||||
ccr |= insn.Op2.value; // or ccr,imm8
|
||||
split_sreg_range(get_item_end(insn.ea), CCR, ccr, SR_auto);
|
||||
}
|
||||
|
||||
|
||||
// check for DTB,ADB,SSB,USB,DPR changes
|
||||
if ( insn.itype == F2MC_mov && is_bank(insn.Op1)
|
||||
&& insn.Op2.type == o_reg && insn.Op2.reg == A ) // mov dtb|adb|ssb|usb|dpr,a
|
||||
{
|
||||
sel_t bank = BADSEL;
|
||||
insn_t l;
|
||||
if ( decode_prev_insn(&l, insn.ea) != BADADDR && l.itype == F2MC_mov
|
||||
&& l.Op1.type == o_reg && l.Op1.reg == A )
|
||||
{
|
||||
if ( l.Op2.type == o_imm ) // mov a,imm8
|
||||
bank = l.Op2.value;
|
||||
else if ( is_bank(l.Op2) ) // mov a,dtb|adb|ssb|usb|dpr|pcb
|
||||
{
|
||||
bank = get_sreg(l.ea, l.Op2.reg);
|
||||
if ( bank == BADSEL )
|
||||
bank = 0;
|
||||
}
|
||||
}
|
||||
if ( bank != BADSEL )
|
||||
split_sreg_range(get_item_end(insn.ea), insn.Op1.reg, bank, SR_auto);
|
||||
}
|
||||
|
||||
|
||||
// determine if the next instruction should be executed
|
||||
if ( segtype(insn.ea) == SEG_XTRN )
|
||||
flow = false;
|
||||
if ( flow )
|
||||
add_cref(insn.ea, insn.ea + insn.size, fl_F);
|
||||
|
||||
if ( may_trace_sp() )
|
||||
{
|
||||
if ( !flow )
|
||||
recalc_spd(insn.ea); // recalculate SP register for the next insn
|
||||
else
|
||||
trace_sp(insn);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool idaapi create_func_frame(func_t *pfn)
|
||||
{
|
||||
if ( pfn != NULL )
|
||||
{
|
||||
if ( pfn->frame == BADNODE )
|
||||
{
|
||||
ea_t ea = pfn->start_ea;
|
||||
if ( ea + 4 < pfn->end_ea ) // minimum 2+1+1 bytes needed
|
||||
{
|
||||
insn_t insn;
|
||||
decode_insn(&insn, ea);
|
||||
if ( insn.itype == F2MC_link )
|
||||
{
|
||||
size_t localsize = (size_t)insn.Op1.value;
|
||||
ushort regsize = 2;
|
||||
decode_insn(&insn, ea + 2);
|
||||
pfn->flags |= FUNC_FRAME;
|
||||
return add_frame(pfn, localsize, regsize, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int idaapi is_sp_based(const insn_t &, const op_t &)
|
||||
{
|
||||
return OP_SP_ADD | OP_FP_BASED;
|
||||
}
|
||||
159
idasdk76/module/f2mc/f2mc.hpp
Normal file
159
idasdk76/module/f2mc/f2mc.hpp
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _F2MC_HPP
|
||||
#define _F2MC_HPP
|
||||
|
||||
#include "../idaidp.hpp"
|
||||
#include <diskio.hpp>
|
||||
#include <segregs.hpp>
|
||||
#include "ins.hpp"
|
||||
#include "../iohandler.hpp"
|
||||
|
||||
//------------------------------------------------------------------
|
||||
enum regnum_t
|
||||
{
|
||||
A, // accumulator
|
||||
AL, // accumulator
|
||||
AH, // accumulator
|
||||
PC, // program counter
|
||||
SP, // stack pointer
|
||||
R0,
|
||||
R1,
|
||||
R2,
|
||||
R3,
|
||||
R4,
|
||||
R5,
|
||||
R6,
|
||||
R7,
|
||||
RW0,
|
||||
RW1,
|
||||
RW2,
|
||||
RW3,
|
||||
RW4,
|
||||
RW5,
|
||||
RW6,
|
||||
RW7,
|
||||
RL0,
|
||||
RL1,
|
||||
RL2,
|
||||
RL3,
|
||||
|
||||
PCB, // program bank register
|
||||
DTB, // data bank register
|
||||
ADB, // additional data bank register
|
||||
SSB, // system stack bank register
|
||||
USB, // user stack bank register
|
||||
CCR, // condition code register
|
||||
DPR, // direct page register
|
||||
rVcs, rVds, // virtual registers for code and data segments
|
||||
|
||||
SPB, // stack pointer bank register
|
||||
PS, // processor status
|
||||
ILM, // interrupt level mask register
|
||||
RP // register bank pointer
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// specific processor records
|
||||
|
||||
#define default_bank segpref
|
||||
#define prefix_bank auxpref_u8[1]
|
||||
#define op_bank auxpref_u8[0]
|
||||
// o_phrase = @reg+(f2mc_index) (f2mc_index if PHRASE_INDEX)
|
||||
#define at specflag1 // number of @ indirections (dtype @ = op.dtype)
|
||||
#define special_mode specflag2
|
||||
#define MODE_INC 1
|
||||
#define MODE_INDEX 2
|
||||
#define f2mc_index specval_shorts.high
|
||||
#define o_reglist o_idpspec0
|
||||
// o_disp = @reg+value
|
||||
#define addr_dtyp specflag3
|
||||
#define MODE_BIT 1
|
||||
#define byte_bit specflag4
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// processor types
|
||||
|
||||
typedef uchar proctype_t;
|
||||
|
||||
const proctype_t F2MC16L = 0;
|
||||
const proctype_t F2MC16LX = 1;
|
||||
|
||||
extern ea_t dataseg;
|
||||
//------------------------------------------------------------------
|
||||
#define F2MC_MACRO 0x0001 // use instruction macros
|
||||
inline ea_t calc_code_mem(const insn_t &insn, ea_t ea) { return to_ea(insn.cs, ea); }
|
||||
inline ea_t calc_data_mem(ea_t ea) { return (get_sreg(ea, DTB) << 16) | ea; }
|
||||
|
||||
int get_signed(int byte,int mask);
|
||||
|
||||
ea_t map_port(ea_t from);
|
||||
int calc_outf(const op_t &x);
|
||||
//------------------------------------------------------------------
|
||||
void idaapi f2mc_segend(outctx_t &ctx, segment_t *seg);
|
||||
|
||||
bool idaapi create_func_frame(func_t *pfn);
|
||||
int idaapi is_sp_based(const insn_t &insn, const op_t &x);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
struct f2mc_iohandler_t : public iohandler_t
|
||||
{
|
||||
struct f2mc_t ±
|
||||
f2mc_iohandler_t(f2mc_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {}
|
||||
virtual const char *aux_segm() const override { return "FSR"; }
|
||||
virtual bool area_processing(ea_t /*start*/, ea_t /*end*/, const char * /*name*/, const char * /*aclass*/) override;
|
||||
virtual const char *iocallback(const ioports_t &iop, const char *line) override;
|
||||
};
|
||||
|
||||
struct f2mc_t : public procmod_t
|
||||
{
|
||||
netnode helper;
|
||||
f2mc_iohandler_t ioh = f2mc_iohandler_t(*this, helper);
|
||||
const char *cfgname = nullptr;
|
||||
proctype_t ptype = F2MC16LX; // contains processor type
|
||||
ushort idpflags = F2MC_MACRO;
|
||||
bool flow = false;
|
||||
|
||||
virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override;
|
||||
|
||||
void load_symbols(int _respect_info);
|
||||
const char *find_sym(ea_t address);
|
||||
const char *find_bit(ea_t address, int bit);
|
||||
bool exist_bits(ea_t ea, int bitl, int bith);
|
||||
void f2mc_set_device_name(int _respect_info);
|
||||
void choose_and_set_device(int flags);
|
||||
inline void choose_device();
|
||||
const char *set_idp_options(
|
||||
const char *keyword,
|
||||
int value_type,
|
||||
const void * value,
|
||||
bool idb_loaded);
|
||||
void adjust_ea_bit(ea_t &ea, int &bit);
|
||||
void handle_operand(const insn_t &insn, const op_t &x, bool use);
|
||||
int emu(const insn_t &insn);
|
||||
|
||||
void ana_F2MC16LX(insn_t &insn);
|
||||
int ana(insn_t *_insn);
|
||||
|
||||
void f2mc_header(outctx_t &ctx);
|
||||
void f2mc_assumes(outctx_t &ctx);
|
||||
void print_segment_register(outctx_t &ctx, int reg, sel_t value);
|
||||
void f2mc_segstart(outctx_t &ctx, segment_t *Srange) const;
|
||||
void f2mc_footer(outctx_t &ctx) const;
|
||||
|
||||
void save_idpflags() { helper.altset(-1, idpflags); }
|
||||
void load_from_idb();
|
||||
};
|
||||
|
||||
extern int data_id;
|
||||
#define PROCMOD_NODE_NAME "$ f2mc"
|
||||
#define PROCMOD_NAME f2mc
|
||||
|
||||
#endif // _F2MC_HPP
|
||||
5250
idasdk76/module/f2mc/f2mc16l.cfg
Normal file
5250
idasdk76/module/f2mc/f2mc16l.cfg
Normal file
File diff suppressed because it is too large
Load Diff
11706
idasdk76/module/f2mc/f2mc16lx.cfg
Normal file
11706
idasdk76/module/f2mc/f2mc16lx.cfg
Normal file
File diff suppressed because it is too large
Load Diff
219
idasdk76/module/f2mc/ins.cpp
Normal file
219
idasdk76/module/f2mc/ins.cpp
Normal file
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "f2mc.hpp"
|
||||
|
||||
const instruc_t Instructions[] =
|
||||
{
|
||||
|
||||
{ "", 0 }, // Unknown Operation
|
||||
|
||||
// TRANSFER INSTRUCTIONS
|
||||
|
||||
{ "mov", CF_CHG1|CF_USE2 }, // Move byte data from source to destination
|
||||
{ "movn", CF_CHG1|CF_USE2 }, // Move immediate nibble data to A
|
||||
{ "movx", CF_CHG1|CF_USE2 }, // Move byte data with sign extension from source to A
|
||||
{ "xch", CF_CHG1|CF_CHG2 }, // Exchange byte data of source to destination
|
||||
{ "movw", CF_CHG1|CF_USE2 }, // Move word data from source to destination
|
||||
{ "xchw", CF_CHG1|CF_CHG2 }, // Exchange word data of source to destination
|
||||
{ "movl", CF_CHG1|CF_USE2 }, // Move long word data from source to destination
|
||||
|
||||
// NUMERIC DATA OPERATIONS INSTRUCTIONS
|
||||
|
||||
{ "add", CF_CHG1|CF_USE2 }, // Add byte data of destination and source to destination
|
||||
{ "addc", CF_CHG1 }, // Add byte data of AL and AH with Carry to AL
|
||||
{ "addc", CF_CHG1|CF_USE2 }, // Add byte data of A and effective address with Carry to A
|
||||
{ "adddc", CF_CHG1 }, // Add decimal data of AL and AH with Carry to AL
|
||||
{ "sub", CF_CHG1|CF_USE2 }, // Subtract byte data of source from festination to destination
|
||||
{ "subc", CF_CHG1 }, // Subtract byte data of AL from AH with Carry to AL
|
||||
{ "subc", CF_CHG1|CF_USE2 }, // Subtract byte data of effective address from A with Carry to A
|
||||
{ "subdc", CF_CHG1 }, // Subtract decimal data of AL from AH with Carry to AL
|
||||
{ "addw", CF_CHG1 }, // Add word data of AH and AL to AL
|
||||
{ "addw", CF_CHG1|CF_USE2 }, // Add word data of destination and source to destination
|
||||
{ "addcw", CF_CHG1 }, // Add word data of A and effective address from A with Carry to A
|
||||
{ "subw", CF_CHG1 }, // Subtract word data of AL from AH to AL
|
||||
{ "subw", CF_CHG1|CF_USE2 }, // Subtract word data of source from festination to destination
|
||||
{ "subcw", CF_CHG1 }, // Subtract word data of A and effective address from A with carry to A
|
||||
{ "addl", CF_CHG1|CF_USE2 }, // Add long word data of destination and source to destination
|
||||
{ "subl", CF_CHG1|CF_USE2 }, // Subtract long word data of source from festination to destination
|
||||
{ "inc", CF_CHG1 }, // Increment byte data
|
||||
{ "dec", CF_CHG1 }, // Decrement byte data
|
||||
{ "incw", CF_CHG1 }, // Increment word data
|
||||
{ "decw", CF_CHG1 }, // Decrement word data
|
||||
{ "incl", CF_CHG1 }, // Increment long word data
|
||||
{ "decl", CF_CHG1 }, // Decrement long word data
|
||||
{ "cmp", CF_USE1 }, // Compare byte data of AH and AL
|
||||
{ "cmp", CF_USE1|CF_USE2 }, // Compare byte data of destination and source
|
||||
{ "cmpw", CF_USE1 }, // Compare word data of AH and AL
|
||||
{ "cmpw", CF_USE1|CF_USE2 }, // Compare word data of destination and source
|
||||
{ "cmpl", CF_USE1|CF_USE2 }, // Compare long word data of destination and source
|
||||
{ "divu", CF_CHG1 }, // Divide AH by AL
|
||||
{ "divu", CF_CHG1|CF_CHG2 }, // Divide unsigned word data by unsigned byte data
|
||||
{ "divuw", CF_CHG1|CF_CHG2 }, // Divide unsigned long word data by unsigned word data
|
||||
{ "mulu", CF_CHG1 }, // Multiply unsigned byte AH by AL
|
||||
{ "mulu", CF_CHG1|CF_USE2 }, // Multiply unsigned byte data
|
||||
{ "muluw", CF_CHG1 }, // Multiply unsigned word AH by AL
|
||||
{ "muluw", CF_CHG1|CF_USE2 }, // Multiply unsigned word data
|
||||
{ "div", CF_CHG1 }, // Divide word data by byte data
|
||||
{ "div", CF_CHG1|CF_CHG2 }, // Divide word data by byte data
|
||||
{ "divw", CF_CHG1|CF_CHG2 }, // Divide long word data by word data
|
||||
{ "mul", CF_CHG1 }, // Multiply byte AH by AL
|
||||
{ "mul", CF_CHG1|CF_USE2 }, // Multiply byte data
|
||||
{ "mulw", CF_CHG1 }, // Multiply word AH by AL
|
||||
{ "mulw", CF_CHG1|CF_USE2 }, // Multiply word data
|
||||
|
||||
// LOGICAL DATA OPERATION INSTRUCTIONS
|
||||
|
||||
{ "and", CF_CHG1|CF_USE2 }, // And byte data of destination and source to destination
|
||||
{ "or", CF_CHG1|CF_USE2 }, // Or byte data of destination and source to destination
|
||||
{ "xor", CF_CHG1|CF_USE2 }, // Exclusive or byte data of destination and source to destination
|
||||
{ "not", CF_CHG1 }, // Not byte data of destination
|
||||
{ "andw", CF_CHG1 }, // And word data of AH and AL to AL
|
||||
{ "andw", CF_CHG1|CF_USE2 }, // And word data of destination and source to destination
|
||||
{ "orw", CF_CHG1 }, // Or word data of AH and AL to AL
|
||||
{ "orw", CF_CHG1|CF_USE2 }, // Or word data of destination and source to destination
|
||||
{ "xorw", CF_CHG1 }, // Exclusive or word data of AH and AL to AL
|
||||
{ "xorw", CF_CHG1|CF_USE2 }, // Exclusive or word data of destination and source to destination
|
||||
{ "notw", CF_CHG1 }, // Not word data of destination
|
||||
{ "andl", CF_CHG1|CF_USE2 }, // And long word data of destination and source to destination
|
||||
{ "orl", CF_CHG1|CF_USE2 }, // Or long word data of destination and source to destination
|
||||
{ "xorl", CF_CHG1|CF_USE2 }, // Exclusive or long word data of destination and source to destination
|
||||
{ "neg", CF_CHG1 }, // Negate byte data of destination
|
||||
{ "negw", CF_CHG1 }, // Negate word data of destination
|
||||
{ "nrml", CF_CHG1|CF_CHG2 }, // Normalize long word
|
||||
|
||||
// SHIFT INSTRUCTIONS
|
||||
|
||||
{ "rorc", CF_CHG1 }, // Rotate byte data of A with Carry to right
|
||||
{ "rolc", CF_CHG1 }, // Rotate byte data of A with Carry to left
|
||||
{ "asr", CF_CHG1|CF_USE2 }, // Arithmetic shift byte data of A to right
|
||||
{ "lsr", CF_CHG1|CF_USE2 }, // Logical shift byte data of A to right
|
||||
{ "lsl", CF_CHG1|CF_USE2 }, // Logical shift byte data of A to left
|
||||
{ "asrw", CF_CHG1 }, // Arithmetic shift word data of A to right
|
||||
{ "asrw", CF_CHG1|CF_USE2 }, // Arithmetic shift word data of A to right
|
||||
{ "lsrw", CF_CHG1 }, // Logical shift word data of A to right
|
||||
{ "lsrw", CF_CHG1|CF_USE2 }, // Logical shift word data of A to right
|
||||
{ "lslw", CF_CHG1 }, // Logical shift word data of A to left
|
||||
{ "lslw", CF_CHG1|CF_USE2 }, // Logical shift word data of A to left
|
||||
{ "asrl", CF_CHG1|CF_USE2 }, // Arithmetic shift long word data of A to right
|
||||
{ "lsrl", CF_CHG1|CF_USE2 }, // Logical shift long word data of A to right
|
||||
{ "lsll", CF_CHG1|CF_USE2 }, // Logical shift long word data of A to left
|
||||
|
||||
// BRANCH INSTRUCTIONS
|
||||
|
||||
{ "bz", CF_USE1 }, // Branch if Zero
|
||||
{ "bnz", CF_USE1 }, // Branch if Not Zero
|
||||
{ "bc", CF_USE1 }, // Branch if Carry
|
||||
{ "bnc", CF_USE1 }, // Branch if Not Carry
|
||||
{ "bn", CF_USE1 }, // Branch if Negative
|
||||
{ "bp", CF_USE1 }, // Branch if Not Negative
|
||||
{ "bv", CF_USE1 }, // Branch if Overflow
|
||||
{ "bnv", CF_USE1 }, // Branch if Not Overflow
|
||||
{ "bt", CF_USE1 }, // Branch if Sticky
|
||||
{ "bnt", CF_USE1 }, // Branch if Not Sticky
|
||||
{ "blt", CF_USE1 }, // Branch if Overflow or Negative
|
||||
{ "bge", CF_USE1 }, // Branch if Not (Overflow or Negative)
|
||||
{ "ble", CF_USE1 }, // Branch if ( Overflow xor Negative ) or Zero
|
||||
{ "bgt", CF_USE1 }, // Branch if Not ((Overflow xor Negative) or Zero)
|
||||
{ "bls", CF_USE1 }, // Branch if Carry or Zero
|
||||
{ "bhi", CF_USE1 }, // Branch if Not (Carry or Zero)
|
||||
{ "bra", CF_USE1|CF_STOP }, // Branch unconditionally
|
||||
{ "jmp", CF_USE1|CF_STOP }, // Jump destination address
|
||||
{ "jmpp", CF_USE1|CF_STOP }, // Jump destination physical address
|
||||
{ "call", CF_USE1|CF_CALL }, // Call subroutine
|
||||
{ "callv", CF_USE1|CF_CALL }, // Call vectored subroutine
|
||||
{ "callp", CF_USE1|CF_CALL }, // Call physical address
|
||||
{ "cbne", CF_USE1|CF_USE2|CF_USE3 }, // Compare byte data and branch if not Equal
|
||||
{ "cwbne", CF_USE1|CF_USE2|CF_USE3 }, // Compare word data and branch if not Equal
|
||||
{ "dbnz", CF_CHG1|CF_USE2 }, // Decrement byte data and branch if not Zero
|
||||
{ "dwbnz", CF_CHG1|CF_USE2 }, // Decrement word data and branch if not Zero
|
||||
{ "int", CF_USE1|CF_CALL }, // Software interrupt
|
||||
{ "intp", CF_USE1|CF_CALL }, // Software interrupt
|
||||
{ "int9", CF_CALL }, // Software interrupt
|
||||
{ "reti", CF_STOP }, // Return from interrupt
|
||||
{ "link", CF_USE1 }, // Link and create new stack frame
|
||||
{ "unlink", 0 }, // Unlink and create new stack frame
|
||||
{ "ret", CF_STOP }, // Return from subroutine
|
||||
{ "retp", CF_STOP }, // Return from physical address
|
||||
|
||||
// OTHER INSTRUCTIONS
|
||||
|
||||
{ "pushw", CF_USE1 }, // Push to stack memory
|
||||
{ "popw", CF_CHG1 }, // Pop from stack memory
|
||||
{ "jctx", CF_USE1|CF_STOP }, // Jump context
|
||||
// F2MC_and,
|
||||
// F2MC_or,
|
||||
// F2MC_mov,
|
||||
{ "movea", CF_CHG1|CF_USE2 }, // Move effective address to destination
|
||||
{ "addsp", CF_USE1 }, // Add word data of SP and immediate data to SP
|
||||
// F2MC_mov,
|
||||
{ "nop", 0 }, // No operation
|
||||
{ "adb", 0 }, // ADB register
|
||||
{ "dtb", 0 }, // DTB register
|
||||
{ "pcb", 0 }, // PCB register
|
||||
{ "spb", 0 }, // SPB register
|
||||
{ "ncc", 0 }, // Flag change inhibit
|
||||
{ "cmr", 0 }, // Common register bank
|
||||
{ "movb", CF_CHG1|CF_USE2 }, // Move bit data
|
||||
{ "setb", CF_CHG1 }, // Set bit
|
||||
{ "clrb", CF_CHG1 }, // Clear bit
|
||||
{ "bbc", CF_USE1|CF_USE2 }, // Branch if bit condition satisfied
|
||||
{ "bbs", CF_USE1|CF_USE2 }, // Branch if bit condition satisfied
|
||||
{ "sbbs", CF_USE1|CF_USE2 }, // Set bit and branch if bit set
|
||||
{ "wbts", CF_USE1 }, // Wait until bit condition satisfied
|
||||
{ "wbtc", CF_USE1 }, // Wait until bit condition satisfied
|
||||
{ "swap", 0 }, // Swap byte data of A
|
||||
{ "swapw", 0 }, // Swap word data of A
|
||||
{ "ext", 0 }, // Sign extend from byte data to word data
|
||||
{ "extw", 0 }, // Sign extend from word data to long word data
|
||||
{ "zext", 0 }, // Zero extendfrom byte data to word data
|
||||
{ "zextw", 0 }, // Zero extendfrom word data to long word data
|
||||
{ "movsi", CF_USE1|CF_USE2 }, // Move string byte with addresses incremented
|
||||
{ "movsd", CF_USE1|CF_USE2 }, // Move string byte with addresses decremented
|
||||
{ "sceqi", 0 }, // Scan string byte until Equal with address incremented
|
||||
{ "sceqd", 0 }, // Scan string byte until Equal with address decremented
|
||||
{ "filsi", 0 }, // Fill string byte
|
||||
{ "movswi", CF_USE1|CF_USE2 }, // Move string word with address incremented
|
||||
{ "movswd", CF_USE1|CF_USE2 }, // Move string word with address decremented
|
||||
{ "scweqi", 0 }, // Scan string word until Equal with address incremented
|
||||
{ "scweqd", 0 }, // Scan string word until Equal with address decremented
|
||||
{ "filswi", 0 }, // Fill string word
|
||||
|
||||
// MACROS
|
||||
|
||||
{ "bz16", CF_USE1 }, // Branch if Zero
|
||||
{ "bnz16", CF_USE1 }, // Branch if Not Zero
|
||||
{ "bc16", CF_USE1 }, // Branch if Carry
|
||||
{ "bnc16", CF_USE1 }, // Branch if Not Carry
|
||||
{ "bn16", CF_USE1 }, // Branch if Negative
|
||||
{ "bp16", CF_USE1 }, // Branch if Not Negative
|
||||
{ "bv16", CF_USE1 }, // Branch if Overflow
|
||||
{ "bnv16", CF_USE1 }, // Branch if Not Overflow
|
||||
{ "bt16", CF_USE1 }, // Branch if Sticky
|
||||
{ "bnt16", CF_USE1 }, // Branch if Not Sticky
|
||||
{ "blt16", CF_USE1 }, // Branch if Overflow or Negative
|
||||
{ "bge16", CF_USE1 }, // Branch if Not (Overflow or Negative)
|
||||
{ "ble16", CF_USE1 }, // Branch if ( Overflow xor Negative ) or Zero
|
||||
{ "bgt16", CF_USE1 }, // Branch if Not ((Overflow xor Negative) or Zero)
|
||||
{ "bls16", CF_USE1 }, // Branch if Carry or Zero
|
||||
{ "bhi16", CF_USE1 }, // Branch if Not (Carry or Zero)
|
||||
|
||||
{ "cbne16", CF_USE1|CF_USE2|CF_USE3 }, // Compare byte data and branch if not Equal
|
||||
{ "cwbne16", CF_USE1|CF_USE2|CF_USE3 }, // Compare word data and branch if not Equal
|
||||
|
||||
{ "dbnz16", CF_CHG1|CF_USE2 }, // Decrement byte data and branch if not Zero
|
||||
{ "dwbnz16", CF_CHG1|CF_USE2 }, // Decrement word data and branch if not Zero
|
||||
|
||||
{ "bbc16", CF_USE1|CF_USE2 }, // Branch if bit condition satisfied
|
||||
{ "bbs16", CF_USE1|CF_USE2 }, // Branch if bit condition satisfied
|
||||
{ "sbbs16", CF_USE1|CF_USE2 }, // Set bit and branch if bit set
|
||||
|
||||
};
|
||||
|
||||
CASSERT(qnumber(Instructions) == F2MC_last);
|
||||
222
idasdk76/module/f2mc/ins.hpp
Normal file
222
idasdk76/module/f2mc/ins.hpp
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-2021 Hex-Rays
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __INSTRS_HPP
|
||||
#define __INSTRS_HPP
|
||||
|
||||
extern const instruc_t Instructions[];
|
||||
|
||||
enum nameNum
|
||||
{
|
||||
|
||||
F2MC_null = 0, // Unknown Operation
|
||||
|
||||
// TRANSFER INSTRUCTIONS
|
||||
|
||||
F2MC_mov, // Move byte data from source to destination
|
||||
F2MC_movn, // Move immediate nibble data to A
|
||||
F2MC_movx, // Move byte data with sign extension from source to A
|
||||
F2MC_xch, // Exchange byte data of source to destination
|
||||
F2MC_movw, // Move word data from source to destination
|
||||
F2MC_xchw, // Exchange word data of source to destination
|
||||
F2MC_movl, // Move long word data from source to destination
|
||||
|
||||
// NUMERIC DATA OPERATIONS INSTRUCTIONS
|
||||
|
||||
F2MC_add, // Add byte data of destination and source to destination
|
||||
F2MC_addc1, // Add byte data of AL and AH with Carry to AL
|
||||
F2MC_addc2, // Add byte data of A and effective address with Carry to A
|
||||
F2MC_adddc, // Add decimal data of AL and AH with Carry to AL
|
||||
F2MC_sub, // Subtract byte data of source from festination to destination
|
||||
F2MC_subc1, // Subtract byte data of AL from AH with Carry to AL
|
||||
F2MC_subc2, // Subtract byte data of effective address from A with Carry to A
|
||||
F2MC_subdc, // Subtract decimal data of AL from AH with Carry to AL
|
||||
F2MC_addw1, // Add word data of AH and AL to AL
|
||||
F2MC_addw2, // Add word data of destination and source to destination
|
||||
F2MC_addcw, // Add word data of A and effective address from A with Carry to A
|
||||
F2MC_subw1, // Subtract word data of AL from AH to AL
|
||||
F2MC_subw2, // Subtract word data of source from festination to destination
|
||||
F2MC_subcw, // Subtract word data of A and effective address from A with carry to A
|
||||
F2MC_addl, // Add long word data of destination and source to destination
|
||||
F2MC_subl, // Subtract long word data of source from festination to destination
|
||||
F2MC_inc, // Increment byte data
|
||||
F2MC_dec, // Decrement byte data
|
||||
F2MC_incw, // Increment word data
|
||||
F2MC_decw, // Decrement word data
|
||||
F2MC_incl, // Increment long word data
|
||||
F2MC_decl, // Decrement long word data
|
||||
F2MC_cmp1, // Compare byte data of AH and AL
|
||||
F2MC_cmp2, // Compare byte data of destination and source
|
||||
F2MC_cmpw1, // Compare word data of AH and AL
|
||||
F2MC_cmpw2, // Compare word data of destination and source
|
||||
F2MC_cmpl, // Compare long word data of destination and source
|
||||
F2MC_divu1, // Divide unsigned AH by AL
|
||||
F2MC_divu2, // Divide unsigned word data by unsigned byte data
|
||||
F2MC_divuw, // Divide unsigned long word data by unsigned word data
|
||||
F2MC_mulu1, // Multiply unsigned byte AH by AL
|
||||
F2MC_mulu2, // Multiply unsigned byte data
|
||||
F2MC_muluw1, // Multiply unsigned word AH by AL
|
||||
F2MC_muluw2, // Multiply unsigned word data
|
||||
F2MC_div1, // Divide AH by AL
|
||||
F2MC_div2, // Divide word data by byte data
|
||||
F2MC_divw, // Divide long word data by word data
|
||||
F2MC_mul1, // Multiply byte AH by AL
|
||||
F2MC_mul2, // Multiply byte data
|
||||
F2MC_mulw1, // Multiply word AH by AL
|
||||
F2MC_mulw2, // Multiply word data
|
||||
|
||||
// LOGICAL DATA OPERATION INSTRUCTIONS
|
||||
|
||||
F2MC_and, // And byte data of destination and source to destination
|
||||
F2MC_or, // Or byte data of destination and source to destination
|
||||
F2MC_xor, // Exclusive or byte data of destination and source to destination
|
||||
F2MC_not, // Not byte data of destination
|
||||
F2MC_andw1, // And word data of AH and AL to AL
|
||||
F2MC_andw2, // And word data of destination and source to destination
|
||||
F2MC_orw1, // Or word data of AH and AL to AL
|
||||
F2MC_orw2, // Or word data of destination and source to destination
|
||||
F2MC_xorw1, // Exclusive or word data of AH and AL to AL
|
||||
F2MC_xorw2, // Exclusive or word data of destination and source to destination
|
||||
F2MC_notw, // Not word data of destination
|
||||
F2MC_andl, // And long word data of destination and source to destination
|
||||
F2MC_orl, // Or long word data of destination and source to destination
|
||||
F2MC_xorl, // Exclusive or long word data of destination and source to destination
|
||||
F2MC_neg, // Negate byte data of destination
|
||||
F2MC_negw, // Negate word data of destination
|
||||
F2MC_nrml, // Normalize long word
|
||||
|
||||
// SHIFT INSTRUCTIONS
|
||||
|
||||
F2MC_rorc, // Rotate byte data of A with Carry to right
|
||||
F2MC_rolc, // Rotate byte data of A with Carry to left
|
||||
F2MC_asr, // Arithmetic shift byte data of A to right
|
||||
F2MC_lsr, // Logical shift byte data of A to right
|
||||
F2MC_lsl, // Logical shift byte data of A to left
|
||||
F2MC_asrw1, // Arithmetic shift word data of A to right
|
||||
F2MC_asrw2, // Arithmetic shift word data of A to right
|
||||
F2MC_lsrw1, // Logical shift word data of A to right
|
||||
F2MC_lsrw2, // Logical shift word data of A to right
|
||||
F2MC_lslw1, // Logical shift word data of A to left
|
||||
F2MC_lslw2, // Logical shift word data of A to left
|
||||
F2MC_asrl, // Arithmetic shift long word data of A to right
|
||||
F2MC_lsrl, // Logical shift long word data of A to right
|
||||
F2MC_lsll, // Logical shift long word data of A to left
|
||||
|
||||
// BRANCH INSTRUCTIONS
|
||||
|
||||
F2MC_bz, // Branch if Zero
|
||||
F2MC_bnz, // Branch if Not Zero
|
||||
F2MC_bc, // Branch if Carry
|
||||
F2MC_bnc, // Branch if Not Carry
|
||||
F2MC_bn, // Branch if Negative
|
||||
F2MC_bp, // Branch if Not Negative
|
||||
F2MC_bv, // Branch if Overflow
|
||||
F2MC_bnv, // Branch if Not Overflow
|
||||
F2MC_bt, // Branch if Sticky
|
||||
F2MC_bnt, // Branch if Not Sticky
|
||||
F2MC_blt, // Branch if Overflow or Negative
|
||||
F2MC_bge, // Branch if Not (Overflow or Negative)
|
||||
F2MC_ble, // Branch if (Overflow xor Negative) or Zero
|
||||
F2MC_bgt, // Branch if Not ((Overflow xor Negative) or Zero)
|
||||
F2MC_bls, // Branch if Carry or Zero
|
||||
F2MC_bhi, // Branch if Not (Carry or Zero)
|
||||
F2MC_bra, // Branch unconditionally
|
||||
F2MC_jmp, // Jump destination address
|
||||
F2MC_jmpp, // Jump destination physical address
|
||||
F2MC_call, // Call subroutine
|
||||
F2MC_callv, // Call vectored subroutine
|
||||
F2MC_callp, // Call physical address
|
||||
F2MC_cbne, // Compare byte data and branch if not Equal
|
||||
F2MC_cwbne, // Compare word data and branch if not Equal
|
||||
F2MC_dbnz, // Decrement byte data and branch if not Zero
|
||||
F2MC_dwbnz, // Decrement word data and branch if not Zero
|
||||
F2MC_int, // Software interrupt
|
||||
F2MC_intp, // Software interrupt
|
||||
F2MC_int9, // Software interrupt
|
||||
F2MC_reti, // Return from interrupt
|
||||
F2MC_link, // Link and create new stack frame
|
||||
F2MC_unlink, // Unlink and create new stack frame
|
||||
F2MC_ret, // Return from subroutine
|
||||
F2MC_retp, // Return from physical address
|
||||
|
||||
// OTHER INSTRUCTIONS
|
||||
|
||||
F2MC_pushw, // Push to stack memory
|
||||
F2MC_popw, // Pop from stack memory
|
||||
F2MC_jctx, // Jump context
|
||||
// F2MC_and,
|
||||
// F2MC_or,
|
||||
// F2MC_mov,
|
||||
F2MC_movea, // Move effective address to destination
|
||||
F2MC_addsp, // Add word data of SP and immediate data to SP
|
||||
// F2MC_mov,
|
||||
F2MC_nop, // No operation
|
||||
F2MC_adb, // ADB register
|
||||
F2MC_dtb, // DTB register
|
||||
F2MC_pcb, // PCB register
|
||||
F2MC_spb, // SPB register
|
||||
F2MC_ncc, // Flag change inhibit
|
||||
F2MC_cmr, // Common register bank
|
||||
F2MC_movb, // Move bit data
|
||||
F2MC_setb, // Set bit
|
||||
F2MC_clrb, // Clear bit
|
||||
F2MC_bbc, // Branch if bit condition satisfied
|
||||
F2MC_bbs, // Branch if bit condition satisfied
|
||||
F2MC_sbbs, // Set bit and branch if bit set
|
||||
F2MC_wbts, // Wait until bit condition satisfied
|
||||
F2MC_wbtc, // Wait until bit condition satisfied
|
||||
F2MC_swap, // Swap byte data of A
|
||||
F2MC_swapw, // Swap word data of A
|
||||
F2MC_ext, // Sign extend from byte data to word data
|
||||
F2MC_extw, // Sign extend from word data to long word data
|
||||
F2MC_zext, // Zero extendfrom byte data to word data
|
||||
F2MC_zextw, // Zero extendfrom word data to long word data
|
||||
F2MC_movsi, // Move string byte with addresses incremented
|
||||
F2MC_movsd, // Move string byte with addresses decremented
|
||||
F2MC_sceqi, // Scan string byte until Equal with address incremented
|
||||
F2MC_sceqd, // Scan string byte until Equal with address decremented
|
||||
F2MC_filsi, // Fill string byte
|
||||
F2MC_movswi, // Move string word with address incremented
|
||||
F2MC_movswd, // Move string word with address decremented
|
||||
F2MC_scweqi, // Scan string word until Equal with address incremented
|
||||
F2MC_scweqd, // Scan string word until Equal with address decremented
|
||||
F2MC_filswi, // Fill string word
|
||||
|
||||
// MACROS
|
||||
|
||||
F2MC_bz16, // Branch if Zero
|
||||
F2MC_bnz16, // Branch if Not Zero
|
||||
F2MC_bc16, // Branch if Carry
|
||||
F2MC_bnc16, // Branch if Not Carry
|
||||
F2MC_bn16, // Branch if Negative
|
||||
F2MC_bp16, // Branch if Not Negative
|
||||
F2MC_bv16, // Branch if Overflow
|
||||
F2MC_bnv16, // Branch if Not Overflow
|
||||
F2MC_bt16, // Branch if Sticky
|
||||
F2MC_bnt16, // Branch if Not Sticky
|
||||
F2MC_blt16, // Branch if Overflow or Negative
|
||||
F2MC_bge16, // Branch if Not (Overflow or Negative)
|
||||
F2MC_ble16, // Branch if (Overflow xor Negative) or Zero
|
||||
F2MC_bgt16, // Branch if Not ((Overflow xor Negative) or Zero)
|
||||
F2MC_bls16, // Branch if Carry or Zero
|
||||
F2MC_bhi16, // Branch if Not (Carry or Zero)
|
||||
|
||||
F2MC_cbne16, // Compare byte data and branch if not Equal
|
||||
F2MC_cwbne16, // Compare word data and branch if not Equal
|
||||
|
||||
F2MC_dbnz16, // Decrement byte data and branch if not Zero
|
||||
F2MC_dwbnz16, // Decrement word data and branch if not Zero
|
||||
|
||||
F2MC_bbc16, // Branch if bit condition satisfied
|
||||
F2MC_bbs16, // Branch if bit condition satisfied
|
||||
F2MC_sbbs16, // Set bit and branch if bit set
|
||||
|
||||
F2MC_last,
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
57
idasdk76/module/f2mc/makefile
Normal file
57
idasdk76/module/f2mc/makefile
Normal file
@@ -0,0 +1,57 @@
|
||||
PROC=f2mc
|
||||
CONFIGS=f2mc16l.cfg f2mc16lx.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 ana.cpp f2mc.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)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 emu.cpp f2mc.hpp 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)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 f2mc.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)frame.hpp $(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 f2mc.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 f2mc.hpp ins.hpp reg.cpp
|
||||
358
idasdk76/module/f2mc/out.cpp
Normal file
358
idasdk76/module/f2mc/out.cpp
Normal file
@@ -0,0 +1,358 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "f2mc.hpp"
|
||||
#include <frame.hpp>
|
||||
#include <segregs.hpp>
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
class out_f2mc_t : public outctx_t
|
||||
{
|
||||
out_f2mc_t(void) = delete; // not used
|
||||
public:
|
||||
void out_address(ea_t ea, const op_t &x);
|
||||
void out_reglist(ushort reglist);
|
||||
|
||||
bool out_operand(const op_t &x);
|
||||
void out_insn(void);
|
||||
};
|
||||
CASSERT(sizeof(out_f2mc_t) == sizeof(outctx_t));
|
||||
|
||||
DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_f2mc_t)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_f2mc_t::out_address(ea_t ea, const op_t &x)
|
||||
{
|
||||
if ( !out_name_expr(x, ea, x.addr & 0xffff) )
|
||||
{
|
||||
out_tagon(COLOR_ERROR);
|
||||
out_btoa(x.addr, 16);
|
||||
out_tagoff(COLOR_ERROR);
|
||||
remember_problem(PR_NONAME, insn.ea);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_f2mc_t::out_reglist(ushort reglist)
|
||||
{
|
||||
out_symbol('(');
|
||||
bool first = true;
|
||||
int i = 0;
|
||||
while ( i < 8 )
|
||||
{
|
||||
int size = 1;
|
||||
if ( (reglist>>i) & 1 )
|
||||
{
|
||||
while ( (i + size < 8) && ((reglist>>(i+size)) & 1 ) )
|
||||
size++;
|
||||
if ( first )
|
||||
first = false;
|
||||
else
|
||||
out_symbol(',');
|
||||
out_register(ph.reg_names[RW0+i]);
|
||||
if ( size > 1 )
|
||||
{
|
||||
out_symbol('-');
|
||||
out_register(ph.reg_names[RW0+i+size-1]);
|
||||
}
|
||||
}
|
||||
i+=size;
|
||||
}
|
||||
out_symbol(')');
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool f2mc_t::exist_bits(ea_t ea, int bitl, int bith)
|
||||
{
|
||||
for ( int i = bitl; i <= bith; i++ )
|
||||
{
|
||||
const char *name = find_bit(ea, i);
|
||||
if ( name != NULL && name[0] != '\0' )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// adjust to respect 16 bits an 32 bits definitions
|
||||
void f2mc_t::adjust_ea_bit(ea_t &ea, int &bit)
|
||||
{
|
||||
const char *name = find_sym(ea);
|
||||
if ( name != NULL && name[0] != '\0' )
|
||||
return;
|
||||
name = find_sym(ea-1);
|
||||
if ( name != NULL && name[0] != '\0' && exist_bits(ea-1, 8, 15) )
|
||||
{
|
||||
ea--;
|
||||
bit+=8;
|
||||
return;
|
||||
}
|
||||
name = find_sym(ea-2);
|
||||
if ( name != NULL && name[0] != '\0' && exist_bits(ea-2, 16, 31) )
|
||||
{
|
||||
ea-=2;
|
||||
bit+=16;
|
||||
return;
|
||||
}
|
||||
name = find_sym(ea-3);
|
||||
if ( name != NULL && name[0] != '\0' && exist_bits(ea-3, 16, 31) )
|
||||
{
|
||||
ea-=3;
|
||||
bit+=24;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int calc_outf(const op_t &x)
|
||||
{
|
||||
if ( x.type == o_imm )
|
||||
return OOFS_IFSIGN|OOFW_IMM;
|
||||
|
||||
QASSERT(10103, x.type == o_displ);
|
||||
if ( x.addr_dtyp == dt_byte )
|
||||
return OOF_ADDR|OOFS_NEEDSIGN|OOF_SIGNED|OOFW_8;
|
||||
if ( x.addr_dtyp == dt_word )
|
||||
return OOF_ADDR|OOFS_NEEDSIGN|OOF_SIGNED|OOFW_16;
|
||||
INTERR(10104);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool out_f2mc_t::out_operand(const op_t &x)
|
||||
{
|
||||
f2mc_t &pm = *static_cast<f2mc_t *>(procmod);
|
||||
ea_t ea;
|
||||
|
||||
if ( insn.prefix_bank && (insn.op_bank == x.n)
|
||||
&& (insn.prefix_bank != insn.default_bank) )
|
||||
{
|
||||
out_register(ph.reg_names[insn.prefix_bank]);
|
||||
out_symbol(':');
|
||||
}
|
||||
|
||||
for ( int i = 0; i < x.at; i++ )
|
||||
out_symbol('@');
|
||||
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_void:
|
||||
return 0;
|
||||
|
||||
case o_reg:
|
||||
out_register(ph.reg_names[x.reg]);
|
||||
break;
|
||||
|
||||
case o_near:
|
||||
case o_far:
|
||||
{
|
||||
ea_t addr = x.addr;
|
||||
if ( x.type == o_near )
|
||||
addr = calc_code_mem(insn, addr);
|
||||
out_address(addr, x);
|
||||
}
|
||||
break;
|
||||
|
||||
case o_imm:
|
||||
out_symbol('#');
|
||||
out_value(x, calc_outf(x));
|
||||
break;
|
||||
|
||||
case o_mem:
|
||||
{
|
||||
ea = calc_data_mem(x.addr);
|
||||
if ( x.addr_dtyp != 'i' ) // data address
|
||||
{
|
||||
if ( x.addr_dtyp )
|
||||
{
|
||||
out_symbol(x.addr_dtyp);
|
||||
out_symbol(':');
|
||||
}
|
||||
out_address(ea, x);
|
||||
if ( x.special_mode == MODE_BIT )
|
||||
{
|
||||
out_symbol(':');
|
||||
out_symbol('0' + x.byte_bit);
|
||||
}
|
||||
}
|
||||
else // IO address
|
||||
{
|
||||
int bit = x.byte_bit;
|
||||
out_symbol('i'); out_symbol(':');
|
||||
if ( x.special_mode == MODE_BIT )
|
||||
pm.adjust_ea_bit(ea, bit);
|
||||
const char *name = pm.find_sym(ea);
|
||||
if ( name != NULL && name[0] != '\0' )
|
||||
{
|
||||
out_addr_tag(ea);
|
||||
out_line(name, COLOR_IMPNAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_address(ea, x);
|
||||
}
|
||||
if ( x.special_mode == MODE_BIT )
|
||||
{
|
||||
name = pm.find_bit(ea,bit);
|
||||
if ( name != NULL && name[0] != '\0' )
|
||||
{
|
||||
out_symbol('_');
|
||||
out_line(name, COLOR_IMPNAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_symbol(':');
|
||||
out_tagon(COLOR_SYMBOL);
|
||||
out_btoa(bit, 10);
|
||||
out_tagoff(COLOR_SYMBOL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case o_phrase:
|
||||
out_register(ph.reg_names[x.reg]);
|
||||
switch ( x.special_mode )
|
||||
{
|
||||
case MODE_INC:
|
||||
out_symbol('+');
|
||||
break;
|
||||
case MODE_INDEX:
|
||||
out_symbol('+');
|
||||
out_register(ph.reg_names[x.f2mc_index]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case o_displ:
|
||||
out_register(ph.reg_names[x.reg]);
|
||||
out_value(x, calc_outf(x));
|
||||
break;
|
||||
|
||||
case o_reglist:
|
||||
out_reglist(x.reg);
|
||||
break;
|
||||
|
||||
default:
|
||||
error("interr: out");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_f2mc_t::out_insn(void)
|
||||
{
|
||||
out_mnemonic();
|
||||
out_one_operand(0);
|
||||
if ( insn.Op2.type != o_void )
|
||||
{
|
||||
out_symbol(',');
|
||||
out_char(' ');
|
||||
out_one_operand(1);
|
||||
if ( insn.Op3.type != o_void )
|
||||
{
|
||||
out_symbol(',');
|
||||
out_char(' ');
|
||||
out_one_operand(2);
|
||||
}
|
||||
}
|
||||
|
||||
out_immchar_cmts();
|
||||
flush_outbuf();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void f2mc_t::print_segment_register(outctx_t &ctx, int reg, sel_t value)
|
||||
{
|
||||
if ( reg == ph.reg_data_sreg )
|
||||
return;
|
||||
char buf[MAX_NUMBUF];
|
||||
btoa(buf, sizeof(buf), value);
|
||||
ctx.gen_cmt_line("assume %s = %s", ph.reg_names[reg], buf);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// function to produce assume directives
|
||||
//lint -esym(1764, ctx) could be made const
|
||||
void f2mc_t::f2mc_assumes(outctx_t &ctx)
|
||||
{
|
||||
ea_t ea = ctx.insn_ea;
|
||||
segment_t *seg = getseg(ea);
|
||||
if ( seg == NULL || (inf_get_outflags() & OFLG_GEN_ASSUME) == 0 )
|
||||
return;
|
||||
|
||||
for ( int i = ph.reg_first_sreg; i <= ph.reg_last_sreg; ++i )
|
||||
{
|
||||
if ( i == ph.reg_code_sreg )
|
||||
continue;
|
||||
sreg_range_t sra;
|
||||
if ( !get_sreg_range(&sra, ea, i) )
|
||||
continue;
|
||||
sel_t now = get_sreg(ea, i);
|
||||
bool seg_started = (ea == seg->start_ea);
|
||||
if ( seg_started || sra.start_ea == ea )
|
||||
{
|
||||
sreg_range_t prev_sra;
|
||||
bool prev_exists = get_sreg_range(&prev_sra, ea - 1, i);
|
||||
if ( seg_started || (prev_exists && get_sreg(prev_sra.start_ea, i) != now) )
|
||||
print_segment_register(ctx, i, now);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//lint -esym(1764, ctx) could be made const
|
||||
//lint -esym(818, Srange) could be made const
|
||||
void f2mc_t::f2mc_segstart(outctx_t &ctx, segment_t *Srange) const
|
||||
{
|
||||
if ( is_spec_segm(Srange->type) )
|
||||
return;
|
||||
|
||||
qstring sname;
|
||||
qstring sclas;
|
||||
get_visible_segm_name(&sname, Srange);
|
||||
get_segm_class(&sclas, Srange);
|
||||
|
||||
ctx.gen_printf(DEFAULT_INDENT,
|
||||
COLSTR(".section %s, %s", SCOLOR_ASMDIR),
|
||||
sname.c_str(),
|
||||
sclas == "CODE" ? "code"
|
||||
: sclas == "BSS" ? "data"
|
||||
: "const");
|
||||
if ( Srange->orgbase != 0 )
|
||||
{
|
||||
char buf[MAX_NUMBUF];
|
||||
btoa(buf, sizeof(buf), Srange->orgbase);
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void idaapi f2mc_segend(outctx_t &, segment_t *) {}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void f2mc_t::f2mc_header(outctx_t &ctx)
|
||||
{
|
||||
ctx.gen_header(GH_PRINT_PROC_AND_ASM, ioh.device.c_str(), ioh.deviceparams.c_str());
|
||||
ctx.gen_printf(0, "");
|
||||
ctx.gen_printf(0, COLSTR("#include <_ffmc16_a.asm>", SCOLOR_ASMDIR));
|
||||
ctx.gen_header_extra();
|
||||
ctx.gen_empty_line();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void f2mc_t::f2mc_footer(outctx_t &ctx) const
|
||||
{
|
||||
qstring nbuf = get_colored_name(inf_get_start_ea());
|
||||
const char *name = nbuf.c_str();
|
||||
ctx.gen_printf(DEFAULT_INDENT,
|
||||
COLSTR("%s",SCOLOR_ASMDIR) " " COLSTR("%s %s",SCOLOR_AUTOCMT),
|
||||
ash.end,
|
||||
ash.cmnt,
|
||||
name);
|
||||
}
|
||||
553
idasdk76/module/f2mc/reg.cpp
Normal file
553
idasdk76/module/f2mc/reg.cpp
Normal file
@@ -0,0 +1,553 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include "f2mc.hpp"
|
||||
#include <diskio.hpp>
|
||||
#include <segregs.hpp>
|
||||
int data_id;
|
||||
|
||||
static const proctype_t ptypes[] =
|
||||
{
|
||||
F2MC16L,
|
||||
F2MC16LX
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const char *const register_names[] =
|
||||
{
|
||||
"A", // accumulator
|
||||
"AL", // accumulator
|
||||
"AH", // accumulator
|
||||
"PC", // program counter
|
||||
"SP", // stack pointer
|
||||
"R0",
|
||||
"R1",
|
||||
"R2",
|
||||
"R3",
|
||||
"R4",
|
||||
"R5",
|
||||
"R6",
|
||||
"R7",
|
||||
"RW0",
|
||||
"RW1",
|
||||
"RW2",
|
||||
"RW3",
|
||||
"RW4",
|
||||
"RW5",
|
||||
"RW6",
|
||||
"RW7",
|
||||
"RL0",
|
||||
"RL1",
|
||||
"RL2",
|
||||
"RL3",
|
||||
|
||||
"PCB", // program bank register
|
||||
"DTB", // data bank register
|
||||
"ADB", // additional data bank register
|
||||
"SSB", // system stack bank register
|
||||
"USB", // user stack bank register
|
||||
"CCR", // condition code register
|
||||
"DPR", // direct page register
|
||||
"cs","ds", // virtual registers for code and data segments
|
||||
|
||||
"SPB", // stack pointer bank register
|
||||
"PS", // processor status
|
||||
"ILM", // interrupt level mask register
|
||||
"RP" // register bank pointer
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const uchar retcode_0[] = { 0x66 }; // retp
|
||||
static const uchar retcode_1[] = { 0x67 }; // ret
|
||||
static const uchar retcode_2[] = { 0x6B }; // reti
|
||||
|
||||
static const bytes_t retcodes[] =
|
||||
{
|
||||
{ sizeof(retcode_0), retcode_0 },
|
||||
{ sizeof(retcode_1), retcode_1 },
|
||||
{ sizeof(retcode_2), retcode_2 },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Fujitsu FASM
|
||||
//-----------------------------------------------------------------------
|
||||
static const asm_t fasm =
|
||||
{
|
||||
AS_N2CHR|AS_NCMAS|ASH_HEXF3|ASD_DECF0|ASO_OCTF1|ASB_BINF3|AS_ONEDUP,
|
||||
0,
|
||||
"Fujitsu FASM",
|
||||
0,
|
||||
NULL, // header lines
|
||||
".org", // org
|
||||
".end", // end
|
||||
|
||||
";", // comment string
|
||||
'"', // string delimiter
|
||||
'\'', // char delimiter
|
||||
"'\"", // special symbols in char and string constants
|
||||
|
||||
".ascii", // ascii string directive
|
||||
".data.b", // byte directive
|
||||
".data.w", // word directive
|
||||
".data.l", // 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
|
||||
NULL, // arrays (#h,#d,#v,#s(...)
|
||||
".res.b %s", // uninited arrays
|
||||
".equ", // equ
|
||||
NULL, // 'seg' prefix (example: push seg seg001)
|
||||
"$", // current IP (instruction pointer)
|
||||
NULL, // func_header
|
||||
NULL, // func_footer
|
||||
NULL, // "public" name keyword
|
||||
NULL, // "weak" name keyword
|
||||
NULL, // "extrn" name keyword
|
||||
NULL, // "comm" (communal variable)
|
||||
NULL, // get_type_name
|
||||
".align", // "align" keyword
|
||||
'(', ')', // lbrace, rbrace
|
||||
"%", // mod
|
||||
"&", // and
|
||||
"|", // or
|
||||
"^", // xor
|
||||
"~", // not
|
||||
"<<", // shl
|
||||
">>", // shr
|
||||
NULL, // sizeof
|
||||
};
|
||||
|
||||
static const asm_t *const asms[] = { &fasm, NULL };
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool f2mc_iohandler_t::area_processing(ea_t start, ea_t end, const char *name, const char *aclass)
|
||||
{
|
||||
const bool split = end > start && (end - start) > 0x10000;
|
||||
for ( ea_t chunk_ea = start; chunk_ea < end; chunk_ea += 0x10000 )
|
||||
{
|
||||
ea_t segbase = (chunk_ea >> 16) << 12;
|
||||
sel_t sel = allocate_selector(segbase);
|
||||
qstring nm(name);
|
||||
if ( split )
|
||||
nm.cat_sprnt("_%02X", uint32((chunk_ea >> 16) & 0xFF));
|
||||
ea_t chunk_end = chunk_ea + 0x10000;
|
||||
if ( chunk_end > end )
|
||||
chunk_end = end;
|
||||
add_segm(sel, chunk_ea, chunk_end, nm.c_str(), aclass);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
const char *f2mc_iohandler_t::iocallback(const ioports_t &iop, const char *line)
|
||||
{
|
||||
const char *ret = NULL;
|
||||
bool handled = false;
|
||||
int len;
|
||||
ea_t ea1;
|
||||
char word[MAXSTR];
|
||||
word[MAXSTR-1] = '\0';
|
||||
CASSERT(MAXSTR == 1024);
|
||||
if ( qsscanf(line, "interrupt %1023s %" FMT_EA "i%n", word, &ea1, &len) == 2 ) //lint !e706 nominally inconsistent format
|
||||
{
|
||||
if ( (respect_info & IORESP_INT) != 0 )
|
||||
{
|
||||
segment_t *s = getseg(ea1);
|
||||
ea_t proc;
|
||||
if ( s != NULL )
|
||||
{
|
||||
create_dword(ea1, 4);
|
||||
proc = get_dword(ea1);
|
||||
if ( proc != 0xFFFFFFFF )
|
||||
{
|
||||
op_plain_offset(ea1, 0, 0);
|
||||
add_entry(proc, proc, word, true);
|
||||
|
||||
const char *ptr = &line[len];
|
||||
ptr = skip_spaces(ptr);
|
||||
if ( ptr[0] != '\0' )
|
||||
set_cmt(ea1, ptr, true);
|
||||
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( !handled )
|
||||
ret = standard_callback(iop, line);
|
||||
return ret;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void f2mc_t::load_symbols(int _respect_info)
|
||||
{
|
||||
if ( cfgname != NULL )
|
||||
{
|
||||
ioh.deviceparams.qclear();
|
||||
ioh.respect_info = _respect_info;
|
||||
if ( !inf_like_binary() )
|
||||
ioh.respect_info &= ~2;
|
||||
ioh.ports.clear();
|
||||
iohandler_t::ioports_loader_t ldr(&ioh);
|
||||
read_ioports2(&ioh.ports, &ioh.device, cfgname, &ldr);
|
||||
if ( ioh.respect_info )
|
||||
{
|
||||
for ( int i=0; i < ioh.ports.size(); i++ )
|
||||
{
|
||||
ea_t ea = ioh.ports[i].address;
|
||||
create_byte(ea, 1);
|
||||
const char *name = ioh.ports[i].name.c_str();
|
||||
if ( !set_name(ea, name, SN_NOCHECK|SN_NOWARN|SN_NODUMMY) )
|
||||
set_cmt(ea, name, 0);
|
||||
else
|
||||
set_cmt(ea, ioh.ports[i].cmt.c_str(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *f2mc_t::find_sym(ea_t address)
|
||||
{
|
||||
const ioport_t *port = find_ioport(ioh.ports, address);
|
||||
return port ? port->name.c_str() : NULL;
|
||||
}
|
||||
|
||||
const char *f2mc_t::find_bit(ea_t address, int bit)
|
||||
{
|
||||
const ioport_bit_t *b = find_ioport_bit(ioh.ports, address, bit);
|
||||
return b ? b->name.c_str() : NULL;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void f2mc_t::f2mc_set_device_name(int _respect_info)
|
||||
{
|
||||
helper.supset(-1, ioh.device.c_str());
|
||||
load_symbols(_respect_info);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
void f2mc_t::choose_and_set_device(int flags)
|
||||
{
|
||||
iohandler_t::parse_area_line0_t cb(ioh);
|
||||
if ( choose_ioport_device2(&ioh.device, cfgname, &cb) )
|
||||
f2mc_set_device_name(flags);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
inline void f2mc_t::choose_device()
|
||||
{
|
||||
choose_and_set_device(IORESP_PORT|IORESP_INT);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static int idaapi choose_device_cb(int, form_actions_t &fa)
|
||||
{
|
||||
f2mc_t &pm = *(f2mc_t *)fa.get_ud();
|
||||
pm.choose_device();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
const char *f2mc_t::set_idp_options(
|
||||
const char *keyword,
|
||||
int value_type,
|
||||
const void * value,
|
||||
bool idb_loaded)
|
||||
{
|
||||
if ( keyword == NULL )
|
||||
{
|
||||
static const char form[] =
|
||||
"HELP\n"
|
||||
"F2MC specific options\n"
|
||||
"\n"
|
||||
" Use macro instructions\n"
|
||||
"\n"
|
||||
" If this option is on, IDA will try to combine several instructions\n"
|
||||
" into a macro instruction\n"
|
||||
" For example,\n"
|
||||
"\n"
|
||||
" sbbs data:7, $1\n"
|
||||
" bra $2\n"
|
||||
" $1:\n"
|
||||
" jmp LABEL\n"
|
||||
" $2:\n"
|
||||
"\n"
|
||||
" will be replaced by\n"
|
||||
"\n"
|
||||
" sbbs16 data:7, LABEL\n"
|
||||
"\n"
|
||||
"ENDHELP\n"
|
||||
"F2MC specific options\n"
|
||||
"%*\n"
|
||||
" <Use ~m~acro instructions:C>>\n"
|
||||
"\n"
|
||||
" <~C~hoose device name:B:0::>\n"
|
||||
"\n"
|
||||
"\n";
|
||||
CASSERT(sizeof(idpflags) == sizeof(ushort));
|
||||
ask_form(form, this, &idpflags, choose_device_cb);
|
||||
OK:
|
||||
if ( idb_loaded )
|
||||
save_idpflags();
|
||||
return IDPOPT_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( value_type != IDPOPT_BIT )
|
||||
return IDPOPT_BADTYPE;
|
||||
if ( streq(keyword, "F2MC_MACRO") )
|
||||
{
|
||||
setflag(idpflags, F2MC_MACRO, *(int*)value != 0);
|
||||
goto OK;
|
||||
}
|
||||
return IDPOPT_BADKEY;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void f2mc_t::load_from_idb()
|
||||
{
|
||||
idpflags = (ushort)helper.altval(-1);
|
||||
ioh.restore_device();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// 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(f2mc_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
ssize_t idaapi f2mc_t::on_event(ssize_t msgid, va_list va)
|
||||
{
|
||||
switch ( msgid )
|
||||
{
|
||||
case processor_t::ev_init:
|
||||
helper.create(PROCMOD_NODE_NAME);
|
||||
inf_set_wide_high_byte_first(true);
|
||||
break;
|
||||
|
||||
case processor_t::ev_term:
|
||||
ioh.ports.clear();
|
||||
clr_module_data(data_id);
|
||||
break;
|
||||
|
||||
case processor_t::ev_newfile: // new file loaded
|
||||
set_segm_name(get_first_seg(), "CODE");
|
||||
choose_and_set_device(IORESP_ALL);
|
||||
for ( int i = DTB; i <= rVds; i++ )
|
||||
{
|
||||
for ( segment_t *s=get_first_seg(); s != NULL; s=get_next_seg(s->start_ea) )
|
||||
set_default_sreg_value(s, i, 0);
|
||||
}
|
||||
save_idpflags();
|
||||
break;
|
||||
|
||||
case processor_t::ev_ending_undo:
|
||||
// restore ptype
|
||||
ptype = ptypes[ph.get_proc_index()];
|
||||
//fall through
|
||||
case processor_t::ev_oldfile: // old file loaded
|
||||
ioh.upgrade_device_index();
|
||||
load_from_idb();
|
||||
break;
|
||||
|
||||
case processor_t::ev_newprc: // new processor type
|
||||
{
|
||||
ptype = ptypes[va_arg(va, int)];
|
||||
// bool keep_cfg = va_argi(va, bool);
|
||||
switch ( ptype )
|
||||
{
|
||||
case F2MC16L:
|
||||
cfgname = "f2mc16l.cfg";
|
||||
break;
|
||||
case F2MC16LX:
|
||||
cfgname = "f2mc16lx.cfg";
|
||||
break;
|
||||
default:
|
||||
error("interr: setprc");
|
||||
}
|
||||
ioh.device.qclear();
|
||||
if ( get_first_seg() != NULL )
|
||||
choose_device();
|
||||
}
|
||||
break;
|
||||
|
||||
case processor_t::ev_out_header:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
f2mc_header(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_footer:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
f2mc_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 *);
|
||||
f2mc_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 *);
|
||||
f2mc_segend(*ctx, seg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_assumes:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
f2mc_assumes(*ctx);
|
||||
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_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_create_func_frame:
|
||||
{
|
||||
func_t *pfn = va_arg(va, func_t *);
|
||||
create_func_frame(pfn);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
#define FAMILY "Fujitsu F2MC:"
|
||||
|
||||
static const char *const shnames[] =
|
||||
{ "F2MC16L",
|
||||
"F2MC16LX",
|
||||
NULL
|
||||
};
|
||||
static const char *const lnames[] =
|
||||
{ FAMILY"Fujitsu F2MC 16L",
|
||||
"Fujitsu F2MC 16LX",
|
||||
NULL
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Processor Definition
|
||||
//-----------------------------------------------------------------------
|
||||
processor_t LPH =
|
||||
{
|
||||
IDP_INTERFACE_VERSION, // version
|
||||
PLFM_F2MC, // id
|
||||
// flag
|
||||
PRN_HEX
|
||||
| PR_SEGS
|
||||
| PR_SGROTHER,
|
||||
// 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,
|
||||
|
||||
register_names, // Register names
|
||||
qnumber(register_names), // Number of registers
|
||||
|
||||
DTB, // first. We don't start at PCB, because
|
||||
// PCB == cs, and the way to get addresses
|
||||
// right is not to modify PCB, but rather
|
||||
// create the segmentation correctly.
|
||||
rVds, // last
|
||||
1, // size of a segment register
|
||||
rVcs, rVds,
|
||||
|
||||
NULL, // No known code start sequences
|
||||
retcodes,
|
||||
|
||||
F2MC_null,
|
||||
F2MC_last,
|
||||
Instructions, // instruc
|
||||
0, // 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
|
||||
F2MC_ret, // Icode of return instruction. It is ok to give any of possible return instructions
|
||||
};
|
||||
Reference in New Issue
Block a user