From 22b4d0eb41ead00ef556c4b1960a5569212c54a5 Mon Sep 17 00:00:00 2001 From: Wolfgang Schwotzer Date: Sat, 21 Oct 2017 15:44:36 +0200 Subject: [PATCH] M680X: Target ready for pull request (#1034) * Added new M680X target. Supports M6800/1/2/3/9, HD6301 * M680X: Reformat for coding guide lines. Set alphabetical order in HACK.TXT * M680X: Prepare for python binding. Move cs_m680x, m680x_insn to m680x_info. Chec > k cpu type, no default. * M680X: Add python bindings. Added python tests. * M680X: Added cpu types to usage message. * cstool: Avoid segfault for invalid . * Make test_m680x.c/test_m680x.py output comparable (diff params: -bu). Keep xprint.py untouched. * M680X: Update CMake/make for m680x support. Update .gitignore. * M680X: Reduce compiler warnings. * M680X: Reduce compiler warnings. * M680X: Reduce compiler warnings. * M680X: Make test_m680x.c/test_m680x.py output comparable (diff params: -bu). * M680X: Add ocaml bindings and tests. * M680X: Add java bindings and tests. * M680X: Added tests for all indexed addressing modes. C/Python/Ocaml * M680X: Naming, use page1 for PAGE1 instructions (without prefix). * M680X: Naming, use page1 for PAGE1 instructions (without prefix). * M680X: Used M680X_FIRST_OP_IN_MNEM in tests C/python/java/ocaml. * M680X: Added access property to cs_m680x_op. * M680X: Added operand size. * M680X: Remove compiler warnings. * M680X: Added READ/WRITE access property per operator. * M680X: Make reg_inherent_hdlr independent of CPU type. * M680X: Add HD6309 support + bug fixes * M680X: Remove errors and warning. * M680X: Add Bcc/LBcc to group BRAREL (relative branch). * M680X: Add group JUMP to BVS/BVC/LBVS/LBVC. Remove BRAREL from BRN/LBRN. * M680X: Remove LBRN from group BRAREL. * M680X: Refactored cpu_type initialization for better readability. * M680X: Add two operands for insn having two reg. in mnemonic. e.g. ABX. * M680X: Remove typo in cstool.c * M680X: Some format improvements in changed_regs. * M680X: Remove insn id string list from tests (C/python/java/ocaml). * M680X: SEXW, set access of reg. D to WRITE. * M680X: Sort changed_regs in increasing m680x_insn order. * M680X: Add M68HC11 support + Reduced from two to one INDEXED operand. * M680X: cstool, also write '(in mnemonic)' for second reg. operand. * M680X: Add BRN/LBRN to group JUMP and BRAREL. * M680X: For Bcc/LBcc/BRSET/BRCLR set reg. CC to read access. * M680X: Correctly print negative immediate values with option CS_OPT_UNSIGNED. * M680X: Rename some instruction handlers. * M680X: Add M68HC05 support. * M680X: Dont print prefix '<' for direct addr. mode. * M680X: Add M68HC08 support + resorted tables + bug fixes. * M680X: Add Freescale HCS08 support. * M680X: Changed group names, avoid spaces. * M680X: Refactoring, rename addessing mode handlers. * M680X: indexed addr. mode, changed pre/post inc-/decrement representation. * M680X: Rename some M6809/HD6309 specific functions. * M680X: Add CPU12 (68HC12/HCS12) support. * M680X: Correctly display illegal instruction as FCB . * M680X: bugfix: BRA/BRN/BSR/LBRA/LBRN/LBSR does not read CC reg. * M680X: bugfix: Correctly check for sufficient code size for M6809 indexed addressing. * M680X: Better support for changing insn id within handler for addessing mode. * M680X: Remove warnings. * M680X: In set_changed_regs_read_write_counts use own access_mode. * M680X: Split cpu specific tables into separate *.inc files. * M680X: Remove warnings. * M680X: Removed address_mode. Addressing mode is available in operand.type * M680X: Bugfix: BSET/BCLR/BRSET/BRCLR correct read/modify CC reg. * M680X: Remove register TMP1. It is first visible in CPU12X. * M680X: Performance improvement + bug fixes. * M680X: Performance improvement, make cpu_tables const static. * M680X: Simplify operand decoding by using two handlers. * M680X: Replace M680X_OP_INDEX by M680X_OP_CONSTANT + bugfix in java/python/ocaml bindings. * M680X: Format with astyle. * M680X: Update documentation. * M680X: Corrected author for m680x specific files. * M680X: Make max. number of architectures single source. --- .gitignore | 3 + CMakeLists.txt | 24 +- COMPILE_CMAKE.TXT | 3 +- CREDITS.TXT | 2 + HACK.TXT | 1 + Makefile | 17 +- README.md | 2 +- arch/M680X/M680XDisassembler.c | 2305 +++++++++++++++++++++++ arch/M680X/M680XDisassembler.h | 17 + arch/M680X/M680XDisassemblerInternals.h | 57 + arch/M680X/M680XInstPrinter.c | 365 ++++ arch/M680X/M680XInstPrinter.h | 25 + arch/M680X/M680XModule.c | 85 + arch/M680X/cpu12.inc | 335 ++++ arch/M680X/hcs08.inc | 60 + arch/M680X/hd6301.inc | 15 + arch/M680X/hd6309.inc | 259 +++ arch/M680X/insn_props.inc | 367 ++++ arch/M680X/m6800.inc | 277 +++ arch/M680X/m6801.inc | 39 + arch/M680X/m6805.inc | 277 +++ arch/M680X/m6808.inc | 91 + arch/M680X/m6809.inc | 352 ++++ arch/M680X/m6811.inc | 105 ++ bindings/const_generator.py | 5 +- bindings/java/Makefile | 8 +- bindings/java/TestM680x.java | 207 ++ bindings/java/capstone/Capstone.java | 24 +- bindings/java/capstone/M680x.java | 132 ++ bindings/java/capstone/M680x_const.java | 439 +++++ bindings/java/run.sh | 3 +- bindings/ocaml/Makefile | 34 +- bindings/ocaml/capstone.ml | 17 +- bindings/ocaml/m680x.ml | 48 + bindings/ocaml/m680x_const.ml | 435 +++++ bindings/ocaml/ocaml.c | 151 ++ bindings/ocaml/test_m680x.ml | 167 ++ bindings/python/Makefile | 2 +- bindings/python/capstone/__init__.py | 32 +- bindings/python/capstone/m680x.py | 88 + bindings/python/capstone/m680x_const.py | 435 +++++ bindings/python/test_all.py | 4 +- bindings/python/test_basic.py | 2 + bindings/python/test_detail.py | 2 + bindings/python/test_lite.py | 2 + bindings/python/test_m680x.py | 159 ++ config.mk | 2 +- cs.c | 23 +- cs_priv.h | 2 +- cstool/cstool.c | 35 +- cstool/cstool_m680x.c | 155 ++ include/capstone/capstone.h | 15 + include/capstone/m680x.h | 537 ++++++ suite/fuzz/fuzz_harness.c | 5 + tests/Makefile | 4 + tests/test_basic.c | 13 + tests/test_detail.c | 13 + tests/test_iter.c | 12 + tests/test_m680x.c | 398 ++++ utils.h | 1 + 60 files changed, 8668 insertions(+), 26 deletions(-) create mode 100644 arch/M680X/M680XDisassembler.c create mode 100644 arch/M680X/M680XDisassembler.h create mode 100644 arch/M680X/M680XDisassemblerInternals.h create mode 100644 arch/M680X/M680XInstPrinter.c create mode 100644 arch/M680X/M680XInstPrinter.h create mode 100644 arch/M680X/M680XModule.c create mode 100644 arch/M680X/cpu12.inc create mode 100644 arch/M680X/hcs08.inc create mode 100644 arch/M680X/hd6301.inc create mode 100644 arch/M680X/hd6309.inc create mode 100644 arch/M680X/insn_props.inc create mode 100644 arch/M680X/m6800.inc create mode 100644 arch/M680X/m6801.inc create mode 100644 arch/M680X/m6805.inc create mode 100644 arch/M680X/m6808.inc create mode 100644 arch/M680X/m6809.inc create mode 100644 arch/M680X/m6811.inc create mode 100644 bindings/java/TestM680x.java create mode 100644 bindings/java/capstone/M680x.java create mode 100644 bindings/java/capstone/M680x_const.java create mode 100644 bindings/ocaml/m680x.ml create mode 100644 bindings/ocaml/m680x_const.ml create mode 100644 bindings/ocaml/test_m680x.ml create mode 100644 bindings/python/capstone/m680x.py create mode 100644 bindings/python/capstone/m680x_const.py create mode 100755 bindings/python/test_m680x.py create mode 100644 cstool/cstool_m680x.c create mode 100644 include/capstone/m680x.h create mode 100644 tests/test_m680x.c diff --git a/.gitignore b/.gitignore index 1111fe4f0f..3e846c3efa 100644 --- a/.gitignore +++ b/.gitignore @@ -38,6 +38,7 @@ bindings/ocaml/*.mli bindings/ocaml/test bindings/ocaml/test_arm bindings/ocaml/test_arm64 +bindings/ocaml/test_basic bindings/ocaml/test_mips bindings/ocaml/test_x86 bindings/ocaml/test_detail @@ -45,6 +46,7 @@ bindings/ocaml/test_ppc bindings/ocaml/test_sparc bindings/ocaml/test_systemz bindings/ocaml/test_xcore +bindings/ocaml/test_m680x # test binaries @@ -64,6 +66,7 @@ tests/*.static tests/test_customized_mnem tests/test_m68k tests/test_tms320c64x +tests/test_m680x # vim tmp file *.swp diff --git a/CMakeLists.txt b/CMakeLists.txt index dad1833b01..7629cd3265 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,8 +27,8 @@ option(CAPSTONE_BUILD_DIET "Build diet library" OFF) option(CAPSTONE_BUILD_TESTS "Build tests" ON) option(CAPSTONE_USE_DEFAULT_ALLOC "Use default memory allocation functions" ON) -set(SUPPORTED_ARCHITECTURES ARM ARM64 M68K MIPS PPC SPARC SYSZ XCORE X86 TMS320C64X) -set(SUPPORTED_ARCHITECTURE_LABELS ARM ARM64 M68K MIPS PowerPC Sparc SystemZ XCore x86 TMS320C64x) +set(SUPPORTED_ARCHITECTURES ARM ARM64 M68K MIPS PPC SPARC SYSZ XCORE X86 TMS320C64X M680X) +set(SUPPORTED_ARCHITECTURE_LABELS ARM ARM64 M68K MIPS PowerPC Sparc SystemZ XCore x86 TMS320C64x M680x) list(LENGTH SUPPORTED_ARCHITECTURES count) math(EXPR count "${count}-1") @@ -104,6 +104,7 @@ set(HEADERS_COMMON include/capstone/xcore.h include/capstone/m68k.h include/capstone/tms320c64x.h + include/capstone/m680x.h include/capstone/platform.h ) @@ -343,6 +344,21 @@ if (CAPSTONE_TMS320C64X_SUPPORT) set(TEST_SOURCES ${TEST_SOURCES} test_tms320c64x.c) endif () +if (CAPSTONE_M680X_SUPPORT) + add_definitions(-DCAPSTONE_HAS_M680X) + set(SOURCES_M680X + arch/M680X/M680XDisassembler.c + arch/M680X/M680XInstPrinter.c + arch/M680X/M680XModule.c + ) + set(HEADERS_M680X + arch/M680X/M680XInstPrinter.h + arch/M680X/M680XDisassembler.h + arch/M680X/M680XDisassemblerInternals.h + ) + set(TEST_SOURCES ${TEST_SOURCES} test_m680x.c) +endif () + if (CAPSTONE_OSXKERNEL_SUPPORT) add_definitions(-DCAPSTONE_HAS_OSXKERNEL) endif () @@ -359,6 +375,7 @@ set(ALL_SOURCES ${SOURCES_XCORE} ${SOURCES_M68K} ${SOURCES_TMS320C64X} + ${SOURCES_M680X} ) set(ALL_HEADERS @@ -374,6 +391,7 @@ set(ALL_HEADERS ${HEADERS_XCORE} ${HEADERS_M68K} ${HEADERS_TMS320C64X} + ${HEADERS_M680X} ) include_directories("${PROJECT_SOURCE_DIR}/include") @@ -449,6 +467,7 @@ source_group("Source\\X86" FILES ${SOURCES_X86}) source_group("Source\\XCore" FILES ${SOURCES_XCORE}) source_group("Source\\M68K" FILES ${SOURCES_M68K}) source_group("Source\\TMS320C64x" FILES ${SOURCES_TMS320C64X}) +source_group("Source\\M680X" FILES ${SOURCES_M680X}) source_group("Include\\Common" FILES ${HEADERS_COMMON}) source_group("Include\\Engine" FILES ${HEADERS_ENGINE}) @@ -462,6 +481,7 @@ source_group("Include\\X86" FILES ${HEADERS_X86}) source_group("Include\\XCore" FILES ${HEADERS_XCORE}) source_group("Include\\M68K" FILES ${HEADERS_M68K}) source_group("Include\\TMS320C64x" FILES ${HEADERS_TMS320C64X}) +source_group("Include\\M680X" FILES ${HEADERS_MC680X}) ### test library 64bit routine: get_property(LIB64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS) diff --git a/COMPILE_CMAKE.TXT b/COMPILE_CMAKE.TXT index 1145cdcb30..8555d1a77c 100644 --- a/COMPILE_CMAKE.TXT +++ b/COMPILE_CMAKE.TXT @@ -22,6 +22,7 @@ Get CMake for free from http://www.cmake.org. - CAPSTONE_ARM_SUPPORT: support ARM. Run cmake with -DCAPSTONE_ARM_SUPPORT=0 to remove ARM. - CAPSTONE_ARM64_SUPPORT: support ARM64. Run cmake with -DCAPSTONE_ARM64_SUPPORT=0 to remove ARM64. + - CAPSTONE_M680X_SUPPORT: support M680X. Run cmake with -DCAPSTONE_M680X_SUPPORT=0 to remove M680X. - CAPSTONE_M68K_SUPPORT: support M68K. Run cmake with -DCAPSTONE_M68K_SUPPORT=0 to remove M68K. - CAPSTONE_MIPS_SUPPORT: support Mips. Run cmake with -DCAPSTONE_MIPS_SUPPORT=0 to remove Mips. - CAPSTONE_PPC_SUPPORT: support PPC. Run cmake with -DCAPSTONE_PPC_SUPPORT=0 to remove PPC. @@ -30,7 +31,7 @@ Get CMake for free from http://www.cmake.org. - CAPSTONE_XCORE_SUPPORT: support XCore. Run cmake with -DCAPSTONE_XCORE_SUPPORT=0 to remove XCore. - CAPSTONE_X86_SUPPORT: support X86. Run cmake with -DCAPSTONE_X86_SUPPORT=0 to remove X86. - By default, all 9 architectures are compiled in. + By default, all 10 architectures are compiled in. Besides, Capstone also allows some more customization via following macros. diff --git a/CREDITS.TXT b/CREDITS.TXT index b560a523a2..5418cc6753 100644 --- a/CREDITS.TXT +++ b/CREDITS.TXT @@ -65,3 +65,5 @@ Xipiter LLC: Capstone logo redesigned. Satoshi Tanda: Support Windows kernel driver. Koutheir Attouchi: Support for Windows CE. Fotis Loukos: TMS320C64x architecture. +Wolfgang Schwotzer: M680X architecture. + diff --git a/HACK.TXT b/HACK.TXT index 522b360f2e..e641c68b3c 100644 --- a/HACK.TXT +++ b/HACK.TXT @@ -5,6 +5,7 @@ Capstone source is organized as followings. ├── arch <- code handling disasm engine for each arch │   ├── AArch64 <- ARM64 (aka ARMv8) engine │   ├── ARM <- ARM engine +│   ├── M680X <- M680X engine │   ├── M68K <- M68K engine │   ├── Mips <- Mips engine │   ├── PowerPC <- PowerPC engine diff --git a/Makefile b/Makefile index 71be3a0128..08d1083a1a 100644 --- a/Makefile +++ b/Makefile @@ -243,10 +243,22 @@ ifneq (,$(findstring tms320c64x,$(CAPSTONE_ARCHS))) LIBOBJ_TMS320C64X += $(OBJDIR)/arch/TMS320C64x/TMS320C64xModule.o endif +DEP_M680X = +DEP_M680X += arch/M680X/M680XInstPrinter.h +DEP_M680X += arch/M680X/M680XDisassembler.h +DEP_M680X += arch/M680X/M680XDisassemblerInternals.h + +LIBOBJ_M680X = +ifneq (,$(findstring m680x,$(CAPSTONE_ARCHS))) + CFLAGS += -DCAPSTONE_HAS_M680X + LIBOBJ_M680X += $(OBJDIR)/arch/M680X/M680XDisassembler.o + LIBOBJ_M680X += $(OBJDIR)/arch/M680X/M680XInstPrinter.o + LIBOBJ_M680X += $(OBJDIR)/arch/M680X/M680XModule.o +endif LIBOBJ = LIBOBJ += $(OBJDIR)/cs.o $(OBJDIR)/utils.o $(OBJDIR)/SStream.o $(OBJDIR)/MCInstrDesc.o $(OBJDIR)/MCRegisterInfo.o -LIBOBJ += $(LIBOBJ_ARM) $(LIBOBJ_ARM64) $(LIBOBJ_M68K) $(LIBOBJ_MIPS) $(LIBOBJ_PPC) $(LIBOBJ_SPARC) $(LIBOBJ_SYSZ) $(LIBOBJ_X86) $(LIBOBJ_XCORE) $(LIBOBJ_TMS320C64X) +LIBOBJ += $(LIBOBJ_ARM) $(LIBOBJ_ARM64) $(LIBOBJ_M68K) $(LIBOBJ_MIPS) $(LIBOBJ_PPC) $(LIBOBJ_SPARC) $(LIBOBJ_SYSZ) $(LIBOBJ_X86) $(LIBOBJ_XCORE) $(LIBOBJ_TMS320C64X) $(LIBOBJ_M680X) LIBOBJ += $(OBJDIR)/MCInst.o @@ -371,6 +383,7 @@ $(LIBOBJ_SYSZ): $(DEP_SYSZ) $(LIBOBJ_X86): $(DEP_X86) $(LIBOBJ_XCORE): $(DEP_XCORE) $(LIBOBJ_TMS320C64X): $(DEP_TMS320C64X) +$(LIBOBJ_M680X): $(DEP_M680X) ifeq ($(CAPSTONE_STATIC),yes) $(ARCHIVE): $(LIBOBJ) @@ -448,7 +461,7 @@ TESTS = test_basic test_detail test_arm test_arm64 test_m68k test_mips test_ppc TESTS += test_systemz test_x86 test_xcore test_iter TESTS += test_basic.static test_detail.static test_arm.static test_arm64.static TESTS += test_m68k.static test_mips.static test_ppc.static test_sparc.static -TESTS += test_systemz.static test_x86.static test_xcore.static +TESTS += test_systemz.static test_x86.static test_xcore.static test_m680x.static TESTS += test_skipdata test_skipdata.static test_iter.static check: @for t in $(TESTS); do \ diff --git a/README.md b/README.md index 78aa845f4b..39a069e0fc 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Created by Nguyen Anh Quynh, then developed and maintained by a small community, Capstone offers some unparalleled features: - Support multiple hardware architectures: ARM, ARM64 (ARMv8), M68K, Mips, PPC, - Sparc, SystemZ, TMS320C64X, XCore and X86 (including X86_64). + Sparc, SystemZ, TMS320C64X, M680X, XCore and X86 (including X86_64). - Having clean/simple/lightweight/intuitive architecture-neutral API. diff --git a/arch/M680X/M680XDisassembler.c b/arch/M680X/M680XDisassembler.c new file mode 100644 index 0000000000..56f6664320 --- /dev/null +++ b/arch/M680X/M680XDisassembler.c @@ -0,0 +1,2305 @@ +/* Capstone Disassembly Engine */ +/* M680X Backend by Wolfgang Schwotzer 2017 */ + +/* ======================================================================== */ +/* ================================ INCLUDES ============================== */ +/* ======================================================================== */ + +#include +#include +#include + +#include "../../cs_priv.h" +#include "../../utils.h" + +#include "../../MCInst.h" +#include "../../MCInstrDesc.h" +#include "../../MCRegisterInfo.h" +#include "M680XInstPrinter.h" +#include "M680XDisassembler.h" +#include "M680XDisassemblerInternals.h" + +#ifdef CAPSTONE_HAS_M680X + +#ifndef DECL_SPEC +#ifdef _MSC_VER +#define DECL_SPEC __cdecl +#else +#define DECL_SPEC +#endif // _MSC_VER +#endif // DECL_SPEC + +/* ======================================================================== */ +/* ============================ GENERAL DEFINES =========================== */ +/* ======================================================================== */ + +/* ======================================================================== */ +/* =============================== PROTOTYPES ============================= */ +/* ======================================================================== */ + +typedef enum insn_hdlr_id { + illgl_hid, + rel8_hid, + rel16_hid, + imm8_hid, + imm16_hid, + imm32_hid, + dir_hid, + ext_hid, + idxX_hid, + idxY_hid, + idx09_hid, + inh_hid, + rr09_hid, + rbits_hid, + bitmv_hid, + tfm_hid, + opidx_hid, + opidxdr_hid, + idxX0_hid, + idxX16_hid, + imm8rel_hid, + idxS_hid, + idxS16_hid, + idxXp_hid, + idxX0p_hid, + idx12_hid, + idx12s_hid, + rr12_hid, + loop_hid, + index_hid, + imm8i12x_hid, + imm16i12x_hid, + exti12x_hid, + HANDLER_ID_ENDING, +} insn_hdlr_id; + +// Access modes for the first 4 operands. If there are more than +// four operands they use the same access mode as the 4th operand. +// +// u: unchanged +// r: (r)read access +// w: (w)write access +// m: (m)odify access (= read + write) +// +typedef enum e_access_mode { + + uuuu, + rrrr, + wwww, + rwww, + rrrm, + rmmm, + wrrr, + mrrr, + mwww, + mmmm, + mwrr, + mmrr, + wmmm, + rruu, + muuu, + ACCESS_MODE_ENDING, +} e_access_mode; + +// Access type values are compatible with enum cs_ac_type: +typedef enum e_access { + UNCHANGED = CS_AC_INVALID, + READ = CS_AC_READ, + WRITE = CS_AC_WRITE, + MODIFY = (CS_AC_READ | CS_AC_WRITE), +} e_access; + +/* Properties of one instruction in PAGE1 (without prefix) */ +typedef struct inst_page1 { + m680x_insn insn : 9; + insn_hdlr_id handler_id1 : 6; /* first instruction handler id */ + insn_hdlr_id handler_id2 : 6; /* second instruction handler id */ +} inst_page1; + +/* Properties of one instruction in any other PAGE X */ +typedef struct inst_pageX { + unsigned opcode : 8; + m680x_insn insn : 9; + insn_hdlr_id handler_id1 : 6; /* first instruction handler id */ + insn_hdlr_id handler_id2 : 6; /* second instruction handler id */ +} inst_pageX; + +typedef struct insn_props { + unsigned group : 4; + e_access_mode access_mode : 5; + m680x_reg reg0 : 5; + m680x_reg reg1 : 5; + bool cc_modified : 1; + bool update_reg_access : 1; +} insn_props; + +#include "m6800.inc" +#include "m6801.inc" +#include "hd6301.inc" +#include "m6811.inc" +#include "cpu12.inc" +#include "m6805.inc" +#include "m6808.inc" +#include "hcs08.inc" +#include "m6809.inc" +#include "hd6309.inc" + +#include "insn_props.inc" + +////////////////////////////////////////////////////////////////////////////// + +// M680X instuctions have 1 up to 8 bytes (CPU12: MOVW IDX2,IDX2). +// A reader is needed to read a byte or word from a given memory address. +// See also X86 reader(...) +static bool read_byte(const m680x_info *info, uint8_t *byte, uint16_t address) +{ + if (address - info->offset >= info->size) + // out of code buffer range + return false; + + *byte = info->code[address - info->offset]; + + return true; +} + +static bool read_byte_sign_extended(const m680x_info *info, int16_t *word, + uint16_t address) +{ + if (address - info->offset >= info->size) + // out of code buffer range + return false; + + *word = (int16_t) info->code[address - info->offset]; + + if (*word & 0x80) + *word |= 0xFF00; + + return true; +} + +static bool read_word(const m680x_info *info, uint16_t *word, uint16_t address) +{ + if (address + 1 - info->offset >= info->size) + // out of code buffer range + return false; + + *word = (uint16_t)info->code[address - info->offset] << 8; + *word |= (uint16_t)info->code[address + 1 - info->offset]; + + return true; +} + +static bool read_sdword(const m680x_info *info, int32_t *sdword, + uint16_t address) +{ + if (address + 3 - info->offset >= info->size) + // out of code buffer range + return false; + + *sdword = (uint32_t)info->code[address - info->offset] << 24; + *sdword |= (uint32_t)info->code[address + 1 - info->offset] << 16; + *sdword |= (uint32_t)info->code[address + 2 - info->offset] << 8; + *sdword |= (uint32_t)info->code[address + 3 - info->offset]; + + return true; +} + +// For PAGE2 and PAGE3 opcodes when using an an array of inst_page1 most +// entries have M680X_INS_ILLGL. To avoid wasting memory an inst_pageX is +// used which contains the opcode. Using a binary search for the right opcode +// is much faster (= O(log n) ) in comparison to a linear search ( = O(n) ). +static int binary_search(const inst_pageX *const inst_pageX_table, + int table_size, uint8_t opcode) +{ + int first = 0; + int last = table_size - 1; + int middle = (first + last) / 2; + + while (first <= last) { + if (inst_pageX_table[middle].opcode < opcode) { + first = middle + 1; + } + else if (inst_pageX_table[middle].opcode == opcode) { + return middle; /* item found */ + } + else + last = middle - 1; + + middle = (first + last) / 2; + } + + if (first > last) + return -1; /* item not found */ + + return -2; +} + +void M680X_get_insn_id(cs_struct *handle, cs_insn *insn, unsigned int id) +{ + const m680x_info *const info = (const m680x_info *)handle->printer_info; + const cpu_tables *cpu = info->cpu; + uint8_t insn_prefix = (id >> 8) & 0xff; + int index; + int i; + + insn->id = M680X_INS_ILLGL; + + for (i = 0; i < ARR_SIZE(cpu->pageX_prefix); ++i) { + if (cpu->pageX_table_size[i] == 0 || + (cpu->inst_pageX_table[i] == NULL)) + break; + + if (cpu->pageX_prefix[i] == insn_prefix) { + index = binary_search(cpu->inst_pageX_table[i], + cpu->pageX_table_size[i], id & 0xff); + insn->id = (index >= 0) ? + cpu->inst_pageX_table[i][index].insn : + M680X_INS_ILLGL; + return; + } + } + + if (insn_prefix != 0) + return; + + insn->id = cpu->inst_page1_table[id].insn; + + if (insn->id != M680X_INS_ILLGL) + return; + + // Check if opcode byte is present in an overlay table + for (i = 0; i < ARR_SIZE(cpu->overlay_table_size); ++i) { + if (cpu->overlay_table_size[i] == 0 || + (cpu->inst_overlay_table[i] == NULL)) + break; + + if ((index = binary_search(cpu->inst_overlay_table[i], + cpu->overlay_table_size[i], + id & 0xff)) >= 0) { + insn->id = cpu->inst_overlay_table[i][index].insn; + return; + } + } +} + +static void add_insn_group(cs_detail *detail, m680x_group_type group) +{ + if (detail != NULL && + (group != M680X_GRP_INVALID) && (group != M680X_GRP_ENDING)) + detail->groups[detail->groups_count++] = (uint8_t)group; +} + +static bool exists_reg_list(uint16_t *regs, uint8_t count, m680x_reg reg) +{ + uint8_t i; + + for (i = 0; i < count; ++i) { + if (regs[i] == (uint16_t)reg) + return true; + } + + return false; +} + +static void add_reg_to_rw_list(MCInst *MI, m680x_reg reg, e_access access) +{ + cs_detail *detail = MI->flat_insn->detail; + + if (detail == NULL || (reg == M680X_REG_INVALID)) + return; + + switch (access) { + case MODIFY: + if (!exists_reg_list(detail->regs_read, + detail->regs_read_count, reg)) + detail->regs_read[detail->regs_read_count++] = + (uint16_t)reg; + + // intentionally fall through + + case WRITE: + if (!exists_reg_list(detail->regs_write, + detail->regs_write_count, reg)) + detail->regs_write[detail->regs_write_count++] = + (uint16_t)reg; + + break; + + case READ: + if (!exists_reg_list(detail->regs_read, + detail->regs_read_count, reg)) + detail->regs_read[detail->regs_read_count++] = + (uint16_t)reg; + + break; + + case UNCHANGED: + default: + break; + } +} + +static void update_am_reg_list(MCInst *MI, m680x_info *info, cs_m680x_op *op, + e_access access) +{ + if (MI->flat_insn->detail == NULL) + return; + + switch (op->type) { + case M680X_OP_REGISTER: + add_reg_to_rw_list(MI, op->reg, access); + break; + + case M680X_OP_INDEXED: + add_reg_to_rw_list(MI, op->idx.base_reg, READ); + + if (op->idx.base_reg == M680X_REG_X && + info->cpu->reg_byte_size[M680X_REG_H]) + add_reg_to_rw_list(MI, M680X_REG_H, READ); + + + if (op->idx.offset_reg != M680X_REG_INVALID) + add_reg_to_rw_list(MI, op->idx.offset_reg, READ); + + if (op->idx.inc_dec) { + add_reg_to_rw_list(MI, op->idx.base_reg, WRITE); + + if (op->idx.base_reg == M680X_REG_X && + info->cpu->reg_byte_size[M680X_REG_H]) + add_reg_to_rw_list(MI, M680X_REG_H, WRITE); + } + + break; + + default: + break; + } +} + +static const e_access g_access_mode_to_access[4][15] = { + { + UNCHANGED, READ, WRITE, READ, READ, READ, WRITE, MODIFY, + MODIFY, MODIFY, MODIFY, MODIFY, WRITE, READ, MODIFY, + }, + { + UNCHANGED, READ, WRITE, WRITE, READ, MODIFY, READ, READ, + WRITE, MODIFY, WRITE, MODIFY, MODIFY, READ, UNCHANGED, + }, + { + UNCHANGED, READ, WRITE, WRITE, READ, MODIFY, READ, READ, + WRITE, MODIFY, READ, READ, MODIFY, UNCHANGED, UNCHANGED, + }, + { + UNCHANGED, READ, WRITE, WRITE, MODIFY, MODIFY, READ, READ, + WRITE, MODIFY, READ, READ, MODIFY, UNCHANGED, UNCHANGED, + }, +}; + +static e_access get_access(int operator_index, e_access_mode access_mode) +{ + int idx = (operator_index > 3) ? 3 : operator_index; + + return g_access_mode_to_access[idx][access_mode]; +} + +static void build_regs_read_write_counts(MCInst *MI, m680x_info *info, + e_access_mode access_mode) +{ + cs_m680x *m680x = &info->m680x; + int i; + + if (MI->flat_insn->detail == NULL || (!m680x->op_count)) + return; + + for (i = 0; i < m680x->op_count; ++i) { + + e_access access = get_access(i, access_mode); + update_am_reg_list(MI, info, &m680x->operands[i], access); + } +} + +static void add_operators_access(MCInst *MI, m680x_info *info, + e_access_mode access_mode) +{ + cs_m680x *m680x = &info->m680x; + int offset = 0; + int i; + + if (MI->flat_insn->detail == NULL || (!m680x->op_count) || + (access_mode == uuuu)) + return; + + for (i = 0; i < m680x->op_count; ++i) { + + // Ugly fix: MULD has a register operand, an immediate operand + // AND an implicitly changed register W + if (info->insn == M680X_INS_MULD && (i == 1)) + offset = 1; + + e_access access = get_access(i + offset, access_mode); + m680x->operands[i].access = access; + } +} + +typedef struct insn_to_changed_regs { + m680x_insn insn; + e_access_mode access_mode; + m680x_reg regs[10]; +} insn_to_changed_regs; + +static void set_changed_regs_read_write_counts(MCInst *MI, m680x_info *info) +{ + //TABLE +#define EOL M680X_REG_INVALID + static const insn_to_changed_regs changed_regs[] = { + { M680X_INS_BSR, mmmm, { M680X_REG_S, EOL } }, + { M680X_INS_CALL, mmmm, { M680X_REG_S, EOL } }, + { + M680X_INS_CWAI, mrrr, { + M680X_REG_S, M680X_REG_PC, M680X_REG_U, + M680X_REG_Y, M680X_REG_X, M680X_REG_DP, + M680X_REG_D, M680X_REG_CC, EOL + }, + }, + { M680X_INS_DAA, mrrr, { M680X_REG_A, EOL } }, + { + M680X_INS_DIV, mmrr, { + M680X_REG_A, M680X_REG_H, M680X_REG_X, EOL + } + }, + { + M680X_INS_EDIV, mmrr, { + M680X_REG_D, M680X_REG_Y, M680X_REG_X, EOL + } + }, + { + M680X_INS_EDIVS, mmrr, { + M680X_REG_D, M680X_REG_Y, M680X_REG_X, EOL + } + }, + { M680X_INS_EMACS, mrrr, { M680X_REG_X, M680X_REG_Y, EOL } }, + { M680X_INS_EMAXM, rrrr, { M680X_REG_D, EOL } }, + { M680X_INS_EMINM, rrrr, { M680X_REG_D, EOL } }, + { M680X_INS_EMUL, mmrr, { M680X_REG_D, M680X_REG_Y, EOL } }, + { M680X_INS_EMULS, mmrr, { M680X_REG_D, M680X_REG_Y, EOL } }, + { M680X_INS_ETBL, wmmm, { M680X_REG_A, M680X_REG_B, EOL } }, + { M680X_INS_FDIV, mmmm, { M680X_REG_D, M680X_REG_X, EOL } }, + { M680X_INS_IDIV, mmmm, { M680X_REG_D, M680X_REG_X, EOL } }, + { M680X_INS_IDIVS, mmmm, { M680X_REG_D, M680X_REG_X, EOL } }, + { M680X_INS_JSR, mmmm, { M680X_REG_S, EOL } }, + { M680X_INS_LBSR, mmmm, { M680X_REG_S, EOL } }, + { M680X_INS_MAXM, rrrr, { M680X_REG_A, EOL } }, + { M680X_INS_MINM, rrrr, { M680X_REG_A, EOL } }, + { + M680X_INS_MEM, mmrr, { + M680X_REG_X, M680X_REG_Y, M680X_REG_A, EOL + } + }, + { M680X_INS_MUL, mmmm, { M680X_REG_A, M680X_REG_B, EOL } }, + { M680X_INS_MULD, mwrr, { M680X_REG_D, M680X_REG_W, EOL } }, + { M680X_INS_PSHA, rmmm, { M680X_REG_A, M680X_REG_S, EOL } }, + { M680X_INS_PSHB, rmmm, { M680X_REG_B, M680X_REG_S, EOL } }, + { M680X_INS_PSHC, rmmm, { M680X_REG_CC, M680X_REG_S, EOL } }, + { M680X_INS_PSHD, rmmm, { M680X_REG_D, M680X_REG_S, EOL } }, + { M680X_INS_PSHH, rmmm, { M680X_REG_H, M680X_REG_S, EOL } }, + { M680X_INS_PSHX, rmmm, { M680X_REG_X, M680X_REG_S, EOL } }, + { M680X_INS_PSHY, rmmm, { M680X_REG_Y, M680X_REG_S, EOL } }, + { M680X_INS_PULA, wmmm, { M680X_REG_A, M680X_REG_S, EOL } }, + { M680X_INS_PULB, wmmm, { M680X_REG_B, M680X_REG_S, EOL } }, + { M680X_INS_PULC, wmmm, { M680X_REG_CC, M680X_REG_S, EOL } }, + { M680X_INS_PULD, wmmm, { M680X_REG_D, M680X_REG_S, EOL } }, + { M680X_INS_PULH, wmmm, { M680X_REG_H, M680X_REG_S, EOL } }, + { M680X_INS_PULX, wmmm, { M680X_REG_X, M680X_REG_S, EOL } }, + { M680X_INS_PULY, wmmm, { M680X_REG_Y, M680X_REG_S, EOL } }, + { + M680X_INS_REV, mmrr, { + M680X_REG_A, M680X_REG_X, M680X_REG_Y, EOL + } + }, + { + M680X_INS_REVW, mmmm, { + M680X_REG_A, M680X_REG_X, M680X_REG_Y, EOL + } + }, + { M680X_INS_RTC, mwww, { M680X_REG_S, M680X_REG_PC, EOL } }, + { + M680X_INS_RTI, mwww, { + M680X_REG_S, M680X_REG_CC, M680X_REG_B, + M680X_REG_A, M680X_REG_DP, M680X_REG_X, + M680X_REG_Y, M680X_REG_U, M680X_REG_PC, + EOL + }, + }, + { M680X_INS_RTS, mwww, { M680X_REG_S, M680X_REG_PC, EOL } }, + { M680X_INS_SEX, wrrr, { M680X_REG_A, M680X_REG_B, EOL } }, + { M680X_INS_SEXW, rwww, { M680X_REG_W, M680X_REG_D, EOL } }, + { + M680X_INS_SWI, mmrr, { + M680X_REG_S, M680X_REG_PC, M680X_REG_U, + M680X_REG_Y, M680X_REG_X, M680X_REG_DP, + M680X_REG_A, M680X_REG_B, M680X_REG_CC, + EOL + } + }, + { + M680X_INS_SWI2, mmrr, { + M680X_REG_S, M680X_REG_PC, M680X_REG_U, + M680X_REG_Y, M680X_REG_X, M680X_REG_DP, + M680X_REG_A, M680X_REG_B, M680X_REG_CC, + EOL + }, + }, + { + M680X_INS_SWI3, mmrr, { + M680X_REG_S, M680X_REG_PC, M680X_REG_U, + M680X_REG_Y, M680X_REG_X, M680X_REG_DP, + M680X_REG_A, M680X_REG_B, M680X_REG_CC, + EOL + }, + }, + { M680X_INS_TBL, wrrr, { M680X_REG_A, M680X_REG_B, EOL } }, + { + M680X_INS_WAI, mrrr, { + M680X_REG_S, M680X_REG_PC, M680X_REG_X, + M680X_REG_A, M680X_REG_B, M680X_REG_CC, + EOL + } + }, + { + M680X_INS_WAV, rmmm, { + M680X_REG_A, M680X_REG_B, M680X_REG_X, + M680X_REG_Y, EOL + } + }, + { + M680X_INS_WAVR, rmmm, { + M680X_REG_A, M680X_REG_B, M680X_REG_X, + M680X_REG_Y, EOL + } + }, + }; + + int i, j; + + if (MI->flat_insn->detail == NULL) + return; + + for (i = 0; i < ARR_SIZE(changed_regs); ++i) { + if (info->insn == changed_regs[i].insn) { + e_access_mode access_mode = changed_regs[i].access_mode; + + for (j = 0; changed_regs[i].regs[j] != EOL; ++j) { + e_access access; + + m680x_reg reg = changed_regs[i].regs[j]; + + if (!info->cpu->reg_byte_size[reg]) { + if (info->insn != M680X_INS_MUL) + continue; + + // Hack for M68HC05: MUL uses reg. A,X + reg = M680X_REG_X; + } + + access = get_access(j, access_mode); + add_reg_to_rw_list(MI, reg, access); + } + } + } + +#undef EOL +} + +typedef struct insn_desc { + uint32_t opcode; + m680x_insn insn; + insn_hdlr_id hid[2]; + uint16_t insn_size; +} insn_desc; + +static bool is_indexed09_post_byte_valid(const m680x_info *info, + uint16_t *address, uint8_t post_byte, insn_desc *insn_description) +{ + uint8_t ir = 0; + bool retval; + + switch (post_byte & 0x9F) { + case 0x87: + case 0x8A: + case 0x8E: + case 0x8F: + case 0x90: + case 0x92: + case 0x97: + case 0x9A: + case 0x9E: + return false; // illegal indexed post bytes + + case 0x88: // n8,R + case 0x8C: // n8,PCR + case 0x98: // [n8,R] + case 0x9C: // [n8,PCR] + insn_description->insn_size++; + return read_byte(info, &ir, (*address)++); + + case 0x89: // n16,R + case 0x8D: // n16,PCR + case 0x99: // [n16,R] + case 0x9D: // [n16,PCR] + insn_description->insn_size += 2; + retval = read_byte(info, &ir, *address + 1); + address += 2; + return retval; + + case 0x9F: // [n] + insn_description->insn_size += 2; + retval = (post_byte & 0x60) == 0 && + read_byte(info, &ir, *address + 1); + address += 2; + return retval; + } + + return true; // Any other indexed post byte is valid and + // no additional bytes have to be read. +} + +static bool is_indexed12_post_byte_valid(const m680x_info *info, + uint16_t *address, uint8_t post_byte, insn_desc *insn_description, + bool is_subset) +{ + uint8_t ir; + bool result; + + if (!(post_byte & 0x20)) // n5,R + return true; + + switch (post_byte & 0xe7) { + case 0xe0: + case 0xe1: // n9,R + if (is_subset) + return false; + + insn_description->insn_size++; + return read_byte(info, &ir, (*address)++); + + case 0xe2: // n16,R + case 0xe3: // [n16,R] + if (is_subset) + return false; + + insn_description->insn_size += 2; + result = read_byte(info, &ir, *address + 1); + *address += 2; + return result; + + case 0xe4: // A,R + case 0xe5: // B,R + case 0xe6: // D,R + case 0xe7: // [D,R] + default: // n,-r n,+r n,r- n,r+ + break; + } + + return true; +} + +// Check for M6809/HD6309 TFR/EXG instruction for valid register +static bool is_tfr09_reg_valid(const m680x_info *info, uint8_t reg_nibble) +{ + if (info->cpu->tfr_reg_valid != NULL) + return info->cpu->tfr_reg_valid[reg_nibble]; + + return true; // e.g. for the M6309 all registers are valid +} + +// Check for CPU12 TFR/EXG instruction for valid register +static bool is_exg_tfr12_post_byte_valid(const m680x_info *info, + uint8_t post_byte) +{ + return !(post_byte & 0x08); +} + +static bool is_tfm_reg_valid(const m680x_info *info, uint8_t reg_nibble) +{ + // HD6809 TFM instruction: Only register X,Y,U,S,D is allowed + return reg_nibble <= 4; +} + +static bool is_loop_post_byte_valid(const m680x_info *info, uint8_t post_byte) +{ + // According to documentation bit 3 is don't care and not checked here. + if (post_byte >= 0xc0) + return false; + + return ((post_byte & 0x07) != 2 && ((post_byte & 0x07) != 3)); +} + +static bool is_sufficient_code_size(const m680x_info *info, uint16_t address, + insn_desc *insn_description) +{ + int i; + bool retval; + + for (i = 0; i < 2; i++) { + uint8_t ir = 0; + bool is_subset = false; + + switch (insn_description->hid[i]) { + + case imm32_hid: + insn_description->insn_size += 4; + retval = read_byte(info, &ir, address + 3); + address += 4; + break; + + case ext_hid: + case imm16_hid: + case rel16_hid: + case imm8rel_hid: + case opidxdr_hid: + case idxX16_hid: + case idxS16_hid: + insn_description->insn_size += 2; + retval = read_byte(info, &ir, address + 1); + address += 2; + break; + + case rel8_hid: + case dir_hid: + case rbits_hid: + case imm8_hid: + case idxX_hid: + case idxXp_hid: + case idxY_hid: + case idxS_hid: + case index_hid: + insn_description->insn_size += 1; + retval = read_byte(info, &ir, address++); + break; + + case illgl_hid: + case inh_hid: + case idxX0_hid: + case idxX0p_hid: + case opidx_hid: + retval = true; + break; + + case idx09_hid: + insn_description->insn_size += 1; + + if (!read_byte(info, &ir, address++)) + retval = false; + else + retval = is_indexed09_post_byte_valid(info, + &address, ir, insn_description); + + break; + + case idx12s_hid: + is_subset = true; + + // intentionally fall through + + case idx12_hid: + insn_description->insn_size += 1; + + if (!read_byte(info, &ir, address++)) + retval = false; + else + retval = is_indexed12_post_byte_valid(info, + &address, ir, insn_description, + is_subset); + + break; + + case exti12x_hid: + case imm16i12x_hid: + insn_description->insn_size += 1; + + if (!read_byte(info, &ir, address++)) + retval = false; + else if (!is_indexed12_post_byte_valid(info, &address, + ir, insn_description, false)) + retval = false; + else { + insn_description->insn_size += 2; + retval = read_byte(info, &ir, address + 1); + address += 2; + } + + break; + + case imm8i12x_hid: + insn_description->insn_size += 1; + + if (!read_byte(info, &ir, address++)) + retval = false; + else if (!is_indexed12_post_byte_valid(info, &address, + ir, insn_description, false)) + retval = false; + else { + insn_description->insn_size += 1; + retval = read_byte(info, &ir, address++); + } + + break; + + case tfm_hid: + insn_description->insn_size += 1; + + if (!read_byte(info, &ir, address++)) + retval = false; + else + retval = is_tfm_reg_valid(info, (ir >> 4) & 0x0F) && + is_tfm_reg_valid(info, ir & 0x0F); + + break; + + case rr09_hid: + insn_description->insn_size += 1; + + if (!read_byte(info, &ir, address++)) + retval = false; + else + retval = is_tfr09_reg_valid(info, (ir >> 4) & 0x0F) && + is_tfr09_reg_valid(info, ir & 0x0F); + + break; + + case rr12_hid: + insn_description->insn_size += 1; + + if (!read_byte(info, &ir, address++)) + retval = false; + else + retval = is_exg_tfr12_post_byte_valid(info, ir); + + break; + + case bitmv_hid: + insn_description->insn_size += 2; + + if (!read_byte(info, &ir, address++)) + retval = false; + else if ((ir & 0xc0) == 0xc0) + retval = false; // Invalid register specified + else + retval = read_byte(info, &ir, address++); + + break; + + case loop_hid: + insn_description->insn_size += 2; + + if (!read_byte(info, &ir, address++)) + retval = false; + else if (!is_loop_post_byte_valid(info, ir)) + retval = false; + else + retval = read_byte(info, &ir, address++); + + break; + + default: + fprintf(stderr, "Internal error: Unexpected instruction " + "handler id %d\n", insn_description->hid[i]); + retval = false; + break; + } + + if (!retval) + return false; + } + + return retval; +} + +// Check for a valid M680X instruction AND for enough bytes in the code buffer +// Return an instruction description in insn_desc. +static bool decode_insn(const m680x_info *info, uint16_t address, + insn_desc *insn_description) +{ + const inst_pageX *inst_table = NULL; + const cpu_tables *cpu = info->cpu; + int table_size = 0; + uint16_t base_address = address; + uint8_t ir; // instruction register + int i; + int index; + + if (!read_byte(info, &ir, address++)) + return false; + + insn_description->insn = M680X_INS_ILLGL; + insn_description->opcode = ir; + + // Check if a page prefix byte is present + for (i = 0; i < ARR_SIZE(cpu->pageX_table_size); ++i) { + if (cpu->pageX_table_size[i] == 0 || + (cpu->inst_pageX_table[i] == NULL)) + break; + + if ((cpu->pageX_prefix[i] == ir)) { + // Get pageX instruction and handler id. + // Abort for illegal instr. + inst_table = cpu->inst_pageX_table[i]; + table_size = cpu->pageX_table_size[i]; + + if (!read_byte(info, &ir, address++)) + return false; + + insn_description->opcode = + (insn_description->opcode << 8) | ir; + + if ((index = binary_search(inst_table, table_size, ir)) < 0) + return false; + + insn_description->hid[0] = + inst_table[index].handler_id1; + insn_description->hid[1] = + inst_table[index].handler_id2; + insn_description->insn = inst_table[index].insn; + break; + } + } + + if (insn_description->insn == M680X_INS_ILLGL) { + // Get page1 insn description + insn_description->insn = cpu->inst_page1_table[ir].insn; + insn_description->hid[0] = + cpu->inst_page1_table[ir].handler_id1; + insn_description->hid[1] = + cpu->inst_page1_table[ir].handler_id2; + } + + if (insn_description->insn == M680X_INS_ILLGL) { + // Check if opcode byte is present in an overlay table + for (i = 0; i < ARR_SIZE(cpu->overlay_table_size); ++i) { + if (cpu->overlay_table_size[i] == 0 || + (cpu->inst_overlay_table[i] == NULL)) + break; + + inst_table = cpu->inst_overlay_table[i]; + table_size = cpu->overlay_table_size[i]; + + if ((index = binary_search(inst_table, table_size, + ir)) >= 0) { + insn_description->hid[0] = + inst_table[index].handler_id1; + insn_description->hid[1] = + inst_table[index].handler_id2; + insn_description->insn = inst_table[index].insn; + break; + } + } + } + + insn_description->insn_size = address - base_address; + + return (insn_description->insn != M680X_INS_ILLGL) && + (insn_description->insn != M680X_INS_INVLD) && + is_sufficient_code_size(info, address, insn_description); +} + +static void illegal_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + cs_m680x_op *op0 = &info->m680x.operands[info->m680x.op_count++]; + uint8_t temp8 = 0; + + info->insn = M680X_INS_ILLGL; + read_byte(info, &temp8, (*address)++); + op0->imm = (int32_t)temp8 & 0xff; + op0->type = M680X_OP_IMMEDIATE; + op0->size = 1; +} + +static void inherent_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + // There is nothing to do here :-) +} + +static void add_reg_operand(m680x_info *info, m680x_reg reg) +{ + cs_m680x *m680x = &info->m680x; + cs_m680x_op *op = &m680x->operands[m680x->op_count++]; + + op->type = M680X_OP_REGISTER; + op->reg = reg; + op->size = info->cpu->reg_byte_size[reg]; +} + +static void set_operand_size(m680x_info *info, cs_m680x_op *op, + uint8_t default_size) +{ + cs_m680x *m680x = &info->m680x; + + if (info->insn == M680X_INS_JMP || info->insn == M680X_INS_JSR) + op->size = 0; + else if (info->insn == M680X_INS_DIVD || + ((info->insn == M680X_INS_AIS || info->insn == M680X_INS_AIX) && + op->type != M680X_OP_REGISTER)) + op->size = 1; + else if (info->insn == M680X_INS_DIVQ || + info->insn == M680X_INS_MOVW) + op->size = 2; + else if (info->insn == M680X_INS_EMACS) + op->size = 4; + else if ((m680x->op_count > 0) && + (m680x->operands[0].type == M680X_OP_REGISTER)) + op->size = m680x->operands[0].size; + else + op->size = default_size; +} + +static const m680x_reg reg_s_reg_ids[] = { + M680X_REG_CC, M680X_REG_A, M680X_REG_B, M680X_REG_DP, + M680X_REG_X, M680X_REG_Y, M680X_REG_U, M680X_REG_PC, +}; + +static const m680x_reg reg_u_reg_ids[] = { + M680X_REG_CC, M680X_REG_A, M680X_REG_B, M680X_REG_DP, + M680X_REG_X, M680X_REG_Y, M680X_REG_S, M680X_REG_PC, +}; + +static void reg_bits_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + cs_m680x_op *op0 = &info->m680x.operands[0]; + uint8_t reg_bits = 0; + uint16_t bit_index; + const m680x_reg *reg_to_reg_ids; + + read_byte(info, ®_bits, (*address)++); + + switch (op0->reg) { + case M680X_REG_U: + reg_to_reg_ids = ®_u_reg_ids[0]; + break; + + case M680X_REG_S: + reg_to_reg_ids = ®_s_reg_ids[0]; + break; + + default: + fprintf(stderr, "Internal error: Unexpected operand0 register " + "%d\n", op0->reg); + abort(); + } + + if ((info->insn == M680X_INS_PULU || + (info->insn == M680X_INS_PULS)) && + ((reg_bits & 0x80) != 0)) + // PULS xxx,PC or PULU xxx,PC which is like return from + // subroutine (RTS) + add_insn_group(MI->flat_insn->detail, M680X_GRP_RET); + + for (bit_index = 0; bit_index < 8; ++bit_index) { + if (reg_bits & (1 << bit_index)) + add_reg_operand(info, reg_to_reg_ids[bit_index]); + } +} + +static const m680x_reg g_tfr_exg_reg_ids[] = { + /* 16-bit registers */ + M680X_REG_D, M680X_REG_X, M680X_REG_Y, M680X_REG_U, + M680X_REG_S, M680X_REG_PC, M680X_REG_W, M680X_REG_V, + /* 8-bit registers */ + M680X_REG_A, M680X_REG_B, M680X_REG_CC, M680X_REG_DP, + M680X_REG_0, M680X_REG_0, M680X_REG_E, M680X_REG_F, +}; + +static void reg_reg09_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + uint8_t regs = 0; + + read_byte(info, ®s, (*address)++); + + add_reg_operand(info, g_tfr_exg_reg_ids[regs >> 4]); + add_reg_operand(info, g_tfr_exg_reg_ids[regs & 0x0f]); + + if ((regs & 0x0f) == 0x05) { + // EXG xxx,PC or TFR xxx,PC which is like a JMP + add_insn_group(MI->flat_insn->detail, M680X_GRP_JUMP); + } +} + + +static void reg_reg12_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + static const m680x_reg g_tfr_exg12_reg0_ids[] = { + M680X_REG_A, M680X_REG_B, M680X_REG_CC, M680X_REG_TMP3, + M680X_REG_D, M680X_REG_X, M680X_REG_Y, M680X_REG_S, + }; + static const m680x_reg g_tfr_exg12_reg1_ids[] = { + M680X_REG_A, M680X_REG_B, M680X_REG_CC, M680X_REG_TMP2, + M680X_REG_D, M680X_REG_X, M680X_REG_Y, M680X_REG_S, + }; + uint8_t regs = 0; + + read_byte(info, ®s, (*address)++); + + // The opcode of this instruction depends on + // the msb of its post byte. + if (regs & 0x80) + info->insn = M680X_INS_EXG; + else + info->insn = M680X_INS_TFR; + + add_reg_operand(info, g_tfr_exg12_reg0_ids[(regs >> 4) & 0x07]); + add_reg_operand(info, g_tfr_exg12_reg1_ids[regs & 0x07]); +} + +static void add_rel_operand(m680x_info *info, int16_t offset, uint16_t address) +{ + cs_m680x *m680x = &info->m680x; + cs_m680x_op *op = &m680x->operands[m680x->op_count++]; + + op->type = M680X_OP_RELATIVE; + op->size = 0; + op->rel.offset = offset; + op->rel.address = address; +} + +static void relative8_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + int16_t offset = 0; + + read_byte_sign_extended(info, &offset, (*address)++); + add_rel_operand(info, offset, *address + offset); + add_insn_group(MI->flat_insn->detail, M680X_GRP_BRAREL); + + if ((info->insn != M680X_INS_BRA) && + (info->insn != M680X_INS_BSR) && + (info->insn != M680X_INS_BRN)) + add_reg_to_rw_list(MI, M680X_REG_CC, READ); +} + +static void relative16_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + uint16_t offset = 0; + + read_word(info, &offset, *address); + *address += 2; + add_rel_operand(info, (int16_t)offset, *address + offset); + add_insn_group(MI->flat_insn->detail, M680X_GRP_BRAREL); + + if ((info->insn != M680X_INS_LBRA) && + (info->insn != M680X_INS_LBSR) && + (info->insn != M680X_INS_LBRN)) + add_reg_to_rw_list(MI, M680X_REG_CC, READ); +} + +static const m680x_reg g_rr5_to_reg_ids[] = { + M680X_REG_X, M680X_REG_Y, M680X_REG_U, M680X_REG_S, +}; + +static void add_indexed_operand(m680x_info *info, m680x_reg base_reg, + bool post_inc_dec, uint8_t inc_dec, uint8_t offset_bits, + uint16_t offset, bool no_comma) +{ + cs_m680x *m680x = &info->m680x; + cs_m680x_op *op = &m680x->operands[m680x->op_count++]; + + op->type = M680X_OP_INDEXED; + set_operand_size(info, op, 1); + op->idx.base_reg = base_reg; + op->idx.offset_reg = M680X_REG_INVALID; + op->idx.inc_dec = inc_dec; + + if (inc_dec && post_inc_dec) + op->idx.flags |= M680X_IDX_POST_INC_DEC; + + if (offset_bits != M680X_OFFSET_NONE) { + op->idx.offset = offset; + op->idx.offset_addr = 0; + } + + op->idx.offset_bits = offset_bits; + op->idx.flags |= (no_comma ? M680X_IDX_NO_COMMA : 0); +} + +// M6800/1/2/3 indexed mode handler +static void indexedX_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + uint8_t offset = 0; + + read_byte(info, &offset, (*address)++); + + add_indexed_operand(info, M680X_REG_X, false, 0, M680X_OFFSET_BITS_8, + (uint16_t)offset, false); +} + +static void indexedY_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + uint8_t offset = 0; + + read_byte(info, &offset, (*address)++); + + add_indexed_operand(info, M680X_REG_Y, false, 0, M680X_OFFSET_BITS_8, + (uint16_t)offset, false); +} + +// M6809/M6309 indexed mode handler +static void indexed09_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + cs_m680x *m680x = &info->m680x; + cs_m680x_op *op = &m680x->operands[m680x->op_count++]; + uint8_t post_byte = 0; + uint16_t offset = 0; + int16_t soffset = 0; + + read_byte(info, &post_byte, (*address)++); + + op->type = M680X_OP_INDEXED; + set_operand_size(info, op, 1); + op->idx.base_reg = g_rr5_to_reg_ids[(post_byte >> 5) & 0x03]; + op->idx.offset_reg = M680X_REG_INVALID; + + if (!(post_byte & 0x80)) { + // n5,R + if ((post_byte & 0x10) == 0x10) + op->idx.offset = post_byte | 0xfff0; + else + op->idx.offset = post_byte & 0x0f; + + op->idx.offset_addr = op->idx.offset + *address; + op->idx.offset_bits = M680X_OFFSET_BITS_5; + } + else { + if ((post_byte & 0x10) == 0x10) + op->idx.flags |= M680X_IDX_INDIRECT; + + // indexed addressing + switch (post_byte & 0x1f) { + case 0x00: // ,R+ + op->idx.inc_dec = 1; + op->idx.flags |= M680X_IDX_POST_INC_DEC; + break; + + case 0x11: // [,R++] + case 0x01: // ,R++ + op->idx.inc_dec = 2; + op->idx.flags |= M680X_IDX_POST_INC_DEC; + break; + + case 0x02: // ,-R + op->idx.inc_dec = -1; + break; + + case 0x13: // [,--R] + case 0x03: // ,--R + op->idx.inc_dec = -2; + break; + + case 0x14: // [,R] + case 0x04: // ,R + break; + + case 0x15: // [B,R] + case 0x05: // B,R + op->idx.offset_reg = M680X_REG_B; + break; + + case 0x16: // [A,R] + case 0x06: // A,R + op->idx.offset_reg = M680X_REG_A; + break; + + case 0x1c: // [n8,PCR] + case 0x0c: // n8,PCR + op->idx.base_reg = M680X_REG_PC; + read_byte_sign_extended(info, &soffset, (*address)++); + op->idx.offset_addr = offset + *address; + op->idx.offset = soffset; + op->idx.offset_bits = M680X_OFFSET_BITS_8; + break; + + case 0x18: // [n8,R] + case 0x08: // n8,R + read_byte_sign_extended(info, &soffset, (*address)++); + op->idx.offset = soffset; + op->idx.offset_bits = M680X_OFFSET_BITS_8; + break; + + case 0x1d: // [n16,PCR] + case 0x0d: // n16,PCR + op->idx.base_reg = M680X_REG_PC; + read_word(info, &offset, *address); + *address += 2; + op->idx.offset_addr = offset + *address; + op->idx.offset = (int16_t)offset; + op->idx.offset_bits = M680X_OFFSET_BITS_16; + break; + + case 0x19: // [n16,R] + case 0x09: // n16,R + read_word(info, &offset, *address); + *address += 2; + op->idx.offset = (int16_t)offset; + op->idx.offset_bits = M680X_OFFSET_BITS_16; + break; + + case 0x1b: // [D,R] + case 0x0b: // D,R + op->idx.offset_reg = M680X_REG_D; + break; + + case 0x1f: // [n16] + op->type = M680X_OP_EXTENDED; + op->ext.indirect = true; + read_word(info, &op->ext.address, *address); + *address += 2; + break; + + default: + op->idx.base_reg = M680X_REG_INVALID; + break; + } + } + + if (((info->insn == M680X_INS_LEAU) || + (info->insn == M680X_INS_LEAS) || + (info->insn == M680X_INS_LEAX) || + (info->insn == M680X_INS_LEAY)) && + (m680x->operands[0].reg == M680X_REG_X || + (m680x->operands[0].reg == M680X_REG_Y))) + // Only LEAX and LEAY modify CC register + add_reg_to_rw_list(MI, M680X_REG_CC, MODIFY); +} + + +m680x_reg g_idx12_to_reg_ids[4] = { + M680X_REG_X, M680X_REG_Y, M680X_REG_S, M680X_REG_PC, +}; + +m680x_reg g_or12_to_reg_ids[3] = { + M680X_REG_A, M680X_REG_B, M680X_REG_D +}; + +// CPU12 indexed mode handler +static void indexed12_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + cs_m680x *m680x = &info->m680x; + cs_m680x_op *op = &m680x->operands[m680x->op_count++]; + uint8_t post_byte = 0; + uint8_t offset8 = 0; + + read_byte(info, &post_byte, (*address)++); + + op->type = M680X_OP_INDEXED; + set_operand_size(info, op, 1); + op->idx.offset_reg = M680X_REG_INVALID; + + if (!(post_byte & 0x20)) { + // n5,R n5 is a 5-bit signed offset + op->idx.base_reg = g_idx12_to_reg_ids[(post_byte >> 6) & 0x03]; + + if ((post_byte & 0x10) == 0x10) + op->idx.offset = post_byte | 0xfff0; + else + op->idx.offset = post_byte & 0x0f; + + op->idx.offset_addr = op->idx.offset + *address; + op->idx.offset_bits = M680X_OFFSET_BITS_5; + } + else { + if ((post_byte & 0xe0) == 0xe0) + op->idx.base_reg = + g_idx12_to_reg_ids[(post_byte >> 3) & 0x03]; + + switch (post_byte & 0xe7) { + case 0xe0: + case 0xe1: // n9,R + read_byte(info, &offset8, (*address)++); + op->idx.offset = offset8; + + if (post_byte & 0x01) // sign extension + op->idx.offset |= 0xff00; + + op->idx.offset_bits = M680X_OFFSET_BITS_9; + + if (op->idx.base_reg == M680X_REG_PC) + op->idx.offset_addr = op->idx.offset + *address; + + break; + + case 0xe3: // [n16,R] + op->idx.flags |= M680X_IDX_INDIRECT; + + // intentionally fall through + case 0xe2: // n16,R + read_word(info, (uint16_t *)&op->idx.offset, *address); + (*address) += 2; + op->idx.offset_bits = M680X_OFFSET_BITS_16; + + if (op->idx.base_reg == M680X_REG_PC) + op->idx.offset_addr = op->idx.offset + *address; + + break; + + case 0xe4: // A,R + case 0xe5: // B,R + case 0xe6: // D,R + op->idx.offset_reg = + g_or12_to_reg_ids[post_byte & 0x03]; + break; + + case 0xe7: // [D,R] + op->idx.offset_reg = M680X_REG_D; + op->idx.flags |= M680X_IDX_INDIRECT; + break; + + default: // n,-r n,+r n,r- n,r+ + // PC is not allowed in this mode + op->idx.base_reg = + g_idx12_to_reg_ids[(post_byte >> 6) & 0x03]; + op->idx.inc_dec = post_byte & 0x0f; + + if (op->idx.inc_dec & 0x08) // evtl. sign extend value + op->idx.inc_dec |= 0xf0; + + if (op->idx.inc_dec >= 0) + op->idx.inc_dec++; + + if (post_byte & 0x10) + op->idx.flags |= M680X_IDX_POST_INC_DEC; + + break; + + } + } +} + +static void index_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + cs_m680x *m680x = &info->m680x; + cs_m680x_op *op = &m680x->operands[m680x->op_count++]; + + op->type = M680X_OP_CONSTANT; + read_byte(info, &op->const_val, (*address)++); +}; + +static void direct_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + cs_m680x *m680x = &info->m680x; + cs_m680x_op *op = &m680x->operands[m680x->op_count++]; + + op->type = M680X_OP_DIRECT; + set_operand_size(info, op, 1); + read_byte(info, &op->direct_addr, (*address)++); +}; + +static void extended_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + cs_m680x *m680x = &info->m680x; + cs_m680x_op *op = &m680x->operands[m680x->op_count++]; + + op->type = M680X_OP_EXTENDED; + set_operand_size(info, op, 1); + read_word(info, &op->ext.address, *address); + *address += 2; +} + +static void immediate_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + cs_m680x *m680x = &info->m680x; + cs_m680x_op *op = &m680x->operands[m680x->op_count++]; + uint16_t word = 0; + int16_t sword = 0; + + op->type = M680X_OP_IMMEDIATE; + set_operand_size(info, op, 1); + + switch (op->size) { + case 1: + read_byte_sign_extended(info, &sword, *address); + op->imm = sword; + break; + + case 2: + read_word(info, &word, *address); + op->imm = (int16_t)word; + break; + + case 4: + read_sdword(info, &op->imm, *address); + break; + + default: + op->imm = 0; + fprintf(stderr, "Internal error: Unexpected immediate byte " + "size %d.\n", op->size); + } + + *address += op->size; +} + +// handler for bit move instructions, e.g: BAND A,5,1,$40 Used by HD6309 +static void bit_move_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + static const m680x_reg m680x_reg[] = { + M680X_REG_CC, M680X_REG_A, M680X_REG_B, M680X_REG_INVALID, + }; + + uint8_t post_byte = 0; + cs_m680x *m680x = &info->m680x; + cs_m680x_op *op; + + read_byte(info, &post_byte, *address); + (*address)++; + + // operand[0] = register + add_reg_operand(info, m680x_reg[post_byte >> 6]); + + // operand[1] = bit index in source operand + op = &m680x->operands[m680x->op_count++]; + op->type = M680X_OP_CONSTANT; + op->const_val = (post_byte >> 3) & 0x07; + + // operand[2] = bit index in destination operand + op = &m680x->operands[m680x->op_count++]; + op->type = M680X_OP_CONSTANT; + op->const_val = post_byte & 0x07; + + direct_hdlr(MI, info, address); +} + +// handler for TFM instruction, e.g: TFM X+,Y+ Used by HD6309 +static void tfm_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + static const uint8_t inc_dec_r0[] = { + 1, -1, 1, 0, + }; + static const uint8_t inc_dec_r1[] = { + 1, -1, 0, 1, + }; + uint8_t regs = 0; + uint8_t index = (MI->Opcode & 0xff) - 0x38; + + read_byte(info, ®s, *address); + + add_indexed_operand(info, g_tfr_exg_reg_ids[regs >> 4], true, + inc_dec_r0[index], M680X_OFFSET_NONE, 0, true); + add_indexed_operand(info, g_tfr_exg_reg_ids[regs & 0x0f], true, + inc_dec_r1[index], M680X_OFFSET_NONE, 0, true); + + add_reg_to_rw_list(MI, M680X_REG_W, READ | WRITE); +} + +static void opidx_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + cs_m680x *m680x = &info->m680x; + cs_m680x_op *op = &m680x->operands[m680x->op_count++]; + + // bit index is coded in Opcode + op->type = M680X_OP_CONSTANT; + op->const_val = (MI->Opcode & 0x0e) >> 1; +} + +// handler for bit test and branch instruction. Used by M6805. +// The bit index is part of the opcode. +// Example: BRSET 3,<$40,LOOP +static void opidx_dir_rel_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + cs_m680x *m680x = &info->m680x; + cs_m680x_op *op = &m680x->operands[m680x->op_count++]; + + // bit index is coded in Opcode + op->type = M680X_OP_CONSTANT; + op->const_val = (MI->Opcode & 0x0e) >> 1; + direct_hdlr(MI, info, address); + relative8_hdlr(MI, info, address); + + add_reg_to_rw_list(MI, M680X_REG_CC, MODIFY); +} + +static void indexedX0_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + add_indexed_operand(info, M680X_REG_X, false, 0, M680X_OFFSET_NONE, + 0, false); +} + +static void indexedX16_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + uint16_t offset = 0; + + read_word(info, &offset, *address); + *address += 2; + add_indexed_operand(info, M680X_REG_X, false, 0, M680X_OFFSET_BITS_16, + offset, false); +} + +static void imm_rel_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + immediate_hdlr(MI, info, address); + relative8_hdlr(MI, info, address); +} + +static void indexedS_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + uint8_t offset = 0; + + read_byte(info, &offset, (*address)++); + + add_indexed_operand(info, M680X_REG_S, false, 0, M680X_OFFSET_BITS_8, + (uint16_t)offset, false); +} + +static void indexedS16_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + uint16_t offset = 0; + + read_word(info, &offset, *address); + address += 2; + + add_indexed_operand(info, M680X_REG_S, false, 0, M680X_OFFSET_BITS_16, + offset, false); +} + +static void indexedX0p_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + add_indexed_operand(info, M680X_REG_X, true, 1, M680X_OFFSET_NONE, + 0, true); +} + +static void indexedXp_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + uint8_t offset = 0; + + read_byte(info, &offset, (*address)++); + + add_indexed_operand(info, M680X_REG_X, true, 1, M680X_OFFSET_BITS_8, + (uint16_t)offset, false); +} + +static void imm_idx12_x_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + cs_m680x *m680x = &info->m680x; + cs_m680x_op *op = &m680x->operands[m680x->op_count++]; + + indexed12_hdlr(MI, info, address); + op->type = M680X_OP_IMMEDIATE; + + if (info->insn == M680X_INS_MOVW) { + uint16_t imm16 = 0; + + read_word(info, &imm16, *address); + op->imm = (int16_t)imm16; + op->size = 2; + } + else { + uint8_t imm8 = 0; + + read_byte(info, &imm8, *address); + op->imm = (int8_t)imm8; + op->size = 1; + } + + set_operand_size(info, op, 1); +} + +static void ext_idx12_x_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + cs_m680x *m680x = &info->m680x; + cs_m680x_op *op0 = &m680x->operands[m680x->op_count++]; + uint16_t imm16 = 0; + + indexed12_hdlr(MI, info, address); + read_word(info, &imm16, *address); + op0->type = M680X_OP_EXTENDED; + op0->imm = (int16_t)imm16; + set_operand_size(info, op0, 1); +} + +// handler for CPU12 DBEQ/DNBE/IBEQ/IBNE/TBEQ/TBNE instructions. +// Example: DBNE X,$1000 +static void loop_hdlr(MCInst *MI, m680x_info *info, uint16_t *address) +{ + static const m680x_reg index_to_reg_id[] = { + M680X_REG_A, M680X_REG_B, M680X_REG_INVALID, M680X_REG_INVALID, + M680X_REG_D, M680X_REG_X, M680X_REG_Y, M680X_REG_S, + }; + static const m680x_insn index_to_insn_id[] = { + M680X_INS_DBEQ, M680X_INS_DBNE, M680X_INS_TBEQ, M680X_INS_TBNE, + M680X_INS_IBEQ, M680X_INS_IBNE, M680X_INS_ILLGL, M680X_INS_ILLGL + }; + cs_m680x *m680x = &info->m680x; + uint8_t post_byte = 0; + uint8_t rel = 0; + + read_byte(info, &post_byte, (*address)++); + + info->insn = index_to_insn_id[(post_byte >> 5) & 0x07]; + + if (info->insn == M680X_INS_ILLGL) { + fprintf(stderr, "Internal error: Unexpected post byte " + "in loop instruction %02X.\n", post_byte); + illegal_hdlr(MI, info, address); + }; + + read_byte(info, &rel, (*address)++); + + add_reg_operand(info, index_to_reg_id[post_byte & 0x07]); + + cs_m680x_op *op = &m680x->operands[m680x->op_count++]; + + op->type = M680X_OP_RELATIVE; + + op->rel.offset = (post_byte & 0x10) ? 0xff00 | rel : rel; + + op->rel.address = *address + op->rel.offset; + + add_insn_group(MI->flat_insn->detail, M680X_GRP_BRAREL); +} + +static void (*const g_insn_handler[])(MCInst *, m680x_info *, uint16_t *) = { + illegal_hdlr, + relative8_hdlr, + relative16_hdlr, + immediate_hdlr, // 8-bit + immediate_hdlr, // 16-bit + immediate_hdlr, // 32-bit + direct_hdlr, + extended_hdlr, + indexedX_hdlr, + indexedY_hdlr, + indexed09_hdlr, + inherent_hdlr, + reg_reg09_hdlr, + reg_bits_hdlr, + bit_move_hdlr, + tfm_hdlr, + opidx_hdlr, + opidx_dir_rel_hdlr, + indexedX0_hdlr, + indexedX16_hdlr, + imm_rel_hdlr, + indexedS_hdlr, + indexedS16_hdlr, + indexedXp_hdlr, + indexedX0p_hdlr, + indexed12_hdlr, + indexed12_hdlr, // subset of indexed12 + reg_reg12_hdlr, + loop_hdlr, + index_hdlr, + imm_idx12_x_hdlr, + imm_idx12_x_hdlr, + ext_idx12_x_hdlr, +}; /* handler function pointers */ + +/* Disasemble one instruction at address and store in str_buff */ +static unsigned int m680x_disassemble(MCInst *MI, m680x_info *info, + uint16_t address) +{ + cs_m680x *m680x = &info->m680x; + cs_detail *detail = MI->flat_insn->detail; + uint16_t base_address = address; + insn_desc insn_description; + + if (detail != NULL) { + detail->regs_read_count = 0; + detail->regs_write_count = 0; + detail->groups_count = 0; + } + + memset(&insn_description, 0, sizeof(insn_description)); + memset(m680x, 0, sizeof(*m680x)); + info->insn_size = 1; + + if (decode_insn(info, address, &insn_description)) { + m680x_reg reg; + + if (insn_description.opcode > 0xff) + address += 2; // 8-bit opcode + page prefix + else + address++; // 8-bit opcode only + + info->insn = insn_description.insn; + + MCInst_setOpcode(MI, insn_description.opcode); + + reg = g_insn_props[info->insn].reg0; + + if (reg != M680X_REG_INVALID) { + if (reg == M680X_REG_HX && + (!info->cpu->reg_byte_size[reg])) + reg = M680X_REG_X; + + add_reg_operand(info, reg); + // First (or second) operand is a register which is + // part of the mnemonic + m680x->flags |= M680X_FIRST_OP_IN_MNEM; + reg = g_insn_props[info->insn].reg1; + + if (reg != M680X_REG_INVALID) { + if (reg == M680X_REG_HX && + (!info->cpu->reg_byte_size[reg])) + reg = M680X_REG_X; + + add_reg_operand(info, reg); + m680x->flags |= M680X_SECOND_OP_IN_MNEM; + } + } + + // Call addressing mode specific instruction handler + (g_insn_handler[insn_description.hid[0]])(MI, info, + &address); + (g_insn_handler[insn_description.hid[1]])(MI, info, + &address); + + add_insn_group(detail, g_insn_props[info->insn].group); + + if (g_insn_props[info->insn].cc_modified && + (info->cpu->insn_cc_not_modified[0] != info->insn) && + (info->cpu->insn_cc_not_modified[1] != info->insn)) + add_reg_to_rw_list(MI, M680X_REG_CC, MODIFY); + + e_access_mode access_mode = + g_insn_props[info->insn].access_mode; + + // Fix for M6805 BSET/BCLR. It has a differnt operand order + // in comparison to the M6811 + if ((info->cpu->insn_cc_not_modified[0] == info->insn) || + (info->cpu->insn_cc_not_modified[1] == info->insn)) + access_mode = rmmm; + + build_regs_read_write_counts(MI, info, access_mode); + add_operators_access(MI, info, access_mode); + + if (g_insn_props[info->insn].update_reg_access) + set_changed_regs_read_write_counts(MI, info); + + info->insn_size = insn_description.insn_size; + + return info->insn_size; + } + else + MCInst_setOpcode(MI, insn_description.opcode); + + // Illegal instruction + address = base_address; + illegal_hdlr(MI, info, &address); + return 1; +} + +// Tables to get the byte size of a register on the CPU +// based on an enum m680x_reg value. +// Invalid registers return 0. +static const uint8_t g_m6800_reg_byte_size[22] = { + // A B E F 0 D W CC DP MD HX H X Y S U V Q PC T2 T3 + 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 2, 0, 0 +}; + +static const uint8_t g_m6805_reg_byte_size[22] = { + // A B E F 0 D W CC DP MD HX H X Y S U V Q PC T2 T3 + 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 2, 0, 0 +}; + +static const uint8_t g_m6808_reg_byte_size[22] = { + // A B E F 0 D W CC DP MD HX H X Y S U V Q PC T2 T3 + 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 1, 1, 0, 2, 0, 0, 0, 2, 0, 0 +}; + +static const uint8_t g_m6801_reg_byte_size[22] = { + // A B E F 0 D W CC DP MD HX H X Y S U V Q PC T2 T3 + 0, 1, 1, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 2, 0, 0 +}; + +static const uint8_t g_m6811_reg_byte_size[22] = { + // A B E F 0 D W CC DP MD HX H X Y S U V Q PC T2 T3 + 0, 1, 1, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 2, 0, 0 +}; + +static const uint8_t g_cpu12_reg_byte_size[22] = { + // A B E F 0 D W CC DP MD HX H X Y S U V Q PC T2 T3 + 0, 1, 1, 0, 0, 0, 2, 0, 1, 0, 0, 0, 0, 2, 2, 2, 0, 0, 0, 2, 2, 2 +}; + +static const uint8_t g_m6809_reg_byte_size[22] = { + // A B E F 0 D W CC DP MD HX H X Y S U V Q PC T2 T3 + 0, 1, 1, 0, 0, 0, 2, 0, 1, 1, 0, 0, 0, 2, 2, 2, 2, 0, 0, 2, 0, 0 +}; + +static const uint8_t g_hd6309_reg_byte_size[22] = { + // A B E F 0 D W CC DP MD HX H X Y S U V Q PC T2 T3 + 0, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 0, 0, 2, 2, 2, 2, 2, 4, 2, 0, 0 +}; + +// Table to check for a valid register nibble on the M6809 CPU +// used for TFR and EXG instruction. +static const bool m6809_tfr_reg_valid[16] = { + true, true, true, true, true, true, false, false, + true, true, true, true, false, false, false, false, +}; + +static const cpu_tables g_cpu_tables[] = { + { + // M680X_CPU_TYPE_INVALID + NULL, + { NULL, NULL }, + { 0, 0 }, + { 0x00, 0x00, 0x00 }, + { NULL, NULL, NULL }, + { 0, 0, 0 }, + NULL, + NULL, + { M680X_INS_INVLD, M680X_INS_INVLD } + }, + { + // M680X_CPU_TYPE_6301 + &g_m6800_inst_page1_table[0], + { &g_m6801_inst_overlay_table[0], &g_hd6301_inst_overlay_table[0] }, + { + ARR_SIZE(g_m6801_inst_overlay_table), + ARR_SIZE(g_hd6301_inst_overlay_table) + }, + { 0x00, 0x00, 0x00 }, + { NULL, NULL, NULL }, + { 0, 0, 0 }, + &g_m6801_reg_byte_size[0], + NULL, + { M680X_INS_INVLD, M680X_INS_INVLD } + }, + { + // M680X_CPU_TYPE_6309 + &g_m6809_inst_page1_table[0], + { &g_hd6309_inst_overlay_table[0], NULL }, + { ARR_SIZE(g_hd6309_inst_overlay_table), 0 }, + { 0x10, 0x11, 0x00 }, + { &g_hd6309_inst_page2_table[0], &g_hd6309_inst_page3_table[0], NULL }, + { + ARR_SIZE(g_hd6309_inst_page2_table), + ARR_SIZE(g_hd6309_inst_page3_table), + 0 + }, + &g_hd6309_reg_byte_size[0], + NULL, + { M680X_INS_INVLD, M680X_INS_INVLD } + }, + { + // M680X_CPU_TYPE_6800 + &g_m6800_inst_page1_table[0], + { NULL, NULL }, + { 0, 0 }, + { 0x00, 0x00, 0x00 }, + { NULL, NULL, NULL }, + { 0, 0, 0 }, + &g_m6800_reg_byte_size[0], + NULL, + { M680X_INS_INVLD, M680X_INS_INVLD } + }, + { + // M680X_CPU_TYPE_6801 + &g_m6800_inst_page1_table[0], + { &g_m6801_inst_overlay_table[0], NULL }, + { ARR_SIZE(g_m6801_inst_overlay_table), 0 }, + { 0x00, 0x00, 0x00 }, + { NULL, NULL, NULL }, + { 0, 0, 0 }, + &g_m6801_reg_byte_size[0], + NULL, + { M680X_INS_INVLD, M680X_INS_INVLD } + }, + { + // M680X_CPU_TYPE_6805 + &g_m6805_inst_page1_table[0], + { NULL, NULL }, + { 0, 0 }, + { 0x00, 0x00, 0x00 }, + { NULL, NULL, NULL }, + { 0, 0, 0 }, + &g_m6805_reg_byte_size[0], + NULL, + { M680X_INS_BCLR, M680X_INS_BSET } + }, + { + // M680X_CPU_TYPE_6808 + &g_m6805_inst_page1_table[0], + { &g_m6808_inst_overlay_table[0], NULL }, + { ARR_SIZE(g_m6808_inst_overlay_table), 0 }, + { 0x9E, 0x00, 0x00 }, + { &g_m6808_inst_page2_table[0], NULL, NULL }, + { ARR_SIZE(g_m6808_inst_page2_table), 0, 0 }, + &g_m6808_reg_byte_size[0], + NULL, + { M680X_INS_BCLR, M680X_INS_BSET } + }, + { + // M680X_CPU_TYPE_6809 + &g_m6809_inst_page1_table[0], + { NULL, NULL }, + { 0, 0 }, + { 0x10, 0x11, 0x00 }, + { + &g_m6809_inst_page2_table[0], + &g_m6809_inst_page3_table[0], + NULL + }, + { + ARR_SIZE(g_m6809_inst_page2_table), + ARR_SIZE(g_m6809_inst_page3_table), + 0 + }, + &g_m6809_reg_byte_size[0], + &m6809_tfr_reg_valid[0], + { M680X_INS_INVLD, M680X_INS_INVLD } + }, + { + // M680X_CPU_TYPE_6811 + &g_m6800_inst_page1_table[0], + { + &g_m6801_inst_overlay_table[0], + &g_m6811_inst_overlay_table[0] + }, + { + ARR_SIZE(g_m6801_inst_overlay_table), + ARR_SIZE(g_m6811_inst_overlay_table) + }, + { 0x18, 0x1A, 0xCD }, + { + &g_m6811_inst_page2_table[0], + &g_m6811_inst_page3_table[0], + &g_m6811_inst_page4_table[0] + }, + { + ARR_SIZE(g_m6811_inst_page2_table), + ARR_SIZE(g_m6811_inst_page3_table), + ARR_SIZE(g_m6811_inst_page4_table) + }, + &g_m6811_reg_byte_size[0], + NULL, + { M680X_INS_INVLD, M680X_INS_INVLD } + }, + { + // M680X_CPU_TYPE_CPU12 + &g_cpu12_inst_page1_table[0], + { NULL, NULL }, + { 0, 0 }, + { 0x18, 0x00, 0x00 }, + { &g_cpu12_inst_page2_table[0], NULL, NULL }, + { ARR_SIZE(g_cpu12_inst_page2_table), 0, 0 }, + &g_cpu12_reg_byte_size[0], + NULL, + { M680X_INS_INVLD, M680X_INS_INVLD } + }, + { + // M680X_CPU_TYPE_HCS08 + &g_m6805_inst_page1_table[0], + { + &g_m6808_inst_overlay_table[0], + &g_hcs08_inst_overlay_table[0] + }, + { + ARR_SIZE(g_m6808_inst_overlay_table), + ARR_SIZE(g_hcs08_inst_overlay_table) + }, + { 0x9E, 0x00, 0x00 }, + { &g_hcs08_inst_page2_table[0], NULL, NULL }, + { ARR_SIZE(g_hcs08_inst_page2_table), 0, 0 }, + &g_m6808_reg_byte_size[0], + NULL, + { M680X_INS_BCLR, M680X_INS_BSET } + }, +}; + +static const char *s_cpu_type[] = { + "INVALID", "6301", "6309", "6800", "6801", "6805", "6808", + "6809", "6811", "CPU12", "HCS08", +}; + +static bool m680x_setup_internals(m680x_info *info, e_cpu_type cpu_type, + uint16_t address, + const uint8_t *code, uint16_t code_len) +{ + if (cpu_type == M680X_CPU_TYPE_INVALID) { + fprintf(stderr, "M680X_CPU_TYPE_%s is not suppported\n", + s_cpu_type[cpu_type]); + return false; + } + + info->code = code; + info->size = code_len; + info->offset = address; + info->cpu_type = cpu_type; + + info->cpu = &g_cpu_tables[info->cpu_type]; + + return true; +} + +bool M680X_getInstruction(csh ud, const uint8_t *code, size_t code_len, + MCInst *MI, uint16_t *size, uint64_t address, void *inst_info) +{ + unsigned int insn_size = 0; + e_cpu_type cpu_type = M680X_CPU_TYPE_INVALID; // No default CPU type + cs_struct *handle = (cs_struct *)ud; + m680x_info *info = (m680x_info *)handle->printer_info; + + MCInst_clear(MI); + + if (handle->mode & CS_MODE_M680X_6800) + cpu_type = M680X_CPU_TYPE_6800; + + else if (handle->mode & CS_MODE_M680X_6801) + cpu_type = M680X_CPU_TYPE_6801; + + else if (handle->mode & CS_MODE_M680X_6805) + cpu_type = M680X_CPU_TYPE_6805; + + else if (handle->mode & CS_MODE_M680X_6808) + cpu_type = M680X_CPU_TYPE_6808; + + else if (handle->mode & CS_MODE_M680X_HCS08) + cpu_type = M680X_CPU_TYPE_HCS08; + + else if (handle->mode & CS_MODE_M680X_6809) + cpu_type = M680X_CPU_TYPE_6809; + + else if (handle->mode & CS_MODE_M680X_6301) + cpu_type = M680X_CPU_TYPE_6301; + + else if (handle->mode & CS_MODE_M680X_6309) + cpu_type = M680X_CPU_TYPE_6309; + + else if (handle->mode & CS_MODE_M680X_6811) + cpu_type = M680X_CPU_TYPE_6811; + + else if (handle->mode & CS_MODE_M680X_CPU12) + cpu_type = M680X_CPU_TYPE_CPU12; + + if (cpu_type != M680X_CPU_TYPE_INVALID && + m680x_setup_internals(info, cpu_type, (uint16_t)address, code, + code_len)) + insn_size = m680x_disassemble(MI, info, (uint16_t)address); + + if (insn_size == 0) { + *size = 1; + return false; + } + + // Make sure we always stay within range + if (insn_size > code_len) { + *size = (uint16_t)code_len; + return false; + } + else + *size = (uint16_t)insn_size; + + return true; +} + +cs_err M680X_disassembler_init(cs_struct *ud) +{ + if (M680X_REG_ENDING != ARR_SIZE(g_m6800_reg_byte_size)) { + fprintf(stderr, "Internal error: Size mismatch in enum " + "m680x_reg and g_m6800_reg_byte_size\n"); + + return CS_ERR_MODE; + } + + if (M680X_REG_ENDING != ARR_SIZE(g_m6801_reg_byte_size)) { + fprintf(stderr, "Internal error: Size mismatch in enum " + "m680x_reg and g_m6801_reg_byte_size\n"); + + return CS_ERR_MODE; + } + + if (M680X_REG_ENDING != ARR_SIZE(g_m6805_reg_byte_size)) { + fprintf(stderr, "Internal error: Size mismatch in enum " + "m680x_reg and g_m6805_reg_byte_size\n"); + + return CS_ERR_MODE; + } + + if (M680X_REG_ENDING != ARR_SIZE(g_m6808_reg_byte_size)) { + fprintf(stderr, "Internal error: Size mismatch in enum " + "m680x_reg and g_m6808_reg_byte_size\n"); + + return CS_ERR_MODE; + } + + if (M680X_REG_ENDING != ARR_SIZE(g_m6811_reg_byte_size)) { + fprintf(stderr, "Internal error: Size mismatch in enum " + "m680x_reg and g_m6811_reg_byte_size\n"); + + return CS_ERR_MODE; + } + + if (M680X_REG_ENDING != ARR_SIZE(g_cpu12_reg_byte_size)) { + fprintf(stderr, "Internal error: Size mismatch in enum " + "m680x_reg and g_cpu12_reg_byte_size\n"); + + return CS_ERR_MODE; + } + + if (M680X_REG_ENDING != ARR_SIZE(g_m6809_reg_byte_size)) { + fprintf(stderr, "Internal error: Size mismatch in enum " + "m680x_reg and g_m6809_reg_byte_size\n"); + + return CS_ERR_MODE; + } + + if (M680X_INS_ENDING != ARR_SIZE(g_insn_props)) { + fprintf(stderr, "Internal error: Size mismatch in enum " + "m680x_insn and g_insn_props\n"); + + return CS_ERR_MODE; + } + + if (M680X_CPU_TYPE_ENDING != ARR_SIZE(s_cpu_type)) { + fprintf(stderr, "Internal error: Size mismatch in enum " + "e_cpu_type and s_cpu_type\n"); + + return CS_ERR_MODE; + } + + if (M680X_CPU_TYPE_ENDING != ARR_SIZE(g_cpu_tables)) { + fprintf(stderr, "Internal error: Size mismatch in enum " + "e_cpu_type and g_cpu_tables\n"); + + return CS_ERR_MODE; + } + + if (HANDLER_ID_ENDING != ARR_SIZE(g_insn_handler)) { + fprintf(stderr, "Internal error: Size mismatch in enum " + "insn_hdlr_id and g_insn_handler\n"); + + return CS_ERR_MODE; + } + + if (ACCESS_MODE_ENDING != MATRIX_SIZE(g_access_mode_to_access)) { + fprintf(stderr, "Internal error: Size mismatch in enum " + "e_access_mode and g_access_mode_to_access\n"); + + return CS_ERR_MODE; + } + + return CS_ERR_OK; +} + +#ifndef CAPSTONE_DIET +void M680X_reg_access(const cs_insn *insn, + cs_regs regs_read, uint8_t *regs_read_count, + cs_regs regs_write, uint8_t *regs_write_count) +{ + if (insn->detail == NULL) { + *regs_read_count = 0; + *regs_write_count = 0; + } + else { + *regs_read_count = insn->detail->regs_read_count; + *regs_write_count = insn->detail->regs_write_count; + + memcpy(regs_read, insn->detail->regs_read, + *regs_read_count * sizeof(insn->detail->regs_read[0])); + memcpy(regs_write, insn->detail->regs_write, + *regs_write_count * + sizeof(insn->detail->regs_write[0])); + } +} +#endif + +#endif + diff --git a/arch/M680X/M680XDisassembler.h b/arch/M680X/M680XDisassembler.h new file mode 100644 index 0000000000..d85a3cca60 --- /dev/null +++ b/arch/M680X/M680XDisassembler.h @@ -0,0 +1,17 @@ +/* Capstone Disassembly Engine */ +/* M680X Backend by Wolfgang Schwotzer 2017 */ + +#ifndef CS_M680XDISASSEMBLER_H +#define CS_M680XDISASSEMBLER_H + +#include "../../MCInst.h" + +bool M680X_getInstruction(csh ud, const uint8_t *code, size_t code_len, + MCInst *instr, uint16_t *size, uint64_t address, void *info); +void M680X_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id); +void M680X_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 + diff --git a/arch/M680X/M680XDisassemblerInternals.h b/arch/M680X/M680XDisassemblerInternals.h new file mode 100644 index 0000000000..2f59c3f59d --- /dev/null +++ b/arch/M680X/M680XDisassemblerInternals.h @@ -0,0 +1,57 @@ +/* Capstone Disassembly Engine */ +/* M680X Backend by Wolfgang Schwotzer 2017 */ + +#ifndef CS_M680XDISASSEMBLERINTERNALS_H +#define CS_M680XDISASSEMBLERINTERNALS_H + +#include "../../MCInst.h" +#include "../../include/capstone/m680x.h" + +typedef enum e_cpu_type { + M680X_CPU_TYPE_INVALID, + M680X_CPU_TYPE_6301, // M680X Hitachi HD6301,HD6303 mode + M680X_CPU_TYPE_6309, // M680X Hitachi HD6309 mode + M680X_CPU_TYPE_6800, // M680X Motorola 6800,6802 mode + M680X_CPU_TYPE_6801, // M680X Motorola 6801,6803 mode + M680X_CPU_TYPE_6805, // M680X Motorola/Freescale M68HC05 mode + M680X_CPU_TYPE_6808, // M680X Motorola/Freescale M68HC08 mode + M680X_CPU_TYPE_6809, // M680X Motorola 6809 mode + M680X_CPU_TYPE_6811, // M680X Motorola/Freescale M68HC11 mode + M680X_CPU_TYPE_CPU12, // M680X Motorola/Freescale CPU12 mode + // used on M68HC12/HCS12 + M680X_CPU_TYPE_HCS08, // M680X Freescale HCS08 mode + M680X_CPU_TYPE_ENDING, +} e_cpu_type; + +struct inst_page1; +struct inst_pageX; + +typedef struct { + const struct inst_page1 *inst_page1_table; + const struct inst_pageX *inst_overlay_table[2]; + size_t overlay_table_size[2]; + uint8_t pageX_prefix[3]; + const struct inst_pageX *inst_pageX_table[3]; + size_t pageX_table_size[3]; + const uint8_t *reg_byte_size; + const bool *tfr_reg_valid; + m680x_insn insn_cc_not_modified[2]; +} cpu_tables; + +/* Private, For internal use only */ +typedef struct m680x_info { + const uint8_t *code; // code buffer + uint32_t size; // byte size of code + uint16_t offset; // address offset of first byte in code buffer + e_cpu_type cpu_type; // The CPU type to be used for disassembling + cs_m680x m680x; // M680X specific properties + const cpu_tables *cpu; + m680x_insn insn; // Instruction ID + uint8_t insn_size; // byte size of instruction +} m680x_info; + +extern cs_err M680X_disassembler_init(cs_struct *ud); +extern cs_err M680X_instprinter_init(cs_struct *ud); + +#endif + diff --git a/arch/M680X/M680XInstPrinter.c b/arch/M680X/M680XInstPrinter.c new file mode 100644 index 0000000000..34a8836a8f --- /dev/null +++ b/arch/M680X/M680XInstPrinter.c @@ -0,0 +1,365 @@ +/* Capstone Disassembly Engine */ +/* M680X Backend by Wolfgang Schwotzer 2017 */ + +#ifdef CAPSTONE_HAS_M680X +#include +#include +#include +#include + +#include "../../MCInst.h" +#include "../../SStream.h" +#include "../../MCRegisterInfo.h" +#include "../../utils.h" +#include "M680XInstPrinter.h" +#include "M680XDisassembler.h" +#include "M680XDisassemblerInternals.h" + +#ifndef CAPSTONE_DIET +static const char s_reg_names[][10] = { + "", "A", "B", "E", "F", "0", "D", "W", "CC", "DP", "MD", + "HX", "H", "X", "Y", "S", "U", "V", "Q", "PC", "TMP2", "TMP3", +}; + +static const char s_instruction_names[][6] = { + "INVLD", "ABA", "ABX", "ABY", "ADC", "ADCA", "ADCB", "ADCD", "ADCR", + "ADD", "ADDA", "ADDB", "ADDD", "ADDE", "ADDF", "ADDR", "ADDW", + "AIM", "AIS", "AIX", "AND", "ANDA", "ANDB", "ANDCC", "ANDD", "ANDR", + "ASL", "ASLA", "ASLB", "ASLD", + "ASR", "ASRA", "ASRB", "ASRD", "ASRX", + "BAND", + "BCC", "BCLR", "BCS", "BEOR", "BEQ", "BGE", "BGND", "BGT", "BHCC", + "BHCS", "BHI", + "BIAND", "BIEOR", "BIH", "BIL", + "BIOR", "BIT", "BITA", "BITB", "BITD", "BITMD", "BLE", "BLS", "BLT", + "BMC", + "BMI", "BMS", + "BNE", "BOR", "BPL", "BRCLR", "BRSET", "BRA", "BRN", "BSET", "BSR", + "BVC", "BVS", + "CALL", "CBA", "CBEQ", "CBEQA", "CBEQX", "CLC", "CLI", + "CLR", "CLRA", "CLRB", "CLRD", "CLRE", "CLRF", "CLRH", "CLRW", "CLRX", + "CLV", "CMP", + "CMPA", "CMPB", "CMPD", "CMPE", "CMPF", "CMPR", "CMPS", "CMPU", "CMPW", + "CMPX", "CMPY", + "COM", "COMA", "COMB", "COMD", "COME", "COMF", "COMW", "COMX", "CPD", + "CPHX", "CPS", "CPX", "CPY", + "CWAI", "DAA", "DBEQ", "DBNE", "DBNZ", "DBNZA", "DBNZX", + "DEC", "DECA", "DECB", "DECD", "DECE", "DECF", "DECW", + "DECX", "DES", "DEX", "DEY", + "DIV", "DIVD", "DIVQ", "EDIV", "EDIVS", "EIM", "EMACS", "EMAXD", + "EMAXM", "EMIND", "EMINM", "EMUL", "EMULS", + "EOR", "EORA", "EORB", "EORD", "EORR", "ETBL", + "EXG", "FDIV", "IBEQ", "IBNE", "IDIV", "IDIVS", "ILLGL", + "INC", "INCA", "INCB", "INCD", "INCE", "INCF", "INCW", "INCX", + "INS", "INX", "INY", + "JMP", "JSR", + "LBCC", "LBCS", "LBEQ", "LBGE", "LBGT", "LBHI", "LBLE", "LBLS", "LBLT", + "LBMI", "LBNE", "LBPL", "LBRA", "LBRN", "LBSR", "LBVC", "LBVS", + "LDA", "LDAA", "LDAB", "LDB", "LDBT", "LDD", "LDE", "LDF", "LDHX", + "LDMD", + "LDQ", "LDS", "LDU", "LDW", "LDX", "LDY", + "LEAS", "LEAU", "LEAX", "LEAY", + "LSL", "LSLA", "LSLB", "LSLD", "LSLX", + "LSR", "LSRA", "LSRB", "LSRD", "LSRW", "LSRX", + "MAXA", "MAXM", "MEM", "MINA", "MINM", "MOV", "MOVB", "MOVW", "MUL", + "MULD", + "NEG", "NEGA", "NEGB", "NEGD", "NEGX", + "NOP", "NSA", "OIM", "ORA", "ORAA", "ORAB", "ORB", "ORCC", "ORD", "ORR", + "PSHA", "PSHB", "PSHC", "PSHD", "PSHH", "PSHS", "PSHSW", "PSHU", + "PSHUW", "PSHX", "PSHY", + "PULA", "PULB", "PULC", "PULD", "PULH", "PULS", "PULSW", "PULU", + "PULUW", "PULX", "PULY", "REV", "REVW", + "ROL", "ROLA", "ROLB", "ROLD", "ROLW", "ROLX", + "ROR", "RORA", "RORB", "RORD", "RORW", "RORX", + "RSP", "RTC", "RTI", "RTS", "SBA", "SBC", "SBCA", "SBCB", "SBCD", + "SBCR", + "SEC", "SEI", "SEV", "SEX", "SEXW", "SLP", "STA", "STAA", "STAB", "STB", + "STBT", "STD", "STE", "STF", "STOP", "STHX", + "STQ", "STS", "STU", "STW", "STX", "STY", + "SUB", "SUBA", "SUBB", "SUBD", "SUBE", "SUBF", "SUBR", "SUBW", + "SWI", "SWI2", "SWI3", + "SYNC", "TAB", "TAP", "TAX", "TBA", "TBEQ", "TBL", "TBNE", "TEST", + "TFM", "TFR", + "TIM", "TPA", + "TST", "TSTA", "TSTB", "TSTD", "TSTE", "TSTF", "TSTW", "TSTX", + "TSX", "TSY", "TXA", "TXS", "TYS", "WAI", "WAIT", "WAV", "WAVR", + "XGDX", "XGDY", +}; + +static name_map s_group_names[] = { + { M680X_GRP_INVALID, "" }, + { M680X_GRP_JUMP, "JUMP" }, + { M680X_GRP_CALL, "CALL" }, + { M680X_GRP_RET, "RETURN" }, + { M680X_GRP_INT, "INTERRUPT" }, + { M680X_GRP_IRET, "INTERRUPT_RETURN" }, + { M680X_GRP_PRIV, "PRIVILEGED" }, + { M680X_GRP_BRAREL, "BRANCH_RELATIVE" }, +}; +#endif + +static void printRegName(cs_struct *handle, SStream *OS, unsigned int reg) +{ +#ifndef CAPSTONE_DIET + SStream_concat(OS, handle->reg_name((csh)handle, reg)); +#endif +} + +static void printInstructionName(cs_struct *handle, SStream *OS, + unsigned int insn) +{ +#ifndef CAPSTONE_DIET + SStream_concat(OS, handle->insn_name((csh)handle, insn)); +#endif +} + +static uint32_t get_unsigned(int32_t value, int byte_size) +{ + switch (byte_size) { + case 1: + return (uint32_t)(value & 0xff); + + case 2: + return (uint32_t)(value & 0xffff); + + default: + case 4: + return (uint32_t)value; + } +} + +static void printIncDec(bool isPost, SStream *O, m680x_info *info, + cs_m680x_op *op) +{ + static const char s_inc_dec[][3] = { "--", "-", "", "+", "++" }; + + if (!op->idx.inc_dec) + return; + + if ((!isPost && !(op->idx.flags & M680X_IDX_POST_INC_DEC)) || + (isPost && (op->idx.flags & M680X_IDX_POST_INC_DEC))) { + char *prePostfix = ""; + + if (info->cpu_type == M680X_CPU_TYPE_CPU12) + prePostfix = (op->idx.inc_dec < 0) ? "-" : "+"; + else if (op->idx.inc_dec >= -2 && (op->idx.inc_dec <= 2)) { + prePostfix = (char *)s_inc_dec[op->idx.inc_dec + 2]; + } + + SStream_concat(O, prePostfix); + } +} + +static void printOperand(MCInst *MI, SStream *O, m680x_info *info, + cs_m680x_op *op) +{ + switch (op->type) { + case M680X_OP_REGISTER: + printRegName(MI->csh, O, op->reg); + break; + + case M680X_OP_CONSTANT: + SStream_concat(O, "%u", op->const_val); + break; + + case M680X_OP_IMMEDIATE: + if (MI->csh->imm_unsigned) + SStream_concat(O, "#%u", + get_unsigned(op->imm, op->size)); + else + SStream_concat(O, "#%d", op->imm); + + break; + + case M680X_OP_INDEXED: + if (op->idx.flags & M680X_IDX_INDIRECT) + SStream_concat(O, "["); + + if (op->idx.offset_reg != M680X_REG_INVALID) + printRegName(MI->csh, O, op->idx.offset_reg); + else if (op->idx.offset_bits > 0) { + if (op->idx.base_reg == M680X_REG_PC) + SStream_concat(O, "$%04X", op->idx.offset_addr); + else + SStream_concat(O, "%d", op->idx.offset); + } + else if (op->idx.inc_dec != 0 && + info->cpu_type == M680X_CPU_TYPE_CPU12) + SStream_concat(O, "%d", abs(op->idx.inc_dec)); + + if (!(op->idx.flags & M680X_IDX_NO_COMMA)) + SStream_concat(O, ","); + + printIncDec(false, O, info, op); + + printRegName(MI->csh, O, op->idx.base_reg); + + if (op->idx.base_reg == M680X_REG_PC && + (op->idx.offset_bits > 0)) + SStream_concat(O, "R"); + + printIncDec(true, O, info, op); + + if (op->idx.flags & M680X_IDX_INDIRECT) + SStream_concat(O, "]"); + + break; + + case M680X_OP_RELATIVE: + SStream_concat(O, "$%04X", op->rel.address); + break; + + case M680X_OP_DIRECT: + SStream_concat(O, "$%02X", op->direct_addr); + break; + + case M680X_OP_EXTENDED: + if (op->ext.indirect) + SStream_concat(O, "[$%04X]", op->ext.address); + else { + if (op->ext.address < 256) { + SStream_concat(O, ">$%04X", op->ext.address); + } + else { + SStream_concat(O, "$%04X", op->ext.address); + } + } + + break; + + default: + SStream_concat(O, ""); + break; + } +} + +static const char *getDelimiter(m680x_info *info, cs_m680x *m680x) +{ + bool indexed = false; + int count = 0; + int i; + + if (info->insn == M680X_INS_TFM) + return ","; + + if (m680x->op_count > 1) { + for (i = 0; i < m680x->op_count; ++i) { + if (m680x->operands[i].type == M680X_OP_INDEXED) + indexed = true; + + if (m680x->operands[i].type != M680X_OP_REGISTER) + count++; + } + } + + return (indexed && (count >= 1)) ? ";" : ","; +}; + +void M680X_printInst(MCInst *MI, SStream *O, void *PrinterInfo) +{ + m680x_info *info = (m680x_info *)PrinterInfo; + cs_m680x *m680x = &info->m680x; + cs_detail *detail = MI->flat_insn->detail; + int suppress_operands = 0; + const char *delimiter = getDelimiter(info, m680x); + int i; + + if (detail != NULL) + memcpy(&detail->m680x, m680x, sizeof(cs_m680x)); + + if (info->insn == M680X_INS_INVLD || info->insn == M680X_INS_ILLGL) { + if (m680x->op_count) + SStream_concat(O, "FCB $%02X", m680x->operands[0].imm); + else + SStream_concat(O, "FCB $"); + + return; + } + + printInstructionName(MI->csh, O, info->insn); + SStream_concat(O, " "); + + if ((m680x->flags & M680X_FIRST_OP_IN_MNEM) != 0) + suppress_operands++; + + if ((m680x->flags & M680X_SECOND_OP_IN_MNEM) != 0) + suppress_operands++; + + for (i = 0; i < m680x->op_count; ++i) { + if (i >= suppress_operands) { + printOperand(MI, O, info, &m680x->operands[i]); + + if ((i + 1) != m680x->op_count) + SStream_concat(O, delimiter); + } + } +} + +const char *M680X_reg_name(csh handle, unsigned int reg) +{ +#ifndef CAPSTONE_DIET + + if (reg >= M680X_REG_ENDING) + return NULL; + + return s_reg_names[(int)reg]; +#else + return NULL; +#endif +} + +const char *M680X_insn_name(csh handle, unsigned int id) +{ +#ifndef CAPSTONE_DIET + + if (id >= ARR_SIZE(s_instruction_names)) + return NULL; + else + return s_instruction_names[(int)id]; + +#else + return NULL; +#endif +} + +const char *M680X_group_name(csh handle, unsigned int id) +{ +#ifndef CAPSTONE_DIET + return id2name(s_group_names, ARR_SIZE(s_group_names), id); +#else + return NULL; +#endif +} + +cs_err M680X_instprinter_init(cs_struct *ud) +{ +#ifndef CAPSTONE_DIET + + if (M680X_REG_ENDING != ARR_SIZE(s_reg_names)) { + fprintf(stderr, "Internal error: Size mismatch in enum " + "m680x_reg and s_reg_names\n"); + + return CS_ERR_MODE; + } + + if (M680X_INS_ENDING != ARR_SIZE(s_instruction_names)) { + fprintf(stderr, "Internal error: Size mismatch in enum " + "m680x_insn and s_instruction_names\n"); + + return CS_ERR_MODE; + } + + if (M680X_GRP_ENDING != ARR_SIZE(s_group_names)) { + fprintf(stderr, "Internal error: Size mismatch in enum " + "m680x_group_type and s_group_names\n"); + + return CS_ERR_MODE; + } + +#endif + + return CS_ERR_OK; +} + +#endif + diff --git a/arch/M680X/M680XInstPrinter.h b/arch/M680X/M680XInstPrinter.h new file mode 100644 index 0000000000..6fa9f8d59e --- /dev/null +++ b/arch/M680X/M680XInstPrinter.h @@ -0,0 +1,25 @@ +/* Capstone Disassembly Engine */ +/* M680X Backend by Wolfgang Schwotzer 2017 */ + +#ifndef CS_M680XINSTPRINTER_H +#define CS_M680XINSTPRINTER_H + + +#include "capstone/capstone.h" +#include "../../MCRegisterInfo.h" +#include "../../MCInst.h" + +struct SStream; + +void M680X_init(MCRegisterInfo *MRI); + +void M680X_printInst(MCInst *MI, struct SStream *O, void *Info); +const char *M680X_reg_name(csh handle, unsigned int reg); +const char *M680X_insn_name(csh handle, unsigned int id); +const char *M680X_group_name(csh handle, unsigned int id); +void M680X_post_printer(csh handle, cs_insn *flat_insn, char *insn_asm, + MCInst *mci); + +#endif + + diff --git a/arch/M680X/M680XModule.c b/arch/M680X/M680XModule.c new file mode 100644 index 0000000000..b432ff7384 --- /dev/null +++ b/arch/M680X/M680XModule.c @@ -0,0 +1,85 @@ +/* Capstone Disassembly Engine */ +/* M680X Backend by Wolfgang Schwotzer 2017 */ + +#ifdef CAPSTONE_HAS_M680X + +#include "../../utils.h" +#include "../../MCRegisterInfo.h" +#include "M680XDisassembler.h" +#include "M680XDisassemblerInternals.h" +#include "M680XInstPrinter.h" + +static cs_err init(cs_struct *ud) +{ + m680x_info *info; + cs_err errcode; + + /* Do some validation checks */ + errcode = M680X_disassembler_init(ud); + + if (errcode != CS_ERR_OK) + return errcode; + + errcode = M680X_instprinter_init(ud); + + if (errcode != CS_ERR_OK) + return errcode; + + // verify if requested mode is valid + if (ud->mode & ~(CS_MODE_M680X_6800 | CS_MODE_M680X_6801 | + CS_MODE_M680X_6805 | CS_MODE_M680X_6808 | + CS_MODE_M680X_6809 | CS_MODE_M680X_6811 | + CS_MODE_M680X_6301 | CS_MODE_M680X_6309 | + CS_MODE_M680X_CPU12 | CS_MODE_M680X_HCS08)) { + // At least one mode is not supported by M680X + return CS_ERR_MODE; + } + + if (!(ud->mode & (CS_MODE_M680X_6800 | CS_MODE_M680X_6801 | + CS_MODE_M680X_6805 | CS_MODE_M680X_6808 | + CS_MODE_M680X_6809 | CS_MODE_M680X_6811 | + CS_MODE_M680X_6301 | CS_MODE_M680X_6309 | + CS_MODE_M680X_CPU12 | CS_MODE_M680X_HCS08))) { + // At least the cpu type has to be selected. No default. + return CS_ERR_MODE; + } + + info = cs_mem_malloc(sizeof(m680x_info)); + + if (!info) + return CS_ERR_MEM; + + ud->printer = M680X_printInst; + ud->printer_info = info; + ud->getinsn_info = NULL; + ud->disasm = M680X_getInstruction; + ud->reg_name = M680X_reg_name; + ud->insn_id = M680X_get_insn_id; + ud->insn_name = M680X_insn_name; + ud->group_name = M680X_group_name; + ud->skipdata_size = 1; + ud->post_printer = NULL; +#ifndef CAPSTONE_DIET + ud->reg_access = M680X_reg_access; +#endif + + return CS_ERR_OK; +} + +static cs_err option(cs_struct *handle, cs_opt_type type, size_t value) +{ + //TODO + return CS_ERR_OK; +} + +void M680X_enable(void) +{ + arch_init[CS_ARCH_M680X] = init; + arch_option[CS_ARCH_M680X] = option; + + // support this arch + all_arch |= (1 << CS_ARCH_M680X); +} + +#endif + diff --git a/arch/M680X/cpu12.inc b/arch/M680X/cpu12.inc new file mode 100644 index 0000000000..83f2e89e7b --- /dev/null +++ b/arch/M680X/cpu12.inc @@ -0,0 +1,335 @@ + +// CPU12 instructions on PAGE1 +static const inst_page1 g_cpu12_inst_page1_table[256] = { + // 0x0x + { M680X_INS_BGND, inh_hid, inh_hid }, + { M680X_INS_MEM, inh_hid, inh_hid }, + { M680X_INS_INY, inh_hid, inh_hid }, + { M680X_INS_DEY, inh_hid, inh_hid }, + { M680X_INS_DBEQ, loop_hid, inh_hid }, // or DBNE/IBEQ/IBNE/TBEQ/TBNE + { M680X_INS_JMP, idx12_hid, inh_hid }, + { M680X_INS_JMP, ext_hid, inh_hid }, + { M680X_INS_BSR, rel8_hid, inh_hid }, + { M680X_INS_INX, inh_hid, inh_hid }, + { M680X_INS_DEX, inh_hid, inh_hid }, + { M680X_INS_RTC, inh_hid, inh_hid }, + { M680X_INS_RTI, inh_hid, inh_hid }, + { M680X_INS_BSET, idx12_hid, imm8_hid }, + { M680X_INS_BCLR, idx12_hid, imm8_hid }, + { M680X_INS_BRSET, idx12_hid, imm8rel_hid }, + { M680X_INS_BRCLR, idx12_hid, imm8rel_hid }, + // 0x1x + { M680X_INS_ANDCC, imm8_hid, inh_hid }, + { M680X_INS_EDIV, inh_hid, inh_hid }, + { M680X_INS_MUL, inh_hid, inh_hid }, + { M680X_INS_EMUL, inh_hid, inh_hid }, + { M680X_INS_ORCC, imm8_hid, inh_hid }, + { M680X_INS_JSR, idx12_hid, inh_hid }, + { M680X_INS_JSR, ext_hid, inh_hid }, + { M680X_INS_JSR, dir_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_LEAY, idx12_hid, inh_hid }, + { M680X_INS_LEAX, idx12_hid, inh_hid }, + { M680X_INS_LEAS, idx12_hid, inh_hid }, + { M680X_INS_BSET, ext_hid, imm8_hid }, + { M680X_INS_BCLR, ext_hid, imm8_hid }, + { M680X_INS_BRSET, ext_hid, imm8rel_hid }, + { M680X_INS_BRCLR, ext_hid, imm8rel_hid }, + // 0x2x, relative branch instructions + { M680X_INS_BRA, rel8_hid, inh_hid }, + { M680X_INS_BRN, rel8_hid, inh_hid }, + { M680X_INS_BHI, rel8_hid, inh_hid }, + { M680X_INS_BLS, rel8_hid, inh_hid }, + { M680X_INS_BCC, rel8_hid, inh_hid }, + { M680X_INS_BCS, rel8_hid, inh_hid }, + { M680X_INS_BNE, rel8_hid, inh_hid }, + { M680X_INS_BEQ, rel8_hid, inh_hid }, + { M680X_INS_BVC, rel8_hid, inh_hid }, + { M680X_INS_BVS, rel8_hid, inh_hid }, + { M680X_INS_BPL, rel8_hid, inh_hid }, + { M680X_INS_BMI, rel8_hid, inh_hid }, + { M680X_INS_BGE, rel8_hid, inh_hid }, + { M680X_INS_BLT, rel8_hid, inh_hid }, + { M680X_INS_BGT, rel8_hid, inh_hid }, + { M680X_INS_BLE, rel8_hid, inh_hid }, + // 0x3x + { M680X_INS_PULX, inh_hid, inh_hid }, + { M680X_INS_PULY, inh_hid, inh_hid }, + { M680X_INS_PULA, inh_hid, inh_hid }, + { M680X_INS_PULB, inh_hid, inh_hid }, + { M680X_INS_PSHX, inh_hid, inh_hid }, + { M680X_INS_PSHY, inh_hid, inh_hid }, + { M680X_INS_PSHA, inh_hid, inh_hid }, + { M680X_INS_PSHB, inh_hid, inh_hid }, + { M680X_INS_PULC, inh_hid, inh_hid }, + { M680X_INS_PSHC, inh_hid, inh_hid }, + { M680X_INS_PULD, inh_hid, inh_hid }, + { M680X_INS_PSHD, inh_hid, inh_hid }, + { M680X_INS_WAVR, inh_hid, inh_hid }, + { M680X_INS_RTS, inh_hid, inh_hid }, + { M680X_INS_WAI, inh_hid, inh_hid }, + { M680X_INS_SWI, inh_hid, inh_hid }, + // 0x4x + { M680X_INS_NEGA, inh_hid, inh_hid }, + { M680X_INS_COMA, inh_hid, inh_hid }, + { M680X_INS_INCA, inh_hid, inh_hid }, + { M680X_INS_DECA, inh_hid, inh_hid }, + { M680X_INS_LSRA, inh_hid, inh_hid }, + { M680X_INS_ROLA, inh_hid, inh_hid }, + { M680X_INS_RORA, inh_hid, inh_hid }, + { M680X_INS_ASRA, inh_hid, inh_hid }, + { M680X_INS_ASLA, inh_hid, inh_hid }, + { M680X_INS_LSRD, inh_hid, inh_hid }, + { M680X_INS_CALL, ext_hid, index_hid }, + { M680X_INS_CALL, idx12_hid, index_hid }, + { M680X_INS_BSET, dir_hid, imm8_hid }, + { M680X_INS_BCLR, dir_hid, imm8_hid }, + { M680X_INS_BRSET, dir_hid, imm8rel_hid }, + { M680X_INS_BRCLR, dir_hid, imm8rel_hid }, + // 0x5x + { M680X_INS_NEGB, inh_hid, inh_hid }, + { M680X_INS_COMB, inh_hid, inh_hid }, + { M680X_INS_INCB, inh_hid, inh_hid }, + { M680X_INS_DECB, inh_hid, inh_hid }, + { M680X_INS_LSRB, inh_hid, inh_hid }, + { M680X_INS_ROLB, inh_hid, inh_hid }, + { M680X_INS_RORB, inh_hid, inh_hid }, + { M680X_INS_ASRB, inh_hid, inh_hid }, + { M680X_INS_ASLB, inh_hid, inh_hid }, + { M680X_INS_ASLD, inh_hid, inh_hid }, + { M680X_INS_STAA, dir_hid, inh_hid }, + { M680X_INS_STAB, dir_hid, inh_hid }, + { M680X_INS_STD, dir_hid, inh_hid }, + { M680X_INS_STY, dir_hid, inh_hid }, + { M680X_INS_STX, dir_hid, inh_hid }, + { M680X_INS_STS, dir_hid, inh_hid }, + // 0x6x + { M680X_INS_NEG, idx12_hid, inh_hid }, + { M680X_INS_COM, idx12_hid, inh_hid }, + { M680X_INS_INC, idx12_hid, inh_hid }, + { M680X_INS_DEC, idx12_hid, inh_hid }, + { M680X_INS_LSR, idx12_hid, inh_hid }, + { M680X_INS_ROL, idx12_hid, inh_hid }, + { M680X_INS_ROR, idx12_hid, inh_hid }, + { M680X_INS_ASR, idx12_hid, inh_hid }, + { M680X_INS_ASL, idx12_hid, inh_hid }, + { M680X_INS_CLR, idx12_hid, inh_hid }, + { M680X_INS_STAA, idx12_hid, inh_hid }, + { M680X_INS_STAB, idx12_hid, inh_hid }, + { M680X_INS_STD, idx12_hid, inh_hid }, + { M680X_INS_STY, idx12_hid, inh_hid }, + { M680X_INS_STX, idx12_hid, inh_hid }, + { M680X_INS_STS, idx12_hid, inh_hid }, + // 0x7x + { M680X_INS_NEG, ext_hid, inh_hid }, + { M680X_INS_COM, ext_hid, inh_hid }, + { M680X_INS_INC, ext_hid, inh_hid }, + { M680X_INS_DEC, ext_hid, inh_hid }, + { M680X_INS_LSR, ext_hid, inh_hid }, + { M680X_INS_ROL, ext_hid, inh_hid }, + { M680X_INS_ROR, ext_hid, inh_hid }, + { M680X_INS_ASR, ext_hid, inh_hid }, + { M680X_INS_ASL, ext_hid, inh_hid }, + { M680X_INS_CLR, ext_hid, inh_hid }, + { M680X_INS_STAA, ext_hid, inh_hid }, + { M680X_INS_STAB, ext_hid, inh_hid }, + { M680X_INS_STD, ext_hid, inh_hid }, + { M680X_INS_STY, ext_hid, inh_hid }, + { M680X_INS_STX, ext_hid, inh_hid }, + { M680X_INS_STS, ext_hid, inh_hid }, + // 0x8x + { M680X_INS_SUBA, imm8_hid, inh_hid }, + { M680X_INS_CMPA, imm8_hid, inh_hid }, + { M680X_INS_SBCA, imm8_hid, inh_hid }, + { M680X_INS_SUBD, imm16_hid, inh_hid }, + { M680X_INS_ANDA, imm8_hid, inh_hid }, + { M680X_INS_BITA, imm8_hid, inh_hid }, + { M680X_INS_LDAA, imm8_hid, inh_hid }, + { M680X_INS_CLRA, inh_hid, inh_hid }, + { M680X_INS_EORA, imm8_hid, inh_hid }, + { M680X_INS_ADCA, imm8_hid, inh_hid }, + { M680X_INS_ORAA, imm8_hid, inh_hid }, + { M680X_INS_ADDA, imm8_hid, inh_hid }, + { M680X_INS_CPD, imm16_hid, inh_hid }, + { M680X_INS_CPY, imm16_hid, inh_hid }, + { M680X_INS_CPX, imm16_hid, inh_hid }, + { M680X_INS_CPS, imm16_hid, inh_hid }, + // 0x9x + { M680X_INS_SUBA, dir_hid, inh_hid }, + { M680X_INS_CMPA, dir_hid, inh_hid }, + { M680X_INS_SBCA, dir_hid, inh_hid }, + { M680X_INS_SUBD, dir_hid, inh_hid }, + { M680X_INS_ANDA, dir_hid, inh_hid }, + { M680X_INS_BITA, dir_hid, inh_hid }, + { M680X_INS_LDAA, dir_hid, inh_hid }, + { M680X_INS_TSTA, inh_hid, inh_hid }, + { M680X_INS_EORA, dir_hid, inh_hid }, + { M680X_INS_ADCA, dir_hid, inh_hid }, + { M680X_INS_ORAA, dir_hid, inh_hid }, + { M680X_INS_ADDA, dir_hid, inh_hid }, + { M680X_INS_CPD, dir_hid, inh_hid }, + { M680X_INS_CPY, dir_hid, inh_hid }, + { M680X_INS_CPX, dir_hid, inh_hid }, + { M680X_INS_CPS, dir_hid, inh_hid }, + // 0xAx + { M680X_INS_SUBA, idx12_hid, inh_hid }, + { M680X_INS_CMPA, idx12_hid, inh_hid }, + { M680X_INS_SBCA, idx12_hid, inh_hid }, + { M680X_INS_SUBD, idx12_hid, inh_hid }, + { M680X_INS_ANDA, idx12_hid, inh_hid }, + { M680X_INS_BITA, idx12_hid, inh_hid }, + { M680X_INS_LDAA, idx12_hid, inh_hid }, + { M680X_INS_NOP, inh_hid, inh_hid }, + { M680X_INS_EORA, idx12_hid, inh_hid }, + { M680X_INS_ADCA, idx12_hid, inh_hid }, + { M680X_INS_ORAA, idx12_hid, inh_hid }, + { M680X_INS_ADDA, idx12_hid, inh_hid }, + { M680X_INS_CPD, idx12_hid, inh_hid }, + { M680X_INS_CPY, idx12_hid, inh_hid }, + { M680X_INS_CPX, idx12_hid, inh_hid }, + { M680X_INS_CPS, idx12_hid, inh_hid }, + // 0xBx + { M680X_INS_SUBA, ext_hid, inh_hid }, + { M680X_INS_CMPA, ext_hid, inh_hid }, + { M680X_INS_SBCA, ext_hid, inh_hid }, + { M680X_INS_SUBD, ext_hid, inh_hid }, + { M680X_INS_ANDA, ext_hid, inh_hid }, + { M680X_INS_BITA, ext_hid, inh_hid }, + { M680X_INS_LDAA, ext_hid, inh_hid }, + { M680X_INS_TFR, rr12_hid, inh_hid }, // or EXG + { M680X_INS_EORA, ext_hid, inh_hid }, + { M680X_INS_ADCA, ext_hid, inh_hid }, + { M680X_INS_ORAA, ext_hid, inh_hid }, + { M680X_INS_ADDA, ext_hid, inh_hid }, + { M680X_INS_CPD, ext_hid, inh_hid }, + { M680X_INS_CPY, ext_hid, inh_hid }, + { M680X_INS_CPX, ext_hid, inh_hid }, + { M680X_INS_CPS, ext_hid, inh_hid }, + // 0xCx + { M680X_INS_SUBB, imm8_hid, inh_hid }, + { M680X_INS_CMPB, imm8_hid, inh_hid }, + { M680X_INS_SBCB, imm8_hid, inh_hid }, + { M680X_INS_ADDD, imm16_hid, inh_hid }, + { M680X_INS_ANDB, imm8_hid, inh_hid }, + { M680X_INS_BITB, imm8_hid, inh_hid }, + { M680X_INS_LDAB, imm8_hid, inh_hid }, + { M680X_INS_CLRB, inh_hid, inh_hid }, + { M680X_INS_EORB, imm8_hid, inh_hid }, + { M680X_INS_ADCB, imm8_hid, inh_hid }, + { M680X_INS_ORAB, imm8_hid, inh_hid }, + { M680X_INS_ADDB, imm8_hid, inh_hid }, + { M680X_INS_LDD, imm16_hid, inh_hid }, + { M680X_INS_LDY, imm16_hid, inh_hid }, + { M680X_INS_LDX, imm16_hid, inh_hid }, + { M680X_INS_LDS, imm16_hid, inh_hid }, + // 0xDx + { M680X_INS_SUBB, dir_hid, inh_hid }, + { M680X_INS_CMPB, dir_hid, inh_hid }, + { M680X_INS_SBCB, dir_hid, inh_hid }, + { M680X_INS_ADDD, dir_hid, inh_hid }, + { M680X_INS_ANDB, dir_hid, inh_hid }, + { M680X_INS_BITB, dir_hid, inh_hid }, + { M680X_INS_LDAB, dir_hid, inh_hid }, + { M680X_INS_TSTB, inh_hid, inh_hid }, + { M680X_INS_EORB, dir_hid, inh_hid }, + { M680X_INS_ADCB, dir_hid, inh_hid }, + { M680X_INS_ORAB, dir_hid, inh_hid }, + { M680X_INS_ADDB, dir_hid, inh_hid }, + { M680X_INS_LDD, dir_hid, inh_hid }, + { M680X_INS_LDY, dir_hid, inh_hid }, + { M680X_INS_LDX, dir_hid, inh_hid }, + { M680X_INS_LDS, dir_hid, inh_hid }, + // 0xEx + { M680X_INS_SUBB, idx12_hid, inh_hid }, + { M680X_INS_CMPB, idx12_hid, inh_hid }, + { M680X_INS_SBCB, idx12_hid, inh_hid }, + { M680X_INS_ADDD, idx12_hid, inh_hid }, + { M680X_INS_ANDB, idx12_hid, inh_hid }, + { M680X_INS_BITB, idx12_hid, inh_hid }, + { M680X_INS_LDAB, idx12_hid, inh_hid }, + { M680X_INS_TST, idx12_hid, inh_hid }, + { M680X_INS_EORB, idx12_hid, inh_hid }, + { M680X_INS_ADCB, idx12_hid, inh_hid }, + { M680X_INS_ORAB, idx12_hid, inh_hid }, + { M680X_INS_ADDB, idx12_hid, inh_hid }, + { M680X_INS_LDD, idx12_hid, inh_hid }, + { M680X_INS_LDY, idx12_hid, inh_hid }, + { M680X_INS_LDX, idx12_hid, inh_hid }, + { M680X_INS_LDS, idx12_hid, inh_hid }, + // 0xFx + { M680X_INS_SUBA, ext_hid, inh_hid }, + { M680X_INS_CMPA, ext_hid, inh_hid }, + { M680X_INS_SBCA, ext_hid, inh_hid }, + { M680X_INS_ADDD, ext_hid, inh_hid }, + { M680X_INS_ANDA, ext_hid, inh_hid }, + { M680X_INS_BITA, ext_hid, inh_hid }, + { M680X_INS_LDAA, ext_hid, inh_hid }, + { M680X_INS_TST, ext_hid, inh_hid }, + { M680X_INS_EORA, ext_hid, inh_hid }, + { M680X_INS_ADCA, ext_hid, inh_hid }, + { M680X_INS_ORAA, ext_hid, inh_hid }, + { M680X_INS_ADDA, ext_hid, inh_hid }, + { M680X_INS_LDD, ext_hid, inh_hid }, + { M680X_INS_LDY, ext_hid, inh_hid }, + { M680X_INS_LDX, ext_hid, inh_hid }, + { M680X_INS_LDS, ext_hid, inh_hid }, +}; + +// CPU12 instructions on PAGE2 +static const inst_pageX g_cpu12_inst_page2_table[] = { + { 0x00, M680X_INS_MOVW, imm16i12x_hid, inh_hid }, + { 0x01, M680X_INS_MOVW, exti12x_hid, inh_hid }, + { 0x02, M680X_INS_MOVW, idx12_hid, idx12_hid }, + { 0x03, M680X_INS_MOVW, imm16_hid, ext_hid }, + { 0x04, M680X_INS_MOVW, ext_hid, ext_hid }, + { 0x05, M680X_INS_MOVW, idx12_hid, ext_hid }, + { 0x06, M680X_INS_ABA, inh_hid, inh_hid }, + { 0x07, M680X_INS_DAA, inh_hid, inh_hid }, + { 0x08, M680X_INS_MOVB, imm8i12x_hid, inh_hid }, + { 0x09, M680X_INS_MOVB, exti12x_hid, inh_hid }, + { 0x0a, M680X_INS_MOVB, idx12_hid, idx12_hid }, + { 0x0b, M680X_INS_MOVB, imm8_hid, ext_hid }, + { 0x0c, M680X_INS_MOVB, ext_hid, ext_hid }, + { 0x0d, M680X_INS_MOVB, idx12_hid, ext_hid }, + { 0x0e, M680X_INS_TAB, inh_hid, inh_hid }, + { 0x0f, M680X_INS_TBA, inh_hid, inh_hid }, + { 0x10, M680X_INS_IDIV, inh_hid, inh_hid }, + { 0x11, M680X_INS_FDIV, inh_hid, inh_hid }, + { 0x12, M680X_INS_EMACS, ext_hid, inh_hid }, + { 0x13, M680X_INS_EMULS, inh_hid, inh_hid }, + { 0x14, M680X_INS_EDIVS, inh_hid, inh_hid }, + { 0x15, M680X_INS_IDIVS, inh_hid, inh_hid }, + { 0x16, M680X_INS_SBA, inh_hid, inh_hid }, + { 0x17, M680X_INS_CBA, inh_hid, inh_hid }, + { 0x18, M680X_INS_MAXA, idx12_hid, inh_hid }, + { 0x19, M680X_INS_MINA, idx12_hid, inh_hid }, + { 0x1a, M680X_INS_EMAXD, idx12_hid, inh_hid }, + { 0x1b, M680X_INS_EMIND, idx12_hid, inh_hid }, + { 0x1c, M680X_INS_MAXM, idx12_hid, inh_hid }, + { 0x1d, M680X_INS_MINM, idx12_hid, inh_hid }, + { 0x1e, M680X_INS_EMAXM, idx12_hid, inh_hid }, + { 0x1f, M680X_INS_EMINM, idx12_hid, inh_hid }, + { 0x20, M680X_INS_LBRA, rel16_hid, inh_hid }, + { 0x21, M680X_INS_LBRN, rel16_hid, inh_hid }, + { 0x22, M680X_INS_LBHI, rel16_hid, inh_hid }, + { 0x23, M680X_INS_LBLS, rel16_hid, inh_hid }, + { 0x24, M680X_INS_LBCC, rel16_hid, inh_hid }, + { 0x25, M680X_INS_LBCS, rel16_hid, inh_hid }, + { 0x26, M680X_INS_LBNE, rel16_hid, inh_hid }, + { 0x27, M680X_INS_LBEQ, rel16_hid, inh_hid }, + { 0x28, M680X_INS_LBVC, rel16_hid, inh_hid }, + { 0x29, M680X_INS_LBVS, rel16_hid, inh_hid }, + { 0x2a, M680X_INS_LBPL, rel16_hid, inh_hid }, + { 0x2b, M680X_INS_LBMI, rel16_hid, inh_hid }, + { 0x2c, M680X_INS_LBGE, rel16_hid, inh_hid }, + { 0x2d, M680X_INS_LBLT, rel16_hid, inh_hid }, + { 0x2e, M680X_INS_LBGT, rel16_hid, inh_hid }, + { 0x2f, M680X_INS_LBLE, rel16_hid, inh_hid }, + { 0x3a, M680X_INS_REV, inh_hid, inh_hid }, + { 0x3b, M680X_INS_REVW, inh_hid, inh_hid }, + { 0x3c, M680X_INS_WAV, inh_hid, inh_hid }, + { 0x3d, M680X_INS_TBL, idx12s_hid, inh_hid }, + { 0x3e, M680X_INS_STOP, inh_hid, inh_hid }, + { 0x3f, M680X_INS_ETBL, idx12s_hid, inh_hid }, +}; + diff --git a/arch/M680X/hcs08.inc b/arch/M680X/hcs08.inc new file mode 100644 index 0000000000..60f8af6046 --- /dev/null +++ b/arch/M680X/hcs08.inc @@ -0,0 +1,60 @@ + +// Additional instructions only supported on HCS08 +static const inst_pageX g_hcs08_inst_overlay_table[] = { + { 0x32, M680X_INS_LDHX, ext_hid, inh_hid }, + { 0x3e, M680X_INS_CPHX, ext_hid, inh_hid }, + { 0x82, M680X_INS_BGND, inh_hid, inh_hid }, + { 0x96, M680X_INS_STHX, ext_hid, inh_hid }, +}; + +// HCS08 PAGE2 instructions (prefix 0x9E) +static const inst_pageX g_hcs08_inst_page2_table[] = { + { 0x60, M680X_INS_NEG, idxS_hid, inh_hid }, + { 0x61, M680X_INS_CBEQ, idxS_hid,rel8_hid }, + { 0x63, M680X_INS_COM, idxS_hid, inh_hid }, + { 0x64, M680X_INS_LSR, idxS_hid, inh_hid }, + { 0x66, M680X_INS_ROR, idxS_hid, inh_hid }, + { 0x67, M680X_INS_ASR, idxS_hid, inh_hid }, + { 0x68, M680X_INS_LSL, idxS_hid, inh_hid }, + { 0x69, M680X_INS_ROL, idxS_hid, inh_hid }, + { 0x6a, M680X_INS_DEC, idxS_hid, inh_hid }, + { 0x6b, M680X_INS_DBNZ, idxS_hid,rel8_hid }, + { 0x6c, M680X_INS_INC, idxS_hid, inh_hid }, + { 0x6d, M680X_INS_TST, idxS_hid, inh_hid }, + { 0x6f, M680X_INS_CLR, idxS_hid, inh_hid }, + { 0xae, M680X_INS_LDHX, idxX0_hid, inh_hid }, + { 0xbe, M680X_INS_LDHX, idxX16_hid, inh_hid }, + { 0xce, M680X_INS_LDHX, idxX_hid, inh_hid }, + { 0xd0, M680X_INS_SUB, idxS16_hid, inh_hid }, + { 0xd1, M680X_INS_CMP, idxS16_hid, inh_hid }, + { 0xd2, M680X_INS_SBC, idxS16_hid, inh_hid }, + { 0xd3, M680X_INS_CPX, idxS16_hid, inh_hid }, + { 0xd4, M680X_INS_AND, idxS16_hid, inh_hid }, + { 0xd5, M680X_INS_BIT, idxS16_hid, inh_hid }, + { 0xd6, M680X_INS_LDA, idxS16_hid, inh_hid }, + { 0xd7, M680X_INS_STA, idxS16_hid, inh_hid }, + { 0xd8, M680X_INS_EOR, idxS16_hid, inh_hid }, + { 0xd9, M680X_INS_ADC, idxS16_hid, inh_hid }, + { 0xda, M680X_INS_ORA, idxS16_hid, inh_hid }, + { 0xdb, M680X_INS_ADD, idxS16_hid, inh_hid }, + { 0xde, M680X_INS_LDX, idxS16_hid, inh_hid }, + { 0xdf, M680X_INS_STX, idxS16_hid, inh_hid }, + { 0xe0, M680X_INS_SUB, idxS_hid, inh_hid }, + { 0xe1, M680X_INS_CMP, idxS_hid, inh_hid }, + { 0xe2, M680X_INS_SBC, idxS_hid, inh_hid }, + { 0xe3, M680X_INS_CPX, idxS_hid, inh_hid }, + { 0xe4, M680X_INS_AND, idxS_hid, inh_hid }, + { 0xe5, M680X_INS_BIT, idxS_hid, inh_hid }, + { 0xe6, M680X_INS_LDA, idxS_hid, inh_hid }, + { 0xe7, M680X_INS_STA, idxS_hid, inh_hid }, + { 0xe8, M680X_INS_EOR, idxS_hid, inh_hid }, + { 0xe9, M680X_INS_ADC, idxS_hid, inh_hid }, + { 0xea, M680X_INS_ORA, idxS_hid, inh_hid }, + { 0xeb, M680X_INS_ADD, idxS_hid, inh_hid }, + { 0xee, M680X_INS_LDX, idxS_hid, inh_hid }, + { 0xef, M680X_INS_STX, idxS_hid, inh_hid }, + { 0xf3, M680X_INS_CPHX, idxS_hid, inh_hid }, + { 0xfe, M680X_INS_LDHX, idxS_hid, inh_hid }, + { 0xff, M680X_INS_STHX, idxS_hid, inh_hid }, +}; + diff --git a/arch/M680X/hd6301.inc b/arch/M680X/hd6301.inc new file mode 100644 index 0000000000..63493ab049 --- /dev/null +++ b/arch/M680X/hd6301.inc @@ -0,0 +1,15 @@ + +// Additional instructions only supported on HD6301/3 +static const inst_pageX g_hd6301_inst_overlay_table[] = { + { 0x18, M680X_INS_XGDX, inh_hid, inh_hid }, + { 0x1a, M680X_INS_SLP, inh_hid, inh_hid }, + { 0x61, M680X_INS_AIM, imm8_hid, idxX_hid }, + { 0x62, M680X_INS_OIM, imm8_hid, idxX_hid }, + { 0x65, M680X_INS_EIM, imm8_hid, idxX_hid }, + { 0x6B, M680X_INS_TIM, imm8_hid, idxX_hid }, + { 0x71, M680X_INS_AIM, imm8_hid, dir_hid }, + { 0x72, M680X_INS_OIM, imm8_hid, dir_hid }, + { 0x75, M680X_INS_EIM, imm8_hid, dir_hid }, + { 0x7B, M680X_INS_TIM, imm8_hid, dir_hid }, +}; + diff --git a/arch/M680X/hd6309.inc b/arch/M680X/hd6309.inc new file mode 100644 index 0000000000..69c0dec50f --- /dev/null +++ b/arch/M680X/hd6309.inc @@ -0,0 +1,259 @@ + +// The following array has to be sorted by increasing +// opcodes. Otherwise the binary_search will fail. +// +// Additional instructions only supported on HD6309 PAGE1 +static const inst_pageX g_hd6309_inst_overlay_table[] = { + { 0x01, M680X_INS_OIM, imm8_hid, dir_hid }, + { 0x02, M680X_INS_AIM, imm8_hid, dir_hid }, + { 0x05, M680X_INS_EIM, imm8_hid, dir_hid }, + { 0x0B, M680X_INS_TIM, imm8_hid, dir_hid }, + { 0x14, M680X_INS_SEXW, inh_hid, inh_hid }, + { 0x61, M680X_INS_OIM, imm8_hid, idx09_hid }, + { 0x62, M680X_INS_AIM, imm8_hid, idx09_hid }, + { 0x65, M680X_INS_EIM, imm8_hid, idx09_hid }, + { 0x6B, M680X_INS_TIM, imm8_hid, idx09_hid }, + { 0x71, M680X_INS_OIM, imm8_hid, ext_hid }, + { 0x72, M680X_INS_AIM, imm8_hid, ext_hid }, + { 0x75, M680X_INS_EIM, imm8_hid, ext_hid }, + { 0x7B, M680X_INS_TIM, imm8_hid, ext_hid }, + { 0xCD, M680X_INS_LDQ, imm32_hid, inh_hid }, +}; + +// The following array has to be sorted by increasing +// opcodes. Otherwise the binary_search will fail. +// +// HD6309 PAGE2 instructions (with prefix 0x10) +static const inst_pageX g_hd6309_inst_page2_table[] = { + // 0x2x, relative long branch instructions + { 0x21, M680X_INS_LBRN, rel16_hid, inh_hid }, + { 0x22, M680X_INS_LBHI, rel16_hid, inh_hid }, + { 0x23, M680X_INS_LBLS, rel16_hid, inh_hid }, + { 0x24, M680X_INS_LBCC, rel16_hid, inh_hid }, + { 0x25, M680X_INS_LBCS, rel16_hid, inh_hid }, + { 0x26, M680X_INS_LBNE, rel16_hid, inh_hid }, + { 0x27, M680X_INS_LBEQ, rel16_hid, inh_hid }, + { 0x28, M680X_INS_LBVC, rel16_hid, inh_hid }, + { 0x29, M680X_INS_LBVS, rel16_hid, inh_hid }, + { 0x2a, M680X_INS_LBPL, rel16_hid, inh_hid }, + { 0x2b, M680X_INS_LBMI, rel16_hid, inh_hid }, + { 0x2c, M680X_INS_LBGE, rel16_hid, inh_hid }, + { 0x2d, M680X_INS_LBLT, rel16_hid, inh_hid }, + { 0x2e, M680X_INS_LBGT, rel16_hid, inh_hid }, + { 0x2f, M680X_INS_LBLE, rel16_hid, inh_hid }, + // 0x3x + { 0x30, M680X_INS_ADDR, rr09_hid, inh_hid }, + { 0x31, M680X_INS_ADCR, rr09_hid, inh_hid }, + { 0x32, M680X_INS_SUBR, rr09_hid, inh_hid }, + { 0x33, M680X_INS_SBCR, rr09_hid, inh_hid }, + { 0x34, M680X_INS_ANDR, rr09_hid, inh_hid }, + { 0x35, M680X_INS_ORR, rr09_hid, inh_hid }, + { 0x36, M680X_INS_EORR, rr09_hid, inh_hid }, + { 0x37, M680X_INS_CMPR, rr09_hid, inh_hid }, + { 0x38, M680X_INS_PSHSW, inh_hid, inh_hid }, + { 0x39, M680X_INS_PULSW, inh_hid, inh_hid }, + { 0x3a, M680X_INS_PSHUW, inh_hid, inh_hid }, + { 0x3b, M680X_INS_PULUW, inh_hid, inh_hid }, + { 0x3f, M680X_INS_SWI2, inh_hid, inh_hid }, + // 0x4x, Register D instructions + { 0x40, M680X_INS_NEGD, inh_hid, inh_hid }, + { 0x43, M680X_INS_COMD, inh_hid, inh_hid }, + { 0x44, M680X_INS_LSRD, inh_hid, inh_hid }, + { 0x46, M680X_INS_RORD, inh_hid, inh_hid }, + { 0x47, M680X_INS_ASRD, inh_hid, inh_hid }, + { 0x48, M680X_INS_LSLD, inh_hid, inh_hid }, + { 0x49, M680X_INS_ROLD, inh_hid, inh_hid }, + { 0x4a, M680X_INS_DECD, inh_hid, inh_hid }, + { 0x4c, M680X_INS_INCD, inh_hid, inh_hid }, + { 0x4d, M680X_INS_TSTD, inh_hid, inh_hid }, + { 0x4f, M680X_INS_CLRD, inh_hid, inh_hid }, + // 0x5x, Register W instructions + { 0x53, M680X_INS_COMW, inh_hid, inh_hid }, + { 0x54, M680X_INS_LSRW, inh_hid, inh_hid }, + { 0x56, M680X_INS_RORW, inh_hid, inh_hid }, + { 0x59, M680X_INS_ROLW, inh_hid, inh_hid }, + { 0x5a, M680X_INS_DECW, inh_hid, inh_hid }, + { 0x5c, M680X_INS_INCW, inh_hid, inh_hid }, + { 0x5d, M680X_INS_TSTW, inh_hid, inh_hid }, + { 0x5f, M680X_INS_CLRW, inh_hid, inh_hid }, + // 0x8x, immediate instructionY with register D,W,Y + { 0x80, M680X_INS_SUBW, imm16_hid, inh_hid }, + { 0x81, M680X_INS_CMPW, imm16_hid, inh_hid }, + { 0x82, M680X_INS_SBCD, imm16_hid, inh_hid }, + { 0x83, M680X_INS_CMPD, imm16_hid, inh_hid }, + { 0x84, M680X_INS_ANDD, imm16_hid, inh_hid }, + { 0x85, M680X_INS_BITD, imm16_hid, inh_hid }, + { 0x86, M680X_INS_LDW, imm16_hid, inh_hid }, + { 0x88, M680X_INS_EORD, imm16_hid, inh_hid }, + { 0x89, M680X_INS_ADCD, imm16_hid, inh_hid }, + { 0x8a, M680X_INS_ORD, imm16_hid, inh_hid }, + { 0x8b, M680X_INS_ADDW, imm16_hid, inh_hid }, + { 0x8c, M680X_INS_CMPY, imm16_hid, inh_hid }, + { 0x8e, M680X_INS_LDY, imm16_hid, inh_hid }, + // 0x9x, direct instructions with register D,W,Y + { 0x90, M680X_INS_SUBW, dir_hid, inh_hid }, + { 0x91, M680X_INS_CMPW, dir_hid, inh_hid }, + { 0x92, M680X_INS_SBCD, dir_hid, inh_hid }, + { 0x93, M680X_INS_CMPD, dir_hid, inh_hid }, + { 0x94, M680X_INS_ANDD, dir_hid, inh_hid }, + { 0x95, M680X_INS_BITD, dir_hid, inh_hid }, + { 0x96, M680X_INS_LDW, dir_hid, inh_hid }, + { 0x97, M680X_INS_STW, dir_hid, inh_hid }, + { 0x98, M680X_INS_EORD, dir_hid, inh_hid }, + { 0x99, M680X_INS_ADCD, dir_hid, inh_hid }, + { 0x9a, M680X_INS_ORD, dir_hid, inh_hid }, + { 0x9b, M680X_INS_ADDW, dir_hid, inh_hid }, + { 0x9c, M680X_INS_CMPY, dir_hid, inh_hid }, + { 0x9e, M680X_INS_LDY, dir_hid, inh_hid }, + { 0x9f, M680X_INS_STY, dir_hid, inh_hid }, + // 0xAx, indexed instructions with register D,W,Y + { 0xa0, M680X_INS_SUBW, idx09_hid, inh_hid }, + { 0xa1, M680X_INS_CMPW, idx09_hid, inh_hid }, + { 0xa2, M680X_INS_SBCD, idx09_hid, inh_hid }, + { 0xa3, M680X_INS_CMPD, idx09_hid, inh_hid }, + { 0xa4, M680X_INS_ANDD, idx09_hid, inh_hid }, + { 0xa5, M680X_INS_BITD, idx09_hid, inh_hid }, + { 0xa6, M680X_INS_LDW, idx09_hid, inh_hid }, + { 0xa7, M680X_INS_STW, idx09_hid, inh_hid }, + { 0xa8, M680X_INS_EORD, idx09_hid, inh_hid }, + { 0xa9, M680X_INS_ADCD, idx09_hid, inh_hid }, + { 0xaa, M680X_INS_ORD, idx09_hid, inh_hid }, + { 0xab, M680X_INS_ADDW, idx09_hid, inh_hid }, + { 0xac, M680X_INS_CMPY, idx09_hid, inh_hid }, + { 0xae, M680X_INS_LDY, idx09_hid, inh_hid }, + { 0xaf, M680X_INS_STY, idx09_hid, inh_hid }, + // 0xBx, extended instructions with register D,W,Y + { 0xb0, M680X_INS_SUBW, ext_hid, inh_hid }, + { 0xb1, M680X_INS_CMPW, ext_hid, inh_hid }, + { 0xb2, M680X_INS_SBCD, ext_hid, inh_hid }, + { 0xb3, M680X_INS_CMPD, ext_hid, inh_hid }, + { 0xb4, M680X_INS_ANDD, ext_hid, inh_hid }, + { 0xb5, M680X_INS_BITD, ext_hid, inh_hid }, + { 0xb6, M680X_INS_LDW, ext_hid, inh_hid }, + { 0xb7, M680X_INS_STW, ext_hid, inh_hid }, + { 0xb8, M680X_INS_EORD, ext_hid, inh_hid }, + { 0xb9, M680X_INS_ADCD, ext_hid, inh_hid }, + { 0xba, M680X_INS_ORD, ext_hid, inh_hid }, + { 0xbb, M680X_INS_ADDW, ext_hid, inh_hid }, + { 0xbc, M680X_INS_CMPY, ext_hid, inh_hid }, + { 0xbe, M680X_INS_LDY, ext_hid, inh_hid }, + { 0xbf, M680X_INS_STY, ext_hid, inh_hid }, + // 0xCx, immediate instructions with register S + { 0xce, M680X_INS_LDS, imm16_hid, inh_hid }, + // 0xDx, direct instructions with register S,Q + { 0xdc, M680X_INS_LDQ, dir_hid, inh_hid }, + { 0xdd, M680X_INS_STQ, dir_hid, inh_hid }, + { 0xde, M680X_INS_LDS, dir_hid, inh_hid }, + { 0xdf, M680X_INS_STS, dir_hid, inh_hid }, + // 0xEx, indexed instructions with register S,Q + { 0xec, M680X_INS_LDQ, idx09_hid, inh_hid }, + { 0xed, M680X_INS_STQ, idx09_hid, inh_hid }, + { 0xee, M680X_INS_LDS, idx09_hid, inh_hid }, + { 0xef, M680X_INS_STS, idx09_hid, inh_hid }, + // 0xFx, extended instructions with register S,Q + { 0xfc, M680X_INS_LDQ, ext_hid, inh_hid }, + { 0xfd, M680X_INS_STQ, ext_hid, inh_hid }, + { 0xfe, M680X_INS_LDS, ext_hid, inh_hid }, + { 0xff, M680X_INS_STS, ext_hid, inh_hid }, +}; + +// The following array has to be sorted by increasing +// opcodes. Otherwise the binary_search will fail. +// +// HD6309 PAGE3 instructions (with prefix 0x11) +static const inst_pageX g_hd6309_inst_page3_table[] = { + { 0x30, M680X_INS_BAND, bitmv_hid, inh_hid }, + { 0x31, M680X_INS_BIAND, bitmv_hid, inh_hid }, + { 0x32, M680X_INS_BOR, bitmv_hid, inh_hid }, + { 0x33, M680X_INS_BIOR, bitmv_hid, inh_hid }, + { 0x34, M680X_INS_BEOR, bitmv_hid, inh_hid }, + { 0x35, M680X_INS_BIEOR, bitmv_hid, inh_hid }, + { 0x36, M680X_INS_LDBT, bitmv_hid, inh_hid }, + { 0x37, M680X_INS_STBT, bitmv_hid, inh_hid }, + { 0x38, M680X_INS_TFM, tfm_hid, inh_hid }, + { 0x39, M680X_INS_TFM, tfm_hid, inh_hid }, + { 0x3a, M680X_INS_TFM, tfm_hid, inh_hid }, + { 0x3b, M680X_INS_TFM, tfm_hid, inh_hid }, + { 0x3c, M680X_INS_BITMD, imm8_hid, inh_hid }, + { 0x3d, M680X_INS_LDMD, imm8_hid, inh_hid }, + { 0x3f, M680X_INS_SWI3, inh_hid, inh_hid }, + // 0x4x, Register E instructions + { 0x43, M680X_INS_COME, inh_hid, inh_hid }, + { 0x4a, M680X_INS_DECE, inh_hid, inh_hid }, + { 0x4c, M680X_INS_INCE, inh_hid, inh_hid }, + { 0x4d, M680X_INS_TSTE, inh_hid, inh_hid }, + { 0x4f, M680X_INS_CLRE, inh_hid, inh_hid }, + // 0x5x, Register F instructions + { 0x53, M680X_INS_COMF, inh_hid, inh_hid }, + { 0x5a, M680X_INS_DECF, inh_hid, inh_hid }, + { 0x5c, M680X_INS_INCF, inh_hid, inh_hid }, + { 0x5d, M680X_INS_TSTF, inh_hid, inh_hid }, + { 0x5f, M680X_INS_CLRF, inh_hid, inh_hid }, + // 0x8x, immediate instructions with register U,S,E + { 0x80, M680X_INS_SUBE, imm8_hid, inh_hid }, + { 0x81, M680X_INS_CMPE, imm8_hid, inh_hid }, + { 0x83, M680X_INS_CMPU, imm16_hid, inh_hid }, + { 0x86, M680X_INS_LDE, imm8_hid, inh_hid }, + { 0x8b, M680X_INS_ADDE, imm8_hid, inh_hid }, + { 0x8c, M680X_INS_CMPS, imm16_hid, inh_hid }, + { 0x8d, M680X_INS_DIVD, imm8_hid, inh_hid }, + { 0x8e, M680X_INS_DIVQ, imm16_hid, inh_hid }, + { 0x8f, M680X_INS_MULD, imm16_hid, inh_hid }, + // 0x9x, direct instructions with register U,S,E,Q + { 0x90, M680X_INS_SUBE, dir_hid, inh_hid }, + { 0x91, M680X_INS_CMPE, dir_hid, inh_hid }, + { 0x93, M680X_INS_CMPU, dir_hid, inh_hid }, + { 0x96, M680X_INS_LDE, dir_hid, inh_hid }, + { 0x97, M680X_INS_STE, dir_hid, inh_hid }, + { 0x9b, M680X_INS_ADDE, dir_hid, inh_hid }, + { 0x9c, M680X_INS_CMPS, dir_hid, inh_hid }, + { 0x9d, M680X_INS_DIVD, dir_hid, inh_hid }, + { 0x9e, M680X_INS_DIVQ, dir_hid, inh_hid }, + { 0x9f, M680X_INS_MULD, dir_hid, inh_hid }, + // 0xAx, indexed instructions with register U,S,D,Q + { 0xa0, M680X_INS_SUBE, idx09_hid, inh_hid }, + { 0xa1, M680X_INS_CMPE, idx09_hid, inh_hid }, + { 0xa3, M680X_INS_CMPU, idx09_hid, inh_hid }, + { 0xa6, M680X_INS_LDE, idx09_hid, inh_hid }, + { 0xa7, M680X_INS_STE, idx09_hid, inh_hid }, + { 0xab, M680X_INS_ADDE, idx09_hid, inh_hid }, + { 0xac, M680X_INS_CMPS, idx09_hid, inh_hid }, + { 0xad, M680X_INS_DIVD, idx09_hid, inh_hid }, + { 0xae, M680X_INS_DIVQ, idx09_hid, inh_hid }, + { 0xaf, M680X_INS_MULD, idx09_hid, inh_hid }, + // 0xBx, extended instructions with register U,S,D,Q + { 0xb0, M680X_INS_SUBE, ext_hid, inh_hid }, + { 0xb1, M680X_INS_CMPE, ext_hid, inh_hid }, + { 0xb3, M680X_INS_CMPU, ext_hid, inh_hid }, + { 0xb6, M680X_INS_LDE, ext_hid, inh_hid }, + { 0xb7, M680X_INS_STE, ext_hid, inh_hid }, + { 0xbb, M680X_INS_ADDE, ext_hid, inh_hid }, + { 0xbc, M680X_INS_CMPS, ext_hid, inh_hid }, + { 0xbd, M680X_INS_DIVD, ext_hid, inh_hid }, + { 0xbe, M680X_INS_DIVQ, ext_hid, inh_hid }, + { 0xbf, M680X_INS_MULD, ext_hid, inh_hid }, + // 0xCx, immediate instructions with register F + { 0xc0, M680X_INS_SUBF, imm8_hid, inh_hid }, + { 0xc1, M680X_INS_CMPF, imm8_hid, inh_hid }, + { 0xc6, M680X_INS_LDF, imm8_hid, inh_hid }, + { 0xcb, M680X_INS_ADDF, imm8_hid, inh_hid }, + // 0xDx, direct instructions with register F + { 0xd0, M680X_INS_SUBF, dir_hid, inh_hid }, + { 0xd1, M680X_INS_CMPF, dir_hid, inh_hid }, + { 0xd6, M680X_INS_LDF, dir_hid, inh_hid }, + { 0xd7, M680X_INS_STF, dir_hid, inh_hid }, + { 0xdb, M680X_INS_ADDF, dir_hid, inh_hid }, + // 0xEx, indexed instructions with register F + { 0xe0, M680X_INS_SUBF, idx09_hid, inh_hid }, + { 0xe1, M680X_INS_CMPF, idx09_hid, inh_hid }, + { 0xe6, M680X_INS_LDF, idx09_hid, inh_hid }, + { 0xe7, M680X_INS_STF, idx09_hid, inh_hid }, + { 0xeb, M680X_INS_ADDF, idx09_hid, inh_hid }, + // 0xFx, extended instructions with register F + { 0xf0, M680X_INS_SUBF, ext_hid, inh_hid }, + { 0xf1, M680X_INS_CMPF, ext_hid, inh_hid }, + { 0xf6, M680X_INS_LDF, ext_hid, inh_hid }, + { 0xf7, M680X_INS_STF, ext_hid, inh_hid }, + { 0xfb, M680X_INS_ADDF, ext_hid, inh_hid }, +}; + diff --git a/arch/M680X/insn_props.inc b/arch/M680X/insn_props.inc new file mode 100644 index 0000000000..813bffbca4 --- /dev/null +++ b/arch/M680X/insn_props.inc @@ -0,0 +1,367 @@ + +// These temporary defines keep the following table short and handy. +#define NOG M680X_GRP_INVALID +#define NOR M680X_REG_INVALID + +static const insn_props g_insn_props[] = { + { NOG, uuuu, NOR, NOR, false, false }, // INVLD + { NOG, rmmm, M680X_REG_B, M680X_REG_A, true, false }, // ABA + { NOG, rmmm, M680X_REG_B, M680X_REG_X, false, false }, // ABX + { NOG, rmmm, M680X_REG_B, M680X_REG_Y, false, false }, // ABY + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // ADC + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // ADCA + { NOG, mrrr, M680X_REG_B, NOR, true, false }, // ADCB + { NOG, mrrr, M680X_REG_D, NOR, true, false }, // ADCD + { NOG, rmmm, NOR, NOR, true, false }, // ADCR + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // ADD + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // ADDA + { NOG, mrrr, M680X_REG_B, NOR, true, false }, // ADDB + { NOG, mrrr, M680X_REG_D, NOR, true, false }, // ADDD + { NOG, mrrr, M680X_REG_E, NOR, true, false }, // ADDE + { NOG, mrrr, M680X_REG_F, NOR, true, false }, // ADDF + { NOG, rmmm, NOR, NOR, true, false }, // ADDR + { NOG, mrrr, M680X_REG_W, NOR, true, false }, // ADDW + { NOG, rmmm, NOR, NOR, true, false }, // AIM + { NOG, mrrr, M680X_REG_S, NOR, false, false }, // AIS + { NOG, mrrr, M680X_REG_HX, NOR, false, false }, // AIX + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // AND + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // ANDA + { NOG, mrrr, M680X_REG_B, NOR, true, false }, // ANDB + { NOG, mrrr, M680X_REG_CC, NOR, true, false }, // ANDCC + { NOG, mrrr, M680X_REG_D, NOR, true, false }, // ANDD + { NOG, rmmm, NOR, NOR, true, false }, // ANDR + { NOG, mrrr, NOR, NOR, true, false }, // ASL + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // ASLA + { NOG, mrrr, M680X_REG_B, NOR, true, false }, // ASLB + { NOG, mrrr, M680X_REG_D, NOR, true, false }, // ASLD + { NOG, mrrr, NOR, NOR, true, false }, // ASR + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // ASRA + { NOG, mrrr, M680X_REG_B, NOR, true, false }, // ASRB + { NOG, mrrr, M680X_REG_D, NOR, true, false }, // ASRD + { NOG, mrrr, M680X_REG_X, NOR, true, false }, // ASRX + { NOG, mrrr, NOR, NOR, false, false }, // BAND + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // BCC + { NOG, mrrr, NOR, NOR, true, false }, // BCLR + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // BCS + { NOG, mrrr, NOR, NOR, false, false }, // BEOR + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // BEQ + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // BGE + { NOG, uuuu, NOR, NOR, false, false }, // BGND + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // BGT + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // BHCC + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // BHCS + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // BHI + { NOG, mrrr, NOR, NOR, false, false }, // BIAND + { NOG, mrrr, NOR, NOR, false, false }, // BIEOR + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // BIH + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // BIL + { NOG, mrrr, NOR, NOR, false, false }, // BIOR + { NOG, rrrr, M680X_REG_A, NOR, true, false }, // BIT + { NOG, rrrr, M680X_REG_A, NOR, true, false }, // BITA + { NOG, rrrr, M680X_REG_B, NOR, true, false }, // BITB + { NOG, rrrr, M680X_REG_D, NOR, true, false }, // BITD + { NOG, rrrr, M680X_REG_MD, NOR, true, false }, // BITMD + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // BLE + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // BLS + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // BLT + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // BMC + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // BMI + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // BMS + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // BNE + { NOG, mrrr, NOR, NOR, false, false }, // BOR + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // BPL + { M680X_GRP_JUMP, rruu, NOR, NOR, false, false }, // BRCLR + { M680X_GRP_JUMP, rruu, NOR, NOR, false, false }, // BRSET + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // BRA + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // BRN never branches + { NOG, mrrr, NOR, NOR, true, false }, // BSET + { M680X_GRP_CALL, uuuu, NOR, NOR, false, true }, // BSR + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // BVC + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // BVS + { M680X_GRP_CALL, uuuu, NOR, NOR, false, true }, // CALL + { NOG, rrrr, M680X_REG_B, M680X_REG_A, true, false }, // CBA + { M680X_GRP_JUMP, rruu, M680X_REG_A, NOR, false, false }, // CBEQ + { M680X_GRP_JUMP, rruu, M680X_REG_A, NOR, false, false }, // CBEQA + { M680X_GRP_JUMP, rruu, M680X_REG_X, NOR, false, false }, // CBEQX + { NOG, uuuu, NOR, NOR, true, false }, // CLC + { NOG, uuuu, NOR, NOR, true, false }, // CLI + { NOG, wrrr, NOR, NOR, true, false }, // CLR + { NOG, wrrr, M680X_REG_A, NOR, true, false }, // CLRA + { NOG, wrrr, M680X_REG_B, NOR, true, false }, // CLRB + { NOG, wrrr, M680X_REG_D, NOR, true, false }, // CLRD + { NOG, wrrr, M680X_REG_E, NOR, true, false }, // CLRE + { NOG, wrrr, M680X_REG_F, NOR, true, false }, // CLRF + { NOG, wrrr, M680X_REG_H, NOR, true, false }, // CLRH + { NOG, wrrr, M680X_REG_W, NOR, true, false }, // CLRW + { NOG, wrrr, M680X_REG_X, NOR, true, false }, // CLRX + { NOG, uuuu, NOR, NOR, true, false }, // CLV + { NOG, rrrr, M680X_REG_A, NOR, true, false }, // CMP + { NOG, rrrr, M680X_REG_A, NOR, true, false }, // CMPA + { NOG, rrrr, M680X_REG_B, NOR, true, false }, // CMPB + { NOG, rrrr, M680X_REG_D, NOR, true, false }, // CMPD + { NOG, rrrr, M680X_REG_E, NOR, true, false }, // CMPE + { NOG, rrrr, M680X_REG_F, NOR, true, false }, // CMPF + { NOG, rrrr, NOR, NOR, true, false }, // CMPR + { NOG, rrrr, M680X_REG_S, NOR, true, false }, // CMPS + { NOG, rrrr, M680X_REG_U, NOR, true, false }, // CMPU + { NOG, rrrr, M680X_REG_W, NOR, true, false }, // CMPW + { NOG, rrrr, M680X_REG_X, NOR, true, false }, // CMPX + { NOG, rrrr, M680X_REG_Y, NOR, true, false }, // CMPY + { NOG, mrrr, NOR, NOR, true, false }, // COM + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // COMA + { NOG, mrrr, M680X_REG_B, NOR, true, false }, // COMB + { NOG, mrrr, M680X_REG_D, NOR, true, false }, // COMD + { NOG, mrrr, M680X_REG_E, NOR, true, false }, // COME + { NOG, mrrr, M680X_REG_F, NOR, true, false }, // COMF + { NOG, mrrr, M680X_REG_W, NOR, true, false }, // COMW + { NOG, mrrr, M680X_REG_X, NOR, true, false }, // COMX + { NOG, rrrr, M680X_REG_D, NOR, true, false }, // CPD + { NOG, rrrr, M680X_REG_HX, NOR, true, false }, // CPHX + { NOG, rrrr, M680X_REG_S, NOR, true, false }, // CPS + { NOG, rrrr, M680X_REG_X, NOR, true, false }, // CPX + { NOG, rrrr, M680X_REG_Y, NOR, true, false }, // CPY + { NOG, mrrr, NOR, NOR, true, true }, // CWAI + { NOG, mrrr, NOR, NOR, true, true }, // DAA + { M680X_GRP_JUMP, muuu, NOR, NOR, false, false }, // DBEQ + { M680X_GRP_JUMP, muuu, NOR, NOR, false, false }, // DBNE + { M680X_GRP_JUMP, muuu, NOR, NOR, false, false }, // DBNZ + { M680X_GRP_JUMP, muuu, M680X_REG_A, NOR, false, false }, // DBNZA + { M680X_GRP_JUMP, muuu, M680X_REG_X, NOR, false, false }, // DBNZX + { NOG, mrrr, NOR, NOR, true, false }, // DEC + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // DECA + { NOG, mrrr, M680X_REG_B, NOR, true, false }, // DECB + { NOG, mrrr, M680X_REG_D, NOR, true, false }, // DECD + { NOG, mrrr, M680X_REG_E, NOR, true, false }, // DECE + { NOG, mrrr, M680X_REG_F, NOR, true, false }, // DECF + { NOG, mrrr, M680X_REG_W, NOR, true, false }, // DECW + { NOG, mrrr, M680X_REG_X, NOR, true, false }, // DECX + { NOG, mrrr, M680X_REG_S, NOR, false, false }, // DES + { NOG, mrrr, M680X_REG_X, NOR, true, false }, // DEX + { NOG, mrrr, M680X_REG_Y, NOR, true, false }, // DEY + { NOG, mmrr, NOR, NOR, true, true }, // DIV + { NOG, mrrr, M680X_REG_D, NOR, true, false }, // DIVD + { NOG, mrrr, M680X_REG_Q, NOR, true, false }, // DIVQ + { NOG, mmrr, NOR, NOR, true, true }, // EDIV + { NOG, mmrr, NOR, NOR, true, true }, // EDIVS + { NOG, rmmm, NOR, NOR, true, false }, // EIM + { NOG, mrrr, NOR, NOR, true, true }, // EMACS + { NOG, mrrr, M680X_REG_D, NOR, true, false }, // EMAXD + { NOG, mrrr, NOR, NOR, true, true }, // EMAXM + { NOG, mrrr, M680X_REG_D, NOR, true, false }, // EMIND + { NOG, mrrr, NOR, NOR, true, true }, // EMINM + { NOG, mmrr, NOR, NOR, true, true }, // EMUL + { NOG, mmrr, NOR, NOR, true, true }, // EMULS + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // EOR + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // EORA + { NOG, mrrr, M680X_REG_B, NOR, true, false }, // EORB + { NOG, mrrr, M680X_REG_D, NOR, true, false }, // EORD + { NOG, rmmm, NOR, NOR, true, false }, // EORR + { NOG, rmmm, NOR, NOR, true, true }, // ETBL + { NOG, mmmm, NOR, NOR, false, false }, // EXG + { NOG, mmmm, NOR, NOR, true, true }, // FDIV + { M680X_GRP_JUMP, muuu, NOR, NOR, false, false }, // IBEQ + { M680X_GRP_JUMP, muuu, NOR, NOR, false, false }, // IBNE + { NOG, mmmm, NOR, NOR, true, true }, // IDIV + { NOG, mmmm, NOR, NOR, true, true }, // IDIVS + { NOG, uuuu, NOR, NOR, false, false }, // ILLGL + { NOG, mrrr, NOR, NOR, true, false }, // INC + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // INCA + { NOG, mrrr, M680X_REG_B, NOR, true, false }, // INCB + { NOG, mrrr, M680X_REG_D, NOR, true, false }, // INCD + { NOG, mrrr, M680X_REG_E, NOR, true, false }, // INCE + { NOG, mrrr, M680X_REG_F, NOR, true, false }, // INCF + { NOG, mrrr, M680X_REG_W, NOR, true, false }, // INCW + { NOG, mrrr, M680X_REG_X, NOR, true, false }, // INCX + { NOG, mrrr, M680X_REG_S, NOR, false, false }, // INS + { NOG, mrrr, M680X_REG_X, NOR, true, false }, // INX + { NOG, mrrr, M680X_REG_Y, NOR, true, false }, // INY + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // JMP + { M680X_GRP_CALL, uuuu, NOR, NOR, false, true }, // JSR + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // LBCC + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // LBCS + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // LBEQ + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // LBGE + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // LBGT + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // LBHI + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // LBLE + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // LBLS + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // LBLT + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // LBMI + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // LBNE + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // LBPL + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // LBRA + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // LBRN never branches + { M680X_GRP_CALL, uuuu, NOR, NOR, false, true }, // LBSR + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // LBVC + { M680X_GRP_JUMP, uuuu, NOR, NOR, false, false }, // LBVS + { NOG, wrrr, M680X_REG_A, NOR, true, false }, // LDA + { NOG, wrrr, M680X_REG_A, NOR, true, false }, // LDAA + { NOG, wrrr, M680X_REG_B, NOR, true, false }, // LDAB + { NOG, wrrr, M680X_REG_B, NOR, true, false }, // LDB + { NOG, mrrr, NOR, NOR, false, false }, // LDBT + { NOG, wrrr, M680X_REG_D, NOR, true, false }, // LDD + { NOG, wrrr, M680X_REG_E, NOR, true, false }, // LDE + { NOG, wrrr, M680X_REG_F, NOR, true, false }, // LDF + { NOG, wrrr, M680X_REG_HX, NOR, true, false }, // LDHX + { NOG, mrrr, M680X_REG_MD, NOR, false, false }, // LDMD + { NOG, wrrr, M680X_REG_Q, NOR, true, false }, // LDQ + { NOG, wrrr, M680X_REG_S, NOR, true, false }, // LDS + { NOG, wrrr, M680X_REG_U, NOR, true, false }, // LDU + { NOG, wrrr, M680X_REG_W, NOR, true, false }, // LDW + { NOG, wrrr, M680X_REG_X, NOR, true, false }, // LDX + { NOG, wrrr, M680X_REG_Y, NOR, true, false }, // LDY + { NOG, wrrr, M680X_REG_S, NOR, false, false }, // LEAS + { NOG, wrrr, M680X_REG_U, NOR, false, false }, // LEAU + { NOG, wrrr, M680X_REG_X, NOR, false, false }, // LEAX + { NOG, wrrr, M680X_REG_Y, NOR, false, false }, // LEAY + { NOG, mrrr, NOR, NOR, true, false }, // LSL + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // LSLA + { NOG, mrrr, M680X_REG_B, NOR, true, false }, // LSLB + { NOG, mrrr, M680X_REG_D, NOR, true, false }, // LSLD + { NOG, mrrr, M680X_REG_X, NOR, true, false }, // LSLX + { NOG, mrrr, NOR, NOR, true, false }, // LSR + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // LSRA + { NOG, mrrr, M680X_REG_B, NOR, true, false }, // LSRB + { NOG, mrrr, M680X_REG_D, NOR, true, false }, // LSRD + { NOG, mrrr, M680X_REG_W, NOR, true, false }, // LSRW + { NOG, mrrr, M680X_REG_X, NOR, true, false }, // LSRX + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // MAXA + { NOG, mrrr, NOR, NOR, true, true }, // MAXM + { NOG, mmrr, NOR, NOR, true, true }, // MEM + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // MINA + { NOG, mrrr, NOR, NOR, true, true }, // MINM + { NOG, rwww, NOR, NOR, true, false }, // MOV + { NOG, rwww, NOR, NOR, false, false }, // MOVB + { NOG, rwww, NOR, NOR, false, false }, // MOVW + { NOG, mmmm, NOR, NOR, true, true }, // MUL + { NOG, mwrr, M680X_REG_D, NOR, true, true }, // MULD + { NOG, mrrr, NOR, NOR, true, false }, // NEG + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // NEGA + { NOG, mrrr, M680X_REG_B, NOR, true, false }, // NEGB + { NOG, mrrr, M680X_REG_D, NOR, true, false }, // NEGD + { NOG, mrrr, M680X_REG_X, NOR, true, false }, // NEGX + { NOG, uuuu, NOR, NOR, false, false }, // NOP + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // NSA + { NOG, rmmm, NOR, NOR, true, false }, // OIM + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // ORA + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // ORAA + { NOG, mrrr, M680X_REG_B, NOR, true, false }, // ORAB + { NOG, mrrr, M680X_REG_B, NOR, true, false }, // ORB + { NOG, mrrr, M680X_REG_CC, NOR, true, false }, // ORCC + { NOG, mrrr, M680X_REG_D, NOR, true, false }, // ORD + { NOG, rmmm, NOR, NOR, true, false }, // ORR + { NOG, rmmm, M680X_REG_A, NOR, false, true }, // PSHA + { NOG, rmmm, M680X_REG_B, NOR, false, true }, // PSHB + { NOG, rmmm, M680X_REG_CC, NOR, false, true }, // PSHC + { NOG, rmmm, M680X_REG_D, NOR, false, true }, // PSHD + { NOG, rmmm, M680X_REG_H, NOR, false, true }, // PSHH + { NOG, mrrr, M680X_REG_S, NOR, false, false }, // PSHS + { NOG, mrrr, M680X_REG_S, M680X_REG_W, false, false }, // PSHSW + { NOG, mrrr, M680X_REG_U, NOR, false, false }, // PSHU + { NOG, mrrr, M680X_REG_U, M680X_REG_W, false, false }, // PSHUW + { NOG, rmmm, M680X_REG_X, NOR, false, true }, // PSHX + { NOG, rmmm, M680X_REG_Y, NOR, false, true }, // PSHY + { NOG, wmmm, M680X_REG_A, NOR, false, true }, // PULA + { NOG, wmmm, M680X_REG_B, NOR, false, true }, // PULB + { NOG, wmmm, M680X_REG_CC, NOR, false, true }, // PULC + { NOG, wmmm, M680X_REG_D, NOR, false, true }, // PULD + { NOG, wmmm, M680X_REG_H, NOR, false, true }, // PULH + { NOG, mwww, M680X_REG_S, NOR, false, false }, // PULS + { NOG, mwww, M680X_REG_S, M680X_REG_W, false, false }, // PULSW + { NOG, mwww, M680X_REG_U, NOR, false, false }, // PULU + { NOG, mwww, M680X_REG_U, M680X_REG_W, false, false }, // PULUW + { NOG, wmmm, M680X_REG_X, NOR, false, true }, // PULX + { NOG, wmmm, M680X_REG_Y, NOR, false, true }, // PULY + { NOG, mmrr, NOR, NOR, true, true }, // REV + { NOG, mmmm, NOR, NOR, true, true }, // REVW + { NOG, mrrr, NOR, NOR, true, false }, // ROL + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // ROLA + { NOG, mrrr, M680X_REG_B, NOR, true, false }, // ROLB + { NOG, mrrr, M680X_REG_D, NOR, true, false }, // ROLD + { NOG, mrrr, M680X_REG_W, NOR, true, false }, // ROLW + { NOG, mrrr, M680X_REG_X, NOR, true, false }, // ROLX + { NOG, mrrr, NOR, NOR, true, false }, // ROR + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // RORA + { NOG, mrrr, M680X_REG_B, NOR, true, false }, // RORB + { NOG, mrrr, M680X_REG_D, NOR, true, false }, // RORD + { NOG, mrrr, M680X_REG_W, NOR, true, false }, // RORW + { NOG, mrrr, M680X_REG_X, NOR, true, false }, // RORX + { NOG, wrrr, M680X_REG_S, NOR, false, false }, // RSP + { M680X_GRP_RET, mwww, NOR, NOR, false, true }, // RTC + { M680X_GRP_IRET, mwww, NOR, NOR, false, true }, // RTI + { M680X_GRP_RET, mwww, NOR, NOR, false, true }, // RTS + { NOG, rmmm, M680X_REG_B, M680X_REG_A, true, false }, // SBA + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // SBC + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // SBCA + { NOG, mrrr, M680X_REG_B, NOR, true, false }, // SBCB + { NOG, mrrr, M680X_REG_D, NOR, true, false }, // SBCD + { NOG, rmmm, NOR, NOR, true, false }, // SBCR + { NOG, uuuu, NOR, NOR, true, false }, // SEC + { NOG, uuuu, NOR, NOR, true, false }, // SEI + { NOG, uuuu, NOR, NOR, true, false }, // SEV + { NOG, wrrr, NOR, NOR, true, true }, // SEX + { NOG, rwww, M680X_REG_W, NOR, true, true }, // SEXW + { NOG, uuuu, NOR, NOR, false, false }, // SLP + { NOG, rwww, M680X_REG_A, NOR, true, false }, // STA + { NOG, rwww, M680X_REG_A, NOR, true, false }, // STAA + { NOG, rwww, M680X_REG_B, NOR, true, false }, // STAB + { NOG, rwww, M680X_REG_B, NOR, true, false }, // STB + { NOG, rrrm, NOR, NOR, false, false }, // STBT + { NOG, rwww, M680X_REG_D, NOR, true, false }, // STD + { NOG, rwww, M680X_REG_E, NOR, true, false }, // STE + { NOG, rwww, M680X_REG_F, NOR, true, false }, // STF + { NOG, uuuu, NOR, NOR, false, false }, // STOP + { NOG, rwww, M680X_REG_HX, NOR, true, false }, // STHX + { NOG, rwww, M680X_REG_Q, NOR, true, false }, // STQ + { NOG, rwww, M680X_REG_S, NOR, true, false }, // STS + { NOG, rwww, M680X_REG_U, NOR, true, false }, // STU + { NOG, rwww, M680X_REG_W, NOR, true, false }, // STW + { NOG, rwww, M680X_REG_X, NOR, true, false }, // STX + { NOG, rwww, M680X_REG_Y, NOR, true, false }, // STY + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // SUB + { NOG, mrrr, M680X_REG_A, NOR, true, false }, // SUBA + { NOG, mrrr, M680X_REG_B, NOR, true, false }, // SUBB + { NOG, mrrr, M680X_REG_D, NOR, true, false }, // SUBD + { NOG, mrrr, M680X_REG_E, NOR, true, false }, // SUBE + { NOG, mrrr, M680X_REG_F, NOR, true, false }, // SUBF + { NOG, rmmm, NOR, NOR, true, false }, // SUBR + { NOG, mrrr, M680X_REG_W, NOR, true, false }, // SUBW + { M680X_GRP_INT, mmrr, NOR, NOR, true, true }, // SWI + { M680X_GRP_INT, mmrr, NOR, NOR, true, true }, // SWI2 + { M680X_GRP_INT, mmrr, NOR, NOR, true, true }, // SWI3 + { NOG, uuuu, NOR, NOR, false, false }, // SYNC + { NOG, rwww, M680X_REG_A, M680X_REG_B, true, false }, // TAB + { NOG, rwww, M680X_REG_A, M680X_REG_CC, false, false }, // TAP + { NOG, rwww, M680X_REG_A, M680X_REG_X, false, false }, // TAX + { NOG, rwww, M680X_REG_B, M680X_REG_A, true, false }, // TBA + { M680X_GRP_JUMP, muuu, NOR, NOR, false, false }, // TBEQ + { NOG, rmmm, NOR, NOR, true, true }, // TBL + { M680X_GRP_JUMP, muuu, NOR, NOR, false, false }, // TBNE + { NOG, uuuu, NOR, NOR, false, false }, // TEST + { NOG, rwww, NOR, NOR, false, false }, // TFM + { NOG, rwww, NOR, NOR, false, false }, // TFR + { NOG, rrrr, NOR, NOR, true, false }, // TIM + { NOG, rwww, M680X_REG_CC, M680X_REG_A, false, false }, // TPA + { NOG, rrrr, NOR, NOR, true, false }, // TST + { NOG, rrrr, M680X_REG_A, NOR, true, false }, // TSTA + { NOG, rrrr, M680X_REG_B, NOR, true, false }, // TSTB + { NOG, rrrr, M680X_REG_D, NOR, true, false }, // TSTD + { NOG, rrrr, M680X_REG_E, NOR, true, false }, // TSTE + { NOG, rrrr, M680X_REG_F, NOR, true, false }, // TSTF + { NOG, rrrr, M680X_REG_W, NOR, true, false }, // TSTW + { NOG, rrrr, M680X_REG_X, NOR, true, false }, // TSTX + { NOG, rwww, M680X_REG_S, M680X_REG_HX, false, false }, // TSX + { NOG, rwww, M680X_REG_S, M680X_REG_Y, false, false }, // TSY + { NOG, rwww, M680X_REG_X, M680X_REG_A, false, false }, // TXA + { NOG, rwww, M680X_REG_HX, M680X_REG_S, false, false }, // TXS + { NOG, rwww, M680X_REG_Y, M680X_REG_S, false, false }, // TYS + { NOG, mrrr, NOR, NOR, true, true }, // WAI + { NOG, uuuu, NOR, NOR, true, false }, // WAIT + { NOG, uuuu, NOR, NOR, true, true }, // WAV + { NOG, uuuu, NOR, NOR, true, true }, // WAVR + { NOG, mmmm, M680X_REG_D, M680X_REG_X, false, false }, // XGDX + { NOG, mmmm, M680X_REG_D, M680X_REG_Y, false, false }, // XGDY +}; +#undef NOR +#undef NOG + diff --git a/arch/M680X/m6800.inc b/arch/M680X/m6800.inc new file mode 100644 index 0000000000..b100aa3db4 --- /dev/null +++ b/arch/M680X/m6800.inc @@ -0,0 +1,277 @@ + +// M6800/2 instructions +static const inst_page1 g_m6800_inst_page1_table[256] = { + // 0x0x, inherent instructions + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_NOP, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_TAP, inh_hid, inh_hid }, + { M680X_INS_TPA, inh_hid, inh_hid }, + { M680X_INS_INX, inh_hid, inh_hid }, + { M680X_INS_DEX, inh_hid, inh_hid }, + { M680X_INS_CLV, inh_hid, inh_hid }, + { M680X_INS_SEV, inh_hid, inh_hid }, + { M680X_INS_CLC, inh_hid, inh_hid }, + { M680X_INS_SEC, inh_hid, inh_hid }, + { M680X_INS_CLI, inh_hid, inh_hid }, + { M680X_INS_SEI, inh_hid, inh_hid }, + // 0x1x, inherent instructions + { M680X_INS_SBA, inh_hid, inh_hid }, + { M680X_INS_CBA, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_TAB, inh_hid, inh_hid }, + { M680X_INS_TBA, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_DAA, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ABA, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + // 0x2x, relative branch instructions + { M680X_INS_BRA, rel8_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_BHI, rel8_hid, inh_hid }, + { M680X_INS_BLS, rel8_hid, inh_hid }, + { M680X_INS_BCC, rel8_hid, inh_hid }, + { M680X_INS_BCS, rel8_hid, inh_hid }, + { M680X_INS_BNE, rel8_hid, inh_hid }, + { M680X_INS_BEQ, rel8_hid, inh_hid }, + { M680X_INS_BVC, rel8_hid, inh_hid }, + { M680X_INS_BVS, rel8_hid, inh_hid }, + { M680X_INS_BPL, rel8_hid, inh_hid }, + { M680X_INS_BMI, rel8_hid, inh_hid }, + { M680X_INS_BGE, rel8_hid, inh_hid }, + { M680X_INS_BLT, rel8_hid, inh_hid }, + { M680X_INS_BGT, rel8_hid, inh_hid }, + { M680X_INS_BLE, rel8_hid, inh_hid }, + // 0x3x, inherent instructions + { M680X_INS_TSX, inh_hid, inh_hid }, + { M680X_INS_INS, inh_hid, inh_hid }, + { M680X_INS_PULA, inh_hid, inh_hid }, + { M680X_INS_PULB, inh_hid, inh_hid }, + { M680X_INS_DES, inh_hid, inh_hid }, + { M680X_INS_TXS, inh_hid, inh_hid }, + { M680X_INS_PSHA, inh_hid, inh_hid }, + { M680X_INS_PSHB, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_RTS, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_RTI, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_WAI, inh_hid, inh_hid }, + { M680X_INS_SWI, inh_hid, inh_hid }, + // 0x4x, Register A instructions + { M680X_INS_NEGA, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_COMA, inh_hid, inh_hid }, + { M680X_INS_LSRA, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_RORA, inh_hid, inh_hid }, + { M680X_INS_ASRA, inh_hid, inh_hid }, + { M680X_INS_ASLA, inh_hid, inh_hid }, + { M680X_INS_ROLA, inh_hid, inh_hid }, + { M680X_INS_DECA, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_INCA, inh_hid, inh_hid }, + { M680X_INS_TSTA, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_CLRA, inh_hid, inh_hid }, + // 0x5x, Register B instructions + { M680X_INS_NEGB, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_COMB, inh_hid, inh_hid }, + { M680X_INS_LSRB, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_RORB, inh_hid, inh_hid }, + { M680X_INS_ASRB, inh_hid, inh_hid }, + { M680X_INS_ASLB, inh_hid, inh_hid }, + { M680X_INS_ROLB, inh_hid, inh_hid }, + { M680X_INS_DECB, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_INCB, inh_hid, inh_hid }, + { M680X_INS_TSTB, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_CLRB, inh_hid, inh_hid }, + // 0x6x, indexed instructions + { M680X_INS_NEG, idxX_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_COM, idxX_hid, inh_hid }, + { M680X_INS_LSR, idxX_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ROR, idxX_hid, inh_hid }, + { M680X_INS_ASR, idxX_hid, inh_hid }, + { M680X_INS_ASL, idxX_hid, inh_hid }, + { M680X_INS_ROL, idxX_hid, inh_hid }, + { M680X_INS_DEC, idxX_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_INC, idxX_hid, inh_hid }, + { M680X_INS_TST, idxX_hid, inh_hid }, + { M680X_INS_JMP, idxX_hid, inh_hid }, + { M680X_INS_CLR, idxX_hid, inh_hid }, + // 0x7x, extended instructions + { M680X_INS_NEG, ext_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_COM, ext_hid, inh_hid }, + { M680X_INS_LSR, ext_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ROR, ext_hid, inh_hid }, + { M680X_INS_ASR, ext_hid, inh_hid }, + { M680X_INS_ASL, ext_hid, inh_hid }, + { M680X_INS_ROL, ext_hid, inh_hid }, + { M680X_INS_DEC, ext_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_INC, ext_hid, inh_hid }, + { M680X_INS_TST, ext_hid, inh_hid }, + { M680X_INS_JMP, ext_hid, inh_hid }, + { M680X_INS_CLR, ext_hid, inh_hid }, + // 0x8x, immediate instructions with Register A,X,S + { M680X_INS_SUBA, imm8_hid, inh_hid }, + { M680X_INS_CMPA, imm8_hid, inh_hid }, + { M680X_INS_SBCA, imm8_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ANDA, imm8_hid, inh_hid }, + { M680X_INS_BITA, imm8_hid, inh_hid }, + { M680X_INS_LDAA, imm8_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_EORA, imm8_hid, inh_hid }, + { M680X_INS_ADCA, imm8_hid, inh_hid }, + { M680X_INS_ORAA, imm8_hid, inh_hid }, + { M680X_INS_ADDA, imm8_hid, inh_hid }, + { M680X_INS_CPX, imm16_hid, inh_hid }, + { M680X_INS_BSR, rel8_hid, inh_hid }, + { M680X_INS_LDS, imm16_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + // 0x9x, direct instructions with register A,X,S + { M680X_INS_SUBA, dir_hid, inh_hid }, + { M680X_INS_CMPA, dir_hid, inh_hid }, + { M680X_INS_SBCA, dir_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ANDA, dir_hid, inh_hid }, + { M680X_INS_BITA, dir_hid, inh_hid }, + { M680X_INS_LDAA, dir_hid, inh_hid }, + { M680X_INS_STAA, dir_hid, inh_hid }, + { M680X_INS_EORA, dir_hid, inh_hid }, + { M680X_INS_ADCA, dir_hid, inh_hid }, + { M680X_INS_ORAA, dir_hid, inh_hid }, + { M680X_INS_ADDA, dir_hid, inh_hid }, + { M680X_INS_CPX, dir_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_LDS, dir_hid, inh_hid }, + { M680X_INS_STS, dir_hid, inh_hid }, + // 0xAx, indexed instructions with Register A,X + { M680X_INS_SUBA, idxX_hid, inh_hid }, + { M680X_INS_CMPA, idxX_hid, inh_hid }, + { M680X_INS_SBCA, idxX_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ANDA, idxX_hid, inh_hid }, + { M680X_INS_BITA, idxX_hid, inh_hid }, + { M680X_INS_LDAA, idxX_hid, inh_hid }, + { M680X_INS_STAA, idxX_hid, inh_hid }, + { M680X_INS_EORA, idxX_hid, inh_hid }, + { M680X_INS_ADCA, idxX_hid, inh_hid }, + { M680X_INS_ORAA, idxX_hid, inh_hid }, + { M680X_INS_ADDA, idxX_hid, inh_hid }, + { M680X_INS_CPX, idxX_hid, inh_hid }, + { M680X_INS_JSR, idxX_hid, inh_hid }, + { M680X_INS_LDS, idxX_hid, inh_hid }, + { M680X_INS_STS, idxX_hid, inh_hid }, + // 0xBx, extended instructions with register A,X,S + { M680X_INS_SUBA, ext_hid, inh_hid }, + { M680X_INS_CMPA, ext_hid, inh_hid }, + { M680X_INS_SBCA, ext_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ANDA, ext_hid, inh_hid }, + { M680X_INS_BITA, ext_hid, inh_hid }, + { M680X_INS_LDAA, ext_hid, inh_hid }, + { M680X_INS_STAA, ext_hid, inh_hid }, + { M680X_INS_EORA, ext_hid, inh_hid }, + { M680X_INS_ADCA, ext_hid, inh_hid }, + { M680X_INS_ORAA, ext_hid, inh_hid }, + { M680X_INS_ADDA, ext_hid, inh_hid }, + { M680X_INS_CPX, ext_hid, inh_hid }, + { M680X_INS_JSR, ext_hid, inh_hid }, + { M680X_INS_LDS, ext_hid, inh_hid }, + { M680X_INS_STS, ext_hid, inh_hid }, + // 0xCx, immediate instructions with register B,X + { M680X_INS_SUBB, imm8_hid, inh_hid }, + { M680X_INS_CMPB, imm8_hid, inh_hid }, + { M680X_INS_SBCB, imm8_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ANDB, imm8_hid, inh_hid }, + { M680X_INS_BITB, imm8_hid, inh_hid }, + { M680X_INS_LDAB, imm8_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_EORB, imm8_hid, inh_hid }, + { M680X_INS_ADCB, imm8_hid, inh_hid }, + { M680X_INS_ORAB, imm8_hid, inh_hid }, + { M680X_INS_ADDB, imm8_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_LDX, imm16_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + // 0xDx direct instructions with register B,X + { M680X_INS_SUBB, dir_hid, inh_hid }, + { M680X_INS_CMPB, dir_hid, inh_hid }, + { M680X_INS_SBCB, dir_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ANDB, dir_hid, inh_hid }, + { M680X_INS_BITB, dir_hid, inh_hid }, + { M680X_INS_LDAB, dir_hid, inh_hid }, + { M680X_INS_STAB, dir_hid, inh_hid }, + { M680X_INS_EORB, dir_hid, inh_hid }, + { M680X_INS_ADCB, dir_hid, inh_hid }, + { M680X_INS_ORAB, dir_hid, inh_hid }, + { M680X_INS_ADDB, dir_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_LDX, dir_hid, inh_hid }, + { M680X_INS_STX, dir_hid, inh_hid }, + // 0xEx, indexed instruction with register B,X + { M680X_INS_SUBB, idxX_hid, inh_hid }, + { M680X_INS_CMPB, idxX_hid, inh_hid }, + { M680X_INS_SBCB, idxX_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ANDB, idxX_hid, inh_hid }, + { M680X_INS_BITB, idxX_hid, inh_hid }, + { M680X_INS_LDAB, idxX_hid, inh_hid }, + { M680X_INS_STAB, idxX_hid, inh_hid }, + { M680X_INS_EORB, idxX_hid, inh_hid }, + { M680X_INS_ADCB, idxX_hid, inh_hid }, + { M680X_INS_ORAB, idxX_hid, inh_hid }, + { M680X_INS_ADDB, idxX_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_LDX, idxX_hid, inh_hid }, + { M680X_INS_STX, idxX_hid, inh_hid }, + // 0xFx, extended instructions with register B,U + { M680X_INS_SUBB, ext_hid, inh_hid }, + { M680X_INS_CMPB, ext_hid, inh_hid }, + { M680X_INS_SBCB, ext_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ANDB, ext_hid, inh_hid }, + { M680X_INS_BITB, ext_hid, inh_hid }, + { M680X_INS_LDAB, ext_hid, inh_hid }, + { M680X_INS_STAB, ext_hid, inh_hid }, + { M680X_INS_EORB, ext_hid, inh_hid }, + { M680X_INS_ADCB, ext_hid, inh_hid }, + { M680X_INS_ORAB, ext_hid, inh_hid }, + { M680X_INS_ADDB, ext_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_LDX, ext_hid, inh_hid }, + { M680X_INS_STX, ext_hid, inh_hid }, +}; + diff --git a/arch/M680X/m6801.inc b/arch/M680X/m6801.inc new file mode 100644 index 0000000000..0fe4592cab --- /dev/null +++ b/arch/M680X/m6801.inc @@ -0,0 +1,39 @@ + +// Additional instructions only supported on M6801/3 +static const inst_pageX g_m6801_inst_overlay_table[] = { + // 0x0x, inherent instructions + { 0x04, M680X_INS_LSRD, inh_hid, inh_hid }, + { 0x05, M680X_INS_ASLD, inh_hid, inh_hid }, + // 0x2x, relative branch instructions + { 0x21, M680X_INS_BRN, rel8_hid, inh_hid }, + // 0x3x, inherent instructions + { 0x38, M680X_INS_PULX, inh_hid, inh_hid }, + { 0x3A, M680X_INS_ABX, inh_hid, inh_hid }, + { 0x3C, M680X_INS_PSHX, inh_hid, inh_hid }, + { 0x3D, M680X_INS_MUL, inh_hid, inh_hid }, + // 0x8x, immediate instructions with Register D + { 0x83, M680X_INS_SUBD, imm16_hid, inh_hid }, + // 0x9x, direct instructions with register D + { 0x93, M680X_INS_SUBD, dir_hid, inh_hid }, + { 0x9D, M680X_INS_JSR, dir_hid, inh_hid }, + // 0xAx, indexed instructions with Register D + { 0xA3, M680X_INS_SUBD, idxX_hid, inh_hid }, + // 0xBx, extended instructions with register D + { 0xB3, M680X_INS_SUBD, ext_hid, inh_hid }, + // 0xCx, immediate instructions with register D + { 0xC3, M680X_INS_ADDD, imm16_hid, inh_hid }, + { 0xCC, M680X_INS_LDD, imm16_hid, inh_hid }, + // 0xDx direct instructions with register D + { 0xD3, M680X_INS_ADDD, dir_hid, inh_hid }, + { 0xDC, M680X_INS_LDD, dir_hid, inh_hid }, + { 0xDD, M680X_INS_STD, dir_hid, inh_hid }, + // 0xEx, indexed instruction with register D + { 0xE3, M680X_INS_ADDD, idxX_hid, inh_hid }, + { 0xEC, M680X_INS_LDD, idxX_hid, inh_hid }, + { 0xED, M680X_INS_STD, idxX_hid, inh_hid }, + // 0xFx, extended instructions with register D + { 0xF3, M680X_INS_ADDD, ext_hid, inh_hid }, + { 0xFC, M680X_INS_LDD, ext_hid, inh_hid }, + { 0xFD, M680X_INS_STD, ext_hid, inh_hid }, +}; + diff --git a/arch/M680X/m6805.inc b/arch/M680X/m6805.inc new file mode 100644 index 0000000000..080c1406c6 --- /dev/null +++ b/arch/M680X/m6805.inc @@ -0,0 +1,277 @@ + +// M68HC05 instructions +static const inst_page1 g_m6805_inst_page1_table[256] = { + // 0x0x, bit manipulation instructions + { M680X_INS_BRSET, opidxdr_hid, inh_hid }, + { M680X_INS_BRCLR, opidxdr_hid, inh_hid }, + { M680X_INS_BRSET, opidxdr_hid, inh_hid }, + { M680X_INS_BRCLR, opidxdr_hid, inh_hid }, + { M680X_INS_BRSET, opidxdr_hid, inh_hid }, + { M680X_INS_BRCLR, opidxdr_hid, inh_hid }, + { M680X_INS_BRSET, opidxdr_hid, inh_hid }, + { M680X_INS_BRCLR, opidxdr_hid, inh_hid }, + { M680X_INS_BRSET, opidxdr_hid, inh_hid }, + { M680X_INS_BRCLR, opidxdr_hid, inh_hid }, + { M680X_INS_BRSET, opidxdr_hid, inh_hid }, + { M680X_INS_BRCLR, opidxdr_hid, inh_hid }, + { M680X_INS_BRSET, opidxdr_hid, inh_hid }, + { M680X_INS_BRCLR, opidxdr_hid, inh_hid }, + { M680X_INS_BRSET, opidxdr_hid, inh_hid }, + { M680X_INS_BRCLR, opidxdr_hid, inh_hid }, + // 0x1x, bit set/clear instructions + { M680X_INS_BCLR, opidx_hid, dir_hid }, + { M680X_INS_BSET, opidx_hid, dir_hid }, + { M680X_INS_BCLR, opidx_hid, dir_hid }, + { M680X_INS_BSET, opidx_hid, dir_hid }, + { M680X_INS_BCLR, opidx_hid, dir_hid }, + { M680X_INS_BSET, opidx_hid, dir_hid }, + { M680X_INS_BCLR, opidx_hid, dir_hid }, + { M680X_INS_BSET, opidx_hid, dir_hid }, + { M680X_INS_BCLR, opidx_hid, dir_hid }, + { M680X_INS_BSET, opidx_hid, dir_hid }, + { M680X_INS_BCLR, opidx_hid, dir_hid }, + { M680X_INS_BSET, opidx_hid, dir_hid }, + { M680X_INS_BCLR, opidx_hid, dir_hid }, + { M680X_INS_BSET, opidx_hid, dir_hid }, + { M680X_INS_BCLR, opidx_hid, dir_hid }, + { M680X_INS_BSET, opidx_hid, dir_hid }, + // 0x2x, relative branch instructions + { M680X_INS_BRA, rel8_hid, inh_hid }, + { M680X_INS_BRN, rel8_hid, inh_hid }, + { M680X_INS_BHI, rel8_hid, inh_hid }, + { M680X_INS_BLS, rel8_hid, inh_hid }, + { M680X_INS_BCC, rel8_hid, inh_hid }, + { M680X_INS_BCS, rel8_hid, inh_hid }, + { M680X_INS_BNE, rel8_hid, inh_hid }, + { M680X_INS_BEQ, rel8_hid, inh_hid }, + { M680X_INS_BHCC, rel8_hid, inh_hid }, + { M680X_INS_BHCS, rel8_hid, inh_hid }, + { M680X_INS_BPL, rel8_hid, inh_hid }, + { M680X_INS_BMI, rel8_hid, inh_hid }, + { M680X_INS_BMC, rel8_hid, inh_hid }, + { M680X_INS_BMS, rel8_hid, inh_hid }, + { M680X_INS_BIL, rel8_hid, inh_hid }, + { M680X_INS_BIH, rel8_hid, inh_hid }, + // 0x3x, direct instructions + { M680X_INS_NEG, dir_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_COM, dir_hid, inh_hid }, + { M680X_INS_LSR, dir_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ROR, dir_hid, inh_hid }, + { M680X_INS_ASR, dir_hid, inh_hid }, + { M680X_INS_LSL, dir_hid, inh_hid }, + { M680X_INS_ROL, dir_hid, inh_hid }, + { M680X_INS_DEC, dir_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_INC, dir_hid, inh_hid }, + { M680X_INS_TST, dir_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_CLR, dir_hid, inh_hid }, + // 0x4x, inherent instructions + { M680X_INS_NEGA, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_MUL, inh_hid, inh_hid }, + { M680X_INS_COMA, inh_hid, inh_hid }, + { M680X_INS_LSRA, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_RORA, inh_hid, inh_hid }, + { M680X_INS_ASRA, inh_hid, inh_hid }, + { M680X_INS_LSLA, inh_hid, inh_hid }, + { M680X_INS_ROLA, inh_hid, inh_hid }, + { M680X_INS_DECA, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_INCA, inh_hid, inh_hid }, + { M680X_INS_TSTA, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_CLRA, inh_hid, inh_hid }, + // 0x5x, inherent instructions + { M680X_INS_NEGX, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_COMX, inh_hid, inh_hid }, + { M680X_INS_LSRX, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_RORX, inh_hid, inh_hid }, + { M680X_INS_ASRX, inh_hid, inh_hid }, + { M680X_INS_LSLX, inh_hid, inh_hid }, + { M680X_INS_ROLX, inh_hid, inh_hid }, + { M680X_INS_DECX, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_INCX, inh_hid, inh_hid }, + { M680X_INS_TSTX, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_CLRX, inh_hid, inh_hid }, + // 0x6x, indexed, 1 byte offset instructions + { M680X_INS_NEG, idxX_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_COM, idxX_hid, inh_hid }, + { M680X_INS_LSR, idxX_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ROR, idxX_hid, inh_hid }, + { M680X_INS_ASR, idxX_hid, inh_hid }, + { M680X_INS_LSL, idxX_hid, inh_hid }, + { M680X_INS_ROL, idxX_hid, inh_hid }, + { M680X_INS_DEC, idxX_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_INC, idxX_hid, inh_hid }, + { M680X_INS_TST, idxX_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_CLR, idxX_hid, inh_hid }, + // 0x7x, indexed, no offset instructions + { M680X_INS_NEG, idxX0_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_COM, idxX0_hid, inh_hid }, + { M680X_INS_LSR, idxX0_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ROR, idxX0_hid, inh_hid }, + { M680X_INS_ASR, idxX0_hid, inh_hid }, + { M680X_INS_LSL, idxX0_hid, inh_hid }, + { M680X_INS_ROL, idxX0_hid, inh_hid }, + { M680X_INS_DEC, idxX0_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_INC, idxX0_hid, inh_hid }, + { M680X_INS_TST, idxX0_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_CLR, idxX0_hid, inh_hid }, + // 0x8x, inherent instructions + { M680X_INS_RTI, inh_hid, inh_hid }, + { M680X_INS_RTS, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_SWI, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_STOP, inh_hid, inh_hid }, + { M680X_INS_WAIT, inh_hid, inh_hid }, + // 0x9x, inherent instructions + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_TAX, inh_hid, inh_hid }, + { M680X_INS_CLC, inh_hid, inh_hid }, + { M680X_INS_SEC, inh_hid, inh_hid }, + { M680X_INS_CLI, inh_hid, inh_hid }, + { M680X_INS_SEI, inh_hid, inh_hid }, + { M680X_INS_RSP, inh_hid, inh_hid }, + { M680X_INS_NOP, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_TXA, inh_hid, inh_hid }, + // 0xAx, immediate instructions with reg. A + { M680X_INS_SUB, imm8_hid, inh_hid }, + { M680X_INS_CMP, imm8_hid, inh_hid }, + { M680X_INS_SBC, imm8_hid, inh_hid }, + { M680X_INS_CPX, imm8_hid, inh_hid }, + { M680X_INS_AND, imm8_hid, inh_hid }, + { M680X_INS_BIT, imm8_hid, inh_hid }, + { M680X_INS_LDA, imm8_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_EOR, imm8_hid, inh_hid }, + { M680X_INS_ADC, imm8_hid, inh_hid }, + { M680X_INS_ORA, imm8_hid, inh_hid }, + { M680X_INS_ADD, imm8_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_BSR, rel8_hid, inh_hid }, + { M680X_INS_LDX, imm8_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + // 0xBx, direct instructions with reg. A + { M680X_INS_SUB, dir_hid, inh_hid }, + { M680X_INS_CMP, dir_hid, inh_hid }, + { M680X_INS_SBC, dir_hid, inh_hid }, + { M680X_INS_CPX, dir_hid, inh_hid }, + { M680X_INS_AND, dir_hid, inh_hid }, + { M680X_INS_BIT, dir_hid, inh_hid }, + { M680X_INS_LDA, dir_hid, inh_hid }, + { M680X_INS_STA, dir_hid, inh_hid }, + { M680X_INS_EOR, dir_hid, inh_hid }, + { M680X_INS_ADC, dir_hid, inh_hid }, + { M680X_INS_ORA, dir_hid, inh_hid }, + { M680X_INS_ADD, dir_hid, inh_hid }, + { M680X_INS_JMP, dir_hid, inh_hid }, + { M680X_INS_JSR, dir_hid, inh_hid }, + { M680X_INS_LDX, dir_hid, inh_hid }, + { M680X_INS_STX, dir_hid, inh_hid }, + // 0xCx, extended instructions with reg. A + { M680X_INS_SUB, ext_hid, inh_hid }, + { M680X_INS_CMP, ext_hid, inh_hid }, + { M680X_INS_SBC, ext_hid, inh_hid }, + { M680X_INS_CPX, ext_hid, inh_hid }, + { M680X_INS_AND, ext_hid, inh_hid }, + { M680X_INS_BIT, ext_hid, inh_hid }, + { M680X_INS_LDA, ext_hid, inh_hid }, + { M680X_INS_STA, ext_hid, inh_hid }, + { M680X_INS_EOR, ext_hid, inh_hid }, + { M680X_INS_ADC, ext_hid, inh_hid }, + { M680X_INS_ORA, ext_hid, inh_hid }, + { M680X_INS_ADD, ext_hid, inh_hid }, + { M680X_INS_JMP, ext_hid, inh_hid }, + { M680X_INS_JSR, ext_hid, inh_hid }, + { M680X_INS_LDX, ext_hid, inh_hid }, + { M680X_INS_STX, ext_hid, inh_hid }, + // 0xDx, indexed with 2 byte offset instructions with reg. A + { M680X_INS_SUB, idxX16_hid, inh_hid }, + { M680X_INS_CMP, idxX16_hid, inh_hid }, + { M680X_INS_SBC, idxX16_hid, inh_hid }, + { M680X_INS_CPX, idxX16_hid, inh_hid }, + { M680X_INS_AND, idxX16_hid, inh_hid }, + { M680X_INS_BIT, idxX16_hid, inh_hid }, + { M680X_INS_LDA, idxX16_hid, inh_hid }, + { M680X_INS_STA, idxX16_hid, inh_hid }, + { M680X_INS_EOR, idxX16_hid, inh_hid }, + { M680X_INS_ADC, idxX16_hid, inh_hid }, + { M680X_INS_ORA, idxX16_hid, inh_hid }, + { M680X_INS_ADD, idxX16_hid, inh_hid }, + { M680X_INS_JMP, idxX16_hid, inh_hid }, + { M680X_INS_JSR, idxX16_hid, inh_hid }, + { M680X_INS_LDX, idxX16_hid, inh_hid }, + { M680X_INS_STX, idxX16_hid, inh_hid }, + // 0xEx, indexed with 1 byte offset instructions with reg. A + { M680X_INS_SUB, idxX_hid, inh_hid }, + { M680X_INS_CMP, idxX_hid, inh_hid }, + { M680X_INS_SBC, idxX_hid, inh_hid }, + { M680X_INS_CPX, idxX_hid, inh_hid }, + { M680X_INS_AND, idxX_hid, inh_hid }, + { M680X_INS_BIT, idxX_hid, inh_hid }, + { M680X_INS_LDA, idxX_hid, inh_hid }, + { M680X_INS_STA, idxX_hid, inh_hid }, + { M680X_INS_EOR, idxX_hid, inh_hid }, + { M680X_INS_ADC, idxX_hid, inh_hid }, + { M680X_INS_ORA, idxX_hid, inh_hid }, + { M680X_INS_ADD, idxX_hid, inh_hid }, + { M680X_INS_JMP, idxX_hid, inh_hid }, + { M680X_INS_JSR, idxX_hid, inh_hid }, + { M680X_INS_LDX, idxX_hid, inh_hid }, + { M680X_INS_STX, idxX_hid, inh_hid }, + // 0xFx, indexed without offset instructions with reg. A + { M680X_INS_SUB, idxX0_hid, inh_hid }, + { M680X_INS_CMP, idxX0_hid, inh_hid }, + { M680X_INS_SBC, idxX0_hid, inh_hid }, + { M680X_INS_CPX, idxX0_hid, inh_hid }, + { M680X_INS_AND, idxX0_hid, inh_hid }, + { M680X_INS_BIT, idxX0_hid, inh_hid }, + { M680X_INS_LDA, idxX0_hid, inh_hid }, + { M680X_INS_STA, idxX0_hid, inh_hid }, + { M680X_INS_EOR, idxX0_hid, inh_hid }, + { M680X_INS_ADC, idxX0_hid, inh_hid }, + { M680X_INS_ORA, idxX0_hid, inh_hid }, + { M680X_INS_ADD, idxX0_hid, inh_hid }, + { M680X_INS_JMP, idxX0_hid, inh_hid }, + { M680X_INS_JSR, idxX0_hid, inh_hid }, + { M680X_INS_LDX, idxX0_hid, inh_hid }, + { M680X_INS_STX, idxX0_hid, inh_hid }, +}; + diff --git a/arch/M680X/m6808.inc b/arch/M680X/m6808.inc new file mode 100644 index 0000000000..6114f3c3f5 --- /dev/null +++ b/arch/M680X/m6808.inc @@ -0,0 +1,91 @@ + +// Additional instructions only supported on M68HC08 +static const inst_pageX g_m6808_inst_overlay_table[] = { + { 0x31, M680X_INS_CBEQ, dir_hid, rel8_hid }, + { 0x35, M680X_INS_STHX, dir_hid, inh_hid }, + { 0x3b, M680X_INS_DBNZ, dir_hid, rel8_hid }, + { 0x41, M680X_INS_CBEQA, imm8rel_hid, inh_hid }, + { 0x45, M680X_INS_LDHX, imm16_hid, inh_hid }, + { 0x4b, M680X_INS_DBNZA, rel8_hid, inh_hid }, + { 0x4e, M680X_INS_MOV, dir_hid, dir_hid }, + { 0x51, M680X_INS_CBEQX, imm8rel_hid, inh_hid }, + { 0x52, M680X_INS_DIV, inh_hid, inh_hid }, + { 0x55, M680X_INS_LDHX, dir_hid, inh_hid }, + { 0x5b, M680X_INS_DBNZX, rel8_hid, inh_hid }, + { 0x5e, M680X_INS_MOV, dir_hid, idxX0p_hid }, + { 0x61, M680X_INS_CBEQ, idxXp_hid, rel8_hid }, + { 0x62, M680X_INS_NSA, inh_hid, inh_hid }, + { 0x65, M680X_INS_CPHX, imm16_hid, inh_hid }, + { 0x6b, M680X_INS_DBNZ, idxX_hid, rel8_hid }, + { 0x6e, M680X_INS_MOV, imm8_hid, dir_hid }, + { 0x71, M680X_INS_CBEQ, idxX0p_hid, rel8_hid }, + { 0x72, M680X_INS_DAA, inh_hid, inh_hid }, + { 0x75, M680X_INS_CPHX, dir_hid, inh_hid }, + { 0x7b, M680X_INS_DBNZ, idxX0_hid, rel8_hid }, + { 0x7e, M680X_INS_MOV, idxX0p_hid, dir_hid }, + { 0x84, M680X_INS_TAP, inh_hid, inh_hid }, + { 0x85, M680X_INS_TPA, inh_hid, inh_hid }, + { 0x86, M680X_INS_PULA, inh_hid, inh_hid }, + { 0x87, M680X_INS_PSHA, inh_hid, inh_hid }, + { 0x88, M680X_INS_PULX, inh_hid, inh_hid }, + { 0x89, M680X_INS_PSHX, inh_hid, inh_hid }, + { 0x8a, M680X_INS_PULH, inh_hid, inh_hid }, + { 0x8b, M680X_INS_PSHH, inh_hid, inh_hid }, + { 0x8c, M680X_INS_CLRH, inh_hid, inh_hid }, + { 0x90, M680X_INS_BGE, rel8_hid, inh_hid }, + { 0x91, M680X_INS_BLT, rel8_hid, inh_hid }, + { 0x92, M680X_INS_BGT, rel8_hid, inh_hid }, + { 0x93, M680X_INS_BLE, rel8_hid, inh_hid }, + { 0x94, M680X_INS_TXS, inh_hid, inh_hid }, + { 0x95, M680X_INS_TSX, inh_hid, inh_hid }, + { 0x97, M680X_INS_TAX, inh_hid, inh_hid }, + { 0x9f, M680X_INS_TXA, inh_hid, inh_hid }, + { 0xa7, M680X_INS_AIS, imm8_hid, inh_hid }, + { 0xaf, M680X_INS_AIX, imm8_hid, inh_hid }, +}; + +// M68HC08 PAGE2 instructions (prefix 0x9E) +static const inst_pageX g_m6808_inst_page2_table[] = { + { 0x60, M680X_INS_NEG, idxS_hid, inh_hid }, + { 0x61, M680X_INS_CBEQ, idxS_hid, rel8_hid }, + { 0x63, M680X_INS_COM, idxS_hid, inh_hid }, + { 0x64, M680X_INS_LSR, idxS_hid, inh_hid }, + { 0x66, M680X_INS_ROR, idxS_hid, inh_hid }, + { 0x67, M680X_INS_ASR, idxS_hid, inh_hid }, + { 0x68, M680X_INS_LSL, idxS_hid, inh_hid }, + { 0x69, M680X_INS_ROL, idxS_hid, inh_hid }, + { 0x6a, M680X_INS_DEC, idxS_hid, inh_hid }, + { 0x6b, M680X_INS_DBNZ, idxS_hid, rel8_hid }, + { 0x6c, M680X_INS_INC, idxS_hid, inh_hid }, + { 0x6d, M680X_INS_TST, idxS_hid, inh_hid }, + { 0x6f, M680X_INS_CLR, idxS_hid, inh_hid }, + { 0xd0, M680X_INS_SUB, idxS16_hid, inh_hid }, + { 0xd1, M680X_INS_CMP, idxS16_hid, inh_hid }, + { 0xd2, M680X_INS_SBC, idxS16_hid, inh_hid }, + { 0xd3, M680X_INS_CPX, idxS16_hid, inh_hid }, + { 0xd4, M680X_INS_AND, idxS16_hid, inh_hid }, + { 0xd5, M680X_INS_BIT, idxS16_hid, inh_hid }, + { 0xd6, M680X_INS_LDA, idxS16_hid, inh_hid }, + { 0xd7, M680X_INS_STA, idxS16_hid, inh_hid }, + { 0xd8, M680X_INS_EOR, idxS16_hid, inh_hid }, + { 0xd9, M680X_INS_ADC, idxS16_hid, inh_hid }, + { 0xda, M680X_INS_ORA, idxS16_hid, inh_hid }, + { 0xdb, M680X_INS_ADD, idxS16_hid, inh_hid }, + { 0xde, M680X_INS_LDX, idxS16_hid, inh_hid }, + { 0xdf, M680X_INS_STX, idxS16_hid, inh_hid }, + { 0xe0, M680X_INS_SUB, idxS_hid, inh_hid }, + { 0xe1, M680X_INS_CMP, idxS_hid, inh_hid }, + { 0xe2, M680X_INS_SBC, idxS_hid, inh_hid }, + { 0xe3, M680X_INS_CPX, idxS_hid, inh_hid }, + { 0xe4, M680X_INS_AND, idxS_hid, inh_hid }, + { 0xe5, M680X_INS_BIT, idxS_hid, inh_hid }, + { 0xe6, M680X_INS_LDA, idxS_hid, inh_hid }, + { 0xe7, M680X_INS_STA, idxS_hid, inh_hid }, + { 0xe8, M680X_INS_EOR, idxS_hid, inh_hid }, + { 0xe9, M680X_INS_ADC, idxS_hid, inh_hid }, + { 0xea, M680X_INS_ORA, idxS_hid, inh_hid }, + { 0xeb, M680X_INS_ADD, idxS_hid, inh_hid }, + { 0xee, M680X_INS_LDX, idxS_hid, inh_hid }, + { 0xef, M680X_INS_STX, idxS_hid, inh_hid }, +}; + diff --git a/arch/M680X/m6809.inc b/arch/M680X/m6809.inc new file mode 100644 index 0000000000..24f02603fb --- /dev/null +++ b/arch/M680X/m6809.inc @@ -0,0 +1,352 @@ + +// M6809/HD6309 PAGE1 instructions +static const inst_page1 g_m6809_inst_page1_table[256] = { + // 0x0x, direct instructions + { M680X_INS_NEG, dir_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_COM, dir_hid, inh_hid }, + { M680X_INS_LSR, dir_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ROR, dir_hid, inh_hid }, + { M680X_INS_ASR, dir_hid, inh_hid }, + { M680X_INS_LSL, dir_hid, inh_hid }, + { M680X_INS_ROL, dir_hid, inh_hid }, + { M680X_INS_DEC, dir_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_INC, dir_hid, inh_hid }, + { M680X_INS_TST, dir_hid, inh_hid }, + { M680X_INS_JMP, dir_hid, inh_hid }, + { M680X_INS_CLR, dir_hid, inh_hid }, + // 0x1x, misc instructions + { M680X_INS_ILLGL, illgl_hid, inh_hid }, // PAGE2 + { M680X_INS_ILLGL, illgl_hid, inh_hid }, // PAGE3 + { M680X_INS_NOP, inh_hid, inh_hid }, + { M680X_INS_SYNC, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_LBRA, rel16_hid, inh_hid }, + { M680X_INS_LBSR, rel16_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_DAA, inh_hid, inh_hid }, + { M680X_INS_ORCC, imm8_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ANDCC, imm8_hid, inh_hid }, + { M680X_INS_SEX, inh_hid, inh_hid }, + { M680X_INS_EXG, rr09_hid, inh_hid }, + { M680X_INS_TFR, rr09_hid, inh_hid }, + // 0x2x, relative branch instructions + { M680X_INS_BRA, rel8_hid, inh_hid }, + { M680X_INS_BRN, rel8_hid, inh_hid }, + { M680X_INS_BHI, rel8_hid, inh_hid }, + { M680X_INS_BLS, rel8_hid, inh_hid }, + { M680X_INS_BCC, rel8_hid, inh_hid }, + { M680X_INS_BCS, rel8_hid, inh_hid }, + { M680X_INS_BNE, rel8_hid, inh_hid }, + { M680X_INS_BEQ, rel8_hid, inh_hid }, + { M680X_INS_BVC, rel8_hid, inh_hid }, + { M680X_INS_BVS, rel8_hid, inh_hid }, + { M680X_INS_BPL, rel8_hid, inh_hid }, + { M680X_INS_BMI, rel8_hid, inh_hid }, + { M680X_INS_BGE, rel8_hid, inh_hid }, + { M680X_INS_BLT, rel8_hid, inh_hid }, + { M680X_INS_BGT, rel8_hid, inh_hid }, + { M680X_INS_BLE, rel8_hid, inh_hid }, + // 0x3x, misc instructions + { M680X_INS_LEAX, idx09_hid, inh_hid }, + { M680X_INS_LEAY, idx09_hid, inh_hid }, + { M680X_INS_LEAS, idx09_hid, inh_hid }, + { M680X_INS_LEAU, idx09_hid, inh_hid }, + { M680X_INS_PSHS, rbits_hid, inh_hid }, + { M680X_INS_PULS, rbits_hid, inh_hid }, + { M680X_INS_PSHU, rbits_hid, inh_hid }, + { M680X_INS_PULU, rbits_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_RTS, inh_hid, inh_hid }, + { M680X_INS_ABX, inh_hid, inh_hid }, + { M680X_INS_RTI, inh_hid, inh_hid }, + { M680X_INS_CWAI, imm8_hid, inh_hid }, + { M680X_INS_MUL, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_SWI, inh_hid, inh_hid }, + // 0x4x, Register A instructions + { M680X_INS_NEGA, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_COMA, inh_hid, inh_hid }, + { M680X_INS_LSRA, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_RORA, inh_hid, inh_hid }, + { M680X_INS_ASRA, inh_hid, inh_hid }, + { M680X_INS_LSLA, inh_hid, inh_hid }, + { M680X_INS_ROLA, inh_hid, inh_hid }, + { M680X_INS_DECA, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_INCA, inh_hid, inh_hid }, + { M680X_INS_TSTA, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_CLRA, inh_hid, inh_hid }, + // 0x5x, Register B instructions + { M680X_INS_NEGB, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_COMB, inh_hid, inh_hid }, + { M680X_INS_LSRB, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_RORB, inh_hid, inh_hid }, + { M680X_INS_ASRB, inh_hid, inh_hid }, + { M680X_INS_LSLB, inh_hid, inh_hid }, + { M680X_INS_ROLB, inh_hid, inh_hid }, + { M680X_INS_DECB, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_INCB, inh_hid, inh_hid }, + { M680X_INS_TSTB, inh_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_CLRB, inh_hid, inh_hid }, + // 0x6x, indexed instructions + { M680X_INS_NEG, idx09_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_COM, idx09_hid, inh_hid }, + { M680X_INS_LSR, idx09_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ROR, idx09_hid, inh_hid }, + { M680X_INS_ASR, idx09_hid, inh_hid }, + { M680X_INS_LSL, idx09_hid, inh_hid }, + { M680X_INS_ROL, idx09_hid, inh_hid }, + { M680X_INS_DEC, idx09_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_INC, idx09_hid, inh_hid }, + { M680X_INS_TST, idx09_hid, inh_hid }, + { M680X_INS_JMP, idx09_hid, inh_hid }, + { M680X_INS_CLR, idx09_hid, inh_hid }, + // 0x7x, extended instructions + { M680X_INS_NEG, ext_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_COM, ext_hid, inh_hid }, + { M680X_INS_LSR, ext_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_ROR, ext_hid, inh_hid }, + { M680X_INS_ASR, ext_hid, inh_hid }, + { M680X_INS_LSL, ext_hid, inh_hid }, + { M680X_INS_ROL, ext_hid, inh_hid }, + { M680X_INS_DEC, ext_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_INC, ext_hid, inh_hid }, + { M680X_INS_TST, ext_hid, inh_hid }, + { M680X_INS_JMP, ext_hid, inh_hid }, + { M680X_INS_CLR, ext_hid, inh_hid }, + // 0x8x, immediate instructions with Register A,D,X + { M680X_INS_SUBA, imm8_hid, inh_hid }, + { M680X_INS_CMPA, imm8_hid, inh_hid }, + { M680X_INS_SBCA, imm8_hid, inh_hid }, + { M680X_INS_SUBD, imm16_hid, inh_hid }, + { M680X_INS_ANDA, imm8_hid, inh_hid }, + { M680X_INS_BITA, imm8_hid, inh_hid }, + { M680X_INS_LDA, imm8_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_EORA, imm8_hid, inh_hid }, + { M680X_INS_ADCA, imm8_hid, inh_hid }, + { M680X_INS_ORA, imm8_hid, inh_hid }, + { M680X_INS_ADDA, imm8_hid, inh_hid }, + { M680X_INS_CMPX, imm16_hid, inh_hid }, + { M680X_INS_BSR, rel8_hid, inh_hid }, + { M680X_INS_LDX, imm16_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + // 0x9x, direct instructions with register A,D,X + { M680X_INS_SUBA, dir_hid, inh_hid }, + { M680X_INS_CMPA, dir_hid, inh_hid }, + { M680X_INS_SBCA, dir_hid, inh_hid }, + { M680X_INS_SUBD, dir_hid, inh_hid }, + { M680X_INS_ANDA, dir_hid, inh_hid }, + { M680X_INS_BITA, dir_hid, inh_hid }, + { M680X_INS_LDA, dir_hid, inh_hid }, + { M680X_INS_STA, dir_hid, inh_hid }, + { M680X_INS_EORA, dir_hid, inh_hid }, + { M680X_INS_ADCA, dir_hid, inh_hid }, + { M680X_INS_ORA, dir_hid, inh_hid }, + { M680X_INS_ADDA, dir_hid, inh_hid }, + { M680X_INS_CMPX, dir_hid, inh_hid }, + { M680X_INS_JSR, dir_hid, inh_hid }, + { M680X_INS_LDX, dir_hid, inh_hid }, + { M680X_INS_STX, dir_hid, inh_hid }, + // 0xAx, indexed instructions with Register A,D,X + { M680X_INS_SUBA, idx09_hid, inh_hid }, + { M680X_INS_CMPA, idx09_hid, inh_hid }, + { M680X_INS_SBCA, idx09_hid, inh_hid }, + { M680X_INS_SUBD, idx09_hid, inh_hid }, + { M680X_INS_ANDA, idx09_hid, inh_hid }, + { M680X_INS_BITA, idx09_hid, inh_hid }, + { M680X_INS_LDA, idx09_hid, inh_hid }, + { M680X_INS_STA, idx09_hid, inh_hid }, + { M680X_INS_EORA, idx09_hid, inh_hid }, + { M680X_INS_ADCA, idx09_hid, inh_hid }, + { M680X_INS_ORA, idx09_hid, inh_hid }, + { M680X_INS_ADDA, idx09_hid, inh_hid }, + { M680X_INS_CMPX, idx09_hid, inh_hid }, + { M680X_INS_JSR, idx09_hid, inh_hid }, + { M680X_INS_LDX, idx09_hid, inh_hid }, + { M680X_INS_STX, idx09_hid, inh_hid }, + // 0xBx, extended instructions with register A,D,X + { M680X_INS_SUBA, ext_hid, inh_hid }, + { M680X_INS_CMPA, ext_hid, inh_hid }, + { M680X_INS_SBCA, ext_hid, inh_hid }, + { M680X_INS_SUBD, ext_hid, inh_hid }, + { M680X_INS_ANDA, ext_hid, inh_hid }, + { M680X_INS_BITA, ext_hid, inh_hid }, + { M680X_INS_LDA, ext_hid, inh_hid }, + { M680X_INS_STA, ext_hid, inh_hid }, + { M680X_INS_EORA, ext_hid, inh_hid }, + { M680X_INS_ADCA, ext_hid, inh_hid }, + { M680X_INS_ORA, ext_hid, inh_hid }, + { M680X_INS_ADDA, ext_hid, inh_hid }, + { M680X_INS_CMPX, ext_hid, inh_hid }, + { M680X_INS_JSR, ext_hid, inh_hid }, + { M680X_INS_LDX, ext_hid, inh_hid }, + { M680X_INS_STX, ext_hid, inh_hid }, + // 0xCx, immediate instructions with register B,D,U + { M680X_INS_SUBB, imm8_hid, inh_hid }, + { M680X_INS_CMPB, imm8_hid, inh_hid }, + { M680X_INS_SBCB, imm8_hid, inh_hid }, + { M680X_INS_ADDD, imm16_hid, inh_hid }, + { M680X_INS_ANDB, imm8_hid, inh_hid }, + { M680X_INS_BITB, imm8_hid, inh_hid }, + { M680X_INS_LDB, imm8_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_EORB, imm8_hid, inh_hid }, + { M680X_INS_ADCB, imm8_hid, inh_hid }, + { M680X_INS_ORB, imm8_hid, inh_hid }, + { M680X_INS_ADDB, imm8_hid, inh_hid }, + { M680X_INS_LDD, imm16_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + { M680X_INS_LDU, imm16_hid, inh_hid }, + { M680X_INS_ILLGL, illgl_hid, inh_hid }, + // 0xDx direct instructions with register B,D,U + { M680X_INS_SUBB, dir_hid, inh_hid }, + { M680X_INS_CMPB, dir_hid, inh_hid }, + { M680X_INS_SBCB, dir_hid, inh_hid }, + { M680X_INS_ADDD, dir_hid, inh_hid }, + { M680X_INS_ANDB, dir_hid, inh_hid }, + { M680X_INS_BITB, dir_hid, inh_hid }, + { M680X_INS_LDB, dir_hid, inh_hid }, + { M680X_INS_STB, dir_hid, inh_hid }, + { M680X_INS_EORB, dir_hid, inh_hid }, + { M680X_INS_ADCB, dir_hid, inh_hid }, + { M680X_INS_ORB, dir_hid, inh_hid }, + { M680X_INS_ADDB, dir_hid, inh_hid }, + { M680X_INS_LDD, dir_hid, inh_hid }, + { M680X_INS_STD, dir_hid, inh_hid }, + { M680X_INS_LDU, dir_hid, inh_hid }, + { M680X_INS_STU, dir_hid, inh_hid }, + // 0xEx, indexed instruction with register B,D,U + { M680X_INS_SUBB, idx09_hid, inh_hid }, + { M680X_INS_CMPB, idx09_hid, inh_hid }, + { M680X_INS_SBCB, idx09_hid, inh_hid }, + { M680X_INS_ADDD, idx09_hid, inh_hid }, + { M680X_INS_ANDB, idx09_hid, inh_hid }, + { M680X_INS_BITB, idx09_hid, inh_hid }, + { M680X_INS_LDB, idx09_hid, inh_hid }, + { M680X_INS_STB, idx09_hid, inh_hid }, + { M680X_INS_EORB, idx09_hid, inh_hid }, + { M680X_INS_ADCB, idx09_hid, inh_hid }, + { M680X_INS_ORB, idx09_hid, inh_hid }, + { M680X_INS_ADDB, idx09_hid, inh_hid }, + { M680X_INS_LDD, idx09_hid, inh_hid }, + { M680X_INS_STD, idx09_hid, inh_hid }, + { M680X_INS_LDU, idx09_hid, inh_hid }, + { M680X_INS_STU, idx09_hid, inh_hid }, + // 0xFx, extended instructions with register B,D,U + { M680X_INS_SUBB, ext_hid, inh_hid }, + { M680X_INS_CMPB, ext_hid, inh_hid }, + { M680X_INS_SBCB, ext_hid, inh_hid }, + { M680X_INS_ADDD, ext_hid, inh_hid }, + { M680X_INS_ANDB, ext_hid, inh_hid }, + { M680X_INS_BITB, ext_hid, inh_hid }, + { M680X_INS_LDB, ext_hid, inh_hid }, + { M680X_INS_STB, ext_hid, inh_hid }, + { M680X_INS_EORB, ext_hid, inh_hid }, + { M680X_INS_ADCB, ext_hid, inh_hid }, + { M680X_INS_ORB, ext_hid, inh_hid }, + { M680X_INS_ADDB, ext_hid, inh_hid }, + { M680X_INS_LDD, ext_hid, inh_hid }, + { M680X_INS_STD, ext_hid, inh_hid }, + { M680X_INS_LDU, ext_hid, inh_hid }, + { M680X_INS_STU, ext_hid, inh_hid }, +}; + +// The following array has to be sorted by increasing +// opcodes. Otherwise the binary_search will fail. +// +// M6809 PAGE2 instructions (with prefix 0x10) +static const inst_pageX g_m6809_inst_page2_table[] = { + // 0x2x, relative long branch instructions + { 0x21, M680X_INS_LBRN, rel16_hid, inh_hid }, + { 0x22, M680X_INS_LBHI, rel16_hid, inh_hid }, + { 0x23, M680X_INS_LBLS, rel16_hid, inh_hid }, + { 0x24, M680X_INS_LBCC, rel16_hid, inh_hid }, + { 0x25, M680X_INS_LBCS, rel16_hid, inh_hid }, + { 0x26, M680X_INS_LBNE, rel16_hid, inh_hid }, + { 0x27, M680X_INS_LBEQ, rel16_hid, inh_hid }, + { 0x28, M680X_INS_LBVC, rel16_hid, inh_hid }, + { 0x29, M680X_INS_LBVS, rel16_hid, inh_hid }, + { 0x2a, M680X_INS_LBPL, rel16_hid, inh_hid }, + { 0x2b, M680X_INS_LBMI, rel16_hid, inh_hid }, + { 0x2c, M680X_INS_LBGE, rel16_hid, inh_hid }, + { 0x2d, M680X_INS_LBLT, rel16_hid, inh_hid }, + { 0x2e, M680X_INS_LBGT, rel16_hid, inh_hid }, + { 0x2f, M680X_INS_LBLE, rel16_hid, inh_hid }, + // 0x3x + { 0x3f, M680X_INS_SWI2, inh_hid, inh_hid }, + // 0x8x, immediate instructions with register D,Y + { 0x83, M680X_INS_CMPD, imm16_hid, inh_hid }, + { 0x8c, M680X_INS_CMPY, imm16_hid, inh_hid }, + { 0x8e, M680X_INS_LDY, imm16_hid, inh_hid }, + // 0x9x, direct instructions with register D,Y + { 0x93, M680X_INS_CMPD, dir_hid, inh_hid }, + { 0x9c, M680X_INS_CMPY, dir_hid, inh_hid }, + { 0x9e, M680X_INS_LDY, dir_hid, inh_hid }, + { 0x9f, M680X_INS_STY, dir_hid, inh_hid }, + // 0xAx, indexed instructions with register D,Y + { 0xa3, M680X_INS_CMPD, idx09_hid, inh_hid }, + { 0xac, M680X_INS_CMPY, idx09_hid, inh_hid }, + { 0xae, M680X_INS_LDY, idx09_hid, inh_hid }, + { 0xaf, M680X_INS_STY, idx09_hid, inh_hid }, + // 0xBx, extended instructions with register D,Y + { 0xb3, M680X_INS_CMPD, ext_hid, inh_hid }, + { 0xbc, M680X_INS_CMPY, ext_hid, inh_hid }, + { 0xbe, M680X_INS_LDY, ext_hid, inh_hid }, + { 0xbf, M680X_INS_STY, ext_hid, inh_hid }, + // 0xCx, immediate instructions with register S + { 0xce, M680X_INS_LDS, imm16_hid, inh_hid }, + // 0xDx, direct instructions with register S + { 0xde, M680X_INS_LDS, dir_hid, inh_hid }, + { 0xdf, M680X_INS_STS, dir_hid, inh_hid }, + // 0xEx, indexed instructions with register S + { 0xee, M680X_INS_LDS, idx09_hid, inh_hid }, + { 0xef, M680X_INS_STS, idx09_hid, inh_hid }, + // 0xFx, extended instructions with register S + { 0xfe, M680X_INS_LDS, ext_hid, inh_hid }, + { 0xff, M680X_INS_STS, ext_hid, inh_hid }, +}; + +// The following array has to be sorted by increasing +// opcodes. Otherwise the binary_search will fail. +// +// M6809 PAGE3 instructions (with prefix 0x11) +static const inst_pageX g_m6809_inst_page3_table[] = { + { 0x3f, M680X_INS_SWI3, inh_hid, inh_hid }, + // 0x8x, immediate instructions with register U,S + { 0x83, M680X_INS_CMPU, imm16_hid, inh_hid }, + { 0x8c, M680X_INS_CMPS, imm16_hid, inh_hid }, + // 0x9x, direct instructions with register U,S + { 0x93, M680X_INS_CMPU, dir_hid, inh_hid }, + { 0x9c, M680X_INS_CMPS, dir_hid, inh_hid }, + // 0xAx, indexed instructions with register U,S + { 0xa3, M680X_INS_CMPU, idx09_hid, inh_hid }, + { 0xac, M680X_INS_CMPS, idx09_hid, inh_hid }, + // 0xBx, extended instructions with register U,S + { 0xb3, M680X_INS_CMPU, ext_hid, inh_hid }, + { 0xbc, M680X_INS_CMPS, ext_hid, inh_hid }, +}; + diff --git a/arch/M680X/m6811.inc b/arch/M680X/m6811.inc new file mode 100644 index 0000000000..f26fb2c4b1 --- /dev/null +++ b/arch/M680X/m6811.inc @@ -0,0 +1,105 @@ + +// Additional instructions only supported on M68HC11 +static const inst_pageX g_m6811_inst_overlay_table[] = { + { 0x00, M680X_INS_TEST, inh_hid, inh_hid }, + { 0x02, M680X_INS_IDIV, inh_hid, inh_hid }, + { 0x03, M680X_INS_FDIV, inh_hid, inh_hid }, + { 0x12, M680X_INS_BRSET, dir_hid, imm8rel_hid }, + { 0x13, M680X_INS_BRCLR, dir_hid, imm8rel_hid }, + { 0x14, M680X_INS_BSET, dir_hid, imm8_hid }, + { 0x15, M680X_INS_BCLR, dir_hid, imm8_hid }, + { 0x1c, M680X_INS_BSET, idxX_hid, imm8_hid }, + { 0x1d, M680X_INS_BCLR, idxX_hid, imm8_hid }, + { 0x1e, M680X_INS_BRSET, idxX_hid, imm8rel_hid }, + { 0x1f, M680X_INS_BRCLR, idxX_hid, imm8rel_hid }, + { 0x8f, M680X_INS_XGDX, inh_hid, inh_hid }, + { 0xcf, M680X_INS_STOP, inh_hid, inh_hid }, +}; + +// M68HC11 PAGE2 instructions +static const inst_pageX g_m6811_inst_page2_table[] = { + { 0x08, M680X_INS_INY, inh_hid, inh_hid }, + { 0x09, M680X_INS_DEY, inh_hid, inh_hid }, + { 0x1c, M680X_INS_BSET, idxY_hid, imm8_hid }, + { 0x1d, M680X_INS_BCLR, idxY_hid, imm8_hid }, + { 0x1e, M680X_INS_BRSET, idxY_hid, imm8rel_hid }, + { 0x1f, M680X_INS_BRCLR, idxY_hid, imm8rel_hid }, + { 0x30, M680X_INS_TSY, inh_hid, inh_hid }, + { 0x35, M680X_INS_TYS, inh_hid, inh_hid }, + { 0x38, M680X_INS_PULY, inh_hid, inh_hid }, + { 0x3a, M680X_INS_ABY, inh_hid, inh_hid }, + { 0x3c, M680X_INS_PSHY, inh_hid, inh_hid }, + { 0x60, M680X_INS_NEG, idxY_hid, inh_hid }, + { 0x63, M680X_INS_COM, idxY_hid, inh_hid }, + { 0x64, M680X_INS_LSR, idxY_hid, inh_hid }, + { 0x66, M680X_INS_ROR, idxY_hid, inh_hid }, + { 0x67, M680X_INS_ASR, idxY_hid, inh_hid }, + { 0x68, M680X_INS_ASL, idxY_hid, inh_hid }, + { 0x69, M680X_INS_ROL, idxY_hid, inh_hid }, + { 0x6a, M680X_INS_DEC, idxY_hid, inh_hid }, + { 0x6c, M680X_INS_INC, idxY_hid, inh_hid }, + { 0x6d, M680X_INS_TST, idxY_hid, inh_hid }, + { 0x6e, M680X_INS_JMP, idxY_hid, inh_hid }, + { 0x6f, M680X_INS_CLR, idxY_hid, inh_hid }, + { 0x8c, M680X_INS_CPY, imm16_hid, inh_hid }, + { 0x8f, M680X_INS_XGDY, inh_hid, inh_hid }, + { 0x9c, M680X_INS_CPY, dir_hid, inh_hid }, + { 0xa0, M680X_INS_SUBA, idxY_hid, inh_hid }, + { 0xa1, M680X_INS_CMPA, idxY_hid, inh_hid }, + { 0xa2, M680X_INS_SBCA, idxY_hid, inh_hid }, + { 0xa3, M680X_INS_SUBD, idxY_hid, inh_hid }, + { 0xa4, M680X_INS_ANDA, idxY_hid, inh_hid }, + { 0xa5, M680X_INS_BITA, idxY_hid, inh_hid }, + { 0xa6, M680X_INS_LDAA, idxY_hid, inh_hid }, + { 0xa7, M680X_INS_STAA, idxY_hid, inh_hid }, + { 0xa8, M680X_INS_EORA, idxY_hid, inh_hid }, + { 0xa9, M680X_INS_ADCA, idxY_hid, inh_hid }, + { 0xaa, M680X_INS_ORAA, idxY_hid, inh_hid }, + { 0xab, M680X_INS_ADDA, idxY_hid, inh_hid }, + { 0xac, M680X_INS_CPY, idxY_hid, inh_hid }, + { 0xad, M680X_INS_JSR, idxY_hid, inh_hid }, + { 0xae, M680X_INS_LDS, idxY_hid, inh_hid }, + { 0xaf, M680X_INS_STS, idxY_hid, inh_hid }, + { 0xbc, M680X_INS_CPY, ext_hid, inh_hid }, + { 0xce, M680X_INS_LDY, imm16_hid, inh_hid }, + { 0xde, M680X_INS_LDY, dir_hid, inh_hid }, + { 0xdf, M680X_INS_STY, dir_hid, inh_hid }, + { 0xe0, M680X_INS_SUBB, idxY_hid, inh_hid }, + { 0xe1, M680X_INS_CMPB, idxY_hid, inh_hid }, + { 0xe2, M680X_INS_SBCB, idxY_hid, inh_hid }, + { 0xe3, M680X_INS_ADDD, idxY_hid, inh_hid }, + { 0xe4, M680X_INS_ANDB, idxY_hid, inh_hid }, + { 0xe5, M680X_INS_BITB, idxY_hid, inh_hid }, + { 0xe6, M680X_INS_LDAB, idxY_hid, inh_hid }, + { 0xe7, M680X_INS_STAB, idxY_hid, inh_hid }, + { 0xe8, M680X_INS_EORB, idxY_hid, inh_hid }, + { 0xe9, M680X_INS_ADCB, idxY_hid, inh_hid }, + { 0xea, M680X_INS_ORAB, idxY_hid, inh_hid }, + { 0xeb, M680X_INS_ADDB, idxY_hid, inh_hid }, + { 0xec, M680X_INS_LDD, idxY_hid, inh_hid }, + { 0xed, M680X_INS_STD, idxY_hid, inh_hid }, + { 0xee, M680X_INS_LDY, idxY_hid, inh_hid }, + { 0xef, M680X_INS_STY, idxY_hid, inh_hid }, + { 0xfe, M680X_INS_LDY, ext_hid, inh_hid }, + { 0xff, M680X_INS_STY, ext_hid, inh_hid }, +}; + +// M68HC11 PAGE3 instructions +static const inst_pageX g_m6811_inst_page3_table[] = { + { 0x83, M680X_INS_CPD, imm16_hid, inh_hid }, + { 0x93, M680X_INS_CPD, dir_hid, inh_hid }, + { 0xa3, M680X_INS_CPD, idxX_hid, inh_hid }, + { 0xac, M680X_INS_CPY, idxX_hid, inh_hid }, + { 0xb3, M680X_INS_CPD, ext_hid, inh_hid }, + { 0xee, M680X_INS_LDY, idxX_hid, inh_hid }, + { 0xef, M680X_INS_STY, idxX_hid, inh_hid }, +}; + +// M68HC11 PAGE4 instructions +static const inst_pageX g_m6811_inst_page4_table[] = { + { 0xa3, M680X_INS_CPD, idxY_hid, inh_hid }, + { 0xac, M680X_INS_CPX, idxY_hid, inh_hid }, + { 0xee, M680X_INS_LDX, idxY_hid, inh_hid }, + { 0xef, M680X_INS_STX, idxY_hid, inh_hid }, +}; + diff --git a/bindings/const_generator.py b/bindings/const_generator.py index 91c50eaabd..a8d3b1f180 100644 --- a/bindings/const_generator.py +++ b/bindings/const_generator.py @@ -5,7 +5,7 @@ INCL_DIR = '../include/capstone/' -include = [ 'arm.h', 'arm64.h', 'm68k.h', 'mips.h', 'x86.h', 'ppc.h', 'sparc.h', 'systemz.h', 'xcore.h', 'tms320c64x.h' ] +include = [ 'arm.h', 'arm64.h', 'm68k.h', 'mips.h', 'x86.h', 'ppc.h', 'sparc.h', 'systemz.h', 'xcore.h', 'tms320c64x.h', 'm680x.h' ] template = { 'java': { @@ -24,6 +24,7 @@ 'systemz.h': 'Sysz', 'xcore.h': 'Xcore', 'tms320c64x.h': 'TMS320C64x', + 'm680x.h': 'M680x', 'comment_open': '\t//', 'comment_close': '', }, @@ -43,6 +44,7 @@ 'systemz.h': 'sysz', 'xcore.h': 'xcore', 'tms320c64x.h': 'tms320c64x', + 'm680x.h': 'm680x', 'comment_open': '#', 'comment_close': '', }, @@ -62,6 +64,7 @@ 'systemz.h': 'sysz', 'xcore.h': 'xcore', 'tms320c64x.h': 'tms320c64x', + 'm680x.h': 'm680x', 'comment_open': '(*', 'comment_close': ' *)', }, diff --git a/bindings/java/Makefile b/bindings/java/Makefile index 9db68dc766..5115a9f950 100644 --- a/bindings/java/Makefile +++ b/bindings/java/Makefile @@ -22,9 +22,9 @@ endif CAPSTONE_JAVA = Capstone.java Arm_const.java Arm64_const.java Mips_const.java \ X86_const.java Xcore_const.java Ppc_const.java Sparc_const.java\ - Sysz_const.java \ + Sysz_const.java M680x_const.java \ Arm.java Arm64.java Mips.java X86.java Xcore.java Ppc.java\ - Sparc.java Systemz.java + Sparc.java Systemz.java M680x.java all: gen_const capstone tests @@ -44,7 +44,7 @@ tests: capstone_class jna @mkdir -p $(OBJDIR) javac -d $(OBJDIR) -classpath "$(JNA):$(BLDIR)/capstone.jar" TestBasic.java\ TestArm.java TestArm64.java TestMips.java TestX86.java TestXcore.java\ - TestPpc.java TestSparc.java TestSystemz.java + TestPpc.java TestSparc.java TestSystemz.java TestM680x.java gen_const: cd ../ && python const_generator.py java @@ -60,7 +60,7 @@ ifdef BUILDDIR rm -rf $(OBJDIR) endif -TESTS = testbasic arm arm64 mips ppc sparc systemz x86 xcore +TESTS = testbasic arm arm64 m680x mips ppc sparc systemz x86 xcore check: @for t in $(TESTS); do \ echo Check $$t ... ; \ diff --git a/bindings/java/TestM680x.java b/bindings/java/TestM680x.java new file mode 100644 index 0000000000..b99517b760 --- /dev/null +++ b/bindings/java/TestM680x.java @@ -0,0 +1,207 @@ +// Capstone Java binding +/* M680X Backend by Wolfgang Schwotzer 2017 */ + +import java.lang.*; +import capstone.Capstone; +import capstone.M680x; + +import static capstone.M680x_const.*; + +public class TestM680x { + + static final String sAccess[] = { + "UNCHANGED", "READ", "WRITE", "READ | WRITE", + }; + + static final String M6800_CODE = "010936647f7410009010A410b6100039"; + static final String M6801_CODE = "04053c3d389310ec10ed1039"; + static final String M6805_CODE = "047f00172228002e0040425a708e979ca015ad00c31000da1234e57ffe"; + static final String M6808_CODE = "31220035224510004b005110525e226265123472848586878a8b8c9495a710af109e607f9e6b7f009ed610009ee67f"; + static final String HD6301_CODE = "6b100071100072101039"; + static final String M6809_CODE = "0610191a551e0123e931063455a681a7897fffa69d1000a791a69f100011ac99100039A607A627A647A667A60FA610A680A681A682A683A684A685A686A6887FA68880A6897FFFA6898000A68BA68C10A68D1000A691A693A694A695A696A6987FA69880A6997FFFA6998000A69BA69C10A69D1000A69F1000"; + static final String M6811_CODE = "0203127f100013990800147f02157f011e7f20008fcf18081830183c1867188c1000188f18ce100018ff10001aa37f1aac1aee7f1aef7fcdac7f"; + static final String CPU12_CODE = "000401000c00800e008000111e100080003b4a1000044b01044f7f80008f1000b752b7b1a667a6fea6f71802e23039e21000180c30391000181118121000181900181e00183e183f00"; + static final String HD6309_CODE = "0110106210107b101000cd499602d21030231038103b1053105d1130431011372510113812113923113b34118e100011af1011ab1011f68000"; + static final String HCS08_CODE = "3210009eae9ece7f9ebe10009efe7f3e10009ef37f9610009eff7f82"; + + static byte[] hexString2Byte(String s) { + // from http://stackoverflow.com/questions/140131/convert-a-string-representation-of-a-hex-dump-to-a-byte-array-using-java + int len = s.length(); + byte[] data = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + + Character.digit(s.charAt(i+1), 16)); + } + return data; + } + + static public String stringToHexUc(byte[] code) { + StringBuilder buf = new StringBuilder(800); + for (byte ch: code) { + buf.append(String.format(" 0x%02X", ch)); + } + return buf.toString(); + } + + static public String stringToHexShortUc(byte[] code) { + StringBuilder buf = new StringBuilder(800); + for (byte ch: code) { + buf.append(String.format("%02X", ch)); + } + return buf.toString(); + } + + public static Capstone cs; +/* + private static String hex(int i) { + return Integer.toString(i, 16); + } + + private static String hex(long i) { + return Long.toString(i, 16); + } +*/ + public static void print_ins_detail(Capstone.CsInsn ins) { + String bytes = stringToHexShortUc(ins.bytes); + System.out.printf("0x%04X:\t%s\t%s\t%s\n", ins.address, bytes, ins.mnemonic, ins.opStr); + + M680x.OpInfo operands = (M680x.OpInfo) ins.operands; + + if (operands.op.length != 0) { + System.out.printf("\top_count: %d\n", operands.op.length); + for (int c = 0; c < operands.op.length; c++) { + M680x.Operand i = (M680x.Operand) operands.op[c]; + if (i.type == M680X_OP_REGISTER) { + String comment = ""; + if ((c == 0 && ((operands.flags & M680X_FIRST_OP_IN_MNEM) != 0)) || + (c == 1 && ((operands.flags & M680X_SECOND_OP_IN_MNEM) != 0))) + comment = " (in mnemonic)"; + System.out.printf("\t\toperands[%d].type: REGISTER = %s%s\n", c, ins.regName(i.value.reg), comment); + } + if (i.type == M680X_OP_CONSTANT) + System.out.printf("\t\toperands[%d].type: CONSTANT = %d\n", c, i.value.const_val); + if (i.type == M680X_OP_IMMEDIATE) + System.out.printf("\t\toperands[%d].type: IMMEDIATE = #%d\n", c, i.value.imm); + if (i.type == M680X_OP_DIRECT) + System.out.printf("\t\toperands[%d].type: DIRECT = 0x%02X\n", c, i.value.direct_addr); + if (i.type == M680X_OP_EXTENDED) + System.out.printf("\t\toperands[%d].type: EXTENDED %s = 0x%04X\n", c, + i.value.ext.indirect != 0 ? "INDIRECT" : "", i.value.ext.address); + if (i.type == M680X_OP_RELATIVE) + System.out.printf("\t\toperands[%d].type: RELATIVE = 0x%04X\n", c, i.value.rel.address ); + if (i.type == M680X_OP_INDEXED) { + System.out.printf("\t\toperands[%d].type: INDEXED%s\n", c, + (i.value.idx.flags & M680X_IDX_INDIRECT) != 0 ? " INDIRECT" : ""); + if (i.value.idx.base_reg != M680X_REG_INVALID) { + String regName = ins.regName(i.value.idx.base_reg); + if (regName != null) + System.out.printf("\t\t\tbase register: %s\n", regName); + } + if (i.value.idx.offset_reg != M680X_REG_INVALID) { + String regName = ins.regName(i.value.idx.offset_reg); + if (regName != null) + System.out.printf("\t\t\toffset register: %s\n", regName); + } + if ((i.value.idx.offset_bits != 0) && + (i.value.idx.offset_reg == M680X_REG_INVALID) && + (i.value.idx.inc_dec == 0)) { + System.out.printf("\t\t\toffset: %d\n", i.value.idx.offset); + if (i.value.idx.base_reg == M680X_REG_PC) + System.out.printf("\t\t\toffset address: 0x%04X\n", i.value.idx.offset_addr); + System.out.printf("\t\t\toffset bits: %d\n", i.value.idx.offset_bits); + } + if (i.value.idx.inc_dec != 0) { + String post_pre = + (i.value.idx.flags & M680X_IDX_POST_INC_DEC) != 0 ? + "post" : "pre"; + String inc_dec = + i.value.idx.inc_dec > 0 ? "increment" : "decrement"; + + System.out.printf("\t\t\t%s %s: %d\n", post_pre, inc_dec, + Math.abs(i.value.idx.inc_dec)); + } + } + if (i.size != 0) + System.out.printf("\t\t\tsize: %d\n", i.size); + if (i.access != Capstone.CS_AC_INVALID) + System.out.printf("\t\t\taccess: %s\n", sAccess[i.access]); + } + } + + if (ins.regsRead.length > 0) { + System.out.printf("\tRegisters read:"); + for (int c = 0; c < ins.regsRead.length; c++) { + System.out.printf(" %s", ins.regName(ins.regsRead[c])); + } + System.out.printf("\n"); + } + + if (ins.regsWrite.length > 0) { + System.out.printf("\tRegisters modified:"); + for (int c = 0; c < ins.regsWrite.length; c++) { + System.out.printf(" %s", ins.regName(ins.regsWrite[c])); + } + System.out.printf("\n"); + } + + if (ins.groups.length > 0) + System.out.printf("\tgroups_count: %d\n", ins.groups.length); + } + + public static void main(String argv[]) { + + final TestBasic.platform[] all_tests = { + new TestBasic.platform(Capstone.CS_ARCH_M680X, + Capstone.CS_MODE_M680X_6301, + hexString2Byte(HD6301_CODE), "M680X_HD6301"), + new TestBasic.platform(Capstone.CS_ARCH_M680X, + Capstone.CS_MODE_M680X_6309, + hexString2Byte(HD6309_CODE), "M680X_HD6309"), + new TestBasic.platform(Capstone.CS_ARCH_M680X, + Capstone.CS_MODE_M680X_6800, + hexString2Byte(M6800_CODE), "M680X_M6800"), + new TestBasic.platform(Capstone.CS_ARCH_M680X, + Capstone.CS_MODE_M680X_6801, + hexString2Byte(M6801_CODE), "M680X_M6801"), + new TestBasic.platform(Capstone.CS_ARCH_M680X, + Capstone.CS_MODE_M680X_6805, + hexString2Byte(M6805_CODE), "M680X_M68HC05"), + new TestBasic.platform(Capstone.CS_ARCH_M680X, + Capstone.CS_MODE_M680X_6808, + hexString2Byte(M6808_CODE), "M680X_M68HC08"), + new TestBasic.platform(Capstone.CS_ARCH_M680X, + Capstone.CS_MODE_M680X_6809, + hexString2Byte(M6809_CODE), "M680X_M6809"), + new TestBasic.platform(Capstone.CS_ARCH_M680X, + Capstone.CS_MODE_M680X_6811, + hexString2Byte(M6811_CODE), "M680X_M68HC11"), + new TestBasic.platform(Capstone.CS_ARCH_M680X, + Capstone.CS_MODE_M680X_CPU12, + hexString2Byte(CPU12_CODE), "M680X_CPU12"), + new TestBasic.platform(Capstone.CS_ARCH_M680X, + Capstone.CS_MODE_M680X_HCS08, + hexString2Byte(HCS08_CODE), "M680X_HCS08"), + }; + + for (int i=0; i 2017 */ + +package capstone; + +import com.sun.jna.Structure; +import com.sun.jna.Union; + +import java.util.List; +import java.util.Arrays; + +import static capstone.M680x_const.*; + +public class M680x { + + public static class OpIndexed extends Structure { + public int base_reg; + public int offset_reg; + public short offset; + public short offset_addr; + public byte offset_bits; + public byte inc_dec; + public byte flags; + + @Override + public List getFieldOrder() { + return Arrays.asList("base_reg", "offset_reg", "offset", "offset_addr", "offset_bits", "inc_dec", "flags"); + } + } + + public static class OpRelative extends Structure { + public short address; + public short offset; + + @Override + public List getFieldOrder() { + return Arrays.asList("address", "offset"); + } + } + + public static class OpExtended extends Structure { + public short address; + public byte indirect; + + @Override + public List getFieldOrder() { + return Arrays.asList("address", "indirect"); + } + } + + public static class OpValue extends Union { + public int imm; + public int reg; + public OpIndexed idx; + public OpRelative rel; + public OpExtended ext; + public byte direct_addr; + public byte const_val; + + @Override + public List getFieldOrder() { + return Arrays.asList("imm", "reg", "idx", "rel", "ext", "direct_addr", "const_val"); + } + } + + public static class Operand extends Structure { + public int type; + public OpValue value; + public byte size; + public byte access; + + public void read() { + readField("type"); + if (type == M680X_OP_IMMEDIATE) + value.setType(Integer.TYPE); + if (type == M680X_OP_REGISTER) + value.setType(Integer.TYPE); + if (type == M680X_OP_INDEXED) + value.setType(OpIndexed.class); + if (type == M680X_OP_RELATIVE) + value.setType(OpRelative.class); + if (type == M680X_OP_EXTENDED) + value.setType(OpExtended.class); + if (type == M680X_OP_DIRECT) + value.setType(Integer.TYPE); + if (type == M680X_OP_INVALID) + return; + readField("value"); + readField("size"); + readField("access"); + } + + @Override + public List getFieldOrder() { + return Arrays.asList("type", "value", "size", "access"); + } + } + + public static class UnionOpInfo extends Capstone.UnionOpInfo { + public byte flags; + public byte op_count; + + public Operand [] op; + + public UnionOpInfo() { + op = new Operand[9]; + } + + public void read() { + readField("flags"); + readField("op_count"); + op = new Operand[op_count]; + if (op_count != 0) + readField("op"); + } + + @Override + public List getFieldOrder() { + return Arrays.asList("flags", "op_count", "op"); + } + } + + public static class OpInfo extends Capstone.OpInfo { + public byte flags; + public Operand [] op = null; + + public OpInfo(UnionOpInfo op_info) { + flags = op_info.flags; + op = op_info.op; + } + } +} diff --git a/bindings/java/capstone/M680x_const.java b/bindings/java/capstone/M680x_const.java new file mode 100644 index 0000000000..69057d95e5 --- /dev/null +++ b/bindings/java/capstone/M680x_const.java @@ -0,0 +1,439 @@ +// For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT +package capstone; + +public class M680x_const { + public static final int M680X_OPERAND_COUNT = 9; + + // M680X registers and special registers + + public static final int M680X_REG_INVALID = 0; + public static final int M680X_REG_A = 1; + public static final int M680X_REG_B = 2; + public static final int M680X_REG_E = 3; + public static final int M680X_REG_F = 4; + public static final int M680X_REG_0 = 5; + public static final int M680X_REG_D = 6; + public static final int M680X_REG_W = 7; + public static final int M680X_REG_CC = 8; + public static final int M680X_REG_DP = 9; + public static final int M680X_REG_MD = 10; + public static final int M680X_REG_HX = 11; + public static final int M680X_REG_H = 12; + public static final int M680X_REG_X = 13; + public static final int M680X_REG_Y = 14; + public static final int M680X_REG_S = 15; + public static final int M680X_REG_U = 16; + public static final int M680X_REG_V = 17; + public static final int M680X_REG_Q = 18; + public static final int M680X_REG_PC = 19; + public static final int M680X_REG_TMP2 = 20; + public static final int M680X_REG_TMP3 = 21; + public static final int M680X_REG_ENDING = 22; + + // Operand type for instruction's operands + + public static final int M680X_OP_INVALID = 0; + public static final int M680X_OP_REGISTER = 1; + public static final int M680X_OP_IMMEDIATE = 2; + public static final int M680X_OP_INDEXED = 3; + public static final int M680X_OP_EXTENDED = 4; + public static final int M680X_OP_DIRECT = 5; + public static final int M680X_OP_RELATIVE = 6; + public static final int M680X_OP_CONSTANT = 7; + + // Supported bit values for mem.idx.offset_bits + + public static final int M680X_OFFSET_NONE = 0; + public static final int M680X_OFFSET_BITS_5 = 5; + public static final int M680X_OFFSET_BITS_8 = 8; + public static final int M680X_OFFSET_BITS_9 = 9; + public static final int M680X_OFFSET_BITS_16 = 16; + + // Supported bit flags for mem.idx.flags + + // These flags can be comined + public static final int M680X_IDX_INDIRECT = 1; + public static final int M680X_IDX_NO_COMMA = 2; + public static final int M680X_IDX_POST_INC_DEC = 4; + + // Group of M680X instructions + + public static final int M680X_GRP_INVALID = 0; + + // Generic groups + public static final int M680X_GRP_JUMP = 1; + public static final int M680X_GRP_CALL = 2; + public static final int M680X_GRP_RET = 3; + public static final int M680X_GRP_INT = 4; + public static final int M680X_GRP_IRET = 5; + public static final int M680X_GRP_PRIV = 6; + public static final int M680X_GRP_BRAREL = 7; + + // Architecture-specific groups + public static final int M680X_GRP_ENDING = 8; + + // M680X instruction flags: + public static final int M680X_FIRST_OP_IN_MNEM = 1; + public static final int M680X_SECOND_OP_IN_MNEM = 2; + + // M680X instruction IDs + + public static final int M680X_INS_INVLD = 0; + public static final int M680X_INS_ABA = 1; + public static final int M680X_INS_ABX = 2; + public static final int M680X_INS_ABY = 3; + public static final int M680X_INS_ADC = 4; + public static final int M680X_INS_ADCA = 5; + public static final int M680X_INS_ADCB = 6; + public static final int M680X_INS_ADCD = 7; + public static final int M680X_INS_ADCR = 8; + public static final int M680X_INS_ADD = 9; + public static final int M680X_INS_ADDA = 10; + public static final int M680X_INS_ADDB = 11; + public static final int M680X_INS_ADDD = 12; + public static final int M680X_INS_ADDE = 13; + public static final int M680X_INS_ADDF = 14; + public static final int M680X_INS_ADDR = 15; + public static final int M680X_INS_ADDW = 16; + public static final int M680X_INS_AIM = 17; + public static final int M680X_INS_AIS = 18; + public static final int M680X_INS_AIX = 19; + public static final int M680X_INS_AND = 20; + public static final int M680X_INS_ANDA = 21; + public static final int M680X_INS_ANDB = 22; + public static final int M680X_INS_ANDCC = 23; + public static final int M680X_INS_ANDD = 24; + public static final int M680X_INS_ANDR = 25; + public static final int M680X_INS_ASL = 26; + public static final int M680X_INS_ASLA = 27; + public static final int M680X_INS_ASLB = 28; + public static final int M680X_INS_ASLD = 29; + public static final int M680X_INS_ASR = 30; + public static final int M680X_INS_ASRA = 31; + public static final int M680X_INS_ASRB = 32; + public static final int M680X_INS_ASRD = 33; + public static final int M680X_INS_ASRX = 34; + public static final int M680X_INS_BAND = 35; + public static final int M680X_INS_BCC = 36; + public static final int M680X_INS_BCLR = 37; + public static final int M680X_INS_BCS = 38; + public static final int M680X_INS_BEOR = 39; + public static final int M680X_INS_BEQ = 40; + public static final int M680X_INS_BGE = 41; + public static final int M680X_INS_BGND = 42; + public static final int M680X_INS_BGT = 43; + public static final int M680X_INS_BHCC = 44; + public static final int M680X_INS_BHCS = 45; + public static final int M680X_INS_BHI = 46; + public static final int M680X_INS_BIAND = 47; + public static final int M680X_INS_BIEOR = 48; + public static final int M680X_INS_BIH = 49; + public static final int M680X_INS_BIL = 50; + public static final int M680X_INS_BIOR = 51; + public static final int M680X_INS_BIT = 52; + public static final int M680X_INS_BITA = 53; + public static final int M680X_INS_BITB = 54; + public static final int M680X_INS_BITD = 55; + public static final int M680X_INS_BITMD = 56; + public static final int M680X_INS_BLE = 57; + public static final int M680X_INS_BLS = 58; + public static final int M680X_INS_BLT = 59; + public static final int M680X_INS_BMC = 60; + public static final int M680X_INS_BMI = 61; + public static final int M680X_INS_BMS = 62; + public static final int M680X_INS_BNE = 63; + public static final int M680X_INS_BOR = 64; + public static final int M680X_INS_BPL = 65; + public static final int M680X_INS_BRCLR = 66; + public static final int M680X_INS_BRSET = 67; + public static final int M680X_INS_BRA = 68; + public static final int M680X_INS_BRN = 69; + public static final int M680X_INS_BSET = 70; + public static final int M680X_INS_BSR = 71; + public static final int M680X_INS_BVC = 72; + public static final int M680X_INS_BVS = 73; + public static final int M680X_INS_CALL = 74; + public static final int M680X_INS_CBA = 75; + public static final int M680X_INS_CBEQ = 76; + public static final int M680X_INS_CBEQA = 77; + public static final int M680X_INS_CBEQX = 78; + public static final int M680X_INS_CLC = 79; + public static final int M680X_INS_CLI = 80; + public static final int M680X_INS_CLR = 81; + public static final int M680X_INS_CLRA = 82; + public static final int M680X_INS_CLRB = 83; + public static final int M680X_INS_CLRD = 84; + public static final int M680X_INS_CLRE = 85; + public static final int M680X_INS_CLRF = 86; + public static final int M680X_INS_CLRH = 87; + public static final int M680X_INS_CLRW = 88; + public static final int M680X_INS_CLRX = 89; + public static final int M680X_INS_CLV = 90; + public static final int M680X_INS_CMP = 91; + public static final int M680X_INS_CMPA = 92; + public static final int M680X_INS_CMPB = 93; + public static final int M680X_INS_CMPD = 94; + public static final int M680X_INS_CMPE = 95; + public static final int M680X_INS_CMPF = 96; + public static final int M680X_INS_CMPR = 97; + public static final int M680X_INS_CMPS = 98; + public static final int M680X_INS_CMPU = 99; + public static final int M680X_INS_CMPW = 100; + public static final int M680X_INS_CMPX = 101; + public static final int M680X_INS_CMPY = 102; + public static final int M680X_INS_COM = 103; + public static final int M680X_INS_COMA = 104; + public static final int M680X_INS_COMB = 105; + public static final int M680X_INS_COMD = 106; + public static final int M680X_INS_COME = 107; + public static final int M680X_INS_COMF = 108; + public static final int M680X_INS_COMW = 109; + public static final int M680X_INS_COMX = 110; + public static final int M680X_INS_CPD = 111; + public static final int M680X_INS_CPHX = 112; + public static final int M680X_INS_CPS = 113; + public static final int M680X_INS_CPX = 114; + public static final int M680X_INS_CPY = 115; + public static final int M680X_INS_CWAI = 116; + public static final int M680X_INS_DAA = 117; + public static final int M680X_INS_DBEQ = 118; + public static final int M680X_INS_DBNE = 119; + public static final int M680X_INS_DBNZ = 120; + public static final int M680X_INS_DBNZA = 121; + public static final int M680X_INS_DBNZX = 122; + public static final int M680X_INS_DEC = 123; + public static final int M680X_INS_DECA = 124; + public static final int M680X_INS_DECB = 125; + public static final int M680X_INS_DECD = 126; + public static final int M680X_INS_DECE = 127; + public static final int M680X_INS_DECF = 128; + public static final int M680X_INS_DECW = 129; + public static final int M680X_INS_DECX = 130; + public static final int M680X_INS_DES = 131; + public static final int M680X_INS_DEX = 132; + public static final int M680X_INS_DEY = 133; + public static final int M680X_INS_DIV = 134; + public static final int M680X_INS_DIVD = 135; + public static final int M680X_INS_DIVQ = 136; + public static final int M680X_INS_EDIV = 137; + public static final int M680X_INS_EDIVS = 138; + public static final int M680X_INS_EIM = 139; + public static final int M680X_INS_EMACS = 140; + public static final int M680X_INS_EMAXD = 141; + public static final int M680X_INS_EMAXM = 142; + public static final int M680X_INS_EMIND = 143; + public static final int M680X_INS_EMINM = 144; + public static final int M680X_INS_EMUL = 145; + public static final int M680X_INS_EMULS = 146; + public static final int M680X_INS_EOR = 147; + public static final int M680X_INS_EORA = 148; + public static final int M680X_INS_EORB = 149; + public static final int M680X_INS_EORD = 150; + public static final int M680X_INS_EORR = 151; + public static final int M680X_INS_ETBL = 152; + public static final int M680X_INS_EXG = 153; + public static final int M680X_INS_FDIV = 154; + public static final int M680X_INS_IBEQ = 155; + public static final int M680X_INS_IBNE = 156; + public static final int M680X_INS_IDIV = 157; + public static final int M680X_INS_IDIVS = 158; + public static final int M680X_INS_ILLGL = 159; + public static final int M680X_INS_INC = 160; + public static final int M680X_INS_INCA = 161; + public static final int M680X_INS_INCB = 162; + public static final int M680X_INS_INCD = 163; + public static final int M680X_INS_INCE = 164; + public static final int M680X_INS_INCF = 165; + public static final int M680X_INS_INCW = 166; + public static final int M680X_INS_INCX = 167; + public static final int M680X_INS_INS = 168; + public static final int M680X_INS_INX = 169; + public static final int M680X_INS_INY = 170; + public static final int M680X_INS_JMP = 171; + public static final int M680X_INS_JSR = 172; + public static final int M680X_INS_LBCC = 173; + public static final int M680X_INS_LBCS = 174; + public static final int M680X_INS_LBEQ = 175; + public static final int M680X_INS_LBGE = 176; + public static final int M680X_INS_LBGT = 177; + public static final int M680X_INS_LBHI = 178; + public static final int M680X_INS_LBLE = 179; + public static final int M680X_INS_LBLS = 180; + public static final int M680X_INS_LBLT = 181; + public static final int M680X_INS_LBMI = 182; + public static final int M680X_INS_LBNE = 183; + public static final int M680X_INS_LBPL = 184; + public static final int M680X_INS_LBRA = 185; + public static final int M680X_INS_LBRN = 186; + public static final int M680X_INS_LBSR = 187; + public static final int M680X_INS_LBVC = 188; + public static final int M680X_INS_LBVS = 189; + public static final int M680X_INS_LDA = 190; + public static final int M680X_INS_LDAA = 191; + public static final int M680X_INS_LDAB = 192; + public static final int M680X_INS_LDB = 193; + public static final int M680X_INS_LDBT = 194; + public static final int M680X_INS_LDD = 195; + public static final int M680X_INS_LDE = 196; + public static final int M680X_INS_LDF = 197; + public static final int M680X_INS_LDHX = 198; + public static final int M680X_INS_LDMD = 199; + public static final int M680X_INS_LDQ = 200; + public static final int M680X_INS_LDS = 201; + public static final int M680X_INS_LDU = 202; + public static final int M680X_INS_LDW = 203; + public static final int M680X_INS_LDX = 204; + public static final int M680X_INS_LDY = 205; + public static final int M680X_INS_LEAS = 206; + public static final int M680X_INS_LEAU = 207; + public static final int M680X_INS_LEAX = 208; + public static final int M680X_INS_LEAY = 209; + public static final int M680X_INS_LSL = 210; + public static final int M680X_INS_LSLA = 211; + public static final int M680X_INS_LSLB = 212; + public static final int M680X_INS_LSLD = 213; + public static final int M680X_INS_LSLX = 214; + public static final int M680X_INS_LSR = 215; + public static final int M680X_INS_LSRA = 216; + public static final int M680X_INS_LSRB = 217; + public static final int M680X_INS_LSRD = 218; + public static final int M680X_INS_LSRW = 219; + public static final int M680X_INS_LSRX = 220; + public static final int M680X_INS_MAXA = 221; + public static final int M680X_INS_MAXM = 222; + public static final int M680X_INS_MEM = 223; + public static final int M680X_INS_MINA = 224; + public static final int M680X_INS_MINM = 225; + public static final int M680X_INS_MOV = 226; + public static final int M680X_INS_MOVB = 227; + public static final int M680X_INS_MOVW = 228; + public static final int M680X_INS_MUL = 229; + public static final int M680X_INS_MULD = 230; + public static final int M680X_INS_NEG = 231; + public static final int M680X_INS_NEGA = 232; + public static final int M680X_INS_NEGB = 233; + public static final int M680X_INS_NEGD = 234; + public static final int M680X_INS_NEGX = 235; + public static final int M680X_INS_NOP = 236; + public static final int M680X_INS_NSA = 237; + public static final int M680X_INS_OIM = 238; + public static final int M680X_INS_ORA = 239; + public static final int M680X_INS_ORAA = 240; + public static final int M680X_INS_ORAB = 241; + public static final int M680X_INS_ORB = 242; + public static final int M680X_INS_ORCC = 243; + public static final int M680X_INS_ORD = 244; + public static final int M680X_INS_ORR = 245; + public static final int M680X_INS_PSHA = 246; + public static final int M680X_INS_PSHB = 247; + public static final int M680X_INS_PSHC = 248; + public static final int M680X_INS_PSHD = 249; + public static final int M680X_INS_PSHH = 250; + public static final int M680X_INS_PSHS = 251; + public static final int M680X_INS_PSHSW = 252; + public static final int M680X_INS_PSHU = 253; + public static final int M680X_INS_PSHUW = 254; + public static final int M680X_INS_PSHX = 255; + public static final int M680X_INS_PSHY = 256; + public static final int M680X_INS_PULA = 257; + public static final int M680X_INS_PULB = 258; + public static final int M680X_INS_PULC = 259; + public static final int M680X_INS_PULD = 260; + public static final int M680X_INS_PULH = 261; + public static final int M680X_INS_PULS = 262; + public static final int M680X_INS_PULSW = 263; + public static final int M680X_INS_PULU = 264; + public static final int M680X_INS_PULUW = 265; + public static final int M680X_INS_PULX = 266; + public static final int M680X_INS_PULY = 267; + public static final int M680X_INS_REV = 268; + public static final int M680X_INS_REVW = 269; + public static final int M680X_INS_ROL = 270; + public static final int M680X_INS_ROLA = 271; + public static final int M680X_INS_ROLB = 272; + public static final int M680X_INS_ROLD = 273; + public static final int M680X_INS_ROLW = 274; + public static final int M680X_INS_ROLX = 275; + public static final int M680X_INS_ROR = 276; + public static final int M680X_INS_RORA = 277; + public static final int M680X_INS_RORB = 278; + public static final int M680X_INS_RORD = 279; + public static final int M680X_INS_RORW = 280; + public static final int M680X_INS_RORX = 281; + public static final int M680X_INS_RSP = 282; + public static final int M680X_INS_RTC = 283; + public static final int M680X_INS_RTI = 284; + public static final int M680X_INS_RTS = 285; + public static final int M680X_INS_SBA = 286; + public static final int M680X_INS_SBC = 287; + public static final int M680X_INS_SBCA = 288; + public static final int M680X_INS_SBCB = 289; + public static final int M680X_INS_SBCD = 290; + public static final int M680X_INS_SBCR = 291; + public static final int M680X_INS_SEC = 292; + public static final int M680X_INS_SEI = 293; + public static final int M680X_INS_SEV = 294; + public static final int M680X_INS_SEX = 295; + public static final int M680X_INS_SEXW = 296; + public static final int M680X_INS_SLP = 297; + public static final int M680X_INS_STA = 298; + public static final int M680X_INS_STAA = 299; + public static final int M680X_INS_STAB = 300; + public static final int M680X_INS_STB = 301; + public static final int M680X_INS_STBT = 302; + public static final int M680X_INS_STD = 303; + public static final int M680X_INS_STE = 304; + public static final int M680X_INS_STF = 305; + public static final int M680X_INS_STOP = 306; + public static final int M680X_INS_STHX = 307; + public static final int M680X_INS_STQ = 308; + public static final int M680X_INS_STS = 309; + public static final int M680X_INS_STU = 310; + public static final int M680X_INS_STW = 311; + public static final int M680X_INS_STX = 312; + public static final int M680X_INS_STY = 313; + public static final int M680X_INS_SUB = 314; + public static final int M680X_INS_SUBA = 315; + public static final int M680X_INS_SUBB = 316; + public static final int M680X_INS_SUBD = 317; + public static final int M680X_INS_SUBE = 318; + public static final int M680X_INS_SUBF = 319; + public static final int M680X_INS_SUBR = 320; + public static final int M680X_INS_SUBW = 321; + public static final int M680X_INS_SWI = 322; + public static final int M680X_INS_SWI2 = 323; + public static final int M680X_INS_SWI3 = 324; + public static final int M680X_INS_SYNC = 325; + public static final int M680X_INS_TAB = 326; + public static final int M680X_INS_TAP = 327; + public static final int M680X_INS_TAX = 328; + public static final int M680X_INS_TBA = 329; + public static final int M680X_INS_TBEQ = 330; + public static final int M680X_INS_TBL = 331; + public static final int M680X_INS_TBNE = 332; + public static final int M680X_INS_TEST = 333; + public static final int M680X_INS_TFM = 334; + public static final int M680X_INS_TFR = 335; + public static final int M680X_INS_TIM = 336; + public static final int M680X_INS_TPA = 337; + public static final int M680X_INS_TST = 338; + public static final int M680X_INS_TSTA = 339; + public static final int M680X_INS_TSTB = 340; + public static final int M680X_INS_TSTD = 341; + public static final int M680X_INS_TSTE = 342; + public static final int M680X_INS_TSTF = 343; + public static final int M680X_INS_TSTW = 344; + public static final int M680X_INS_TSTX = 345; + public static final int M680X_INS_TSX = 346; + public static final int M680X_INS_TSY = 347; + public static final int M680X_INS_TXA = 348; + public static final int M680X_INS_TXS = 349; + public static final int M680X_INS_TYS = 350; + public static final int M680X_INS_WAI = 351; + public static final int M680X_INS_WAIT = 352; + public static final int M680X_INS_WAV = 353; + public static final int M680X_INS_WAVR = 354; + public static final int M680X_INS_XGDX = 355; + public static final int M680X_INS_XGDY = 356; + public static final int M680X_INS_ENDING = 357; +} \ No newline at end of file diff --git a/bindings/java/run.sh b/bindings/java/run.sh index 8dcc1851aa..1430199d46 100755 --- a/bindings/java/run.sh +++ b/bindings/java/run.sh @@ -21,5 +21,6 @@ case "$1" in "ppc") java -classpath ${JNA}:. TestPpc ;; "sparc") java -classpath ${JNA}:. TestSparc ;; "systemz") java -classpath ${JNA}:. TestSystemz ;; - * ) echo "Usage: ./run.sh [arm|arm64|mips|ppc|sparc|systemz|x86]"; exit 1;; + "m680x") java -classpath ${JNA}:. TestM680x ;; + * ) echo "Usage: ./run.sh [arm|arm64|m680x|mips|ppc|sparc|systemz|x86]"; exit 1;; esac diff --git a/bindings/ocaml/Makefile b/bindings/ocaml/Makefile index 45c6dbce9b..6e9208aa77 100644 --- a/bindings/ocaml/Makefile +++ b/bindings/ocaml/Makefile @@ -4,7 +4,7 @@ LIB = capstone FLAGS = '-Wall -Wextra -Wwrite-strings' -all: arm_const.cmxa arm64_const.cmxa mips_const.cmxa ppc_const.cmxa sparc_const.cmxa sysz_const.cmxa x86_const.cmxa xcore_const.cmxa arm.cmxa arm64.cmxa mips.cmxa ppc.cmxa x86.cmxa sparc.cmxa systemz.cmxa xcore.cmxa capstone.cmxa test_basic.cmx test_detail.cmx test_x86.cmx test_arm.cmx test_arm64.cmx test_mips.cmx test_ppc.cmx test_sparc.cmx test_systemz.cmx test_xcore.cmx ocaml.o +all: arm_const.cmxa arm64_const.cmxa m680x_const.cmxa mips_const.cmxa ppc_const.cmxa sparc_const.cmxa sysz_const.cmxa x86_const.cmxa xcore_const.cmxa arm.cmxa arm64.cmxa m680x.cmxa mips.cmxa ppc.cmxa x86.cmxa sparc.cmxa systemz.cmxa xcore.cmxa capstone.cmxa test_basic.cmx test_detail.cmx test_x86.cmx test_arm.cmx test_arm64.cmx test_mips.cmx test_ppc.cmx test_sparc.cmx test_systemz.cmx test_xcore.cmx test_m680x.cmx ocaml.o ocamlopt -o test_basic -ccopt $(FLAGS) ocaml.o capstone.cmx test_basic.cmx -cclib -l$(LIB) ocamlopt -o test_detail -ccopt $(FLAGS) capstone.cmx ocaml.o test_detail.cmx -cclib -l$(LIB) ocamlopt -o test_x86 -ccopt $(FLAGS) capstone.cmx ocaml.o x86.cmx x86_const.cmx test_x86.cmx -cclib -l$(LIB) @@ -15,6 +15,7 @@ all: arm_const.cmxa arm64_const.cmxa mips_const.cmxa ppc_const.cmxa sparc_const. ocamlopt -o test_sparc -ccopt $(FLAGS) capstone.cmx ocaml.o sparc.cmx sparc_const.cmx test_sparc.cmx -cclib -l$(LIB) ocamlopt -o test_systemz -ccopt $(FLAGS) capstone.cmx ocaml.o systemz.cmx sysz_const.cmx test_systemz.cmx -cclib -l$(LIB) ocamlopt -o test_xcore -ccopt $(FLAGS) capstone.cmx ocaml.o xcore.cmx xcore_const.cmx test_xcore.cmx -cclib -l$(LIB) + ocamlopt -o test_m680x -ccopt $(FLAGS) capstone.cmx ocaml.o m680x.cmx m680x_const.cmx test_m680x.cmx -cclib -l$(LIB) test_basic.cmx: test_basic.ml @@ -47,6 +48,9 @@ test_systemz.cmx: test_systemz.ml test_xcore.cmx: test_xcore.ml ocamlopt -ccopt $(FLAGS) -c $< -cclib -l$(LIB) +test_m680x.cmx: test_m680x.ml + ocamlopt -ccopt $(FLAGS) -c $< -cclib -l$(LIB) + ocaml.o: ocaml.c ocamlc -ccopt $(FLAGS) -c $< @@ -134,6 +138,30 @@ arm64_const.cmx: arm64_const.ml arm64_const.cmi arm64_const.cmxa: arm64_const.cmx ocamlopt -ccopt $(FLAGS) -a -o $@ $< +m680x.mli: m680x.ml + ocamlc -ccopt $(FLAGS) -i $< > $@ + +m680x.cmi: m680x.mli + ocamlc -ccopt $(FLAGS) -c $< + +m680x.cmx: m680x.ml m680x.cmi + ocamlopt -ccopt $(FLAGS) -c $< + +m680x.cmxa: m680x.cmx + ocamlopt -ccopt $(FLAGS) -a -o $@ $< + +m680x_const.mli: m680x_const.ml + ocamlc -ccopt $(FLAGS) -i $< > $@ + +m680x_const.cmi: m680x_const.mli + ocamlc -ccopt $(FLAGS) -c $< + +m680x_const.cmx: m680x_const.ml m680x_const.cmi + ocamlopt -ccopt $(FLAGS) -c $< + +m680x_const.cmxa: m680x_const.cmx + ocamlopt -ccopt $(FLAGS) -a -o $@ $< + mips.mli: mips.ml ocamlc -ccopt $(FLAGS) -i $< > $@ @@ -255,12 +283,12 @@ xcore_const.cmxa: xcore_const.cmx ocamlopt -ccopt $(FLAGS) -a -o $@ $< clean: - rm -f *.[oa] *.so *.cm[ixoa] *.cmxa *.mli test_basic test_detail test_x86 test_arm test_arm64 test_mips test_ppc test_sparc test_systemz test_xcore + rm -f *.[oa] *.so *.cm[ixoa] *.cmxa *.mli test_basic test_detail test_x86 test_arm test_arm64 test_mips test_ppc test_sparc test_systemz test_xcore test_m680x gen_const: cd .. && python const_generator.py ocaml -TESTS = test_basic test_detail test_arm test_arm64 test_mips test_ppc +TESTS = test_basic test_detail test_arm test_arm64 test_m680x test_mips test_ppc TESTS += test_sparc test_systemz test_x86 test_xcore check: @for t in $(TESTS); do \ diff --git a/bindings/ocaml/capstone.ml b/bindings/ocaml/capstone.ml index a81b90dd64..9d7a8dbc30 100644 --- a/bindings/ocaml/capstone.ml +++ b/bindings/ocaml/capstone.ml @@ -9,6 +9,7 @@ open X86 open Sparc open Systemz open Xcore +open M680x open Printf (* debug *) (* Hardware architectures *) @@ -21,6 +22,9 @@ type arch = | CS_ARCH_SPARC | CS_ARCH_SYSZ | CS_ARCH_XCORE + | CS_ARCH_M68K + | CS_ARCH_TMS320C64X + | CS_ARCH_M680X (* Hardware modes *) type mode = @@ -40,7 +44,17 @@ type mode = | CS_MODE_BIG_ENDIAN (* big-endian mode *) | CS_MODE_MIPS32 (* Mips32 mode (for Mips) *) | CS_MODE_MIPS64 (* Mips64 mode (for Mips) *) - | CS_MODE_QPX (* Quad Processing eXtensions mode (PowerPC) *) + | CS_MODE_QPX (* Quad Processing eXtensions mode (PowerPC) *) + | CS_MODE_M680X_6301 (* M680X Hitachi 6301,6303 mode *) + | CS_MODE_M680X_6309 (* M680X Hitachi 6309 mode *) + | CS_MODE_M680X_6800 (* M680X Motorola 6800,6802 mode *) + | CS_MODE_M680X_6801 (* M680X Motorola 6801,6803 mode *) + | CS_MODE_M680X_6805 (* M680X Motorola 6805 mode *) + | CS_MODE_M680X_6808 (* M680X Motorola 6808 mode *) + | CS_MODE_M680X_6809 (* M680X Motorola 6809 mode *) + | CS_MODE_M680X_6811 (* M680X Motorola/Freescale 68HC11 mode *) + | CS_MODE_M680X_CPU12 (* M680X Motorola/Freescale/NXP CPU12 mode *) + | CS_MODE_M680X_HCS08 (* M680X Freescale HCS08 mode *) @@ -93,6 +107,7 @@ type cs_arch = | CS_INFO_SPARC of cs_sparc | CS_INFO_SYSZ of cs_sysz | CS_INFO_XCORE of cs_xcore + | CS_INFO_M680X of cs_m680x type csh = { diff --git a/bindings/ocaml/m680x.ml b/bindings/ocaml/m680x.ml new file mode 100644 index 0000000000..139715db91 --- /dev/null +++ b/bindings/ocaml/m680x.ml @@ -0,0 +1,48 @@ +(* Capstone Disassembly Engine + * M680X Backend by Wolfgang Schwotzer 2017 *) + +open M680x_const + + +(* architecture specific info of instruction *) +type m680x_op_idx = { + base_reg: int; + offset_reg: int; + offset: int; + offset_addr: int; + offset_bits: int; + inc_dec: int; + flags: int; +} + +type m680x_op_rel = { + addr_rel: int; + offset: int; +} + +type m680x_op_ext = { + addr_ext: int; + indirect: bool; +} + +type m680x_op_value = + | M680X_OP_INVALID of int + | M680X_OP_IMMEDIATE of int + | M680X_OP_REGISTER of int + | M680X_OP_INDEXED of m680x_op_idx + | M680X_OP_RELATIVE of m680x_op_rel + | M680X_OP_EXTENDED of m680x_op_ext + | M680X_OP_DIRECT of int + | M680X_OP_CONSTANT of int + +type m680x_op = { + value: m680x_op_value; + size: int; + access: int; +} + +type cs_m680x = { + flags: int; + operands: m680x_op array; +} + diff --git a/bindings/ocaml/m680x_const.ml b/bindings/ocaml/m680x_const.ml new file mode 100644 index 0000000000..696e554e77 --- /dev/null +++ b/bindings/ocaml/m680x_const.ml @@ -0,0 +1,435 @@ +(* For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT [m680x_const.ml] *) +let _M680X_OPERAND_COUNT = 9;; + +(* M680X registers and special registers *) + +let _M680X_REG_INVALID = 0;; +let _M680X_REG_A = 1;; +let _M680X_REG_B = 2;; +let _M680X_REG_E = 3;; +let _M680X_REG_F = 4;; +let _M680X_REG_0 = 5;; +let _M680X_REG_D = 6;; +let _M680X_REG_W = 7;; +let _M680X_REG_CC = 8;; +let _M680X_REG_DP = 9;; +let _M680X_REG_MD = 10;; +let _M680X_REG_HX = 11;; +let _M680X_REG_H = 12;; +let _M680X_REG_X = 13;; +let _M680X_REG_Y = 14;; +let _M680X_REG_S = 15;; +let _M680X_REG_U = 16;; +let _M680X_REG_V = 17;; +let _M680X_REG_Q = 18;; +let _M680X_REG_PC = 19;; +let _M680X_REG_TMP2 = 20;; +let _M680X_REG_TMP3 = 21;; +let _M680X_REG_ENDING = 22;; + +(* Operand type for instruction's operands *) + +let _M680X_OP_INVALID = 0;; +let _M680X_OP_REGISTER = 1;; +let _M680X_OP_IMMEDIATE = 2;; +let _M680X_OP_INDEXED = 3;; +let _M680X_OP_EXTENDED = 4;; +let _M680X_OP_DIRECT = 5;; +let _M680X_OP_RELATIVE = 6;; +let _M680X_OP_CONSTANT = 7;; + +(* Supported bit values for mem.idx.offset_bits *) + +let _M680X_OFFSET_NONE = 0;; +let _M680X_OFFSET_BITS_5 = 5;; +let _M680X_OFFSET_BITS_8 = 8;; +let _M680X_OFFSET_BITS_9 = 9;; +let _M680X_OFFSET_BITS_16 = 16;; + +(* Supported bit flags for mem.idx.flags *) + +(* These flags can be comined *) +let _M680X_IDX_INDIRECT = 1;; +let _M680X_IDX_NO_COMMA = 2;; +let _M680X_IDX_POST_INC_DEC = 4;; + +(* Group of M680X instructions *) + +let _M680X_GRP_INVALID = 0;; + +(* Generic groups *) +let _M680X_GRP_JUMP = 1;; +let _M680X_GRP_CALL = 2;; +let _M680X_GRP_RET = 3;; +let _M680X_GRP_INT = 4;; +let _M680X_GRP_IRET = 5;; +let _M680X_GRP_PRIV = 6;; +let _M680X_GRP_BRAREL = 7;; + +(* Architecture-specific groups *) +let _M680X_GRP_ENDING = 8;; + +(* M680X instruction flags: *) +let _M680X_FIRST_OP_IN_MNEM = 1;; +let _M680X_SECOND_OP_IN_MNEM = 2;; + +(* M680X instruction IDs *) + +let _M680X_INS_INVLD = 0;; +let _M680X_INS_ABA = 1;; +let _M680X_INS_ABX = 2;; +let _M680X_INS_ABY = 3;; +let _M680X_INS_ADC = 4;; +let _M680X_INS_ADCA = 5;; +let _M680X_INS_ADCB = 6;; +let _M680X_INS_ADCD = 7;; +let _M680X_INS_ADCR = 8;; +let _M680X_INS_ADD = 9;; +let _M680X_INS_ADDA = 10;; +let _M680X_INS_ADDB = 11;; +let _M680X_INS_ADDD = 12;; +let _M680X_INS_ADDE = 13;; +let _M680X_INS_ADDF = 14;; +let _M680X_INS_ADDR = 15;; +let _M680X_INS_ADDW = 16;; +let _M680X_INS_AIM = 17;; +let _M680X_INS_AIS = 18;; +let _M680X_INS_AIX = 19;; +let _M680X_INS_AND = 20;; +let _M680X_INS_ANDA = 21;; +let _M680X_INS_ANDB = 22;; +let _M680X_INS_ANDCC = 23;; +let _M680X_INS_ANDD = 24;; +let _M680X_INS_ANDR = 25;; +let _M680X_INS_ASL = 26;; +let _M680X_INS_ASLA = 27;; +let _M680X_INS_ASLB = 28;; +let _M680X_INS_ASLD = 29;; +let _M680X_INS_ASR = 30;; +let _M680X_INS_ASRA = 31;; +let _M680X_INS_ASRB = 32;; +let _M680X_INS_ASRD = 33;; +let _M680X_INS_ASRX = 34;; +let _M680X_INS_BAND = 35;; +let _M680X_INS_BCC = 36;; +let _M680X_INS_BCLR = 37;; +let _M680X_INS_BCS = 38;; +let _M680X_INS_BEOR = 39;; +let _M680X_INS_BEQ = 40;; +let _M680X_INS_BGE = 41;; +let _M680X_INS_BGND = 42;; +let _M680X_INS_BGT = 43;; +let _M680X_INS_BHCC = 44;; +let _M680X_INS_BHCS = 45;; +let _M680X_INS_BHI = 46;; +let _M680X_INS_BIAND = 47;; +let _M680X_INS_BIEOR = 48;; +let _M680X_INS_BIH = 49;; +let _M680X_INS_BIL = 50;; +let _M680X_INS_BIOR = 51;; +let _M680X_INS_BIT = 52;; +let _M680X_INS_BITA = 53;; +let _M680X_INS_BITB = 54;; +let _M680X_INS_BITD = 55;; +let _M680X_INS_BITMD = 56;; +let _M680X_INS_BLE = 57;; +let _M680X_INS_BLS = 58;; +let _M680X_INS_BLT = 59;; +let _M680X_INS_BMC = 60;; +let _M680X_INS_BMI = 61;; +let _M680X_INS_BMS = 62;; +let _M680X_INS_BNE = 63;; +let _M680X_INS_BOR = 64;; +let _M680X_INS_BPL = 65;; +let _M680X_INS_BRCLR = 66;; +let _M680X_INS_BRSET = 67;; +let _M680X_INS_BRA = 68;; +let _M680X_INS_BRN = 69;; +let _M680X_INS_BSET = 70;; +let _M680X_INS_BSR = 71;; +let _M680X_INS_BVC = 72;; +let _M680X_INS_BVS = 73;; +let _M680X_INS_CALL = 74;; +let _M680X_INS_CBA = 75;; +let _M680X_INS_CBEQ = 76;; +let _M680X_INS_CBEQA = 77;; +let _M680X_INS_CBEQX = 78;; +let _M680X_INS_CLC = 79;; +let _M680X_INS_CLI = 80;; +let _M680X_INS_CLR = 81;; +let _M680X_INS_CLRA = 82;; +let _M680X_INS_CLRB = 83;; +let _M680X_INS_CLRD = 84;; +let _M680X_INS_CLRE = 85;; +let _M680X_INS_CLRF = 86;; +let _M680X_INS_CLRH = 87;; +let _M680X_INS_CLRW = 88;; +let _M680X_INS_CLRX = 89;; +let _M680X_INS_CLV = 90;; +let _M680X_INS_CMP = 91;; +let _M680X_INS_CMPA = 92;; +let _M680X_INS_CMPB = 93;; +let _M680X_INS_CMPD = 94;; +let _M680X_INS_CMPE = 95;; +let _M680X_INS_CMPF = 96;; +let _M680X_INS_CMPR = 97;; +let _M680X_INS_CMPS = 98;; +let _M680X_INS_CMPU = 99;; +let _M680X_INS_CMPW = 100;; +let _M680X_INS_CMPX = 101;; +let _M680X_INS_CMPY = 102;; +let _M680X_INS_COM = 103;; +let _M680X_INS_COMA = 104;; +let _M680X_INS_COMB = 105;; +let _M680X_INS_COMD = 106;; +let _M680X_INS_COME = 107;; +let _M680X_INS_COMF = 108;; +let _M680X_INS_COMW = 109;; +let _M680X_INS_COMX = 110;; +let _M680X_INS_CPD = 111;; +let _M680X_INS_CPHX = 112;; +let _M680X_INS_CPS = 113;; +let _M680X_INS_CPX = 114;; +let _M680X_INS_CPY = 115;; +let _M680X_INS_CWAI = 116;; +let _M680X_INS_DAA = 117;; +let _M680X_INS_DBEQ = 118;; +let _M680X_INS_DBNE = 119;; +let _M680X_INS_DBNZ = 120;; +let _M680X_INS_DBNZA = 121;; +let _M680X_INS_DBNZX = 122;; +let _M680X_INS_DEC = 123;; +let _M680X_INS_DECA = 124;; +let _M680X_INS_DECB = 125;; +let _M680X_INS_DECD = 126;; +let _M680X_INS_DECE = 127;; +let _M680X_INS_DECF = 128;; +let _M680X_INS_DECW = 129;; +let _M680X_INS_DECX = 130;; +let _M680X_INS_DES = 131;; +let _M680X_INS_DEX = 132;; +let _M680X_INS_DEY = 133;; +let _M680X_INS_DIV = 134;; +let _M680X_INS_DIVD = 135;; +let _M680X_INS_DIVQ = 136;; +let _M680X_INS_EDIV = 137;; +let _M680X_INS_EDIVS = 138;; +let _M680X_INS_EIM = 139;; +let _M680X_INS_EMACS = 140;; +let _M680X_INS_EMAXD = 141;; +let _M680X_INS_EMAXM = 142;; +let _M680X_INS_EMIND = 143;; +let _M680X_INS_EMINM = 144;; +let _M680X_INS_EMUL = 145;; +let _M680X_INS_EMULS = 146;; +let _M680X_INS_EOR = 147;; +let _M680X_INS_EORA = 148;; +let _M680X_INS_EORB = 149;; +let _M680X_INS_EORD = 150;; +let _M680X_INS_EORR = 151;; +let _M680X_INS_ETBL = 152;; +let _M680X_INS_EXG = 153;; +let _M680X_INS_FDIV = 154;; +let _M680X_INS_IBEQ = 155;; +let _M680X_INS_IBNE = 156;; +let _M680X_INS_IDIV = 157;; +let _M680X_INS_IDIVS = 158;; +let _M680X_INS_ILLGL = 159;; +let _M680X_INS_INC = 160;; +let _M680X_INS_INCA = 161;; +let _M680X_INS_INCB = 162;; +let _M680X_INS_INCD = 163;; +let _M680X_INS_INCE = 164;; +let _M680X_INS_INCF = 165;; +let _M680X_INS_INCW = 166;; +let _M680X_INS_INCX = 167;; +let _M680X_INS_INS = 168;; +let _M680X_INS_INX = 169;; +let _M680X_INS_INY = 170;; +let _M680X_INS_JMP = 171;; +let _M680X_INS_JSR = 172;; +let _M680X_INS_LBCC = 173;; +let _M680X_INS_LBCS = 174;; +let _M680X_INS_LBEQ = 175;; +let _M680X_INS_LBGE = 176;; +let _M680X_INS_LBGT = 177;; +let _M680X_INS_LBHI = 178;; +let _M680X_INS_LBLE = 179;; +let _M680X_INS_LBLS = 180;; +let _M680X_INS_LBLT = 181;; +let _M680X_INS_LBMI = 182;; +let _M680X_INS_LBNE = 183;; +let _M680X_INS_LBPL = 184;; +let _M680X_INS_LBRA = 185;; +let _M680X_INS_LBRN = 186;; +let _M680X_INS_LBSR = 187;; +let _M680X_INS_LBVC = 188;; +let _M680X_INS_LBVS = 189;; +let _M680X_INS_LDA = 190;; +let _M680X_INS_LDAA = 191;; +let _M680X_INS_LDAB = 192;; +let _M680X_INS_LDB = 193;; +let _M680X_INS_LDBT = 194;; +let _M680X_INS_LDD = 195;; +let _M680X_INS_LDE = 196;; +let _M680X_INS_LDF = 197;; +let _M680X_INS_LDHX = 198;; +let _M680X_INS_LDMD = 199;; +let _M680X_INS_LDQ = 200;; +let _M680X_INS_LDS = 201;; +let _M680X_INS_LDU = 202;; +let _M680X_INS_LDW = 203;; +let _M680X_INS_LDX = 204;; +let _M680X_INS_LDY = 205;; +let _M680X_INS_LEAS = 206;; +let _M680X_INS_LEAU = 207;; +let _M680X_INS_LEAX = 208;; +let _M680X_INS_LEAY = 209;; +let _M680X_INS_LSL = 210;; +let _M680X_INS_LSLA = 211;; +let _M680X_INS_LSLB = 212;; +let _M680X_INS_LSLD = 213;; +let _M680X_INS_LSLX = 214;; +let _M680X_INS_LSR = 215;; +let _M680X_INS_LSRA = 216;; +let _M680X_INS_LSRB = 217;; +let _M680X_INS_LSRD = 218;; +let _M680X_INS_LSRW = 219;; +let _M680X_INS_LSRX = 220;; +let _M680X_INS_MAXA = 221;; +let _M680X_INS_MAXM = 222;; +let _M680X_INS_MEM = 223;; +let _M680X_INS_MINA = 224;; +let _M680X_INS_MINM = 225;; +let _M680X_INS_MOV = 226;; +let _M680X_INS_MOVB = 227;; +let _M680X_INS_MOVW = 228;; +let _M680X_INS_MUL = 229;; +let _M680X_INS_MULD = 230;; +let _M680X_INS_NEG = 231;; +let _M680X_INS_NEGA = 232;; +let _M680X_INS_NEGB = 233;; +let _M680X_INS_NEGD = 234;; +let _M680X_INS_NEGX = 235;; +let _M680X_INS_NOP = 236;; +let _M680X_INS_NSA = 237;; +let _M680X_INS_OIM = 238;; +let _M680X_INS_ORA = 239;; +let _M680X_INS_ORAA = 240;; +let _M680X_INS_ORAB = 241;; +let _M680X_INS_ORB = 242;; +let _M680X_INS_ORCC = 243;; +let _M680X_INS_ORD = 244;; +let _M680X_INS_ORR = 245;; +let _M680X_INS_PSHA = 246;; +let _M680X_INS_PSHB = 247;; +let _M680X_INS_PSHC = 248;; +let _M680X_INS_PSHD = 249;; +let _M680X_INS_PSHH = 250;; +let _M680X_INS_PSHS = 251;; +let _M680X_INS_PSHSW = 252;; +let _M680X_INS_PSHU = 253;; +let _M680X_INS_PSHUW = 254;; +let _M680X_INS_PSHX = 255;; +let _M680X_INS_PSHY = 256;; +let _M680X_INS_PULA = 257;; +let _M680X_INS_PULB = 258;; +let _M680X_INS_PULC = 259;; +let _M680X_INS_PULD = 260;; +let _M680X_INS_PULH = 261;; +let _M680X_INS_PULS = 262;; +let _M680X_INS_PULSW = 263;; +let _M680X_INS_PULU = 264;; +let _M680X_INS_PULUW = 265;; +let _M680X_INS_PULX = 266;; +let _M680X_INS_PULY = 267;; +let _M680X_INS_REV = 268;; +let _M680X_INS_REVW = 269;; +let _M680X_INS_ROL = 270;; +let _M680X_INS_ROLA = 271;; +let _M680X_INS_ROLB = 272;; +let _M680X_INS_ROLD = 273;; +let _M680X_INS_ROLW = 274;; +let _M680X_INS_ROLX = 275;; +let _M680X_INS_ROR = 276;; +let _M680X_INS_RORA = 277;; +let _M680X_INS_RORB = 278;; +let _M680X_INS_RORD = 279;; +let _M680X_INS_RORW = 280;; +let _M680X_INS_RORX = 281;; +let _M680X_INS_RSP = 282;; +let _M680X_INS_RTC = 283;; +let _M680X_INS_RTI = 284;; +let _M680X_INS_RTS = 285;; +let _M680X_INS_SBA = 286;; +let _M680X_INS_SBC = 287;; +let _M680X_INS_SBCA = 288;; +let _M680X_INS_SBCB = 289;; +let _M680X_INS_SBCD = 290;; +let _M680X_INS_SBCR = 291;; +let _M680X_INS_SEC = 292;; +let _M680X_INS_SEI = 293;; +let _M680X_INS_SEV = 294;; +let _M680X_INS_SEX = 295;; +let _M680X_INS_SEXW = 296;; +let _M680X_INS_SLP = 297;; +let _M680X_INS_STA = 298;; +let _M680X_INS_STAA = 299;; +let _M680X_INS_STAB = 300;; +let _M680X_INS_STB = 301;; +let _M680X_INS_STBT = 302;; +let _M680X_INS_STD = 303;; +let _M680X_INS_STE = 304;; +let _M680X_INS_STF = 305;; +let _M680X_INS_STOP = 306;; +let _M680X_INS_STHX = 307;; +let _M680X_INS_STQ = 308;; +let _M680X_INS_STS = 309;; +let _M680X_INS_STU = 310;; +let _M680X_INS_STW = 311;; +let _M680X_INS_STX = 312;; +let _M680X_INS_STY = 313;; +let _M680X_INS_SUB = 314;; +let _M680X_INS_SUBA = 315;; +let _M680X_INS_SUBB = 316;; +let _M680X_INS_SUBD = 317;; +let _M680X_INS_SUBE = 318;; +let _M680X_INS_SUBF = 319;; +let _M680X_INS_SUBR = 320;; +let _M680X_INS_SUBW = 321;; +let _M680X_INS_SWI = 322;; +let _M680X_INS_SWI2 = 323;; +let _M680X_INS_SWI3 = 324;; +let _M680X_INS_SYNC = 325;; +let _M680X_INS_TAB = 326;; +let _M680X_INS_TAP = 327;; +let _M680X_INS_TAX = 328;; +let _M680X_INS_TBA = 329;; +let _M680X_INS_TBEQ = 330;; +let _M680X_INS_TBL = 331;; +let _M680X_INS_TBNE = 332;; +let _M680X_INS_TEST = 333;; +let _M680X_INS_TFM = 334;; +let _M680X_INS_TFR = 335;; +let _M680X_INS_TIM = 336;; +let _M680X_INS_TPA = 337;; +let _M680X_INS_TST = 338;; +let _M680X_INS_TSTA = 339;; +let _M680X_INS_TSTB = 340;; +let _M680X_INS_TSTD = 341;; +let _M680X_INS_TSTE = 342;; +let _M680X_INS_TSTF = 343;; +let _M680X_INS_TSTW = 344;; +let _M680X_INS_TSTX = 345;; +let _M680X_INS_TSX = 346;; +let _M680X_INS_TSY = 347;; +let _M680X_INS_TXA = 348;; +let _M680X_INS_TXS = 349;; +let _M680X_INS_TYS = 350;; +let _M680X_INS_WAI = 351;; +let _M680X_INS_WAIT = 352;; +let _M680X_INS_WAV = 353;; +let _M680X_INS_WAVR = 354;; +let _M680X_INS_XGDX = 355;; +let _M680X_INS_XGDY = 356;; +let _M680X_INS_ENDING = 357;; diff --git a/bindings/ocaml/ocaml.c b/bindings/ocaml/ocaml.c index 4e26441623..ac95ad26aa 100644 --- a/bindings/ocaml/ocaml.c +++ b/bindings/ocaml/ocaml.c @@ -606,6 +606,79 @@ CAMLprim value _cs_disasm(cs_arch arch, csh handle, const uint8_t * code, size_t break; + case CS_ARCH_M680X: + arch_info = caml_alloc(1, 8); + + op_info_val = caml_alloc(2, 0); // struct cs_m680x + Store_field(op_info_val, 0, Val_int(insn[j-1].detail->m680x.flags)); + + lcount = insn[j-1].detail->m680x.op_count; + if (lcount > 0) { + array = caml_alloc(lcount, 0); + for (i = 0; i < lcount; i++) { + tmp2 = caml_alloc(3, 0); // m680x_op + switch(insn[j-1].detail->m680x.operands[i].type) { + case M680X_OP_IMMEDIATE: + tmp = caml_alloc(1, 1); // imm + Store_field(tmp, 0, Val_int(insn[j-1].detail->m680x.operands[i].imm)); + break; + case M680X_OP_REGISTER: + tmp = caml_alloc(1, 2); // reg + Store_field(tmp, 0, Val_int(insn[j-1].detail->m680x.operands[i].reg)); + break; + case M680X_OP_INDEXED: + tmp = caml_alloc(1, 3); + tmp3 = caml_alloc(7, 0); // m680x_op_idx + Store_field(tmp3, 0, Val_int(insn[j-1].detail->m680x.operands[i].idx.base_reg)); + Store_field(tmp3, 1, Val_int(insn[j-1].detail->m680x.operands[i].idx.offset_reg)); + Store_field(tmp3, 2, Val_int(insn[j-1].detail->m680x.operands[i].idx.offset)); + Store_field(tmp3, 3, Val_int(insn[j-1].detail->m680x.operands[i].idx.offset_addr)); + Store_field(tmp3, 4, Val_int(insn[j-1].detail->m680x.operands[i].idx.offset_bits)); + Store_field(tmp3, 5, Val_int(insn[j-1].detail->m680x.operands[i].idx.inc_dec)); + Store_field(tmp3, 6, Val_int(insn[j-1].detail->m680x.operands[i].idx.flags)); + Store_field(tmp, 0, tmp3); + break; + case M680X_OP_RELATIVE: + tmp = caml_alloc(1, 4); + tmp3 = caml_alloc(2, 0); // m680x_op_rel + Store_field(tmp3, 0, Val_int(insn[j-1].detail->m680x.operands[i].rel.address)); + Store_field(tmp3, 1, Val_int(insn[j-1].detail->m680x.operands[i].rel.offset)); + Store_field(tmp, 0, tmp3); + break; + case M680X_OP_EXTENDED: + tmp = caml_alloc(1, 5); + tmp3 = caml_alloc(2, 0); // m680x_op_ext + Store_field(tmp3, 0, Val_int(insn[j-1].detail->m680x.operands[i].ext.address)); + Store_field(tmp3, 1, Val_bool(insn[j-1].detail->m680x.operands[i].ext.indirect)); + Store_field(tmp, 0, tmp3); + break; + case M680X_OP_DIRECT: + tmp = caml_alloc(1, 6); // direct_addr + Store_field(tmp, 0, Val_int(insn[j-1].detail->m680x.operands[i].direct_addr)); + break; + case M680X_OP_CONSTANT: + tmp = caml_alloc(1, 7); // const_val + Store_field(tmp, 0, Val_int(insn[j-1].detail->m680x.operands[i].const_val)); + break; + default: break; + } + Store_field(tmp2, 0, tmp); // add union + Store_field(tmp2, 1, Val_int(insn[j-1].detail->m680x.operands[i].size)); + Store_field(tmp2, 2, Val_int(insn[j-1].detail->m680x.operands[i].access)); + Store_field(array, i, tmp2); // add operand to operand array + } + } else // empty list + array = Atom(0); + + Store_field(op_info_val, 1, array); + + // finally, insert this into arch_info + Store_field(arch_info, 0, op_info_val); + + Store_field(rec_insn, 9, arch_info); + + break; + default: break; } } @@ -658,6 +731,15 @@ CAMLprim value ocaml_cs_disasm(value _arch, value _mode, value _code, value _add case 7: arch = CS_ARCH_XCORE; break; + case 8: + arch = CS_ARCH_M68K; + break; + case 9: + arch = CS_ARCH_TMS320C64X; + break; + case 10: + arch = CS_ARCH_M680X; + break; default: caml_invalid_argument("Invalid arch"); return Val_emptylist; @@ -717,6 +799,36 @@ CAMLprim value ocaml_cs_disasm(value _arch, value _mode, value _code, value _add case 16: mode |= CS_MODE_QPX; break; + case 17: + mode |= CS_MODE_M680X_6301; + break; + case 18: + mode |= CS_MODE_M680X_6309; + break; + case 19: + mode |= CS_MODE_M680X_6800; + break; + case 20: + mode |= CS_MODE_M680X_6801; + break; + case 21: + mode |= CS_MODE_M680X_6805; + break; + case 22: + mode |= CS_MODE_M680X_6808; + break; + case 23: + mode |= CS_MODE_M680X_6809; + break; + case 24: + mode |= CS_MODE_M680X_6811; + break; + case 25: + mode |= CS_MODE_M680X_CPU12; + break; + case 26: + mode |= CS_MODE_M680X_HCS08; + break; default: caml_invalid_argument("Invalid mode"); return Val_emptylist; @@ -791,6 +903,15 @@ CAMLprim value ocaml_open(value _arch, value _mode) case 7: arch = CS_ARCH_XCORE; break; + case 8: + arch = CS_ARCH_M68K; + break; + case 9: + arch = CS_ARCH_TMS320C64X; + break; + case 10: + arch = CS_ARCH_M680X; + break; default: caml_invalid_argument("Invalid arch"); return Val_emptylist; @@ -851,6 +972,36 @@ CAMLprim value ocaml_open(value _arch, value _mode) case 16: mode |= CS_MODE_QPX; break; + case 17: + mode |= CS_MODE_M680X_6301; + break; + case 18: + mode |= CS_MODE_M680X_6309; + break; + case 19: + mode |= CS_MODE_M680X_6800; + break; + case 20: + mode |= CS_MODE_M680X_6801; + break; + case 21: + mode |= CS_MODE_M680X_6805; + break; + case 22: + mode |= CS_MODE_M680X_6808; + break; + case 23: + mode |= CS_MODE_M680X_6809; + break; + case 24: + mode |= CS_MODE_M680X_6811; + break; + case 25: + mode |= CS_MODE_M680X_CPU12; + break; + case 26: + mode |= CS_MODE_M680X_HCS08; + break; default: caml_invalid_argument("Invalid mode"); return Val_emptylist; diff --git a/bindings/ocaml/test_m680x.ml b/bindings/ocaml/test_m680x.ml new file mode 100644 index 0000000000..8e26eeb198 --- /dev/null +++ b/bindings/ocaml/test_m680x.ml @@ -0,0 +1,167 @@ +(* Capstone Disassembly Engine +* M680X Backend by Wolfgang Schwotzer 2017 *) + +open Printf +open Capstone +open M680x +open M680x_const + + +let print_char_hex ch = + printf " 0x%02X" (Char.code ch) + +let print_int_hex_short value = + printf "%02X" value + +let print_string_hex comment str = + printf "%s" comment; + String.iter print_char_hex str; + printf "\n" + +let print_array_hex_short arr = + Array.iter print_int_hex_short arr + +let s_access = [ + "UNCHANGED"; "READ"; "WRITE"; "READ | WRITE" ];; + +let _M6800_CODE = "\x01\x09\x36\x64\x7f\x74\x10\x00\x90\x10\xA4\x10\xb6\x10\x00\x39";; +let _M6801_CODE = "\x04\x05\x3c\x3d\x38\x93\x10\xec\x10\xed\x10\x39";; +let _M6805_CODE = "\x04\x7f\x00\x17\x22\x28\x00\x2e\x00\x40\x42\x5a\x70\x8e\x97\x9c\xa0\x15\xad\x00\xc3\x10\x00\xda\x12\x34\xe5\x7f\xfe";; +let _M6808_CODE = "\x31\x22\x00\x35\x22\x45\x10\x00\x4b\x00\x51\x10\x52\x5e\x22\x62\x65\x12\x34\x72\x84\x85\x86\x87\x8a\x8b\x8c\x94\x95\xa7\x10\xaf\x10\x9e\x60\x7f\x9e\x6b\x7f\x00\x9e\xd6\x10\x00\x9e\xe6\x7f";; +let _HD6301_CODE = "\x6b\x10\x00\x71\x10\x00\x72\x10\x10\x39";; +let _M6809_CODE = "\x06\x10\x19\x1a\x55\x1e\x01\x23\xe9\x31\x06\x34\x55\xa6\x81\xa7\x89\x7f\xff\xa6\x9d\x10\x00\xa7\x91\xa6\x9f\x10\x00\x11\xac\x99\x10\x00\x39\xA6\x07\xA6\x27\xA6\x47\xA6\x67\xA6\x0F\xA6\x10\xA6\x80\xA6\x81\xA6\x82\xA6\x83\xA6\x84\xA6\x85\xA6\x86\xA6\x88\x7F\xA6\x88\x80\xA6\x89\x7F\xFF\xA6\x89\x80\x00\xA6\x8B\xA6\x8C\x10\xA6\x8D\x10\x00\xA6\x91\xA6\x93\xA6\x94\xA6\x95\xA6\x96\xA6\x98\x7F\xA6\x98\x80\xA6\x99\x7F\xFF\xA6\x99\x80\x00\xA6\x9B\xA6\x9C\x10\xA6\x9D\x10\x00\xA6\x9F\x10\x00";; +let _HD6309_CODE = "\x01\x10\x10\x62\x10\x10\x7b\x10\x10\x00\xcd\x49\x96\x02\xd2\x10\x30\x23\x10\x38\x10\x3b\x10\x53\x10\x5d\x11\x30\x43\x10\x11\x37\x25\x10\x11\x38\x12\x11\x39\x23\x11\x3b\x34\x11\x8e\x10\x00\x11\xaf\x10\x11\xab\x10\x11\xf6\x80\x00";; +let _M6811_CODE = "\x02\x03\x12\x7f\x10\x00\x13\x99\x08\x00\x14\x7f\x02\x15\x7f\x01\x1e\x7f\x20\x00\x8f\xcf\x18\x08\x18\x30\x18\x3c\x18\x67\x18\x8c\x10\x00\x18\x8f\x18\xce\x10\x00\x18\xff\x10\x00\x1a\xa3\x7f\x1a\xac\x1a\xee\x7f\x1a\xef\x7f\xcd\xac\x7f";; +let _CPU12_CODE = "\x00\x04\x01\x00\x0c\x00\x80\x0e\x00\x80\x00\x11\x1e\x10\x00\x80\x00\x3b\x4a\x10\x00\x04\x4b\x01\x04\x4f\x7f\x80\x00\x8f\x10\x00\xb7\x52\xb7\xb1\xa6\x67\xa6\xfe\xa6\xf7\x18\x02\xe2\x30\x39\xe2\x10\x00\x18\x0c\x30\x39\x10\x00\x18\x11\x18\x12\x10\x00\x18\x19\x00\x18\x1e\x00\x18\x3e\x18\x3f\x00";; +let _HCS08_CODE = "\x32\x10\x00\x9e\xae\x9e\xce\x7f\x9e\xbe\x10\x00\x9e\xfe\x7f\x3e\x10\x00\x9e\xf3\x7f\x96\x10\x00\x9e\xff\x7f\x82";; + +let bit_set value mask = + value land mask != 0 + +let all_tests = [ + (CS_ARCH_M680X, [CS_MODE_M680X_6301], _HD6301_CODE, "M680X_HD6301"); + (CS_ARCH_M680X, [CS_MODE_M680X_6309], _HD6309_CODE, "M680X_HD6309"); + (CS_ARCH_M680X, [CS_MODE_M680X_6800], _M6800_CODE, "M680X_M6800"); + (CS_ARCH_M680X, [CS_MODE_M680X_6801], _M6801_CODE, "M680X_M6801"); + (CS_ARCH_M680X, [CS_MODE_M680X_6805], _M6805_CODE, "M680X_M68HC05"); + (CS_ARCH_M680X, [CS_MODE_M680X_6808], _M6808_CODE, "M680X_M68HC08"); + (CS_ARCH_M680X, [CS_MODE_M680X_6809], _M6809_CODE, "M680X_M6809"); + (CS_ARCH_M680X, [CS_MODE_M680X_6811], _M6811_CODE, "M680X_M68HC11"); + (CS_ARCH_M680X, [CS_MODE_M680X_CPU12], _CPU12_CODE, "M680X_CPU12"); + (CS_ARCH_M680X, [CS_MODE_M680X_HCS08], _HCS08_CODE, "M680X_HCS08"); +];; + +let print_inc_dec inc_dec is_post = ( + printf "\t\t\t"; + if is_post then printf "post" else printf "pre"; + if inc_dec > 0 then + printf " increment: %d\n" inc_dec + else + printf " decrement: %d\n" (abs inc_dec); + ); + ();; + +let print_op handle flags i op = + ( match op.value with + | M680X_OP_INVALID _ -> (); (* this would never happens *) + | M680X_OP_REGISTER reg -> ( + printf "\t\toperands[%d].type: REGISTER = %s" i (cs_reg_name handle reg); + if (((i == 0) && (bit_set flags _M680X_FIRST_OP_IN_MNEM)) || + ((i == 1) && (bit_set flags _M680X_SECOND_OP_IN_MNEM))) then + printf " (in mnemonic)"; + printf "\n"; + ); + | M680X_OP_IMMEDIATE imm -> + printf "\t\toperands[%d].type: IMMEDIATE = #%d\n" i imm; + | M680X_OP_DIRECT direct_addr -> + printf "\t\toperands[%d].type: DIRECT = 0x%02X\n" i direct_addr; + | M680X_OP_EXTENDED ext -> ( + printf "\t\toperands[%d].type: EXTENDED " i; + if ext.indirect then + printf "INDIRECT"; + printf " = 0x%04X\n" ext.addr_ext; + ); + | M680X_OP_RELATIVE rel -> + printf "\t\toperands[%d].type: RELATIVE = 0x%04X\n" i rel.addr_rel; + | M680X_OP_INDEXED idx -> ( + printf "\t\toperands[%d].type: INDEXED" i; + if (bit_set idx.flags _M680X_IDX_INDIRECT) then + printf " INDIRECT"; + printf "\n"; + if idx.base_reg != _M680X_REG_INVALID then + printf "\t\t\tbase register: %s\n" (cs_reg_name handle idx.base_reg); + if idx.offset_reg != _M680X_REG_INVALID then + printf "\t\t\toffset register: %s\n" (cs_reg_name handle idx.offset_reg); + if idx.offset_bits != 0 && idx.offset_reg == 0 && idx.inc_dec == 0 then begin + printf "\t\t\toffset: %d\n" idx.offset; + if idx.base_reg == _M680X_REG_PC then + printf "\t\t\toffset address: 0x%X\n" idx.offset_addr; + printf "\t\t\toffset bits: %u\n" idx.offset_bits; + end; + if idx.inc_dec != 0 then + print_inc_dec idx.inc_dec (bit_set idx.flags _M680X_IDX_POST_INC_DEC); + ); + | M680X_OP_CONSTANT const_val -> + printf "\t\toperands[%d].type: CONSTANT = %d\n" i const_val; + ); + + if op.size != 0 then + printf "\t\t\tsize: %d\n" op.size; + if op.access != _CS_AC_INVALID then + printf "\t\t\taccess: %s\n" (List.nth s_access op.access); + ();; + + +let print_detail handle insn = + match insn.arch with + | CS_INFO_M680X m680x -> ( + (* print all operands info (type & value) *) + if (Array.length m680x.operands) > 0 then ( + printf "\top_count: %d\n" (Array.length m680x.operands); + Array.iteri (print_op handle m680x.flags) m680x.operands; + ); + ); + | _ -> (); + ;; + +let print_reg handle reg = + printf " %s" (cs_reg_name handle reg) + +let print_insn handle insn = + printf "0x%04X:\t" insn.address; + print_array_hex_short insn.bytes; + printf "\t%s\t%s\n" insn.mnemonic insn.op_str; + print_detail handle insn; + if (Array.length insn.regs_read) > 0 then begin + printf "\tRegisters read:"; + Array.iter (print_reg handle) insn.regs_read; + printf "\n"; + end; + if (Array.length insn.regs_write) > 0 then begin + printf "\tRegisters modified:"; + Array.iter (print_reg handle) insn.regs_write; + printf "\n"; + end; + if (Array.length insn.groups) > 0 then + printf "\tgroups_count: %d\n" (Array.length insn.groups); + printf "\n" + +let print_arch x = + let (arch, mode, code, comment) = x in + let handle = cs_open arch mode in + let err = cs_option handle CS_OPT_DETAIL _CS_OPT_ON in + match err with + | _ -> (); + let insns = cs_disasm handle code 0x1000L 0L in + printf "********************\n"; + printf "Platform: %s\n" comment; + print_string_hex "Code: " code; + printf "Disasm:\n"; + List.iter (print_insn handle) insns; + match cs_close handle with + | 0 -> (); + | _ -> printf "Failed to close handle"; + ;; + +List.iter print_arch all_tests;; + diff --git a/bindings/python/Makefile b/bindings/python/Makefile index 0616b05012..b38a4a475c 100644 --- a/bindings/python/Makefile +++ b/bindings/python/Makefile @@ -66,7 +66,7 @@ clean: TESTS = test_basic.py test_detail.py test_arm.py test_arm64.py test_m68k.py test_mips.py -TESTS += test_ppc.py test_sparc.py test_systemz.py test_x86.py test_xcore.py test_tms320c64x.py test_skipdata.py +TESTS += test_ppc.py test_sparc.py test_systemz.py test_x86.py test_xcore.py test_tms320c64x.py test_m680x.py test_skipdata.py check: @for t in $(TESTS); do \ echo Check $$t ... ; \ diff --git a/bindings/python/capstone/__init__.py b/bindings/python/capstone/__init__.py index a7c1453ab4..091a6dd94f 100644 --- a/bindings/python/capstone/__init__.py +++ b/bindings/python/capstone/__init__.py @@ -33,6 +33,7 @@ 'CS_ARCH_XCORE', 'CS_ARCH_M68K', 'CS_ARCH_TMS320C64X', + 'CS_ARCH_M680X', 'CS_ARCH_ALL', 'CS_MODE_LITTLE_ENDIAN', @@ -58,6 +59,16 @@ 'CS_MODE_M68K_060', 'CS_MODE_MIPS32', 'CS_MODE_MIPS64', + 'CS_MODE_M680X_6301', + 'CS_MODE_M680X_6309', + 'CS_MODE_M680X_6800', + 'CS_MODE_M680X_6801', + 'CS_MODE_M680X_6805', + 'CS_MODE_M680X_6808', + 'CS_MODE_M680X_6809', + 'CS_MODE_M680X_6811', + 'CS_MODE_M680X_CPU12', + 'CS_MODE_M680X_HCS08', 'CS_OPT_SYNTAX', 'CS_OPT_SYNTAX_DEFAULT', @@ -137,7 +148,8 @@ CS_ARCH_XCORE = 7 CS_ARCH_M68K = 8 CS_ARCH_TMS320C64X = 9 -CS_ARCH_MAX = 10 +CS_ARCH_M680X = 10 +CS_ARCH_MAX = 11 CS_ARCH_ALL = 0xFFFF # disasm mode @@ -164,6 +176,16 @@ CS_MODE_BIG_ENDIAN = (1 << 31) # big-endian mode CS_MODE_MIPS32 = CS_MODE_32 # Mips32 ISA CS_MODE_MIPS64 = CS_MODE_64 # Mips64 ISA +CS_MODE_M680X_6301 = (1 << 1) # M680X HD6301/3 mode +CS_MODE_M680X_6309 = (1 << 2) # M680X HD6309 mode +CS_MODE_M680X_6800 = (1 << 3) # M680X M6800/2 mode +CS_MODE_M680X_6801 = (1 << 4) # M680X M6801/3 mode +CS_MODE_M680X_6805 = (1 << 5) # M680X M6805 mode +CS_MODE_M680X_6808 = (1 << 6) # M680X M68HC08 mode +CS_MODE_M680X_6809 = (1 << 7) # M680X M6809 mode +CS_MODE_M680X_6811 = (1 << 8) # M680X M68HC11 mode +CS_MODE_M680X_CPU12 = (1 << 9) # M680X CPU12 mode +CS_MODE_M680X_HCS08 = (1 << 10) # M680X HCS08 mode # Capstone option type CS_OPT_SYNTAX = 1 # Intel X86 asm syntax (CS_ARCH_X86 arch) @@ -302,7 +324,7 @@ def copy_ctypes_list(src): return [copy_ctypes(n) for n in src] # Weird import placement because these modules are needed by the below code but need the above functions -from . import arm, arm64, m68k, mips, ppc, sparc, systemz, x86, xcore, tms320c64x +from . import arm, arm64, m68k, mips, ppc, sparc, systemz, x86, xcore, tms320c64x, m680x class _cs_arch(ctypes.Union): _fields_ = ( @@ -316,6 +338,7 @@ class _cs_arch(ctypes.Union): ('sysz', systemz.CsSysz), ('xcore', xcore.CsXcore), ('tms320c64x', tms320c64x.CsTMS320C64x), + ('m680x', m680x.CsM680x), ) class _cs_detail(ctypes.Structure): @@ -620,6 +643,8 @@ def __gen_detail(self): (self.operands) = xcore.get_arch_info(self._raw.detail.contents.arch.xcore) elif arch == CS_ARCH_TMS320C64X: (self.condition, self.funit, self.parallel, self.operands) = tms320c64x.get_arch_info(self._raw.detail.contents.arch.tms320c64x) + elif arch == CS_ARCH_M680X: + (self.flags, self.operands) = m680x.get_arch_info(self._raw.detail.contents.arch.m680x) def __getattr__(self, name): @@ -1043,7 +1068,8 @@ def debug(): archs = { "arm": CS_ARCH_ARM, "arm64": CS_ARCH_ARM64, "m68k": CS_ARCH_M68K, \ "mips": CS_ARCH_MIPS, "ppc": CS_ARCH_PPC, "sparc": CS_ARCH_SPARC, \ - "sysz": CS_ARCH_SYSZ, 'xcore': CS_ARCH_XCORE, "tms320c64x": CS_ARCH_TMS320C64X } + "sysz": CS_ARCH_SYSZ, 'xcore': CS_ARCH_XCORE, "tms320c64x": CS_ARCH_TMS320C64X, \ + "m680x": CS_ARCH_M680X } all_archs = "" keys = archs.keys() diff --git a/bindings/python/capstone/m680x.py b/bindings/python/capstone/m680x.py new file mode 100644 index 0000000000..dae21be45d --- /dev/null +++ b/bindings/python/capstone/m680x.py @@ -0,0 +1,88 @@ +# Capstone Python bindings, by Wolfgang Schwotzer + +import ctypes +from . import copy_ctypes_list +from .m680x_const import * + +# define the API +class M680xOpIdx(ctypes.Structure): + _fields_ = ( + ('base_reg', ctypes.c_uint), + ('offset_reg', ctypes.c_uint), + ('offset', ctypes.c_int16), + ('offset_addr', ctypes.c_uint16), + ('offset_bits', ctypes.c_uint8), + ('inc_dec', ctypes.c_int8), + ('flags', ctypes.c_uint8), + ) + +class M680xOpRel(ctypes.Structure): + _fields_ = ( + ('address', ctypes.c_uint16), + ('offset', ctypes.c_int16), + ) + +class M680xOpExt(ctypes.Structure): + _fields_ = ( + ('address', ctypes.c_uint16), + ('indirect', ctypes.c_bool), + ) + +class M680xOpValue(ctypes.Union): + _fields_ = ( + ('imm', ctypes.c_int32), + ('reg', ctypes.c_uint), + ('idx', M680xOpIdx), + ('rel', M680xOpRel), + ('ext', M680xOpExt), + ('direct_addr', ctypes.c_uint8), + ('const_val', ctypes.c_uint8), + ) + +class M680xOp(ctypes.Structure): + _fields_ = ( + ('type', ctypes.c_uint), + ('value', M680xOpValue), + ('size', ctypes.c_uint8), + ('access', ctypes.c_uint8), + ) + + @property + def imm(self): + return self.value.imm + + @property + def reg(self): + return self.value.reg + + @property + def idx(self): + return self.value.idx + + @property + def rel(self): + return self.value.rel + + @property + def ext(self): + return self.value.ext + + @property + def direct_addr(self): + return self.value.direct_addr + + @property + def const_val(self): + return self.value.const_val + + +class CsM680x(ctypes.Structure): + _fields_ = ( + ('flags', ctypes.c_uint8), + ('op_count', ctypes.c_uint8), + ('operands', M680xOp * 9), + ) + +def get_arch_info(a): + return (a.flags, copy_ctypes_list(a.operands[:a.op_count])) + diff --git a/bindings/python/capstone/m680x_const.py b/bindings/python/capstone/m680x_const.py new file mode 100644 index 0000000000..96171d0c8d --- /dev/null +++ b/bindings/python/capstone/m680x_const.py @@ -0,0 +1,435 @@ +# For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT [m680x_const.py] +M680X_OPERAND_COUNT = 9 + +# M680X registers and special registers + +M680X_REG_INVALID = 0 +M680X_REG_A = 1 +M680X_REG_B = 2 +M680X_REG_E = 3 +M680X_REG_F = 4 +M680X_REG_0 = 5 +M680X_REG_D = 6 +M680X_REG_W = 7 +M680X_REG_CC = 8 +M680X_REG_DP = 9 +M680X_REG_MD = 10 +M680X_REG_HX = 11 +M680X_REG_H = 12 +M680X_REG_X = 13 +M680X_REG_Y = 14 +M680X_REG_S = 15 +M680X_REG_U = 16 +M680X_REG_V = 17 +M680X_REG_Q = 18 +M680X_REG_PC = 19 +M680X_REG_TMP2 = 20 +M680X_REG_TMP3 = 21 +M680X_REG_ENDING = 22 + +# Operand type for instruction's operands + +M680X_OP_INVALID = 0 +M680X_OP_REGISTER = 1 +M680X_OP_IMMEDIATE = 2 +M680X_OP_INDEXED = 3 +M680X_OP_EXTENDED = 4 +M680X_OP_DIRECT = 5 +M680X_OP_RELATIVE = 6 +M680X_OP_CONSTANT = 7 + +# Supported bit values for mem.idx.offset_bits + +M680X_OFFSET_NONE = 0 +M680X_OFFSET_BITS_5 = 5 +M680X_OFFSET_BITS_8 = 8 +M680X_OFFSET_BITS_9 = 9 +M680X_OFFSET_BITS_16 = 16 + +# Supported bit flags for mem.idx.flags + +# These flags can be comined +M680X_IDX_INDIRECT = 1 +M680X_IDX_NO_COMMA = 2 +M680X_IDX_POST_INC_DEC = 4 + +# Group of M680X instructions + +M680X_GRP_INVALID = 0 + +# Generic groups +M680X_GRP_JUMP = 1 +M680X_GRP_CALL = 2 +M680X_GRP_RET = 3 +M680X_GRP_INT = 4 +M680X_GRP_IRET = 5 +M680X_GRP_PRIV = 6 +M680X_GRP_BRAREL = 7 + +# Architecture-specific groups +M680X_GRP_ENDING = 8 + +# M680X instruction flags: +M680X_FIRST_OP_IN_MNEM = 1 +M680X_SECOND_OP_IN_MNEM = 2 + +# M680X instruction IDs + +M680X_INS_INVLD = 0 +M680X_INS_ABA = 1 +M680X_INS_ABX = 2 +M680X_INS_ABY = 3 +M680X_INS_ADC = 4 +M680X_INS_ADCA = 5 +M680X_INS_ADCB = 6 +M680X_INS_ADCD = 7 +M680X_INS_ADCR = 8 +M680X_INS_ADD = 9 +M680X_INS_ADDA = 10 +M680X_INS_ADDB = 11 +M680X_INS_ADDD = 12 +M680X_INS_ADDE = 13 +M680X_INS_ADDF = 14 +M680X_INS_ADDR = 15 +M680X_INS_ADDW = 16 +M680X_INS_AIM = 17 +M680X_INS_AIS = 18 +M680X_INS_AIX = 19 +M680X_INS_AND = 20 +M680X_INS_ANDA = 21 +M680X_INS_ANDB = 22 +M680X_INS_ANDCC = 23 +M680X_INS_ANDD = 24 +M680X_INS_ANDR = 25 +M680X_INS_ASL = 26 +M680X_INS_ASLA = 27 +M680X_INS_ASLB = 28 +M680X_INS_ASLD = 29 +M680X_INS_ASR = 30 +M680X_INS_ASRA = 31 +M680X_INS_ASRB = 32 +M680X_INS_ASRD = 33 +M680X_INS_ASRX = 34 +M680X_INS_BAND = 35 +M680X_INS_BCC = 36 +M680X_INS_BCLR = 37 +M680X_INS_BCS = 38 +M680X_INS_BEOR = 39 +M680X_INS_BEQ = 40 +M680X_INS_BGE = 41 +M680X_INS_BGND = 42 +M680X_INS_BGT = 43 +M680X_INS_BHCC = 44 +M680X_INS_BHCS = 45 +M680X_INS_BHI = 46 +M680X_INS_BIAND = 47 +M680X_INS_BIEOR = 48 +M680X_INS_BIH = 49 +M680X_INS_BIL = 50 +M680X_INS_BIOR = 51 +M680X_INS_BIT = 52 +M680X_INS_BITA = 53 +M680X_INS_BITB = 54 +M680X_INS_BITD = 55 +M680X_INS_BITMD = 56 +M680X_INS_BLE = 57 +M680X_INS_BLS = 58 +M680X_INS_BLT = 59 +M680X_INS_BMC = 60 +M680X_INS_BMI = 61 +M680X_INS_BMS = 62 +M680X_INS_BNE = 63 +M680X_INS_BOR = 64 +M680X_INS_BPL = 65 +M680X_INS_BRCLR = 66 +M680X_INS_BRSET = 67 +M680X_INS_BRA = 68 +M680X_INS_BRN = 69 +M680X_INS_BSET = 70 +M680X_INS_BSR = 71 +M680X_INS_BVC = 72 +M680X_INS_BVS = 73 +M680X_INS_CALL = 74 +M680X_INS_CBA = 75 +M680X_INS_CBEQ = 76 +M680X_INS_CBEQA = 77 +M680X_INS_CBEQX = 78 +M680X_INS_CLC = 79 +M680X_INS_CLI = 80 +M680X_INS_CLR = 81 +M680X_INS_CLRA = 82 +M680X_INS_CLRB = 83 +M680X_INS_CLRD = 84 +M680X_INS_CLRE = 85 +M680X_INS_CLRF = 86 +M680X_INS_CLRH = 87 +M680X_INS_CLRW = 88 +M680X_INS_CLRX = 89 +M680X_INS_CLV = 90 +M680X_INS_CMP = 91 +M680X_INS_CMPA = 92 +M680X_INS_CMPB = 93 +M680X_INS_CMPD = 94 +M680X_INS_CMPE = 95 +M680X_INS_CMPF = 96 +M680X_INS_CMPR = 97 +M680X_INS_CMPS = 98 +M680X_INS_CMPU = 99 +M680X_INS_CMPW = 100 +M680X_INS_CMPX = 101 +M680X_INS_CMPY = 102 +M680X_INS_COM = 103 +M680X_INS_COMA = 104 +M680X_INS_COMB = 105 +M680X_INS_COMD = 106 +M680X_INS_COME = 107 +M680X_INS_COMF = 108 +M680X_INS_COMW = 109 +M680X_INS_COMX = 110 +M680X_INS_CPD = 111 +M680X_INS_CPHX = 112 +M680X_INS_CPS = 113 +M680X_INS_CPX = 114 +M680X_INS_CPY = 115 +M680X_INS_CWAI = 116 +M680X_INS_DAA = 117 +M680X_INS_DBEQ = 118 +M680X_INS_DBNE = 119 +M680X_INS_DBNZ = 120 +M680X_INS_DBNZA = 121 +M680X_INS_DBNZX = 122 +M680X_INS_DEC = 123 +M680X_INS_DECA = 124 +M680X_INS_DECB = 125 +M680X_INS_DECD = 126 +M680X_INS_DECE = 127 +M680X_INS_DECF = 128 +M680X_INS_DECW = 129 +M680X_INS_DECX = 130 +M680X_INS_DES = 131 +M680X_INS_DEX = 132 +M680X_INS_DEY = 133 +M680X_INS_DIV = 134 +M680X_INS_DIVD = 135 +M680X_INS_DIVQ = 136 +M680X_INS_EDIV = 137 +M680X_INS_EDIVS = 138 +M680X_INS_EIM = 139 +M680X_INS_EMACS = 140 +M680X_INS_EMAXD = 141 +M680X_INS_EMAXM = 142 +M680X_INS_EMIND = 143 +M680X_INS_EMINM = 144 +M680X_INS_EMUL = 145 +M680X_INS_EMULS = 146 +M680X_INS_EOR = 147 +M680X_INS_EORA = 148 +M680X_INS_EORB = 149 +M680X_INS_EORD = 150 +M680X_INS_EORR = 151 +M680X_INS_ETBL = 152 +M680X_INS_EXG = 153 +M680X_INS_FDIV = 154 +M680X_INS_IBEQ = 155 +M680X_INS_IBNE = 156 +M680X_INS_IDIV = 157 +M680X_INS_IDIVS = 158 +M680X_INS_ILLGL = 159 +M680X_INS_INC = 160 +M680X_INS_INCA = 161 +M680X_INS_INCB = 162 +M680X_INS_INCD = 163 +M680X_INS_INCE = 164 +M680X_INS_INCF = 165 +M680X_INS_INCW = 166 +M680X_INS_INCX = 167 +M680X_INS_INS = 168 +M680X_INS_INX = 169 +M680X_INS_INY = 170 +M680X_INS_JMP = 171 +M680X_INS_JSR = 172 +M680X_INS_LBCC = 173 +M680X_INS_LBCS = 174 +M680X_INS_LBEQ = 175 +M680X_INS_LBGE = 176 +M680X_INS_LBGT = 177 +M680X_INS_LBHI = 178 +M680X_INS_LBLE = 179 +M680X_INS_LBLS = 180 +M680X_INS_LBLT = 181 +M680X_INS_LBMI = 182 +M680X_INS_LBNE = 183 +M680X_INS_LBPL = 184 +M680X_INS_LBRA = 185 +M680X_INS_LBRN = 186 +M680X_INS_LBSR = 187 +M680X_INS_LBVC = 188 +M680X_INS_LBVS = 189 +M680X_INS_LDA = 190 +M680X_INS_LDAA = 191 +M680X_INS_LDAB = 192 +M680X_INS_LDB = 193 +M680X_INS_LDBT = 194 +M680X_INS_LDD = 195 +M680X_INS_LDE = 196 +M680X_INS_LDF = 197 +M680X_INS_LDHX = 198 +M680X_INS_LDMD = 199 +M680X_INS_LDQ = 200 +M680X_INS_LDS = 201 +M680X_INS_LDU = 202 +M680X_INS_LDW = 203 +M680X_INS_LDX = 204 +M680X_INS_LDY = 205 +M680X_INS_LEAS = 206 +M680X_INS_LEAU = 207 +M680X_INS_LEAX = 208 +M680X_INS_LEAY = 209 +M680X_INS_LSL = 210 +M680X_INS_LSLA = 211 +M680X_INS_LSLB = 212 +M680X_INS_LSLD = 213 +M680X_INS_LSLX = 214 +M680X_INS_LSR = 215 +M680X_INS_LSRA = 216 +M680X_INS_LSRB = 217 +M680X_INS_LSRD = 218 +M680X_INS_LSRW = 219 +M680X_INS_LSRX = 220 +M680X_INS_MAXA = 221 +M680X_INS_MAXM = 222 +M680X_INS_MEM = 223 +M680X_INS_MINA = 224 +M680X_INS_MINM = 225 +M680X_INS_MOV = 226 +M680X_INS_MOVB = 227 +M680X_INS_MOVW = 228 +M680X_INS_MUL = 229 +M680X_INS_MULD = 230 +M680X_INS_NEG = 231 +M680X_INS_NEGA = 232 +M680X_INS_NEGB = 233 +M680X_INS_NEGD = 234 +M680X_INS_NEGX = 235 +M680X_INS_NOP = 236 +M680X_INS_NSA = 237 +M680X_INS_OIM = 238 +M680X_INS_ORA = 239 +M680X_INS_ORAA = 240 +M680X_INS_ORAB = 241 +M680X_INS_ORB = 242 +M680X_INS_ORCC = 243 +M680X_INS_ORD = 244 +M680X_INS_ORR = 245 +M680X_INS_PSHA = 246 +M680X_INS_PSHB = 247 +M680X_INS_PSHC = 248 +M680X_INS_PSHD = 249 +M680X_INS_PSHH = 250 +M680X_INS_PSHS = 251 +M680X_INS_PSHSW = 252 +M680X_INS_PSHU = 253 +M680X_INS_PSHUW = 254 +M680X_INS_PSHX = 255 +M680X_INS_PSHY = 256 +M680X_INS_PULA = 257 +M680X_INS_PULB = 258 +M680X_INS_PULC = 259 +M680X_INS_PULD = 260 +M680X_INS_PULH = 261 +M680X_INS_PULS = 262 +M680X_INS_PULSW = 263 +M680X_INS_PULU = 264 +M680X_INS_PULUW = 265 +M680X_INS_PULX = 266 +M680X_INS_PULY = 267 +M680X_INS_REV = 268 +M680X_INS_REVW = 269 +M680X_INS_ROL = 270 +M680X_INS_ROLA = 271 +M680X_INS_ROLB = 272 +M680X_INS_ROLD = 273 +M680X_INS_ROLW = 274 +M680X_INS_ROLX = 275 +M680X_INS_ROR = 276 +M680X_INS_RORA = 277 +M680X_INS_RORB = 278 +M680X_INS_RORD = 279 +M680X_INS_RORW = 280 +M680X_INS_RORX = 281 +M680X_INS_RSP = 282 +M680X_INS_RTC = 283 +M680X_INS_RTI = 284 +M680X_INS_RTS = 285 +M680X_INS_SBA = 286 +M680X_INS_SBC = 287 +M680X_INS_SBCA = 288 +M680X_INS_SBCB = 289 +M680X_INS_SBCD = 290 +M680X_INS_SBCR = 291 +M680X_INS_SEC = 292 +M680X_INS_SEI = 293 +M680X_INS_SEV = 294 +M680X_INS_SEX = 295 +M680X_INS_SEXW = 296 +M680X_INS_SLP = 297 +M680X_INS_STA = 298 +M680X_INS_STAA = 299 +M680X_INS_STAB = 300 +M680X_INS_STB = 301 +M680X_INS_STBT = 302 +M680X_INS_STD = 303 +M680X_INS_STE = 304 +M680X_INS_STF = 305 +M680X_INS_STOP = 306 +M680X_INS_STHX = 307 +M680X_INS_STQ = 308 +M680X_INS_STS = 309 +M680X_INS_STU = 310 +M680X_INS_STW = 311 +M680X_INS_STX = 312 +M680X_INS_STY = 313 +M680X_INS_SUB = 314 +M680X_INS_SUBA = 315 +M680X_INS_SUBB = 316 +M680X_INS_SUBD = 317 +M680X_INS_SUBE = 318 +M680X_INS_SUBF = 319 +M680X_INS_SUBR = 320 +M680X_INS_SUBW = 321 +M680X_INS_SWI = 322 +M680X_INS_SWI2 = 323 +M680X_INS_SWI3 = 324 +M680X_INS_SYNC = 325 +M680X_INS_TAB = 326 +M680X_INS_TAP = 327 +M680X_INS_TAX = 328 +M680X_INS_TBA = 329 +M680X_INS_TBEQ = 330 +M680X_INS_TBL = 331 +M680X_INS_TBNE = 332 +M680X_INS_TEST = 333 +M680X_INS_TFM = 334 +M680X_INS_TFR = 335 +M680X_INS_TIM = 336 +M680X_INS_TPA = 337 +M680X_INS_TST = 338 +M680X_INS_TSTA = 339 +M680X_INS_TSTB = 340 +M680X_INS_TSTD = 341 +M680X_INS_TSTE = 342 +M680X_INS_TSTF = 343 +M680X_INS_TSTW = 344 +M680X_INS_TSTX = 345 +M680X_INS_TSX = 346 +M680X_INS_TSY = 347 +M680X_INS_TXA = 348 +M680X_INS_TXS = 349 +M680X_INS_TYS = 350 +M680X_INS_WAI = 351 +M680X_INS_WAIT = 352 +M680X_INS_WAV = 353 +M680X_INS_WAVR = 354 +M680X_INS_XGDX = 355 +M680X_INS_XGDY = 356 +M680X_INS_ENDING = 357 diff --git a/bindings/python/test_all.py b/bindings/python/test_all.py index d3f004ba36..7e41d8ae6d 100755 --- a/bindings/python/test_all.py +++ b/bindings/python/test_all.py @@ -1,7 +1,8 @@ #!/usr/bin/env python import test_basic, test_arm, test_arm64, test_detail, test_lite, test_m68k, test_mips, \ - test_ppc, test_x86, test_skipdata, test_sparc, test_systemz, test_tms320c64x, test_customized_mnem + test_ppc, test_x86, test_skipdata, test_sparc, test_systemz, test_tms320c64x, test_customized_mnem, \ + test_m680x test_basic.test_class() @@ -16,5 +17,6 @@ test_systemz.test_class() test_x86.test_class() test_tms320c64x.test_class() +test_m680x.test_class() test_skipdata.test_class() test_customized_mnem.test() diff --git a/bindings/python/test_basic.py b/bindings/python/test_basic.py index c446186a3f..b55187bd91 100755 --- a/bindings/python/test_basic.py +++ b/bindings/python/test_basic.py @@ -33,6 +33,7 @@ XCORE_CODE = b"\xfe\x0f\xfe\x17\x13\x17\xc6\xfe\xec\x17\x97\xf8\xec\x4f\x1f\xfd\xec\x37\x07\xf2\x45\x5b\xf9\xfa\x02\x06\x1b\x10" M68K_CODE = b"\xd4\x40\x87\x5a\x4e\x71\x02\xb4\xc0\xde\xc0\xde\x5c\x00\x1d\x80\x71\x12\x01\x23\xf2\x3c\x44\x22\x40\x49\x0e\x56\x54\xc5\xf2\x3c\x44\x00\x44\x7a\x00\x00\xf2\x00\x0a\x28\x4E\xB9\x00\x00\x00\x12\x4E\x75" TMS320C64X_CODE = b"\x01\xac\x88\x40\x81\xac\x88\x43\x00\x00\x00\x00\x02\x90\x32\x96\x02\x80\x46\x9e\x05\x3c\x83\xe6\x0b\x0c\x8b\x24" +M680X_CODE = b"\x06\x10\x19\x1a\x55\x1e\x01\x23\xe9\x31\x06\x34\x55\xa6\x81\xa7\x89\x7f\xff\xa6\x9d\x10\x00\xa7\x91\xa6\x9f\x10\x00\x11\xac\x99\x10\x00\x39" all_tests = ( (CS_ARCH_X86, CS_MODE_16, X86_CODE16, "X86 16bit (Intel syntax)", None), @@ -60,6 +61,7 @@ (CS_ARCH_XCORE, 0, XCORE_CODE, "XCore", None), (CS_ARCH_M68K, CS_MODE_BIG_ENDIAN | CS_MODE_M68K_040, M68K_CODE, "M68K (68040)", None), (CS_ARCH_TMS320C64X, 0, TMS320C64X_CODE, "TMS320C64x", None), + (CS_ARCH_M680X, CS_MODE_M680X_6809, M680X_CODE, "M680X_M6809", None), ) # ## Test cs_disasm_quick() diff --git a/bindings/python/test_detail.py b/bindings/python/test_detail.py index a06c63e0e6..e7cc6a8823 100755 --- a/bindings/python/test_detail.py +++ b/bindings/python/test_detail.py @@ -26,6 +26,7 @@ SYSZ_CODE = b"\xed\x00\x00\x00\x00\x1a\x5a\x0f\x1f\xff\xc2\x09\x80\x00\x00\x00\x07\xf7\xeb\x2a\xff\xff\x7f\x57\xe3\x01\xff\xff\x7f\x57\xeb\x00\xf0\x00\x00\x24\xb2\x4f\x00\x78" XCORE_CODE = b"\xfe\x0f\xfe\x17\x13\x17\xc6\xfe\xec\x17\x97\xf8\xec\x4f\x1f\xfd\xec\x37\x07\xf2\x45\x5b\xf9\xfa\x02\x06\x1b\x10" M68K_CODE = b"\xd4\x40\x87\x5a\x4e\x71\x02\xb4\xc0\xde\xc0\xde\x5c\x00\x1d\x80\x71\x12\x01\x23\xf2\x3c\x44\x22\x40\x49\x0e\x56\x54\xc5\xf2\x3c\x44\x00\x44\x7a\x00\x00\xf2\x00\x0a\x28\x4E\xB9\x00\x00\x00\x12\x4E\x75" +M680X_CODE = b"\x06\x10\x19\x1a\x55\x1e\x01\x23\xe9\x31\x06\x34\x55\xa6\x81\xa7\x89\x7f\xff\xa6\x9d\x10\x00\xa7\x91\xa6\x9f\x10\x00\x11\xac\x99\x10\x00\x39" all_tests = ( (CS_ARCH_X86, CS_MODE_16, X86_CODE16, "X86 16bit (Intel syntax)", None), @@ -50,6 +51,7 @@ (CS_ARCH_SYSZ, 0, SYSZ_CODE, "SystemZ", None), (CS_ARCH_XCORE, 0, XCORE_CODE, "XCore", None), (CS_ARCH_M68K, CS_MODE_BIG_ENDIAN | CS_MODE_M68K_040, M68K_CODE, "M68K (68040)", None), + (CS_ARCH_M680X, CS_MODE_M680X_6809, M680X_CODE, "M680X_M6809", None), ) diff --git a/bindings/python/test_lite.py b/bindings/python/test_lite.py index 9ba7bd8fb2..41b16cadd4 100755 --- a/bindings/python/test_lite.py +++ b/bindings/python/test_lite.py @@ -27,6 +27,7 @@ SYSZ_CODE = b"\xed\x00\x00\x00\x00\x1a\x5a\x0f\x1f\xff\xc2\x09\x80\x00\x00\x00\x07\xf7\xeb\x2a\xff\xff\x7f\x57\xe3\x01\xff\xff\x7f\x57\xeb\x00\xf0\x00\x00\x24\xb2\x4f\x00\x78" XCORE_CODE = b"\xfe\x0f\xfe\x17\x13\x17\xc6\xfe\xec\x17\x97\xf8\xec\x4f\x1f\xfd\xec\x37\x07\xf2\x45\x5b\xf9\xfa\x02\x06\x1b\x10" M68K_CODE = b"\xd4\x40\x87\x5a\x4e\x71\x02\xb4\xc0\xde\xc0\xde\x5c\x00\x1d\x80\x71\x12\x01\x23\xf2\x3c\x44\x22\x40\x49\x0e\x56\x54\xc5\xf2\x3c\x44\x00\x44\x7a\x00\x00\xf2\x00\x0a\x28\x4E\xB9\x00\x00\x00\x12\x4E\x75" +M680X_CODE = b"\x06\x10\x19\x1a\x55\x1e\x01\x23\xe9\x31\x06\x34\x55\xa6\x81\xa7\x89\x7f\xff\xa6\x9d\x10\x00\xa7\x91\xa6\x9f\x10\x00\x11\xac\x99\x10\x00\x39" all_tests = ( (CS_ARCH_X86, CS_MODE_16, X86_CODE16, "X86 16bit (Intel syntax)", None), @@ -53,6 +54,7 @@ (CS_ARCH_SYSZ, 0, SYSZ_CODE, "SystemZ", None), (CS_ARCH_XCORE, 0, XCORE_CODE, "XCore", None), (CS_ARCH_M68K, CS_MODE_BIG_ENDIAN | CS_MODE_M68K_040, M68K_CODE, "M68K (68040)", None), + (CS_ARCH_M680X, CS_MODE_M680X_6809, M680X_CODE, "M680X_M6809", None), ) diff --git a/bindings/python/test_m680x.py b/bindings/python/test_m680x.py new file mode 100755 index 0000000000..0c0e973725 --- /dev/null +++ b/bindings/python/test_m680x.py @@ -0,0 +1,159 @@ +#!/usr/bin/env python + +# Capstone Python bindings, by Wolfgang Schwotzer + +from __future__ import print_function +import sys +from capstone import * +from capstone.m680x import * +_python3 = sys.version_info.major == 3 + + +s_access = ( + "UNCHANGED", "READ", "WRITE", "READ | WRITE", + ) + +M6800_CODE = b"\x01\x09\x36\x64\x7f\x74\x10\x00\x90\x10\xA4\x10\xb6\x10\x00\x39" + +M6801_CODE = b"\x04\x05\x3c\x3d\x38\x93\x10\xec\x10\xed\x10\x39" +M6805_CODE = b"\x04\x7f\x00\x17\x22\x28\x00\x2e\x00\x40\x42\x5a\x70\x8e\x97\x9c\xa0\x15\xad\x00\xc3\x10\x00\xda\x12\x34\xe5\x7f\xfe" +M6808_CODE = b"\x31\x22\x00\x35\x22\x45\x10\x00\x4b\x00\x51\x10\x52\x5e\x22\x62\x65\x12\x34\x72\x84\x85\x86\x87\x8a\x8b\x8c\x94\x95\xa7\x10\xaf\x10\x9e\x60\x7f\x9e\x6b\x7f\x00\x9e\xd6\x10\x00\x9e\xe6\x7f" +HCS08_CODE = b"\x32\x10\x00\x9e\xae\x9e\xce\x7f\x9e\xbe\x10\x00\x9e\xfe\x7f\x3e\x10\x00\x9e\xf3\x7f\x96\x10\x00\x9e\xff\x7f\x82" +HD6301_CODE = b"\x6b\x10\x00\x71\x10\x00\x72\x10\x10\x39" +M6809_CODE = b"\x06\x10\x19\x1a\x55\x1e\x01\x23\xe9\x31\x06\x34\x55\xa6\x81\xa7\x89\x7f\xff\xa6\x9d\x10\x00\xa7\x91\xa6\x9f\x10\x00\x11\xac\x99\x10\x00\x39\xA6\x07\xA6\x27\xA6\x47\xA6\x67\xA6\x0F\xA6\x10\xA6\x80\xA6\x81\xA6\x82\xA6\x83\xA6\x84\xA6\x85\xA6\x86\xA6\x88\x7F\xA6\x88\x80\xA6\x89\x7F\xFF\xA6\x89\x80\x00\xA6\x8B\xA6\x8C\x10\xA6\x8D\x10\x00\xA6\x91\xA6\x93\xA6\x94\xA6\x95\xA6\x96\xA6\x98\x7F\xA6\x98\x80\xA6\x99\x7F\xFF\xA6\x99\x80\x00\xA6\x9B\xA6\x9C\x10\xA6\x9D\x10\x00\xA6\x9F\x10\x00" +M6811_CODE = b"\x02\x03\x12\x7f\x10\x00\x13\x99\x08\x00\x14\x7f\x02\x15\x7f\x01\x1e\x7f\x20\x00\x8f\xcf\x18\x08\x18\x30\x18\x3c\x18\x67\x18\x8c\x10\x00\x18\x8f\x18\xce\x10\x00\x18\xff\x10\x00\x1a\xa3\x7f\x1a\xac\x1a\xee\x7f\x1a\xef\x7f\xcd\xac\x7f" +CPU12_CODE = b"\x00\x04\x01\x00\x0c\x00\x80\x0e\x00\x80\x00\x11\x1e\x10\x00\x80\x00\x3b\x4a\x10\x00\x04\x4b\x01\x04\x4f\x7f\x80\x00\x8f\x10\x00\xb7\x52\xb7\xb1\xa6\x67\xa6\xfe\xa6\xf7\x18\x02\xe2\x30\x39\xe2\x10\x00\x18\x0c\x30\x39\x10\x00\x18\x11\x18\x12\x10\x00\x18\x19\x00\x18\x1e\x00\x18\x3e\x18\x3f\x00" +HD6309_CODE = b"\x01\x10\x10\x62\x10\x10\x7b\x10\x10\x00\xcd\x49\x96\x02\xd2\x10\x30\x23\x10\x38\x10\x3b\x10\x53\x10\x5d\x11\x30\x43\x10\x11\x37\x25\x10\x11\x38\x12\x11\x39\x23\x11\x3b\x34\x11\x8e\x10\x00\x11\xaf\x10\x11\xab\x10\x11\xf6\x80\x00" + +all_tests = ( + (CS_ARCH_M680X, CS_MODE_M680X_6301, HD6301_CODE, "M680X_HD6301", None), + (CS_ARCH_M680X, CS_MODE_M680X_6309, HD6309_CODE, "M680X_HD6309", None), + (CS_ARCH_M680X, CS_MODE_M680X_6800, M6800_CODE, "M680X_M6800", None), + (CS_ARCH_M680X, CS_MODE_M680X_6801, M6801_CODE, "M680X_M6801", None), + (CS_ARCH_M680X, CS_MODE_M680X_6805, M6805_CODE, "M680X_M68HC05", None), + (CS_ARCH_M680X, CS_MODE_M680X_6808, M6808_CODE, "M680X_M68HC08", None), + (CS_ARCH_M680X, CS_MODE_M680X_6809, M6809_CODE, "M680X_M6809", None), + (CS_ARCH_M680X, CS_MODE_M680X_6811, M6811_CODE, "M680X_M68HC11", None), + (CS_ARCH_M680X, CS_MODE_M680X_CPU12, CPU12_CODE, "M680X_CPU12", None), + (CS_ARCH_M680X, CS_MODE_M680X_HCS08, HCS08_CODE, "M680X_HCS08", None), + ) + +# print hex dump from string all upper case +def to_hex_uc(string): + if _python3: + return " ".join("0x%02X" % c for c in string) + else: + return " ".join("0x%02X" % ord(c) for c in string) + +# print short hex dump from byte array all upper case +def to_hex_short_uc(byte_array): + return "".join("%02X" % b for b in byte_array) + +def print_insn_detail(insn): + # print address, mnemonic and operands + #print("0x%x:\t%s\t%s\t%s" % (insn.address, binascii.hexlify(bytearray(insn.bytes)), \ + print("0x%04X: %s\t%s\t%s" % (insn.address, to_hex_short_uc(insn.bytes), \ + insn.mnemonic, insn.op_str)) + + # "data" instruction generated by SKIPDATA option has no detail + if insn.id == 0: + return + + if len(insn.operands) > 0: + print("\top_count: %u" % len(insn.operands)) + c = 0 + for i in insn.operands: + if i.type == M680X_OP_REGISTER: + comment = ""; + if (((c == 0) and (insn.flags & M680X_FIRST_OP_IN_MNEM)) or + ((c == 1) and (insn.flags & M680X_SECOND_OP_IN_MNEM))): + comment = " (in mnemonic)"; + print("\t\toperands[%u].type: REGISTER = %s%s" % (c, + insn.reg_name(i.reg), comment)) + if i.type == M680X_OP_CONSTANT: + print("\t\toperands[%u].type: CONSTANT = %u" % (c, i.const_val)) + if i.type == M680X_OP_IMMEDIATE: + print("\t\toperands[%u].type: IMMEDIATE = #%d" % (c, i.imm)) + if i.type == M680X_OP_DIRECT: + print("\t\toperands[%u].type: DIRECT = 0x%02X" % (c, i.direct_addr)) + if i.type == M680X_OP_EXTENDED: + if i.ext.indirect: + indirect = "INDIRECT" + else: + indirect = "" + print("\t\toperands[%u].type: EXTENDED %s = 0x%04X" % (c, indirect, i.ext.address)) + if i.type == M680X_OP_RELATIVE: + print("\t\toperands[%u].type: RELATIVE = 0x%04X" % (c, i.rel.address)) + if i.type == M680X_OP_INDEXED: + if (i.idx.flags & M680X_IDX_INDIRECT): + indirect = " INDIRECT" + else: + indirect = "" + print("\t\toperands[%u].type: INDEXED%s" % (c, indirect)) + if i.idx.base_reg != M680X_REG_INVALID: + print("\t\t\tbase register: %s" % insn.reg_name(i.idx.base_reg)) + if i.idx.offset_reg != M680X_REG_INVALID: + print("\t\t\toffset register: %s" % insn.reg_name(i.idx.offset_reg)) + if (i.idx.offset_bits != 0) and (i.idx.offset_reg == M680X_REG_INVALID) and (i.idx.inc_dec == 0): + print("\t\t\toffset: %u" % i.idx.offset) + if i.idx.base_reg == M680X_REG_PC: + print("\t\t\toffset address: 0x%04X" % i.idx.offset_addr) + print("\t\t\toffset bits: %u" % i.idx.offset_bits) + if i.idx.inc_dec != 0: + if i.idx.flags & M680X_IDX_POST_INC_DEC: + s_post_pre = "post" + else: + s_post_pre = "pre" + if i.idx.inc_dec > 0: + s_inc_dec = "increment" + else: + s_inc_dec = "decrement" + print("\t\t\t%s %s: %d" % + (s_post_pre, s_inc_dec, abs(i.idx.inc_dec))) + if (i.size != 0): + print("\t\t\tsize: %d" % i.size) + if (i.access != CS_AC_INVALID): + print("\t\t\taccess: %s" % s_access[i.access]) + + c += 1 + + (regs_read, regs_write) = insn.regs_access() + + if len(regs_read) > 0: + print("\tRegisters read:", end="") + for r in regs_read: + print(" %s" %(insn.reg_name(r)), end="") + print("") + + if len(regs_write) > 0: + print("\tRegisters modified:", end="") + for r in regs_write: + print(" %s" %(insn.reg_name(r)), end="") + print("") + + if len(insn.groups) > 0: + print("\tgroups_count: %u" % len(insn.groups)) + +# ## Test class Cs +def test_class(): + + for (arch, mode, code, comment, syntax) in all_tests: + print("*" * 20) + print("Platform: %s" % comment) + print("Code: %s" % to_hex_uc(code)) + print("Disasm:") + + try: + md = Cs(arch, mode) + if syntax is not None: + md.syntax = syntax + md.detail = True + for insn in md.disasm(code, 0x1000): + print_insn_detail(insn) + print () + except CsError as e: + print("ERROR: %s" % e) + + +if __name__ == '__main__': + test_class() diff --git a/config.mk b/config.mk index 1496a1f22a..546d4330fa 100644 --- a/config.mk +++ b/config.mk @@ -4,7 +4,7 @@ ################################################################################ # Specify which archs you want to compile in. By default, we build all archs. -CAPSTONE_ARCHS ?= arm aarch64 m68k mips powerpc sparc systemz x86 xcore tms320c64x +CAPSTONE_ARCHS ?= arm aarch64 m68k mips powerpc sparc systemz x86 xcore tms320c64x m680x ################################################################################ diff --git a/cs.c b/cs.c index 82f9efec8c..449b1da54f 100644 --- a/cs.c +++ b/cs.c @@ -57,6 +57,7 @@ void (*arch_destroy[MAX_ARCH]) (cs_struct *) = { NULL }; extern void ARM_enable(void); extern void AArch64_enable(void); +extern void M680X_enable(void); extern void M68K_enable(void); extern void Mips_enable(void); extern void X86_enable(void); @@ -79,6 +80,9 @@ static void archs_enable(void) #ifdef CAPSTONE_HAS_ARM64 AArch64_enable(); #endif +#ifdef CAPSTONE_HAS_M680X + M680X_enable(); +#endif #ifdef CAPSTONE_HAS_M68K M68K_enable(); #endif @@ -182,7 +186,8 @@ bool CAPSTONE_API cs_support(int query) (1 << CS_ARCH_MIPS) | (1 << CS_ARCH_X86) | (1 << CS_ARCH_PPC) | (1 << CS_ARCH_SPARC) | (1 << CS_ARCH_SYSZ) | (1 << CS_ARCH_XCORE) | - (1 << CS_ARCH_M68K) | (1 << CS_ARCH_TMS320C64X)); + (1 << CS_ARCH_M68K) | (1 << CS_ARCH_TMS320C64X) | + (1 << CS_ARCH_M680X)); if ((unsigned int)query < CS_ARCH_MAX) return all_arch & (1 << query); @@ -439,6 +444,9 @@ static uint8_t skipdata_size(cs_struct *handle) case CS_ARCH_TMS320C64X: // TMS320C64x alignment is 4. return 4; + case CS_ARCH_M680X: + // M680X alignment is 1. + return 1; } } @@ -1140,6 +1148,11 @@ int CAPSTONE_API cs_op_count(csh ud, const cs_insn *insn, unsigned int op_type) if (insn->detail->tms320c64x.operands[i].type == (tms320c64x_op_type)op_type) count++; break; + case CS_ARCH_M680X: + for (i = 0; i < insn->detail->m680x.op_count; i++) + if (insn->detail->m680x.operands[i].type == (m680x_op_type)op_type) + count++; + break; } return count; @@ -1257,6 +1270,14 @@ int CAPSTONE_API cs_op_index(csh ud, const cs_insn *insn, unsigned int op_type, return i; } break; + case CS_ARCH_M680X: + for (i = 0; i < insn->detail->m680x.op_count; i++) { + if (insn->detail->m680x.operands[i].type == (m680x_op_type)op_type) + count++; + if (count == post) + return i; + } + break; } return -1; diff --git a/cs_priv.h b/cs_priv.h index b3ca9936ee..a16f0dd8b3 100644 --- a/cs_priv.h +++ b/cs_priv.h @@ -76,7 +76,7 @@ struct cs_struct { struct insn_mnem *mnem_list; // linked list of customized instruction mnemonic }; -#define MAX_ARCH 10 +#define MAX_ARCH CS_ARCH_MAX // constructor initialization for all archs extern cs_err (*arch_init[MAX_ARCH]) (cs_struct *); diff --git a/cstool/cstool.c b/cstool/cstool.c index 0b3efaeef5..50e3e0ccdb 100644 --- a/cstool/cstool.c +++ b/cstool/cstool.c @@ -44,6 +44,16 @@ static struct { { "m68k40", CS_ARCH_M68K, CS_MODE_M68K_040 }, { "tms320c64x", CS_ARCH_TMS320C64X, CS_MODE_BIG_ENDIAN }, { "tms320c64x", CS_ARCH_TMS320C64X, CS_MODE_BIG_ENDIAN }, + { "m6800", CS_ARCH_M680X, CS_MODE_M680X_6800 }, + { "m6801", CS_ARCH_M680X, CS_MODE_M680X_6801 }, + { "m6805", CS_ARCH_M680X, CS_MODE_M680X_6805 }, + { "m6808", CS_ARCH_M680X, CS_MODE_M680X_6808 }, + { "m6809", CS_ARCH_M680X, CS_MODE_M680X_6809 }, + { "m6811", CS_ARCH_M680X, CS_MODE_M680X_6811 }, + { "cpu12", CS_ARCH_M680X, CS_MODE_M680X_CPU12 }, + { "hd6301", CS_ARCH_M680X, CS_MODE_M680X_6301 }, + { "hd6309", CS_ARCH_M680X, CS_MODE_M680X_6309 }, + { "hcs08", CS_ARCH_M680X, CS_MODE_M680X_HCS08 }, { NULL } }; @@ -57,6 +67,7 @@ void print_insn_detail_sysz(csh handle, cs_insn *ins); void print_insn_detail_xcore(csh handle, cs_insn *ins); void print_insn_detail_m68k(csh handle, cs_insn *ins); void print_insn_detail_tms320c64x(csh handle, cs_insn *ins); +void print_insn_detail_m680x(csh handle, cs_insn *ins); static void print_details(csh handle, cs_arch arch, cs_mode md, cs_insn *ins); void print_string_hex(char *comment, unsigned char *str, size_t len) @@ -175,6 +186,19 @@ static void usage(char *prog) printf(" tms320c64x:TMS320C64x\n"); } + if (cs_support(CS_ARCH_M680X)) { + printf(" m6800: M6800/2\n"); + printf(" m6801: M6801/3\n"); + printf(" m6805: M6805\n"); + printf(" m6808: M68HC08\n"); + printf(" m6809: M6809\n"); + printf(" m6811: M68HC11\n"); + printf(" cpu12: M68HC12/HCS12\n"); + printf(" hd6301: HD6301/3\n"); + printf(" hd6309: HD6309\n"); + printf(" hcs08: HCS08\n"); + } + printf("\nExtra options:\n"); printf(" -d show detailed information of the instructions\n"); printf(" -u show immediates as unsigned\n\n"); @@ -213,6 +237,9 @@ static void print_details(csh handle, cs_arch arch, cs_mode md, cs_insn *ins) case CS_ARCH_TMS320C64X: print_insn_detail_tms320c64x(handle, ins); break; + case CS_ARCH_M680X: + print_insn_detail_m680x(handle, ins); + break; default: break; } @@ -240,7 +267,7 @@ int main(int argc, char **argv) cs_insn *insn; cs_err err; cs_mode md; - cs_arch arch = -1; + cs_arch arch = CS_ARCH_ALL; bool detail_flag = false; bool unsigned_flag = false; int args_left; @@ -301,6 +328,12 @@ int main(int argc, char **argv) } } + if (arch == CS_ARCH_ALL) { + printf("ERROR: Invalid : \"%s\", quit!\n", mode); + usage(argv[0]); + return -1; + } + if (err) { printf("ERROR: Failed on cs_open(), quit!\n"); usage(argv[0]); diff --git a/cstool/cstool_m680x.c b/cstool/cstool_m680x.c new file mode 100644 index 0000000000..841305157d --- /dev/null +++ b/cstool/cstool_m680x.c @@ -0,0 +1,155 @@ +/* Capstone Disassembly Engine */ +/* M680X Backend by Wolfgang Schwotzer 2017 */ + +#include +#include + +void print_string_hex(char *comment, unsigned char *str, size_t len); + +static const char *s_access[] = { + "UNCHANGED", "READ", "WRITE", "READ | WRITE", +}; + +void print_read_write_regs(csh handle, cs_detail *detail) +{ + int i; + + if (detail->regs_read_count > 0) { + printf("\treading from regs: "); + + for (i = 0; i < detail->regs_read_count; ++i) { + if (i > 0) + printf(", "); + + printf("%s", cs_reg_name(handle, detail->regs_read[i])); + } + + printf("\n"); + } + + if (detail->regs_write_count > 0) { + printf("\twriting to regs: "); + + for (i = 0; i < detail->regs_write_count; ++i) { + if (i > 0) + printf(", "); + + printf("%s", cs_reg_name(handle, + detail->regs_write[i])); + } + + printf("\n"); + } +} + +void print_insn_detail_m680x(csh handle, cs_insn *insn) +{ + cs_detail *detail = insn->detail; + cs_m680x *m680x = NULL; + int i; + + // detail can be NULL on "data" instruction if SKIPDATA option is + // turned ON + if (detail == NULL) + return; + + m680x = &detail->m680x; + + if (m680x->op_count) + printf("\top_count: %u\n", m680x->op_count); + + for (i = 0; i < m680x->op_count; i++) { + cs_m680x_op *op = &(m680x->operands[i]); + char *comment; + + switch ((int)op->type) { + default: + break; + + case M680X_OP_REGISTER: + comment = ""; + + if ((i == 0 && m680x->flags & M680X_FIRST_OP_IN_MNEM) || + (i == 1 && m680x->flags & + M680X_SECOND_OP_IN_MNEM)) + comment = " (in mnemonic)"; + + printf("\t\toperands[%u].type: REGISTER = %s%s\n", i, + cs_reg_name(handle, op->reg), comment); + break; + + case M680X_OP_CONSTANT: + printf("\t\toperands[%u].type: CONSTANT = %u\n", i, + op->const_val); + break; + + case M680X_OP_IMMEDIATE: + printf("\t\toperands[%u].type: IMMEDIATE = #%d\n", i, + op->imm); + break; + + case M680X_OP_DIRECT: + printf("\t\toperands[%u].type: DIRECT = 0x%02X\n", i, + op->direct_addr); + break; + + case M680X_OP_EXTENDED: + printf("\t\toperands[%u].type: EXTENDED %s = 0x%04X\n", + i, op->ext.indirect ? "INDIRECT" : "", + op->ext.address); + break; + + case M680X_OP_RELATIVE: + printf("\t\toperands[%u].type: RELATIVE = 0x%04X\n", i, + op->rel.address); + break; + + case M680X_OP_INDEXED: + printf("\t\toperands[%u].type: INDEXED%s\n", i, + (op->idx.flags & M680X_IDX_INDIRECT) ? + " INDIRECT" : ""); + + if (op->idx.base_reg != M680X_REG_INVALID) + printf("\t\t\tbase register: %s\n", + cs_reg_name(handle, op->idx.base_reg)); + + if (op->idx.offset_reg != M680X_REG_INVALID) + printf("\t\t\toffset register: %s\n", + cs_reg_name(handle, op->idx.offset_reg)); + + if ((op->idx.offset_bits != 0) && + (op->idx.offset_reg == M680X_REG_INVALID) && + !op->idx.inc_dec) { + printf("\t\t\toffset: %d\n", op->idx.offset); + + if (op->idx.base_reg == M680X_REG_PC) + printf("\t\t\toffset address: 0x%X\n", + op->idx.offset_addr); + + printf("\t\t\toffset bits: %u\n", + op->idx.offset_bits); + } + + if (op->idx.inc_dec) { + char *post_pre = op->idx.flags & + M680X_IDX_POST_INC_DEC ? "post" : "pre"; + char *inc_dec = (op->idx.inc_dec > 0) ? + "increment" : "decrement"; + + printf("\t\t\t%s %s: %d\n", post_pre, inc_dec, + abs(op->idx.inc_dec)); + } + + break; + } + + if (op->size != 0) + printf("\t\t\tsize: %u\n", op->size); + + if (op->access != CS_AC_INVALID) + printf("\t\t\taccess: %s\n", s_access[op->access]); + } + + print_read_write_regs(handle, detail); +} + diff --git a/include/capstone/capstone.h b/include/capstone/capstone.h index 4da8c97b32..68e3bc6ac3 100644 --- a/include/capstone/capstone.h +++ b/include/capstone/capstone.h @@ -82,6 +82,7 @@ typedef enum cs_arch { CS_ARCH_XCORE, // XCore architecture CS_ARCH_M68K, // 68K architecture CS_ARCH_TMS320C64X, // TMS320C64x architecture + CS_ARCH_M680X, // 680X architecture CS_ARCH_MAX, CS_ARCH_ALL = 0xFFFF, // All architectures - for cs_support() } cs_arch; @@ -121,6 +122,17 @@ typedef enum cs_mode { CS_MODE_BIG_ENDIAN = 1 << 31, // big-endian mode CS_MODE_MIPS32 = CS_MODE_32, // Mips32 ISA (Mips) CS_MODE_MIPS64 = CS_MODE_64, // Mips64 ISA (Mips) + CS_MODE_M680X_6301 = 1 << 1, // M680X Hitachi 6301,6303 mode + CS_MODE_M680X_6309 = 1 << 2, // M680X Hitachi 6309 mode + CS_MODE_M680X_6800 = 1 << 3, // M680X Motorola 6800,6802 mode + CS_MODE_M680X_6801 = 1 << 4, // M680X Motorola 6801,6803 mode + CS_MODE_M680X_6805 = 1 << 5, // M680X Motorola/Freescale 6805 mode + CS_MODE_M680X_6808 = 1 << 6, // M680X Motorola/Freescale/NXP 68HC08 mode + CS_MODE_M680X_6809 = 1 << 7, // M680X Motorola 6809 mode + CS_MODE_M680X_6811 = 1 << 8, // M680X Motorola/Freescale/NXP 68HC11 mode + CS_MODE_M680X_CPU12 = 1 << 9, // M680X Motorola/Freescale/NXP CPU12 + // used on M68HC12/HCS12 + CS_MODE_M680X_HCS08 = 1 << 10, // M680X Freescale/NXP HCS08 mode } cs_mode; typedef void* (CAPSTONE_API *cs_malloc_t)(size_t size); @@ -237,6 +249,7 @@ typedef struct cs_opt_skipdata { // Arm: 2 bytes (Thumb mode) or 4 bytes. // Arm64: 4 bytes. // Mips: 4 bytes. + // M680x: 1 byte. // PowerPC: 4 bytes. // Sparc: 4 bytes. // SystemZ: 2 bytes. @@ -259,6 +272,7 @@ typedef struct cs_opt_skipdata { #include "x86.h" #include "xcore.h" #include "tms320c64x.h" +#include "m680x.h" // NOTE: All information in cs_detail is only available when CS_OPT_DETAIL = CS_OPT_ON typedef struct cs_detail { @@ -283,6 +297,7 @@ typedef struct cs_detail { cs_sysz sysz; // SystemZ architecture cs_xcore xcore; // XCore architecture cs_tms320c64x tms320c64x; // TMS320C64x architecture + cs_m680x m680x; // M680X architecture }; } cs_detail; diff --git a/include/capstone/m680x.h b/include/capstone/m680x.h new file mode 100644 index 0000000000..1ec36bf56e --- /dev/null +++ b/include/capstone/m680x.h @@ -0,0 +1,537 @@ +#ifndef CAPSTONE_M680X_H +#define CAPSTONE_M680X_H + +/* Capstone Disassembly Engine */ +/* M680X Backend by Wolfgang Schwotzer 2017 */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "platform.h" + +#ifdef _MSC_VER +#pragma warning(disable:4201) +#endif + +#define M680X_OPERAND_COUNT 9 + +//> M680X registers and special registers +typedef enum m680x_reg { + M680X_REG_INVALID = 0, + + M680X_REG_A, // M6800/1/2/3/9, HD6301/9 + M680X_REG_B, // M6800/1/2/3/9, HD6301/9 + M680X_REG_E, // HD6309 + M680X_REG_F, // HD6309 + M680X_REG_0, // HD6309 + + M680X_REG_D, // M6801/3/9, HD6301/9 + M680X_REG_W, // HD6309 + + M680X_REG_CC, // M6800/1/2/3/9, M6301/9 + M680X_REG_DP, // M6809/M6309 + M680X_REG_MD, // M6309 + + M680X_REG_HX, // M6808 + M680X_REG_H, // M6808 + M680X_REG_X, // M6800/1/2/3/9, M6301/9 + M680X_REG_Y, // M6809/M6309 + M680X_REG_S, // M6809/M6309 + M680X_REG_U, // M6809/M6309 + M680X_REG_V, // M6309 + + M680X_REG_Q, // M6309 + + M680X_REG_PC, // M6800/1/2/3/9, M6301/9 + + M680X_REG_TMP2, // CPU12 + M680X_REG_TMP3, // CPU12 + + M680X_REG_ENDING, // <-- mark the end of the list of registers +} m680x_reg; + +//> Operand type for instruction's operands +typedef enum m680x_op_type { + M680X_OP_INVALID = 0, // = CS_OP_INVALID (Uninitialized). + M680X_OP_REGISTER, // = Register operand. + M680X_OP_IMMEDIATE, // = Immediate operand. + M680X_OP_INDEXED, // = Indexed addressing operand. + M680X_OP_EXTENDED, // = Extended addressing operand. + M680X_OP_DIRECT, // = Direct addressing operand. + M680X_OP_RELATIVE, // = Relative addressing operand. + M680X_OP_CONSTANT, // = constant operand (Displayed as number only). + // Used e.g. for a bit index or page number. +} m680x_op_type; + +//> Supported bit values for mem.idx.offset_bits +#define M680X_OFFSET_NONE 0 +#define M680X_OFFSET_BITS_5 5 +#define M680X_OFFSET_BITS_8 8 +#define M680X_OFFSET_BITS_9 9 +#define M680X_OFFSET_BITS_16 16 + +//> Supported bit flags for mem.idx.flags +//> These flags can be comined +#define M680X_IDX_INDIRECT 1 +#define M680X_IDX_NO_COMMA 2 +#define M680X_IDX_POST_INC_DEC 4 + +// Instruction's operand referring to indexed addressing +typedef struct m680x_op_idx { + m680x_reg base_reg; // base register (or M680X_REG_INVALID if + // irrelevant) + m680x_reg offset_reg; // offset register (or M680X_REG_INVALID if + // irrelevant) + int16_t offset; // 5-,8- or 16-bit offset. See also offset_bits. + uint16_t offset_addr; // = offset addr. if base_reg == M680X_REG_PC. + // calculated as offset + PC + uint8_t offset_bits; // offset width in bits for indexed addressing + int8_t inc_dec; // inc. or dec. value: + // 0: no inc-/decrement + // 1 .. 8: increment by 1 .. 8 + // -1 .. -8: decrement by 1 .. 8 + // if flag M680X_IDX_POST_INC_DEC set it is post + // inc-/decrement otherwise pre inc-/decrement + uint8_t flags; // 8-bit flags (see above) +} m680x_op_idx; + +// Instruction's memory operand referring to relative addressing (Bcc/LBcc) +typedef struct m680x_op_rel { + uint16_t address; // The absolute address. + // calculated as PC + offset. PC is the first + // address after the instruction. + int16_t offset; // the offset/displacement value +} m680x_op_rel; + +// Instruction's operand referring to extended addressing +typedef struct m680x_op_ext { + uint16_t address; // The absolute address + bool indirect; // true if extended indirect addressing +} m680x_op_ext; + +// Instruction operand +typedef struct cs_m680x_op { + m680x_op_type type; + union { + int32_t imm; // immediate value for IMM operand + m680x_reg reg; // register value for REG operand + m680x_op_idx idx; // Indexed addressing operand + m680x_op_rel rel; // Relative address. operand (Bcc/LBcc) + m680x_op_ext ext; // Extended address + uint8_t direct_addr; // Direct address (lower 8-bit) + uint8_t const_val; // constant value (bit index, page nr.) + }; + uint8_t size; // size of this operand (in bytes) + // How is this operand accessed? (READ, WRITE or READ|WRITE) + // This field is combined of cs_ac_type. + // NOTE: this field is irrelevant if engine is compiled in DIET + uint8_t access; +} cs_m680x_op; + +//> Group of M680X instructions +typedef enum m680x_group_type { + M680X_GRP_INVALID = 0, // = CS_GRP_INVALID + //> Generic groups + // all jump instructions (conditional+direct+indirect jumps) + M680X_GRP_JUMP, // = CS_GRP_JUMP + // all call instructions + M680X_GRP_CALL, // = CS_GRP_CALL + // all return instructions + M680X_GRP_RET, // = CS_GRP_RET + // all interrupt instructions (int+syscall) + M680X_GRP_INT, // = CS_GRP_INT + // all interrupt return instructions + M680X_GRP_IRET, // = CS_GRP_IRET + // all privileged instructions + M680X_GRP_PRIV, // = CS_GRP_PRIVILEDGE; not used + // all relative branching instructions + M680X_GRP_BRAREL, // = CS_GRP_BRANCH_RELATIVE + + //> Architecture-specific groups + M680X_GRP_ENDING, // <-- mark the end of the list of groups +} m680x_group_type; + +//> M680X instruction flags: + +// The first (register) operand is part of the +// instruction mnemonic +#define M680X_FIRST_OP_IN_MNEM 1 +// The second (register) operand is part of the +// instruction mnemonic +#define M680X_SECOND_OP_IN_MNEM 2 + +// The M680X instruction and it's operands +typedef struct cs_m680x { + uint8_t flags; // See: M680X instruction flags + uint8_t op_count; // number of operands for the instruction or 0 + cs_m680x_op operands[M680X_OPERAND_COUNT]; // operands for this insn. +} cs_m680x; + +//> M680X instruction IDs +typedef enum m680x_insn { + M680X_INS_INVLD = 0, + M680X_INS_ABA, // M6800/1/2/3 + M680X_INS_ABX, + M680X_INS_ABY, + M680X_INS_ADC, + M680X_INS_ADCA, + M680X_INS_ADCB, + M680X_INS_ADCD, + M680X_INS_ADCR, + M680X_INS_ADD, + M680X_INS_ADDA, + M680X_INS_ADDB, + M680X_INS_ADDD, + M680X_INS_ADDE, + M680X_INS_ADDF, + M680X_INS_ADDR, + M680X_INS_ADDW, + M680X_INS_AIM, + M680X_INS_AIS, + M680X_INS_AIX, + M680X_INS_AND, + M680X_INS_ANDA, + M680X_INS_ANDB, + M680X_INS_ANDCC, + M680X_INS_ANDD, + M680X_INS_ANDR, + M680X_INS_ASL, + M680X_INS_ASLA, + M680X_INS_ASLB, + M680X_INS_ASLD, // or LSLD + M680X_INS_ASR, + M680X_INS_ASRA, + M680X_INS_ASRB, + M680X_INS_ASRD, + M680X_INS_ASRX, + M680X_INS_BAND, + M680X_INS_BCC, // or BHS + M680X_INS_BCLR, + M680X_INS_BCS, // or BLO + M680X_INS_BEOR, + M680X_INS_BEQ, + M680X_INS_BGE, + M680X_INS_BGND, + M680X_INS_BGT, + M680X_INS_BHCC, + M680X_INS_BHCS, + M680X_INS_BHI, + M680X_INS_BIAND, + M680X_INS_BIEOR, + M680X_INS_BIH, + M680X_INS_BIL, + M680X_INS_BIOR, + M680X_INS_BIT, + M680X_INS_BITA, + M680X_INS_BITB, + M680X_INS_BITD, + M680X_INS_BITMD, + M680X_INS_BLE, + M680X_INS_BLS, + M680X_INS_BLT, + M680X_INS_BMC, + M680X_INS_BMI, + M680X_INS_BMS, + M680X_INS_BNE, + M680X_INS_BOR, + M680X_INS_BPL, + M680X_INS_BRCLR, + M680X_INS_BRSET, + M680X_INS_BRA, + M680X_INS_BRN, + M680X_INS_BSET, + M680X_INS_BSR, + M680X_INS_BVC, + M680X_INS_BVS, + M680X_INS_CALL, + M680X_INS_CBA, // M6800/1/2/3 + M680X_INS_CBEQ, + M680X_INS_CBEQA, + M680X_INS_CBEQX, + M680X_INS_CLC, // M6800/1/2/3 + M680X_INS_CLI, // M6800/1/2/3 + M680X_INS_CLR, + M680X_INS_CLRA, + M680X_INS_CLRB, + M680X_INS_CLRD, + M680X_INS_CLRE, + M680X_INS_CLRF, + M680X_INS_CLRH, + M680X_INS_CLRW, + M680X_INS_CLRX, + M680X_INS_CLV, // M6800/1/2/3 + M680X_INS_CMP, + M680X_INS_CMPA, + M680X_INS_CMPB, + M680X_INS_CMPD, + M680X_INS_CMPE, + M680X_INS_CMPF, + M680X_INS_CMPR, + M680X_INS_CMPS, + M680X_INS_CMPU, + M680X_INS_CMPW, + M680X_INS_CMPX, + M680X_INS_CMPY, + M680X_INS_COM, + M680X_INS_COMA, + M680X_INS_COMB, + M680X_INS_COMD, + M680X_INS_COME, + M680X_INS_COMF, + M680X_INS_COMW, + M680X_INS_COMX, + M680X_INS_CPD, + M680X_INS_CPHX, + M680X_INS_CPS, + M680X_INS_CPX, // M6800/1/2/3 + M680X_INS_CPY, + M680X_INS_CWAI, + M680X_INS_DAA, + M680X_INS_DBEQ, + M680X_INS_DBNE, + M680X_INS_DBNZ, + M680X_INS_DBNZA, + M680X_INS_DBNZX, + M680X_INS_DEC, + M680X_INS_DECA, + M680X_INS_DECB, + M680X_INS_DECD, + M680X_INS_DECE, + M680X_INS_DECF, + M680X_INS_DECW, + M680X_INS_DECX, + M680X_INS_DES, // M6800/1/2/3 + M680X_INS_DEX, // M6800/1/2/3 + M680X_INS_DEY, + M680X_INS_DIV, + M680X_INS_DIVD, + M680X_INS_DIVQ, + M680X_INS_EDIV, + M680X_INS_EDIVS, + M680X_INS_EIM, + M680X_INS_EMACS, + M680X_INS_EMAXD, + M680X_INS_EMAXM, + M680X_INS_EMIND, + M680X_INS_EMINM, + M680X_INS_EMUL, + M680X_INS_EMULS, + M680X_INS_EOR, + M680X_INS_EORA, + M680X_INS_EORB, + M680X_INS_EORD, + M680X_INS_EORR, + M680X_INS_ETBL, + M680X_INS_EXG, + M680X_INS_FDIV, + M680X_INS_IBEQ, + M680X_INS_IBNE, + M680X_INS_IDIV, + M680X_INS_IDIVS, + M680X_INS_ILLGL, + M680X_INS_INC, + M680X_INS_INCA, + M680X_INS_INCB, + M680X_INS_INCD, + M680X_INS_INCE, + M680X_INS_INCF, + M680X_INS_INCW, + M680X_INS_INCX, + M680X_INS_INS, // M6800/1/2/3 + M680X_INS_INX, // M6800/1/2/3 + M680X_INS_INY, + M680X_INS_JMP, + M680X_INS_JSR, + M680X_INS_LBCC, // or LBHS + M680X_INS_LBCS, // or LBLO + M680X_INS_LBEQ, + M680X_INS_LBGE, + M680X_INS_LBGT, + M680X_INS_LBHI, + M680X_INS_LBLE, + M680X_INS_LBLS, + M680X_INS_LBLT, + M680X_INS_LBMI, + M680X_INS_LBNE, + M680X_INS_LBPL, + M680X_INS_LBRA, + M680X_INS_LBRN, + M680X_INS_LBSR, + M680X_INS_LBVC, + M680X_INS_LBVS, + M680X_INS_LDA, + M680X_INS_LDAA, // M6800/1/2/3 + M680X_INS_LDAB, // M6800/1/2/3 + M680X_INS_LDB, + M680X_INS_LDBT, + M680X_INS_LDD, + M680X_INS_LDE, + M680X_INS_LDF, + M680X_INS_LDHX, + M680X_INS_LDMD, + M680X_INS_LDQ, + M680X_INS_LDS, + M680X_INS_LDU, + M680X_INS_LDW, + M680X_INS_LDX, + M680X_INS_LDY, + M680X_INS_LEAS, + M680X_INS_LEAU, + M680X_INS_LEAX, + M680X_INS_LEAY, + M680X_INS_LSL, + M680X_INS_LSLA, + M680X_INS_LSLB, + M680X_INS_LSLD, + M680X_INS_LSLX, + M680X_INS_LSR, + M680X_INS_LSRA, + M680X_INS_LSRB, + M680X_INS_LSRD, // or ASRD + M680X_INS_LSRW, + M680X_INS_LSRX, + M680X_INS_MAXA, + M680X_INS_MAXM, + M680X_INS_MEM, + M680X_INS_MINA, + M680X_INS_MINM, + M680X_INS_MOV, + M680X_INS_MOVB, + M680X_INS_MOVW, + M680X_INS_MUL, + M680X_INS_MULD, + M680X_INS_NEG, + M680X_INS_NEGA, + M680X_INS_NEGB, + M680X_INS_NEGD, + M680X_INS_NEGX, + M680X_INS_NOP, + M680X_INS_NSA, + M680X_INS_OIM, + M680X_INS_ORA, + M680X_INS_ORAA, // M6800/1/2/3 + M680X_INS_ORAB, // M6800/1/2/3 + M680X_INS_ORB, + M680X_INS_ORCC, + M680X_INS_ORD, + M680X_INS_ORR, + M680X_INS_PSHA, // M6800/1/2/3 + M680X_INS_PSHB, // M6800/1/2/3 + M680X_INS_PSHC, + M680X_INS_PSHD, + M680X_INS_PSHH, + M680X_INS_PSHS, + M680X_INS_PSHSW, + M680X_INS_PSHU, + M680X_INS_PSHUW, + M680X_INS_PSHX, // M6800/1/2/3 + M680X_INS_PSHY, + M680X_INS_PULA, // M6800/1/2/3 + M680X_INS_PULB, // M6800/1/2/3 + M680X_INS_PULC, + M680X_INS_PULD, + M680X_INS_PULH, + M680X_INS_PULS, + M680X_INS_PULSW, + M680X_INS_PULU, + M680X_INS_PULUW, + M680X_INS_PULX, // M6800/1/2/3 + M680X_INS_PULY, + M680X_INS_REV, + M680X_INS_REVW, + M680X_INS_ROL, + M680X_INS_ROLA, + M680X_INS_ROLB, + M680X_INS_ROLD, + M680X_INS_ROLW, + M680X_INS_ROLX, + M680X_INS_ROR, + M680X_INS_RORA, + M680X_INS_RORB, + M680X_INS_RORD, + M680X_INS_RORW, + M680X_INS_RORX, + M680X_INS_RSP, + M680X_INS_RTC, + M680X_INS_RTI, + M680X_INS_RTS, + M680X_INS_SBA, // M6800/1/2/3 + M680X_INS_SBC, + M680X_INS_SBCA, + M680X_INS_SBCB, + M680X_INS_SBCD, + M680X_INS_SBCR, + M680X_INS_SEC, + M680X_INS_SEI, + M680X_INS_SEV, + M680X_INS_SEX, + M680X_INS_SEXW, + M680X_INS_SLP, + M680X_INS_STA, + M680X_INS_STAA, // M6800/1/2/3 + M680X_INS_STAB, // M6800/1/2/3 + M680X_INS_STB, + M680X_INS_STBT, + M680X_INS_STD, + M680X_INS_STE, + M680X_INS_STF, + M680X_INS_STOP, + M680X_INS_STHX, + M680X_INS_STQ, + M680X_INS_STS, + M680X_INS_STU, + M680X_INS_STW, + M680X_INS_STX, + M680X_INS_STY, + M680X_INS_SUB, + M680X_INS_SUBA, + M680X_INS_SUBB, + M680X_INS_SUBD, + M680X_INS_SUBE, + M680X_INS_SUBF, + M680X_INS_SUBR, + M680X_INS_SUBW, + M680X_INS_SWI, + M680X_INS_SWI2, + M680X_INS_SWI3, + M680X_INS_SYNC, + M680X_INS_TAB, // M6800/1/2/3 + M680X_INS_TAP, // M6800/1/2/3 + M680X_INS_TAX, + M680X_INS_TBA, // M6800/1/2/3 + M680X_INS_TBEQ, + M680X_INS_TBL, + M680X_INS_TBNE, + M680X_INS_TEST, + M680X_INS_TFM, + M680X_INS_TFR, + M680X_INS_TIM, + M680X_INS_TPA, // M6800/1/2/3 + M680X_INS_TST, + M680X_INS_TSTA, + M680X_INS_TSTB, + M680X_INS_TSTD, + M680X_INS_TSTE, + M680X_INS_TSTF, + M680X_INS_TSTW, + M680X_INS_TSTX, + M680X_INS_TSX, // M6800/1/2/3 + M680X_INS_TSY, + M680X_INS_TXA, + M680X_INS_TXS, // M6800/1/2/3 + M680X_INS_TYS, + M680X_INS_WAI, // M6800/1/2/3 + M680X_INS_WAIT, + M680X_INS_WAV, + M680X_INS_WAVR, + M680X_INS_XGDX, // HD6301 + M680X_INS_XGDY, + M680X_INS_ENDING, // <-- mark the end of the list of instructions +} m680x_insn; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/suite/fuzz/fuzz_harness.c b/suite/fuzz/fuzz_harness.c index a7d817682f..b69d3ba47d 100644 --- a/suite/fuzz/fuzz_harness.c +++ b/suite/fuzz/fuzz_harness.c @@ -112,6 +112,11 @@ int main(int argc, char **argv) (cs_mode)0, "M68K" }, + { + CS_ARCH_M680X, + (cs_mode)CS_MODE_M680X_6809, + "M680X_M6809" + }, }; // Read input diff --git a/tests/Makefile b/tests/Makefile index 36a53840ed..57d90651ef 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -105,6 +105,10 @@ ifneq (,$(findstring tms320c64x,$(CAPSTONE_ARCHS))) CFLAGS += -DCAPSTONE_HAS_TMS320C64X SOURCES += test_tms320c64x.c endif +ifneq (,$(findstring m680x,$(CAPSTONE_ARCHS))) +CFLAGS += -DCAPSTONE_HAS_M680X +SOURCES += test_m680x.c +endif OBJS = $(addprefix $(OBJDIR)/,$(SOURCES:.c=.o)) BINARY = $(addprefix $(TESTDIR)/,$(SOURCES:.c=$(BIN_EXT))) diff --git a/tests/test_basic.c b/tests/test_basic.c index 92d84d6969..40e24c53eb 100644 --- a/tests/test_basic.c +++ b/tests/test_basic.c @@ -78,6 +78,10 @@ static void test() #ifdef CAPSTONE_HAS_TMS320C64X #define TMS320C64X_CODE "\x01\xac\x88\x40\x81\xac\x88\x43\x00\x00\x00\x00\x02\x90\x32\x96\x02\x80\x46\x9e\x05\x3c\x83\xe6\x0b\x0c\x8b\x24" #endif +#ifdef CAPSTONE_HAS_M680X +#define M680X_CODE "\x06\x10\x19\x1a\x55\x1e\x01\x23\xe9\x31\x06\x34\x55\xa6\x81\xa7\x89\x7f\xff\xa6\x9d\x10\x00\xa7\x91\xa6\x9f\x10\x00\x11\xac\x99\x10\x00\x39" +#endif + struct platform { cs_arch arch; @@ -289,6 +293,15 @@ static void test() sizeof(TMS320C64X_CODE) - 1, "TMS320C64x", }, +#endif +#ifdef CAPSTONE_HAS_M680X + { + CS_ARCH_M680X, + (cs_mode)(CS_MODE_M680X_6809), + (unsigned char*)M680X_CODE, + sizeof(M680X_CODE) - 1, + "M680X_M6809", + }, #endif }; diff --git a/tests/test_detail.c b/tests/test_detail.c index fd914a1d54..d9a48dd203 100644 --- a/tests/test_detail.c +++ b/tests/test_detail.c @@ -83,6 +83,10 @@ static void test() #ifdef CAPSTONE_HAS_M68K #define M68K_CODE "\xd4\x40\x87\x5a\x4e\x71\x02\xb4\xc0\xde\xc0\xde\x5c\x00\x1d\x80\x71\x12\x01\x23\xf2\x3c\x44\x22\x40\x49\x0e\x56\x54\xc5\xf2\x3c\x44\x00\x44\x7a\x00\x00\xf2\x00\x0a\x28" #endif +#ifdef CAPSTONE_HAS_M680X +#define M680X_CODE "\x06\x10\x19\x1a\x55\x1e\x01\x23\xe9\x31\x06\x34\x55\xa6\x81\xa7\x89\x7f\xff\xa6\x9d\x10\x00\xa7\x91\xa6\x9f\x10\x00\x11\xac\x99\x10\x00\x39" +#endif + struct platform platforms[] = { #ifdef CAPSTONE_HAS_X86 @@ -258,6 +262,15 @@ static void test() sizeof(M68K_CODE) - 1, "M68K", }, +#endif +#ifdef CAPSTONE_HAS_M680X + { + CS_ARCH_M680X, + (cs_mode)(CS_MODE_M680X_6809), + (unsigned char*)M680X_CODE, + sizeof(M680X_CODE) - 1, + "M680X_M6809", + }, #endif }; diff --git a/tests/test_iter.c b/tests/test_iter.c index 47f2f95a4b..ec258a7685 100644 --- a/tests/test_iter.c +++ b/tests/test_iter.c @@ -75,6 +75,9 @@ static void test() #endif #ifdef CAPSTONE_HAS_XCORE #define XCORE_CODE "\xfe\x0f\xfe\x17\x13\x17\xc6\xfe\xec\x17\x97\xf8\xec\x4f\x1f\xfd\xec\x37\x07\xf2\x45\x5b\xf9\xfa\x02\x06\x1b\x10" +#endif +#ifdef CAPSTONE_HAS_M680X +#define M680X_CODE "\x06\x10\x19\x1a\x55\x1e\x01\x23\xe9\x31\x06\x34\x55\xa6\x81\xa7\x89\x7f\xff\xa6\x9d\x10\x00\xa7\x91\xa6\x9f\x10\x00\x11\xac\x99\x10\x00\x39" #endif struct platform platforms[] = { @@ -207,6 +210,15 @@ static void test() sizeof(XCORE_CODE) - 1, "XCore" }, +#endif +#ifdef CAPSTONE_HAS_M680X + { + CS_ARCH_M680X, + (cs_mode)CS_MODE_M680X_6809, + (unsigned char*)M680X_CODE, + sizeof(M680X_CODE) - 1, + "M680X_6809" + }, #endif }; diff --git a/tests/test_m680x.c b/tests/test_m680x.c new file mode 100644 index 0000000000..699453d813 --- /dev/null +++ b/tests/test_m680x.c @@ -0,0 +1,398 @@ +/* Capstone Disassembler Engine */ +/* M680X Backend by Wolfgang Schwotzer 2017 */ + +#include +#include + +#include +#include + +#define ARR_SIZE(a) (sizeof(a)/sizeof(a[0])) + +#define WITH_DETAILS + +struct platform { + cs_arch arch; + cs_mode mode; + unsigned char *code; + size_t size; + char *comment; +}; + +static void print_string_hex(char *comment, unsigned char *str, size_t len) +{ + unsigned char *c; + + printf("%s", comment); + + for (c = str; c < str + len; c++) + printf("0x%02X ", *c & 0xff); + + printf("\n"); +} + +static void print_string_hex_short(unsigned char *str, size_t len) +{ + unsigned char *c; + + for (c = str; c < str + len; c++) + printf("%02X", *c & 0xff); +} + +static const char *s_access[] = { + "UNCHANGED", "READ", "WRITE", "READ | WRITE", +}; + +static void print_read_write_regs(csh handle, cs_detail *detail) +{ + int i; + + if (detail->regs_read_count > 0) { + printf("\tRegisters read:"); + + for (i = 0; i < detail->regs_read_count; ++i) + printf(" %s", + cs_reg_name(handle, detail->regs_read[i])); + + printf("\n"); + } + + if (detail->regs_write_count > 0) { + printf("\tRegisters modified:"); + + for (i = 0; i < detail->regs_write_count; ++i) + printf(" %s", + cs_reg_name(handle, detail->regs_write[i])); + + printf("\n"); + } +} + +static void print_insn_detail(csh handle, cs_insn *insn) +{ + cs_detail *detail = insn->detail; + cs_m680x *m680x = NULL; + int i; + + // detail can be NULL on "data" instruction if SKIPDATA option is turned ON + if (detail == NULL) + return; + + m680x = &detail->m680x; + + if (m680x->op_count) + printf("\top_count: %u\n", m680x->op_count); + + for (i = 0; i < m680x->op_count; i++) { + cs_m680x_op *op = &(m680x->operands[i]); + char *comment; + + switch ((int)op->type) { + default: + break; + + case M680X_OP_REGISTER: + comment = ""; + + if ((i == 0 && (m680x->flags & + M680X_FIRST_OP_IN_MNEM)) || + ((i == 1 && (m680x->flags & + M680X_SECOND_OP_IN_MNEM)))) + comment = " (in mnemonic)"; + + printf("\t\toperands[%u].type: REGISTER = %s%s\n", i, + cs_reg_name(handle, op->reg), comment); + break; + + case M680X_OP_CONSTANT: + printf("\t\toperands[%u].type: CONSTANT = %u\n", i, + op->const_val); + break; + + case M680X_OP_IMMEDIATE: + printf("\t\toperands[%u].type: IMMEDIATE = #%d\n", i, + op->imm); + break; + + case M680X_OP_DIRECT: + printf("\t\toperands[%u].type: DIRECT = 0x%02X\n", i, + op->direct_addr); + break; + + case M680X_OP_EXTENDED: + printf("\t\toperands[%u].type: EXTENDED %s = 0x%04X\n", + i, op->ext.indirect ? "INDIRECT" : "", + op->ext.address); + break; + + case M680X_OP_RELATIVE: + printf("\t\toperands[%u].type: RELATIVE = 0x%04X\n", i, + op->rel.address); + break; + + case M680X_OP_INDEXED: + printf("\t\toperands[%u].type: INDEXED%s\n", i, + (op->idx.flags & M680X_IDX_INDIRECT) ? + " INDIRECT" : ""); + + if (op->idx.base_reg != M680X_REG_INVALID) + printf("\t\t\tbase register: %s\n", + cs_reg_name(handle, op->idx.base_reg)); + + if (op->idx.offset_reg != M680X_REG_INVALID) + printf("\t\t\toffset register: %s\n", + cs_reg_name(handle, op->idx.offset_reg)); + + if ((op->idx.offset_bits != 0) && + (op->idx.offset_reg == M680X_REG_INVALID) && + !op->idx.inc_dec) { + printf("\t\t\toffset: %d\n", op->idx.offset); + + if (op->idx.base_reg == M680X_REG_PC) + printf("\t\t\toffset address: 0x%X\n", + op->idx.offset_addr); + + printf("\t\t\toffset bits: %u\n", + op->idx.offset_bits); + } + + if (op->idx.inc_dec) { + char *post_pre = op->idx.flags & + M680X_IDX_POST_INC_DEC ? "post" : "pre"; + char *inc_dec = (op->idx.inc_dec > 0) ? + "increment" : "decrement"; + + printf("\t\t\t%s %s: %d\n", post_pre, inc_dec, + abs(op->idx.inc_dec)); + } + + break; + } + + if (op->size != 0) + printf("\t\t\tsize: %u\n", op->size); + + if (op->access != CS_AC_INVALID) + printf("\t\t\taccess: %s\n", s_access[op->access]); + + } + + print_read_write_regs(handle, detail); + + if (detail->groups_count) { + printf("\tgroups_count: %u\n", detail->groups_count); + } + + printf("\n"); +} + +static bool consistency_checks() +{ + return true; +} + +static void test() +{ +#define M6800_CODE \ + "\x01\x09\x36\x64\x7f\x74\x10\x00\x90\x10\xA4\x10\xb6\x10\x00\x39" + +#define M6801_CODE \ + "\x04\x05\x3c\x3d\x38\x93\x10\xec\x10\xed\x10\x39" + +#define M6805_CODE \ + "\x04\x7f\x00\x17\x22\x28\x00\x2e\x00\x40\x42\x5a\x70\x8e\x97\x9c" \ + "\xa0\x15\xad\x00\xc3\x10\x00\xda\x12\x34\xe5\x7f\xfe" + +#define M6808_CODE \ + "\x31\x22\x00\x35\x22\x45\x10\x00\x4b\x00\x51\x10\x52\x5e\x22\x62" \ + "\x65\x12\x34\x72\x84\x85\x86\x87\x8a\x8b\x8c\x94\x95\xa7\x10\xaf\x10" \ + "\x9e\x60\x7f\x9e\x6b\x7f\x00\x9e\xd6\x10\x00\x9e\xe6\x7f" + +#define HCS08_CODE \ + "\x32\x10\x00\x9e\xae\x9e\xce\x7f\x9e\xbe\x10\x00\x9e\xfe\x7f" \ + "\x3e\x10\x00\x9e\xf3\x7f\x96\x10\x00\x9e\xff\x7f\x82" + +#define M6811_CODE \ + "\x02\x03\x12\x7f\x10\x00\x13\x99\x08\x00\x14\x7f\x02\x15\x7f\x01" \ + "\x1e\x7f\x20\x00\x8f\xcf" \ + "\x18\x08\x18\x30\x18\x3c\x18\x67\x18\x8c\x10\x00\x18\x8f" \ + "\x18\xce\x10\x00\x18\xff\x10\x00" \ + "\x1a\xa3\x7f\x1a\xac\x1a\xee\x7f\x1a\xef\x7f\xcd\xac\x7f" + +#define CPU12_CODE \ + "\x00\x04\x01\x00\x0c\x00\x80\x0e\x00\x80\x00\x11\x1e\x10\x00\x80\x00" \ + "\x3b\x4a\x10\x00\x04\x4b\x01\x04\x4f\x7f\x80\x00\x8f\x10\x00\xb7\x52" \ + "\xb7\xb1\xa6\x67\xa6\xfe\xa6\xf7\x18\x02\xe2\x30\x39\xe2\x10\x00" \ + "\x18\x0c\x30\x39\x10\x00\x18\x11\x18\x12\x10\x00\x18\x19\x00\x18\x1e\x00" \ + "\x18\x3e\x18\x3f\x00" + +#define HD6301_CODE \ + "\x6b\x10\x00\x71\x10\x00\x72\x10\x10\x39" + +#define M6809_CODE \ + "\x06\x10\x19\x1a\x55\x1e\x01\x23\xe9\x31\x06\x34\x55\xa6\x81" \ + "\xa7\x89\x7f\xff\xa6\x9d\x10\x00\xa7\x91\xa6\x9f\x10\x00" \ + "\x11\xac\x99\x10\x00\x39" \ + \ + "\xA6\x07\xA6\x27\xA6\x47\xA6\x67\xA6\x0F\xA6\x10" \ + "\xA6\x80\xA6\x81\xA6\x82\xA6\x83\xA6\x84\xA6\x85\xA6\x86" \ + "\xA6\x88\x7F\xA6\x88\x80\xA6\x89\x7F\xFF\xA6\x89\x80\x00" \ + "\xA6\x8B\xA6\x8C\x10\xA6\x8D\x10\x00" \ + \ + "\xA6\x91\xA6\x93\xA6\x94\xA6\x95\xA6\x96" \ + "\xA6\x98\x7F\xA6\x98\x80\xA6\x99\x7F\xFF\xA6\x99\x80\x00" \ + "\xA6\x9B\xA6\x9C\x10\xA6\x9D\x10\x00\xA6\x9F\x10\x00" + + +#define HD6309_CODE \ + "\x01\x10\x10\x62\x10\x10\x7b\x10\x10\x00\xcd\x49\x96\x02\xd2" \ + "\x10\x30\x23\x10\x38\x10\x3b\x10\x53\x10\x5d" \ + "\x11\x30\x43\x10\x11\x37\x25\x10\x11\x38\x12\x11\x39\x23\x11\x3b\x34" \ + "\x11\x8e\x10\x00\x11\xaf\x10\x11\xab\x10\x11\xf6\x80\x00" + + struct platform platforms[] = { + { + CS_ARCH_M680X, + (cs_mode)(CS_MODE_M680X_6301), + (unsigned char *)HD6301_CODE, + sizeof(HD6301_CODE) - 1, + "M680X_HD6301", + }, + { + CS_ARCH_M680X, + (cs_mode)(CS_MODE_M680X_6309), + (unsigned char *)HD6309_CODE, + sizeof(HD6309_CODE) - 1, + "M680X_HD6309", + }, + { + CS_ARCH_M680X, + (cs_mode)(CS_MODE_M680X_6800), + (unsigned char *)M6800_CODE, + sizeof(M6800_CODE) - 1, + "M680X_M6800", + }, + { + CS_ARCH_M680X, + (cs_mode)(CS_MODE_M680X_6801), + (unsigned char *)M6801_CODE, + sizeof(M6801_CODE) - 1, + "M680X_M6801", + }, + { + CS_ARCH_M680X, + (cs_mode)(CS_MODE_M680X_6805), + (unsigned char *)M6805_CODE, + sizeof(M6805_CODE) - 1, + "M680X_M68HC05", + }, + { + CS_ARCH_M680X, + (cs_mode)(CS_MODE_M680X_6808), + (unsigned char *)M6808_CODE, + sizeof(M6808_CODE) - 1, + "M680X_M68HC08", + }, + { + CS_ARCH_M680X, + (cs_mode)(CS_MODE_M680X_6809), + (unsigned char *)M6809_CODE, + sizeof(M6809_CODE) - 1, + "M680X_M6809", + }, + { + CS_ARCH_M680X, + (cs_mode)(CS_MODE_M680X_6811), + (unsigned char *)M6811_CODE, + sizeof(M6811_CODE) - 1, + "M680X_M68HC11", + }, + { + CS_ARCH_M680X, + (cs_mode)(CS_MODE_M680X_CPU12), + (unsigned char *)CPU12_CODE, + sizeof(CPU12_CODE) - 1, + "M680X_CPU12", + }, + { + CS_ARCH_M680X, + (cs_mode)(CS_MODE_M680X_HCS08), + (unsigned char *)HCS08_CODE, + sizeof(HCS08_CODE) - 1, + "M680X_HCS08", + }, + }; + + uint64_t address = 0x1000; + csh handle; + cs_insn *insn; + int i; + size_t count; + char *nine_spaces = " "; + + if (!consistency_checks()) + abort(); + + for (i = 0; i < sizeof(platforms) / sizeof(platforms[0]); i++) { + cs_err err = cs_open(platforms[i].arch, platforms[i].mode, + &handle); + + if (err) { + printf("Failed on cs_open() with error returned: %u\n", + err); + abort(); + } + +#ifdef WITH_DETAILS + cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); +#endif + + count = cs_disasm(handle, platforms[i].code, platforms[i].size, + address, 0, &insn); + + if (count) { + size_t j; + + printf("********************\n"); + printf("Platform: %s\n", platforms[i].comment); + print_string_hex("Code: ", platforms[i].code, + platforms[i].size); + printf("Disasm:\n"); + + for (j = 0; j < count; j++) { + printf("0x%04X: ", (uint16_t)insn[j].address); + print_string_hex_short(insn[j].bytes, + insn[j].size); + printf("%.*s", 1 + ((5 - insn[j].size) * 2), + nine_spaces); + printf("%s", insn[j].mnemonic); + int slen = (int)strlen(insn[j].mnemonic); + printf("%.*s", 1 + (5 - slen), nine_spaces); + printf("%s\n", insn[j].op_str); +#ifdef WITH_DETAILS + print_insn_detail(handle, &insn[j]); +#endif + } + + // free memory allocated by cs_disasm() + cs_free(insn, count); + } + else { + printf("********************\n"); + printf("Platform: %s\n", platforms[i].comment); + print_string_hex("Code:", platforms[i].code, + platforms[i].size); + printf("ERROR: Failed to disasm given code!\n"); + abort(); + } + + cs_close(&handle); + } +} + +int main() +{ + test(); + + return 0; +} diff --git a/utils.h b/utils.h index 62cbc95efe..e1d9ad6d67 100644 --- a/utils.h +++ b/utils.h @@ -52,6 +52,7 @@ unsigned int count_positive(uint16_t *list); unsigned int count_positive8(unsigned char *list); #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0])) +#define MATRIX_SIZE(a) (sizeof(a[0])/sizeof(a[0][0])) char *cs_strdup(const char *str);