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

1217
idasdk76/module/f2mc/ana.cpp Normal file

File diff suppressed because it is too large Load Diff

View 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;
}

View 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 &pm;
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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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);

View 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

View 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

View 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);
}

View 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
};