update to ida 7.6, add builds
This commit is contained in:
2065
idasdk76/module/nec850/ana.cpp
Normal file
2065
idasdk76/module/nec850/ana.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1299
idasdk76/module/nec850/emu.cpp
Normal file
1299
idasdk76/module/nec850/emu.cpp
Normal file
File diff suppressed because it is too large
Load Diff
299
idasdk76/module/nec850/ins.cpp
Normal file
299
idasdk76/module/nec850/ins.cpp
Normal 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);
|
||||
310
idasdk76/module/nec850/ins.hpp
Normal file
310
idasdk76/module/nec850/ins.hpp
Normal 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
|
||||
52
idasdk76/module/nec850/makefile
Normal file
52
idasdk76/module/nec850/makefile
Normal 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
|
||||
211
idasdk76/module/nec850/necv850.hpp
Normal file
211
idasdk76/module/nec850/necv850.hpp
Normal 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
|
||||
339
idasdk76/module/nec850/out.cpp
Normal file
339
idasdk76/module/nec850/out.cpp
Normal 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;
|
||||
}
|
||||
532
idasdk76/module/nec850/reg.cpp
Normal file
532
idasdk76/module/nec850/reg.cpp
Normal 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
|
||||
};
|
||||
Reference in New Issue
Block a user