You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
596 lines
24 KiB
596 lines
24 KiB
/* 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: |
|
case MOS65XX_AM_INDX: |
|
case MOS65XX_AM_INDY: |
|
return 2; |
|
|
|
case MOS65XX_AM_ABS: |
|
case MOS65XX_AM_ABSX: |
|
case MOS65XX_AM_ABSY: |
|
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, " $0x%04x", value); |
|
break; |
|
|
|
case MOS65XX_AM_IMM: |
|
SStream_concat(O, " #$0x%02x", value); |
|
break; |
|
|
|
case MOS65XX_AM_ZP: |
|
SStream_concat(O, " $0x%02x", value); |
|
break; |
|
|
|
case MOS65XX_AM_ABSX: |
|
SStream_concat(O, " $0x%04x, x", value); |
|
break; |
|
|
|
case MOS65XX_AM_ABSY: |
|
SStream_concat(O, " $0x%04x, y", value); |
|
break; |
|
|
|
case MOS65XX_AM_ZPX: |
|
SStream_concat(O, " $0x%02x, x", value); |
|
break; |
|
|
|
case MOS65XX_AM_ZPY: |
|
SStream_concat(O, " $0x%02x, y", value); |
|
break; |
|
|
|
case MOS65XX_AM_REL: |
|
SStream_concat(O, " $0x%04x", MI->address + (signed char) value + 2); |
|
break; |
|
|
|
case MOS65XX_AM_IND: |
|
SStream_concat(O, " ($0x%04x)", value); |
|
break; |
|
|
|
case MOS65XX_AM_INDX: |
|
SStream_concat(O, " ($0x%02x, x)", value); |
|
break; |
|
|
|
case MOS65XX_AM_INDY: |
|
SStream_concat(O, " ($0x%02x), 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 |
|
}
|
|
|