Add support for the MOS65XX family such as the MOS 6502.

Signed-off-by: Sebastian Macke <sebastian@macke.de>
This commit is contained in:
Sebastian Macke 2018-12-02 21:39:41 +01:00
parent a69f7880a8
commit 87221fa742
16 changed files with 1163 additions and 6 deletions

View File

@ -28,8 +28,8 @@ option(CAPSTONE_BUILD_TESTS "Build tests" ON)
option(CAPSTONE_BUILD_CSTOOL "Build cstool" 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 M680X EVM)
set(SUPPORTED_ARCHITECTURE_LABELS ARM ARM64 M68K MIPS PowerPC Sparc SystemZ XCore x86 TMS320C64x M680x EVM)
set(SUPPORTED_ARCHITECTURES ARM ARM64 M68K MIPS PPC SPARC SYSZ XCORE X86 TMS320C64X M680X EVM MOS65XX)
set(SUPPORTED_ARCHITECTURE_LABELS ARM ARM64 M68K MIPS PowerPC Sparc SystemZ XCore x86 TMS320C64x M680x EVM MOS65XX)
list(LENGTH SUPPORTED_ARCHITECTURES count)
math(EXPR count "${count}-1")
@ -112,6 +112,7 @@ set(HEADERS_COMMON
include/capstone/m68k.h
include/capstone/tms320c64x.h
include/capstone/m680x.h
include/capstone/mos65xx.h
include/capstone/platform.h
)
@ -444,6 +445,17 @@ if (CAPSTONE_EVM_SUPPORT)
set(TEST_SOURCES ${TEST_SOURCES} test_evm.c)
endif ()
if (CAPSTONE_MOS65XX_SUPPORT)
add_definitions(-DCAPSTONE_HAS_MOS65XX)
set(SOURCES_MOS65XX
arch/MOS65XX/MOS65XXModule.c
arch/MOS65XX/MOS65XXDisassembler.c)
set(HEADERS_SOURCES_MOS65XX
arch/MOS65XX/MOS65XXDisassembler.h
)
set(TEST_SOURCES ${TEST_SOURCES} test_mos65xx.c)
endif ()
if (CAPSTONE_OSXKERNEL_SUPPORT)
add_definitions(-DCAPSTONE_HAS_OSXKERNEL)
endif ()
@ -462,6 +474,7 @@ set(ALL_SOURCES
${SOURCES_TMS320C64X}
${SOURCES_M680X}
${SOURCES_EVM}
${SOURCES_MOS65XX}
)
set(ALL_HEADERS
@ -479,6 +492,7 @@ set(ALL_HEADERS
${HEADERS_TMS320C64X}
${HEADERS_M680X}
${HEADERS_EVM}
${HEADERS_MOS65XX}
)
include_directories("${PROJECT_SOURCE_DIR}/include")
@ -559,6 +573,7 @@ source_group("Source\\M68K" FILES ${SOURCES_M68K})
source_group("Source\\TMS320C64x" FILES ${SOURCES_TMS320C64X})
source_group("Source\\M680X" FILES ${SOURCES_M680X})
source_group("Source\\EVM" FILES ${SOURCES_EVM})
source_group("Source\\MOS65XX" FILES ${SOURCES_MOS65XX})
source_group("Include\\Common" FILES ${HEADERS_COMMON})
source_group("Include\\Engine" FILES ${HEADERS_ENGINE})
@ -574,6 +589,7 @@ source_group("Include\\M68K" FILES ${HEADERS_M68K})
source_group("Include\\TMS320C64x" FILES ${HEADERS_TMS320C64X})
source_group("Include\\M680X" FILES ${HEADERS_MC680X})
source_group("Include\\EVM" FILES ${HEADERS_EVM})
source_group("Include\\MOS65XX" FILES ${HEADERS_MOS65XX})
### test library 64bit routine:
get_property(LIB64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS)

View File

@ -250,9 +250,21 @@ ifneq (,$(findstring evm,$(CAPSTONE_ARCHS)))
endif
DEP_MOS65XX =
DEP_MOS65XX += $(wildcard arch/MOS65XX/MOS65XX*.inc)
LIBOBJ_MOS65XX =
ifneq (,$(findstring mos65xx,$(CAPSTONE_ARCHS)))
CFLAGS += -DCAPSTONE_HAS_MOS65XX
LIBSRC_MOS65XX += $(wildcard arch/MOS65XX/MOS65XX*.c)
LIBOBJ_MOS65XX += $(LIBSRC_MOS65XX:%.c=$(OBJDIR)/%.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_M680X) $(LIBOBJ_EVM)
LIBOBJ += $(LIBOBJ_ARM) $(LIBOBJ_ARM64) $(LIBOBJ_M68K) $(LIBOBJ_MIPS) $(LIBOBJ_PPC) $(LIBOBJ_SPARC) $(LIBOBJ_SYSZ)
LIBOBJ += $(LIBOBJ_X86) $(LIBOBJ_XCORE) $(LIBOBJ_TMS320C64X) $(LIBOBJ_M680X) $(LIBOBJ_EVM) $(LIBOBJ_MOS65XX)
LIBOBJ += $(OBJDIR)/MCInst.o
@ -381,6 +393,7 @@ $(LIBOBJ_XCORE): $(DEP_XCORE)
$(LIBOBJ_TMS320C64X): $(DEP_TMS320C64X)
$(LIBOBJ_M680X): $(DEP_M680X)
$(LIBOBJ_EVM): $(DEP_EVM)
$(LIBOBJ_MOS65XX): $(DEP_MOS65XX)
ifeq ($(CAPSTONE_STATIC),yes)
$(ARCHIVE): $(LIBOBJ)
@ -456,11 +469,12 @@ dist:
TESTS = test_basic test_detail test_arm test_arm64 test_m68k test_mips test_ppc test_sparc
TESTS += test_systemz test_x86 test_xcore test_iter test_evm
TESTS += test_systemz test_x86 test_xcore test_iter test_evm test_mos65xx
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 test_m680x.static
TESTS += test_skipdata test_skipdata.static test_iter.static test_evm.static
TESTS += test_mos65xx.static
check: $(TESTS) fuzztest
test_%:
./tests/$@ > /dev/null && echo OK || echo FAILED

View File

@ -0,0 +1,591 @@
/* Capstone Disassembly Engine */
/* MOS65XX Backend by Sebastian Macke <sebastian@macke.de> 2018 */
#include "capstone/mos65xx.h"
#include "MOS65XXDisassembler.h"
typedef struct OpInfo {
mos65xx_insn ins;
mos65xx_address_mode am;
} OpInfo;
const struct OpInfo OpInfoTable[]= {
MOS65XX_INS_BRK , MOS65XX_AM_IMP , // 0x00
MOS65XX_INS_ORA , MOS65XX_AM_INDX, // 0x01
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x02
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x03
MOS65XX_INS_NOP , MOS65XX_AM_ZP , // 0x04
MOS65XX_INS_ORA , MOS65XX_AM_ZP , // 0x05
MOS65XX_INS_ASL , MOS65XX_AM_ZP , // 0x06
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x07
MOS65XX_INS_PHP , MOS65XX_AM_IMP , // 0x08
MOS65XX_INS_ORA , MOS65XX_AM_IMM , // 0x09
MOS65XX_INS_ASL , MOS65XX_AM_ACC , // 0x0a
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x0b
MOS65XX_INS_NOP , MOS65XX_AM_ABS , // 0x0c
MOS65XX_INS_ORA , MOS65XX_AM_ABS , // 0x0d
MOS65XX_INS_ASL , MOS65XX_AM_ABS , // 0x0e
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x0f
MOS65XX_INS_BPL , MOS65XX_AM_REL , // 0x10
MOS65XX_INS_ORA , MOS65XX_AM_INDY, // 0x11
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x12
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x13
MOS65XX_INS_NOP , MOS65XX_AM_ZPX , // 0x14
MOS65XX_INS_ORA , MOS65XX_AM_ZPX , // 0x15
MOS65XX_INS_ASL , MOS65XX_AM_ZPX , // 0x16
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x17
MOS65XX_INS_CLC , MOS65XX_AM_IMP , // 0x18
MOS65XX_INS_ORA , MOS65XX_AM_ABSY, // 0x19
MOS65XX_INS_NOP , MOS65XX_AM_IMP , // 0x1a
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x1b
MOS65XX_INS_NOP , MOS65XX_AM_ABS , // 0x1c
MOS65XX_INS_ORA , MOS65XX_AM_ABSX, // 0x1d
MOS65XX_INS_ASL , MOS65XX_AM_ABSX, // 0x1e
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x1f
MOS65XX_INS_JSR , MOS65XX_AM_ABS , // 0x20
MOS65XX_INS_AND , MOS65XX_AM_INDX, // 0x21
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x22
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x23
MOS65XX_INS_BIT , MOS65XX_AM_ZP , // 0x24
MOS65XX_INS_AND , MOS65XX_AM_ZP , // 0x25
MOS65XX_INS_ROL , MOS65XX_AM_ZP , // 0x26
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x27
MOS65XX_INS_PLP , MOS65XX_AM_IMP , // 0x28
MOS65XX_INS_AND , MOS65XX_AM_IMM , // 0x29
MOS65XX_INS_ROL , MOS65XX_AM_ACC , // 0x2a
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x2b
MOS65XX_INS_BIT , MOS65XX_AM_ABS , // 0x2c
MOS65XX_INS_AND , MOS65XX_AM_ABS , // 0x2d
MOS65XX_INS_ROL , MOS65XX_AM_ABS , // 0x2e
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x2f
MOS65XX_INS_BMI , MOS65XX_AM_REL , // 0x30
MOS65XX_INS_AND , MOS65XX_AM_INDY, // 0x31
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x32
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x33
MOS65XX_INS_NOP , MOS65XX_AM_ZPX , // 0x34
MOS65XX_INS_AND , MOS65XX_AM_ZPX , // 0x35
MOS65XX_INS_ROL , MOS65XX_AM_ZPX , // 0x36
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x37
MOS65XX_INS_SEC , MOS65XX_AM_IMP , // 0x38
MOS65XX_INS_AND , MOS65XX_AM_ABSY, // 0x39
MOS65XX_INS_NOP , MOS65XX_AM_IMP , // 0x3a
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x3b
MOS65XX_INS_NOP , MOS65XX_AM_ABSX, // 0x3c
MOS65XX_INS_AND , MOS65XX_AM_ABSX, // 0x3d
MOS65XX_INS_ROL , MOS65XX_AM_ABSX, // 0x3e
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x3f
MOS65XX_INS_RTI , MOS65XX_AM_IMP , // 0x40
MOS65XX_INS_EOR , MOS65XX_AM_INDX, // 0x41
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x42
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x43
MOS65XX_INS_NOP , MOS65XX_AM_ZP , // 0x44
MOS65XX_INS_EOR , MOS65XX_AM_ZP , // 0x45
MOS65XX_INS_LSR , MOS65XX_AM_ZP , // 0x46
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x47
MOS65XX_INS_PHA , MOS65XX_AM_IMP , // 0x48
MOS65XX_INS_EOR , MOS65XX_AM_IMM , // 0x49
MOS65XX_INS_LSR , MOS65XX_AM_ACC , // 0x4a
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x4b
MOS65XX_INS_JMP , MOS65XX_AM_ABS , // 0x4c
MOS65XX_INS_EOR , MOS65XX_AM_ABS , // 0x4d
MOS65XX_INS_LSR , MOS65XX_AM_ABS , // 0x4e
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x4f
MOS65XX_INS_BVC , MOS65XX_AM_REL , // 0x50
MOS65XX_INS_EOR , MOS65XX_AM_INDY, // 0x51
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x52
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x53
MOS65XX_INS_NOP , MOS65XX_AM_ZPX , // 0x54
MOS65XX_INS_EOR , MOS65XX_AM_ZPX , // 0x55
MOS65XX_INS_LSR , MOS65XX_AM_ZPX , // 0x56
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x57
MOS65XX_INS_CLI , MOS65XX_AM_IMP , // 0x58
MOS65XX_INS_EOR , MOS65XX_AM_ABSY, // 0x59
MOS65XX_INS_NOP , MOS65XX_AM_IMP , // 0x5a
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x5b
MOS65XX_INS_NOP , MOS65XX_AM_ABSX, // 0x5c
MOS65XX_INS_EOR , MOS65XX_AM_ABSX, // 0x5d
MOS65XX_INS_LSR , MOS65XX_AM_ABSX, // 0x5e
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x5f
MOS65XX_INS_RTS , MOS65XX_AM_IMP , // 0x60
MOS65XX_INS_ADC , MOS65XX_AM_INDX, // 0x61
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x62
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x63
MOS65XX_INS_NOP , MOS65XX_AM_ZP , // 0x64
MOS65XX_INS_ADC , MOS65XX_AM_ZP , // 0x65
MOS65XX_INS_ROR , MOS65XX_AM_ZP , // 0x66
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x67
MOS65XX_INS_PLA , MOS65XX_AM_IMP , // 0x68
MOS65XX_INS_ADC , MOS65XX_AM_IMM , // 0x69
MOS65XX_INS_ROR , MOS65XX_AM_ACC , // 0x6a
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x6b
MOS65XX_INS_JMP , MOS65XX_AM_IND , // 0x6c
MOS65XX_INS_ADC , MOS65XX_AM_ABS , // 0x6d
MOS65XX_INS_ROR , MOS65XX_AM_ABS , // 0x6e
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x6f
MOS65XX_INS_BVS , MOS65XX_AM_REL , // 0x70
MOS65XX_INS_ADC , MOS65XX_AM_INDY, // 0x71
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x72
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x73
MOS65XX_INS_NOP , MOS65XX_AM_ZPX , // 0x74
MOS65XX_INS_ADC , MOS65XX_AM_ZPX , // 0x75
MOS65XX_INS_ROR , MOS65XX_AM_ZPX , // 0x76
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x77
MOS65XX_INS_SEI , MOS65XX_AM_IMP , // 0x78
MOS65XX_INS_ADC , MOS65XX_AM_ABSY, // 0x79
MOS65XX_INS_NOP , MOS65XX_AM_IMP , // 0x7a
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x7b
MOS65XX_INS_NOP , MOS65XX_AM_ABSX, // 0x7c
MOS65XX_INS_ADC , MOS65XX_AM_ABSX, // 0x7d
MOS65XX_INS_ROR , MOS65XX_AM_ABSX, // 0x7e
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x7f
MOS65XX_INS_NOP , MOS65XX_AM_IMP , // 0x80
MOS65XX_INS_STA , MOS65XX_AM_INDX, // 0x81
MOS65XX_INS_NOP , MOS65XX_AM_IMP , // 0x82
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x83
MOS65XX_INS_STY , MOS65XX_AM_ZP , // 0x84
MOS65XX_INS_STA , MOS65XX_AM_ZP , // 0x85
MOS65XX_INS_STX , MOS65XX_AM_ZP , // 0x86
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x87
MOS65XX_INS_DEY , MOS65XX_AM_IMP , // 0x88
MOS65XX_INS_NOP , MOS65XX_AM_IMP , // 0x89
MOS65XX_INS_TXA , MOS65XX_AM_IMP , // 0x8a
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x8b
MOS65XX_INS_STY , MOS65XX_AM_ABS , // 0x8c
MOS65XX_INS_STA , MOS65XX_AM_ABS , // 0x8d
MOS65XX_INS_STX , MOS65XX_AM_ABS , // 0x8e
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x8f
MOS65XX_INS_BCC , MOS65XX_AM_REL , // 0x90
MOS65XX_INS_STA , MOS65XX_AM_INDY, // 0x91
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x92
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x93
MOS65XX_INS_STY , MOS65XX_AM_ZPX , // 0x94
MOS65XX_INS_STA , MOS65XX_AM_ZPX , // 0x95
MOS65XX_INS_STX , MOS65XX_AM_ZPY , // 0x96
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x97
MOS65XX_INS_TYA , MOS65XX_AM_IMP , // 0x98
MOS65XX_INS_STA , MOS65XX_AM_ABSY, // 0x99
MOS65XX_INS_TXS , MOS65XX_AM_IMP , // 0x9a
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x9b
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x9c
MOS65XX_INS_STA , MOS65XX_AM_ABSX, // 0x9d
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x9e
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0x9f
MOS65XX_INS_LDY , MOS65XX_AM_IMM , // 0xa0
MOS65XX_INS_LDA , MOS65XX_AM_INDX, // 0xa1
MOS65XX_INS_LDX , MOS65XX_AM_IMM , // 0xa2
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xa3
MOS65XX_INS_LDY , MOS65XX_AM_ZP , // 0xa4
MOS65XX_INS_LDA , MOS65XX_AM_ZP , // 0xa5
MOS65XX_INS_LDX , MOS65XX_AM_ZP , // 0xa6
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xa7
MOS65XX_INS_TAY , MOS65XX_AM_IMP , // 0xa8
MOS65XX_INS_LDA , MOS65XX_AM_IMM , // 0xa9
MOS65XX_INS_TAX , MOS65XX_AM_IMP , // 0xaa
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xab
MOS65XX_INS_LDY , MOS65XX_AM_ABS , // 0xac
MOS65XX_INS_LDA , MOS65XX_AM_ABS , // 0xad
MOS65XX_INS_LDX , MOS65XX_AM_ABS , // 0xae
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xaf
MOS65XX_INS_BCS , MOS65XX_AM_REL , // 0xb0
MOS65XX_INS_LDA , MOS65XX_AM_INDY, // 0xb1
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xb2
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xb3
MOS65XX_INS_LDY , MOS65XX_AM_ZPX , // 0xb4
MOS65XX_INS_LDA , MOS65XX_AM_ZPX , // 0xb5
MOS65XX_INS_LDX , MOS65XX_AM_ZPY , // 0xb6
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xb7
MOS65XX_INS_CLV , MOS65XX_AM_IMP , // 0xb8
MOS65XX_INS_LDA , MOS65XX_AM_ABSY, // 0xb9
MOS65XX_INS_TSX , MOS65XX_AM_IMP , // 0xba
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xbb
MOS65XX_INS_LDY , MOS65XX_AM_ABSX, // 0xbc
MOS65XX_INS_LDA , MOS65XX_AM_ABSX, // 0xbd
MOS65XX_INS_LDX , MOS65XX_AM_ABSY, // 0xbe
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xbf
MOS65XX_INS_CPY , MOS65XX_AM_IMM , // 0xc0
MOS65XX_INS_CMP , MOS65XX_AM_INDX, // 0xc1
MOS65XX_INS_NOP , MOS65XX_AM_IMP , // 0xc2
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xc3
MOS65XX_INS_CPY , MOS65XX_AM_ZP , // 0xc4
MOS65XX_INS_CMP , MOS65XX_AM_ZP , // 0xc5
MOS65XX_INS_DEC , MOS65XX_AM_ZP , // 0xc6
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xc7
MOS65XX_INS_INY , MOS65XX_AM_IMP , // 0xc8
MOS65XX_INS_CMP , MOS65XX_AM_IMM , // 0xc9
MOS65XX_INS_DEX , MOS65XX_AM_IMP , // 0xca
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xcb
MOS65XX_INS_CPY , MOS65XX_AM_ABS , // 0xcc
MOS65XX_INS_CMP , MOS65XX_AM_ABS , // 0xcd
MOS65XX_INS_DEC , MOS65XX_AM_ABS , // 0xce
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xcf
MOS65XX_INS_BNE , MOS65XX_AM_REL , // 0xd0
MOS65XX_INS_CMP , MOS65XX_AM_INDY, // 0xd1
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xd2
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xd3
MOS65XX_INS_NOP , MOS65XX_AM_ZPX , // 0xd4
MOS65XX_INS_CMP , MOS65XX_AM_ZPX , // 0xd5
MOS65XX_INS_DEC , MOS65XX_AM_ZPX , // 0xd6
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xd7
MOS65XX_INS_CLD , MOS65XX_AM_IMP , // 0xd8
MOS65XX_INS_CMP , MOS65XX_AM_ABSY, // 0xd9
MOS65XX_INS_NOP , MOS65XX_AM_IMP , // 0xda
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xdb
MOS65XX_INS_NOP , MOS65XX_AM_ABSX, // 0xdc
MOS65XX_INS_CMP , MOS65XX_AM_ABSX, // 0xdd
MOS65XX_INS_DEC , MOS65XX_AM_ABSX, // 0xde
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xdf
MOS65XX_INS_CPX , MOS65XX_AM_IMM , // 0xe0
MOS65XX_INS_SBC , MOS65XX_AM_INDX, // 0xe1
MOS65XX_INS_NOP , MOS65XX_AM_IMP , // 0xe2
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xe3
MOS65XX_INS_CPX , MOS65XX_AM_ZP , // 0xe4
MOS65XX_INS_SBC , MOS65XX_AM_ZP , // 0xe5
MOS65XX_INS_INC , MOS65XX_AM_ZP , // 0xe6
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xe7
MOS65XX_INS_INX , MOS65XX_AM_IMP , // 0xe8
MOS65XX_INS_SBC , MOS65XX_AM_IMM , // 0xe9
MOS65XX_INS_NOP , MOS65XX_AM_IMP , // 0xea
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xeb
MOS65XX_INS_CPX , MOS65XX_AM_ABS , // 0xec
MOS65XX_INS_SBC , MOS65XX_AM_ABS , // 0xed
MOS65XX_INS_INC , MOS65XX_AM_ABS , // 0xee
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xef
MOS65XX_INS_BEQ , MOS65XX_AM_REL , // 0xf0
MOS65XX_INS_SBC , MOS65XX_AM_INDY, // 0xf1
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xf2
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xf3
MOS65XX_INS_NOP , MOS65XX_AM_ZPX , // 0xf4
MOS65XX_INS_SBC , MOS65XX_AM_ZPX , // 0xf5
MOS65XX_INS_INC , MOS65XX_AM_ZPX , // 0xf6
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xf7
MOS65XX_INS_SED , MOS65XX_AM_IMP , // 0xf8
MOS65XX_INS_SBC , MOS65XX_AM_ABSY, // 0xf9
MOS65XX_INS_NOP , MOS65XX_AM_IMP , // 0xfa
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xfb
MOS65XX_INS_NOP , MOS65XX_AM_ABSX, // 0xfc
MOS65XX_INS_SBC , MOS65XX_AM_ABSX, // 0xfd
MOS65XX_INS_INC , MOS65XX_AM_ABSX, // 0xfe
MOS65XX_INS_INVALID, MOS65XX_AM_NONE, // 0xff
};
static const char* RegNames[] = {
"invalid", "A", "X", "Y", "P", "SP"
};
#ifndef CAPSTONE_DIET
static const char* GroupNames[] = {
NULL,
"jump",
"call",
"ret",
NULL,
"iret",
"branch_relative"
};
typedef struct InstructionInfo {
char* name;
mos65xx_group_type group_type;
mos65xx_reg write, read;
bool modifies_status;
} InstructionInfo;
const struct InstructionInfo InstructionInfoTable[]= {
"INVALID", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, false,
"ADC", MOS65XX_GRP_INVALID, MOS65XX_REG_ACC, MOS65XX_REG_INVALID, true,
"AND", MOS65XX_GRP_INVALID, MOS65XX_REG_ACC, MOS65XX_REG_INVALID, true,
"ASL", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true,
"BCC", MOS65XX_GRP_BRANCH_RELATIVE, MOS65XX_REG_INVALID, MOS65XX_REG_P, false,
"BCS", MOS65XX_GRP_BRANCH_RELATIVE, MOS65XX_REG_INVALID, MOS65XX_REG_P, false,
"BEQ", MOS65XX_GRP_BRANCH_RELATIVE, MOS65XX_REG_INVALID, MOS65XX_REG_P, false,
"BIT", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true,
"BMI", MOS65XX_GRP_BRANCH_RELATIVE, MOS65XX_REG_INVALID, MOS65XX_REG_P, false,
"BNE", MOS65XX_GRP_BRANCH_RELATIVE, MOS65XX_REG_INVALID, MOS65XX_REG_P, false,
"BPL", MOS65XX_GRP_BRANCH_RELATIVE, MOS65XX_REG_INVALID, MOS65XX_REG_P, false,
"BRK", MOS65XX_GRP_INVALID, MOS65XX_REG_SP, MOS65XX_REG_INVALID, false,
"BVC", MOS65XX_GRP_BRANCH_RELATIVE, MOS65XX_REG_INVALID, MOS65XX_REG_P, false,
"BVS", MOS65XX_GRP_BRANCH_RELATIVE, MOS65XX_REG_INVALID, MOS65XX_REG_P, false,
"CLC", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true,
"CLD", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true,
"CLI", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true,
"CLV", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true,
"CMP", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_ACC, true,
"CPX", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_X, true,
"CPY", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_Y, true,
"DEC", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true,
"DEX", MOS65XX_GRP_INVALID, MOS65XX_REG_X, MOS65XX_REG_X, true,
"DEY", MOS65XX_GRP_INVALID, MOS65XX_REG_Y, MOS65XX_REG_Y, true,
"EOR", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true,
"INC", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true,
"INX", MOS65XX_GRP_INVALID, MOS65XX_REG_X, MOS65XX_REG_X, true,
"INY", MOS65XX_GRP_INVALID, MOS65XX_REG_Y, MOS65XX_REG_Y, true,
"JMP", MOS65XX_GRP_JUMP, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, false,
"JSR", MOS65XX_GRP_CALL, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, false,
"LDA", MOS65XX_GRP_INVALID, MOS65XX_REG_ACC, MOS65XX_REG_INVALID, true,
"LDX", MOS65XX_GRP_INVALID, MOS65XX_REG_X, MOS65XX_REG_INVALID, true,
"LDY", MOS65XX_GRP_INVALID, MOS65XX_REG_Y, MOS65XX_REG_INVALID, true,
"LSR", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true,
"NOP", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, false,
"ORA", MOS65XX_GRP_INVALID, MOS65XX_REG_ACC, MOS65XX_REG_INVALID, true,
"PHA", MOS65XX_GRP_INVALID, MOS65XX_REG_SP, MOS65XX_REG_ACC, false,
"PLA", MOS65XX_GRP_INVALID, MOS65XX_REG_ACC, MOS65XX_REG_SP, true,
"PHP", MOS65XX_GRP_INVALID, MOS65XX_REG_SP, MOS65XX_REG_P, false,
"PLP", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_SP, true,
"ROL", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true,
"ROR", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true,
"RTI", MOS65XX_GRP_IRET, MOS65XX_REG_SP, MOS65XX_REG_INVALID, true,
"RTS", MOS65XX_GRP_RET, MOS65XX_REG_SP, MOS65XX_REG_INVALID, false,
"SBC", MOS65XX_GRP_INVALID, MOS65XX_REG_ACC, MOS65XX_REG_INVALID, true,
"SEC", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true,
"SED", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true,
"SEI", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_INVALID, true,
"STA", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_ACC, false,
"STX", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_X, false,
"STY", MOS65XX_GRP_INVALID, MOS65XX_REG_INVALID, MOS65XX_REG_Y, false,
"TAX", MOS65XX_GRP_INVALID, MOS65XX_REG_X, MOS65XX_REG_ACC, true,
"TAY", MOS65XX_GRP_INVALID, MOS65XX_REG_Y, MOS65XX_REG_ACC, true,
"TSX", MOS65XX_GRP_INVALID, MOS65XX_REG_X, MOS65XX_REG_SP, true,
"TXA", MOS65XX_GRP_INVALID, MOS65XX_REG_ACC, MOS65XX_REG_X, true,
"TXS", MOS65XX_GRP_INVALID, MOS65XX_REG_SP, MOS65XX_REG_X, true,
"TYA", MOS65XX_GRP_INVALID, MOS65XX_REG_ACC, MOS65XX_REG_Y, true,
};
#endif
int getInstructionLength(mos65xx_address_mode am)
{
switch(am) {
case MOS65XX_AM_NONE:
case MOS65XX_AM_ACC:
case MOS65XX_AM_IMP:
return 1;
case MOS65XX_AM_IMM:
case MOS65XX_AM_ZPX:
case MOS65XX_AM_ZPY:
case MOS65XX_AM_ZP:
case MOS65XX_AM_REL:
return 2;
case MOS65XX_AM_ABS:
case MOS65XX_AM_ABSX:
case MOS65XX_AM_ABSY:
case MOS65XX_AM_INDX:
case MOS65XX_AM_INDY:
case MOS65XX_AM_IND:
return 3;
}
}
#ifndef CAPSTONE_DIET
void fillDetails(MCInst *MI, unsigned char opcode) {
cs_detail *detail = MI->flat_insn->detail;
mos65xx_insn ins = OpInfoTable[opcode].ins;
mos65xx_address_mode am = OpInfoTable[opcode].am;
detail->mos65xx.am = am;
detail->mos65xx.modifies_flags = InstructionInfoTable[ins].modifies_status;
detail->groups_count = 0;
detail->regs_read_count = 0;
detail->regs_write_count = 0;
detail->mos65xx.op_count = 0;
if (InstructionInfoTable[ins].group_type != MOS65XX_GRP_INVALID) {
detail->groups[0] = InstructionInfoTable[ins].group_type;
detail->groups_count++;
}
if (InstructionInfoTable[ins].read != MOS65XX_REG_INVALID) {
detail->regs_read[detail->regs_read_count++] = InstructionInfoTable[ins].read;
} else if (OpInfoTable[opcode].am == MOS65XX_AM_ACC) {
detail->regs_read[detail->regs_read_count++] = MOS65XX_REG_ACC;
} else if (OpInfoTable[opcode].am == MOS65XX_AM_INDY || OpInfoTable[opcode].am == MOS65XX_AM_ABSY || OpInfoTable[opcode].am == MOS65XX_AM_ZPY) {
detail->regs_read[detail->regs_read_count++] = MOS65XX_REG_Y;
} else if (OpInfoTable[opcode].am == MOS65XX_AM_INDX || OpInfoTable[opcode].am == MOS65XX_AM_ABSX || OpInfoTable[opcode].am == MOS65XX_AM_ZPX) {
detail->regs_read[detail->regs_read_count++] = MOS65XX_REG_X;
}
if (InstructionInfoTable[ins].write != MOS65XX_REG_INVALID) {
detail->regs_write[detail->regs_write_count++] = InstructionInfoTable[ins].write;
} else if (OpInfoTable[opcode].am == MOS65XX_AM_ACC) {
detail->regs_write[detail->regs_write_count++] = MOS65XX_REG_ACC;
}
if (InstructionInfoTable[ins].modifies_status) {
detail->regs_write[detail->regs_write_count++] = MOS65XX_REG_P;
}
switch(am) {
case MOS65XX_AM_IMP:
case MOS65XX_AM_REL:
break;
case MOS65XX_AM_IMM:
detail->mos65xx.operands[detail->mos65xx.op_count].type = MOS65XX_OP_IMM;
detail->mos65xx.operands[detail->mos65xx.op_count].mem = MI->Operands[0].ImmVal;
detail->mos65xx.op_count++;
break;
case MOS65XX_AM_ACC:
detail->mos65xx.operands[detail->mos65xx.op_count].type = MOS65XX_OP_REG;
detail->mos65xx.operands[detail->mos65xx.op_count].reg = MOS65XX_REG_ACC;
detail->mos65xx.op_count++;
break;
default:
detail->mos65xx.operands[detail->mos65xx.op_count].type = MOS65XX_OP_MEM;
detail->mos65xx.operands[detail->mos65xx.op_count].mem = MI->Operands[0].ImmVal;
detail->mos65xx.op_count++;
break;
}
}
#endif
void MOS65XX_printInst(MCInst *MI, struct SStream *O, void *PrinterInfo)
{
#ifndef CAPSTONE_DIET
unsigned char opcode = MI->Opcode;
SStream_concat0(O, InstructionInfoTable[OpInfoTable[MI->Opcode].ins].name);
unsigned int value = MI->Operands[0].ImmVal;
switch (OpInfoTable[opcode].am)
{
case MOS65XX_AM_IMP:
break;
case MOS65XX_AM_ACC:
SStream_concat(O, " A");
break;
case MOS65XX_AM_ABS:
SStream_concat(O, " $%04X", value);
break;
case MOS65XX_AM_IMM:
SStream_concat(O, " #$%02X", value);
break;
case MOS65XX_AM_ZP:
SStream_concat(O, " $%02X", value);
break;
case MOS65XX_AM_ABSX:
SStream_concat(O, " $%04X,x", value);
break;
case MOS65XX_AM_ABSY:
SStream_concat(O, " $%04X,y", value);
break;
case MOS65XX_AM_ZPX:
SStream_concat(O, " $%02X,x", value);
break;
case MOS65XX_AM_ZPY:
SStream_concat(O, " $%02X,y", value);
break;
case MOS65XX_AM_REL:
SStream_concat(O, " $%04X", MI->address + (signed char) value + 2);
break;
case MOS65XX_AM_IND:
SStream_concat(O, " ($%04X)", value);
break;
case MOS65XX_AM_INDX:
SStream_concat(O, " ($%04X,x)", value);
break;
case MOS65XX_AM_INDY:
SStream_concat(O, " ($%04X),y", value);
break;
}
#endif
}
bool MOS65XX_getInstruction(csh ud, const uint8_t *code, size_t code_len,
MCInst *MI, uint16_t *size, uint64_t address, void *inst_info)
{
unsigned char opcode;
unsigned char len;
mos65xx_insn ins;
if (code_len == 0) {
*size = 1;
return false;
}
opcode = code[0];
ins = OpInfoTable[opcode].ins;
if (ins == MOS65XX_INS_INVALID) {
*size = 1;
return false;
}
len = getInstructionLength(OpInfoTable[opcode].am);
if (code_len < len) {
*size = 1;
return false;
}
MI->address = address;
MI->Opcode = opcode;
MI->OpcodePub = ins;
MI->size = 0;
*size = len;
if (len == 2) {
MCOperand_CreateImm0(MI, code[1]);
} else
if (len == 3) {
MCOperand_CreateImm0(MI, (code[2]<<8) | code[1]);
}
#ifndef CAPSTONE_DIET
if (MI->flat_insn->detail) {
fillDetails(MI, opcode);
}
#endif
return true;
}
const char *MOS65XX_insn_name(csh handle, unsigned int id)
{
#ifdef CAPSTONE_DIET
return NULL;
#else
if (id >= ARR_SIZE(InstructionInfoTable)) {
return NULL;
}
return InstructionInfoTable[id].name;
#endif
}
const char* MOS65XX_reg_name(csh handle, unsigned int reg)
{
#ifdef CAPSTONE_DIET
return NULL;
#else
if (reg >= ARR_SIZE(RegNames)) {
return NULL;
}
return RegNames[(int)reg];
#endif
}
void MOS65XX_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
{
if (id < 256) {
insn->id = OpInfoTable[id].ins;
}
}
const char *MOS65XX_group_name(csh handle, unsigned int id)
{
#ifdef CAPSTONE_DIET
return NULL;
#else
if (id >= ARR_SIZE(GroupNames)) {
return NULL;
}
return GroupNames[(int)id];
#endif
}

View File

@ -0,0 +1,22 @@
/* Capstone Disassembly Engine */
/* MOS65XX Backend by Sebastian Macke <sebastian@macke.de> 2018 */
#ifndef CAPSTONE_MOS65XXDISASSEMBLER_H
#define CAPSTONE_MOS65XXDISASSEMBLER_H
#include "../../utils.h"
void MOS65XX_printInst(MCInst *MI, struct SStream *O, void *PrinterInfo);
void MOS65XX_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id);
const char *MOS65XX_insn_name(csh handle, unsigned int id);
const char *MOS65XX_group_name(csh handle, unsigned int id);
const char* MOS65XX_reg_name(csh handle, unsigned int reg);
bool MOS65XX_getInstruction(csh ud, const uint8_t *code, size_t code_len,
MCInst *MI, uint16_t *size, uint64_t address, void *inst_info);
#endif //CAPSTONE_MOS65XXDISASSEMBLER_H

View File

@ -0,0 +1,32 @@
/* Capstone Disassembly Engine */
/* MOS65XX Backend by Sebastian Macke <sebastian@macke.de> 2018 */
#ifdef CAPSTONE_HAS_MOS65XX
#include "../../utils.h"
#include "../../MCRegisterInfo.h"
#include "MOS65XXDisassembler.h"
cs_err MOS65XX_global_init(cs_struct *ud)
{
// verify if requested mode is valid
if (ud->mode)
return CS_ERR_MODE;
ud->printer = MOS65XX_printInst;
ud->printer_info = NULL;
ud->insn_id = MOS65XX_get_insn_id;
ud->insn_name = MOS65XX_insn_name;
ud->group_name = MOS65XX_group_name;
ud->disasm = MOS65XX_getInstruction;
ud->reg_name = MOS65XX_reg_name;
return CS_ERR_OK;
}
cs_err MOS65XX_option(cs_struct *handle, cs_opt_type type, size_t value)
{
return CS_ERR_OK;
}
#endif

View File

@ -0,0 +1,12 @@
/* Capstone Disassembly Engine */
/* By Sebastian Macke <sebastian@macke.de>, 2018 */
#ifndef CS_MOS65XX_MODULE_H
#define CS_MOS65XX_MODULE_H
#include "../../utils.h"
cs_err MOS65XX_global_init(cs_struct *ud);
cs_err MOS65XX_option(cs_struct *handle, cs_opt_type type, size_t value);
#endif

View File

@ -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 m680x evm
CAPSTONE_ARCHS ?= arm aarch64 m68k mips powerpc sparc systemz x86 xcore tms320c64x m680x evm mos65xx
################################################################################

39
cs.c
View File

@ -64,6 +64,7 @@
#include "arch/TMS320C64x/TMS320C64xModule.h"
#include "arch/X86/X86Module.h"
#include "arch/XCore/XCoreModule.h"
#include "arch/MOS65XX/MOS65XXModule.h"
// constructor initialization for all archs
static cs_err (*cs_arch_init[MAX_ARCH])(cs_struct *) = {
@ -127,6 +128,11 @@ static cs_err (*cs_arch_init[MAX_ARCH])(cs_struct *) = {
#else
NULL,
#endif
#ifdef CAPSTONE_HAS_MOS65XX
MOS65XX_global_init,
#else
NULL,
#endif
};
// support cs_option() for all archs
@ -191,6 +197,12 @@ static cs_err (*cs_arch_option[MAX_ARCH]) (cs_struct *, cs_opt_type, size_t valu
#else
NULL,
#endif
#ifdef CAPSTONE_HAS_MOS65XX
MOS65XX_option,
#else
NULL,
#endif
};
// bitmask for finding disallowed modes for an arch:
@ -263,6 +275,11 @@ static cs_mode cs_arch_disallowed_mode_mask[MAX_ARCH] = {
#else
0,
#endif
#ifdef CAPSTONE_HAS_MOS65XX
~(CS_MODE_BIG_ENDIAN),
#else
0,
#endif
};
// bitmask of enabled architectures
@ -303,6 +320,9 @@ static uint32_t all_arch = 0
#ifdef CAPSTONE_HAS_EVM
| (1 << CS_ARCH_EVM)
#endif
#ifdef CAPSTONE_HAS_MOS65XX
| (1 << CS_ARCH_MOS65XX)
#endif
;
@ -373,7 +393,8 @@ bool CAPSTONE_API cs_support(int query)
(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_M680X) | (1 << CS_ARCH_EVM));
(1 << CS_ARCH_M680X) | (1 << CS_ARCH_EVM) |
(1 << CS_ARCH_MOS65XX));
if ((unsigned int)query < CS_ARCH_MAX)
return all_arch & (1 << query);
@ -639,6 +660,9 @@ static uint8_t skipdata_size(cs_struct *handle)
case CS_ARCH_EVM:
// EVM alignment is 1.
return 1;
case CS_ARCH_MOS65XX:
// MOS65XX alignment is 1.
return 1;
}
}
@ -1357,6 +1381,11 @@ int CAPSTONE_API cs_op_count(csh ud, const cs_insn *insn, unsigned int op_type)
if (insn->detail->evm.operands[i].type == (evm_op_type)op_type)
count++;
#endif
case CS_ARCH_MOS65XX:
for (i = 0; i < insn->detail->m680x.op_count; i++)
if (insn->detail->m680x.operands[i].type == (m680x_op_type)op_type)
count++;
break;
break;
}
@ -1493,6 +1522,14 @@ int CAPSTONE_API cs_op_index(csh ud, const cs_insn *insn, unsigned int op_type,
}
#endif
break;
case CS_ARCH_MOS65XX:
for (i = 0; i < insn->detail->mos65xx.op_count; i++) {
if (insn->detail->mos65xx.operands[i].type == (mos65xx_op_type)op_type)
count++;
if (count == post)
return i;
}
break;
}
return -1;

View File

@ -56,6 +56,7 @@ static struct {
{ "hd6309", CS_ARCH_M680X, CS_MODE_M680X_6309 },
{ "hcs08", CS_ARCH_M680X, CS_MODE_M680X_HCS08 },
{ "evm", CS_ARCH_EVM, 0 },
{ "mos65xx", CS_ARCH_MOS65XX, 0 },
{ NULL }
};
@ -71,6 +72,7 @@ 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);
void print_insn_detail_evm(csh handle, cs_insn *ins);
void print_insn_detail_mos65xx(csh handle, cs_insn *ins);
static void print_details(csh handle, cs_arch arch, cs_mode md, cs_insn *ins);
@ -207,6 +209,9 @@ static void usage(char *prog)
if (cs_support(CS_ARCH_EVM)) {
printf(" evm: Ethereum Virtual Machine\n");
}
if (cs_support(CS_ARCH_MOS65XX)) {
printf(" mox65xx: MOS65XX family\n");
}
printf("\nExtra options:\n");
printf(" -d show detailed information of the instructions\n");
@ -252,6 +257,9 @@ static void print_details(csh handle, cs_arch arch, cs_mode md, cs_insn *ins)
case CS_ARCH_EVM:
print_insn_detail_evm(handle, ins);
break;
case CS_ARCH_MOS65XX:
print_insn_detail_mos65xx(handle, ins);
break;
default: break;
}

76
cstool/cstool_mos65xx.c Normal file
View File

@ -0,0 +1,76 @@
#include <stdio.h>
#include <stdlib.h>
#include <capstone/capstone.h>
void print_string_hex(char *comment, unsigned char *str, size_t len);
static const char *get_am_name(mos65xx_address_mode mode)
{
switch(mode) {
default:
case MOS65XX_AM_NONE:
return "No address mode";
case MOS65XX_AM_IMP:
return "implied addressing (no addressing mode)";
case MOS65XX_AM_ACC:
return "accumulator addressing";
case MOS65XX_AM_ABS:
return "absolute addressing";
case MOS65XX_AM_ZP:
return "zeropage addressing";
case MOS65XX_AM_IMM:
return "8 Bit immediate value";
case MOS65XX_AM_ABSX:
return "indexed absolute addressing by the X index register";
case MOS65XX_AM_ABSY:
return "indexed absolute addressing by the Y index register";
case MOS65XX_AM_INDX:
return "indexed indirect addressing by the X index register";
case MOS65XX_AM_INDY:
return "indirect indexed addressing by the Y index register";
case MOS65XX_AM_ZPX:
return "indexed zeropage addressing by the X index register";
case MOS65XX_AM_ZPY:
return "indexed zeropage addressing by the Y index register";
case MOS65XX_AM_REL:
return "relative addressing used by branches";
case MOS65XX_AM_IND:
return "absolute indirect addressing";
}
}
void print_insn_detail_mos65xx(csh handle, cs_insn *ins)
{
int i;
cs_mos65xx *mos65xx;
// detail can be NULL on "data" instruction if SKIPDATA option is turned ON
if (ins->detail == NULL)
return;
mos65xx = &(ins->detail->mos65xx);
printf("\taddress mode: %s\n", get_am_name(mos65xx->am));
printf("\tmodifies flags: %s\n", mos65xx->modifies_flags ? "true": "false");
if (mos65xx->op_count)
printf("\top_count: %u\n", mos65xx->op_count);
for (i = 0; i < mos65xx->op_count; i++) {
cs_mos65xx_op *op = &(mos65xx->operands[i]);
switch((int)op->type) {
default:
break;
case MOS65XX_OP_REG:
printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg));
break;
case MOS65XX_OP_IMM:
printf("\t\toperands[%u].type: IMM = 0x%x\n", i, op->imm);
break;
case MOS65XX_OP_MEM:
printf("\t\toperands[%u].type: MEM = 0x%x\n", i, op->mem);
break;
}
}
}

View File

@ -84,6 +84,7 @@ typedef enum cs_arch {
CS_ARCH_TMS320C64X, ///< TMS320C64x architecture
CS_ARCH_M680X, ///< 680X architecture
CS_ARCH_EVM, ///< Ethereum architecture
CS_ARCH_MOS65XX, ///< MOS65XX architecture (including MOS6502)
CS_ARCH_MAX,
CS_ARCH_ALL = 0xFFFF, // All architectures - for cs_support()
} cs_arch;
@ -257,6 +258,7 @@ typedef struct cs_opt_skipdata {
/// X86: 1 bytes.
/// XCore: 2 bytes.
/// EVM: 1 bytes.
/// MOS65XX: 1 bytes.
cs_skipdata_cb_t callback; // default value is NULL
/// User-defined data to be passed to @callback function pointer.
@ -276,6 +278,7 @@ typedef struct cs_opt_skipdata {
#include "tms320c64x.h"
#include "m680x.h"
#include "evm.h"
#include "mos65xx.h"
/// NOTE: All information in cs_detail is only available when CS_OPT_DETAIL = CS_OPT_ON
/// Initialized as memset(., 0, offsetof(cs_detail, ARCH)+sizeof(cs_ARCH))
@ -306,6 +309,7 @@ typedef struct cs_detail {
cs_tms320c64x tms320c64x; ///< TMS320C64x architecture
cs_m680x m680x; ///< M680X architecture
cs_evm evm; ///< Ethereum architecture
cs_mos65xx mos65xx; ///< Ethereum architecture
};
} cs_detail;

148
include/capstone/mos65xx.h Normal file
View File

@ -0,0 +1,148 @@
#ifndef CAPSTONE_MOS65XX_H
#define CAPSTONE_MOS65XX_H
/* Capstone Disassembly Engine */
/* By Sebastian Macke <sebastian@macke.de, 2018 */
#ifdef __cplusplus
extern "C" {
#endif
#include "platform.h"
/// MOS65XX registers and special registers
typedef enum mos65xx_reg {
MOS65XX_REG_INVALID = 0,
MOS65XX_REG_ACC, ///< accumulator
MOS65XX_REG_X, ///< X index register
MOS65XX_REG_Y, ///< Y index register
MOS65XX_REG_P, ///< status register
MOS65XX_REG_SP, ///< stack pointer register
MOS65XX_REG_ENDING, // <-- mark the end of the list of registers
} mos65xx_reg;
/// MOS65XX Addressing Modes
typedef enum mos65xx_address_mode {
MOS65XX_AM_NONE = 0, ///< No address mode.
MOS65XX_AM_IMP, ///< implied addressing (no addressing mode)
MOS65XX_AM_ACC, ///< accumulator addressing
MOS65XX_AM_ABS, ///< absolute addressing
MOS65XX_AM_ZP, ///< zeropage addressing
MOS65XX_AM_IMM, ///< 8 Bit immediate value
MOS65XX_AM_ABSX, ///< indexed absolute addressing by the X index register
MOS65XX_AM_ABSY, ///< indexed absolute addressing by the Y index register
MOS65XX_AM_INDX, ///< indexed indirect addressing by the X index register
MOS65XX_AM_INDY, ///< indirect indexed addressing by the Y index register
MOS65XX_AM_ZPX, ///< indexed zeropage addressing by the X index register
MOS65XX_AM_ZPY, ///< indexed zeropage addressing by the Y index register
MOS65XX_AM_REL, ///< relative addressing used by branches
MOS65XX_AM_IND, ///< absolute indirect addressing
} mos65xx_address_mode;
/// M68K instruction
typedef enum mos65xx_insn {
MOS65XX_INS_INVALID = 0,
MOS65XX_INS_ADC,
MOS65XX_INS_AND,
MOS65XX_INS_ASL,
MOS65XX_INS_BCC,
MOS65XX_INS_BCS,
MOS65XX_INS_BEQ,
MOS65XX_INS_BIT,
MOS65XX_INS_BMI,
MOS65XX_INS_BNE,
MOS65XX_INS_BPL,
MOS65XX_INS_BRK,
MOS65XX_INS_BVC,
MOS65XX_INS_BVS,
MOS65XX_INS_CLC,
MOS65XX_INS_CLD,
MOS65XX_INS_CLI,
MOS65XX_INS_CLV,
MOS65XX_INS_CMP,
MOS65XX_INS_CPX,
MOS65XX_INS_CPY,
MOS65XX_INS_DEC,
MOS65XX_INS_DEX,
MOS65XX_INS_DEY,
MOS65XX_INS_EOR,
MOS65XX_INS_INC,
MOS65XX_INS_INX,
MOS65XX_INS_INY,
MOS65XX_INS_JMP,
MOS65XX_INS_JSR,
MOS65XX_INS_LDA,
MOS65XX_INS_LDX,
MOS65XX_INS_LDY,
MOS65XX_INS_LSR,
MOS65XX_INS_NOP,
MOS65XX_INS_ORA,
MOS65XX_INS_PHA,
MOS65XX_INS_PLA,
MOS65XX_INS_PHP,
MOS65XX_INS_PLP,
MOS65XX_INS_ROL,
MOS65XX_INS_ROR,
MOS65XX_INS_RTI,
MOS65XX_INS_RTS,
MOS65XX_INS_SBC,
MOS65XX_INS_SEC,
MOS65XX_INS_SED,
MOS65XX_INS_SEI,
MOS65XX_INS_STA,
MOS65XX_INS_STX,
MOS65XX_INS_STY,
MOS65XX_INS_TAX,
MOS65XX_INS_TAY,
MOS65XX_INS_TSX,
MOS65XX_INS_TXA,
MOS65XX_INS_TXS,
MOS65XX_INS_TYA,
MOS65XX_INS_ENDING, // <-- mark the end of the list of instructions
} mos65xx_insn;
/// Group of M68K instructions
typedef enum mos65xx_group_type {
MOS65XX_GRP_INVALID = 0, ///< CS_GRP_INVALID
MOS65XX_GRP_JUMP, ///< = CS_GRP_JUMP
MOS65XX_GRP_CALL, ///< = CS_GRP_RET
MOS65XX_GRP_RET, ///< = CS_GRP_RET
MOS65XX_GRP_IRET = 5, ///< = CS_GRP_IRET
MOS65XX_GRP_BRANCH_RELATIVE = 6, ///< = CS_GRP_BRANCH_RELATIVE
MOS65XX_GRP_ENDING,// <-- mark the end of the list of groups
} mos65xx_group_type;
/// Operand type for instruction's operands
typedef enum mos65xx_op_type {
MOS65XX_OP_INVALID = 0, ///< = CS_OP_INVALID (Uninitialized).
MOS65XX_OP_REG, ///< = CS_OP_REG (Register operand).
MOS65XX_OP_IMM, ///< = CS_OP_IMM (Immediate operand).
MOS65XX_OP_MEM, ///< = CS_OP_MEM (Memory operand).
} mos65xx_op_type;
/// Instruction operand
typedef struct cs_mos65xx_op {
mos65xx_op_type type; ///< operand type
union {
mos65xx_reg reg; ///< register value for REG operand
uint8_t imm; ///< immediate value for IMM operand
uint16_t mem; ///< base/index/scale/disp value for MEM operand
};
} cs_mos65xx_op;
/// The MOS65XX address mode and it's operands
typedef struct cs_mos65xx {
mos65xx_address_mode am;
bool modifies_flags;
/// Number of operands of this instruction,
/// or 0 when instruction has no operand.
uint8_t op_count;
cs_mos65xx_op operands[3]; ///< operands for this instruction.
} cs_mos65xx;
#ifdef __cplusplus
}
#endif
#endif //CAPSTONE_MOS65XX_H

View File

@ -113,6 +113,10 @@ ifneq (,$(findstring evm,$(CAPSTONE_ARCHS)))
CFLAGS += -DCAPSTONE_HAS_EVM
SOURCES += test_evm.c
endif
ifneq (,$(findstring evm,$(CAPSTONE_ARCHS)))
CFLAGS += -DCAPSTONE_HAS_MOS65XX
SOURCES += test_mos65xx.c
endif
OBJS = $(addprefix $(OBJDIR)/,$(SOURCES:.c=.o))
BINARY = $(addprefix $(TESTDIR)/,$(SOURCES:.c=$(BIN_EXT)))

View File

@ -85,6 +85,9 @@ static void test()
#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
#ifdef CAPSTONE_HAS_MOS65XX
#define MOS65XX_CODE "\x0A\x00\xFE\x34\x12\xD0\xFF\xEA\x19\x56\x34\x46\x80"
#endif
@ -271,6 +274,15 @@ static void test()
sizeof(M680X_CODE) - 1,
"M680X_M6809",
},
#endif
#ifdef CAPSTONE_HAS_MOS65XX
{
CS_ARCH_MOS65XX,
(cs_mode)0,
(unsigned char*)MOS65XX_CODE,
sizeof(MOS65XX_CODE) - 1,
"MOS65XX",
},
#endif
};

View File

@ -79,6 +79,10 @@ static void test()
#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
#ifdef CAPSTONE_HAS_MOS65XX
#define MOS65XX_CODE "\x0d\x34\x12\x08\x09\xFF\x10\x80\x20\x00\x00\x98"
#endif
struct platform platforms[] = {
#ifdef CAPSTONE_HAS_X86
@ -219,6 +223,15 @@ static void test()
sizeof(M680X_CODE) - 1,
"M680X_6809"
},
#endif
#ifdef CAPSTONE_HAS_MOS65XX
{
CS_ARCH_MOS65XX,
(cs_mode)CS_MODE_LITTLE_ENDIAN,
(unsigned char*)MOS65XX_CODE,
sizeof(MOS65XX_CODE) - 1,
"MOS65XX"
},
#endif
};

168
tests/test_mos65xx.c Normal file
View File

@ -0,0 +1,168 @@
/* Capstone Disassembler Engine */
/* By Sebastian Macke <sebastian@macke.de>, 2018 */
#include <stdio.h>
#include <stdlib.h>
#include <capstone/platform.h>
#include <capstone/capstone.h>
struct platform {
cs_arch arch;
cs_mode mode;
unsigned char *code;
size_t size;
const char *comment;
};
static csh handle;
static void print_string_hex(const 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 const char *get_am_name(mos65xx_address_mode mode)
{
switch(mode) {
default:
case MOS65XX_AM_NONE:
return "No address mode";
case MOS65XX_AM_IMP:
return "implied addressing (no addressing mode)";
case MOS65XX_AM_ACC:
return "accumulator addressing";
case MOS65XX_AM_ABS:
return "absolute addressing";
case MOS65XX_AM_ZP:
return "zeropage addressing";
case MOS65XX_AM_IMM:
return "8 Bit immediate value";
case MOS65XX_AM_ABSX:
return "indexed absolute addressing by the X index register";
case MOS65XX_AM_ABSY:
return "indexed absolute addressing by the Y index register";
case MOS65XX_AM_INDX:
return "indexed indirect addressing by the X index register";
case MOS65XX_AM_INDY:
return "indirect indexed addressing by the Y index register";
case MOS65XX_AM_ZPX:
return "indexed zeropage addressing by the X index register";
case MOS65XX_AM_ZPY:
return "indexed zeropage addressing by the Y index register";
case MOS65XX_AM_REL:
return "relative addressing used by branches";
case MOS65XX_AM_IND:
return "absolute indirect addressing";
}
}
static void print_insn_detail(cs_insn *ins)
{
cs_mos65xx *mos65xx;
int i;
// detail can be NULL on "data" instruction if SKIPDATA option is turned ON
if (ins->detail == NULL)
return;
mos65xx = &(ins->detail->mos65xx);
printf("insn_detail\n");
printf("\taddress mode: %s\n", get_am_name(mos65xx->am));
printf("\tmodifies flags: %s\n", mos65xx->modifies_flags ? "true": "false");
if (mos65xx->op_count)
printf("\top_count: %u\n", mos65xx->op_count);
for (i = 0; i < mos65xx->op_count; i++) {
cs_mos65xx_op *op = &(mos65xx->operands[i]);
switch((int)op->type) {
default:
break;
case MOS65XX_OP_REG:
printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg));
break;
case MOS65XX_OP_IMM:
printf("\t\toperands[%u].type: IMM = 0x%x\n", i, op->imm);
break;
case MOS65XX_OP_MEM:
printf("\t\toperands[%u].type: MEM = 0x%x\n", i, op->mem);
break;
}
}
}
static void test()
{
#define MOS65XX_CODE "\x0d\x34\x12\x00\x81\x65\x87\x6c\x01\x00\x85\xFF\x10\x00\x19\x42\x42\x00\x49\x42"
struct platform platforms[] = {
{
CS_ARCH_MOS65XX,
0,
(unsigned char *)MOS65XX_CODE,
sizeof(MOS65XX_CODE) - 1,
"MOS65XX"
},
};
uint64_t address = 0x1000;
cs_insn *insn;
int i;
size_t count;
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();
}
cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
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%" PRIx64 ":\t%s\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
print_insn_detail(&insn[j]);
}
printf("0x%" PRIx64 ":\n", insn[j-1].address + insn[j-1].size);
// 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();
}
printf("\n");
cs_close(&handle);
}
}
int main()
{
test();
return 0;
}