Merge commit '802798ce3c8baa4697120580f87bc1ee377306d3' as 'external/capstone'
This commit is contained in:
+4432
File diff suppressed because it is too large
Load Diff
+301
@@ -0,0 +1,301 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* M68K Backend by Daniel Collin <daniel@collin.com> 2015-2016 */
|
||||
|
||||
#ifndef CS_M68KDISASSEMBLER_H
|
||||
#define CS_M68KDISASSEMBLER_H
|
||||
|
||||
#include "../../MCInst.h"
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================ GENERAL DEFINES =========================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Bit Isolation Functions */
|
||||
#define BIT_0(A) ((A) & 0x00000001)
|
||||
#define BIT_1(A) ((A) & 0x00000002)
|
||||
#define BIT_2(A) ((A) & 0x00000004)
|
||||
#define BIT_3(A) ((A) & 0x00000008)
|
||||
#define BIT_4(A) ((A) & 0x00000010)
|
||||
#define BIT_5(A) ((A) & 0x00000020)
|
||||
#define BIT_6(A) ((A) & 0x00000040)
|
||||
#define BIT_7(A) ((A) & 0x00000080)
|
||||
#define BIT_8(A) ((A) & 0x00000100)
|
||||
#define BIT_9(A) ((A) & 0x00000200)
|
||||
#define BIT_A(A) ((A) & 0x00000400)
|
||||
#define BIT_B(A) ((A) & 0x00000800)
|
||||
#define BIT_C(A) ((A) & 0x00001000)
|
||||
#define BIT_D(A) ((A) & 0x00002000)
|
||||
#define BIT_E(A) ((A) & 0x00004000)
|
||||
#define BIT_F(A) ((A) & 0x00008000)
|
||||
#define BIT_10(A) ((A) & 0x00010000)
|
||||
#define BIT_11(A) ((A) & 0x00020000)
|
||||
#define BIT_12(A) ((A) & 0x00040000)
|
||||
#define BIT_13(A) ((A) & 0x00080000)
|
||||
#define BIT_14(A) ((A) & 0x00100000)
|
||||
#define BIT_15(A) ((A) & 0x00200000)
|
||||
#define BIT_16(A) ((A) & 0x00400000)
|
||||
#define BIT_17(A) ((A) & 0x00800000)
|
||||
#define BIT_18(A) ((A) & 0x01000000)
|
||||
#define BIT_19(A) ((A) & 0x02000000)
|
||||
#define BIT_1A(A) ((A) & 0x04000000)
|
||||
#define BIT_1B(A) ((A) & 0x08000000)
|
||||
#define BIT_1C(A) ((A) & 0x10000000)
|
||||
#define BIT_1D(A) ((A) & 0x20000000)
|
||||
#define BIT_1E(A) ((A) & 0x40000000)
|
||||
#define BIT_1F(A) ((A) & 0x80000000)
|
||||
|
||||
/* These are the CPU types understood by this disassembler */
|
||||
#define TYPE_68000 1
|
||||
#define TYPE_68010 2
|
||||
#define TYPE_68020 4
|
||||
#define TYPE_68030 8
|
||||
#define TYPE_68040 16
|
||||
#define TYPE_68060 32
|
||||
#define TYPE_CPU32 64
|
||||
|
||||
#define M68000_ONLY TYPE_68000
|
||||
|
||||
#define M68010_ONLY TYPE_68010
|
||||
#define M68010_LESS (TYPE_68000 | TYPE_68010)
|
||||
#define M68010_PLUS \
|
||||
(TYPE_68010 | TYPE_68020 | TYPE_68030 | TYPE_68040 | TYPE_68060)
|
||||
|
||||
#define M68020_ONLY TYPE_68020
|
||||
#define M68020_LESS (TYPE_68010 | TYPE_68020)
|
||||
#define M68020_PLUS (TYPE_68020 | TYPE_68030 | TYPE_68040 | TYPE_68060)
|
||||
|
||||
#define M68030_ONLY TYPE_68030
|
||||
#define M68030_LESS (TYPE_68010 | TYPE_68020 | TYPE_68030)
|
||||
#define M68030_PLUS (TYPE_68030 | TYPE_68040 | TYPE_68060)
|
||||
|
||||
#define M68040_PLUS (TYPE_68040 | TYPE_68060)
|
||||
|
||||
/* Extension word formats */
|
||||
#define EXT_8BIT_DISPLACEMENT(A) ((A) & 0xff)
|
||||
#define EXT_FULL(A) BIT_8(A)
|
||||
#define EXT_EFFECTIVE_ZERO(A) (((A) & 0xe4) == 0xc4 || ((A) & 0xe2) == 0xc0)
|
||||
#define EXT_BASE_REGISTER_PRESENT(A) (!BIT_7(A))
|
||||
#define EXT_INDEX_REGISTER_PRESENT(A) (!BIT_6(A))
|
||||
#define EXT_INDEX_REGISTER(A) (((A) >> 12) & 7)
|
||||
#define EXT_INDEX_PRE_POST(A) (EXT_INDEX_REGISTER_PRESENT(A) && (A) & 3)
|
||||
#define EXT_INDEX_PRE(A) \
|
||||
(EXT_INDEX_REGISTER_PRESENT(A) && ((A) & 7) < 4 && ((A) & 7) != 0)
|
||||
#define EXT_INDEX_POST(A) (EXT_INDEX_REGISTER_PRESENT(A) && ((A) & 7) > 4)
|
||||
#define EXT_INDEX_SCALE(A) (((A) >> 9) & 3)
|
||||
#define EXT_INDEX_LONG(A) BIT_B(A)
|
||||
#define EXT_INDEX_AR(A) BIT_F(A)
|
||||
#define EXT_BASE_DISPLACEMENT_PRESENT(A) (((A) & 0x30) > 0x10)
|
||||
#define EXT_BASE_DISPLACEMENT_WORD(A) (((A) & 0x30) == 0x20)
|
||||
#define EXT_BASE_DISPLACEMENT_LONG(A) (((A) & 0x30) == 0x30)
|
||||
/* Outer displacement is present when I/IS[1:0] (bits 1-0) is 2 (word) or 3 (long).
|
||||
* This applies regardless of the IS bit (bit 6): when index is suppressed,
|
||||
* I/IS values 5-7 mirror 1-3 (just indirect instead of postindexed).
|
||||
* The old check ((A) & 0x47) < 0x44 incorrectly excluded IS=1 cases
|
||||
* (I/IS=6,7) which DO have outer displacements per the M68K spec.
|
||||
*/
|
||||
#define EXT_OUTER_DISPLACEMENT_PRESENT(A) (((A) & 3) > 1)
|
||||
#define EXT_OUTER_DISPLACEMENT_WORD(A) (((A) & 3) == 2)
|
||||
#define EXT_OUTER_DISPLACEMENT_LONG(A) (((A) & 3) == 3)
|
||||
|
||||
#define IS_BITSET(val, b) ((val) & (1 << (b)))
|
||||
#define BITFIELD_MASK(sb, eb) (((1 << ((sb) + 1)) - 1) & (~((1 << (eb)) - 1)))
|
||||
#define BITFIELD(val, sb, eb) ((BITFIELD_MASK(sb, eb) & (val)) >> (eb))
|
||||
|
||||
/* Bitfield offset/width encoding.
|
||||
* Public decode macros (M68K_BF_*) live in <capstone/m68k.h>.
|
||||
* Internal aliases kept for brevity within arch code. */
|
||||
#define M68K_BITFIELD_REG_FLAG M68K_BF_REG_FLAG
|
||||
#define M68K_BITFIELD_IS_REG(v) M68K_BF_IS_REG(v)
|
||||
#define M68K_BITFIELD_REG_NUM(v) M68K_BF_REG_NUM(v)
|
||||
#define M68K_BITFIELD_ENCODE_REG(regnum) (((regnum) & 7) | M68K_BF_REG_FLAG)
|
||||
|
||||
/* ── Coprocessor ID (CpID) ───────────────────────────────────────────
|
||||
* Bits 11:9 of the F-line instruction word select the coprocessor. */
|
||||
#define M68K_CPID(info) (((info)->ir >> 9) & 7)
|
||||
|
||||
#define M68K_CPID_MMU 0 /* PMMU (68030/68851) */
|
||||
#define M68K_CPID_FPU 1 /* FPU (68881/68882/internal) */
|
||||
#define M68K_CPID_CACHE 2 /* Cache ops -- cinvl/cpushl on 68040+ */
|
||||
|
||||
/* ── IR bit-field helpers ────────────────────────────────────────────
|
||||
* Extract commonly-used fields from the first instruction word. */
|
||||
|
||||
/* 6-bit coprocessor condition (bits 5:0 of IR). */
|
||||
#define M68K_IR_CONDITION(info) ((info)->ir & 0x3f)
|
||||
|
||||
/* cinv/cpush: select cpush(1) vs cinv(0) -- bit 5 of IR. */
|
||||
#define M68K_IR_IS_CPUSH(info) (((info)->ir >> 5) & 1)
|
||||
|
||||
/* cinv/cpush: cache scope -- bits 4:3 of IR (0=invalid,1=line,2=page,3=all). */
|
||||
#define M68K_IR_CACHE_SCOPE(info) (((info)->ir >> 3) & 3)
|
||||
|
||||
/* cinv/cpush: cache selector -- bits 7:6 of IR (DC/IC/BC). */
|
||||
#define M68K_IR_CACHE_SEL(info) (((info)->ir >> 6) & 3)
|
||||
|
||||
/* ── FPU extension-word bit-field helpers ────────────────────────────
|
||||
* The FPU command word is the 16-bit extension following the F-line. */
|
||||
|
||||
/* R/M bit (bit 14): 1 = source from EA, 0 = source from FP register. */
|
||||
#define M68K_FEXT_RM(ext) (((ext) >> 14) & 1)
|
||||
|
||||
/* Type / command class (bits 15:13). */
|
||||
#define M68K_FEXT_TYPE(ext) (((ext) >> 13) & 7)
|
||||
|
||||
/* Source specifier (bits 12:10) -- data format when R/M=1. */
|
||||
#define M68K_FEXT_SRC(ext) (((ext) >> 10) & 7)
|
||||
|
||||
/* Destination FP register (bits 9:7). */
|
||||
#define M68K_FEXT_DST(ext) (((ext) >> 7) & 7)
|
||||
|
||||
/* Opmode (bits 5:0) -- FPU operation selector. */
|
||||
#define M68K_FEXT_OPMODE(ext) ((ext) & 0x3f)
|
||||
|
||||
/* Single/double precision flag (bit 6) -- 68040+ only. */
|
||||
#define M68K_FEXT_SD_FLAG(ext) (((ext) >> 6) & 1)
|
||||
|
||||
/* FMOVECR signature: bits 15:10 == 0x17 (010111b). */
|
||||
#define M68K_FEXT_IS_FMOVECR(ext) (BITFIELD((ext), 15, 10) == 0x17)
|
||||
|
||||
/* Register-select field for FMOVE to/from FPCR/FPSR/FPIAR (bits 12:10). */
|
||||
#define M68K_FEXT_REGSEL(ext) (((ext) >> 10) & 7)
|
||||
|
||||
/* Direction bit for FMOVE FPCR (bit 13): 0 = ea->fpcr, 1 = fpcr->ea. */
|
||||
#define M68K_FEXT_DIR(ext) (((ext) >> 13) & 1)
|
||||
|
||||
/* ── FPU condition-code mask ─────────────────────────────────────────
|
||||
* FBcc/FDBcc/FScc/FTRAPcc encode the FP condition in bits 5,3:0
|
||||
* of the extension word (or IR for FBcc). Bit 4 is always 0,
|
||||
* yielding the 0x2f mask. */
|
||||
#define M68K_FP_COND(x) ((x) & 0x2f)
|
||||
|
||||
/* Maximum valid condition codes per coprocessor. */
|
||||
#define M68K_PMMU_MAX_COND 16
|
||||
#define M68K_FPU_MAX_COND 32
|
||||
|
||||
/* ── FPU source-format constants (bits 12:10 of ext word) ───────────*/
|
||||
#define M68K_FPSRC_LONG 0x00 /* .l -- 32-bit integer */
|
||||
#define M68K_FPSRC_SINGLE 0x01 /* .s -- 32-bit IEEE single */
|
||||
#define M68K_FPSRC_EXTENDED 0x02 /* .x -- 96-bit extended real */
|
||||
#define M68K_FPSRC_PACKED 0x03 /* .p -- 96-bit packed decimal */
|
||||
#define M68K_FPSRC_WORD 0x04 /* .w -- 16-bit integer */
|
||||
#define M68K_FPSRC_DOUBLE 0x05 /* .d -- 64-bit IEEE double */
|
||||
#define M68K_FPSRC_BYTE 0x06 /* .b -- 8-bit integer */
|
||||
|
||||
/* ── FPU special raw opmodes (before SD-flag masking) ───────────────
|
||||
* FSSQRT/FDSQRT have raw 7-bit opmodes 0x41/0x45. After the 6-bit
|
||||
* truncation (& 0x3f) they become 0x01/0x05 with the SD flag set. */
|
||||
#define M68K_FPOP_FSSQRT_RAW 0x01 /* 0x41 & 0x3f */
|
||||
#define M68K_FPOP_FDSQRT_RAW 0x05 /* 0x45 & 0x3f */
|
||||
|
||||
/* ── CPU-type guard macros ───────────────────────────────────────────
|
||||
* These reference the `info` parameter available at each call site.
|
||||
* They early-return from the calling function on type mismatch. */
|
||||
|
||||
#define LIMIT_CPU_TYPES(info, ALLOWED_CPU_TYPES) \
|
||||
do { \
|
||||
if (!(info->type & ALLOWED_CPU_TYPES)) { \
|
||||
d68000_invalid(info); \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Like LIMIT_CPU_TYPES but also reverses the instruction word consumption,
|
||||
* so the invalid instruction produces size=0 (not decoded) instead of size=2.
|
||||
* Use for handlers that replace d68000_invalid in the dispatch table. */
|
||||
#define LIMIT_CPU_TYPES_UNDECODED(info, ALLOWED_CPU_TYPES) \
|
||||
do { \
|
||||
if (!(info->type & ALLOWED_CPU_TYPES)) { \
|
||||
info->pc -= 2; \
|
||||
d68000_invalid(info); \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Like LIMIT_CPU_TYPES but also rejects CPU32. CPU32 shares TYPE_68020 but
|
||||
* lacks some 68020 instructions (CAS, CAS2, CHK.L, PACK, UNPK). */
|
||||
#define LIMIT_CPU_TYPES_NOT_CPU32(info, ALLOWED_CPU_TYPES) \
|
||||
do { \
|
||||
if (!(info->type & (ALLOWED_CPU_TYPES)) || \
|
||||
(info->type & TYPE_CPU32)) { \
|
||||
d68000_invalid(info); \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Require CpID == FPU. Rejects all other coprocessor IDs.
|
||||
* Used by cpDBcc, cpScc, cpTRAPcc handlers. */
|
||||
#define REQUIRE_CPID_FPU(info) \
|
||||
do { \
|
||||
if (M68K_CPID(info) != M68K_CPID_FPU) { \
|
||||
d68000_invalid(info); \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Require CpID == MMU or CpID == FPU.
|
||||
* CpID MMU is rejected on CPU32 (no PMMU). Used by cpSAVE/cpRESTORE. */
|
||||
#define REQUIRE_CPID_FPU_OR_PMMU(info) \
|
||||
do { \
|
||||
int _cpid = M68K_CPID(info); \
|
||||
if (_cpid == M68K_CPID_MMU && ((info)->type & TYPE_CPU32)) { \
|
||||
d68000_invalid(info); \
|
||||
return; \
|
||||
} \
|
||||
if (_cpid != M68K_CPID_MMU && _cpid != M68K_CPID_FPU) { \
|
||||
d68000_invalid(info); \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* ── EA / immediate convenience aliases ─────────────────────────────
|
||||
* Shorthand wrappers around the sized get_ea_mode_str / get_imm_str
|
||||
* functions. These expand at the call site where 'info' is in scope. */
|
||||
|
||||
/* Fake a split interface */
|
||||
#define get_ea_mode_str_8(instruction) get_ea_mode_str(instruction, 0)
|
||||
#define get_ea_mode_str_16(instruction) get_ea_mode_str(instruction, 1)
|
||||
#define get_ea_mode_str_32(instruction) get_ea_mode_str(instruction, 2)
|
||||
|
||||
#define get_imm_str_s8() get_imm_str_s(0)
|
||||
#define get_imm_str_s16() get_imm_str_s(1)
|
||||
#define get_imm_str_s32() get_imm_str_s(2)
|
||||
|
||||
#define get_imm_str_u8() get_imm_str_u(0)
|
||||
#define get_imm_str_u16() get_imm_str_u(1)
|
||||
#define get_imm_str_u32() get_imm_str_u(2)
|
||||
|
||||
/* ── Operand access shorthands ──────────────────────────────────────
|
||||
* Quick access to the operand array and instruction size via `info`. */
|
||||
#define IOPS(I) (&info->extension.operands[(I)])
|
||||
#define ISIZE (info->extension.op_size.cpu_size)
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================ INTERNAL TYPES ============================ */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Private, For internal use only */
|
||||
typedef struct m68k_info {
|
||||
const uint8_t *code;
|
||||
size_t code_len;
|
||||
uint64_t baseAddress;
|
||||
MCInst *inst;
|
||||
unsigned int pc; /* program counter */
|
||||
unsigned int ir; /* instruction register */
|
||||
unsigned int type;
|
||||
unsigned int address_mask; /* Address mask to simulate address lines */
|
||||
cs_m68k extension;
|
||||
uint16_t regs_read
|
||||
[MAX_IMPL_R_REGS]; // list of implicit registers read by this insn
|
||||
uint8_t regs_read_count; // number of implicit registers read by this insn
|
||||
uint16_t regs_write
|
||||
[MAX_IMPL_W_REGS]; // list of implicit registers modified by this insn
|
||||
uint8_t regs_write_count; // number of implicit registers modified by this insn
|
||||
uint8_t groups[MAX_NUM_GROUPS];
|
||||
uint8_t groups_count;
|
||||
} m68k_info;
|
||||
|
||||
bool M68K_getInstruction(csh ud, const uint8_t *code, size_t code_len,
|
||||
MCInst *instr, uint16_t *size, uint64_t address,
|
||||
void *info);
|
||||
|
||||
#endif
|
||||
+588
@@ -0,0 +1,588 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* M68K Backend by Daniel Collin <daniel@collin.com> 2015-2016 */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "M68KInstPrinter.h"
|
||||
|
||||
#include "M68KDisassembler.h"
|
||||
|
||||
#include "../../Mapping.h"
|
||||
#include "../../cs_priv.h"
|
||||
#include "../../utils.h"
|
||||
|
||||
#include "../../MCInst.h"
|
||||
#include "../../MCInstrDesc.h"
|
||||
#include "../../MCRegisterInfo.h"
|
||||
|
||||
#ifndef CAPSTONE_DIET
|
||||
static const char s_spacing[] = " ";
|
||||
|
||||
static const char *const s_reg_names[] = {
|
||||
"invalid", "d0", "d1", "d2", "d3", "d4", "d5", "d6",
|
||||
"d7", "a0", "a1", "a2", "a3", "a4", "a5", "a6",
|
||||
"a7", "fp0", "fp1", "fp2", "fp3", "fp4", "fp5", "fp6",
|
||||
"fp7", "pc", "sr", "ccr", "sfc", "dfc", "usp", "vbr",
|
||||
"cacr", "caar", "msp", "isp", "tc", "itt0", "itt1", "dtt0",
|
||||
"dtt1", "mmusr", "urp", "srp",
|
||||
|
||||
"fpcr", "fpsr", "fpiar",
|
||||
|
||||
"tt0", "tt1", "crp",
|
||||
};
|
||||
|
||||
static const char *const s_instruction_names[] = {
|
||||
"invalid", "abcd", "add", "adda", "addi", "addq",
|
||||
"addx", "and", "andi", "asl", "asr", "bhs",
|
||||
"blo", "bhi", "bls", "bcc", "bcs", "bne",
|
||||
"beq", "bvc", "bvs", "bpl", "bmi", "bge",
|
||||
"blt", "bgt", "ble", "bra", "bsr", "bchg",
|
||||
"bclr", "bset", "btst", "bfchg", "bfclr", "bfexts",
|
||||
"bfextu", "bfffo", "bfins", "bfset", "bftst", "bkpt",
|
||||
"callm", "cas", "cas2", "chk", "chk2", "clr",
|
||||
"cmp", "cmpa", "cmpi", "cmpm", "cmp2", "cinvl",
|
||||
"cinvp", "cinva", "cpushl", "cpushp", "cpusha", "dbt",
|
||||
"dbf", "dbhi", "dbls", "dbcc", "dbcs", "dbne",
|
||||
"dbeq", "dbvc", "dbvs", "dbpl", "dbmi", "dbge",
|
||||
"dblt", "dbgt", "dble", "dbra", "divs", "divsl",
|
||||
"divu", "divul", "eor", "eori", "exg", "ext",
|
||||
"extb", "fabs", "fsabs", "fdabs", "facos", "fadd",
|
||||
"fsadd", "fdadd", "fasin", "fatan", "fatanh", "fbf",
|
||||
"fbeq", "fbogt", "fboge", "fbolt", "fbole", "fbogl",
|
||||
"fbor", "fbun", "fbueq", "fbugt", "fbuge", "fbult",
|
||||
"fbule", "fbne", "fbt", "fbsf", "fbseq", "fbgt",
|
||||
"fbge", "fblt", "fble", "fbgl", "fbgle", "fbngle",
|
||||
"fbngl", "fbnle", "fbnlt", "fbnge", "fbngt", "fbsne",
|
||||
"fbst", "fcmp", "fcos", "fcosh", "fdbf", "fdbeq",
|
||||
"fdbogt", "fdboge", "fdbolt", "fdbole", "fdbogl", "fdbor",
|
||||
"fdbun", "fdbueq", "fdbugt", "fdbuge", "fdbult", "fdbule",
|
||||
"fdbne", "fdbt", "fdbsf", "fdbseq", "fdbgt", "fdbge",
|
||||
"fdblt", "fdble", "fdbgl", "fdbgle", "fdbngle", "fdbngl",
|
||||
"fdbnle", "fdbnlt", "fdbnge", "fdbngt", "fdbsne", "fdbst",
|
||||
"fdiv", "fsdiv", "fddiv", "fetox", "fetoxm1", "fgetexp",
|
||||
"fgetman", "fint", "fintrz", "flog10", "flog2", "flogn",
|
||||
"flognp1", "fmod", "fmove", "fsmove", "fdmove", "fmovecr",
|
||||
"fmovem", "fmul", "fsmul", "fdmul", "fneg", "fsneg",
|
||||
"fdneg", "fnop", "frem", "frestore", "fsave", "fscale",
|
||||
"fsgldiv", "fsglmul", "fsin", "fsincos", "fsinh", "fsqrt",
|
||||
"fssqrt", "fdsqrt", "fsf", "fseq", "fsogt", "fsoge",
|
||||
"fsolt", "fsole", "fsogl", "fsor", "fsun", "fsueq",
|
||||
"fsugt", "fsuge", "fsult", "fsule", "fsne", "fst",
|
||||
"fssf", "fsseq", "fsgt", "fsge", "fslt", "fsle",
|
||||
"fsgl", "fsgle", "fsngle", "fsngl", "fsnle", "fsnlt",
|
||||
"fsnge", "fsngt", "fssne", "fsst", "fsub", "fssub",
|
||||
"fdsub", "ftan", "ftanh", "ftentox", "ftrapf", "ftrapeq",
|
||||
"ftrapogt", "ftrapoge", "ftrapolt", "ftrapole", "ftrapogl", "ftrapor",
|
||||
"ftrapun", "ftrapueq", "ftrapugt", "ftrapuge", "ftrapult", "ftrapule",
|
||||
"ftrapne", "ftrapt", "ftrapsf", "ftrapseq", "ftrapgt", "ftrapge",
|
||||
"ftraplt", "ftraple", "ftrapgl", "ftrapgle", "ftrapngle", "ftrapngl",
|
||||
"ftrapnle", "ftrapnlt", "ftrapnge", "ftrapngt", "ftrapsne", "ftrapst",
|
||||
"ftst", "ftwotox", "halt", "illegal", "jmp", "jsr",
|
||||
"lea", "link", "lpstop", "lsl", "lsr", "move",
|
||||
"movea", "movec", "movem", "movep", "moveq", "moves",
|
||||
"move16", "muls", "mulu", "nbcd", "neg", "negx",
|
||||
"nop", "not", "or", "ori", "pack", "pea",
|
||||
"pflush", "pflusha", "pflushan", "pflushn", "ploadr", "ploadw",
|
||||
"plpar", "plpaw", "pmove", "pmovefd", "ptestr", "ptestw",
|
||||
"pulse", "rems", "remu", "reset", "rol", "ror",
|
||||
"roxl", "roxr", "rtd", "rte", "rtm", "rtr",
|
||||
"rts", "sbcd", "st", "sf", "shi", "sls",
|
||||
"scc", "shs", "scs", "slo", "sne", "seq",
|
||||
"svc", "svs", "spl", "smi", "sge", "slt",
|
||||
"sgt", "sle", "stop", "sub", "suba", "subi",
|
||||
"subq", "subx", "swap", "tas", "trap", "trapv",
|
||||
"trapt", "trapf", "traphi", "trapls", "trapcc", "traphs",
|
||||
"trapcs", "traplo", "trapne", "trapeq", "trapvc", "trapvs",
|
||||
"trappl", "trapmi", "trapge", "traplt", "trapgt", "traple",
|
||||
"tst", "unlk", "unpk", "bgnd", "tbls", "tblu",
|
||||
"tblsn", "tblun",
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef CAPSTONE_DIET
|
||||
static const char *getRegName(m68k_reg reg)
|
||||
{
|
||||
return s_reg_names[(int)reg];
|
||||
}
|
||||
|
||||
static void printRegbits(SStream *O, bool *need_sep, uint32_t data,
|
||||
const char *prefix)
|
||||
{
|
||||
unsigned int first;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; ++i) {
|
||||
if (!(data & (1 << i)))
|
||||
continue;
|
||||
|
||||
first = i;
|
||||
while (i < 7 && (data & (1 << (i + 1))))
|
||||
i++;
|
||||
|
||||
if (*need_sep)
|
||||
SStream_concat1(O, '/');
|
||||
*need_sep = true;
|
||||
|
||||
SStream_concat(O, "%s%" PRIu32, prefix, first);
|
||||
|
||||
if ((unsigned int)i > first)
|
||||
SStream_concat(O, "-%s%" PRIu32, prefix,
|
||||
(unsigned int)i);
|
||||
}
|
||||
}
|
||||
|
||||
static void registerBits(SStream *O, const cs_m68k_op *op)
|
||||
{
|
||||
unsigned int data = op->register_bits;
|
||||
bool need_sep = false;
|
||||
|
||||
if (!data) {
|
||||
SStream_concat(O, "%s", "#$0");
|
||||
return;
|
||||
}
|
||||
|
||||
printRegbits(O, &need_sep, data & 0xff, "d");
|
||||
printRegbits(O, &need_sep, (data >> 8) & 0xff, "a");
|
||||
printRegbits(O, &need_sep, (data >> 16) & 0xff, "fp");
|
||||
}
|
||||
|
||||
static void registerPair(SStream *O, const cs_m68k_op *op)
|
||||
{
|
||||
SStream_concat(O, "%s:%s", s_reg_names[op->reg_pair.reg_0],
|
||||
s_reg_names[op->reg_pair.reg_1]);
|
||||
}
|
||||
|
||||
static void printScaleFactor(SStream *O, uint8_t scale, int threshold)
|
||||
{
|
||||
if (scale > threshold)
|
||||
SStream_concat(O, "%s*%s%" PRId8, s_spacing, s_spacing, scale);
|
||||
}
|
||||
|
||||
static void printIndexReg(SStream *O, const cs_m68k_op *op)
|
||||
{
|
||||
SStream_concat(O, "%s.%c", getRegName(op->mem.index_reg),
|
||||
op->mem.index_size ? 'l' : 'w');
|
||||
}
|
||||
|
||||
static void printBitfield(SStream *O, const cs_m68k_op *op)
|
||||
{
|
||||
if (!op->mem.bitfield)
|
||||
return;
|
||||
SStream_concat0(O, "{");
|
||||
if (M68K_BF_IS_REG(op->mem.offset))
|
||||
SStream_concat(O, "d%" PRId8, M68K_BF_REG_NUM(op->mem.offset));
|
||||
else
|
||||
SStream_concat(O, "%" PRId8, op->mem.offset);
|
||||
SStream_concat0(O, ":");
|
||||
if (M68K_BF_IS_REG(op->mem.width))
|
||||
SStream_concat(O, "d%" PRId8, M68K_BF_REG_NUM(op->mem.width));
|
||||
else
|
||||
SStream_concat(O, "%" PRId8, op->mem.width);
|
||||
SStream_concat0(O, "}");
|
||||
}
|
||||
|
||||
static void printImmediate(SStream *O, const cs_m68k *inst,
|
||||
const cs_m68k_op *op)
|
||||
{
|
||||
if (inst->op_size.type == M68K_SIZE_TYPE_FPU) {
|
||||
#if defined(_KERNEL_MODE)
|
||||
SStream_concat(O, "#<float_point_unsupported>");
|
||||
return;
|
||||
#else
|
||||
if (inst->op_size.fpu_size == M68K_FPU_SIZE_SINGLE)
|
||||
SStream_concat(O, "#%f", op->simm);
|
||||
else if (inst->op_size.fpu_size == M68K_FPU_SIZE_DOUBLE)
|
||||
SStream_concat(O, "#%f", op->dimm);
|
||||
else
|
||||
SStream_concat(O, "#<unsupported>");
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
SStream_concat(O, "#$%" PRIx64, op->imm);
|
||||
}
|
||||
|
||||
static void printIndex8BitDisp(SStream *O, unsigned int pc,
|
||||
const cs_m68k_op *op)
|
||||
{
|
||||
if (op->address_mode == M68K_AM_PCI_INDEX_8_BIT_DISP) {
|
||||
SStream_concat(O, "$%" PRIx32 "(pc,%s", pc + 2 + op->mem.disp,
|
||||
s_spacing);
|
||||
} else {
|
||||
SStream_concat(O, "%s$%" PRIx16 "(%s,%s",
|
||||
op->mem.disp < 0 ? "-" : "", abs(op->mem.disp),
|
||||
getRegName(op->mem.base_reg), s_spacing);
|
||||
}
|
||||
printIndexReg(O, op);
|
||||
printScaleFactor(O, op->mem.scale, 1);
|
||||
SStream_concat0(O, ")");
|
||||
}
|
||||
|
||||
static void printRegAddrMode(SStream *O, unsigned int pc, const cs_m68k_op *op)
|
||||
{
|
||||
switch (op->address_mode) {
|
||||
case M68K_AM_REG_DIRECT_DATA:
|
||||
SStream_concat(O, "d%" PRId32, (op->reg - M68K_REG_D0));
|
||||
break;
|
||||
case M68K_AM_REG_DIRECT_ADDR:
|
||||
SStream_concat(O, "a%" PRId32, (op->reg - M68K_REG_A0));
|
||||
break;
|
||||
case M68K_AM_REGI_ADDR:
|
||||
SStream_concat(O, "(a%" PRId32 ")", (op->reg - M68K_REG_A0));
|
||||
break;
|
||||
case M68K_AM_REGI_ADDR_POST_INC:
|
||||
SStream_concat(O, "(a%" PRId32 ")+", (op->reg - M68K_REG_A0));
|
||||
break;
|
||||
case M68K_AM_REGI_ADDR_PRE_DEC:
|
||||
SStream_concat(O, "-(a%" PRId32 ")", (op->reg - M68K_REG_A0));
|
||||
break;
|
||||
case M68K_AM_REGI_ADDR_DISP:
|
||||
SStream_concat(O, "%s$%" PRIx16 "(a%" PRId32 ")",
|
||||
op->mem.disp < 0 ? "-" : "", abs(op->mem.disp),
|
||||
(op->mem.base_reg - M68K_REG_A0));
|
||||
break;
|
||||
case M68K_AM_PCI_DISP:
|
||||
SStream_concat(O, "$%" PRIx32 "(pc)", pc + 2 + op->mem.disp);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void printBaseDisp(SStream *O, unsigned int pc, const cs_m68k_op *op)
|
||||
{
|
||||
int is_pc = (op->address_mode == M68K_AM_PCI_INDEX_BASE_DISP);
|
||||
|
||||
if (is_pc) {
|
||||
SStream_concat(O, "$%" PRIx32, pc + 2 + op->mem.in_disp);
|
||||
} else if (op->mem.in_disp != 0) {
|
||||
SStream_concat(O, "%s$%" PRIx32,
|
||||
op->mem.in_disp >= 0 ? "" : "-",
|
||||
abs(op->mem.in_disp));
|
||||
}
|
||||
|
||||
SStream_concat0(O, "(");
|
||||
|
||||
if (is_pc) {
|
||||
SStream_concat0(O, "pc");
|
||||
} else if (op->mem.base_reg != M68K_REG_INVALID) {
|
||||
SStream_concat(O, "a%" PRId32, op->mem.base_reg - M68K_REG_A0);
|
||||
}
|
||||
|
||||
if ((is_pc || op->mem.base_reg != M68K_REG_INVALID) &&
|
||||
op->mem.index_reg != M68K_REG_INVALID)
|
||||
SStream_concat(O, ",%s", s_spacing);
|
||||
|
||||
if (op->mem.index_reg != M68K_REG_INVALID) {
|
||||
printIndexReg(O, op);
|
||||
printScaleFactor(O, op->mem.scale, 0);
|
||||
}
|
||||
|
||||
SStream_concat0(O, ")");
|
||||
}
|
||||
|
||||
static void printMemIndirect(SStream *O, unsigned int pc, const cs_m68k_op *op)
|
||||
{
|
||||
int is_pc = (op->address_mode == M68K_AM_PC_MEMI_POST_INDEX ||
|
||||
op->address_mode == M68K_AM_PC_MEMI_PRE_INDEX);
|
||||
int is_post = (op->address_mode == M68K_AM_MEMI_POST_INDEX ||
|
||||
op->address_mode == M68K_AM_PC_MEMI_POST_INDEX);
|
||||
int is_pre = (op->address_mode == M68K_AM_MEMI_PRE_INDEX ||
|
||||
op->address_mode == M68K_AM_PC_MEMI_PRE_INDEX);
|
||||
|
||||
SStream_concat0(O, "([");
|
||||
|
||||
if (is_pc) {
|
||||
SStream_concat(O, "$%" PRIx32, pc + 2 + op->mem.in_disp);
|
||||
} else if (op->mem.in_disp != 0) {
|
||||
SStream_concat(O, "%s$%" PRIx32,
|
||||
op->mem.in_disp >= 0 ? "" : "-",
|
||||
abs(op->mem.in_disp));
|
||||
}
|
||||
|
||||
if (op->mem.base_reg != M68K_REG_INVALID) {
|
||||
if (op->mem.in_disp != 0)
|
||||
SStream_concat(O, ",%s%s", s_spacing,
|
||||
getRegName(op->mem.base_reg));
|
||||
else
|
||||
SStream_concat(O, "%s", getRegName(op->mem.base_reg));
|
||||
}
|
||||
|
||||
if (is_post)
|
||||
SStream_concat0(O, "]");
|
||||
|
||||
if (op->mem.index_reg != M68K_REG_INVALID) {
|
||||
SStream_concat(O, ",%s", s_spacing);
|
||||
printIndexReg(O, op);
|
||||
}
|
||||
|
||||
printScaleFactor(O, op->mem.scale, 0);
|
||||
|
||||
if (is_pre)
|
||||
SStream_concat0(O, "]");
|
||||
|
||||
if (op->mem.out_disp != 0) {
|
||||
SStream_concat(O, ",%s%s$%" PRIx32, s_spacing,
|
||||
op->mem.out_disp >= 0 ? "" : "-",
|
||||
abs(op->mem.out_disp));
|
||||
}
|
||||
|
||||
SStream_concat0(O, ")");
|
||||
}
|
||||
|
||||
static void printAddressingMode(SStream *O, unsigned int pc,
|
||||
const cs_m68k *inst, const cs_m68k_op *op)
|
||||
{
|
||||
switch (op->address_mode) {
|
||||
case M68K_AM_NONE:
|
||||
switch (op->type) {
|
||||
case M68K_OP_REG_BITS:
|
||||
registerBits(O, op);
|
||||
break;
|
||||
case M68K_OP_REG_PAIR:
|
||||
registerPair(O, op);
|
||||
break;
|
||||
case M68K_OP_REG:
|
||||
SStream_concat(O, "%s", s_reg_names[op->reg]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case M68K_AM_REG_DIRECT_DATA:
|
||||
case M68K_AM_REG_DIRECT_ADDR:
|
||||
case M68K_AM_REGI_ADDR:
|
||||
case M68K_AM_REGI_ADDR_POST_INC:
|
||||
case M68K_AM_REGI_ADDR_PRE_DEC:
|
||||
case M68K_AM_REGI_ADDR_DISP:
|
||||
case M68K_AM_PCI_DISP:
|
||||
printRegAddrMode(O, pc, op);
|
||||
break;
|
||||
case M68K_AM_ABSOLUTE_DATA_SHORT:
|
||||
SStream_concat(O, "$%" PRIx32 ".w", (uint32_t)op->imm);
|
||||
break;
|
||||
case M68K_AM_ABSOLUTE_DATA_LONG:
|
||||
SStream_concat(O, "$%" PRIx64 ".l", (uint64_t)op->imm);
|
||||
break;
|
||||
case M68K_AM_IMMEDIATE:
|
||||
printImmediate(O, inst, op);
|
||||
break;
|
||||
case M68K_AM_PCI_INDEX_8_BIT_DISP:
|
||||
case M68K_AM_AREGI_INDEX_8_BIT_DISP:
|
||||
printIndex8BitDisp(O, pc, op);
|
||||
break;
|
||||
case M68K_AM_PCI_INDEX_BASE_DISP:
|
||||
case M68K_AM_AREGI_INDEX_BASE_DISP:
|
||||
printBaseDisp(O, pc, op);
|
||||
break;
|
||||
case M68K_AM_PC_MEMI_POST_INDEX:
|
||||
case M68K_AM_PC_MEMI_PRE_INDEX:
|
||||
case M68K_AM_MEMI_PRE_INDEX:
|
||||
case M68K_AM_MEMI_POST_INDEX:
|
||||
printMemIndirect(O, pc, op);
|
||||
break;
|
||||
case M68K_AM_BRANCH_DISPLACEMENT:
|
||||
SStream_concat(O, "$%" PRIx32, pc + 2 + op->br_disp.disp);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
printBitfield(O, op);
|
||||
}
|
||||
|
||||
static void printCAS2(SStream *O, unsigned int pc, const cs_m68k *ext)
|
||||
{
|
||||
printAddressingMode(O, pc, ext, &ext->operands[0]);
|
||||
SStream_concat0(O, ",");
|
||||
printAddressingMode(O, pc, ext, &ext->operands[1]);
|
||||
SStream_concat0(O, ",");
|
||||
|
||||
SStream_concat(O, "(%s):(%s)",
|
||||
s_reg_names[ext->operands[2].reg_pair.reg_0],
|
||||
s_reg_names[ext->operands[2].reg_pair.reg_1]);
|
||||
}
|
||||
|
||||
static void printCacheOp(SStream *O, unsigned int pc, const cs_m68k *ext)
|
||||
{
|
||||
static const char *const cache_names[] = { "nc", "dc", "ic", "bc" };
|
||||
unsigned int sel = (unsigned int)ext->operands[0].imm;
|
||||
int i;
|
||||
|
||||
if (sel < ARR_SIZE(cache_names))
|
||||
SStream_concat0(O, cache_names[sel]);
|
||||
else
|
||||
SStream_concat(O, "#$%" PRIx64, ext->operands[0].imm);
|
||||
|
||||
for (i = 1; i < ext->op_count; ++i) {
|
||||
SStream_concat(O, ",%s", s_spacing);
|
||||
printAddressingMode(O, pc, ext, &ext->operands[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void printOpSize(SStream *O, const cs_m68k *ext)
|
||||
{
|
||||
switch (ext->op_size.type) {
|
||||
case M68K_SIZE_TYPE_INVALID:
|
||||
break;
|
||||
case M68K_SIZE_TYPE_CPU:
|
||||
switch (ext->op_size.cpu_size) {
|
||||
case M68K_CPU_SIZE_BYTE:
|
||||
SStream_concat0(O, ".b");
|
||||
break;
|
||||
case M68K_CPU_SIZE_WORD:
|
||||
SStream_concat0(O, ".w");
|
||||
break;
|
||||
case M68K_CPU_SIZE_LONG:
|
||||
SStream_concat0(O, ".l");
|
||||
break;
|
||||
case M68K_CPU_SIZE_NONE:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case M68K_SIZE_TYPE_FPU:
|
||||
switch (ext->op_size.fpu_size) {
|
||||
case M68K_FPU_SIZE_SINGLE:
|
||||
SStream_concat0(O, ".s");
|
||||
break;
|
||||
case M68K_FPU_SIZE_DOUBLE:
|
||||
SStream_concat0(O, ".d");
|
||||
break;
|
||||
case M68K_FPU_SIZE_EXTENDED:
|
||||
SStream_concat0(O, ".x");
|
||||
break;
|
||||
case M68K_FPU_SIZE_NONE:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void M68K_printInst(MCInst *MI, SStream *O, void *PrinterInfo)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
m68k_info *info = (m68k_info *)PrinterInfo;
|
||||
cs_m68k *ext = &info->extension;
|
||||
cs_detail *detail = NULL;
|
||||
int i = 0;
|
||||
|
||||
if (detail_is_set(MI)) {
|
||||
detail = get_detail(MI);
|
||||
int regs_read_count = MIN((int)ARR_SIZE(detail->regs_read),
|
||||
info->regs_read_count);
|
||||
int regs_write_count = MIN((int)ARR_SIZE(detail->regs_write),
|
||||
info->regs_write_count);
|
||||
int groups_count =
|
||||
MIN((int)ARR_SIZE(detail->groups), info->groups_count);
|
||||
|
||||
memcpy(&detail->m68k, ext, sizeof(cs_m68k));
|
||||
memcpy(&detail->regs_read, &info->regs_read,
|
||||
regs_read_count * sizeof(info->regs_read[0]));
|
||||
detail->regs_read_count = regs_read_count;
|
||||
|
||||
memcpy(&detail->regs_write, &info->regs_write,
|
||||
regs_write_count * sizeof(info->regs_write[0]));
|
||||
detail->regs_write_count = regs_write_count;
|
||||
|
||||
memcpy(&detail->groups, &info->groups, groups_count);
|
||||
detail->groups_count = groups_count;
|
||||
}
|
||||
|
||||
if (MI->Opcode == M68K_INS_INVALID) {
|
||||
if (ext->op_count)
|
||||
SStream_concat(O, "dc.w $%" PRIx32,
|
||||
(uint32_t)ext->operands[0].imm);
|
||||
else
|
||||
SStream_concat(O, "dc.w $<unknown>");
|
||||
return;
|
||||
}
|
||||
|
||||
SStream_concat0(O, (char *)s_instruction_names[MI->Opcode]);
|
||||
printOpSize(O, ext);
|
||||
SStream_concat0(O, " ");
|
||||
|
||||
if (MI->Opcode == M68K_INS_CAS2) {
|
||||
printCAS2(O, info->pc, ext);
|
||||
return;
|
||||
}
|
||||
|
||||
if (MI->Opcode >= M68K_INS_CINVL && MI->Opcode <= M68K_INS_CPUSHA) {
|
||||
printCacheOp(O, info->pc, ext);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ext->op_count; ++i) {
|
||||
printAddressingMode(O, info->pc, ext, &ext->operands[i]);
|
||||
if ((i + 1) != ext->op_count)
|
||||
SStream_concat(O, ",%s", s_spacing);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *M68K_reg_name(csh handle, unsigned int reg)
|
||||
{
|
||||
#ifdef CAPSTONE_DIET
|
||||
return NULL;
|
||||
#else
|
||||
if (reg >= ARR_SIZE(s_reg_names)) {
|
||||
return NULL;
|
||||
}
|
||||
return s_reg_names[(int)reg];
|
||||
#endif
|
||||
}
|
||||
|
||||
void M68K_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
|
||||
{
|
||||
insn->id = id; // These id's matches for 68k
|
||||
}
|
||||
|
||||
const char *M68K_insn_name(csh handle, unsigned int id)
|
||||
{
|
||||
#ifdef CAPSTONE_DIET
|
||||
return NULL;
|
||||
#else
|
||||
return s_instruction_names[id];
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef CAPSTONE_DIET
|
||||
static const name_map group_name_maps[] = {
|
||||
{ M68K_GRP_INVALID, NULL },
|
||||
{ M68K_GRP_JUMP, "jump" },
|
||||
{ M68K_GRP_RET, "ret" },
|
||||
{ M68K_GRP_IRET, "iret" },
|
||||
{ M68K_GRP_BRANCH_RELATIVE, "branch_relative" },
|
||||
};
|
||||
#endif
|
||||
|
||||
const char *M68K_group_name(csh handle, unsigned int id)
|
||||
{
|
||||
#ifndef CAPSTONE_DIET
|
||||
return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef CAPSTONE_DIET
|
||||
void M68K_reg_access(const cs_insn *insn, cs_regs regs_read,
|
||||
uint8_t *regs_read_count, cs_regs regs_write,
|
||||
uint8_t *regs_write_count)
|
||||
{
|
||||
uint8_t read_count, write_count;
|
||||
|
||||
read_count = insn->detail->regs_read_count;
|
||||
write_count = insn->detail->regs_write_count;
|
||||
|
||||
// implicit registers
|
||||
memcpy(regs_read, insn->detail->regs_read,
|
||||
read_count * sizeof(insn->detail->regs_read[0]));
|
||||
memcpy(regs_write, insn->detail->regs_write,
|
||||
write_count * sizeof(insn->detail->regs_write[0]));
|
||||
|
||||
*regs_read_count = read_count;
|
||||
*regs_write_count = write_count;
|
||||
}
|
||||
#endif
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* M68K Backend by Daniel Collin <daniel@collin.com> 2015 */
|
||||
|
||||
#ifndef CS_M68KINSTPRINTER_H
|
||||
#define CS_M68KINSTPRINTER_H
|
||||
|
||||
#include "capstone/capstone.h"
|
||||
#include "../../MCRegisterInfo.h"
|
||||
#include "../../MCInst.h"
|
||||
|
||||
struct SStream;
|
||||
|
||||
void M68K_init(MCRegisterInfo *MRI);
|
||||
void M68K_printInst(MCInst *MI, struct SStream *O, void *Info);
|
||||
const char *M68K_reg_name(csh handle, unsigned int reg);
|
||||
void M68K_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id);
|
||||
const char *M68K_insn_name(csh handle, unsigned int id);
|
||||
const char *M68K_group_name(csh handle, unsigned int id);
|
||||
void M68K_post_printer(csh handle, cs_insn *flat_insn, char *insn_asm,
|
||||
MCInst *mci);
|
||||
#ifndef CAPSTONE_DIET
|
||||
void M68K_reg_access(const cs_insn *insn, cs_regs regs_read,
|
||||
uint8_t *regs_read_count, cs_regs regs_write,
|
||||
uint8_t *regs_write_count);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+65540
File diff suppressed because it is too large
Load Diff
+44
@@ -0,0 +1,44 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* M68K Backend by Daniel Collin <daniel@collin.com> 2015 */
|
||||
|
||||
#ifdef CAPSTONE_HAS_M68K
|
||||
|
||||
#include "../../utils.h"
|
||||
#include "../../MCRegisterInfo.h"
|
||||
#include "M68KDisassembler.h"
|
||||
#include "M68KInstPrinter.h"
|
||||
#include "M68KModule.h"
|
||||
|
||||
cs_err M68K_global_init(cs_struct *ud)
|
||||
{
|
||||
m68k_info *info;
|
||||
|
||||
info = cs_mem_calloc(sizeof(m68k_info), 1);
|
||||
if (!info) {
|
||||
return CS_ERR_MEM;
|
||||
}
|
||||
|
||||
ud->printer = M68K_printInst;
|
||||
ud->printer_info = info;
|
||||
ud->getinsn_info = NULL;
|
||||
ud->disasm = M68K_getInstruction;
|
||||
ud->skipdata_size = 2;
|
||||
ud->post_printer = NULL;
|
||||
|
||||
ud->reg_name = M68K_reg_name;
|
||||
ud->insn_id = M68K_get_insn_id;
|
||||
ud->insn_name = M68K_insn_name;
|
||||
ud->group_name = M68K_group_name;
|
||||
#ifndef CAPSTONE_DIET
|
||||
ud->reg_access = M68K_reg_access;
|
||||
#endif
|
||||
|
||||
return CS_ERR_OK;
|
||||
}
|
||||
|
||||
cs_err M68K_option(cs_struct *handle, cs_opt_type type, size_t value)
|
||||
{
|
||||
return CS_ERR_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By Travis Finkenauer <tmfinken@gmail.com>, 2018 */
|
||||
|
||||
#ifndef CS_M68K_MODULE_H
|
||||
#define CS_M68K_MODULE_H
|
||||
|
||||
#include "../../utils.h"
|
||||
|
||||
cs_err M68K_global_init(cs_struct *ud);
|
||||
cs_err M68K_option(cs_struct *handle, cs_opt_type type, size_t value);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user