| /* 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; |
| unsigned int value = MI->Operands[0].ImmVal; |
| |
| SStream_concat0(O, InstructionInfoTable[OpInfoTable[MI->Opcode].ins].name); |
| |
| 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 |
| } |