Add support for the MOS65XX family such as the MOS 6502.
Signed-off-by: Sebastian Macke <sebastian@macke.de>
This commit is contained in:
parent
a69f7880a8
commit
87221fa742
|
@ -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)
|
||||
|
|
18
Makefile
18
Makefile
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
39
cs.c
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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)))
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue