update
This commit is contained in:
55281
idasdk75/module/78k0/78k0.cfg
Normal file
55281
idasdk75/module/78k0/78k0.cfg
Normal file
File diff suppressed because it is too large
Load Diff
66
idasdk75/module/78k0/78k0.hpp
Normal file
66
idasdk75/module/78k0/78k0.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* NEC 78K0 processor module for IDA.
|
||||
* Copyright (c) 2006 Konstantin Norvatoff, <konnor@bk.ru>
|
||||
* Freeware.
|
||||
*/
|
||||
|
||||
#ifndef _78K0_HPP
|
||||
#define _78K0_HPP
|
||||
|
||||
#include <ida.hpp>
|
||||
#include <idp.hpp>
|
||||
|
||||
#include "../idaidp.hpp"
|
||||
#include "ins.hpp"
|
||||
#include "../iohandler.hpp"
|
||||
|
||||
struct nec78k0_t : public procmod_t
|
||||
{
|
||||
netnode helper;
|
||||
iohandler_t ioh = iohandler_t(helper);
|
||||
bool flow = false; // stop flag
|
||||
|
||||
virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override;
|
||||
|
||||
bool nec_find_ioport_bit(outctx_t &ctx, int port, int bit);
|
||||
void N78K_header(outctx_t &ctx);
|
||||
int N78K_emu(const insn_t &insn);
|
||||
void handle_operand(const op_t &x, bool forced_op, bool isload, const insn_t &insn);
|
||||
void N78K_segstart(outctx_t &ctx, segment_t *Sarea) const;
|
||||
void N78K_footer(outctx_t &ctx) const;
|
||||
};
|
||||
bool idaapi out_opnd(outctx_t &ctx, const op_t &x);
|
||||
|
||||
// subtype of out format
|
||||
#define FormOut specflag1
|
||||
//o_mem, o_near
|
||||
#define FORM_OUT_VSK (0x01)
|
||||
// o_mem, o_reg, o_near
|
||||
#define FORM_OUT_SKOBA (0x02)
|
||||
// o_reg
|
||||
#define FORM_OUT_PLUS (0x04)
|
||||
#define FORM_OUT_DISP (0x08)
|
||||
#define FORM_OUT_REG (0x10)
|
||||
// o_bit
|
||||
#define FORM_OUT_HL (0x04)
|
||||
#define FORM_OUT_PSW (0x08)
|
||||
#define FORM_OUT_A (0x10)
|
||||
#define FORM_OUT_SFR (0x20)
|
||||
#define FORM_OUT_S_ADDR (0x40)
|
||||
// o_reg
|
||||
#define SecondReg specflag2
|
||||
|
||||
//bit operand
|
||||
#define o_bit o_idpspec0
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
enum N78K_registers { rX, rA, rC, rB, rE, rD, rL, rH, rAX, rBC, rDE, rHL,
|
||||
rPSW, rSP, bCY, rRB0, rRB1, rRB2, rRB3,
|
||||
rVcs, rVds };
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
int idaapi N78K_ana(insn_t *_insn);
|
||||
int idaapi N78K_emu(const insn_t &insn);
|
||||
|
||||
#endif
|
||||
|
||||
1491
idasdk75/module/78k0/ana.cpp
Normal file
1491
idasdk75/module/78k0/ana.cpp
Normal file
File diff suppressed because it is too large
Load Diff
102
idasdk75/module/78k0/emu.cpp
Normal file
102
idasdk75/module/78k0/emu.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* NEC 78K0 processor module for IDA.
|
||||
* Copyright (c) 2006 Konstantin Norvatoff, <konnor@bk.ru>
|
||||
* Freeware.
|
||||
*/
|
||||
|
||||
#include "78k0.hpp"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// usage/change of operands
|
||||
void nec78k0_t::handle_operand(const op_t &x, bool forced_op, bool isload, const insn_t &insn)
|
||||
{
|
||||
ea_t ea = map_code_ea(insn, x.addr, x.n);
|
||||
ea_t ev = map_code_ea(insn, x.value, x.n);
|
||||
switch ( x.type )
|
||||
{
|
||||
// unused!
|
||||
case o_void:
|
||||
break;
|
||||
|
||||
case o_reg:
|
||||
if ( forced_op )
|
||||
break;
|
||||
if ( is_off(get_flags(insn.ea), x.n) )
|
||||
insn.add_dref(ev, x.n, dr_O);
|
||||
break;
|
||||
|
||||
case o_imm: // immediate can't be changed
|
||||
if ( !isload )
|
||||
goto badTouch;
|
||||
// set immediate flag
|
||||
set_immd(insn.ea);
|
||||
// if not forced and not offset
|
||||
if ( !forced_op && is_off(get_flags(insn.ea), x.n) )
|
||||
insn.add_dref(ev, x.offb, dr_O); // it's an offset!
|
||||
break;
|
||||
|
||||
case o_mem:
|
||||
insn.create_op_data(ea, x);
|
||||
insn.add_dref(ea, x.offb, isload ? dr_R : dr_W);
|
||||
break;
|
||||
|
||||
|
||||
case o_near:// a call or jump
|
||||
if ( has_insn_feature(insn.itype, CF_CALL) )
|
||||
{
|
||||
// add a code xref
|
||||
insn.add_cref(ea, x.offb, fl_CN);
|
||||
flow = func_does_return(ea);
|
||||
}
|
||||
else
|
||||
{
|
||||
insn.add_cref(ea, x.offb, fl_JN);
|
||||
}
|
||||
break;
|
||||
|
||||
case o_bit:
|
||||
switch ( x.FormOut )
|
||||
{
|
||||
case FORM_OUT_S_ADDR:
|
||||
case FORM_OUT_SFR:
|
||||
insn.create_op_data(ea, x);
|
||||
insn.add_dref(ea, x.offb, isload ? dr_R : dr_W);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
// other - show a warning
|
||||
default:
|
||||
badTouch:
|
||||
warning("%a %s,%d: bad optype %d",
|
||||
insn.ea, insn.get_canon_mnem(ph),
|
||||
x.n, x.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// emulator
|
||||
int nec78k0_t::N78K_emu(const insn_t &insn)
|
||||
{
|
||||
uint32 Feature = insn.get_canon_feature(ph);
|
||||
// get operand types
|
||||
int flag1 = is_forced_operand(insn.ea, 0);
|
||||
int flag2 = is_forced_operand(insn.ea, 1);
|
||||
|
||||
flow = (Feature & CF_STOP) == 0;
|
||||
|
||||
// handle xrefs for the two operands
|
||||
if ( Feature & CF_USE1) handle_operand(insn.Op1, flag1, 1, insn);
|
||||
if ( Feature & CF_USE2) handle_operand(insn.Op2, flag2, 1, insn);
|
||||
// add xref to the queue
|
||||
if ( Feature & CF_JUMP )
|
||||
remember_problem(PR_JUMP, insn.ea);
|
||||
// handle changing operands
|
||||
if ( Feature & CF_CHG1) handle_operand(insn.Op1, flag1, 0, insn);
|
||||
if ( Feature & CF_CHG2) handle_operand(insn.Op2, flag2, 0, insn);
|
||||
// if not stop, continue with the next instruction
|
||||
if ( flow )
|
||||
add_cref(insn.ea, insn.ea + insn.size, fl_F);
|
||||
return 1;
|
||||
}
|
||||
91
idasdk75/module/78k0/ins.cpp
Normal file
91
idasdk75/module/78k0/ins.cpp
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* NEC 78K0 processor module for IDA.
|
||||
* Copyright (c) 2006 Konstantin Norvatoff, <konnor@bk.ru>
|
||||
* Freeware.
|
||||
*/
|
||||
|
||||
#include "78k0.hpp"
|
||||
|
||||
const instruc_t Instructions[] =
|
||||
{
|
||||
|
||||
{ "", 0 }, // Unknown Operation
|
||||
|
||||
{ "mov", CF_USE2 | CF_CHG1 }, // Move Byte Data Transfer
|
||||
{ "xch", CF_CHG1 | CF_CHG2 }, // Exchange Byte Data
|
||||
{ "movw", CF_USE2 | CF_CHG1 }, // Move Word Data Transfer / Word Data Transfer with Stack Pointer
|
||||
{ "xchw", CF_CHG1 | CF_CHG2 }, // Exchange Word Data
|
||||
|
||||
{ "add", CF_USE2 | CF_CHG1 }, // Add Byte Data Addition
|
||||
{ "addc", CF_USE2 | CF_CHG1 }, // Add with Carry Addition of Byte Data with Carry
|
||||
{ "sub", CF_USE2 | CF_CHG1 }, // Subtract Byte Data Subtraction
|
||||
{ "subc", CF_USE2 | CF_CHG1 }, // Subtract with Carry Subtraction of Byte Data with Carry
|
||||
{ "and", CF_USE2 | CF_CHG1 }, // And Logical Product of Byte Data
|
||||
{ "or", CF_USE2 | CF_CHG1 }, // Or Logical Sum of Byte Data
|
||||
{ "xor", CF_USE2 | CF_CHG1 }, // Exclusive Or Exclusive Logical Sum of Byte Data
|
||||
{ "cmp", CF_USE1 | CF_USE2 }, // Compare Byte Data Comparison
|
||||
|
||||
{ "addw", CF_USE2 | CF_CHG1 }, // Add Word Data Addition
|
||||
{ "subw", CF_USE2 | CF_CHG1 }, // Subtract Word Data Subtraction
|
||||
{ "cmpw", CF_USE1 | CF_USE2 }, // Compare Word Data Comparison
|
||||
|
||||
{ "mulu", 0 }, // Multiply Unsigned Multiplication of Data
|
||||
{ "divuw", 0 }, // Divide Unsigned Word Unsigned Division of Word Data
|
||||
|
||||
{ "inc", CF_CHG1 }, // Increment Byte Data Increment
|
||||
{ "dec", CF_CHG1 }, // Decrement Byte Data Decrement
|
||||
{ "incw", CF_CHG1 }, // Increment Word Data Increment
|
||||
{ "decw", CF_CHG1 }, // Decrement Word Data Decrement
|
||||
|
||||
{ "ror", CF_CHG1 }, // Rotate Right Byte Data Rotation to the Right
|
||||
{ "rol", CF_CHG1 }, // Rotate Left Byte Data Rotation to the Left
|
||||
{ "rorc", CF_CHG1 }, // Rotate Right with Carry Byte Data Rotation to the Right with Carry
|
||||
{ "rolc", CF_CHG1 }, // Rotate Left with Carry Byte Data Rotation to the Left with Carry
|
||||
{ "ror4", CF_CHG1 }, // Rotate Right Digit Digit Rotation to the Right
|
||||
{ "rol4", CF_CHG1 }, // Rotate Left Digit Digit Rotation to the Left
|
||||
|
||||
{ "adjba", 0 }, // Decimal Adjust Register for Addition Decimal Adjustment of Addition Result
|
||||
{ "adjbs", 0 }, // Decimal Adjust Register for Subtraction Decimal Adjustment of Subtraction Result
|
||||
|
||||
{ "mov1", CF_USE2 | CF_CHG1 }, // Move Single Bit 1 Bit Data Transfer
|
||||
{ "and1", CF_USE2 | CF_CHG1 }, // And Single Bit 1 Bit Data Logical Product
|
||||
{ "or1", CF_USE2 | CF_CHG1 }, // Or Single Bit 1 Bit Data Logical Sum
|
||||
{ "xor1", CF_USE2 | CF_CHG1 }, // Exclusive Or Single Bit 1 Bit Data Exclusive Logical Sum
|
||||
{ "set1", CF_CHG1 }, // Set Single Bit (Carry Flag) 1 Bit Data Set
|
||||
{ "clr1", CF_CHG1 }, // Clear Single Bit (Carry Flag) 1 Bit Data Clear
|
||||
{ "not1", CF_USE1 }, // Not Single Bit (Carry Flag) 1 Bit Data Logical Negation
|
||||
|
||||
{ "call", CF_USE1 | CF_CALL }, // Call Subroutine Call (16 Bit Direct)
|
||||
{ "callf", CF_USE1 | CF_CALL }, // Call Flag Subroutine Call (11 Bit Direct Specification)
|
||||
{ "callt", CF_USE1 | CF_CALL }, // Call Table Subroutine Call (Refer to the Call Table)
|
||||
{ "brk", 0 }, // Break Software Vectored Interrupt
|
||||
{ "ret", CF_STOP }, // Return Return from Subroutine
|
||||
{ "retb", CF_STOP }, // Return from Interrupt Return from Hardware Vectored Interrupt
|
||||
{ "reti", CF_STOP }, // Return from Break Return from Software Vectored Interrupt
|
||||
|
||||
{ "push", CF_USE1 }, // Push
|
||||
{ "pop", CF_USE1 }, // Pop
|
||||
|
||||
|
||||
{ "br", CF_USE1 | CF_STOP }, // Branch Unconditional Branch
|
||||
{ "bc", CF_USE1 }, // Branch if Carry Conditional Branch with Carry Flag (CY = 1)
|
||||
{ "bnc", CF_USE1 }, // Branch if Not Carry Conditional Branch with Carry Flag (CY = 0)
|
||||
{ "bz", CF_USE1 }, // Branch if Zero Conditional Branch with Zero Flag (Z = 1)
|
||||
{ "bnz", CF_USE1 }, // Branch if Not Zero Conditional Branch with Zero Flag (Z = 0)
|
||||
{ "bt", CF_USE1 | CF_USE2 }, // Branch if True Conditional Branch by Bit Test (Byte Data Bit = 1)
|
||||
{ "bf", CF_USE1 | CF_USE2 }, // Branch if False Conditional Branch by Bit Test (Byte Data Bit = 0)
|
||||
{ "btclr", CF_USE1 | CF_USE2 }, // Branch if True and Clear Conditional Branch and Clear by Bit Test (Byte Data Bit = 1)
|
||||
{ "dbnz", CF_CHG1 | CF_USE2 }, // Decrement and Branch if Not Zero Conditional Loop (R1!= 0)
|
||||
|
||||
{ "sel", CF_USE1 }, // Select Register Bank Register Bank Selection
|
||||
|
||||
|
||||
{ "nop", 0 }, // No Operation
|
||||
{ "EI", 0 }, // Enable Interrupt
|
||||
{ "DI", 0 }, // Disable Interrupt
|
||||
{ "HALT", 0 }, // HALT Mode Set
|
||||
{ "STOP", CF_STOP } // Stop Mode Set
|
||||
|
||||
};
|
||||
|
||||
CASSERT(qnumber(Instructions) == NEC_78K_0_last);
|
||||
95
idasdk75/module/78k0/ins.hpp
Normal file
95
idasdk75/module/78k0/ins.hpp
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* NEC 78K0 processor module for IDA.
|
||||
* Copyright (c) 2006 Konstantin Norvatoff, <konnor@bk.ru>
|
||||
* Freeware.
|
||||
*/
|
||||
|
||||
#ifndef __INSTRS_HPP
|
||||
#define __INSTRS_HPP
|
||||
|
||||
extern const instruc_t Instructions[];
|
||||
|
||||
enum nameNum ENUM_SIZE(uint16)
|
||||
{
|
||||
NEC_78K_0_null = 0, // Unknown Operation
|
||||
|
||||
NEC_78K_0_mov, // Move Byte Data Transfer
|
||||
NEC_78K_0_xch, // Exchange Byte Data
|
||||
NEC_78K_0_movw, // Move Word Data Transfer / Word Data Transfer with Stack Pointer
|
||||
NEC_78K_0_xchw, // Exchange Word Data
|
||||
|
||||
NEC_78K_0_add, // Add Byte Data Addition
|
||||
NEC_78K_0_addc, // Add with Carry Addition of Byte Data with Carry
|
||||
NEC_78K_0_sub, // Subtract Byte Data Subtraction
|
||||
NEC_78K_0_subc, // Subtract with Carry Subtraction of Byte Data with Carry
|
||||
NEC_78K_0_and, // And Logical Product of Byte Data
|
||||
NEC_78K_0_or, // Or Logical Sum of Byte Data
|
||||
NEC_78K_0_xor, // Exclusive Or Exclusive Logical Sum of Byte Data
|
||||
NEC_78K_0_cmp, // Compare Byte Data Comparison
|
||||
|
||||
NEC_78K_0_addw, // Add Word Data Addition
|
||||
NEC_78K_0_subw, // Subtract Word Data Subtraction
|
||||
NEC_78K_0_cmpw, // Compare Word Data Comparison
|
||||
|
||||
NEC_78K_0_mulu, // Multiply Unsigned Multiplication of Data
|
||||
NEC_78K_0_divuw, // Divide Unsigned Word Unsigned Division of Word Data
|
||||
|
||||
NEC_78K_0_inc, // Increment Byte Data Increment
|
||||
NEC_78K_0_dec, // Decrement Byte Data Decrement
|
||||
NEC_78K_0_incw, // Increment Word Data Increment
|
||||
NEC_78K_0_decw, // Decrement Word Data Decrement
|
||||
|
||||
NEC_78K_0_ror, // Rotate Right Byte Data Rotation to the Right
|
||||
NEC_78K_0_rol, // Rotate Left Byte Data Rotation to the Left
|
||||
NEC_78K_0_rorc, // Rotate Right with Carry Byte Data Rotation to the Right with Carry
|
||||
NEC_78K_0_rolc, // Rotate Left with Carry Byte Data Rotation to the Left with Carry
|
||||
NEC_78K_0_ror4, // Rotate Right Digit Digit Rotation to the Right
|
||||
NEC_78K_0_rol4, // Rotate Left Digit Digit Rotation to the Left
|
||||
|
||||
NEC_78K_0_adjba, // Decimal Adjust Register for Addition Decimal Adjustment of Addition Result
|
||||
NEC_78K_0_adjbs, // Decimal Adjust Register for Subtraction Decimal Adjustment of Subtraction Result
|
||||
|
||||
NEC_78K_0_mov1, // Move Single Bit 1 Bit Data Transfer
|
||||
NEC_78K_0_and1, // And Single Bit 1 Bit Data Logical Product
|
||||
NEC_78K_0_or1, // Or Single Bit 1 Bit Data Logical Sum
|
||||
NEC_78K_0_xor1, // Exclusive Or Single Bit 1 Bit Data Exclusive Logical Sum
|
||||
NEC_78K_0_set1, // Set Single Bit (Carry Flag) 1 Bit Data Set
|
||||
NEC_78K_0_clr1, // Clear Single Bit (Carry Flag) 1 Bit Data Clear
|
||||
NEC_78K_0_not1, // Not Single Bit (Carry Flag) 1 Bit Data Logical Negation
|
||||
|
||||
NEC_78K_0_call, // Call Subroutine Call (16 Bit Direct)
|
||||
NEC_78K_0_callf, // Call Flag Subroutine Call (11 Bit Direct Specification)
|
||||
NEC_78K_0_callt, // Call Table Subroutine Call (Refer to the Call Table)
|
||||
NEC_78K_0_brk, // Break Software Vectored Interrupt
|
||||
NEC_78K_0_ret, // Return Return from Subroutine
|
||||
NEC_78K_0_retb, // Return from Interrupt Return from Hardware Vectored Interrupt
|
||||
NEC_78K_0_reti, // Return from Break Return from Software Vectored Interrupt
|
||||
|
||||
NEC_78K_0_push, // Push
|
||||
NEC_78K_0_pop, // Pop
|
||||
|
||||
NEC_78K_0_br, // Branch Unconditional Branch
|
||||
NEC_78K_0_bc, // Branch if Carry Conditional Branch with Carry Flag (CY = 1)
|
||||
NEC_78K_0_bnc, // Branch if Not Carry Conditional Branch with Carry Flag (CY = 0)
|
||||
NEC_78K_0_bz, // Branch if Zero Conditional Branch with Zero Flag (Z = 1)
|
||||
NEC_78K_0_bnz, // Branch if Not Zero Conditional Branch with Zero Flag (Z = 0)
|
||||
NEC_78K_0_bt, // Branch if True Conditional Branch by Bit Test (Byte Data Bit = 1)
|
||||
NEC_78K_0_bf, // Branch if False Conditional Branch by Bit Test (Byte Data Bit = 0)
|
||||
NEC_78K_0_btclr, // Branch if True and Clear Conditional Branch and Clear by Bit Test (Byte Data Bit = 1)
|
||||
NEC_78K_0_dbnz, // Decrement and Branch if Not Zero Conditional Loop (R1!= 0)
|
||||
|
||||
NEC_78K_0_sel, // Select Register Bank Register Bank Selection
|
||||
|
||||
|
||||
NEC_78K_0_nop, // No Operation
|
||||
NEC_78K_0_EI, // Enable Interrupt
|
||||
NEC_78K_0_DI, // Disable Interrupt
|
||||
NEC_78K_0_HALT, // HALT Mode Set
|
||||
NEC_78K_0_STOP, // Stop Mode Set
|
||||
|
||||
|
||||
NEC_78K_0_last
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
46
idasdk75/module/78k0/makefile
Normal file
46
idasdk75/module/78k0/makefile
Normal file
@@ -0,0 +1,46 @@
|
||||
PROC=78k0
|
||||
CONFIGS=78k0.cfg
|
||||
|
||||
include ../module.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \
|
||||
$(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \
|
||||
$(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \
|
||||
78k0.hpp ana.cpp ins.hpp
|
||||
$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \
|
||||
$(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \
|
||||
$(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \
|
||||
78k0.hpp emu.cpp ins.hpp
|
||||
$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \
|
||||
$(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \
|
||||
$(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \
|
||||
78k0.hpp ins.cpp ins.hpp
|
||||
$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \
|
||||
$(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \
|
||||
$(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \
|
||||
78k0.hpp ins.hpp out.cpp
|
||||
$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \
|
||||
$(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \
|
||||
$(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \
|
||||
../iohandler.hpp 78k0.hpp ins.hpp reg.cpp
|
||||
242
idasdk75/module/78k0/out.cpp
Normal file
242
idasdk75/module/78k0/out.cpp
Normal file
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* NEC 78K0 processor module for IDA.
|
||||
* Copyright (c) 2006 Konstantin Norvatoff, <konnor@bk.ru>
|
||||
* Freeware.
|
||||
*/
|
||||
|
||||
#include "78k0.hpp"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
class out_N78K_t : public outctx_t
|
||||
{
|
||||
out_N78K_t(void) = delete; // not used
|
||||
public:
|
||||
void OutReg(int rgnum) { out_register(ph.reg_names[rgnum]); }
|
||||
void OutVarName(const op_t &x);
|
||||
void OutVarNameVal(const op_t &x);
|
||||
|
||||
bool out_operand(const op_t &x);
|
||||
void out_insn(void);
|
||||
};
|
||||
CASSERT(sizeof(out_N78K_t) == sizeof(outctx_t));
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void idaapi out_insn(outctx_t &ctx)
|
||||
{
|
||||
out_N78K_t *p = (out_N78K_t *)&ctx;
|
||||
p->out_insn();
|
||||
}
|
||||
|
||||
bool idaapi out_opnd(outctx_t &ctx, const op_t &x)
|
||||
{
|
||||
out_N78K_t *p = (out_N78K_t *)&ctx;
|
||||
return p->out_operand(x);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_N78K_t::OutVarName(const op_t &x)
|
||||
{
|
||||
ushort addr = ushort(x.addr);
|
||||
ea_t toea = map_code_ea(insn, addr, x.n);
|
||||
if ( !out_name_expr(x, toea, addr) )
|
||||
out_value(x, OOF_ADDR | OOFW_16);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_N78K_t::OutVarNameVal(const op_t &x)
|
||||
{
|
||||
ushort addr = ushort(x.value);
|
||||
ea_t toea = map_code_ea(insn, addr, x.n);
|
||||
if ( !out_name_expr(x, toea, addr) )
|
||||
out_value(x, OOFW_16);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool out_N78K_t::out_operand(const op_t &x)
|
||||
{
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_void:
|
||||
return 0;
|
||||
case o_reg:
|
||||
if ( x.FormOut & FORM_OUT_SKOBA )
|
||||
out_symbol('[');
|
||||
OutReg(x.reg);
|
||||
if ( x.FormOut & FORM_OUT_PLUS )
|
||||
out_symbol('+');
|
||||
if ( x.FormOut & FORM_OUT_DISP )
|
||||
{
|
||||
if ( is_off(F, x.n) )
|
||||
OutVarNameVal(x);
|
||||
else
|
||||
out_value(x, OOFW_IMM);
|
||||
}
|
||||
if ( x.FormOut & FORM_OUT_REG )
|
||||
out_keyword(ph.reg_names[uchar(x.SecondReg)]);
|
||||
if ( x.FormOut & FORM_OUT_SKOBA )
|
||||
out_symbol(']');
|
||||
break;
|
||||
|
||||
case o_bit:
|
||||
switch ( x.FormOut )
|
||||
{
|
||||
case FORM_OUT_S_ADDR:
|
||||
case FORM_OUT_SFR:
|
||||
{
|
||||
OutVarName(x);
|
||||
out_symbol('.');
|
||||
nec78k0_t &pm = *static_cast<nec78k0_t *>(procmod);
|
||||
if ( !pm.nec_find_ioport_bit(*this, (int)x.addr, (int)x.value) )
|
||||
out_value(x, OOFW_IMM);
|
||||
}
|
||||
break;
|
||||
|
||||
case FORM_OUT_A:
|
||||
out_line("A.");
|
||||
out_value(x, OOFW_IMM);
|
||||
break;
|
||||
|
||||
case FORM_OUT_PSW:
|
||||
out_line("PSW.");
|
||||
switch ( x.value )
|
||||
{
|
||||
case 0: out_line("CY"); break;
|
||||
case 1: out_line("ISP"); break;
|
||||
case 3: out_line("RBS0"); break;
|
||||
case 4: out_line("AC"); break;
|
||||
case 5: out_line("RBS1"); break;
|
||||
case 6: out_line("Z"); break;
|
||||
case 7: out_line("IE"); break;
|
||||
default:out_value(x, OOFW_IMM); break;
|
||||
}
|
||||
break;
|
||||
|
||||
case FORM_OUT_HL:
|
||||
out_symbol('[');
|
||||
OutReg(rHL);
|
||||
out_symbol(']');
|
||||
out_symbol('.');
|
||||
if ( is_off(F, x.n) )
|
||||
OutVarNameVal(x);
|
||||
else
|
||||
out_value(x, OOFW_IMM);
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case o_imm:
|
||||
out_symbol('#');
|
||||
if ( is_off(F, x.n) )
|
||||
OutVarNameVal(x);
|
||||
else
|
||||
out_value(x, OOFW_IMM);
|
||||
break;
|
||||
|
||||
case o_mem:
|
||||
// output variable name from the memory (for example byte_98)
|
||||
if ( x.FormOut & FORM_OUT_VSK )
|
||||
out_symbol('!');
|
||||
if ( x.FormOut & FORM_OUT_SKOBA )
|
||||
out_symbol('[');
|
||||
// output memory name
|
||||
OutVarName(x);
|
||||
if ( x.FormOut & FORM_OUT_SKOBA )
|
||||
out_symbol(']');
|
||||
break;
|
||||
|
||||
case o_near:
|
||||
if ( x.FormOut & FORM_OUT_VSK )
|
||||
out_symbol('!');
|
||||
if ( x.FormOut & FORM_OUT_SKOBA )
|
||||
out_symbol('[');
|
||||
{
|
||||
ea_t adr = map_code_ea(insn, x);
|
||||
if ( !out_name_expr(x, adr, x.addr) )
|
||||
{
|
||||
out_value(x, OOF_ADDR | OOF_NUMBER | OOFW_16);
|
||||
remember_problem(PR_NONAME, insn.ea);
|
||||
}
|
||||
}
|
||||
if ( x.FormOut & FORM_OUT_SKOBA )
|
||||
out_symbol(']');
|
||||
break;
|
||||
|
||||
default:
|
||||
INTERR(10130);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_N78K_t::out_insn(void)
|
||||
{
|
||||
out_mnemonic();
|
||||
|
||||
if ( insn.Op1.type != o_void )
|
||||
out_one_operand(0);
|
||||
if ( insn.Op2.type != o_void )
|
||||
{
|
||||
out_symbol(',');
|
||||
out_char(' ');
|
||||
out_one_operand(1);
|
||||
}
|
||||
out_immchar_cmts();
|
||||
flush_outbuf();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void nec78k0_t::N78K_header(outctx_t &ctx)
|
||||
{
|
||||
ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX, ioh.device.c_str(), ioh.deviceparams.c_str());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//lint -esym(1764, ctx) could be made const
|
||||
//lint -esym(818, Sarea) could be made const
|
||||
void nec78k0_t::N78K_segstart(outctx_t &ctx, segment_t *Sarea) const
|
||||
{
|
||||
const char *SegType = Sarea->type == SEG_CODE ? "CSEG"
|
||||
: Sarea->type == SEG_DATA ? "DSEG"
|
||||
: "RSEG";
|
||||
// line: RSEG <NAME>
|
||||
qstring sn;
|
||||
get_visible_segm_name(&sn, Sarea);
|
||||
ctx.gen_printf(-1,"%s %s ", SegType, sn.c_str());
|
||||
// if non-zero offfset output it (ORG XXXX)
|
||||
if ( (inf_get_outflags() & OFLG_GEN_ORG) != 0 )
|
||||
{
|
||||
ea_t org = ctx.insn_ea - get_segm_base(Sarea);
|
||||
if ( org != 0 )
|
||||
{
|
||||
char bufn[MAX_NUMBUF];
|
||||
btoa(bufn, sizeof(bufn), org);
|
||||
ctx.gen_printf(-1, "%s %s", ash.origin, bufn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void nec78k0_t::N78K_footer(outctx_t &ctx) const
|
||||
{
|
||||
if ( ash.end != NULL )
|
||||
{
|
||||
ctx.gen_empty_line();
|
||||
ctx.out_line(ash.end, COLOR_ASMDIR);
|
||||
qstring name;
|
||||
if ( get_colored_name(&name, inf_get_start_ea()) > 0 )
|
||||
{
|
||||
size_t i = strlen(ash.end);
|
||||
do
|
||||
ctx.out_char(' ');
|
||||
while ( ++i < 8 );
|
||||
ctx.out_line(name.begin());
|
||||
}
|
||||
ctx.flush_outbuf(DEFAULT_INDENT);
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.gen_cmt_line("end of file");
|
||||
}
|
||||
}
|
||||
|
||||
279
idasdk75/module/78k0/reg.cpp
Normal file
279
idasdk75/module/78k0/reg.cpp
Normal file
@@ -0,0 +1,279 @@
|
||||
/*
|
||||
* NEC 78K0 processor module for IDA.
|
||||
* Copyright (c) 2006 Konstantin Norvatoff, <konnor@bk.ru>
|
||||
* Freeware.
|
||||
*/
|
||||
|
||||
#include "78k0.hpp"
|
||||
#include <diskio.hpp>
|
||||
#include <segregs.hpp>
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static const char *const RegNames[] =
|
||||
{
|
||||
"X", "A", "C", "B", "E", "D", "L", "H", "AX", "BC", "DE","HL",
|
||||
"PSW", "SP", "CY", "RB0", "RB1", "RB2", "RB3",
|
||||
"cs", "ds"
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static const asm_t nec78k0 =
|
||||
{
|
||||
AS_COLON | ASB_BINF4 | AS_N2CHR,
|
||||
0,
|
||||
"NEC 78K0 Assembler",
|
||||
0,
|
||||
NULL,
|
||||
".org",
|
||||
".end",
|
||||
|
||||
";", // comment string
|
||||
'"', // string delimiter
|
||||
'\'', // char delimiter
|
||||
"'\"", // special symbols in char and string constants
|
||||
|
||||
".db", // ascii string directive
|
||||
".db", // byte directive
|
||||
".dw", // word directive
|
||||
".dd", // no double words
|
||||
NULL, // no qwords
|
||||
NULL, // oword (16 bytes)
|
||||
NULL, // no float
|
||||
NULL, // no double
|
||||
NULL, // no tbytes
|
||||
NULL, // no packreal
|
||||
"#d dup(#v)", //".db.#s(b,w) #d,#v", // #h - header(.byte,.word)
|
||||
// #d - size of array
|
||||
// #v - value of array elements
|
||||
// #s - size specifier
|
||||
".rs %s",// uninited data (reserve space)
|
||||
".equ",
|
||||
NULL, // seg prefix
|
||||
"$", // a_curip
|
||||
|
||||
NULL, // returns function header line
|
||||
NULL, // returns function footer line
|
||||
NULL, // public
|
||||
NULL, // weak
|
||||
NULL, // extrn
|
||||
NULL, // comm
|
||||
NULL, // get_type_name
|
||||
NULL, // align
|
||||
|
||||
'(', ')',// lbrace, rbrace
|
||||
NULL, // mod
|
||||
NULL, // and
|
||||
NULL, // or
|
||||
NULL, // xor
|
||||
NULL, // not
|
||||
NULL, // shl
|
||||
NULL, // shr
|
||||
NULL, // sizeof
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
#define FAMILY "NEC series:"
|
||||
static const char *const shnames[] =
|
||||
{
|
||||
"78k0",
|
||||
NULL
|
||||
};
|
||||
static const char *const lnames[] =
|
||||
{
|
||||
FAMILY"NEC 78K0",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const asm_t *const asms[] =
|
||||
{
|
||||
&nec78k0,
|
||||
NULL
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const uchar retcNEC78K0_0[] = { 0xAF }; //ret
|
||||
static const uchar retcNEC78K0_1[] = { 0x9F }; //retb
|
||||
static const uchar retcNEC78K0_2[] = { 0x8F }; //reti
|
||||
static const uchar retcNEC78K0_3[] = { 0xBF }; //brk
|
||||
static const bytes_t retcodes[] =
|
||||
{
|
||||
{ sizeof(retcNEC78K0_0), retcNEC78K0_0 },
|
||||
{ sizeof(retcNEC78K0_1), retcNEC78K0_1 },
|
||||
{ sizeof(retcNEC78K0_2), retcNEC78K0_2 },
|
||||
{ sizeof(retcNEC78K0_3), retcNEC78K0_3 },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// This old-style callback only returns the processor module object.
|
||||
static ssize_t idaapi notify(void *, int msgid, va_list)
|
||||
{
|
||||
if ( msgid == processor_t::ev_get_procmod )
|
||||
return size_t(new nec78k0_t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
bool nec78k0_t::nec_find_ioport_bit(outctx_t &ctx, int port, int bit)
|
||||
{
|
||||
|
||||
const ioport_bit_t *b = find_ioport_bit(ioh.ports, port, bit);
|
||||
if ( b != NULL && !b->name.empty() )
|
||||
{
|
||||
ctx.out_line(b->name.c_str(), COLOR_IMPNAME);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
void set_dopolnit_info(void)
|
||||
{
|
||||
for ( int banknum = 0; banknum < 4; banknum++ )
|
||||
{
|
||||
for ( int Regs = 0; Regs < 8; Regs++ )
|
||||
{
|
||||
char temp[100];
|
||||
qsnprintf(temp, sizeof(temp), "Bank%d_%s", banknum, RegNames[Regs]);
|
||||
ushort Addr = ushort(0xFEE0+((banknum*8)+Regs));
|
||||
set_name(Addr, temp);
|
||||
qsnprintf(temp, sizeof(temp), "Internal high-speed RAM (Bank %d registr %s)", banknum, RegNames[Regs]);
|
||||
set_cmt(Addr, temp, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
ssize_t idaapi nec78k0_t::on_event(ssize_t msgid, va_list va)
|
||||
{
|
||||
switch ( msgid )
|
||||
{
|
||||
case processor_t::ev_init:
|
||||
inf_set_be(false);
|
||||
inf_set_gen_lzero(true);
|
||||
helper.create("$ 78k0");
|
||||
break;
|
||||
|
||||
case processor_t::ev_term:
|
||||
ioh.ports.clear();
|
||||
break;
|
||||
|
||||
case processor_t::ev_newfile:
|
||||
{
|
||||
char cfgfile[QMAXFILE];
|
||||
ioh.get_cfg_filename(cfgfile, sizeof(cfgfile));
|
||||
iohandler_t::parse_area_line0_t cb(ioh);
|
||||
if ( choose_ioport_device2(&ioh.device, cfgfile, &cb) )
|
||||
ioh.set_device_name(ioh.device.c_str(), IORESP_ALL);
|
||||
set_dopolnit_info();
|
||||
}
|
||||
break;
|
||||
|
||||
case processor_t::ev_ending_undo:
|
||||
case processor_t::ev_oldfile:
|
||||
ioh.restore_device();
|
||||
break;
|
||||
|
||||
case processor_t::ev_creating_segm:
|
||||
{
|
||||
segment_t *s = va_arg(va, segment_t *);
|
||||
// Set default value of DS register for all segments
|
||||
set_default_dataseg(s->sel);
|
||||
}
|
||||
break;
|
||||
|
||||
case processor_t::ev_out_header:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
N78K_header(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_footer:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
N78K_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 *);
|
||||
N78K_segstart(*ctx, seg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_ana_insn:
|
||||
{
|
||||
insn_t *out = va_arg(va, insn_t *);
|
||||
return N78K_ana(out);
|
||||
}
|
||||
|
||||
case processor_t::ev_emu_insn:
|
||||
{
|
||||
const insn_t *insn = va_arg(va, const insn_t *);
|
||||
return N78K_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;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Processor Definition
|
||||
//-----------------------------------------------------------------------
|
||||
processor_t LPH =
|
||||
{
|
||||
IDP_INTERFACE_VERSION, // version
|
||||
PLFM_NEC_78K0,
|
||||
// flag
|
||||
PRN_HEX
|
||||
| PR_SEGTRANS
|
||||
| PR_SEGS,
|
||||
// flag2
|
||||
0,
|
||||
8, // 8 bits in a byte for code segments
|
||||
8, // 8 bits in a byte
|
||||
|
||||
shnames,
|
||||
lnames,
|
||||
|
||||
asms,
|
||||
|
||||
notify,
|
||||
|
||||
RegNames, // Regsiter names
|
||||
qnumber(RegNames), // Number of registers
|
||||
|
||||
rVcs, rVds,
|
||||
2, // size of a segment register
|
||||
rVcs, rVds,
|
||||
NULL,
|
||||
retcodes,
|
||||
0, NEC_78K_0_last,
|
||||
Instructions, // instruc
|
||||
3,
|
||||
{ 0,0,0,0 },
|
||||
0,
|
||||
NULL, // micro virtual mashine
|
||||
};
|
||||
Reference in New Issue
Block a user