capstone/arch/MOS65XX/MOS65XXDisassembler.c

597 lines
24 KiB
C

/* 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;
static 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 {
const char* name;
mos65xx_group_type group_type;
mos65xx_reg write, read;
bool modifies_status;
} InstructionInfo;
static 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
static 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;
default:
return 1;
}
}
#ifndef CAPSTONE_DIET
static 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) {
default:
break;
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
}