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

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,299 @@
/*
* Interactive disassembler (IDA).
* Copyright (c) 1990-2021 Hex-Rays
* ALL RIGHTS RESERVED.
*
*/
#include "ins.hpp"
const instruc_t Instructions[NEC850_LAST_INSTRUCTION] =
{
{ "", 0 }, // Unknown Operation
{ "breakpoint", CF_STOP }, // undefined instruction
{ "xori", CF_USE1|CF_USE2|CF_CHG3 }, // Exclusive Or Immediate
{ "xor", CF_USE1|CF_USE2|CF_CHG2 }, // Exclusive OR
{ "tst1", CF_USE1|CF_USE2 }, // Test bit
{ "tst", CF_USE1|CF_USE2 }, // Test
{ "trap", CF_USE1 }, // Software trap
{ "subr", CF_USE1|CF_USE2|CF_CHG2 }, // Substract reverse
{ "sub", CF_USE1|CF_USE2|CF_CHG2 }, // Substract
{ "stsr", CF_USE1|CF_CHG2 }, // Store Contents of System Register
{ "st.b", CF_USE1|CF_USE2|CF_CHG2 }, // Store byte
{ "st.h", CF_USE1|CF_USE2|CF_CHG2 }, // Store half-word
{ "st.w", CF_USE1|CF_USE2|CF_CHG2 }, // Store word
{ "sst.b", CF_USE1|CF_USE2|CF_CHG2 }, // Store byte (use EP)
{ "sst.h", CF_USE1|CF_USE2|CF_CHG2 }, // Store half-word (use EP)
{ "sst.w", CF_USE1|CF_USE2|CF_CHG2 }, // Store word (use EP)
{ "sld.b", CF_USE1|CF_CHG2 }, // Load byte (use EP)
{ "sld.h", CF_USE1|CF_CHG2 }, // Load half-word (use EP)
{ "sld.w", CF_USE1|CF_CHG2 }, // Load word (use EP)
{ "shr", CF_USE1|CF_USE2|CF_CHG2|CF_SHFT }, // Shift Logical Right
{ "shl", CF_USE1|CF_USE2|CF_CHG2|CF_SHFT }, // Shift Logical Left
{ "set1", CF_USE1|CF_USE2|CF_CHG2 }, // Set Bit
{ "setf", CF_USE1|CF_CHG2 }, // Set register to 1 if condition is satisfied
{ "satsubr", CF_USE1|CF_USE2|CF_CHG2 }, // Saturated Subtract Reverse
{ "satsubi", CF_USE1|CF_USE2|CF_CHG3 }, // Saturated Subtract Immediate
{ "satsub", CF_USE1|CF_USE2|CF_CHG2 }, // Saturated Subtract
{ "satadd", CF_USE1|CF_USE2|CF_CHG2 }, // Saturated Add
{ "sar", CF_USE1|CF_USE2|CF_CHG2|CF_SHFT }, // Shift Arithmetic Right
{ "reti", CF_STOP }, // Return from Trap or Interrupt
{ "ori", CF_USE1|CF_USE2|CF_CHG2 }, // OR immediate
{ "or", CF_USE1|CF_USE2|CF_CHG2 }, // OR
{ "not1", CF_USE1|CF_USE2|CF_CHG2 }, // Not Bit
{ "not", CF_USE1|CF_USE2|CF_CHG2 }, // Not
{ "nop", 0 }, // No Operation
{ "mulhi", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Half-Word Immediate
{ "mulh", CF_USE1|CF_USE2|CF_CHG2 }, // Multiply Half-Word
{ "movhi", CF_USE1|CF_USE2|CF_CHG3 }, // Move High Half-Word
{ "movea", CF_USE1|CF_USE2|CF_CHG3 }, // Move Effective Address
{ "mov", CF_USE1|CF_CHG2 }, // Move
{ "ldsr", CF_USE1|CF_CHG2 }, // Load to system register
{ "ld.b", CF_USE1|CF_CHG2 }, // Load byte
{ "ld.h", CF_USE1|CF_CHG2 }, // Load half-word
{ "ld.w", CF_USE1|CF_CHG2 }, // Load word
{ "jr", CF_USE1|CF_STOP }, // Jump Relative
{ "jmp", CF_USE1|CF_JUMP|CF_STOP }, // Jump Register
{ "jarl", CF_CALL|CF_USE1|CF_CHG2 }, // Jump and Register Link
{ "halt", CF_STOP }, // Halt
{ "ei", 0 }, // Enable interrupt
{ "divh", CF_USE1|CF_USE2|CF_CHG2 }, // Divide Half-Word
{ "di", 0 }, // Disable Interrupt
{ "cmp", CF_USE1|CF_USE2 }, // Compare
{ "clr1", CF_USE1|CF_USE2|CF_CHG2 }, // Clear bit
{ "bv", CF_USE1 }, // Branch if overflow
{ "bl", CF_USE1 }, // Branch if less
{ "bz", CF_USE1 }, // Branch if zero
{ "bnh", CF_USE1 }, // Branch if not higher
{ "bn", CF_USE1 }, // Branch if negative
{ "br", CF_USE1|CF_STOP }, // Branch if always
{ "blt", CF_USE1 }, // Branch if less than (signed)
{ "ble", CF_USE1 }, // Branch if less than or equal (signed)
{ "bnv", CF_USE1 }, // Branch if no overflow
{ "bnc", CF_USE1 }, // Branch if no carry
{ "bnz", CF_USE1 }, // Branch if not zero
{ "bh", CF_USE1 }, // Branch if higher than
{ "bp", CF_USE1 }, // Branch if positive
{ "bsa", CF_USE1 }, // Branch if saturated
{ "bge", CF_USE1 }, // Branch if greater than or equal (signed)
{ "bgt", CF_USE1 }, // Branch if greater than (signed)
{ "andi", CF_USE1|CF_USE2|CF_CHG3 }, // And immediate
{ "and", CF_USE1|CF_USE2|CF_CHG2 }, // And
{ "addi", CF_USE1|CF_USE2|CF_CHG3 }, // Add Immediate
{ "add", CF_USE1|CF_USE2|CF_CHG2 }, // Add
//
// V850E/E1/ES
//
{ "switch", CF_USE1|CF_STOP|CF_JUMP }, // Jump with table look up
{ "zxb", CF_USE1|CF_CHG1 }, //
{ "sxb", CF_USE1|CF_CHG1 }, //
{ "zxh", CF_USE1|CF_CHG1 }, //
{ "sxh", CF_USE1|CF_CHG1 }, //
{ "dispose", CF_USE1|CF_USE2 }, //
{ "dispose", CF_USE1|CF_USE2|CF_USE3|CF_STOP }, //
{ "callt", CF_USE1|CF_CALL }, //
{ "dbtrap", CF_STOP }, //
{ "dbret", CF_STOP }, //
{ "ctret", CF_STOP }, //
{ "sasf", CF_USE1|CF_USE2|CF_CHG2 }, // Shift and set flag condition
{ "prepare", CF_USE1|CF_USE2|CF_USE3 }, // Function prepare
{ "prepare", CF_USE1|CF_USE2 }, // Function prepare
{ "mul", CF_USE1|CF_USE2|CF_CHG2|CF_CHG3 }, // Multiply word
{ "mulu", CF_USE1|CF_USE2|CF_CHG2|CF_CHG3 }, // Multiply word unsigned
{ "divh", CF_USE1|CF_USE2|CF_CHG2|CF_CHG3 }, // Divide halfword
{ "divhu", CF_USE1|CF_USE2|CF_CHG2|CF_CHG3 }, // Divide halfword unsigned
{ "div", CF_USE1|CF_USE2|CF_CHG2|CF_CHG3 }, // Divide word
{ "divu", CF_USE1|CF_USE2|CF_CHG2|CF_CHG3 }, // Divide word unsigned
{ "bsw", CF_USE1|CF_CHG2 }, // Byte swap word
{ "bsh", CF_USE1|CF_CHG2 }, // Byte swap halfword
{ "hsw", CF_USE1|CF_CHG2 }, // Halfword swap word
{ "cmov", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Conditional move
{ "sld.bu", CF_USE1|CF_CHG2 }, // Short format load byte unsigned
{ "sld.hu", CF_USE1|CF_CHG2 }, // Short format load halfword unsigned
{ "ld.bu", CF_USE1|CF_CHG2 }, // load byte unsigned
{ "ld.hu", CF_USE1|CF_CHG2 }, // load halfword unsigned
//
// V850E2
//
{ "adf", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Add on condition flag
{ "hsh", CF_USE1|CF_CHG2 }, // Halfword swap halfword
{ "mac", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Multiply and add word
{ "macu", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Multiply and add word unsigned
{ "sbf", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Subtract on condition flag
{ "sch0l", CF_USE1|CF_CHG2 }, // Search zero from left
{ "sch0r", CF_USE1|CF_CHG2 }, // Search zero from right
{ "sch1l", CF_USE1|CF_CHG2 }, // Search one from left
{ "sch1r", CF_USE1|CF_CHG2 }, // Search one from right
//
// V850E2M
//
{ "caxi", CF_USE1|CF_USE2|CF_USE3 }, // Compare and exchange for interlock
{ "divq", CF_USE1|CF_USE2|CF_CHG2|CF_CHG3 }, // Divide word quickly
{ "divqu", CF_USE1|CF_USE2|CF_CHG2|CF_CHG3 }, // Divide word unsigned quickly
{ "eiret", CF_STOP }, // Return from EI level exception
{ "feret", CF_STOP }, // Return from FE level exception
{ "fetrap", CF_USE1 }, // FE-level Trap
{ "rmtrap", 0 }, // Runtime monitor trap
{ "rie", CF_STOP|CF_USE1|CF_USE2 }, // Reserved instruction exception
{ "synce", 0 }, // Synchronize exceptions
{ "syncm", 0 }, // Synchronize memory
{ "syncp", 0 }, // Synchronize pipeline
{ "syscall", CF_USE1 }, // System call
// floating point (E1F only)
{ "cvt.sw", CF_USE1|CF_CHG2 }, // Real to integer conversion
{ "trnc.sw", CF_USE1|CF_CHG2 }, // Real to integer conversion
{ "cvt.ws", CF_USE1|CF_CHG2 }, // Integer to real conversion
{ "ldfc", CF_USE1|CF_CHG2 }, // Load to Floating Controls
{ "ldff", CF_USE1|CF_CHG2 }, // Load to Floating Flags
{ "stfc", CF_USE1|CF_CHG2 }, // Store Floating Controls
{ "stff", CF_USE1|CF_CHG2 }, // Store Floating Flags
{ "trff", 0 }, // Transfer Floating Flags
// floating point (E2M+)
{ "absf.d", CF_USE1|CF_CHG2 }, // Floating-point Absolute Value (Double)
{ "absf.s", CF_USE1|CF_CHG2 }, // Floating-point Absolute Value (Single)
{ "addf.d", CF_USE1|CF_CHG2 }, // Floating-point Add (Double)
{ "addf.s", CF_USE1|CF_CHG2 }, // Floating-point Add (Single)
{ "divf.d", CF_USE1|CF_CHG2 }, // Floating-point Divide (Double)
{ "divf.s", CF_USE1|CF_CHG2 }, // Floating-point Divide (Single)
{ "maxf.d", CF_USE1|CF_CHG2 }, // Floating-point Maximum (Double)
{ "maxf.s", CF_USE1|CF_CHG2 }, // Floating-point Maximum (Single)
{ "minf.d", CF_USE1|CF_CHG2 }, // Floating-point Minimum (Double)
{ "minf.s", CF_USE1|CF_CHG2 }, // Floating-point Minimum (Single)
{ "mulf.d", CF_USE1|CF_CHG2 }, // Floating-point Multiply (Double)
{ "mulf.s", CF_USE1|CF_CHG2 }, // Floating-point Multiply (Single)
{ "negf.d", CF_USE1|CF_CHG2 }, // Floating-point Negate (Double)
{ "negf.s", CF_USE1|CF_CHG2 }, // Floating-point Negate (Single)
{ "recipf.d", CF_USE1|CF_CHG2 }, // Reciprocal of a floating-point value (Double)
{ "recipf.s", CF_USE1|CF_CHG2 }, // Reciprocal of a floating-point value (Single
{ "rsqrtf.d", CF_USE1|CF_CHG2 }, // Reciprocal of the square root of a floating-point value (Double)
{ "rsqrtf.s", CF_USE1|CF_CHG2 }, // Reciprocal of the square root of a floating-point value (Single)
{ "sqrtf.d", CF_USE1|CF_CHG2 }, // Floating-point Square Root (Double)
{ "sqrtf.s", CF_USE1|CF_CHG2 }, // Floating-point Square Root (Single)
{ "subf.d", CF_USE1|CF_CHG2 }, // Floating-point Subtract (Double)
{ "subf.s", CF_USE1|CF_CHG2 }, // Floating-point Subtract (Single)
{ "maddf.s", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Floating-point Multiply-Add (Single)
{ "msubf.s", CF_USE1|CF_CHG2|CF_USE3|CF_CHG4 }, // Floating-point Multiply-Subtract (Single)
{ "nmaddf.s", CF_USE1|CF_CHG2|CF_USE3|CF_CHG4 }, // Floating-point Negate Multiply-Add (Single)
{ "nmsubf.s", CF_USE1|CF_CHG2|CF_USE3|CF_CHG4 }, // Floating-point Negate Multiply-Subtract (Single)
{ "ceilf.dl", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Long Fixed-point Format, rounded toward +inf (Double)
{ "ceilf.dw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Single Fixed-point Format, rounded toward +inf (Double)
{ "ceilf.sl", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Long Fixed-point Format, rounded toward +inf (Single)
{ "ceilf.sw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Single Fixed-point Format, rounded toward +inf (Single)
{ "ceilf.dul", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Unsigned Long, rounded toward +inf (Double)
{ "ceilf.duw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Unsigned Word, rounded toward +inf (Double)
{ "ceilf.sul", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Unsigned Long, rounded toward +inf (Single)
{ "ceilf.suw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Unsigned Word, rounded toward +inf (Single)
{ "cvtf.dl", CF_USE1|CF_CHG2 }, // Floating-point Convert to Long Fixed-point Format (Double)
{ "cvtf.ds", CF_USE1|CF_CHG2 }, // Floating-point Convert to Single Floating-point Format (Double)
{ "cvtf.dul", CF_USE1|CF_CHG2 }, // Floating-point Convert Double to Unsigned-Long (Double)
{ "cvtf.duw", CF_USE1|CF_CHG2 }, // Floating-point Convert Double to Unsigned-Word (Double)
{ "cvtf.dw", CF_USE1|CF_CHG2 }, // Floating-point Convert to Single Fixed-point Format (Double)
{ "cvtf.ld", CF_USE1|CF_CHG2 }, // Floating-point Convert to Single Floating-point Format (Double)
{ "cvtf.ls", CF_USE1|CF_CHG2 }, // Floating-point Convert to Single Floating-point Format (Single)
{ "cvtf.sd", CF_USE1|CF_CHG2 }, // Floating-point Convert to Double Floating-point Format (Double)
{ "cvtf.sl", CF_USE1|CF_CHG2 }, // Floating-point Convert to Long Fixed-point Format (Single)
{ "cvtf.sul", CF_USE1|CF_CHG2 }, // Floating-point Convert Single to Unsigned-Long (Single)
{ "cvtf.suw", CF_USE1|CF_CHG2 }, // Floating-point Convert Single to Unsigned-Word (Single)
{ "cvtf.sw", CF_USE1|CF_CHG2 }, // Floating-point Convert to Single Fixed-point Format (Single)
{ "cvtf.uld", CF_USE1|CF_CHG2 }, // Floating-point Convert Unsigned-Long to Double (Double)
{ "cvtf.uls", CF_USE1|CF_CHG2 }, // Floating-point Convert Unsigned-Long to Single (Single)
{ "cvtf.uwd", CF_USE1|CF_CHG2 }, // Floating-point Convert Unsigned-Word to Double (Double)
{ "cvtf.uws", CF_USE1|CF_CHG2 }, // Floating-point Convert Unsigned-Word to Single (Single)
{ "cvtf.wd", CF_USE1|CF_CHG2 }, // Floating-point Convert to Single Floating-point Format (Double)
{ "cvtf.ws", CF_USE1|CF_CHG2 }, // Floating-point Convert to Single Floating-point Format (Single)
{ "floorf.dl", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Long Fixed-point Format, rounded toward -inf (Double)
{ "floorf.dw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Single Fixed-point Format, rounded toward -inf (Double)
{ "floorf.sl", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Long Fixed-point Format, rounded toward -inf (Single)
{ "floorf.sw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Single Fixed-point Format, rounded toward -inf (Single)
{ "floorf.dul", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Unsigned Long, rounded toward -inf (Double)
{ "floorf.duw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Unsigned Word, rounded toward -inf (Double)
{ "floorf.sul", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Unsigned Long, rounded toward -inf (Single)
{ "floorf.suw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Unsigned Word, rounded toward -inf (Single)
{ "trncf.dl", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Long Fixed-point Format, rounded to zero (Double)
{ "trncf.dul", CF_USE1|CF_CHG2 }, // Floating-point Truncate Double to Unsigned-Long (Double)
{ "trncf.duw", CF_USE1|CF_CHG2 }, // Floating-point Truncate Double to Unsigned-Word (Double)
{ "trncf.dw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Single Fixed-point Format, rounded to zero (Double)
{ "trncf.sl", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Long Fixed-point Format, rounded to zero (Single)
{ "trncf.sul", CF_USE1|CF_CHG2 }, // Floating-point Truncate Single to Unsigned-Long (Single)
{ "trncf.suw", CF_USE1|CF_CHG2 }, // Floating-point Truncate Single to Unsigned-Word (Single)
{ "trncf.sw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Single Fixed-point Format, rounded to zero (Single)
{ "cmpf.s", CF_USE1|CF_CHG2 }, // Compares floating-point values (Single)
{ "cmpf.d", CF_USE1|CF_CHG2 }, // Compares floating-point values (Double)
{ "cmovf.s", CF_USE1|CF_CHG2 }, // Floating-point conditional move (Single)
{ "cmovf.d", CF_USE1|CF_CHG2 }, // Floating-point conditional move (Double)
{ "trfsr", CF_USE1|CF_CHG2 }, // Transfers specified CC bit to Zero flag in PSW (Single)
//
// RH850
//
{ "synci", 0 }, // Synchronize instruction pipeline
{ "snooze", 0 }, // Snooze
{ "bins", CF_USE1|CF_USE2|CF_USE3|CF_USE4|CF_CHG4 }, // Bitfield Insert
{ "rotl", CF_USE1|CF_USE2|CF_CHG3 }, // Rotate Left
{ "loop", CF_USE1|CF_USE2 }, // Loop
{ "ld.dw", CF_USE1|CF_CHG2 }, // Load Double Word
{ "st.dw", CF_USE1|CF_USE2|CF_CHG2 }, // Store Double Word
{ "ldl.w", CF_USE1|CF_CHG2 }, // Load Linked
{ "stc.w", CF_USE1|CF_USE2|CF_CHG2 }, // Store Conditional
{ "cll", 0 }, // Clear Load Link
{ "cache", CF_USE1|CF_USE2 }, // Cache operation
{ "pref", CF_USE1|CF_USE2 }, // Prefetch
{ "pushsp", CF_USE1 }, // Push registers to Stack
{ "popsp", CF_CHG1 }, // Pop registers from Stack
// new RH850 FP instructions
{ "cvtf.hs", CF_USE1|CF_CHG2 }, // Floating-point Convert Half to Single (Single)
{ "cvtf.sh", CF_USE1|CF_CHG2 }, // Floating-point Convert Single to Half (Single)
{ "fmaf.s", CF_USE1|CF_USE2|CF_CHG3 }, // Floating-point Fused-Multiply-add (Single)
{ "fmsf.s", CF_USE1|CF_USE2|CF_CHG3 }, // Floating-point Fused-Multiply-subtract (Single)
{ "fnmaf.s", CF_USE1|CF_USE2|CF_CHG3 }, // Floating-point Fused-Negate-Multiply-add (Single)
{ "fnmsf.s", CF_USE1|CF_USE2|CF_CHG3 }, // Floating-point Fused-Negate-Multiply-subtract (Single)
// debug instructions
{ "dbpush", CF_USE1 }, // Output registers as software trace data
{ "dbcp", 0 }, // Output current PC value as software trace data
{ "dbtag", CF_USE1 }, // Output immediate value as software trace data
{ "dbhvtrap", 0 }, // Debug hypervisor trap
{ "est", 0 }, //
{ "dst", 0 }, //
{ "hvtrap", CF_USE1 }, // Hypervisor trap
{ "hvcall", CF_USE1 }, // Hypervisor call
{ "ldvc.sr", CF_USE1|CF_USE2 }, //
{ "stvc.sr", CF_USE1|CF_USE2 }, //
{ "ldtc.gr", CF_USE1|CF_USE2 }, //
{ "sttc.gr", CF_USE1|CF_USE2 }, //
{ "ldtc.pc", CF_USE1|CF_USE2 }, //
{ "sttc.pc", CF_USE1|CF_USE2 }, //
{ "ldtc.sr", CF_USE1|CF_USE2 }, //
{ "sttc.sr", CF_USE1|CF_USE2 }, //
{ "ldtc.vr", CF_USE1|CF_USE2 }, //
{ "sttc.vr", CF_USE1|CF_USE2 }, //
// TLB instructions
{ "tlbai", 0 }, //
{ "tlbr", 0 }, //
{ "tlbs", 0 }, //
{ "tlbvi", 0 }, //
{ "tlbw", 0 }, //
};
CASSERT(qnumber(Instructions) == NEC850_LAST_INSTRUCTION);

View File

@@ -0,0 +1,310 @@
/*
* Interactive disassembler (IDA).
* Copyright (c) 1990-2021 Hex-Rays
* ALL RIGHTS RESERVED.
*
*/
#ifndef __INSTRS_HPP
#define __INSTRS_HPP
#include "necv850.hpp"
//----------------------------------------------------------------------
extern const instruc_t Instructions[];
enum NEC850_Instructions
{
NEC850_NULL = 0,
NEC850_BREAKPOINT,
NEC850_XORI,
NEC850_XOR,
NEC850_TST1,
NEC850_TST,
NEC850_TRAP,
NEC850_SUBR,
NEC850_SUB,
NEC850_STSR,
NEC850_ST_B,
NEC850_ST_H,
NEC850_ST_W,
NEC850_SST_B,
NEC850_SST_H,
NEC850_SST_W,
NEC850_SLD_B,
NEC850_SLD_H,
NEC850_SLD_W,
NEC850_SHR,
NEC850_SHL,
NEC850_SET1,
NEC850_SETF,
NEC850_SATSUBR,
NEC850_SATSUBI,
NEC850_SATSUB,
NEC850_SATADD,
NEC850_SAR,
NEC850_RETI,
NEC850_ORI,
NEC850_OR,
NEC850_NOT1,
NEC850_NOT,
NEC850_NOP,
NEC850_MULHI,
NEC850_MULH,
NEC850_MOVHI,
NEC850_MOVEA,
NEC850_MOV,
NEC850_LDSR,
NEC850_LD_B,
NEC850_LD_H,
NEC850_LD_W,
NEC850_JR,
NEC850_JMP,
NEC850_JARL,
NEC850_HALT,
NEC850_EI,
NEC850_DIVH,
NEC850_DI,
NEC850_CMP,
NEC850_CLR1,
NEC850_BV,
NEC850_BL,
NEC850_BZ,
NEC850_BNH,
NEC850_BN,
NEC850_BR,
NEC850_BLT,
NEC850_BLE,
NEC850_BNV,
NEC850_BNC,
NEC850_BNZ,
NEC850_BH,
NEC850_BP,
NEC850_BSA,
NEC850_BGE,
NEC850_BGT,
NEC850_ANDI,
NEC850_AND,
NEC850_ADDI,
NEC850_ADD,
//
// V850E/E1/ES
//
NEC850_SWITCH,
NEC850_ZXB,
NEC850_SXB,
NEC850_ZXH,
NEC850_SXH,
NEC850_DISPOSE_r0,
NEC850_DISPOSE_r,
NEC850_CALLT,
NEC850_DBTRAP,
NEC850_DBRET,
NEC850_CTRET,
NEC850_SASF,
NEC850_PREPARE_sp,
NEC850_PREPARE_i,
NEC850_MUL,
NEC850_MULU,
NEC850_DIVH_r3,
NEC850_DIVHU,
NEC850_DIV,
NEC850_DIVU,
NEC850_BSW,
NEC850_BSH,
NEC850_HSW,
NEC850_CMOV,
NEC850_SLD_BU,
NEC850_SLD_HU,
NEC850_LD_BU,
NEC850_LD_HU,
//
// V850E2
//
NEC850_ADF, // Add on condition flag
NEC850_HSH, // Halfword swap halfword
NEC850_MAC, // Multiply and add word
NEC850_MACU, // Multiply and add word unsigned
NEC850_SBF, // Subtract on condition flag
NEC850_SCH0L, // Search zero from left
NEC850_SCH0R, // Search zero from right
NEC850_SCH1L, // Search one from left
NEC850_SCH1R, // Search one from right
//
// V850E2M
//
NEC850_CAXI, // Compare and exchange for interlock
NEC850_DIVQ, // Divide word quickly
NEC850_DIVQU, // Divide word unsigned quickly
NEC850_EIRET, // Return from EI level exception
NEC850_FERET, // Return from FE level exception
NEC850_FETRAP, // FE-level Trap
NEC850_RMTRAP, // Runtime monitor trap
NEC850_RIE, // Reserved instruction exception
NEC850_SYNCE, // Synchronize exceptions
NEC850_SYNCM, // Synchronize memory
NEC850_SYNCP, // Synchronize pipeline
NEC850_SYSCALL, // System call
// floating point (E1F only)
NEC850_CVT_SW, // Real to integer conversion
NEC850_TRNC_SW, // Real to integer conversion
NEC850_CVT_WS, // Integer to real conversion
NEC850_LDFC, // Load to Floating Controls
NEC850_LDFF, // Load to Floating Flags
NEC850_STFC, // Store Floating Controls
NEC850_STFF, // Store Floating Flags
NEC850_TRFF, // Transfer Floating Flags
// floating point (E2M)
NEC850_ABSF_D, // Floating-point Absolute Value (Double)
NEC850_ABSF_S, // Floating-point Absolute Value (Single)
NEC850_ADDF_D, // Floating-point Add (Double)
NEC850_ADDF_S, // Floating-point Add (Single)
NEC850_DIVF_D, // Floating-point Divide (Double)
NEC850_DIVF_S, // Floating-point Divide (Single)
NEC850_MAXF_D, // Floating-point Maximum (Double)
NEC850_MAXF_S, // Floating-point Maximum (Single)
NEC850_MINF_D, // Floating-point Minimum (Double)
NEC850_MINF_S, // Floating-point Minimum (Single)
NEC850_MULF_D, // Floating-point Multiply (Double)
NEC850_MULF_S, // Floating-point Multiply (Single)
NEC850_NEGF_D, // Floating-point Negate (Double)
NEC850_NEGF_S, // Floating-point Negate (Single)
NEC850_RECIPF_D, // Reciprocal of a floating-point value (Double)
NEC850_RECIPF_S, // Reciprocal of a floating-point value (Single
NEC850_RSQRTF_D, // Reciprocal of the square root of a floating-point value (Double)
NEC850_RSQRTF_S, // Reciprocal of the square root of a floating-point value (Single)
NEC850_SQRTF_D, // Floating-point Square Root (Double)
NEC850_SQRTF_S, // Floating-point Square Root (Single)
NEC850_SUBF_D, // Floating-point Subtract (Double)
NEC850_SUBF_S, // Floating-point Subtract (Single)
NEC850_MADDF_S, // Floating-point Multiply-Add (Single)
NEC850_MSUBF_S, // Floating-point Multiply-Subtract (Single)
NEC850_NMADDF_S, // Floating-point Negate Multiply-Add (Single)
NEC850_NMSUBF_S, // Floating-point Negate Multiply-Subtract (Single)
NEC850_CEILF_DL, // Floating-point Truncate to Long Fixed-point Format, rounded toward +inf (Double)
NEC850_CEILF_DW, // Floating-point Truncate to Single Fixed-point Format, rounded toward +inf (Double)
NEC850_CEILF_SL, // Floating-point Truncate to Long Fixed-point Format, rounded toward +inf (Single)
NEC850_CEILF_SW, // Floating-point Truncate to Single Fixed-point Format, rounded toward +inf (Single)
NEC850_CEILF_DUL, // Floating-point Truncate to Unsigned Long, rounded toward +inf (Double)
NEC850_CEILF_DUW, // Floating-point Truncate to Unsigned Word, rounded toward +inf (Double)
NEC850_CEILF_SUL, // Floating-point Truncate to Unsigned Long, rounded toward +inf (Single)
NEC850_CEILF_SUW, // Floating-point Truncate to Unsigned Word, rounded toward +inf (Single)
NEC850_CVTF_DL, // Floating-point Convert to Long Fixed-point Format (Double)
NEC850_CVTF_DS, // Floating-point Convert to Single Floating-point Format (Double)
NEC850_CVTF_DUL, // Floating-point Convert Double to Unsigned-Long (Double)
NEC850_CVTF_DUW, // Floating-point Convert Double to Unsigned-Word (Double)
NEC850_CVTF_DW, // Floating-point Convert to Single Fixed-point Format (Double)
NEC850_CVTF_LD, // Floating-point Convert to Single Floating-point Format (Double)
NEC850_CVTF_LS, // Floating-point Convert to Single Floating-point Format (Single)
NEC850_CVTF_SD, // Floating-point Convert to Double Floating-point Format (Double)
NEC850_CVTF_SL, // Floating-point Convert to Long Fixed-point Format (Single)
NEC850_CVTF_SUL, // Floating-point Convert Single to Unsigned-Long (Single)
NEC850_CVTF_SUW, // Floating-point Convert Single to Unsigned-Word (Single)
NEC850_CVTF_SW, // Floating-point Convert to Single Fixed-point Format (Single)
NEC850_CVTF_ULD, // Floating-point Convert Unsigned-Long to Double (Double)
NEC850_CVTF_ULS, // Floating-point Convert Unsigned-Long to Single (Single)
NEC850_CVTF_UWD, // Floating-point Convert Unsigned-Word to Double (Double)
NEC850_CVTF_UWS, // Floating-point Convert Unsigned-Word to Single (Single)
NEC850_CVTF_WD, // Floating-point Convert to Single Floating-point Format (Double)
NEC850_CVTF_WS, // Floating-point Convert to Single Floating-point Format (Single)
NEC850_FLOORF_DL, // Floating-point Truncate to Long Fixed-point Format, rounded toward -inf (Double)
NEC850_FLOORF_DW, // Floating-point Truncate to Single Fixed-point Format, rounded toward -inf (Double)
NEC850_FLOORF_SL, // Floating-point Truncate to Long Fixed-point Format, rounded toward -inf (Single)
NEC850_FLOORF_SW, // Floating-point Truncate to Single Fixed-point Format, rounded toward -inf (Single)
NEC850_FLOORF_DUL, // Floating-point Truncate to Unsigned Long, rounded toward -inf (Double)
NEC850_FLOORF_DUW, // Floating-point Truncate to Unsigned Word, rounded toward -inf (Double)
NEC850_FLOORF_SUL, // Floating-point Truncate to Unsigned Long, rounded toward -inf (Single)
NEC850_FLOORF_SUW, // Floating-point Truncate to Unsigned Word, rounded toward -inf (Single)
NEC850_TRNCF_DL, // Floating-point Truncate to Long Fixed-point Format, rounded to zero (Double)
NEC850_TRNCF_DUL, // Floating-point Truncate Double to Unsigned-Long (Double)
NEC850_TRNCF_DUW, // Floating-point Truncate Double to Unsigned-Word (Double)
NEC850_TRNCF_DW, // Floating-point Truncate to Single Fixed-point Format, rounded to zero (Double)
NEC850_TRNCF_SL, // Floating-point Truncate to Long Fixed-point Format, rounded to zero (Single)
NEC850_TRNCF_SUL, // Floating-point Truncate Single to Unsigned-Long (Single)
NEC850_TRNCF_SUW, // Floating-point Truncate Single to Unsigned-Word (Single)
NEC850_TRNCF_SW, // Floating-point Truncate to Single Fixed-point Format, rounded to zero (Single)
NEC850_CMPF_S, // Compares floating-point values (Single)
NEC850_CMPF_D, // Compares floating-point values (Double)
NEC850_CMOVF_S, // Floating-point conditional move (Single)
NEC850_CMOVF_D, // Floating-point conditional move (Double)
NEC850_TRFSR, // Transfers specified CC bit to Zero flag in PSW (Single)
//
// RH850
//
NEC850_SYNCI, // Synchronize instruction pipeline
NEC850_SNOOZE, // Snooze
NEC850_BINS, // Bitfield Insert
NEC850_ROTL, // Rotate Left
NEC850_LOOP, // Loop
NEC850_LD_DW, // Load Double Word
NEC850_ST_DW, // Store Double Word
NEC850_LDL_W, // Load Linked
NEC850_STC_W, // Store Conditional
NEC850_CLL, // Clear Load Link
NEC850_CACHE, // Cache operation
NEC850_PREF, // Prefetch
NEC850_PUSHSP, // Push registers to Stack
NEC850_POPSP, // Pop registers from Stack
// new RH850 FP instructions
NEC850_CVTF_HS, // Floating-point Convert Half to Single (Single)
NEC850_CVTF_SH, // Floating-point Convert Single to Half (Single)
NEC850_FMAF_S, // Floating-point Fused-Multiply-add (Single)
NEC850_FMSF_S, // Floating-point Fused-Multiply-subtract (Single)
NEC850_FNMAF_S, // Floating-point Fused-Negate-Multiply-add (Single)
NEC850_FNMSF_S, // Floating-point Fused-Negate-Multiply-subtract (Single)
// debug instructions
NEC850_DBPUSH, //
NEC850_DBCP, //
NEC850_DBTAG, //
NEC850_DBHVTRAP, //
// virtualization instructions
NEC850_EST, //
NEC850_DST, //
NEC850_HVTRAP, //
NEC850_HVCALL, //
NEC850_LDVC_SR, //
NEC850_STVC_SR, //
NEC850_LDTC_GR, //
NEC850_STTC_GR, //
NEC850_LDTC_PC, //
NEC850_STTC_PC, //
NEC850_LDTC_SR, //
NEC850_STTC_SR, //
NEC850_LDTC_VR, //
NEC850_STTC_VR, //
// TLB instructions
NEC850_TLBAI, //
NEC850_TLBR, //
NEC850_TLBS, //
NEC850_TLBVI, //
NEC850_TLBW, //
NEC850_LAST_INSTRUCTION
};
#endif

View File

@@ -0,0 +1,52 @@
PROC=nec850
include ../module.mak
# MAKEDEP dependency list ------------------
$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.hpp $(I)fpro.h $(I)funcs.hpp \
$(I)ida.hpp $(I)idd.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)ua.hpp $(I)xref.hpp ../idaidp.hpp ana.cpp ins.hpp \
necv850.hpp
$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.hpp $(I)fpro.h $(I)frame.hpp \
$(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp \
$(I)ieee.h $(I)jumptable.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 emu.cpp ins.hpp \
necv850.hpp
$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.hpp $(I)fpro.h $(I)funcs.hpp \
$(I)ida.hpp $(I)idd.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)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.cpp ins.hpp \
necv850.hpp
$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.hpp $(I)fpro.h $(I)funcs.hpp \
$(I)ida.hpp $(I)idd.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)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.hpp \
necv850.hpp out.cpp
$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.hpp $(I)fpro.h $(I)funcs.hpp \
$(I)ida.hpp $(I)idd.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 \
ins.hpp necv850.hpp reg.cpp

View File

@@ -0,0 +1,211 @@
#ifndef __NECV850_INC__
#define __NECV850_INC__
#include "../idaidp.hpp"
#include <list>
#include <pro.h>
#include <fpro.h>
#include <idd.hpp>
#include <ida.hpp>
#include <name.hpp>
#include <idp.hpp>
#include <ieee.h>
#define PROCMOD_NAME nec850
#define PROCMOD_NODE_NAME "$ prog pointers"
#ifndef SIGN_EXTEND
#define SIGN_EXTEND(type, var, nbits) \
if ( var & (1 << (nbits-1)) ) \
var |= ~type((1 << nbits)-1)
#endif
//----------------------------------------------------------------------
// Specific flags
//
// Used in op_t.specflag1
#define N850F_USEBRACKETS 0x01 // some instructions use [reg] syntax even when there is no actual memory dereference
#define N850F_OUTSIGNED 0x02 // output as signed value
#define N850F_VAL32 0x04 // value/addr is wider than 16-bit
#define o_reglist o_idpspec1 // Register list (for DISPOSE)
// bitmask of registers is in 'value' field
//
// Used in insn.auxpref
#define N850F_SP 0x00000001 // instruction modifies the stack pointer
#define N850F_FP 0x00000010 // instruction works with floating-point data
#define o_cond o_idpspec2 // Condition code as operand (for CMOV/CMPF)
// condition stored in 'value' field
#define o_regrange o_idpspec3 // Register range (rh-rl, for PUSHSP/POPSP)
#define regrange_high specval_shorts.high // high register (rh)
#define regrange_low specval_shorts.low // low register (rl)
//----------------------------------------------------------------------
// Registers def
enum NEC850_Registers
{
rZERO,
rR1, rR2, rSP /* r3 */, rGP /* r4 */,
rR5, rR6, rR7, rR8,
rR9, rR10, rR11, rR12,
rR13, rR14, rR15, rR16,
rR17, rR18, rR19, rR20,
rR21, rR22, rR23, rR24,
rR25, rR26, rR27, rR28,
rR29, rEP, rR31,
rLP = rR31,
// system registers start here
rSR0,
rEIP=rSR0, rEIPSW, rFEPC, rFEPSW,
rECR, rPSW, rSR6, rSR7,
rSR8, rSR9, rSR10, rSR11,
rSR12, rSR13, rSR14, rSR15,
rSR16, rSR17, rSR18, rSR19,
rSR20, rSR21, rSR22, rSR23,
rSR24, rSR25, rSR26, rSR27,
rSR28, rSR29, rSR30, rSR31,
// E1F FPU registers
EFG, ECT,
// segment registers
rVep, // virtual element pointer segment register
rVcs, rVds,
rLastRegister
};
enum NEC850_CCode // for CMOV
{
CC_V, // 0000: Overflow (OV=1)
CC_CL, // 0001: Carry (CY=1)
CC_Z, // 0010: Zero (Z=1)
CC_NH, // 0011: Not higher (Less than or equal) ((CY or Z) = 1)
CC_SN, // 0100: Negative) S=1
CC_T, // 0101: Always (true)
CC_LT, // 0110: Less than signed (S xor OV) = 1
CC_LE, // 0111: Less than or equal signed (((S xor OV) or Z) = 1)
CC_NV, // 1000: no overflow (OV=0)
CC_NCNL,// 1001: no carry (CY=0)
CC_NZ, // 1010: not zero (Z=0)
CC_H, // 0011: Higher (Greater than) ((CY or Z) = 0)
CC_NSP, // 0100: Positive (S=0)
CC_SAT, // 1101: Saturated (SAT=1)
CC_GE, // 1110: Greater than or equal signed (S xor OV) = 0
CC_GT, // 1111: Greater than signed (((S xor OV) or Z) = 0)
};
enum proctype_t
{
V850, // including V850
V850E, //
V850ES, // including V850E1
V850E2M,// including V850E2
RH850, //
};
//----------------------------------------------------------------------
// Prototypes
// prototypes -- out.cpp
void idaapi nec850_header(outctx_t &ctx);
void idaapi nec850_segstart(outctx_t &ctx, segment_t *seg);
void idaapi nec850_segend(outctx_t &ctx, segment_t *seg);
bool reg_in_list12(uint16 reg, uint32 L);
// prototypes -- ana.cpp
int detect_inst_len(uint16 w);
int fetch_instruction(uint32 *w);
// prototypes -- emu.cpp
bool idaapi nec850_is_switch(switch_info_t *si, const insn_t &insn);
bool idaapi nec850_create_func_frame(func_t *pfn);
int idaapi nec850_get_frame_retsize(const func_t *pfn);
int idaapi nec850_is_sp_based(const insn_t &insn, const op_t &x);
int nec850_may_be_func(const insn_t &insn);
bool nec850_is_return(const insn_t &insn, bool strict);
int get_imm_outf(const insn_t &insn, const op_t &x);
int get_displ_outf(const insn_t &insn, const op_t &x, flags_t F);
extern const char *const RegNames[];
typedef const regval_t &idaapi getreg_t(const char *name, const regval_t *regvalues);
//------------------------------------------------------------------
DECLARE_PROC_LISTENER(idb_listener_t, struct nec850_t);
struct nec850_t : public procmod_t
{
// altval(1) -> global pointer
// altval(2) -> CALLT base pointer
#define GP_EA_IDX 1
#define CTBP_EA_IDX 2
netnode helper;
idb_listener_t idb_listener = idb_listener_t(*this);
ea_t g_gp_ea = BADADDR; // global pointer
ea_t g_ctbp_ea = BADADDR; // CALLT base pointer
int ptype = 0;
bool flow = false;
bool inline idaapi is_v850e() const { return ptype >= (int)V850E; }
bool inline idaapi is_v850es() const { return ptype >= (int)V850ES; }
bool inline idaapi is_v850e1() const { return is_v850es(); }
bool inline idaapi is_v850e1f() const { return is_v850e1(); }
bool inline idaapi is_v850e2m() const { return ptype >= (int)V850E2M; }
bool inline idaapi is_v850e2() const { return is_v850e2m(); }
bool inline idaapi is_rh850() const { return ptype >= (int)RH850; }
virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override;
const char *idaapi set_idp_options(
const char *keyword,
int value_type,
const void * value,
bool idb_loaded);
bool decode_instruction(const uint32 w, insn_t &ins);
bool decode_coprocessor(const uint32 w, insn_t &ins) const;
int nec850_ana(insn_t *pinsn);
bool get_gp_based_addr(ea_t *target, const insn_t &_insn, const op_t &op) const;
void handle_operand(const insn_t &insn, const op_t &op, bool isRead);
int nec850_emu(const insn_t &insn);
int nec850_is_sane_insn(const insn_t &insn, int no_crefs) const;
sval_t regval(
const op_t &op,
getreg_t *getreg,
const regval_t *rv) const;
// debugger functions
ea_t nec850_next_exec_insn(
ea_t ea,
getreg_t *getreg,
const regval_t *regvalues) const;
ea_t nec850_calc_step_over(ea_t ip) const;
bool nec850_get_operand_info(
idd_opinfo_t *opinf,
ea_t ea,
int n,
getreg_t *getreg,
const regval_t *regvalues);
bool nec850_get_reg_info(
const char **main_regname,
bitrange_t *bitrange,
const char *regname);
int nec850_get_reg_index(const char *name) const; // static
void nec850_footer(outctx_t &ctx) const;
void save_all_options();
void load_from_idb();
};
extern int data_id;
#endif

View File

@@ -0,0 +1,339 @@
/*
* Interactive disassembler (IDA).
* Copyright (c) Hex-Rays
* ALL RIGHTS RESERVED.
*
* Output
*
*/
#include "necv850.hpp"
#include "ins.hpp"
//--------------------------------------------------------------------------
// LIST12 table mapping to corresponding registers
static const int list12_table[] =
{
rR31, // 0
rR29, // 1
rR28, // 2
rR23, // 3
rR22, // 4
rR21, // 5
rR20, // 6
rR27, // 7
rR26, // 8
rR25, // 9
rR24, // 10
rEP // 11
};
// Using the indexes in this table as indexes in list12_table[]
// we can test for bits in List12 in order
static const int list12order_table[] =
{
6, // 0 r20
5, // 1 r21
4, // 2 r22
3, // 3 r23
10, // 4 r24
9, // 5 r25
8, // 6 r26
7, // 7 r27
2, // 8 r28
1, // 9 r29
11, // 10 r30
0, // 11 r31
};
//----------------------------------------------------------------------
int get_displ_outf(const insn_t &insn, const op_t &x, flags_t F)
{
qnotused(insn);
qnotused(F);
int outf = OOF_ADDR;
outf |= ( x.specflag1 & N850F_VAL32 ) ? OOFW_32 : OOFW_16;
if ( ( x.specflag1 & N850F_OUTSIGNED ) != 0 )
outf |= OOFS_IFSIGN | OOF_SIGNED;
return outf;
}
//----------------------------------------------------------------------
class out_nec850_t : public outctx_t
{
out_nec850_t(void) = delete; // not used
public:
void OutReg(const op_t &r);
void out_reg_list(uint32 L);
void out_reg_range(const op_t &op);
bool out_operand(const op_t &x);
void out_insn(void);
void out_cond(const op_t &r);
void out_fcond(const op_t &r);
};
CASSERT(sizeof(out_nec850_t) == sizeof(outctx_t));
DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_nec850_t)
//--------------------------------------------------------------------------
bool reg_in_list12(uint16 reg, uint32 L)
{
if ( rR20 <= reg && reg <= rR31 )
{
uint32 idx = list12order_table[reg - rR20]; //lint !e676 possibly indexing before the beginning of an allocation
return (L & (1 << idx)) != 0;
}
return false;
}
//--------------------------------------------------------------------------
void out_nec850_t::out_reg_list(uint32 L)
{
int last = qnumber(list12_table);
int in_order = 0, c = 0;
const char *last_rn = NULL;
out_symbol('{');
for ( int i=0; i < qnumber(list12order_table); i++ )
{
uint32 idx = list12order_table[i];
if ( (L & (1 << idx)) == 0 )
continue;
c++;
const char *rn = RegNames[list12_table[idx]];
if ( last + 1 == i )
in_order++;
else
{
if ( in_order > 1 )
{
out_symbol('-');
out_register(last_rn);
out_line(", ", COLOR_SYMBOL);
}
else if ( c > 1 )
{
out_line(", ", COLOR_SYMBOL);
}
out_register(rn);
in_order = 1;
}
last_rn = rn;
last = i;
}
if ( in_order > 1 )
{
out_symbol('-');
out_register(last_rn);
}
out_symbol('}');
}
//--------------------------------------------------------------------------
void out_nec850_t::out_reg_range(const op_t &op)
{
out_register(RegNames[op.regrange_high]);
out_symbol('-');
out_register(RegNames[op.regrange_low]);
}
//--------------------------------------------------------------------------
void idaapi nec850_header(outctx_t &ctx)
{
ctx.gen_header(GH_PRINT_PROC_AND_ASM);
}
//--------------------------------------------------------------------------
void nec850_t::nec850_footer(outctx_t &ctx) const
{
ctx.gen_empty_line();
ctx.out_line(ash.end, COLOR_ASMDIR);
ctx.flush_outbuf(DEFAULT_INDENT);
ctx.gen_cmt_line("-------------- end of module --------------");
}
//--------------------------------------------------------------------------
//lint -esym(1764, ctx) could be made const
//lint -esym(818, s) could be made const
void idaapi nec850_segstart(outctx_t &ctx, segment_t *s)
{
qstring sname;
qstring sclass;
get_visible_segm_name(&sname, s);
get_segm_class(&sclass, s);
const char *p_class;
if ( (s->perm == (SEGPERM_READ|SEGPERM_WRITE)) && s->type == SEG_BSS )
p_class = "bss";
else if ( s->perm == SEGPERM_READ )
p_class = "const";
else if ( s->perm == (SEGPERM_READ|SEGPERM_WRITE) )
p_class = "data";
else if ( s->perm == (SEGPERM_READ|SEGPERM_EXEC) )
p_class = "text";
else if ( s->type == SEG_XTRN )
p_class = "symtab";
else
p_class = sclass.c_str();
ctx.gen_printf(0, COLSTR(".section \"%s\", %s", SCOLOR_ASMDIR), sname.c_str(), p_class);
}
//--------------------------------------------------------------------------
void idaapi nec850_segend(outctx_t &, segment_t *)
{
}
//----------------------------------------------------------------------
void out_nec850_t::OutReg(const op_t &r)
{
bool brackets = r.specflag1 & N850F_USEBRACKETS;
if ( brackets )
out_symbol('[');
out_register(ph.reg_names[r.reg]);
if ( brackets )
out_symbol(']');
}
static const char *cond_tbl[16] =
{
"v", // 0000: Overflow (OV=1)
"c/l", // 0001: Carry (CY=1)
"z", // 0010: Zero (Z=1)
"nh", // 0011: Not higher (Less than or equal) ((CY or Z) = 1)
"s/n", // 0100: Negative) S=1
"t", // 0101: Always (true)
"lt", // 0110: Less than signed (S xor OV) = 1
"le", // 0111: Less than or equal signed (((S xor OV) or Z) = 1)
"nv", // 1000: no overflow (OV=0)
"nc/nl",// 1001: no carry (CY=0)
"nz", // 1010: not zero (Z=0)
"h", // 0011: Higher (Greater than) ((CY or Z) = 0)
"ns/p", // 0100: Positive (S=0)
"sat", // 1101: Saturated (SAT=1)
"ge", // 1110: Greater than or equal signed (S xor OV) = 0
"gt", // 1111: Greater than signed (((S xor OV) or Z) = 0)
};
static const char *fcond_tbl[16] =
{
"f/t",
"un/or",
"eq/neq",
"ueq/ogl",
"olt/uge",
"ult/oge",
"ole/ugt",
"ule/ogt",
"sf/st",
"ngle/gle",
"seq/sne",
"ngl/gl",
"lt/nlt",
"nge/ge",
"le/nle",
"ngt/gt"
};
//----------------------------------------------------------------------
void out_nec850_t::out_cond(const op_t &r)
{
int cc = r.value;
QASSERT(10327, r.type == o_cond && cc < qnumber(cond_tbl));
out_keyword(cond_tbl[cc]);
}
//----------------------------------------------------------------------
void out_nec850_t::out_fcond(const op_t &r)
{
int cc = r.value;
QASSERT(10323, r.type == o_cond && cc < qnumber(fcond_tbl));
out_keyword(fcond_tbl[cc]);
}
//----------------------------------------------------------------------
void out_nec850_t::out_insn(void)
{
out_mnemonic();
out_one_operand(0);
for ( int i=1; i < UA_MAXOP; i++ )
{
if ( insn.ops[i].type == o_void )
break;
out_symbol(',');
out_char(' ');
out_one_operand(i);
}
flush_outbuf();
}
//----------------------------------------------------------------------
// Generate text representation of an instructon operand.
// This function shouldn't change the database, flags or anything else.
// All these actions should be performed only by u_emu() function.
// The output text is placed in the output buffer initialized with init_output_buffer()
// This function uses out_...() functions from ua.hpp to generate the operand text
// Returns: 1-ok, 0-operand is hidden.
bool out_nec850_t::out_operand(const op_t &x)
{
switch ( x.type )
{
case o_void:
return false;
case o_reglist:
out_reg_list(x.value);
break;
case o_regrange:
out_reg_range(x);
break;
case o_reg:
OutReg(x);
break;
case o_imm:
out_value(x, OOFW_IMM | ((x.specflag1 & N850F_OUTSIGNED) ? OOF_SIGNED : 0));
break;
case o_near:
case o_mem:
if ( !out_name_expr(x, x.addr, BADADDR) )
{
out_tagon(COLOR_ERROR);
out_value(x, OOF_ADDR | OOFW_IMM | OOFW_32);
out_tagoff(COLOR_ERROR);
remember_problem(PR_NONAME, insn.ea);
}
break;
case o_displ:
if ( x.addr != 0 || x.reg == rSP )
out_value(x, get_displ_outf(insn, x, F));
OutReg(x);
if ( x.reg != rGP && x.reg != rSP && x.addr == 0 )
{ // add name comment
xrefblk_t xb;
for ( bool ok=xb.first_from(insn.ea, XREF_DATA); ok; ok=xb.next_from() )
{
if ( has_cmt(F) )
continue;
if ( xb.type != dr_R && xb.type != dr_W )
continue;
qstring qbuf;
if ( get_name_expr(&qbuf, insn.ea, x.n, xb.to, BADADDR) > 0 )
set_cmt(insn.ea, qbuf.begin(), false);
}
}
break;
case o_cond:
if ( insn.auxpref & N850F_FP )
out_fcond(x);
else
out_cond(x);
break;
default:
return false;
}
return true;
}

View File

@@ -0,0 +1,532 @@
/*
* Interactive disassembler (IDA).
* Copyright (c) Hex-Rays
* ALL RIGHTS RESERVED.
*
* Processor description structures
*
*/
#include "necv850.hpp"
#include "ins.hpp"
#include <loader.hpp>
#include <segregs.hpp>
int data_id;
//-------------------------------------------------------------------------
void nec850_t::save_all_options()
{
helper.altset(GP_EA_IDX, ea2node(g_gp_ea));
helper.altset(CTBP_EA_IDX, ea2node(g_ctbp_ea));
}
//-------------------------------------------------------------------------
// read all procmod data from the idb
void nec850_t::load_from_idb()
{
g_gp_ea = node2ea(helper.altval(GP_EA_IDX));
g_ctbp_ea = node2ea(helper.altval(CTBP_EA_IDX));
}
//------------------------------------------------------------------
const char *nec850_t::set_idp_options(
const char *keyword,
int value_type,
const void * value,
bool idb_loaded)
{
if ( keyword != NULL )
{
if ( streq(keyword, "GP_EA") )
{
if ( value_type != IDPOPT_NUM )
return IDPOPT_BADTYPE;
g_gp_ea = *((uval_t *)value);
goto SAVE;
}
if ( streq(keyword, "CTBP_EA") )
{
if ( value_type != IDPOPT_NUM )
return IDPOPT_BADTYPE;
g_ctbp_ea = *((uval_t *)value);
goto SAVE;
}
return IDPOPT_BADKEY;
}
static const char form[] =
"NEC V850x analyzer options\n"
"\n"
" <~G~lobal Pointer address:$::18::>\n"
" <CALLT ~B~ase pointer :$::18::>\n"
"\n"
"\n"
"\n";
CASSERT(sizeof(g_gp_ea) == sizeof(ea_t));
CASSERT(sizeof(g_ctbp_ea) == sizeof(ea_t));
if ( ask_form(form, &g_gp_ea, &g_ctbp_ea) == ASKBTN_YES )
{
SAVE:
if ( idb_loaded )
save_all_options();
}
return IDPOPT_OK;
}
//----------------------------------------------------------------------
static const asm_t nec850_asm =
{
ASH_HEXF3 | AS_UNEQU | AS_COLON | ASB_BINF4 | AS_N2CHR, // flags
0, // user flags
"NEC V850 Assembler", // assembler name
0, // help
NULL, // array of automatically generated header lines
".org", // org directive
".end", // end directive
"--", // comment string
'"', // string delimiter
'\'', // char delimiter
"'\"", // special symbols in char and string constants
".str", // ascii string directive
".byte", // byte directive
".hword", // halfword (16 bits) [IDA: word]
".word", // word (32 bits) [IDA: dword]
".dword", // doubleword (64 bits) [IDA: qword]
NULL, // oword (16 bytes)
".float", // float (4-byte)
".double", // double (8-byte)
NULL, // no tbytes
NULL, // no packreal
"#d dup(#v)", //".db.#s(b,w) #d,#v"
".byte (%s) ?", // uninited data (reserve space) ;?
".set", // 'equ' Used if AS_UNEQU is set
NULL, // seg prefix
"PC", // a_curip
NULL, // returns function header line
NULL, // returns function footer line
".globl", // public
NULL, // weak
".extern", // extrn
".comm", // comm
NULL, // get_type_name
".align", // align
'(', // lbrace
')', // rbrace
NULL, // mod
"&", // bit-and
"|", // or
"^", // xor
"!", // not
"<<", // shl
">>", // shr
NULL, // sizeof
0, // flags2
NULL, // cmnt2
NULL, // low8 operation, should contain %s for the operand
NULL, // high8
NULL, // low16
NULL, // high16
".include %s", // a_include_fmt
NULL, // if a named item is a structure and displayed
NULL // 'rva' keyword for image based offsets
};
static const asm_t *const asms[] = { &nec850_asm, NULL };
//----------------------------------------------------------------------
#define FAMILY "NEC/Renesas 850 series:"
static const char *const shnames[] =
{
"V850",
"V850E",
"V850E1",
"V850E2M",
"RH850",
NULL
};
static const char *const lnames[] =
{
FAMILY"NEC V850",
"NEC V850E",
"NEC/Renesas V850E1/ES",
"NEC/Renesas V850E2/E2M",
"Renesas RH850",
NULL
};
//--------------------------------------------------------------------------
ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list)
{
switch ( code )
{
// all options are saved immediately after the change
// case idb_event::savebase:
case idb_event::segm_moved: // A segment is moved
// Fix processor dependent address sensitive information
// {
// ea_t from = va_arg(va, ea_t);
// ea_t to = va_arg(va, ea_t);
// asize_t size = va_arg(va, asize_t);
// bool changed_netmap = va_argi(va, bool);
// // adjust gp_ea
// }
break;
default:
break;
}
return 0;
}
//----------------------------------------------------------------------
// 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(nec850_t));
return 0;
}
//----------------------------------------------------------------------
ssize_t idaapi nec850_t::on_event(ssize_t msgid, va_list va)
{
int code = 0;
switch ( msgid )
{
case processor_t::ev_init:
helper.create(PROCMOD_NODE_NAME);
hook_event_listener(HT_IDB, &idb_listener, &LPH);
inf_set_be(false);
break;
case processor_t::ev_term:
unhook_event_listener(HT_IDB, &idb_listener);
clr_module_data(data_id);
break;
case processor_t::ev_newfile:
save_all_options();
break;
case processor_t::ev_newprc:
{
int procnum = va_arg(va, int);
// bool keep_cfg = va_argi(va, bool);
ptype = procnum;
break;
}
case processor_t::ev_ending_undo:
// restore ptype
ptype = ph.get_proc_index();
//fall through
case processor_t::ev_oldfile:
load_from_idb();
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_is_sane_insn:
{
const insn_t &insn = *va_arg(va, insn_t *);
int no_crefs = va_arg(va, int);
code = nec850_is_sane_insn(insn, no_crefs) == 1 ? 1 : -1;
break;
}
case processor_t::ev_may_be_func:
{
const insn_t &insn = *va_arg(va, insn_t *);
code = nec850_may_be_func(insn);
}
break;
case processor_t::ev_is_ret_insn:
{
const insn_t &insn = *va_arg(va, insn_t *);
bool strict = va_argi(va, bool);
code = nec850_is_return(insn, strict) ? 1 : -1;
}
break;
case processor_t::ev_out_header:
{
outctx_t *ctx = va_arg(va, outctx_t *);
nec850_header(*ctx);
return 1;
}
case processor_t::ev_out_footer:
{
outctx_t *ctx = va_arg(va, outctx_t *);
nec850_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 *);
nec850_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 *);
nec850_segend(*ctx, seg);
return 1;
}
case processor_t::ev_ana_insn:
{
insn_t *out = va_arg(va, insn_t *);
return nec850_ana(out);
}
case processor_t::ev_emu_insn:
{
const insn_t *insn = va_arg(va, const insn_t *);
return nec850_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_switch:
{
switch_info_t *si = va_arg(va, switch_info_t *);
const insn_t *insn = va_arg(va, const insn_t *);
return nec850_is_switch(si, *insn) ? 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 = nec850_is_sp_based(*insn, *op);
return 1;
}
case processor_t::ev_create_func_frame:
{
func_t *pfn = va_arg(va, func_t *);
nec850_create_func_frame(pfn);
return 1;
}
case processor_t::ev_get_frame_retsize:
{
int *frsize = va_arg(va, int *);
const func_t *pfn = va_arg(va, const func_t *);
*frsize = nec850_get_frame_retsize(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;
}
// START OF DEBUGGER CALLBACKS
case processor_t::ev_next_exec_insn:
{
ea_t *target = va_arg(va, ea_t *);
ea_t ea = va_arg(va, ea_t);
int tid = va_arg(va, int);
getreg_t *getreg = va_arg(va, getreg_t *);
const regval_t *regvalues = va_arg(va, const regval_t *);
qnotused(tid);
*target = nec850_next_exec_insn(ea, getreg, regvalues);
return 1;
}
case processor_t::ev_calc_step_over:
{
ea_t *target = va_arg(va, ea_t *);
ea_t ip = va_arg(va, ea_t);
*target = nec850_calc_step_over(ip);
return 1;
}
case processor_t::ev_get_idd_opinfo:
{
idd_opinfo_t *opinf = va_arg(va, idd_opinfo_t *);
ea_t ea = va_arg(va, ea_t);
int n = va_arg(va, int);
int thread_id = va_arg(va, int);
getreg_t *getreg = va_arg(va, getreg_t *);
const regval_t *regvalues = va_arg(va, const regval_t *);
qnotused(thread_id);
return nec850_get_operand_info(opinf, ea, n, getreg, regvalues) ? 1 : 0;
}
case processor_t::ev_get_reg_info:
{
const char **main_regname = va_arg(va, const char **);
bitrange_t *bitrange = va_arg(va, bitrange_t *);
const char *regname = va_arg(va, const char *);
return nec850_get_reg_info(main_regname, bitrange, regname) ? 1 : -1;
}
// END OF DEBUGGER CALLBACKS
default:
break;
}
return code;
}
//-----------------------------------------------------------------------
// Registers Definition
//-----------------------------------------------------------------------
const char *const RegNames[rLastRegister] =
{
"r0",
"r1",
"r2",
"sp",
"gp",
"r5", // text pointer - tp
"r6",
"r7",
"r8",
"r9",
"r10",
"r11",
"r12",
"r13",
"r14",
"r15",
"r16",
"r17",
"r18",
"r19",
"r20",
"r21",
"r22",
"r23",
"r24",
"r25",
"r26",
"r27",
"r28",
"r29",
"ep",
"lp",
// system registers start here
"eipc",
"eipsw",
"fepc",
"fepsw",
"ecr",
"psw",
"sr6",
"sr7",
"sr8",
"sr9",
"sr10",
"sr11",
"sr12",
"sr13",
"sr14",
"sr15",
"sr16",
"sr17",
"sr18",
"sr19",
"sr20",
"sr21",
"sr22",
"sr23",
"sr24",
"sr25",
"sr26",
"sr27",
"sr28",
"sr29",
"sr30",
"sr31",
"EFG", "ECT",
//
"ep", "cs", "ds"
};
CASSERT(qnumber(RegNames) == rLastRegister);
//-----------------------------------------------------------------------
// Processor Definition
//-----------------------------------------------------------------------
processor_t LPH =
{
IDP_INTERFACE_VERSION, // version
PLFM_NEC_V850X, // id
// flag
PR_DEFSEG32
| PR_USE32
| PRN_HEX
| PR_RNAMESOK,
// 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, // short processor names
lnames, // long processor names
asms, // assemblers
notify,
RegNames, // Regsiter names
rLastRegister, // Number of registers
rVcs/*rVep*/, // number of first segment register
rVds/*rVcs*/, // number of last segment register
0 /*4*/, // size of a segment register
rVcs,
rVds,
NULL, // No known code start sequences
NULL, // Array of 'return' instruction opcodes
NEC850_NULL,
NEC850_LAST_INSTRUCTION,
Instructions, // instruc
0, // size of tbyte
{0,7,15,0}, // real width
0, // icode_return
NULL, // Micro virtual machine description
};