#include #include #include "logging/logging.h" enum SegmentPrefix { kCs = 0x2e, kSs = 0x36, kDs = 0x3e, kEs = 0x26, kFs = 0x64, kGs = 0x65, }; bool supports_rex_ = false; void DecodeInstruction(uint8_t *instr) { bool have_prefixes = true; uint8_t prefix[4] = {0, 0, 0, 0}; // decode legacy prefix do { switch (*instr) { // Group 1 - lock and repeat prefixes: case 0xF0: case 0xF2: case 0xF3: prefix[0] = *instr; break; // Group 2 - segment override prefixes: case kCs: case kSs: case kDs: case kEs: case kFs: case kGs: prefix[1] = *instr; break; // Group 3 - operand size override: case 0x66: prefix[2] = *instr; break; // Group 4 - address size override: case 0x67: prefix[3] = *instr; break; default: have_prefixes = false; break; } if (have_prefixes) { instr++; } } while (have_prefixes); // x64 rex uint8_t rex = (supports_rex_ && (*instr >= 0x40) && (*instr <= 0x4F)) ? *instr : 0; if (rex != 0) { instr++; } bool has_modrm = false; bool reg_is_opcode = false; size_t immediate_bytes = 0; #define OpEn_MR \ do { \ has_modrm = true; \ } while (0); \ break; #define OpEn_RM \ do { \ has_modrm = true; \ } while (0); \ break; #define OpEn_I(immediate_size) \ do { \ immediate_bytes = immediate_size; \ } while (0); \ break; #define OpEn_RMI(immediate_size) \ do { \ immediate_bytes = immediate_size; \ } while (0); \ break; #define OpEn_O \ do { \ reg_is_opcode = true; \ } while (0); \ break; #define OpEn_D \ do { \ reg_is_opcode = true; \ } while (0); \ break; #define OpEn_ZO \ do { \ reg_is_opcode = true; \ } while (0); \ break; #define Op_Prefix \ do { \ reg_is_opcode = true; \ } while (0); \ break; #define UnImplOpcode \ do { \ DLOG(0, "opcode unreachable"); \ } while (0); \ break; typedef enum { MR, } OpEnTy; // decode opcode switch (*instr) { case 0x00: OpEn_MR; case 0x01: OpEn_MR; case 0x02: OpEn_RM; case 0x03: OpEn_RM; case 0x04: OpEn_I(8); case 0x05: OpEn_I(16 | 32); case 0x06: case 0x07: UnImplOpcode; case 0x08: OpEn_MR; case 0x09: OpEn_MR; case 0x0a: OpEn_RM; case 0x0b: OpEn_RM; case 0x0c: OpEn_I(8); case 0x0d: OpEn_I(16 | 32); case 0x0e: case 0x0f: UnImplOpcode; case 0x10: OpEn_MR; case 0x11: OpEn_MR; case 0x12: OpEn_RM; case 0x13: OpEn_RM; case 0x14: OpEn_I(8); case 0x15: OpEn_I(16 | 32); case 0x16: case 0x17: UnImplOpcode; case 0x18: OpEn_MR; case 0x19: OpEn_MR; case 0x1a: OpEn_RM; case 0x1b: OpEn_RM; case 0x1c: OpEn_I(8); case 0x1d: OpEn_I(16 | 32); case 0x1e: case 0x1f: UnImplOpcode; case 0x20: OpEn_MR; case 0x21: OpEn_MR; case 0x22: OpEn_RM; case 0x23: OpEn_RM; case 0x24: OpEn_I(8); case 0x25: OpEn_I(16 | 32); case 0x26: case 0x27: UnImplOpcode; case 0x28: OpEn_MR; case 0x29: OpEn_MR; case 0x2a: OpEn_RM; case 0x2b: OpEn_RM; case 0x2c: OpEn_I(8); case 0x2d: OpEn_I(16 | 32); case 0x2e: case 0x2f: UnImplOpcode; case 0x30: OpEn_MR; case 0x31: OpEn_MR; case 0x32: OpEn_RM; case 0x33: OpEn_RM; case 0x34: OpEn_I(8); case 0x35: OpEn_I(16 | 32); case 0x36: case 0x37: UnImplOpcode; case 0x38: OpEn_MR; case 0x39: OpEn_MR; case 0x3a: OpEn_RM; case 0x3b: OpEn_RM; case 0x3c: OpEn_I(8); case 0x3d: OpEn_I(16 | 32); case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: UnImplOpcode; case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57: case 0x58: case 0x59: case 0x5A: case 0x5B: case 0x5C: case 0x5D: case 0x5E: case 0x5F: OpEn_O; case 0x60: case 0x61: case 0x62: UnImplOpcode; case 0x63: if ((rex & REX_W) != 0) { OpEn_RM; }; break; case 0x64: case 0x65: case 0x66: case 0x67: Op_Prefix; case 0x68: OpEn_I(16 | 32); case 0x69: OpEn_RMI(16 | 32); case 0x6a: OpEn_I(8); case 0x6b: OpEn_RMI(8); case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: case 0x78: case 0x79: case 0x7A: case 0x7B: case 0x7C: case 0x7D: case 0x7E: case 0x7F: OpEn_D; case 0x80: case 0x81: case 0x82: case 0x83: case 0x84: case 0x85: UnImplOpcode; case 0x86: case 0x87: OpEn_RM; case 0x88: case 0x89: case 0x8a: case 0x8b: OpEn_RM; case 0x8c: case 0x8d: case 0x8e: case 0x8f: case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: case 0x98: case 0x99: case 0x9a: case 0x9b: case 0x9c: UnImplOpcode; case 0x9d: OpEn_ZO; case 0x0f: DecodeExtendedOpcode } } void DecodeExtendedOpcode(uint8_t *instr) { }