├── .gitignore ├── README.md ├── CMakeLists.txt ├── tests ├── CMakeLists.txt └── test_x86_64.cpp ├── Instruction.cpp ├── include └── edisassm │ ├── ModRM.h │ ├── SIB.h │ ├── Model.h │ ├── REX.h │ ├── OPTable_Group11.tcc │ ├── OPTable_Group4.tcc │ ├── OPTable_Group8.tcc │ ├── OPTable_Group5.tcc │ ├── OPTable_Group6.tcc │ ├── OPTable_Group10.tcc │ ├── edisassm_exception.h │ ├── OPTable_Group12.tcc │ ├── edisassm_functions.h │ ├── OPTable_Group3.tcc │ ├── OPTable_Group13.tcc │ ├── OPTable_Group14.tcc │ ├── OPTable_Group15.tcc │ ├── OPTable_Group16.tcc │ ├── OPTable_Group17.tcc │ ├── Formatter.h │ ├── OPTable_Group1.tcc │ ├── OPTable_Group9.tcc │ ├── OPTable_Group2.tcc │ ├── Operand.tcc │ ├── edisassm_ops.h │ ├── OPTable_Group7.tcc │ ├── Operand.h │ ├── OPTable_Other.tcc │ ├── Formatter.tcc │ ├── OPTable_1byte.tcc │ ├── OPTable_3byte.tcc │ └── Instruction.h ├── Formatter.cpp ├── edisassm.cpp └── COPYING /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Compilation makes use of cmake and is fairly straight forward. The following 2 | command should successfully build (from withing the root edisassm directory): 3 | 4 | $ mkdir build 5 | $ cd build 6 | $ cmake .. 7 | $ make 8 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 3.1) 2 | set(CMAKE_CXX_STANDARD 11) 3 | PROJECT(edisassm) 4 | INCLUDE_DIRECTORIES(include) 5 | SET(edisassm_SOURCES Instruction.cpp edisassm.cpp Formatter.cpp) 6 | SET(edisassm_HEADERS Instruction.h ModRM.h Operand.h REX.h SIB.h edisassm_exception.h edisassm_util.h Formatter.h) 7 | ADD_EXECUTABLE(edisassm ${edisassm_SOURCES}) 8 | ENABLE_TESTING() 9 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-long-long -Wmissing-field-initializers -ansi -pedantic -W -Wall") 10 | 11 | 12 | -------------------------------------------------------------------------------- /tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 3.1) 2 | set(CMAKE_CXX_STANDARD 11) 3 | SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}) 4 | INCLUDE_DIRECTORIES(../include) 5 | 6 | SET(test_x86_SOURCES test_x86.cpp ../Instruction.cpp ../Formatter.cpp) 7 | SET(test_x86_64_SOURCES test_x86_64.cpp ../Instruction.cpp ../Formatter.cpp) 8 | 9 | SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wmissing-field-initializers -Wno-long-long -ansi -pedantic -W -Wall") 10 | 11 | ADD_EXECUTABLE(test_x86 ${test_x86_SOURCES}) 12 | ADD_EXECUTABLE(test_x86_64 ${test_x86_64_SOURCES}) 13 | 14 | SET(CMAKE_BUILD_TYPE Debug) 15 | -------------------------------------------------------------------------------- /Instruction.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include "edisassm/Instruction.h" 20 | #include "edisassm/Instruction32.h" 21 | #include "edisassm/Instruction64.h" 22 | 23 | // explicitly instantiate these two 24 | // to make sure everything links ok 25 | namespace edisassm { 26 | 27 | template class Instruction; 28 | template class Instruction; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /include/edisassm/ModRM.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef MODRM_20070530_H_ 20 | #define MODRM_20070530_H_ 21 | 22 | #include 23 | 24 | namespace edisassm { 25 | namespace modrm { 26 | inline uint8_t rm(uint8_t value) { return value & 0x07; } 27 | inline uint8_t reg(uint8_t value) { return (value >> 3) & 0x07; } 28 | inline uint8_t mod(uint8_t value) { return (value >> 6) & 0x03; } 29 | } 30 | } 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /include/edisassm/SIB.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef SIB_20070530_H_ 20 | #define SIB_20070530_H_ 21 | 22 | #include 23 | 24 | namespace edisassm { 25 | namespace sib { 26 | inline uint8_t base(uint8_t value) { return value & 0x07; } 27 | inline uint8_t index(uint8_t value) { return (value >> 3) & 0x07; } 28 | inline uint8_t scale(uint8_t value) { return (value >> 6) & 0x03; } 29 | } 30 | } 31 | 32 | #endif 33 | 34 | -------------------------------------------------------------------------------- /include/edisassm/Model.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef EDISASSM_MODEL_20100915_H_ 20 | #define EDISASSM_MODEL_20100915_H_ 21 | 22 | #include 23 | 24 | namespace edisassm { 25 | 26 | struct x86 { 27 | public: 28 | static const int BITS = 32; 29 | static const int MAX_SIZE = 20; 30 | static const int MAX_OPERANDS = 3; 31 | 32 | public: 33 | typedef uint32_t address_type; 34 | }; 35 | 36 | struct x86_64 { 37 | public: 38 | static const int BITS = 64; 39 | static const int MAX_SIZE = 20; 40 | static const int MAX_OPERANDS = 3; 41 | 42 | public: 43 | typedef uint64_t address_type; 44 | }; 45 | 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /include/edisassm/REX.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef REX_20071217_H_ 20 | #define REX_20071217_H_ 21 | 22 | #include 23 | 24 | namespace edisassm { 25 | namespace rex { 26 | inline bool is_rex(uint8_t value) { return (value & 0xf0) == 0x40; } 27 | inline uint8_t w(uint8_t value) { return (value >> 3) & 0x01; } // 64 bit mode 28 | inline uint8_t r(uint8_t value) { return (value >> 2) & 0x01; } // modRM extension 29 | inline uint8_t x(uint8_t value) { return (value >> 1) & 0x01; } // SIB extension 30 | inline uint8_t b(uint8_t value) { return (value >> 0) & 0x01; } // ModRM OR SIB base or Opcode Reg extension 31 | } 32 | } 33 | 34 | #endif 35 | 36 | -------------------------------------------------------------------------------- /include/edisassm/OPTable_Group11.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef OPTABLE_GROUP11_20080314_TCC_ 20 | #define OPTABLE_GROUP11_20080314_TCC_ 21 | 22 | namespace edisassm { 23 | 24 | template 25 | const typename Instruction::opcode_entry Instruction::Opcodes_Group11[8] = { 26 | { "ud", &Instruction::decode0, OP_UD, FLAG_NONE }, 27 | { "ud", &Instruction::decode0, OP_UD, FLAG_NONE }, 28 | { "ud", &Instruction::decode0, OP_UD, FLAG_NONE }, 29 | { "ud", &Instruction::decode0, OP_UD, FLAG_NONE }, 30 | { "ud", &Instruction::decode0, OP_UD, FLAG_NONE }, 31 | { "ud", &Instruction::decode0, OP_UD, FLAG_NONE }, 32 | { "ud", &Instruction::decode0, OP_UD, FLAG_NONE }, 33 | { "ud", &Instruction::decode0, OP_UD, FLAG_NONE }, 34 | }; 35 | 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /include/edisassm/OPTable_Group4.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef OPTABLE_GROUP4_20080314_TCC_ 20 | #define OPTABLE_GROUP4_20080314_TCC_ 21 | 22 | namespace edisassm { 23 | 24 | template 25 | const typename Instruction::opcode_entry Instruction::Opcodes_Group4[8] = { 26 | { "inc", &Instruction::decode_Eb, OP_INC, FLAG_W_FLAGS }, 27 | { "dec", &Instruction::decode_Eb, OP_DEC, FLAG_W_FLAGS }, 28 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 29 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 30 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 31 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 32 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 33 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 34 | }; 35 | 36 | } 37 | 38 | #endif 39 | 40 | -------------------------------------------------------------------------------- /include/edisassm/OPTable_Group8.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef OPTABLE_GROUP8_20080314_TCC_ 20 | #define OPTABLE_GROUP8_20080314_TCC_ 21 | 22 | namespace edisassm { 23 | 24 | template 25 | const typename Instruction::opcode_entry Instruction::Opcodes_Group8[8] = { 26 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 27 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 28 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 29 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 30 | { "bt", &Instruction::decode_Ev_Ib, OP_BT, FLAG_W_FLAGS }, 31 | { "bts", &Instruction::decode_Ev_Ib, OP_BTS, FLAG_W_FLAGS }, 32 | { "btr", &Instruction::decode_Ev_Ib, OP_BTR, FLAG_W_FLAGS }, 33 | { "btc", &Instruction::decode_Ev_Ib, OP_BTC, FLAG_W_FLAGS }, 34 | }; 35 | 36 | } 37 | 38 | #endif 39 | 40 | -------------------------------------------------------------------------------- /include/edisassm/OPTable_Group5.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef OPTABLE_GROUP5_20080314_TCC_ 20 | #define OPTABLE_GROUP5_20080314_TCC_ 21 | 22 | namespace edisassm { 23 | 24 | template 25 | const typename Instruction::opcode_entry Instruction::Opcodes_Group5[8] = { 26 | { "inc", &Instruction::decode_Ev, OP_INC, FLAG_W_FLAGS }, 27 | { "dec", &Instruction::decode_Ev, OP_DEC, FLAG_W_FLAGS }, 28 | { "call", &Instruction::decode_Ev, OP_CALL, FLAG_STACK }, 29 | { "callf", &Instruction::decode_Ep, OP_CALL, FLAG_32BIT_ONLY | FLAG_STACK }, 30 | { "jmp", &Instruction::decode_Ev, OP_JMP, FLAG_NONE }, 31 | { "jmpf", &Instruction::decode_Ep, OP_JMP, FLAG_NONE }, 32 | { "push", &Instruction::decode_Ev, OP_PUSH, FLAG_STACK }, 33 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 34 | }; 35 | 36 | } 37 | 38 | #endif 39 | 40 | -------------------------------------------------------------------------------- /include/edisassm/OPTable_Group6.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef OPTABLE_GROUP6_20080314_TCC_ 20 | #define OPTABLE_GROUP6_20080314_TCC_ 21 | 22 | namespace edisassm { 23 | 24 | template 25 | const typename Instruction::opcode_entry Instruction::Opcodes_Group6[8] = { 26 | { "sldt", &Instruction::decode_Rv_Mw, OP_SLDT, FLAG_NONE }, 27 | { "str", &Instruction::decode_Rv_Mw, OP_STR, FLAG_NONE }, 28 | { "lldt", &Instruction::decode_Ew, OP_LLDT, FLAG_NONE }, 29 | { "ltr", &Instruction::decode_Ew, OP_LTR, FLAG_NONE }, 30 | { "verr", &Instruction::decode_Ew, OP_VERR, FLAG_NONE }, 31 | { "verw", &Instruction::decode_Ew, OP_VERW, FLAG_NONE }, 32 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, // NOTE: jmpe Ev on x86-64 33 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 34 | }; 35 | 36 | } 37 | 38 | #endif 39 | 40 | -------------------------------------------------------------------------------- /include/edisassm/OPTable_Group10.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef OPTABLE_GROUP10_20080314_TCC_ 20 | #define OPTABLE_GROUP10_20080314_TCC_ 21 | 22 | // Group 1A in Intel docs 23 | 24 | namespace edisassm { 25 | 26 | template 27 | const typename Instruction::opcode_entry Instruction::Opcodes_Group10[8] = { 28 | { "pop", &Instruction::decode_Ev, OP_POP, FLAG_STACK }, 29 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 30 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 31 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 32 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 33 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 34 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 35 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 36 | }; 37 | 38 | } 39 | 40 | #endif 41 | 42 | -------------------------------------------------------------------------------- /include/edisassm/edisassm_exception.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef EDISASSM_EXCEPTION_20080414_H_ 20 | #define EDISASSM_EXCEPTION_20080414_H_ 21 | 22 | #include 23 | 24 | namespace edisassm { 25 | 26 | struct invalid_instruction : public std::exception { 27 | public: 28 | invalid_instruction(std::size_t size) : size_(size) { 29 | } 30 | 31 | std::size_t size() const { return size_; } 32 | 33 | private: 34 | std::size_t size_; 35 | }; 36 | 37 | struct instruction_too_big : invalid_instruction { instruction_too_big(std::size_t size) : invalid_instruction(size) {} }; 38 | struct invalid_operand : invalid_instruction { invalid_operand(std::size_t size) : invalid_instruction(size) {} }; 39 | struct too_many_operands : invalid_instruction { too_many_operands(std::size_t size) : invalid_instruction(size) {} }; 40 | struct multiple_displacements : invalid_instruction { multiple_displacements(std::size_t size) : invalid_instruction(size) {} }; 41 | 42 | } 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /include/edisassm/OPTable_Group12.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef OPTABLE_GROUP12_20080314_TCC_ 20 | #define OPTABLE_GROUP12_20080314_TCC_ 21 | 22 | namespace edisassm { 23 | 24 | template 25 | const typename Instruction::opcode_entry Instruction::Opcodes_Group12[16] = { 26 | { "mov", &Instruction::decode_Eb_Ib, OP_MOV, FLAG_NONE }, 27 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 28 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 29 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 30 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 31 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 32 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 33 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 34 | 35 | { "mov", &Instruction::decode_Ev_Iz, OP_MOV, FLAG_NONE }, 36 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 37 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 38 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 39 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 40 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 41 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 42 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 43 | }; 44 | 45 | } 46 | 47 | #endif 48 | 49 | -------------------------------------------------------------------------------- /include/edisassm/edisassm_functions.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef EDISASSM_FUNCTIONS_20130610_H_ 20 | #define EDISASSM_FUNCTIONS_20130610_H_ 21 | 22 | namespace edisassm { 23 | 24 | template 25 | bool is_call(const Instruction &insn) { 26 | return insn.type() == Instruction::OP_CALL; 27 | } 28 | 29 | template 30 | bool is_ret(const Instruction &insn) { 31 | return insn.type() == Instruction::OP_RET; 32 | } 33 | 34 | template 35 | bool is_conditional_jump(const Instruction &insn) { 36 | 37 | switch(insn.type()) { 38 | case Instruction::OP_JCC: 39 | case Instruction::OP_LOOP: 40 | case Instruction::OP_LOOPE: 41 | case Instruction::OP_LOOPNE: 42 | return true; 43 | default: 44 | return false; 45 | } 46 | } 47 | 48 | template 49 | bool is_unconditional_jump(const Instruction &insn) { 50 | return insn.type() == Instruction::OP_JMP; 51 | } 52 | 53 | template 54 | bool is_jump(const Instruction &insn) { 55 | return is_unconditional_jump(insn) || is_conditional_jump(insn); 56 | } 57 | 58 | template 59 | bool is_nop(const Instruction &insn) { 60 | return insn.type() == Instruction::OP_NOP; 61 | } 62 | 63 | template 64 | bool is_halt(const Instruction &insn) { 65 | return insn.type() == Instruction::OP_HLT; 66 | } 67 | 68 | template 69 | bool is_terminator(const Instruction &insn) { 70 | return is_halt(insn) || is_jump(insn) || is_ret(insn); 71 | } 72 | 73 | } 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /include/edisassm/OPTable_Group3.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef OPTABLE_GROUP3_20080314_TCC_ 20 | #define OPTABLE_GROUP3_20080314_TCC_ 21 | 22 | namespace edisassm { 23 | 24 | template 25 | const typename Instruction::opcode_entry Instruction::Opcodes_Group3[16] = { 26 | { "test", &Instruction::decode_Eb_Ib, OP_TEST, FLAG_NONE }, 27 | { "test", &Instruction::decode_Eb_Ib, OP_TEST, FLAG_NONE }, // undocumented 28 | { "not", &Instruction::decode_Eb, OP_NOT, FLAG_NONE }, 29 | { "neg", &Instruction::decode_Eb, OP_NEG, FLAG_W_FLAGS }, 30 | { "mul", &Instruction::decode_Eb, OP_MUL, FLAG_W_FLAGS }, 31 | { "imul", &Instruction::decode_Eb, OP_IMUL, FLAG_W_FLAGS }, 32 | { "div", &Instruction::decode_Eb, OP_DIV, FLAG_NONE }, 33 | { "idiv", &Instruction::decode_Eb, OP_IDIV, FLAG_NONE }, 34 | 35 | { "test", &Instruction::decode_Ev_Iz, OP_TEST, FLAG_NONE }, 36 | { "test", &Instruction::decode_Ev_Iz, OP_TEST, FLAG_NONE }, // undocumented 37 | { "not", &Instruction::decode_Ev, OP_NOT, FLAG_NONE }, 38 | { "neg", &Instruction::decode_Ev, OP_NEG, FLAG_W_FLAGS }, 39 | { "mul", &Instruction::decode_Ev, OP_MUL, FLAG_W_FLAGS }, 40 | { "imul", &Instruction::decode_Ev, OP_IMUL, FLAG_W_FLAGS }, 41 | { "div", &Instruction::decode_Ev, OP_DIV, FLAG_NONE }, 42 | { "idiv", &Instruction::decode_Ev, OP_IDIV, FLAG_NONE }, 43 | }; 44 | 45 | } 46 | 47 | #endif 48 | 49 | -------------------------------------------------------------------------------- /include/edisassm/OPTable_Group13.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef OPTABLE_GROUP13_20080314_TCC_ 20 | #define OPTABLE_GROUP13_20080314_TCC_ 21 | 22 | namespace edisassm { 23 | 24 | template 25 | const typename Instruction::opcode_entry Instruction::Opcodes_Group13[8] = { 26 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 27 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 28 | { "psrlw", &Instruction::decode_Nq_Ib, OP_PSRLW, FLAG_MMX }, 29 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 30 | { "psraw", &Instruction::decode_Nq_Ib, OP_PSRAW, FLAG_MMX }, 31 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 32 | { "psllw", &Instruction::decode_Nq_Ib, OP_PSLLW, FLAG_MMX }, 33 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 34 | }; 35 | 36 | template 37 | const typename Instruction::opcode_entry Instruction::Opcodes_Group13_66[8] = { 38 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 39 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 40 | { "psrlw", &Instruction::decode_Uo_Ib, OP_PSRLW, FLAG_SSE2 }, 41 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 42 | { "psraw", &Instruction::decode_Uo_Ib, OP_PSRAW, FLAG_SSE2 }, 43 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 44 | { "psllw", &Instruction::decode_Uo_Ib, OP_PSLLW, FLAG_SSE2 }, 45 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 46 | }; 47 | 48 | } 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /include/edisassm/OPTable_Group14.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef OPTABLE_GROUP14_20080314_TCC_ 20 | #define OPTABLE_GROUP14_20080314_TCC_ 21 | 22 | namespace edisassm { 23 | 24 | template 25 | const typename Instruction::opcode_entry Instruction::Opcodes_Group14[8] = { 26 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 27 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 28 | { "psrld", &Instruction::decode_Nq_Ib, OP_PSRLD, FLAG_NONE }, 29 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 30 | { "psrad", &Instruction::decode_Nq_Ib, OP_PSRAD, FLAG_NONE }, 31 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 32 | { "pslld", &Instruction::decode_Nq_Ib, OP_PSLLD, FLAG_NONE }, 33 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 34 | }; 35 | 36 | template 37 | const typename Instruction::opcode_entry Instruction::Opcodes_Group14_66[8] = { 38 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 39 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 40 | { "psrld", &Instruction::decode_Uo_Ib, OP_PSRLD, FLAG_NONE }, 41 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 42 | { "psrad", &Instruction::decode_Uo_Ib, OP_PSRAD, FLAG_NONE }, 43 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 44 | { "pslld", &Instruction::decode_Uo_Ib, OP_PSLLD, FLAG_NONE }, 45 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 46 | }; 47 | 48 | } 49 | 50 | #endif 51 | 52 | -------------------------------------------------------------------------------- /include/edisassm/OPTable_Group15.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef OPTABLE_GROUP15_20080314_TCC_ 20 | #define OPTABLE_GROUP15_20080314_TCC_ 21 | 22 | namespace edisassm { 23 | 24 | template 25 | const typename Instruction::opcode_entry Instruction::Opcodes_Group15[8] = { 26 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 27 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 28 | { "psrlq", &Instruction::decode_Nq_Ib, OP_PSRLQ, FLAG_NONE }, 29 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 30 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 31 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 32 | { "psllq", &Instruction::decode_Nq_Ib, OP_PSLLQ, FLAG_NONE }, 33 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 34 | }; 35 | 36 | template 37 | const typename Instruction::opcode_entry Instruction::Opcodes_Group15_66[8] = { 38 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 39 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 40 | { "psrlq", &Instruction::decode_Uo_Ib, OP_PSRLQ, FLAG_NONE }, 41 | { "psrldq", &Instruction::decode_Uo_Ib, OP_PSRLDQ, FLAG_SSE2 }, 42 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 43 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 44 | { "psllq", &Instruction::decode_Uo_Ib, OP_PSLLQ, FLAG_NONE }, 45 | { "pslldq", &Instruction::decode_Uo_Ib, OP_PSLLDQ, FLAG_SSE2 }, 46 | }; 47 | 48 | } 49 | 50 | #endif 51 | 52 | -------------------------------------------------------------------------------- /include/edisassm/OPTable_Group16.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef OPTABLE_GROUP16_20080314_TCC_ 20 | #define OPTABLE_GROUP16_20080314_TCC_ 21 | 22 | namespace edisassm { 23 | 24 | template 25 | const typename Instruction::opcode_entry Instruction::Opcodes_Group16_Mem[8] = { 26 | { "fxsave", &Instruction::decode_M512, OP_FXSAVE, FLAG_SSE }, 27 | { "fxrstor", &Instruction::decode_M512, OP_FXRSTOR, FLAG_SSE }, 28 | { "ldmxcsr", &Instruction::decode_Md, OP_LDMXCSR, FLAG_SSE }, 29 | { "stmxcsr", &Instruction::decode_Md, OP_STMXCSR, FLAG_SSE }, 30 | { "xsave", &Instruction::decode_M, OP_XSAVE, FLAG_NONE }, 31 | { "xrstor", &Instruction::decode_M, OP_XRSTOR, FLAG_NONE }, 32 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 33 | { "clflush", &Instruction::decode_M, OP_CLFLUSH, FLAG_SSE2 }, 34 | }; 35 | 36 | template 37 | const typename Instruction::opcode_entry Instruction::Opcodes_Group16_Reg[8] = { 38 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 39 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 40 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 41 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 42 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 43 | { "lfence", &Instruction::decode0, OP_LFENCE, FLAG_SSE2 }, 44 | { "mfence", &Instruction::decode0, OP_MFENCE, FLAG_SSE2 }, 45 | { "sfence", &Instruction::decode0, OP_SFENCE, FLAG_SSE }, 46 | }; 47 | 48 | } 49 | 50 | #endif 51 | 52 | -------------------------------------------------------------------------------- /include/edisassm/OPTable_Group17.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef OPTABLE_GROUP17_20080314_TCC_ 20 | #define OPTABLE_GROUP17_20080314_TCC_ 21 | 22 | namespace edisassm { 23 | 24 | template 25 | const typename Instruction::opcode_entry Instruction::Opcodes_Group17[64] = { 26 | { "prefetchnta", &Instruction::decode_M, OP_PREFETCHH, FLAG_NONE }, 27 | { "prefetcht0", &Instruction::decode_M, OP_PREFETCHH, FLAG_NONE }, 28 | { "prefetcht1", &Instruction::decode_M, OP_PREFETCHH, FLAG_NONE }, 29 | { "prefetcht2", &Instruction::decode_M, OP_PREFETCHH, FLAG_NONE }, 30 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 31 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 32 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 33 | { "nop", &Instruction::decode_Ev, OP_NOP, FLAG_NONE }, // undocumented 34 | 35 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 36 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 37 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 38 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 39 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 40 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 41 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 42 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 43 | 44 | INVALID_BLOCK, 45 | 46 | INVALID_BLOCK, 47 | 48 | INVALID_BLOCK 49 | }; 50 | 51 | } 52 | 53 | #endif 54 | 55 | -------------------------------------------------------------------------------- /include/edisassm/Formatter.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef FORMATTER_H_ 20 | #define FORMATTER_H_ 21 | 22 | #include 23 | 24 | namespace edisassm { 25 | 26 | template 27 | class Instruction; 28 | 29 | template 30 | class Operand; 31 | 32 | enum Syntax { 33 | SyntaxIntel, 34 | // SyntexATT // TODO(eteran): implement this format! 35 | }; 36 | 37 | enum Capitalization { 38 | UpperCase, 39 | LowerCase 40 | }; 41 | 42 | enum SmallNumberFormat { 43 | SmallNumAsHex, 44 | SmallNumAsDec 45 | }; 46 | 47 | struct FormatOptions { 48 | Syntax syntax; 49 | Capitalization capitalization; 50 | SmallNumberFormat smallNumFormat; 51 | }; 52 | 53 | class Formatter { 54 | public: 55 | Formatter(); 56 | Formatter(const Formatter &other); 57 | ~Formatter(); 58 | explicit Formatter(const FormatOptions &options); 59 | Formatter &operator=(const Formatter &rhs); 60 | 61 | public: 62 | FormatOptions options() const; 63 | void setOptions(const FormatOptions &options); 64 | 65 | public: 66 | template 67 | std::string to_string(const Instruction &inst) const; 68 | 69 | template 70 | std::string to_string(const Operand &op) const; 71 | 72 | template 73 | std::string to_byte_string(const Instruction &inst) const; 74 | 75 | template 76 | std::string register_name(typename Operand::Register reg) const; 77 | 78 | private: 79 | template 80 | std::string format_expression(const Operand &op) const; 81 | 82 | template 83 | std::string format_register(const Operand &op) const; 84 | 85 | public: 86 | void swap(Formatter &other); 87 | 88 | private: 89 | FormatOptions options_; 90 | }; 91 | 92 | } 93 | 94 | #include "Formatter.tcc" 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /tests/test_x86_64.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "edisassm/Instruction.h" 3 | #include "edisassm/Formatter.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | typedef edisassm::Instruction insn64_t; 10 | 11 | struct test_data_t { 12 | unsigned size; 13 | const char *bytes; 14 | const char *result; 15 | unsigned int flags; 16 | } test64_data[] = { 17 | {6,"\xf0\x66\x0f\x38\xf6\xc1", "lock adcx eax, ecx", insn64_t::FLAG_RW_FLAGS}, 18 | {5,"\x48\x0f\xba\xe4\xff", "bt rsp, 0xff", insn64_t::FLAG_W_FLAGS }, 19 | {2,"\xcd\x80", "int 0x80", insn64_t::FLAG_W_FLAGS}, 20 | {4,"\x66\x83\xe4\xfe", "and sp, 0xfffe", insn64_t::FLAG_W_FLAGS }, 21 | {4,"\x48\x83\xe4\xf0", "and rsp, 0xfffffffffffffff0", insn64_t::FLAG_W_FLAGS }, 22 | {2,"\x6a\xfe", "push 0xfffffffffffffffe", insn64_t::FLAG_STACK }, 23 | {5,"\x68\xff\xff\xff\xff", "push 0xffffffffffffffff", insn64_t::FLAG_STACK }, 24 | {7,"\x67\x8b\x05\x10\x00\x00\x00", "mov eax, dword ptr [eip+16]", insn64_t::FLAG_NONE }, 25 | {6,"\x8b\x05\x10\x00\x00\x00", "mov eax, dword ptr [rip+16]", insn64_t::FLAG_NONE }, 26 | 27 | 28 | {3, "\x0f\x20\x40", "mov eax, cr0", insn64_t::FLAG_R_FLAGS }, 29 | {3, "\x0f\x7e\xf0", "movd eax, mm6", insn64_t::FLAG_MMX}, 30 | {3, "\x0f\x6e\xf8", "movd mm7, eax", insn64_t::FLAG_MMX}, 31 | {5, "\x66\x44\x0f\x6e\xd1", "movd xmm10, ecx", insn64_t::FLAG_MMX}, 32 | {8,"\xf2\x0f\x10\x05\xc0\x87\x04\x08", "movsd xmm0, qword ptr [rip+0x080487c0]", insn64_t::FLAG_SSE2}, 33 | {9,"\xf2\x0f\x11\x84\x24\x98\x00\x00\x00", "movsd qword ptr [rsp+152], xmm0", insn64_t::FLAG_SSE2}, 34 | 35 | 36 | }; 37 | 38 | int main() { 39 | 40 | edisassm::FormatOptions options; 41 | options.syntax = edisassm::SyntaxIntel; 42 | options.capitalization = edisassm::LowerCase; 43 | options.smallNumFormat = edisassm::SmallNumAsHex; 44 | edisassm::Formatter formatter(options); 45 | 46 | for(size_t i = 0; i < sizeof(test64_data) / sizeof(test64_data[0]); ++i) { 47 | test_data_t *p = &test64_data[i]; 48 | 49 | std::cout << "performing test #" << i << "..."; 50 | insn64_t insn(p->bytes, p->bytes + p->size, 0x00000000, std::nothrow); 51 | 52 | if(!insn.valid() || formatter.to_string(insn) != p->result) { 53 | std::cout << "\n----------\n"; 54 | std::cout << "GOT : " << formatter.to_string(insn) << std::endl; 55 | std::cout << "EXPECTED : " << p->result << std::endl; 56 | std::cout << "FAIL" << std::endl; 57 | return -1; 58 | } 59 | 60 | if(insn.size() != p->size) { 61 | std::cout << "\n----------\n"; 62 | std::cout << formatter.to_byte_string(insn) << " incorrect size" << std::endl; 63 | std::cout << "FAIL" << std::endl; 64 | return -1; 65 | } 66 | 67 | if(insn.flags() != p->flags) { 68 | std::cout << "\n----------\n"; 69 | std::cout << formatter.to_byte_string(insn) << " wrong flags" << std::endl; 70 | std::cout << "FLAGS: " << insn.flags() << std::endl; 71 | std::cout << "FAIL" << std::endl; 72 | return -1; 73 | } 74 | 75 | std::cout << " " << formatter.to_byte_string(insn) << " '" << formatter.to_string(insn) << "' " << "OK" << std::endl; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /include/edisassm/OPTable_Group1.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef OPTABLE_GROUP1_20080314_TCC_ 20 | #define OPTABLE_GROUP1_20080314_TCC_ 21 | 22 | namespace edisassm { 23 | 24 | template 25 | const typename Instruction::opcode_entry Instruction::Opcodes_Group1[32] = { 26 | { "add", &Instruction::decode_Eb_Ib, OP_ADD, FLAG_W_FLAGS }, 27 | { "or", &Instruction::decode_Eb_Ib, OP_OR, FLAG_W_FLAGS }, 28 | { "adc", &Instruction::decode_Eb_Ib, OP_ADC, FLAG_RW_FLAGS }, 29 | { "sbb", &Instruction::decode_Eb_Ib, OP_SBB, FLAG_NONE }, 30 | { "and", &Instruction::decode_Eb_Ib, OP_AND, FLAG_W_FLAGS }, 31 | { "sub", &Instruction::decode_Eb_Ib, OP_SUB, FLAG_NONE }, 32 | { "xor", &Instruction::decode_Eb_Ib, OP_XOR, FLAG_NONE }, 33 | { "cmp", &Instruction::decode_Eb_Ib, OP_CMP, FLAG_W_FLAGS }, 34 | 35 | { "add", &Instruction::decode_Ev_Iz, OP_ADD, FLAG_W_FLAGS }, 36 | { "or", &Instruction::decode_Ev_Iz, OP_OR, FLAG_W_FLAGS }, 37 | { "adc", &Instruction::decode_Ev_Iz, OP_ADC, FLAG_RW_FLAGS }, 38 | { "sbb", &Instruction::decode_Ev_Iz, OP_SBB, FLAG_NONE }, 39 | { "and", &Instruction::decode_Ev_Iz, OP_AND, FLAG_W_FLAGS }, 40 | { "sub", &Instruction::decode_Ev_Iz, OP_SUB, FLAG_NONE }, 41 | { "xor", &Instruction::decode_Ev_Iz, OP_XOR, FLAG_NONE }, 42 | { "cmp", &Instruction::decode_Ev_Iz, OP_CMP, FLAG_W_FLAGS }, 43 | 44 | { "add", &Instruction::decode_Eb_Ib, OP_ADD, FLAG_W_FLAGS }, 45 | { "or", &Instruction::decode_Eb_Ib, OP_OR, FLAG_W_FLAGS }, 46 | { "adc", &Instruction::decode_Eb_Ib, OP_ADC, FLAG_RW_FLAGS }, 47 | { "sbb", &Instruction::decode_Eb_Ib, OP_SBB, FLAG_NONE }, 48 | { "and", &Instruction::decode_Eb_Ib, OP_AND, FLAG_W_FLAGS }, 49 | { "sub", &Instruction::decode_Eb_Ib, OP_SUB, FLAG_NONE }, 50 | { "xor", &Instruction::decode_Eb_Ib, OP_XOR, FLAG_NONE }, 51 | { "cmp", &Instruction::decode_Eb_Ib, OP_CMP, FLAG_W_FLAGS }, 52 | 53 | { "add", &Instruction::decode_Ev_Ixb, OP_ADD, FLAG_W_FLAGS }, 54 | { "or", &Instruction::decode_Ev_Ixb, OP_OR, FLAG_W_FLAGS }, 55 | { "adc", &Instruction::decode_Ev_Ixb, OP_ADC, FLAG_RW_FLAGS }, 56 | { "sbb", &Instruction::decode_Ev_Ixb, OP_SBB, FLAG_NONE }, 57 | { "and", &Instruction::decode_Ev_Ixb, OP_AND, FLAG_W_FLAGS }, 58 | { "sub", &Instruction::decode_Ev_Ixb, OP_SUB, FLAG_NONE }, 59 | { "xor", &Instruction::decode_Ev_Ixb, OP_XOR, FLAG_NONE }, 60 | { "cmp", &Instruction::decode_Ev_Ixb, OP_CMP, FLAG_W_FLAGS }, 61 | }; 62 | 63 | } 64 | 65 | #endif 66 | 67 | -------------------------------------------------------------------------------- /Formatter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include "edisassm/Formatter.h" 20 | #include 21 | 22 | namespace edisassm { 23 | 24 | //------------------------------------------------------------------------------ 25 | // Name: Formatter 26 | //------------------------------------------------------------------------------ 27 | Formatter::Formatter() { 28 | options_.syntax = SyntaxIntel; 29 | options_.capitalization = LowerCase; 30 | options_.smallNumFormat = SmallNumAsDec; 31 | } 32 | 33 | //------------------------------------------------------------------------------ 34 | // Name: Formatter 35 | //------------------------------------------------------------------------------ 36 | Formatter::Formatter(const Formatter &other) : options_(other.options_) { 37 | 38 | } 39 | 40 | //------------------------------------------------------------------------------ 41 | // Name: ~Formatter 42 | //------------------------------------------------------------------------------ 43 | Formatter::~Formatter() { 44 | 45 | } 46 | 47 | //------------------------------------------------------------------------------ 48 | // Name: Formatter 49 | //------------------------------------------------------------------------------ 50 | Formatter::Formatter(const FormatOptions &options) : options_(options) { 51 | 52 | } 53 | 54 | //------------------------------------------------------------------------------ 55 | // Name: options 56 | //------------------------------------------------------------------------------ 57 | FormatOptions Formatter::options() const { 58 | return options_; 59 | } 60 | 61 | //------------------------------------------------------------------------------ 62 | // Name: setOptions 63 | //------------------------------------------------------------------------------ 64 | void Formatter::setOptions(const FormatOptions &options) { 65 | options_ = options; 66 | } 67 | 68 | //------------------------------------------------------------------------------ 69 | // Name: operator= 70 | //------------------------------------------------------------------------------ 71 | Formatter &Formatter::operator=(const Formatter &rhs) { 72 | Formatter(rhs).swap(*this); 73 | return *this; 74 | } 75 | 76 | //------------------------------------------------------------------------------ 77 | // Name: swap 78 | //------------------------------------------------------------------------------ 79 | void Formatter::swap(Formatter &other) { 80 | using std::swap; 81 | swap(options_, other.options_); 82 | } 83 | 84 | } 85 | -------------------------------------------------------------------------------- /include/edisassm/OPTable_Group9.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef OPTABLE_GROUP9_20080314_TCC_ 20 | #define OPTABLE_GROUP9_20080314_TCC_ 21 | 22 | namespace edisassm { 23 | 24 | template 25 | const typename Instruction::opcode_entry Instruction::Opcodes_Group9[8] = { 26 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 27 | { "cmpxchg8b/cmpxchg16b", &Instruction::decode_invalid_cmpxchg8b_cmpxchg16b, OP_GROUP, FLAG_NONE }, 28 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 29 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 30 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 31 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 32 | { "vmptrld", &Instruction::decode_Mq, OP_VMPTRLD, FLAG_VMX }, 33 | { "vmptrst", &Instruction::decode_Mq, OP_VMPTRST, FLAG_VMX }, 34 | }; 35 | 36 | template 37 | const typename Instruction::opcode_entry Instruction::Opcodes_Group9_66[8] = { 38 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 39 | { "cmpxchg8b/cmpxchg16b", &Instruction::decode_invalid_cmpxchg8b_cmpxchg16b, OP_GROUP, FLAG_NONE }, 40 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 41 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 42 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 43 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 44 | { "vmclear", &Instruction::decode_Mq, OP_VMCLEAR, FLAG_VMX }, 45 | { "vmptrst", &Instruction::decode_Mq, OP_VMPTRST, FLAG_VMX }, 46 | }; 47 | 48 | template 49 | const typename Instruction::opcode_entry Instruction::Opcodes_Group9_F3[8] = { 50 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 51 | { "cmpxchg8b/cmpxchg16b", &Instruction::decode_invalid_cmpxchg8b_cmpxchg16b, OP_GROUP, FLAG_NONE }, 52 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 53 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 54 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 55 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 56 | { "vmxon", &Instruction::decode_Mq, OP_VMXON, FLAG_VMX }, 57 | { "vmptrst", &Instruction::decode_Mq, OP_VMPTRST, FLAG_VMX }, 58 | }; 59 | 60 | } 61 | 62 | #endif 63 | 64 | -------------------------------------------------------------------------------- /include/edisassm/OPTable_Group2.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef OPTABLE_GROUP2_20080314_TCC_ 20 | #define OPTABLE_GROUP2_20080314_TCC_ 21 | 22 | namespace edisassm { 23 | 24 | template 25 | const typename Instruction::opcode_entry Instruction::Opcodes_Group2[16] = { 26 | { "rol", &Instruction::decode_Eb_Ib, OP_ROL, FLAG_NONE }, 27 | { "ror", &Instruction::decode_Eb_Ib, OP_ROR, FLAG_NONE }, 28 | { "rcl", &Instruction::decode_Eb_Ib, OP_RCL, FLAG_NONE }, 29 | { "rcr", &Instruction::decode_Eb_Ib, OP_RCR, FLAG_NONE }, 30 | { "shl", &Instruction::decode_Eb_Ib, OP_SHL, FLAG_NONE }, 31 | { "shr", &Instruction::decode_Eb_Ib, OP_SHR, FLAG_NONE }, 32 | { "sal", &Instruction::decode_Eb_Ib, OP_SAL, FLAG_NONE }, 33 | { "sar", &Instruction::decode_Eb_Ib, OP_SAR, FLAG_NONE }, 34 | 35 | { "rol", &Instruction::decode_Ev_Ib, OP_ROL, FLAG_NONE }, 36 | { "ror", &Instruction::decode_Ev_Ib, OP_ROR, FLAG_NONE }, 37 | { "rcl", &Instruction::decode_Ev_Ib, OP_RCL, FLAG_NONE }, 38 | { "rcr", &Instruction::decode_Ev_Ib, OP_RCR, FLAG_NONE }, 39 | { "shl", &Instruction::decode_Ev_Ib, OP_SHL, FLAG_NONE }, 40 | { "shr", &Instruction::decode_Ev_Ib, OP_SHR, FLAG_NONE }, 41 | { "sal", &Instruction::decode_Ev_Ib, OP_SAL, FLAG_NONE }, 42 | { "sar", &Instruction::decode_Ev_Ib, OP_SAR, FLAG_NONE }, 43 | }; 44 | 45 | template 46 | const typename Instruction::opcode_entry Instruction::Opcodes_Group2D[32] = { 47 | { "rol", &Instruction::decode_Eb_1, OP_ROL, FLAG_NONE }, 48 | { "ror", &Instruction::decode_Eb_1, OP_ROR, FLAG_NONE }, 49 | { "rcl", &Instruction::decode_Eb_1, OP_RCL, FLAG_NONE }, 50 | { "rcr", &Instruction::decode_Eb_1, OP_RCR, FLAG_NONE }, 51 | { "shl", &Instruction::decode_Eb_1, OP_SHL, FLAG_NONE }, 52 | { "shr", &Instruction::decode_Eb_1, OP_SHR, FLAG_NONE }, 53 | { "sal", &Instruction::decode_Eb_1, OP_SAL, FLAG_NONE }, 54 | { "sar", &Instruction::decode_Eb_1, OP_SAR, FLAG_NONE }, 55 | 56 | { "rol", &Instruction::decode_Ev_1, OP_ROL, FLAG_NONE }, 57 | { "ror", &Instruction::decode_Ev_1, OP_ROR, FLAG_NONE }, 58 | { "rcl", &Instruction::decode_Ev_1, OP_RCL, FLAG_NONE }, 59 | { "rcr", &Instruction::decode_Ev_1, OP_RCR, FLAG_NONE }, 60 | { "shl", &Instruction::decode_Ev_1, OP_SHL, FLAG_NONE }, 61 | { "shr", &Instruction::decode_Ev_1, OP_SHR, FLAG_NONE }, 62 | { "sal", &Instruction::decode_Ev_1, OP_SAL, FLAG_NONE }, 63 | { "sar", &Instruction::decode_Ev_1, OP_SAR, FLAG_NONE }, 64 | 65 | { "rol", &Instruction::decode_Eb_CL, OP_ROL, FLAG_NONE }, 66 | { "ror", &Instruction::decode_Eb_CL, OP_ROR, FLAG_NONE }, 67 | { "rcl", &Instruction::decode_Eb_CL, OP_RCL, FLAG_NONE }, 68 | { "rcr", &Instruction::decode_Eb_CL, OP_RCR, FLAG_NONE }, 69 | { "shl", &Instruction::decode_Eb_CL, OP_SHL, FLAG_NONE }, 70 | { "shr", &Instruction::decode_Eb_CL, OP_SHR, FLAG_NONE }, 71 | { "sal", &Instruction::decode_Eb_CL, OP_SAL, FLAG_NONE }, 72 | { "sar", &Instruction::decode_Eb_CL, OP_SAR, FLAG_NONE }, 73 | 74 | { "rol", &Instruction::decode_Ev_CL, OP_ROL, FLAG_NONE }, 75 | { "ror", &Instruction::decode_Ev_CL, OP_ROR, FLAG_NONE }, 76 | { "rcl", &Instruction::decode_Ev_CL, OP_RCL, FLAG_NONE }, 77 | { "rcr", &Instruction::decode_Ev_CL, OP_RCR, FLAG_NONE }, 78 | { "shl", &Instruction::decode_Ev_CL, OP_SHL, FLAG_NONE }, 79 | { "shr", &Instruction::decode_Ev_CL, OP_SHR, FLAG_NONE }, 80 | { "sal", &Instruction::decode_Ev_CL, OP_SAL, FLAG_NONE }, 81 | { "sar", &Instruction::decode_Ev_CL, OP_SAR, FLAG_NONE }, 82 | }; 83 | 84 | } 85 | 86 | #endif 87 | 88 | -------------------------------------------------------------------------------- /include/edisassm/Operand.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef OPERAND_20080421_TCC_ 20 | #define OPERAND_20080421_TCC_ 21 | 22 | #include "Instruction.h" 23 | #include 24 | #include 25 | 26 | namespace edisassm { 27 | 28 | //------------------------------------------------------------------------------ 29 | // Name: Operand 30 | //------------------------------------------------------------------------------ 31 | template 32 | Operand::Operand() : owner_(0), type_(TYPE_INVALID) { 33 | using std::memset; 34 | memset(&u, 0, sizeof(U)); 35 | } 36 | 37 | //------------------------------------------------------------------------------ 38 | // Name: swap 39 | //------------------------------------------------------------------------------ 40 | template 41 | void Operand::swap(Operand &other) { 42 | using std::swap; 43 | 44 | swap(owner_, other.owner_); 45 | swap(type_, other.type_); 46 | swap(u, other.u); 47 | } 48 | 49 | //------------------------------------------------------------------------------ 50 | // Name: relative_target 51 | //------------------------------------------------------------------------------ 52 | template 53 | uint64_t Operand::relative_target() const { 54 | 55 | const uint64_t rva = owner_->rva(); 56 | const unsigned int size = owner_->size(); 57 | const uint64_t offset = rva + size; 58 | 59 | switch(type_) { 60 | case TYPE_REL8: 61 | return static_cast(u.sbyte + offset); 62 | case TYPE_REL16: 63 | // NOTE: intel truncates EIP to 16-bit here 64 | return static_cast((u.sword + offset) & 0xffff); 65 | case TYPE_REL32: 66 | return static_cast(u.sdword + offset); 67 | case TYPE_REL64: 68 | return static_cast(u.sqword + offset); 69 | default: 70 | return 0; 71 | } 72 | } 73 | 74 | //------------------------------------------------------------------------------ 75 | // Name: displacement 76 | //------------------------------------------------------------------------------ 77 | template 78 | int32_t Operand::displacement() const { 79 | 80 | switch(u.expression.displacement_type) { 81 | case DISP_U8: return static_cast(u.expression.u_disp8); 82 | case DISP_U16: return static_cast(u.expression.u_disp16); 83 | case DISP_U32: return static_cast(u.expression.u_disp32); 84 | case DISP_S8: return static_cast(u.expression.s_disp8); 85 | case DISP_S16: return static_cast(u.expression.s_disp16); 86 | case DISP_S32: return static_cast(u.expression.s_disp32); 87 | default: 88 | return 0; 89 | } 90 | } 91 | 92 | //------------------------------------------------------------------------------ 93 | // Name: immediate 94 | //------------------------------------------------------------------------------ 95 | template 96 | int64_t Operand::immediate() const { 97 | 98 | switch(type_) { 99 | case TYPE_IMMEDIATE8: return static_cast(u.sbyte); 100 | case TYPE_IMMEDIATE16: return static_cast(u.sword); 101 | case TYPE_IMMEDIATE32: return static_cast(u.sdword); 102 | case TYPE_IMMEDIATE64: return static_cast(u.sqword); 103 | default: 104 | return 0; 105 | } 106 | } 107 | 108 | //------------------------------------------------------------------------------ 109 | // Name: general_type 110 | //------------------------------------------------------------------------------ 111 | template 112 | typename Operand::Type Operand::general_type() const { 113 | return static_cast(static_cast(type_) & TYPE_MASK); 114 | } 115 | 116 | } 117 | 118 | #endif 119 | -------------------------------------------------------------------------------- /include/edisassm/edisassm_ops.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef EDISASSM_OPS_20110816_H_ 20 | #define EDISASSM_OPS_20110816_H_ 21 | 22 | namespace edisassm { 23 | 24 | //------------------------------------------------------------------------------ 25 | // Name: operator== 26 | //------------------------------------------------------------------------------ 27 | template 28 | bool operator==(const Instruction &lhs, const Instruction &rhs) { 29 | // invalid ops match nothing 30 | if(!lhs.valid() || !rhs.valid()) { 31 | return false; 32 | } 33 | 34 | // do the types match? 35 | if(lhs.type() != rhs.type()) { 36 | return false; 37 | } 38 | 39 | const unsigned int lhs_operand_count = lhs.operand_count(); 40 | const unsigned int rhs_operand_count = rhs.operand_count(); 41 | 42 | // do the number of operands match? 43 | if(lhs_operand_count != rhs_operand_count) { 44 | return false; 45 | } 46 | 47 | // compare the type and value of each operand 48 | for(unsigned int i = 0; i < lhs_operand_count; ++i) { 49 | 50 | const typename Instruction::operand_type &lhs_operand = lhs.operands_[i]; 51 | const typename Instruction::operand_type &rhs_operand = rhs.operands_[i]; 52 | 53 | typename Instruction::operand_type::Type lhs_operand_type = lhs_operand.general_type(); 54 | typename Instruction::operand_type::Type rhs_operand_type = rhs_operand.general_type(); 55 | 56 | if(lhs_operand_type != rhs_operand_type) { 57 | return false; 58 | } 59 | 60 | // TODO(eteran): support generics 61 | switch(lhs_operand_type) { 62 | case Operand::TYPE_REGISTER: 63 | if(lhs_operand.reg() != rhs_operand.reg()) { 64 | return false; 65 | } 66 | break; 67 | case Operand::TYPE_IMMEDIATE: 68 | if(lhs_operand.immediate() != rhs_operand.immediate()) { 69 | return false; 70 | } 71 | break; 72 | case Operand::TYPE_REL: 73 | if(lhs_operand.relative_target() != rhs_operand.relative_target()) { 74 | return false; 75 | } 76 | break; 77 | case Operand::TYPE_ABSOLUTE: 78 | if(lhs_operand.absolute().offset != rhs_operand.absolute().offset) { 79 | return false; 80 | } 81 | 82 | if(lhs_operand.absolute().seg != rhs_operand.absolute().seg) { 83 | return false; 84 | } 85 | break; 86 | default: 87 | case Operand::TYPE_EXPRESSION: 88 | { 89 | // This is a bit more complex, because there are mathematical 90 | // equivalencies 91 | typename Operand::expression_t lhs_expression = lhs_operand.expression(); 92 | typename Operand::expression_t rhs_expression = rhs_operand.expression(); 93 | 94 | 95 | if(lhs_operand.displacement() != rhs_operand.displacement()) { 96 | return false; 97 | } 98 | 99 | // the simple case 100 | if( lhs_expression.base == rhs_expression.base && 101 | lhs_expression.index == rhs_expression.index && 102 | lhs_expression.scale == rhs_expression.scale) { 103 | 104 | return true; 105 | } 106 | 107 | // Inst1 [index * 1] == Inst2 [base] 108 | if( lhs_expression.base == Operand::REG_NULL && 109 | lhs_expression.scale == 1 && 110 | lhs_expression.index == rhs_expression.base) { 111 | 112 | 113 | return true; 114 | } 115 | 116 | // Inst2 [index * 1] == Inst1 [base] 117 | if( rhs_expression.base == Operand::REG_NULL && 118 | rhs_expression.scale == 1 && 119 | rhs_expression.index == lhs_expression.base) { 120 | 121 | 122 | return true; 123 | } 124 | 125 | if(lhs_expression.index == Operand::REG_NULL || rhs_expression.index == Operand::REG_NULL) { 126 | if(lhs_expression.base == rhs_expression.base) { 127 | return true; 128 | } 129 | } 130 | 131 | return false; 132 | } 133 | break; 134 | } 135 | } 136 | 137 | return true; 138 | } 139 | 140 | //------------------------------------------------------------------------------ 141 | // Name: operator!= 142 | //------------------------------------------------------------------------------ 143 | template 144 | bool operator!=(const Instruction &lhs, const Instruction &rhs) { 145 | return !(lhs == rhs); 146 | } 147 | 148 | } 149 | 150 | #endif 151 | -------------------------------------------------------------------------------- /edisassm.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #include "edisassm/Instruction.h" 20 | #include "edisassm/Formatter.h" 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | using namespace edisassm; 28 | 29 | namespace { 30 | 31 | enum DISPLAY_FLAGS { 32 | FLAG_NONE = 0x00, 33 | FLAG_SHOW_BYTES = 0x01 34 | }; 35 | 36 | template 37 | std::string format_invalid_instruction(const Instruction &inst) { 38 | char byte_buffer[32]; 39 | const uint8_t *const buf = inst.bytes(); 40 | 41 | switch(inst.size()) { 42 | case 1: 43 | snprintf(byte_buffer, sizeof(byte_buffer), "db 0x%02x", buf[0] & 0xff); 44 | break; 45 | case 2: 46 | snprintf(byte_buffer, sizeof(byte_buffer), "dw 0x%02x%02x", buf[1] & 0xff, buf[0] & 0xff); 47 | break; 48 | case 4: 49 | snprintf(byte_buffer, sizeof(byte_buffer), "dd 0x%02x%02x%02x%02x", buf[3] & 0xff, buf[2] & 0xff, buf[1] & 0xff, buf[0] & 0xff); 50 | break; 51 | case 8: 52 | snprintf(byte_buffer, sizeof(byte_buffer), "dq 0x%02x%02x%02x%02x%02x%02x%02x%02x", buf[7] & 0xff, buf[6] & 0xff, buf[5] & 0xff, buf[4] & 0xff, buf[3] & 0xff, buf[2] & 0xff, buf[1] & 0xff, buf[0] & 0xff); 53 | break; 54 | default: 55 | // we tried...didn't we? 56 | return "invalid"; 57 | } 58 | return byte_buffer; 59 | } 60 | 61 | //------------------------------------------------------------------------------ 62 | // Name: disassemble 63 | //------------------------------------------------------------------------------ 64 | template 65 | void disassemble(In first, In last, uint64_t rva, unsigned int flags) { 66 | 67 | typedef Instruction insn_t; 68 | 69 | Formatter formatter; 70 | 71 | while(first != last) { 72 | 73 | insn_t instruction(first, last, rva, std::nothrow); 74 | if(instruction) { 75 | std::cout << std::hex << rva << ": "; 76 | if(flags & FLAG_SHOW_BYTES) { 77 | std::cout << formatter.to_byte_string(instruction) << " "; 78 | } 79 | std::cout << formatter.to_string(instruction) << '\n'; 80 | first += instruction.size(); 81 | rva += instruction.size(); 82 | } else { 83 | std::cout << std::hex << rva << ": "; 84 | if(flags & FLAG_SHOW_BYTES) { 85 | std::cout << formatter.to_byte_string(instruction) << " "; 86 | } 87 | std::cout << format_invalid_instruction(instruction) << " (bad)\n"; 88 | first += instruction.size(); 89 | rva += instruction.size(); 90 | } 91 | } 92 | } 93 | 94 | //------------------------------------------------------------------------------ 95 | // Name: print_usage 96 | //------------------------------------------------------------------------------ 97 | void print_usage(const char *arg0) { 98 | std::cerr << arg0 << " [-m32|-m64] [-x] [--rva
] [--show-bytes] [ | -]" << std::endl; 99 | exit(-1); 100 | } 101 | 102 | //------------------------------------------------------------------------------ 103 | // Name: get_input 104 | //------------------------------------------------------------------------------ 105 | std::vector get_input(const std::string &filename, bool hex_chars) { 106 | 107 | std::vector r; 108 | 109 | std::ifstream file; 110 | std::istream *s = 0; 111 | 112 | if(filename == "-") { 113 | s = &std::cin; 114 | } else { 115 | file.open(filename.c_str(), std::ios::binary); 116 | if(file) { 117 | s = &file; 118 | } else { 119 | std::cerr << "could not open the file: " << filename << std::endl; 120 | } 121 | } 122 | 123 | if(s) { 124 | std::istream &stream = *s; 125 | 126 | if(hex_chars) { 127 | uint32_t x; 128 | while(stream >> std::hex >> x) { 129 | r.push_back(x); 130 | } 131 | } else { 132 | r.assign(std::istreambuf_iterator(stream), std::istreambuf_iterator()); 133 | } 134 | } 135 | 136 | return r; 137 | } 138 | 139 | } 140 | 141 | //------------------------------------------------------------------------------ 142 | // Name: main 143 | //------------------------------------------------------------------------------ 144 | int main(int argc, char *argv[]) { 145 | 146 | unsigned int flags = FLAG_NONE; 147 | bool x86_64_mode = false; 148 | bool hex_chars = false; 149 | uint64_t rva_address = 0; 150 | std::string filename; 151 | 152 | for(int i = 1; i < argc; ++i) { 153 | if(argv[i][0] == '-') { 154 | if(strcmp(argv[i], "-m32") == 0) { 155 | x86_64_mode = false; 156 | } else if(strcmp(argv[i], "-m64") == 0) { 157 | x86_64_mode = true; 158 | } else if(strcmp(argv[i], "-x") == 0) { 159 | hex_chars = true; 160 | } else if(strcmp(argv[i], "--rva") == 0) { 161 | ++i; 162 | if(argv[i] == 0) { 163 | print_usage(argv[0]); 164 | } 165 | rva_address = strtoul(argv[i], 0, 0); 166 | } else if(strcmp(argv[i], "--show-bytes") == 0) { 167 | flags |= FLAG_SHOW_BYTES; 168 | } else if(strcmp(argv[i], "-") == 0) { 169 | filename = argv[i]; 170 | break; 171 | } else { 172 | print_usage(argv[0]); 173 | } 174 | } else { 175 | filename = argv[i]; 176 | break; 177 | } 178 | } 179 | 180 | if(filename.empty()) { 181 | print_usage(argv[0]); 182 | } 183 | 184 | const std::vector data = get_input(filename, hex_chars); 185 | 186 | if(x86_64_mode) { 187 | disassemble(data.begin(), data.end(), rva_address, flags); 188 | } else { 189 | disassemble(data.begin(), data.end(), rva_address, flags); 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /include/edisassm/OPTable_Group7.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef OPTABLE_GROUP7_20080314_TCC_ 20 | #define OPTABLE_GROUP7_20080314_TCC_ 21 | 22 | namespace edisassm { 23 | 24 | template 25 | const typename Instruction::opcode_entry Instruction::Opcodes_Group7[8] = { 26 | { "sgdt", &Instruction::decode_Ms, OP_SGDT, FLAG_NONE }, 27 | { "sidt", &Instruction::decode_Ms, OP_SIDT, FLAG_NONE }, 28 | { "lgdt", &Instruction::decode_Ms, OP_LGDT, FLAG_NONE }, 29 | { "lidt", &Instruction::decode_Ms, OP_LIDT, FLAG_NONE }, 30 | { "smsw", &Instruction::decode_Rv_Mw, OP_SMSW, FLAG_NONE }, 31 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 32 | { "lmsw", &Instruction::decode_Ew, OP_LMSW, FLAG_NONE }, 33 | { "invlpg", &Instruction::decode_Mb, OP_INVLPG, FLAG_NONE }, 34 | }; 35 | 36 | template 37 | const typename Instruction::opcode_entry Instruction::Opcodes_Group7A[64] = { 38 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 39 | { "vmcall", &Instruction::decode0, OP_VMCALL, FLAG_VMX | FLAG_W_FLAGS }, 40 | { "vmlaunch", &Instruction::decode0, OP_VMLAUNCH, FLAG_VMX | FLAG_W_FLAGS }, 41 | { "vmresume", &Instruction::decode0, OP_VMRESUME, FLAG_VMX | FLAG_W_FLAGS }, 42 | { "vmxoff", &Instruction::decode0, OP_VMXOFF, FLAG_VMX | FLAG_W_FLAGS }, 43 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 44 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 45 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 46 | 47 | { "monitor", &Instruction::decode0, OP_MONITOR, FLAG_SSE3 }, 48 | { "mwait", &Instruction::decode0, OP_MWAIT, FLAG_SSE3 }, 49 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 50 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 51 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 52 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 53 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 54 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 55 | 56 | { "xgetbv", &Instruction::decode0, OP_XGETBV, FLAG_NONE }, 57 | { "xsetbv", &Instruction::decode0, OP_XSETBV, FLAG_NONE }, 58 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 59 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 60 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 61 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 62 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 63 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 64 | 65 | { "vmrun", &Instruction::decode0, OP_VMRUN, FLAG_AMD }, 66 | { "vmmcall", &Instruction::decode0, OP_VMMCALL, FLAG_AMD }, 67 | { "vmload", &Instruction::decode0, OP_VMLOAD, FLAG_AMD }, 68 | { "vmsave", &Instruction::decode0, OP_VMSAVE, FLAG_AMD }, 69 | { "stgi", &Instruction::decode0, OP_STGI, FLAG_AMD }, 70 | { "clgi", &Instruction::decode0, OP_CLGI, FLAG_AMD }, 71 | { "skinit", &Instruction::decode0, OP_SKINIT, FLAG_AMD }, 72 | { "invlpga", &Instruction::decode0, OP_INVLPGA, FLAG_AMD }, 73 | 74 | { "smsw", &Instruction::decode_Rv_Mw, OP_SMSW, FLAG_NONE }, 75 | { "smsw", &Instruction::decode_Rv_Mw, OP_SMSW, FLAG_NONE }, 76 | { "smsw", &Instruction::decode_Rv_Mw, OP_SMSW, FLAG_NONE }, 77 | { "smsw", &Instruction::decode_Rv_Mw, OP_SMSW, FLAG_NONE }, 78 | { "smsw", &Instruction::decode_Rv_Mw, OP_SMSW, FLAG_NONE }, 79 | { "smsw", &Instruction::decode_Rv_Mw, OP_SMSW, FLAG_NONE }, 80 | { "smsw", &Instruction::decode_Rv_Mw, OP_SMSW, FLAG_NONE }, 81 | { "smsw", &Instruction::decode_Rv_Mw, OP_SMSW, FLAG_NONE }, 82 | 83 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 84 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 85 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 86 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 87 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 88 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 89 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 90 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 91 | 92 | { "lmsw", &Instruction::decode_Ew, OP_LMSW, FLAG_NONE }, 93 | { "lmsw", &Instruction::decode_Ew, OP_LMSW, FLAG_NONE }, 94 | { "lmsw", &Instruction::decode_Ew, OP_LMSW, FLAG_NONE }, 95 | { "lmsw", &Instruction::decode_Ew, OP_LMSW, FLAG_NONE }, 96 | { "lmsw", &Instruction::decode_Ew, OP_LMSW, FLAG_NONE }, 97 | { "lmsw", &Instruction::decode_Ew, OP_LMSW, FLAG_NONE }, 98 | { "lmsw", &Instruction::decode_Ew, OP_LMSW, FLAG_NONE }, 99 | { "lmsw", &Instruction::decode_Ew, OP_LMSW, FLAG_NONE }, 100 | 101 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, // x86-64: swapgs 102 | { "rdtscp", &Instruction::decode0, OP_RDTSCP, FLAG_NONE }, 103 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 104 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 105 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 106 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 107 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 108 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 109 | }; 110 | 111 | } 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /include/edisassm/Operand.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef OPERAND_20070521_H_ 20 | #define OPERAND_20070521_H_ 21 | 22 | #include 23 | 24 | namespace edisassm { 25 | 26 | template 27 | class Instruction; 28 | 29 | template 30 | class Operand { 31 | private: 32 | friend class Instruction; 33 | 34 | public: 35 | Operand(); 36 | ~Operand() {} 37 | 38 | private: 39 | typedef Operand operand_type; 40 | typedef Instruction instruction_type; 41 | 42 | public: 43 | enum Register { 44 | // a special value to mean "no register used" when appropriate 45 | REG_NULL, 46 | 47 | REG_RAX, REG_RCX, REG_RDX, REG_RBX, 48 | REG_RSP, REG_RBP, REG_RSI, REG_RDI, 49 | REG_R8, REG_R9, REG_R10, REG_R11, 50 | REG_R12, REG_R13, REG_R14, REG_R15, 51 | 52 | REG_EAX, REG_ECX, REG_EDX, REG_EBX, 53 | REG_ESP, REG_EBP, REG_ESI, REG_EDI, 54 | REG_R8D, REG_R9D, REG_R10D, REG_R11D, 55 | REG_R12D, REG_R13D, REG_R14D, REG_R15D, 56 | 57 | REG_AX, REG_CX, REG_DX, REG_BX, 58 | REG_SP, REG_BP, REG_SI, REG_DI, 59 | REG_R8W, REG_R9W, REG_R10W, REG_R11W, 60 | REG_R12W, REG_R13W, REG_R14W, REG_R15W, 61 | 62 | REG_AL, REG_CL, REG_DL, REG_BL, 63 | REG_AH, REG_CH, REG_DH, REG_BH, 64 | REG_R8B, REG_R9B, REG_R10B, REG_R11B, 65 | REG_R12B, REG_R13B, REG_R14B, REG_R15B, 66 | REG_SPL, REG_BPL, REG_SIL, REG_DIL, 67 | 68 | REG_ES, REG_CS, REG_SS, REG_DS, 69 | REG_FS, REG_GS, REG_SEG7, REG_SEG8, 70 | 71 | REG_CR0, REG_CR1, REG_CR2, REG_CR3, 72 | REG_CR4, REG_CR5, REG_CR6, REG_CR7, 73 | REG_CR8, REG_CR9, REG_CR10, REG_CR11, 74 | REG_CR12, REG_CR13, REG_CR14, REG_CR15, 75 | 76 | REG_DR0, REG_DR1, REG_DR2, REG_DR3, 77 | REG_DR4, REG_DR5, REG_DR6, REG_DR7, 78 | REG_DR8, REG_DR9, REG_DR10, REG_DR11, 79 | REG_DR12, REG_DR13, REG_DR14, REG_DR15, 80 | 81 | REG_TR0, REG_TR1, REG_TR2, REG_TR3, 82 | REG_TR4, REG_TR5, REG_TR6, REG_TR7, 83 | 84 | REG_MM0, REG_MM1, REG_MM2, REG_MM3, 85 | REG_MM4, REG_MM5, REG_MM6, REG_MM7, 86 | 87 | REG_XMM0, REG_XMM1, REG_XMM2, REG_XMM3, 88 | REG_XMM4, REG_XMM5, REG_XMM6, REG_XMM7, 89 | REG_XMM8, REG_XMM9, REG_XMM10, REG_XMM11, 90 | REG_XMM12, REG_XMM13, REG_XMM14, REG_XMM15, 91 | 92 | REG_ST, 93 | REG_ST0, REG_ST1, REG_ST2, REG_ST3, 94 | REG_ST4, REG_ST5, REG_ST6, REG_ST7, 95 | 96 | REG_RIP, 97 | REG_EIP, 98 | 99 | // special value meaning an error in decoding 100 | REG_INVALID 101 | }; 102 | 103 | enum Type { 104 | TYPE_INVALID = 0x00000000, 105 | TYPE_REGISTER = 0x00000100, 106 | TYPE_IMMEDIATE = 0x00000200, 107 | TYPE_IMMEDIATE8 = 0x00000201, 108 | TYPE_IMMEDIATE16 = 0x00000202, 109 | TYPE_IMMEDIATE32 = 0x00000203, 110 | TYPE_IMMEDIATE64 = 0x00000204, 111 | TYPE_REL = 0x00000300, 112 | TYPE_REL8 = 0x00000301, 113 | TYPE_REL16 = 0x00000302, 114 | TYPE_REL32 = 0x00000303, 115 | TYPE_REL64 = 0x00000304, 116 | TYPE_EXPRESSION = 0x00000400, 117 | TYPE_EXPRESSION8 = 0x00000401, 118 | TYPE_EXPRESSION16 = 0x00000402, 119 | TYPE_EXPRESSION32 = 0x00000403, 120 | TYPE_EXPRESSION48 = 0x00000404, 121 | TYPE_EXPRESSION64 = 0x00000405, 122 | TYPE_EXPRESSION80 = 0x00000406, 123 | TYPE_EXPRESSION128 = 0x00000407, 124 | TYPE_ABSOLUTE = 0x00000500, 125 | TYPE_MASK = 0xffffff00 126 | }; 127 | 128 | public: 129 | enum DisplacementType { 130 | DISP_NONE, 131 | DISP_U8, 132 | DISP_U16, 133 | DISP_U32, 134 | DISP_S8, 135 | DISP_S16, 136 | DISP_S32 137 | }; 138 | 139 | public: 140 | struct absolute_t { 141 | uint16_t seg; 142 | uint32_t offset; 143 | }; 144 | 145 | struct expression_t { 146 | union { 147 | int8_t s_disp8; 148 | int16_t s_disp16; 149 | int32_t s_disp32; 150 | uint8_t u_disp8; 151 | uint16_t u_disp16; 152 | uint32_t u_disp32; 153 | }; 154 | 155 | DisplacementType displacement_type; 156 | Register base; 157 | Register index; 158 | uint8_t scale; 159 | }; 160 | 161 | public: 162 | int8_t sbyte() const { return u.sbyte; } 163 | int16_t sword() const { return u.sword; } 164 | int32_t sdword() const { return u.sdword; } 165 | int64_t sqword() const { return u.sqword; } 166 | uint8_t byte() const { return u.byte; } 167 | uint16_t word() const { return u.word; } 168 | uint32_t dword() const { return u.dword; } 169 | uint64_t qword() const { return u.qword; } 170 | Register reg() const { return u.reg; } 171 | 172 | const absolute_t absolute() const { return u.absolute; } 173 | const expression_t expression() const { return u.expression; } 174 | 175 | public: 176 | Type complete_type() const { return type_; } 177 | Type general_type() const; 178 | instruction_type *owner() const { return owner_; } 179 | bool valid() const { return type_ != TYPE_INVALID; } 180 | void swap(Operand &other); 181 | 182 | public: 183 | uint64_t relative_target() const; 184 | int32_t displacement() const; 185 | int64_t immediate() const; 186 | 187 | private: 188 | instruction_type *owner_; 189 | Type type_; 190 | 191 | union U { 192 | int8_t sbyte; 193 | int16_t sword; 194 | int32_t sdword; 195 | int64_t sqword; 196 | uint8_t byte; 197 | uint16_t word; 198 | uint32_t dword; 199 | uint64_t qword; 200 | Register reg; 201 | absolute_t absolute; 202 | expression_t expression; 203 | } u; 204 | }; 205 | 206 | } 207 | 208 | #include "Operand.tcc" 209 | 210 | #endif 211 | 212 | -------------------------------------------------------------------------------- /include/edisassm/OPTable_Other.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef OPTABLE_OTHER_20110314_TCC_ 20 | #define OPTABLE_OTHER_20110314_TCC_ 21 | 22 | namespace edisassm { 23 | 24 | template 25 | const typename Instruction::opcode_entry Instruction::Opcode_invalid = 26 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }; 27 | 28 | template 29 | const typename Instruction::opcode_entry Instruction::Opcodes_nop_pause_xchg[3] = { 30 | { "nop", &Instruction::decode0, OP_NOP, FLAG_NONE }, 31 | { "pause", &Instruction::decode0, OP_PAUSE, FLAG_SSE2 }, 32 | { "xchg", &Instruction::template decode2<&instruction_type::decode_rAX, &instruction_type::decode_rAX_NOREX>, OP_XCHG, FLAG_NONE }, 33 | }; 34 | 35 | template 36 | const typename Instruction::opcode_entry Instruction::Opcodes_cbw_cwde_cdqe[3] = { 37 | { "cbw", &Instruction::decode0, OP_CBW, FLAG_NONE }, 38 | { "cwde", &Instruction::decode0, OP_CWDE, FLAG_NONE }, 39 | { "cdqe", &Instruction::decode0, OP_CDQE, FLAG_NONE }, 40 | }; 41 | 42 | template 43 | const typename Instruction::opcode_entry Instruction::Opcodes_cwd_cdq_cqo[3] = { 44 | { "cwd", &Instruction::decode0, OP_CWD, FLAG_NONE }, 45 | { "cdq", &Instruction::decode0, OP_CDQ, FLAG_NONE }, 46 | { "cqo", &Instruction::decode0, OP_CQO, FLAG_NONE }, 47 | }; 48 | 49 | template 50 | const typename Instruction::opcode_entry Instruction::Opcodes_stosw_stosd_stosq[3] = { 51 | { "stosw", &Instruction::decode0, OP_STOS, FLAG_R_FLAGS }, 52 | { "stosd", &Instruction::decode0, OP_STOS, FLAG_R_FLAGS }, 53 | { "stosq", &Instruction::decode0, OP_STOS, FLAG_R_FLAGS }, 54 | }; 55 | 56 | template 57 | const typename Instruction::opcode_entry Instruction::Opcodes_lodsw_lodsd_lodsq[3] = { 58 | { "lodsw", &Instruction::decode0, OP_LODS, FLAG_R_FLAGS }, 59 | { "lodsd", &Instruction::decode0, OP_LODS, FLAG_R_FLAGS }, 60 | { "lodsq", &Instruction::decode0, OP_LODS, FLAG_R_FLAGS }, 61 | }; 62 | 63 | template 64 | const typename Instruction::opcode_entry Instruction::Opcodes_scasw_scasd_scasq[3] = { 65 | { "scasw", &Instruction::decode0, OP_SCAS, FLAG_RW_FLAGS }, 66 | { "scasd", &Instruction::decode0, OP_SCAS, FLAG_RW_FLAGS }, 67 | { "scasq", &Instruction::decode0, OP_SCAS, FLAG_RW_FLAGS }, 68 | }; 69 | 70 | template 71 | const typename Instruction::opcode_entry Instruction::Opcodes_iretw_iret_iretq[3] = { 72 | { "iretw", &Instruction::decode0, OP_IRET, FLAG_W_FLAGS | FLAG_STACK }, 73 | { "iret", &Instruction::decode0, OP_IRET, FLAG_W_FLAGS | FLAG_STACK }, 74 | { "iretq", &Instruction::decode0, OP_IRET, FLAG_W_FLAGS | FLAG_STACK }, 75 | }; 76 | 77 | template 78 | const typename Instruction::opcode_entry Instruction::Opcodes_movsw_movsd_movsq[3] = { 79 | { "movsw", &Instruction::decode0, OP_MOVS, FLAG_R_FLAGS }, 80 | { "movsd", &Instruction::decode0, OP_MOVS, FLAG_R_FLAGS }, 81 | { "movsq", &Instruction::decode0, OP_MOVS, FLAG_R_FLAGS }, 82 | }; 83 | 84 | template 85 | const typename Instruction::opcode_entry Instruction::Opcodes_popfw_popfd_popfq[3] = { 86 | { "popfw", &Instruction::decode0, OP_POPF, FLAG_STACK | FLAG_W_FLAGS }, 87 | { "popfd", &Instruction::decode0, OP_POPF, FLAG_STACK | FLAG_W_FLAGS }, 88 | { "popfq", &Instruction::decode0, OP_POPF, FLAG_STACK | FLAG_W_FLAGS }, 89 | }; 90 | 91 | template 92 | const typename Instruction::opcode_entry Instruction::Opcodes_pushfw_pushfd_pushfq[3] = { 93 | { "pushfw", &Instruction::decode0, OP_PUSHF, FLAG_STACK | FLAG_R_FLAGS }, 94 | { "pushfd", &Instruction::decode0, OP_PUSHF, FLAG_STACK | FLAG_R_FLAGS }, 95 | { "pushfq", &Instruction::decode0, OP_PUSHF, FLAG_STACK | FLAG_R_FLAGS }, 96 | }; 97 | 98 | template 99 | const typename Instruction::opcode_entry Instruction::Opcodes_invalid_cmpxchg8b_cmpxchg16b[3] = { 100 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 101 | { "cmpxchg8b", &Instruction::decode_Mo, OP_CMPXCHG8B, FLAG_W_FLAGS }, 102 | { "cmpxchg16b", &Instruction::decode_Mo, OP_CMPXCHG16B, FLAG_W_FLAGS }, 103 | }; 104 | 105 | template 106 | const typename Instruction::opcode_entry Instruction::Opcodes_insw_insd_invalid[3] = { 107 | { "insw", &Instruction::decode0, OP_INS, FLAG_R_FLAGS }, 108 | { "insd", &Instruction::decode0, OP_INS, FLAG_R_FLAGS }, 109 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 110 | }; 111 | 112 | template 113 | const typename Instruction::opcode_entry Instruction::Opcodes_outsw_outsd_invalid[3] = { 114 | { "outsw", &Instruction::decode0, OP_OUTS, FLAG_R_FLAGS }, 115 | { "outsd", &Instruction::decode0, OP_OUTS, FLAG_R_FLAGS }, 116 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 117 | }; 118 | 119 | template 120 | const typename Instruction::opcode_entry Instruction::Opcodes_cmpsw_cmpsd_cmpsq[3] = { 121 | { "cmpsw", &Instruction::decode0, OP_CMPS, FLAG_RW_FLAGS }, 122 | { "cmpsd", &Instruction::decode0, OP_CMPS, FLAG_RW_FLAGS }, 123 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 124 | }; 125 | 126 | template 127 | const typename Instruction::opcode_entry Instruction::Opcodes_pushaw_pushad_invalid[3] = { 128 | { "pushaw", &Instruction::decode0, OP_PUSHA, FLAG_32BIT_ONLY | FLAG_STACK }, // ia-32 only 129 | { "pushad", &Instruction::decode0, OP_PUSHA, FLAG_32BIT_ONLY | FLAG_STACK }, // ia-32 only 130 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 131 | }; 132 | 133 | template 134 | const typename Instruction::opcode_entry Instruction::Opcodes_popaw_popad_invalid[3] = { 135 | { "popaw", &Instruction::decode0, OP_POPA, FLAG_32BIT_ONLY | FLAG_STACK }, // ia-32 only 136 | { "popad", &Instruction::decode0, OP_POPA, FLAG_32BIT_ONLY | FLAG_STACK }, // ia-32 only 137 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 138 | }; 139 | 140 | } 141 | 142 | #endif 143 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /include/edisassm/Formatter.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef FORMATTER_TCC_ 20 | #define FORMATTER_TCC_ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | namespace edisassm { 29 | namespace { 30 | 31 | template 32 | size_t array_count(T (&)[N]) { 33 | return N; 34 | } 35 | 36 | //------------------------------------------------------------------------------ 37 | // Name: mnemonic_to_string 38 | //------------------------------------------------------------------------------ 39 | template 40 | std::string mnemonic_to_string(const Instruction &inst, const FormatOptions &options) { 41 | std::string s = inst.mnemonic(); 42 | if(options.capitalization == UpperCase) { 43 | std::transform(s.begin(), s.end(), s.begin(), std::ptr_fun(std::toupper)); 44 | } 45 | return s; 46 | } 47 | 48 | //------------------------------------------------------------------------------ 49 | // Name: is_small_num 50 | //------------------------------------------------------------------------------ 51 | template 52 | bool is_small_num(T value, const FormatOptions &options) { 53 | if(options.smallNumFormat == SmallNumAsDec) { 54 | return (value > -127 && value < 128); 55 | } else { 56 | return (value >= 0 && value < 9); 57 | } 58 | } 59 | 60 | //------------------------------------------------------------------------------ 61 | // Name: hex_string 62 | //------------------------------------------------------------------------------ 63 | template 64 | std::string hex_string(T value, const FormatOptions &options) { 65 | 66 | if(value == 0) { 67 | return "0"; 68 | } 69 | 70 | std::ostringstream ss; 71 | ss << "0x"; 72 | 73 | if(options.capitalization == UpperCase) { 74 | ss << std::uppercase; 75 | } 76 | 77 | ss << std::hex << std::setw(sizeof(T) * 2) << std::setfill('0') << static_cast(value); 78 | return ss.str(); 79 | } 80 | 81 | //------------------------------------------------------------------------------ 82 | // Name: format_absolute 83 | //------------------------------------------------------------------------------ 84 | template 85 | std::string format_absolute(const Operand &op, const FormatOptions &options) { 86 | std::ostringstream ss; 87 | 88 | if(options.capitalization == UpperCase) { 89 | ss << "FAR "; 90 | } else { 91 | ss << "far "; 92 | } 93 | 94 | ss << hex_string(op.absolute().seg, options) 95 | << ':' 96 | << hex_string(op.absolute().offset, options); 97 | 98 | return ss.str(); 99 | } 100 | 101 | //------------------------------------------------------------------------------ 102 | // Name: format_prefix 103 | //------------------------------------------------------------------------------ 104 | template 105 | std::string format_prefix(const Instruction &inst, const FormatOptions &options) { 106 | 107 | typedef Instruction I; 108 | 109 | std::string ret; 110 | if(options.capitalization == UpperCase) { 111 | if((inst.prefix() & I::PREFIX_LOCK) && !(inst.mandatory_prefix() & I::PREFIX_LOCK)) { 112 | 113 | // TODO: this is only legal for the memory dest versions of: 114 | // ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG, CMPXCH8B, (CMPXCH16B?) 115 | // DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD, XCHG 116 | 117 | ret = "LOCK "; 118 | 119 | } else if((inst.prefix() & I::PREFIX_REP) && !(inst.mandatory_prefix() & I::PREFIX_REP)) { 120 | if(inst.type() == I::OP_CMPS || inst.type() == I::OP_SCAS) { 121 | ret = "REPE "; 122 | } else { 123 | 124 | // TODO: this is only legal for: 125 | // INS, OUTS, MOVS, LODS and STOS 126 | 127 | ret = "REP "; 128 | } 129 | } else if((inst.prefix() & I::PREFIX_REPNE) && !(inst.mandatory_prefix() & I::PREFIX_REPNE)) { 130 | // TODO: this is only legal for: 131 | // CMPS and SCAS 132 | ret = "REPNE "; 133 | } 134 | } else { 135 | if((inst.prefix() & I::PREFIX_LOCK) && !(inst.mandatory_prefix() & I::PREFIX_LOCK)) { 136 | 137 | // TODO: this is only legal for the memory dest versions of: 138 | // ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG, CMPXCH8B, (CMPXCH16B?) 139 | // DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD, XCHG 140 | 141 | ret = "lock "; 142 | 143 | } else if((inst.prefix() & I::PREFIX_REP) && !(inst.mandatory_prefix() & I::PREFIX_REP)) { 144 | if(inst.type() == I::OP_CMPS || inst.type() == I::OP_SCAS) { 145 | ret = "repe "; 146 | } else { 147 | 148 | // TODO: this is only legal for: 149 | // INS, OUTS, MOVS, LODS and STOS 150 | 151 | ret = "rep "; 152 | } 153 | } else if((inst.prefix() & I::PREFIX_REPNE) && !(inst.mandatory_prefix() & I::PREFIX_REPNE)) { 154 | // TODO: this is only legal for: 155 | // CMPS and SCAS 156 | ret = "repne "; 157 | } 158 | } 159 | 160 | return ret; 161 | } 162 | 163 | //------------------------------------------------------------------------------ 164 | // Name: format_relative 165 | // Desc: 166 | //------------------------------------------------------------------------------ 167 | template 168 | std::string format_relative(const Operand &op, const FormatOptions &options) { 169 | return hex_string(static_cast(op.relative_target()), options); 170 | } 171 | 172 | //------------------------------------------------------------------------------ 173 | // Name: format_immediate 174 | //------------------------------------------------------------------------------ 175 | template 176 | std::string format_immediate(const Operand &op, const FormatOptions &options) { 177 | 178 | typedef Operand O; 179 | 180 | std::ostringstream ss; 181 | 182 | switch(op.complete_type()) { 183 | case O::TYPE_IMMEDIATE64: 184 | if(op.qword() < std::numeric_limits::max()) { 185 | // this will lead to a fall through, we can print smaller 186 | } else { 187 | if(is_small_num(op.sqword(), options)) { 188 | ss << op.sqword(); 189 | } else { 190 | ss << hex_string(op.sqword(), options); 191 | } 192 | break; 193 | } 194 | // FALL THROUGH 195 | case O::TYPE_IMMEDIATE32: 196 | if(op.dword() < std::numeric_limits::max()) { 197 | // this will lead to a fall through, we can print smaller 198 | } else { 199 | if(is_small_num(op.sdword(), options)) { 200 | ss << op.sdword(); 201 | } else { 202 | const int32_t i32 = op.sdword(); 203 | ss << hex_string(static_cast(i32), options); 204 | } 205 | break; 206 | } 207 | // FALL THROUGH 208 | case O::TYPE_IMMEDIATE16: 209 | if(op.word() < std::numeric_limits::max()) { 210 | // this will lead to a fall through, we can print smaller 211 | } else { 212 | if(is_small_num(op.sword(), options)) { 213 | ss << op.sword(); 214 | } else { 215 | const int16_t i16 = op.sword(); 216 | ss << hex_string(static_cast(i16), options); 217 | } 218 | break; 219 | } 220 | // FALL THROUGH 221 | case O::TYPE_IMMEDIATE8: 222 | if(is_small_num(op.byte(), options)) { 223 | ss << static_cast(op.sbyte()); 224 | } else { 225 | const int8_t i8 = op.byte(); 226 | ss << hex_string(static_cast(i8), options); 227 | } 228 | break; 229 | default: 230 | break; 231 | } 232 | 233 | return ss.str(); 234 | } 235 | 236 | } 237 | 238 | 239 | template 240 | std::string Formatter::to_string(const Instruction &inst) const { 241 | 242 | std::ostringstream ss; 243 | 244 | ss << format_prefix(inst, options_); 245 | ss << mnemonic_to_string(inst, options_); 246 | 247 | const std::size_t count = inst.operand_count(); 248 | if(count != 0) { 249 | ss << ' ' << to_string(inst.operands()[0]); 250 | for(std::size_t i = 1; i < count; ++i) { 251 | ss << ", " << to_string(inst.operands()[i]); 252 | } 253 | } 254 | 255 | return ss.str(); 256 | } 257 | 258 | 259 | template 260 | std::string Formatter::to_string(const Operand &op) const { 261 | typedef Operand O; 262 | 263 | switch(op.general_type()) { 264 | case O::TYPE_ABSOLUTE: return format_absolute (op, options_); 265 | case O::TYPE_EXPRESSION: return format_expression(op); 266 | case O::TYPE_IMMEDIATE: return format_immediate (op, options_); 267 | case O::TYPE_REGISTER: return format_register (op); 268 | case O::TYPE_REL: return format_relative (op, options_); 269 | default: 270 | return register_name(O::REG_INVALID); 271 | // is it better to throw, or return a string? 272 | //throw invalid_operand(owner_->size()); 273 | } 274 | } 275 | 276 | 277 | template 278 | std::string Formatter::to_byte_string(const Instruction &inst) const { 279 | 280 | std::ostringstream ss; 281 | const uint8_t *const ptr = inst.bytes(); 282 | const unsigned int size = inst.size(); 283 | 284 | if(size != 0) { 285 | if(options_.capitalization == UpperCase) { 286 | ss << std::hex << std::uppercase << std::setw(2) << std::setfill('0') << static_cast(ptr[0]); 287 | for(unsigned int i = 1; i < size; ++i) { 288 | ss << ' ' << std::uppercase << std::hex << std::setw(2) << std::setfill('0') << static_cast(ptr[i]); 289 | } 290 | } else { 291 | ss << std::hex << std::setw(2) << std::setfill('0') << static_cast(ptr[0]); 292 | for(unsigned int i = 1; i < size; ++i) { 293 | ss << ' ' << std::hex << std::setw(2) << std::setfill('0') << static_cast(ptr[i]); 294 | } 295 | } 296 | } 297 | 298 | return ss.str(); 299 | } 300 | 301 | 302 | template 303 | std::string Formatter::register_name(typename Operand::Register reg) const { 304 | static const char *const names_lower[] = { 305 | "", 306 | 307 | "rax", "rcx", "rdx", "rbx", 308 | "rsp", "rbp", "rsi", "rdi", 309 | "r8", "r9", "r10", "r11", 310 | "r12", "r13", "r14", "r15", 311 | 312 | "eax", "ecx", "edx", "ebx", 313 | "esp", "ebp", "esi", "edi", 314 | "r8d", "r9d", "r10d", "r11d", 315 | "r12d", "r13d", "r14d", "r15d", 316 | 317 | "ax", "cx", "dx", "bx", 318 | "sp", "bp", "si", "di", 319 | "r8w", "r9w", "r10w", "r11w", 320 | "r12w", "r13w", "r14w", "r15w", 321 | 322 | "al", "cl", "dl", "bl", 323 | "ah", "ch", "dh", "bh", 324 | "r8b", "r9b", "r10b", "r11b", 325 | "r12b", "r13b", "r14b", "r15b", 326 | "spl", "bpl", "sil", "dil", 327 | 328 | "es", "cs", "ss", "ds", 329 | "fs", "gs", "seg7", "seg8", 330 | 331 | "cr0", "cr1", "cr2", "cr3", 332 | "cr4", "cr5", "cr6", "cr7", 333 | "cr8", "cr9", "cr10", "cr11", 334 | "cr12", "cr13", "cr14", "cr15", 335 | 336 | "dr0", "dr1", "dr2", "dr3", 337 | "dr4", "dr5", "dr6", "dr7", 338 | "dr8", "dr9", "dr10", "dr11", 339 | "dr12", "dr13", "dr14", "dr15", 340 | 341 | "tr0", "tr1", "tr2", "tr3", 342 | "tr4", "tr5", "tr6", "tr7", 343 | 344 | "mm0", "mm1", "mm2", "mm3", 345 | "mm4", "mm5", "mm6", "mm7", 346 | 347 | "xmm0", "xmm1", "xmm2", "xmm3", 348 | "xmm4", "xmm5", "xmm6", "xmm7", 349 | "xmm8", "xmm9", "xmm10", "xmm11", 350 | "xmm12", "xmm13", "xmm14", "xmm15", 351 | 352 | "st", 353 | "st(0)", "st(1)", "st(2)", "st(3)", 354 | "st(4)", "st(5)", "st(6)", "st(7)", 355 | 356 | "rip", 357 | "eip", 358 | 359 | "(invalid)" 360 | }; 361 | 362 | static const char *const names_upper[] = { 363 | "", 364 | 365 | "RAX", "RCX", "RDX", "RBX", 366 | "RSP", "RBP", "RSI", "RDI", 367 | "R8", "R9", "R10", "R11", 368 | "R12", "R13", "R14", "R15", 369 | 370 | "EAX", "ECX", "EDX", "EBX", 371 | "ESP", "EBP", "ESI", "EDI", 372 | "R8D", "R9D", "R10D", "R11D", 373 | "R12D", "R13D", "R14D", "R15D", 374 | 375 | "AX", "CX", "DX", "BX", 376 | "SP", "BP", "SI", "DI", 377 | "R8W", "R9W", "R10W", "R11W", 378 | "R12W", "R13W", "R14W", "R15W", 379 | 380 | "AL", "CL", "DL", "BL", 381 | "AH", "CH", "DH", "BH", 382 | "R8B", "R9B", "R10B", "R11B", 383 | "R12B", "R13B", "R14B", "R15B", 384 | "SPL", "BPL", "SIL", "DIL", 385 | 386 | "ES", "CS", "SS", "DS", 387 | "FS", "GS", "SEG7", "SEG8", 388 | 389 | "CR0", "CR1", "CR2", "CR3", 390 | "CR4", "CR5", "CR6", "CR7", 391 | "CR8", "CR9", "CR10", "CR11", 392 | "CR12", "CR13", "CR14", "CR15", 393 | 394 | "DR0", "DR1", "DR2", "DR3", 395 | "DR4", "DR5", "DR6", "DR7", 396 | "DR8", "DR9", "DR10", "DR11", 397 | "DR12", "DR13", "DR14", "DR15", 398 | 399 | "TR0", "TR1", "TR2", "TR3", 400 | "TR4", "TR5", "TR6", "TR7", 401 | 402 | "MM0", "MM1", "MM2", "MM3", 403 | "MM4", "MM5", "MM6", "MM7", 404 | 405 | "XMM0", "XMM1", "XMM2", "XMM3", 406 | "XMM4", "XMM5", "XMM6", "XMM7", 407 | "XMM8", "XMM9", "XMM10", "XMM11", 408 | "XMM12", "XMM13", "XMM14", "XMM15", 409 | 410 | "ST", 411 | "ST(0)", "ST(1)", "ST(2)", "ST(3)", 412 | "ST(4)", "ST(5)", "ST(6)", "ST(7)", 413 | 414 | "RIP", 415 | "EIP", 416 | 417 | "(INVALID)" 418 | }; 419 | 420 | if(options_.capitalization == UpperCase) { 421 | assert(static_cast(reg) < array_count(names_upper)); 422 | return names_upper[reg]; 423 | } else { 424 | assert(static_cast(reg) < array_count(names_lower)); 425 | return names_lower[reg]; 426 | } 427 | } 428 | 429 | //------------------------------------------------------------------------------ 430 | // Name: format_expression 431 | //------------------------------------------------------------------------------ 432 | template 433 | std::string Formatter::format_expression(const Operand &op) const{ 434 | 435 | typedef Operand O; 436 | typedef Instruction I; 437 | 438 | std::ostringstream ss; 439 | 440 | const uint32_t prefix = op.owner()->prefix(); 441 | 442 | if(options_.capitalization == UpperCase) { 443 | static const char *expression_strings[] = { 444 | "", 445 | "BYTE PTR ", 446 | "WORD PTR ", 447 | "DWORD PTR ", 448 | "FWORD PTR ", 449 | "QWORD PTR ", 450 | "TBYTE PTR ", 451 | "XMMWORD PTR ", 452 | }; 453 | 454 | ss << expression_strings[op.complete_type() - O::TYPE_EXPRESSION]; 455 | 456 | if(prefix & I::PREFIX_CS) ss << "CS:"; 457 | else if(prefix & I::PREFIX_SS) ss << "SS:"; 458 | else if(prefix & I::PREFIX_DS) ss << "DS:"; 459 | else if(prefix & I::PREFIX_ES) ss << "ES:"; 460 | else if(prefix & I::PREFIX_FS) ss << "FS:"; 461 | else if(prefix & I::PREFIX_GS) ss << "GS:"; 462 | 463 | } else { 464 | static const char *expression_strings[] = { 465 | "", 466 | "byte ptr ", 467 | "word ptr ", 468 | "dword ptr ", 469 | "fword ptr ", 470 | "qword ptr ", 471 | "tbyte ptr ", 472 | "xmmword ptr ", 473 | }; 474 | 475 | 476 | ss << expression_strings[op.complete_type() - O::TYPE_EXPRESSION]; 477 | 478 | if(prefix & I::PREFIX_CS) ss << "cs:"; 479 | else if(prefix & I::PREFIX_SS) ss << "ss:"; 480 | else if(prefix & I::PREFIX_DS) ss << "ds:"; 481 | else if(prefix & I::PREFIX_ES) ss << "es:"; 482 | else if(prefix & I::PREFIX_FS) ss << "fs:"; 483 | else if(prefix & I::PREFIX_GS) ss << "gs:"; 484 | } 485 | 486 | bool only_disp = true; 487 | 488 | ss << '['; 489 | 490 | // the base, if any 491 | if(op.expression().base != O::REG_NULL) { 492 | ss << register_name(op.expression().base); 493 | only_disp = false; 494 | } 495 | 496 | // the index, if any 497 | if(op.expression().index != O::REG_NULL) { 498 | if(!only_disp) { 499 | ss << '+'; 500 | } 501 | ss << register_name(op.expression().index); 502 | only_disp = false; 503 | 504 | // the scale, if any 505 | if(op.expression().scale != 1) { 506 | ss << '*' << static_cast(op.expression().scale); 507 | } 508 | } 509 | 510 | 511 | // the displacement, if any 512 | switch(op.expression().displacement_type) { 513 | case O::DISP_U32: 514 | if(op.expression().u_disp32 <= std::numeric_limits::max()) { 515 | // this will lead to a fall through, we can print smaller 516 | } else { 517 | if(!only_disp) { 518 | ss << '+'; 519 | } 520 | ss << hex_string(op.expression().u_disp32, options_); 521 | break; 522 | } 523 | // FALL THROUGH 524 | case O::DISP_U16: 525 | if(op.expression().u_disp16 <= std::numeric_limits::max()) { 526 | // this will lead to a fall through, we can print smaller 527 | } else { 528 | if(!only_disp) { 529 | ss << '+'; 530 | } 531 | ss << hex_string(op.expression().u_disp16, options_); 532 | break; 533 | } 534 | // FALL THROUGH 535 | case O::DISP_U8: 536 | if(op.expression().u_disp8 != 0 || only_disp) { 537 | if(!only_disp) { 538 | ss << '+'; 539 | } 540 | ss << hex_string(op.expression().u_disp8, options_); 541 | } 542 | break; 543 | 544 | case O::DISP_S32: 545 | if(op.expression().s_disp32 <= std::numeric_limits::max() && op.expression().s_disp32 >= std::numeric_limits::min()) { 546 | // this will lead to a fall through, we can print smaller 547 | } else { 548 | if(only_disp) { 549 | // we only have a displacement, so we wanna display in hex since it is likely an address 550 | ss << hex_string(static_cast(op.expression().s_disp32), options_); 551 | } else { 552 | ss << '+'; 553 | ss << hex_string(static_cast(op.expression().s_disp32), options_); 554 | } 555 | break; 556 | } 557 | // FALL THROUGH 558 | case O::DISP_S16: 559 | if(op.expression().s_disp16 <= std::numeric_limits::max() && op.expression().s_disp16 >= std::numeric_limits::min()) { 560 | // this will lead to a fall through, we can print smaller 561 | } else { 562 | if(only_disp) { 563 | // we only have a displacement, so we wanna display in hex since it is likely an address 564 | ss << hex_string(static_cast(op.expression().s_disp16), options_); 565 | } else { 566 | ss << std::showpos << static_cast(op.expression().s_disp16); 567 | } 568 | break; 569 | } 570 | // FALL THROUGH 571 | case O::DISP_S8: 572 | if(op.expression().s_disp8 != 0 || only_disp) { 573 | if(only_disp) { 574 | // we only have a displacement, so we wanna display in hex since it is likely an address 575 | ss << hex_string(static_cast(op.expression().s_disp8), options_); 576 | } else { 577 | ss << std::showpos << static_cast(op.expression().s_disp8); 578 | } 579 | } 580 | break; 581 | 582 | default: 583 | break; 584 | } 585 | ss << ']'; 586 | 587 | return ss.str(); 588 | } 589 | 590 | //------------------------------------------------------------------------------ 591 | // Name: format_register 592 | //------------------------------------------------------------------------------ 593 | template 594 | std::string Formatter::format_register(const Operand &op) const{ 595 | return register_name(op.reg()); 596 | } 597 | 598 | } 599 | 600 | #endif 601 | -------------------------------------------------------------------------------- /include/edisassm/OPTable_1byte.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef OPTABLE_1BYTE_20080314_TCC_ 20 | #define OPTABLE_1BYTE_20080314_TCC_ 21 | 22 | namespace edisassm { 23 | 24 | template 25 | const typename Instruction::opcode_entry Instruction::Opcodes[0x100] = { 26 | 27 | /* 0x00 - 0x0f */ 28 | { "add", &Instruction::decode_Eb_Gb, OP_ADD, FLAG_W_FLAGS }, 29 | { "add", &Instruction::decode_Ev_Gv, OP_ADD, FLAG_W_FLAGS }, 30 | { "add", &Instruction::decode_Gb_Eb, OP_ADD, FLAG_W_FLAGS }, 31 | { "add", &Instruction::decode_Gv_Ev, OP_ADD, FLAG_W_FLAGS }, 32 | { "add", &Instruction::decode_AL_Ib, OP_ADD, FLAG_W_FLAGS }, 33 | { "add", &Instruction::decode_rAX_Iz, OP_ADD, FLAG_W_FLAGS }, 34 | { "push", &Instruction::decode_SegES, OP_PUSH, FLAG_32BIT_ONLY | FLAG_STACK }, // ia-32 only 35 | { "pop", &Instruction::decode_SegES, OP_POP, FLAG_32BIT_ONLY | FLAG_STACK }, // ia-32 only 36 | { "or", &Instruction::decode_Eb_Gb, OP_OR, FLAG_W_FLAGS }, 37 | { "or", &Instruction::decode_Ev_Gv, OP_OR, FLAG_W_FLAGS }, 38 | { "or", &Instruction::decode_Gb_Eb, OP_OR, FLAG_W_FLAGS }, 39 | { "or", &Instruction::decode_Gv_Ev, OP_OR, FLAG_W_FLAGS }, 40 | { "or", &Instruction::decode_AL_Ib, OP_OR, FLAG_W_FLAGS }, 41 | { "or", &Instruction::decode_rAX_Iz, OP_OR, FLAG_W_FLAGS }, 42 | { "push", &Instruction::decode_SegCS, OP_PUSH, FLAG_32BIT_ONLY | FLAG_STACK }, // ia-32 only 43 | { "2byte", &Instruction::decode_2byte, OP_2BYTE, FLAG_NONE }, 44 | 45 | /* 0x10 - 0x1f */ 46 | { "adc", &Instruction::decode_Eb_Gb, OP_ADC, FLAG_RW_FLAGS }, 47 | { "adc", &Instruction::decode_Ev_Gv, OP_ADC, FLAG_RW_FLAGS }, 48 | { "adc", &Instruction::decode_Gb_Eb, OP_ADC, FLAG_RW_FLAGS }, 49 | { "adc", &Instruction::decode_Gv_Ev, OP_ADC, FLAG_RW_FLAGS }, 50 | { "adc", &Instruction::decode_AL_Ib, OP_ADC, FLAG_RW_FLAGS }, 51 | { "adc", &Instruction::decode_rAX_Iz, OP_ADC, FLAG_RW_FLAGS }, 52 | { "push", &Instruction::decode_SegSS, OP_PUSH, FLAG_32BIT_ONLY | FLAG_STACK }, // ia-32 only 53 | { "pop", &Instruction::decode_SegSS, OP_POP, FLAG_32BIT_ONLY | FLAG_STACK }, // ia-32 only 54 | { "sbb", &Instruction::decode_Eb_Gb, OP_SBB, FLAG_RW_FLAGS }, 55 | { "sbb", &Instruction::decode_Ev_Gv, OP_SBB, FLAG_RW_FLAGS }, 56 | { "sbb", &Instruction::decode_Gb_Eb, OP_SBB, FLAG_RW_FLAGS }, 57 | { "sbb", &Instruction::decode_Gv_Ev, OP_SBB, FLAG_RW_FLAGS }, 58 | { "sbb", &Instruction::decode_AL_Ib, OP_SBB, FLAG_RW_FLAGS }, 59 | { "sbb", &Instruction::decode_rAX_Iz, OP_SBB, FLAG_RW_FLAGS }, 60 | { "push", &Instruction::decode_SegDS, OP_PUSH, FLAG_32BIT_ONLY | FLAG_STACK }, // ia-32 only 61 | { "pop", &Instruction::decode_SegDS, OP_POP, FLAG_32BIT_ONLY | FLAG_STACK }, // ia-32 only 62 | 63 | /* 0x20 - 0x2f */ 64 | { "and", &Instruction::decode_Eb_Gb, OP_AND, FLAG_W_FLAGS }, 65 | { "and", &Instruction::decode_Ev_Gv, OP_AND, FLAG_W_FLAGS }, 66 | { "and", &Instruction::decode_Gb_Eb, OP_AND, FLAG_W_FLAGS }, 67 | { "and", &Instruction::decode_Gv_Ev, OP_AND, FLAG_W_FLAGS }, 68 | { "and", &Instruction::decode_AL_Ib, OP_AND, FLAG_W_FLAGS }, 69 | { "and", &Instruction::decode_rAX_Iz, OP_AND, FLAG_W_FLAGS }, 70 | { "prefix es", &Instruction::decode_invalid, OP_PREFIX, FLAG_NONE }, 71 | { "daa", &Instruction::decode0, OP_DAA, FLAG_32BIT_ONLY | FLAG_RW_FLAGS }, // ia-32 only 72 | { "sub", &Instruction::decode_Eb_Gb, OP_SUB, FLAG_W_FLAGS }, 73 | { "sub", &Instruction::decode_Ev_Gv, OP_SUB, FLAG_W_FLAGS }, 74 | { "sub", &Instruction::decode_Gb_Eb, OP_SUB, FLAG_W_FLAGS }, 75 | { "sub", &Instruction::decode_Gv_Ev, OP_SUB, FLAG_W_FLAGS }, 76 | { "sub", &Instruction::decode_AL_Ib, OP_SUB, FLAG_W_FLAGS }, 77 | { "sub", &Instruction::decode_rAX_Iz, OP_SUB, FLAG_W_FLAGS }, 78 | { "prefix cs", &Instruction::decode_invalid, OP_PREFIX, FLAG_NONE }, 79 | { "das", &Instruction::decode0, OP_DAS, FLAG_32BIT_ONLY | FLAG_RW_FLAGS }, // ia-32 only 80 | 81 | /* 0x30 - 0x3f */ 82 | { "xor", &Instruction::decode_Eb_Gb, OP_XOR, FLAG_W_FLAGS }, 83 | { "xor", &Instruction::decode_Ev_Gv, OP_XOR, FLAG_W_FLAGS }, 84 | { "xor", &Instruction::decode_Gb_Eb, OP_XOR, FLAG_W_FLAGS }, 85 | { "xor", &Instruction::decode_Gv_Ev, OP_XOR, FLAG_W_FLAGS }, 86 | { "xor", &Instruction::decode_AL_Ib, OP_XOR, FLAG_W_FLAGS }, 87 | { "xor", &Instruction::decode_rAX_Iz, OP_XOR, FLAG_W_FLAGS }, 88 | { "prefix ss", &Instruction::decode_invalid, OP_PREFIX, FLAG_NONE }, 89 | { "aaa", &Instruction::decode0, OP_AAA, FLAG_32BIT_ONLY | FLAG_RW_FLAGS }, // ia-32 only 90 | { "cmp", &Instruction::decode_Eb_Gb, OP_CMP, FLAG_W_FLAGS }, 91 | { "cmp", &Instruction::decode_Ev_Gv, OP_CMP, FLAG_W_FLAGS }, 92 | { "cmp", &Instruction::decode_Gb_Eb, OP_CMP, FLAG_W_FLAGS }, 93 | { "cmp", &Instruction::decode_Gv_Ev, OP_CMP, FLAG_W_FLAGS }, 94 | { "cmp", &Instruction::decode_AL_Ib, OP_CMP, FLAG_W_FLAGS }, 95 | { "cmp", &Instruction::decode_rAX_Iz, OP_CMP, FLAG_W_FLAGS }, 96 | { "prefix ds", &Instruction::decode_invalid, OP_PREFIX, FLAG_NONE }, 97 | { "aas", &Instruction::decode0, OP_AAS, FLAG_32BIT_ONLY | FLAG_RW_FLAGS }, // ia-32 only 98 | 99 | /* 0x40 - 0x4f */ 100 | { "inc", &Instruction::decode_rAX, OP_INC, FLAG_32BIT_ONLY | FLAG_W_FLAGS }, // ia-32 only (REX byte) 101 | { "inc", &Instruction::decode_rCX, OP_INC, FLAG_32BIT_ONLY | FLAG_W_FLAGS }, // ia-32 only (REX byte) 102 | { "inc", &Instruction::decode_rDX, OP_INC, FLAG_32BIT_ONLY | FLAG_W_FLAGS }, // ia-32 only (REX byte) 103 | { "inc", &Instruction::decode_rBX, OP_INC, FLAG_32BIT_ONLY | FLAG_W_FLAGS }, // ia-32 only (REX byte) 104 | { "inc", &Instruction::decode_rSP, OP_INC, FLAG_32BIT_ONLY | FLAG_W_FLAGS }, // ia-32 only (REX byte) 105 | { "inc", &Instruction::decode_rBP, OP_INC, FLAG_32BIT_ONLY | FLAG_W_FLAGS }, // ia-32 only (REX byte) 106 | { "inc", &Instruction::decode_rSI, OP_INC, FLAG_32BIT_ONLY | FLAG_W_FLAGS }, // ia-32 only (REX byte) 107 | { "inc", &Instruction::decode_rDI, OP_INC, FLAG_32BIT_ONLY | FLAG_W_FLAGS }, // ia-32 only (REX byte) 108 | { "dec", &Instruction::decode_rAX, OP_DEC, FLAG_32BIT_ONLY | FLAG_W_FLAGS }, // ia-32 only (REX byte) 109 | { "dec", &Instruction::decode_rCX, OP_DEC, FLAG_32BIT_ONLY | FLAG_W_FLAGS }, // ia-32 only (REX byte) 110 | { "dec", &Instruction::decode_rDX, OP_DEC, FLAG_32BIT_ONLY | FLAG_W_FLAGS }, // ia-32 only (REX byte) 111 | { "dec", &Instruction::decode_rBX, OP_DEC, FLAG_32BIT_ONLY | FLAG_W_FLAGS }, // ia-32 only (REX byte) 112 | { "dec", &Instruction::decode_rSP, OP_DEC, FLAG_32BIT_ONLY | FLAG_W_FLAGS }, // ia-32 only (REX byte) 113 | { "dec", &Instruction::decode_rBP, OP_DEC, FLAG_32BIT_ONLY | FLAG_W_FLAGS }, // ia-32 only (REX byte) 114 | { "dec", &Instruction::decode_rSI, OP_DEC, FLAG_32BIT_ONLY | FLAG_W_FLAGS }, // ia-32 only (REX byte) 115 | { "dec", &Instruction::decode_rDI, OP_DEC, FLAG_32BIT_ONLY | FLAG_W_FLAGS }, // ia-32 only (REX byte) 116 | 117 | /* 0x50 - 0x5f */ 118 | { "push", &Instruction::decode_rAX, OP_PUSH, FLAG_STACK }, 119 | { "push", &Instruction::decode_rCX, OP_PUSH, FLAG_STACK }, 120 | { "push", &Instruction::decode_rDX, OP_PUSH, FLAG_STACK }, 121 | { "push", &Instruction::decode_rBX, OP_PUSH, FLAG_STACK }, 122 | { "push", &Instruction::decode_rSP, OP_PUSH, FLAG_STACK }, 123 | { "push", &Instruction::decode_rBP, OP_PUSH, FLAG_STACK }, 124 | { "push", &Instruction::decode_rSI, OP_PUSH, FLAG_STACK }, 125 | { "push", &Instruction::decode_rDI, OP_PUSH, FLAG_STACK }, 126 | { "pop", &Instruction::decode_rAX, OP_POP, FLAG_STACK }, 127 | { "pop", &Instruction::decode_rCX, OP_POP, FLAG_STACK }, 128 | { "pop", &Instruction::decode_rDX, OP_POP, FLAG_STACK }, 129 | { "pop", &Instruction::decode_rBX, OP_POP, FLAG_STACK }, 130 | { "pop", &Instruction::decode_rSP, OP_POP, FLAG_STACK }, 131 | { "pop", &Instruction::decode_rBP, OP_POP, FLAG_STACK }, 132 | { "pop", &Instruction::decode_rSI, OP_POP, FLAG_STACK }, 133 | { "pop", &Instruction::decode_rDI, OP_POP, FLAG_STACK }, 134 | 135 | /* 0x60 - 0x6f */ 136 | { "pushaw/pushad", &Instruction::decode_pushaw_pushad_invalid, OP_GROUP, FLAG_NONE }, 137 | { "popaw/popad", &Instruction::decode_popaw_popad_invalid, OP_GROUP, FLAG_NONE }, 138 | { "bound", &Instruction::decode_Gv_Ma, OP_BOUND, FLAG_32BIT_ONLY | FLAG_W_FLAGS }, // ia-32 only 139 | { "arpl", &Instruction::decode_Ew_Gw, OP_ARPL, FLAG_W_FLAGS }, // x86-64: movsxd Gv,Ev 140 | { "prefix fs", &Instruction::decode_invalid, OP_PREFIX, FLAG_NONE }, 141 | { "prefix gs", &Instruction::decode_invalid, OP_PREFIX, FLAG_NONE }, 142 | { "prefix data16", &Instruction::decode_invalid, OP_PREFIX, FLAG_NONE }, 143 | { "prefix addr16", &Instruction::decode_invalid, OP_PREFIX, FLAG_NONE }, 144 | { "push", &Instruction::decode_Ixz, OP_PUSH, FLAG_STACK }, 145 | { "imul", &Instruction::decode_Gv_Ev_Iz, OP_IMUL, FLAG_W_FLAGS }, 146 | { "push", &Instruction::decode_Ixb, OP_PUSH, FLAG_STACK }, 147 | { "imul", &Instruction::decode_Gv_Ev_Ib, OP_IMUL, FLAG_W_FLAGS }, 148 | { "insb", &Instruction::decode0, OP_INS, FLAG_R_FLAGS }, 149 | { "insw/insd", &Instruction::decode_insw_insd_invalid, OP_GROUP, FLAG_NONE }, 150 | { "outsb", &Instruction::decode0, OP_OUTS, FLAG_R_FLAGS }, 151 | { "outsw/outsd", &Instruction::decode_outsw_outsd_invalid, OP_GROUP, FLAG_NONE }, 152 | 153 | /* 0x70 - 0x7f */ 154 | { "jo", &Instruction::decode_Jb, OP_JCC, FLAG_R_FLAGS }, 155 | { "jno", &Instruction::decode_Jb, OP_JCC, FLAG_R_FLAGS }, 156 | { "jb", &Instruction::decode_Jb, OP_JCC, FLAG_R_FLAGS }, 157 | { "jnb", &Instruction::decode_Jb, OP_JCC, FLAG_R_FLAGS }, 158 | { "jz", &Instruction::decode_Jb, OP_JCC, FLAG_R_FLAGS }, 159 | { "jnz", &Instruction::decode_Jb, OP_JCC, FLAG_R_FLAGS }, 160 | { "jbe", &Instruction::decode_Jb, OP_JCC, FLAG_R_FLAGS }, 161 | { "jnbe", &Instruction::decode_Jb, OP_JCC, FLAG_R_FLAGS }, 162 | { "js", &Instruction::decode_Jb, OP_JCC, FLAG_R_FLAGS }, 163 | { "jns", &Instruction::decode_Jb, OP_JCC, FLAG_R_FLAGS }, 164 | { "jp", &Instruction::decode_Jb, OP_JCC, FLAG_R_FLAGS }, 165 | { "jnp", &Instruction::decode_Jb, OP_JCC, FLAG_R_FLAGS }, 166 | { "jl", &Instruction::decode_Jb, OP_JCC, FLAG_R_FLAGS }, 167 | { "jnl", &Instruction::decode_Jb, OP_JCC, FLAG_R_FLAGS }, 168 | { "jle", &Instruction::decode_Jb, OP_JCC, FLAG_R_FLAGS }, 169 | { "jnle", &Instruction::decode_Jb, OP_JCC, FLAG_R_FLAGS }, 170 | 171 | /* 0x80 - 0x8f */ 172 | { "group1", &Instruction::decode_group1, OP_GROUP, FLAG_NONE }, 173 | { "group1", &Instruction::decode_group1, OP_GROUP, FLAG_NONE }, 174 | { "group1", &Instruction::decode_group1, OP_GROUP, FLAG_NONE }, 175 | { "group1", &Instruction::decode_group1, OP_GROUP, FLAG_NONE }, 176 | { "test", &Instruction::decode_Eb_Gb, OP_TEST, FLAG_W_FLAGS }, 177 | { "test", &Instruction::decode_Ev_Gv, OP_TEST, FLAG_W_FLAGS }, 178 | { "xchg", &Instruction::decode_Gb_Eb, OP_XCHG, FLAG_NONE }, 179 | { "xchg", &Instruction::decode_Gv_Ev, OP_XCHG, FLAG_NONE }, 180 | { "mov", &Instruction::decode_Eb_Gb, OP_MOV, FLAG_NONE }, 181 | { "mov", &Instruction::decode_Ev_Gv, OP_MOV, FLAG_NONE }, 182 | { "mov", &Instruction::decode_Gb_Eb, OP_MOV, FLAG_NONE }, 183 | { "mov", &Instruction::decode_Gv_Ev, OP_MOV, FLAG_NONE }, 184 | { "mov", &Instruction::decode_Ev_Sw, OP_MOV, FLAG_NONE }, 185 | { "lea", &Instruction::decode_Gv_M, OP_LEA, FLAG_NONE }, 186 | { "mov", &Instruction::decode_Sw_Ew, OP_MOV, FLAG_NONE }, 187 | { "group10", &Instruction::decode_group10, OP_GROUP, FLAG_NONE }, 188 | 189 | /* 0x90 - 0x9f */ 190 | { "xchg", &Instruction::decode_rAX_rAX_NOREX, OP_XCHG, FLAG_NONE }, 191 | { "xchg", &Instruction::decode_rCX_rAX_NOREX, OP_XCHG, FLAG_NONE }, 192 | { "xchg", &Instruction::decode_rDX_rAX_NOREX, OP_XCHG, FLAG_NONE }, 193 | { "xchg", &Instruction::decode_rBX_rAX_NOREX, OP_XCHG, FLAG_NONE }, 194 | { "xchg", &Instruction::decode_rSP_rAX_NOREX, OP_XCHG, FLAG_NONE }, 195 | { "xchg", &Instruction::decode_rBP_rAX_NOREX, OP_XCHG, FLAG_NONE }, 196 | { "xchg", &Instruction::decode_rSI_rAX_NOREX, OP_XCHG, FLAG_NONE }, 197 | { "xchg", &Instruction::decode_rDI_rAX_NOREX, OP_XCHG, FLAG_NONE }, 198 | { "cbw/cwde/cdqe", &Instruction::decode_cbw_cwde_cdqe, OP_GROUP, FLAG_NONE }, 199 | { "cwd/cdq/cqo", &Instruction::decode_cwd_cdq_cqo, OP_GROUP, FLAG_NONE }, 200 | { "callf", &Instruction::decode_Ap, OP_CALL, FLAG_32BIT_ONLY | FLAG_STACK }, // ia-32 only 201 | { "wait", &Instruction::decode0, OP_WAIT, FLAG_NONE }, 202 | { "pushfw/pushfd/pushfq", &Instruction::decode_pushfw_pushfd_pushfq, OP_GROUP, FLAG_NONE }, 203 | { "popfw/popfd/popfq", &Instruction::decode_popfw_popfd_popfq, OP_GROUP, FLAG_NONE }, 204 | { "sahf", &Instruction::decode0, OP_SAHF, FLAG_NONE }, 205 | { "lahf", &Instruction::decode0, OP_LAHF, FLAG_R_FLAGS }, 206 | 207 | /* 0xa0 - 0xaf */ 208 | { "mov", &Instruction::decode_AL_Ob, OP_MOV, FLAG_NONE }, 209 | { "mov", &Instruction::decode_rAX_Ov, OP_MOV, FLAG_NONE }, 210 | { "mov", &Instruction::decode_Ob_AL, OP_MOV, FLAG_NONE }, 211 | { "mov", &Instruction::decode_Ov_rAX, OP_MOV, FLAG_NONE }, 212 | { "movsb", &Instruction::decode0, OP_MOVS, FLAG_R_FLAGS }, 213 | { "movsw/movsd/movsq", &Instruction::decode_movsw_movsd_movsq, OP_GROUP, FLAG_NONE }, 214 | { "cmpsb", &Instruction::decode0, OP_CMPS, FLAG_RW_FLAGS }, 215 | { "cmpsw/cmpsd/cmpsq", &Instruction::decode_cmpsw_cmpsd_cmpsq, OP_GROUP, FLAG_NONE }, 216 | { "test", &Instruction::decode_AL_Ib, OP_TEST, FLAG_R_FLAGS }, 217 | { "test", &Instruction::decode_rAX_Iz, OP_TEST, FLAG_R_FLAGS }, 218 | { "stosb", &Instruction::decode0, OP_STOS, FLAG_R_FLAGS }, 219 | { "stosw/stosd/stosq", &Instruction::decode_stosw_stosd_stosq, OP_GROUP, FLAG_NONE }, 220 | { "lodsb", &Instruction::decode0, OP_LODS, FLAG_R_FLAGS }, 221 | { "lodsw/lodsd/lodsq", &Instruction::decode_lodsw_lodsd_lodsq, OP_GROUP, FLAG_NONE }, 222 | { "scasb", &Instruction::decode0, OP_SCAS, FLAG_RW_FLAGS }, 223 | { "scasw/scasd/scasq", &Instruction::decode_scasw_scasd_scasq, OP_GROUP, FLAG_NONE }, 224 | 225 | /* 0xb0 - 0xbf */ 226 | { "mov", &Instruction::decode_AL_Ib, OP_MOV, FLAG_NONE }, 227 | { "mov", &Instruction::decode_CL_Ib, OP_MOV, FLAG_NONE }, 228 | { "mov", &Instruction::decode_DL_Ib, OP_MOV, FLAG_NONE }, 229 | { "mov", &Instruction::decode_BL_Ib, OP_MOV, FLAG_NONE }, 230 | { "mov", &Instruction::decode_AH_Ib, OP_MOV, FLAG_NONE }, 231 | { "mov", &Instruction::decode_CH_Ib, OP_MOV, FLAG_NONE }, 232 | { "mov", &Instruction::decode_DH_Ib, OP_MOV, FLAG_NONE }, 233 | { "mov", &Instruction::decode_BH_Ib, OP_MOV, FLAG_NONE }, 234 | { "mov", &Instruction::decode_rAX_Iv, OP_MOV, FLAG_NONE }, 235 | { "mov", &Instruction::decode_rCX_Iv, OP_MOV, FLAG_NONE }, 236 | { "mov", &Instruction::decode_rDX_Iv, OP_MOV, FLAG_NONE }, 237 | { "mov", &Instruction::decode_rBX_Iv, OP_MOV, FLAG_NONE }, 238 | { "mov", &Instruction::decode_rSP_Iv, OP_MOV, FLAG_NONE }, 239 | { "mov", &Instruction::decode_rBP_Iv, OP_MOV, FLAG_NONE }, 240 | { "mov", &Instruction::decode_rSI_Iv, OP_MOV, FLAG_NONE }, 241 | { "mov", &Instruction::decode_rDI_Iv, OP_MOV, FLAG_NONE }, 242 | 243 | /* 0xc0 - 0xcf */ 244 | { "group2", &Instruction::decode_group2, OP_GROUP, FLAG_NONE }, 245 | { "group2", &Instruction::decode_group2, OP_GROUP, FLAG_NONE }, 246 | { "ret", &Instruction::decode_Iw, OP_RET, FLAG_STACK }, 247 | { "ret", &Instruction::decode0, OP_RET, FLAG_STACK }, 248 | { "les", &Instruction::decode_Gz_Mp, OP_LES, FLAG_32BIT_ONLY }, // ia-32 only 249 | { "lds", &Instruction::decode_Gz_Mp, OP_LDS, FLAG_32BIT_ONLY }, // ia-32 only 250 | { "group12", &Instruction::decode_group12, OP_GROUP, FLAG_NONE }, 251 | { "group12", &Instruction::decode_group12, OP_GROUP, FLAG_NONE }, 252 | { "enter", &Instruction::decode_Iw_Ib, OP_ENTER, FLAG_STACK }, 253 | { "leave", &Instruction::decode0, OP_LEAVE, FLAG_STACK }, 254 | { "retf", &Instruction::decode_Iw, OP_RETF, FLAG_STACK }, 255 | { "retf", &Instruction::decode0, OP_RETF, FLAG_STACK }, 256 | { "int3", &Instruction::decode0, OP_INT3, FLAG_W_FLAGS }, 257 | { "int", &Instruction::decode_Ib, OP_INT, FLAG_W_FLAGS }, 258 | { "into", &Instruction::decode0, OP_INTO, FLAG_RW_FLAGS | FLAG_32BIT_ONLY }, // ia-32 only 259 | { "iretw/iret/iretq", &Instruction::decode_iretw_iret_iretq, OP_GROUP, FLAG_NONE }, 260 | 261 | /* 0xd0 - 0xdf */ 262 | { "group2", &Instruction::decode_group2D, OP_GROUP, FLAG_NONE }, 263 | { "group2", &Instruction::decode_group2D, OP_GROUP, FLAG_NONE }, 264 | { "group2", &Instruction::decode_group2D, OP_GROUP, FLAG_NONE }, 265 | { "group2", &Instruction::decode_group2D, OP_GROUP, FLAG_NONE }, 266 | { "aam", &Instruction::decode_Ib, OP_AAM, FLAG_32BIT_ONLY | FLAG_W_FLAGS }, // ia-32 only 267 | { "aad", &Instruction::decode_Ib, OP_AAD, FLAG_32BIT_ONLY | FLAG_W_FLAGS }, // ia-32 only 268 | { "salc", &Instruction::decode0, OP_SALC, FLAG_UNDOCUMENTED | FLAG_R_FLAGS }, 269 | { "xlat", &Instruction::decode0, OP_XLAT, FLAG_NONE }, 270 | { "esc0", &Instruction::decode_x87, OP_FPU, FLAG_NONE }, 271 | { "esc1", &Instruction::decode_x87, OP_FPU, FLAG_NONE }, 272 | { "esc2", &Instruction::decode_x87, OP_FPU, FLAG_NONE }, 273 | { "esc3", &Instruction::decode_x87, OP_FPU, FLAG_NONE }, 274 | { "esc4", &Instruction::decode_x87, OP_FPU, FLAG_NONE }, 275 | { "esc5", &Instruction::decode_x87, OP_FPU, FLAG_NONE }, 276 | { "esc6", &Instruction::decode_x87, OP_FPU, FLAG_NONE }, 277 | { "esc7", &Instruction::decode_x87, OP_FPU, FLAG_NONE }, 278 | 279 | /* 0xe0 - 0xef */ 280 | { "loopne", &Instruction::decode_Jb, OP_LOOPNE, FLAG_R_FLAGS }, 281 | { "loope", &Instruction::decode_Jb, OP_LOOPE, FLAG_R_FLAGS }, 282 | { "loop", &Instruction::decode_Jb, OP_LOOP, FLAG_R_FLAGS }, 283 | { "jcxz/jecxz/jrcxz", &Instruction::decode_jcxz_jecxz_jrcxz, OP_GROUP, FLAG_NONE }, 284 | { "in", &Instruction::decode_AL_Ib, OP_IN, FLAG_NONE }, 285 | { "in", &Instruction::decode_eAX_Ib, OP_IN, FLAG_NONE }, 286 | { "out", &Instruction::decode_Ib_AL, OP_OUT, FLAG_NONE }, 287 | { "out", &Instruction::decode_Ib_eAX, OP_OUT, FLAG_NONE }, 288 | { "call", &Instruction::decode_Jz, OP_CALL, FLAG_STACK }, 289 | { "jmp", &Instruction::decode_Jz, OP_JMP, FLAG_NONE }, 290 | { "jmp", &Instruction::decode_Ap, OP_JMP, FLAG_32BIT_ONLY }, // ia-32 only 291 | { "jmp", &Instruction::decode_Jb, OP_JMP, FLAG_NONE }, 292 | { "in", &Instruction::decode_AL_DX, OP_IN, FLAG_NONE }, 293 | { "in", &Instruction::decode_eAX_DX, OP_IN, FLAG_NONE }, 294 | { "out", &Instruction::decode_DX_AL, OP_OUT, FLAG_NONE }, 295 | { "out", &Instruction::decode_DX_eAX, OP_OUT, FLAG_NONE }, 296 | 297 | /* 0xf0 - 0xff */ 298 | { "prefix lock", &Instruction::decode_invalid, OP_PREFIX, FLAG_NONE }, 299 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 300 | { "prefix repne", &Instruction::decode_invalid, OP_PREFIX, FLAG_NONE }, 301 | { "prefix rep", &Instruction::decode_invalid, OP_PREFIX, FLAG_NONE }, 302 | { "hlt", &Instruction::decode0, OP_HLT, FLAG_RING0 }, 303 | { "cmc", &Instruction::decode0, OP_CMC, FLAG_RW_FLAGS }, 304 | { "group3", &Instruction::decode_group3, OP_GROUP, FLAG_NONE }, 305 | { "group3", &Instruction::decode_group3, OP_GROUP, FLAG_NONE }, 306 | { "clc", &Instruction::decode0, OP_CLC, FLAG_W_FLAGS }, 307 | { "stc", &Instruction::decode0, OP_STC, FLAG_W_FLAGS }, 308 | { "cli", &Instruction::decode0, OP_CLI, FLAG_W_FLAGS }, 309 | { "sti", &Instruction::decode0, OP_STI, FLAG_W_FLAGS }, 310 | { "cld", &Instruction::decode0, OP_CLD, FLAG_W_FLAGS }, 311 | { "std", &Instruction::decode0, OP_STD, FLAG_W_FLAGS }, 312 | { "group4", &Instruction::decode_group4, OP_GROUP, FLAG_NONE }, 313 | { "group5", &Instruction::decode_group5, OP_GROUP, FLAG_NONE }, 314 | }; 315 | 316 | } 317 | 318 | #endif 319 | -------------------------------------------------------------------------------- /include/edisassm/OPTable_3byte.tcc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef OPTABLE_3BYTE_20080314_TCC_ 20 | #define OPTABLE_3BYTE_20080314_TCC_ 21 | 22 | namespace edisassm { 23 | 24 | template 25 | const typename Instruction::opcode_entry Instruction::Opcodes_3Byte_38_NA[0x100] = { 26 | 27 | /* 0x0f 0x38 0x00 - 0x0f 0x38 0x0f */ 28 | { "pshufb", &Instruction::decode_Pq_Qq, OP_PSHUFB, FLAG_SSSE3 }, 29 | { "phaddw", &Instruction::decode_Pq_Qq, OP_PHADDW, FLAG_SSSE3 }, 30 | { "phaddd", &Instruction::decode_Pq_Qq, OP_PHADDD, FLAG_SSSE3 }, 31 | { "phaddsw", &Instruction::decode_Pq_Qq, OP_PHADDSW, FLAG_SSSE3 }, 32 | { "pmaddubsw", &Instruction::decode_Pq_Qq, OP_PMADDUBSW, FLAG_SSSE3 }, 33 | { "phsubw", &Instruction::decode_Pq_Qq, OP_PHSUBW, FLAG_SSSE3 }, 34 | { "phsubd", &Instruction::decode_Pq_Qq, OP_PHSUBD, FLAG_SSSE3 }, 35 | { "phsubsw", &Instruction::decode_Pq_Qq, OP_PHSUBSW, FLAG_SSSE3 }, 36 | { "psignb", &Instruction::decode_Pq_Qq, OP_PSIGNB, FLAG_SSSE3 }, 37 | { "psignw", &Instruction::decode_Pq_Qq, OP_PSIGNW, FLAG_SSSE3 }, 38 | { "psignd", &Instruction::decode_Pq_Qq, OP_PSIGND, FLAG_SSSE3 }, 39 | { "pmulhrsw", &Instruction::decode_Pq_Qq, OP_PMULHRSW, FLAG_SSSE3 }, 40 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 41 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 42 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 43 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 44 | 45 | /* 0x0f 0x38 0x10 - 0x0f 0x38 0x1f */ 46 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 47 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 48 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 49 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 50 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 51 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 52 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 53 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 54 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 55 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 56 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 57 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 58 | { "pabsb", &Instruction::decode_Pq_Qq, OP_PABSB, FLAG_SSSE3 }, 59 | { "pabsw", &Instruction::decode_Pq_Qq, OP_PABSW, FLAG_SSSE3 }, 60 | { "pabsd", &Instruction::decode_Pq_Qq, OP_PABSD, FLAG_SSSE3 }, 61 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 62 | 63 | /* 0x0f 0x38 0x20 - 0x0f 0x38 0x2f */ 64 | INVALID_BLOCK, 65 | 66 | /* 0x0f 0x38 0x30 - 0x0f 0x38 0x3f */ 67 | INVALID_BLOCK, 68 | 69 | /* 0x0f 0x38 0x40 - 0x0f 0x38 0x4f */ 70 | INVALID_BLOCK, 71 | 72 | /* 0x0f 0x38 0x50 - 0x0f 0x38 0x5f */ 73 | INVALID_BLOCK, 74 | 75 | /* 0x0f 0x38 0x60 - 0x0f 0x38 0x6f */ 76 | INVALID_BLOCK, 77 | 78 | /* 0x0f 0x38 0x70 - 0x0f 0x38 0x7f */ 79 | INVALID_BLOCK, 80 | 81 | /* 0x0f 0x38 0x80 - 0x0f 0x38 0x8f */ 82 | INVALID_BLOCK, 83 | 84 | /* 0x0f 0x38 0x90 - 0x0f 0x38 0x9f */ 85 | INVALID_BLOCK, 86 | 87 | /* 0x0f 0x38 0xa0 - 0x0f 0x38 0xaf */ 88 | INVALID_BLOCK, 89 | 90 | /* 0x0f 0x38 0xb0 - 0x0f 0x38 0xbf */ 91 | INVALID_BLOCK, 92 | 93 | /* 0x0f 0x38 0xc0 - 0x0f 0x38 0xcf */ 94 | INVALID_BLOCK, 95 | 96 | /* 0x0f 0x38 0xd0 - 0x0f 0x38 0xdf */ 97 | INVALID_BLOCK, 98 | 99 | /* 0x0f 0x38 0xe0 - 0x0f 0x38 0xef */ 100 | INVALID_BLOCK, 101 | 102 | /* 0x0f 0x38 0xf0 - 0x0f 0x38 0xff */ 103 | { "movbe", &Instruction::decode_Gv_Mv, OP_MOVBE, FLAG_NONE }, 104 | { "movbe", &Instruction::decode_Mv_Gv, OP_MOVBE, FLAG_NONE }, 105 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 106 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 107 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 108 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 109 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 110 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 111 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 112 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 113 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 114 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 115 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 116 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 117 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 118 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 119 | }; 120 | 121 | template 122 | const typename Instruction::opcode_entry Instruction::Opcodes_3Byte_38_F2[0x100] = { 123 | 124 | /* 0x0f 0x38 0x00 - 0x0f 0x38 0x0f */ 125 | { "pshufb", &Instruction::decode_Pq_Qq, OP_PSHUFB, FLAG_SSSE3 }, 126 | { "phaddw", &Instruction::decode_Pq_Qq, OP_PHADDW, FLAG_SSSE3 }, 127 | { "phaddd", &Instruction::decode_Pq_Qq, OP_PHADDD, FLAG_SSSE3 }, 128 | { "phaddsw", &Instruction::decode_Pq_Qq, OP_PHADDSW, FLAG_SSSE3 }, 129 | { "pmaddubsw", &Instruction::decode_Pq_Qq, OP_PMADDUBSW, FLAG_SSSE3 }, 130 | { "phsubw", &Instruction::decode_Pq_Qq, OP_PHSUBW, FLAG_SSSE3 }, 131 | { "phsubd", &Instruction::decode_Pq_Qq, OP_PHSUBD, FLAG_SSSE3 }, 132 | { "phsubsw", &Instruction::decode_Pq_Qq, OP_PHSUBSW, FLAG_SSSE3 }, 133 | { "psignb", &Instruction::decode_Pq_Qq, OP_PSIGNB, FLAG_SSSE3 }, 134 | { "psignw", &Instruction::decode_Pq_Qq, OP_PSIGNW, FLAG_SSSE3 }, 135 | { "psignd", &Instruction::decode_Pq_Qq, OP_PSIGND, FLAG_SSSE3 }, 136 | { "pmulhrsw", &Instruction::decode_Pq_Qq, OP_PMULHRSW, FLAG_SSSE3 }, 137 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 138 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 139 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 140 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 141 | 142 | /* 0x0f 0x38 0x10 - 0x0f 0x38 0x1f */ 143 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 144 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 145 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 146 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 147 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 148 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 149 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 150 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 151 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 152 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 153 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 154 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 155 | { "pabsb", &Instruction::decode_Pq_Qq, OP_PABSB, FLAG_SSSE3 }, 156 | { "pabsw", &Instruction::decode_Pq_Qq, OP_PABSW, FLAG_SSSE3 }, 157 | { "pabsd", &Instruction::decode_Pq_Qq, OP_PABSD, FLAG_SSSE3 }, 158 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 159 | 160 | /* 0x0f 0x38 0x20 - 0x0f 0x38 0x2f */ 161 | INVALID_BLOCK, 162 | 163 | /* 0x0f 0x38 0x30 - 0x0f 0x38 0x3f */ 164 | INVALID_BLOCK, 165 | 166 | /* 0x0f 0x38 0x40 - 0x0f 0x38 0x4f */ 167 | INVALID_BLOCK, 168 | 169 | /* 0x0f 0x38 0x50 - 0x0f 0x38 0x5f */ 170 | INVALID_BLOCK, 171 | 172 | /* 0x0f 0x38 0x60 - 0x0f 0x38 0x6f */ 173 | INVALID_BLOCK, 174 | 175 | /* 0x0f 0x38 0x70 - 0x0f 0x38 0x7f */ 176 | INVALID_BLOCK, 177 | 178 | /* 0x0f 0x38 0x80 - 0x0f 0x38 0x8f */ 179 | INVALID_BLOCK, 180 | 181 | /* 0x0f 0x38 0x90 - 0x0f 0x38 0x9f */ 182 | INVALID_BLOCK, 183 | 184 | /* 0x0f 0x38 0xa0 - 0x0f 0x38 0xaf */ 185 | INVALID_BLOCK, 186 | 187 | /* 0x0f 0x38 0xb0 - 0x0f 0x38 0xbf */ 188 | INVALID_BLOCK, 189 | 190 | /* 0x0f 0x38 0xc0 - 0x0f 0x38 0xcf */ 191 | INVALID_BLOCK, 192 | 193 | /* 0x0f 0x38 0xd0 - 0x0f 0x38 0xdf */ 194 | INVALID_BLOCK, 195 | 196 | /* 0x0f 0x38 0xe0 - 0x0f 0x38 0xef */ 197 | INVALID_BLOCK, 198 | 199 | /* 0x0f 0x38 0xf0 - 0x0f 0x38 0xff */ 200 | { "crc32", &Instruction::decode_Gq_Eb, OP_CRC32, FLAG_SSE4_2 }, 201 | { "crc32", &Instruction::decode_Gq_Eq, OP_CRC32, FLAG_SSE4_2 }, 202 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 203 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 204 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 205 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 206 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 207 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 208 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 209 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 210 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 211 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 212 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 213 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 214 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 215 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 216 | }; 217 | 218 | template 219 | const typename Instruction::opcode_entry Instruction::Opcodes_3Byte_38_66[0x100] = { 220 | 221 | /* 0x0f 0x38 0x00 - 0x0f 0x38 0x0f */ 222 | { "pshufb", &Instruction::decode_Vo_Wo, OP_PSHUFB, FLAG_SSSE3 }, 223 | { "phaddw", &Instruction::decode_Vo_Wo, OP_PHADDW, FLAG_SSSE3 }, 224 | { "phaddd", &Instruction::decode_Vo_Wo, OP_PHADDD, FLAG_SSSE3 }, 225 | { "phaddsw", &Instruction::decode_Vo_Wo, OP_PHADDSW, FLAG_SSSE3 }, 226 | { "pmaddubsw", &Instruction::decode_Vo_Wo, OP_PMADDUBSW, FLAG_SSSE3 }, 227 | { "phsubw", &Instruction::decode_Vo_Wo, OP_PHSUBW, FLAG_SSSE3 }, 228 | { "phsubd", &Instruction::decode_Vo_Wo, OP_PHSUBD, FLAG_SSSE3 }, 229 | { "phsubsw", &Instruction::decode_Vo_Wo, OP_PHSUBSW, FLAG_SSSE3 }, 230 | { "psignb", &Instruction::decode_Vo_Wo, OP_PSIGNB, FLAG_SSSE3 }, 231 | { "psignw", &Instruction::decode_Vo_Wo, OP_PSIGNW, FLAG_SSSE3 }, 232 | { "psignd", &Instruction::decode_Vo_Wo, OP_PSIGND, FLAG_SSSE3 }, 233 | { "pmulhrsw", &Instruction::decode_Vo_Wo, OP_PMULHRSW, FLAG_SSSE3 }, 234 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 235 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 236 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 237 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 238 | 239 | /* 0x0f 0x38 0x10 - 0x0f 0x38 0x1f */ 240 | { "pblendvb", &Instruction::decode_Vo_Wo, OP_PBLENDVB, FLAG_SSE4_1 }, 241 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 242 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 243 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 244 | { "blendvps", &Instruction::decode_Vo_Wo, OP_BLENDVPS, FLAG_SSE4_1 }, 245 | { "blendvpd", &Instruction::decode_Vo_Wo, OP_BLENDVPD, FLAG_SSE4_1 }, 246 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 247 | { "ptest", &Instruction::decode_Vo_Wo, OP_PTEST, FLAG_SSE4_1 }, 248 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 249 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 250 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 251 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 252 | { "pabsb", &Instruction::decode_Vo_Wo, OP_PABSB, FLAG_SSSE3 }, 253 | { "pabsw", &Instruction::decode_Vo_Wo, OP_PABSW, FLAG_SSSE3 }, 254 | { "pabsd", &Instruction::decode_Vo_Wo, OP_PABSD, FLAG_SSSE3 }, 255 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 256 | 257 | /* 0x0f 0x38 0x20 - 0x0f 0x38 0x2f */ 258 | { "pmovsxbw", &Instruction::decode_Vo_Uo_Mq, OP_PMOVSXBW, FLAG_SSE4_1 }, 259 | { "pmovsxbd", &Instruction::decode_Vo_Uo_Md, OP_PMOVSXBD, FLAG_SSE4_1 }, 260 | { "pmovsxbq", &Instruction::decode_Vo_Uo_Mw, OP_PMOVSXBQ, FLAG_SSE4_1 }, 261 | { "pmovsxwd", &Instruction::decode_Vo_Uo_Mq, OP_PMOVSXWD, FLAG_SSE4_1 }, 262 | { "pmovsxwq", &Instruction::decode_Vo_Uo_Md, OP_PMOVSXWQ, FLAG_SSE4_1 }, 263 | { "pmovsxdq", &Instruction::decode_Vo_Uo_Mq, OP_PMOVSXDQ, FLAG_SSE4_1 }, 264 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 265 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 266 | { "pmuldq", &Instruction::decode_Vo_Wo, OP_PMULDQ, FLAG_SSE4_1 }, 267 | { "pcmpeqq", &Instruction::decode_Vo_Wo, OP_PCMPEQQ, FLAG_SSE4_1 }, 268 | { "movntdqa", &Instruction::decode_Vo_Mo, OP_MOVNTDQA, FLAG_SSE4_1 }, 269 | { "packusdw", &Instruction::decode_Vo_Wo, OP_PACKUSDW, FLAG_SSE4_1 }, 270 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 271 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 272 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 273 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 274 | 275 | /* 0x0f 0x38 0x30 - 0x0f 0x38 0x3f */ 276 | { "pmovzxbw", &Instruction::decode_Vo_Uo_Mq, OP_PMOVZXBW, FLAG_SSE4_1 }, 277 | { "pmovzxbd", &Instruction::decode_Vo_Uo_Md, OP_PMOVZXBD, FLAG_SSE4_1 }, 278 | { "pmovzxbq", &Instruction::decode_Vo_Uo_Mw, OP_PMOVZXBQ, FLAG_SSE4_1 }, 279 | { "pmovzxwd", &Instruction::decode_Vo_Uo_Mq, OP_PMOVZXWD, FLAG_SSE4_1 }, 280 | { "pmovzxwq", &Instruction::decode_Vo_Uo_Md, OP_PMOVZXWQ, FLAG_SSE4_1 }, 281 | { "pmovzxdq", &Instruction::decode_Vo_Uo_Mq, OP_PMOVZXDQ, FLAG_SSE4_1 }, 282 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 283 | { "pcmpgtq", &Instruction::decode_Vo_Wo, OP_PCMPGTQ, FLAG_SSE4_2 }, 284 | { "pminsb", &Instruction::decode_Vo_Wo, OP_PMINSB, FLAG_SSE4_1 }, 285 | { "pminsd", &Instruction::decode_Vo_Wo, OP_PMINSD, FLAG_SSE4_1 }, 286 | { "pminuw", &Instruction::decode_Vo_Wo, OP_PMINUW, FLAG_SSE4_1 }, 287 | { "pminud", &Instruction::decode_Vo_Wo, OP_PMINUD, FLAG_SSE4_1 }, 288 | { "pmaxsb", &Instruction::decode_Vo_Wo, OP_PMAXSB, FLAG_SSE4_1 }, 289 | { "pmaxsd", &Instruction::decode_Vo_Wo, OP_PMAXSD, FLAG_SSE4_1 }, 290 | { "pmaxuw", &Instruction::decode_Vo_Wo, OP_PMAXUW, FLAG_SSE4_1 }, 291 | { "pmaxud", &Instruction::decode_Vo_Wo, OP_PMAXUD, FLAG_SSE4_1 }, 292 | 293 | /* 0x0f 0x38 0x40 - 0x0f 0x38 0x4f */ 294 | { "pmulld", &Instruction::decode_Vo_Wo, OP_PMULLD, FLAG_SSE4_1 }, 295 | { "phminposuw", &Instruction::decode_Vo_Wo, OP_PHMINPOSUW, FLAG_SSE4_1 }, 296 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 297 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 298 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 299 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 300 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 301 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 302 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 303 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 304 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 305 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 306 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 307 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 308 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 309 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 310 | 311 | /* 0x0f 0x38 0x50 - 0x0f 0x38 0x5f */ 312 | INVALID_BLOCK, 313 | 314 | /* 0x0f 0x38 0x60 - 0x0f 0x38 0x6f */ 315 | INVALID_BLOCK, 316 | 317 | /* 0x0f 0x38 0x70 - 0x0f 0x38 0x7f */ 318 | INVALID_BLOCK, 319 | 320 | /* 0x0f 0x38 0x80 - 0x0f 0x38 0x8f */ 321 | { "nvept", &Instruction::decode_Gd_Mo, OP_NVEPT, FLAG_NONE }, // x86-64: nvept Gq, Mo 322 | { "nvvpid", &Instruction::decode_Gd_Mo, OP_NVVPID, FLAG_NONE }, // x86-64: nvvpid Gq, Mo 323 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 324 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 325 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 326 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 327 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 328 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 329 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 330 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 331 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 332 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 333 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 334 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 335 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 336 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 337 | 338 | /* 0x0f 0x38 0x90 - 0x0f 0x38 0x9f */ 339 | INVALID_BLOCK, 340 | 341 | /* 0x0f 0x38 0xa0 - 0x0f 0x38 0xaf */ 342 | INVALID_BLOCK, 343 | 344 | /* 0x0f 0x38 0xb0 - 0x0f 0x38 0xbf */ 345 | INVALID_BLOCK, 346 | 347 | /* 0x0f 0x38 0xc0 - 0x0f 0x38 0xcf */ 348 | INVALID_BLOCK, 349 | 350 | /* 0x0f 0x38 0xd0 - 0x0f 0x38 0xdf */ 351 | INVALID_BLOCK, 352 | 353 | /* 0x0f 0x38 0xe0 - 0x0f 0x38 0xef */ 354 | INVALID_BLOCK, 355 | 356 | /* 0x0f 0x38 0xf0 - 0x0f 0x38 0xff */ 357 | { "movbe", &Instruction::decode_Gv_Mv, OP_MOVBE, FLAG_NONE }, 358 | { "movbe", &Instruction::decode_Mv_Gv, OP_MOVBE, FLAG_NONE }, 359 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 360 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 361 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 362 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 363 | { "adcx", &Instruction::decode_Gy_Ey, OP_ADCX, FLAG_RW_FLAGS }, 364 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 365 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 366 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 367 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 368 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 369 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 370 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 371 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 372 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 373 | }; 374 | 375 | template 376 | const typename Instruction::opcode_entry Instruction::Opcodes_3Byte_3A_66[0x100] = { 377 | /* 0x0f 0x3a 0x00 - 0x0f 0x3a 0x0f */ 378 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 379 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 380 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 381 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 382 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 383 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 384 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 385 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 386 | { "roundps", &Instruction::decode_Vo_Wo_Ib, OP_ROUNDPS, FLAG_SSE4_1 }, 387 | { "roundpd", &Instruction::decode_Vo_Wo_Ib, OP_ROUNDPD, FLAG_SSE4_1 }, 388 | { "roundss", &Instruction::decode_Vo_Wo_Ib, OP_ROUNDSS, FLAG_SSE4_1 }, 389 | { "roundsd", &Instruction::decode_Vo_Wo_Ib, OP_ROUNDSD, FLAG_SSE4_1 }, 390 | { "blendps", &Instruction::decode_Vo_Wo_Ib, OP_BLENDPS, FLAG_SSE4_1 }, 391 | { "blendpd", &Instruction::decode_Vo_Wo_Ib, OP_BLENDPD, FLAG_SSE4_1 }, 392 | { "pblendw", &Instruction::decode_Vo_Wo_Ib, OP_PBLENDW, FLAG_SSE4_1 }, 393 | { "palignr", &Instruction::decode_Vo_Wo_Ib, OP_PALIGNR, FLAG_SSSE3 }, 394 | 395 | /* 0x0f 0x3a 0x10 - 0x0f 0x3a 0x1f */ 396 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 397 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 398 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 399 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 400 | { "pextrb", &Instruction::decode_Rd_Mb_Vo_Ib, OP_PEXTRB, FLAG_SSE4_1 }, 401 | { "pextrw", &Instruction::decode_Rd_Mw_Vo_Ib, OP_PEXTRW, FLAG_SSE | FLAG_SSE4_1 }, 402 | { "pextrd", &Instruction::decode_Ed_Vo_Ib, OP_PEXTRD, FLAG_NONE }, // x86-64: pextrq Eq, Vo, Ib 403 | { "extractps", &Instruction::decode_Ed_Vo_Ib, OP_EXTRACTPS, FLAG_SSE4_1 }, // x86-64: extractps Ev, Vo, Ib 404 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 405 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 406 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 407 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 408 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 409 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 410 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 411 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 412 | 413 | /* 0x0f 0x3a 0x20 - 0x0f 0x3a 0x2f */ 414 | { "pinsrb", &Instruction::decode_Vo_Mb_Ib, OP_PINSRB, FLAG_SSE4_1 }, 415 | { "insertps", &Instruction::decode_Vo_Md_Ib, OP_INSERTPS, FLAG_SSE4_1 }, 416 | { "pinsrd", &Instruction::decode_Vo_Ed_Ib, OP_PINSRD, FLAG_NONE }, // x86-64: pinsrq Vo, Eq, Ib 417 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 418 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 419 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 420 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 421 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 422 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 423 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 424 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 425 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 426 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 427 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 428 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 429 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 430 | 431 | /* 0x0f 0x3a 0x30 - 0x0f 0x3a 0x3f */ 432 | INVALID_BLOCK, 433 | 434 | /* 0x0f 0x3a 0x40 - 0x0f 0x3a 0x4f */ 435 | { "dpps", &Instruction::decode_Vo_Wo_Ib, OP_DPPS, FLAG_SSE4_1 }, 436 | { "dppd", &Instruction::decode_Vo_Wo_Ib, OP_DPPD, FLAG_SSE4_1 }, 437 | { "mpsadbw", &Instruction::decode_Vo_Wo_Ib, OP_MPSADBW, FLAG_SSE4_1 }, 438 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 439 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 440 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 441 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 442 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 443 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 444 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 445 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 446 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 447 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 448 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 449 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 450 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 451 | 452 | /* 0x0f 0x3a 0x50 - 0x0f 0x3a 0x5f */ 453 | INVALID_BLOCK, 454 | 455 | /* 0x0f 0x3a 0x60 - 0x0f 0x3a 0x6f */ 456 | { "pcmpestrm", &Instruction::decode_Vo_Wo_Ib, OP_PCMPESTRM, FLAG_SSE4_2 | FLAG_W_FLAGS }, 457 | { "pcmpestri", &Instruction::decode_Vo_Wo_Ib, OP_PCMPESTRI, FLAG_SSE4_2 | FLAG_W_FLAGS }, 458 | { "pcmpistrm", &Instruction::decode_Vo_Wo_Ib, OP_PCMPISTRM, FLAG_SSE4_2 | FLAG_W_FLAGS }, 459 | { "pcmpistri", &Instruction::decode_Vo_Wo_Ib, OP_PCMPISTRI, FLAG_SSE4_2 | FLAG_W_FLAGS }, 460 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 461 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 462 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 463 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 464 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 465 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 466 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 467 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 468 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 469 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 470 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 471 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 472 | 473 | /* 0x0f 0x3a 0x70 - 0x0f 0x3a 0x7f */ 474 | INVALID_BLOCK, 475 | 476 | /* 0x0f 0x3a 0x80 - 0x0f 0x3a 0x8f */ 477 | INVALID_BLOCK, 478 | 479 | /* 0x0f 0x3a 0x90 - 0x0f 0x3a 0x9f */ 480 | INVALID_BLOCK, 481 | 482 | /* 0x0f 0x3a 0xa0 - 0x0f 0x3a 0xaf */ 483 | INVALID_BLOCK, 484 | 485 | /* 0x0f 0x3a 0xb0 - 0x0f 0x3a 0xbf */ 486 | INVALID_BLOCK, 487 | 488 | /* 0x0f 0x3a 0xc0 - 0x0f 0x3a 0xcf */ 489 | INVALID_BLOCK, 490 | 491 | /* 0x0f 0x3a 0xd0 - 0x0f 0x3a 0xdf */ 492 | INVALID_BLOCK, 493 | 494 | /* 0x0f 0x3a 0xe0 - 0x0f 0x3a 0xef */ 495 | INVALID_BLOCK, 496 | 497 | /* 0x0f 0x3a 0xf0 - 0x0f 0x3a 0xff */ 498 | INVALID_BLOCK 499 | }; 500 | 501 | template 502 | const typename Instruction::opcode_entry Instruction::Opcodes_3Byte_3A_NA[0x100] = { 503 | /* 0x0f 0x3a 0x00 - 0x0f 0x3a 0x0f */ 504 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 505 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 506 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 507 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 508 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 509 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 510 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 511 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 512 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 513 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 514 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 515 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 516 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 517 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 518 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE }, 519 | { "palignr", &Instruction::decode_Pq_Qq_Ib, OP_PALIGNR, FLAG_SSSE3 }, 520 | 521 | /* 0x0f 0x3a 0x10 - 0x0f 0x3a 0x1f */ 522 | INVALID_BLOCK, 523 | 524 | /* 0x0f 0x3a 0x20 - 0x0f 0x3a 0x2f */ 525 | INVALID_BLOCK, 526 | 527 | /* 0x0f 0x3a 0x30 - 0x0f 0x3a 0x3f */ 528 | INVALID_BLOCK, 529 | 530 | /* 0x0f 0x3a 0x40 - 0x0f 0x3a 0x4f */ 531 | INVALID_BLOCK, 532 | 533 | /* 0x0f 0x3a 0x50 - 0x0f 0x3a 0x5f */ 534 | INVALID_BLOCK, 535 | 536 | /* 0x0f 0x3a 0x60 - 0x0f 0x3a 0x6f */ 537 | INVALID_BLOCK, 538 | 539 | /* 0x0f 0x3a 0x70 - 0x0f 0x3a 0x7f */ 540 | INVALID_BLOCK, 541 | 542 | /* 0x0f 0x3a 0x80 - 0x0f 0x3a 0x8f */ 543 | INVALID_BLOCK, 544 | 545 | /* 0x0f 0x3a 0x90 - 0x0f 0x3a 0x9f */ 546 | INVALID_BLOCK, 547 | 548 | /* 0x0f 0x3a 0xa0 - 0x0f 0x3a 0xaf */ 549 | INVALID_BLOCK, 550 | 551 | /* 0x0f 0x3a 0xb0 - 0x0f 0x3a 0xbf */ 552 | INVALID_BLOCK, 553 | 554 | /* 0x0f 0x3a 0xc0 - 0x0f 0x3a 0xcf */ 555 | INVALID_BLOCK, 556 | 557 | /* 0x0f 0x3a 0xd0 - 0x0f 0x3a 0xdf */ 558 | INVALID_BLOCK, 559 | 560 | /* 0x0f 0x3a 0xe0 - 0x0f 0x3a 0xef */ 561 | INVALID_BLOCK, 562 | 563 | /* 0x0f 0x3a 0xf0 - 0x0f 0x3a 0xff */ 564 | INVALID_BLOCK 565 | }; 566 | 567 | } 568 | 569 | #endif 570 | -------------------------------------------------------------------------------- /include/edisassm/Instruction.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 - 2015 Evan Teran 3 | evan.teran@gmail.com 4 | 5 | This program is free software: you can redistribute it and/or modify 6 | it under the terms of the GNU General Public License as published by 7 | the Free Software Foundation, either version 2 of the License, or 8 | (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program. If not, see . 17 | */ 18 | 19 | #ifndef INSTRUCTION_20070427_H_ 20 | #define INSTRUCTION_20070427_H_ 21 | 22 | #include "ModRM.h" 23 | #include "Model.h" 24 | #include "Operand.h" 25 | #include "edisassm_exception.h" 26 | #include 27 | #include 28 | #include 29 | 30 | #ifdef QT_CORE_LIB 31 | #include 32 | #ifdef QT_PLUGIN 33 | #define EDB_EXPORT Q_DECL_IMPORT 34 | #else 35 | #define EDB_EXPORT Q_DECL_EXPORT 36 | #endif 37 | #else 38 | #define EDB_EXPORT 39 | #endif 40 | 41 | #ifndef INVALID_BLOCK 42 | #define INVALID_BLOCK \ 43 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE },\ 44 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE },\ 45 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE },\ 46 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE },\ 47 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE },\ 48 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE },\ 49 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE },\ 50 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE },\ 51 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE },\ 52 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE },\ 53 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE },\ 54 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE },\ 55 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE },\ 56 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE },\ 57 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE },\ 58 | { "invalid", &Instruction::decode_invalid, OP_INVALID, FLAG_NONE } 59 | #endif 60 | 61 | namespace edisassm { 62 | 63 | namespace { 64 | struct modrm_32 { static const int value = 32; }; 65 | struct modrm_64 { static const int value = 64; }; 66 | } 67 | 68 | template 69 | class EDB_EXPORT Instruction { 70 | template 71 | friend bool operator==(const Instruction &lhs, const Instruction &rhs); 72 | 73 | template 74 | friend bool operator!=(const Instruction &lhs, const Instruction &rhs); 75 | 76 | private: 77 | class stream_base { 78 | public: 79 | virtual ~stream_base() {} 80 | virtual uint8_t next() = 0; 81 | virtual uint8_t peek() const = 0; 82 | virtual bool empty() const = 0; 83 | virtual stream_base *clone() const = 0; 84 | }; 85 | 86 | template 87 | class stream_iterator : public stream_base { 88 | public: 89 | stream_iterator(In first, In last) : first_(first), last_(last) { 90 | } 91 | 92 | private: 93 | stream_iterator(const stream_iterator &) = delete; 94 | stream_iterator &operator=(const stream_iterator &) = delete; 95 | 96 | public: 97 | virtual uint8_t next() { return *first_++; } 98 | virtual uint8_t peek() const { return *first_; } 99 | virtual bool empty() const { return first_ == last_; } 100 | virtual stream_base *clone() const { return new stream_iterator(first_, last_); } 101 | 102 | private: 103 | In first_; 104 | In last_; 105 | }; 106 | 107 | public: 108 | static const int MAX_OPERANDS = M::MAX_OPERANDS; 109 | static const int MAX_SIZE = M::MAX_SIZE; 110 | static const int BITS = M::BITS; 111 | 112 | public: 113 | typedef Operand operand_type; 114 | typedef Instruction instruction_type; 115 | 116 | public: 117 | typedef void (instruction_type::*decoder_t)(); 118 | 119 | public: 120 | template 121 | Instruction(In first, In last, uint64_t rva, const std::nothrow_t&) throw() : 122 | byte_stream_(new stream_iterator(first, last)), byte_index_(0), byte1_(0x00), byte2_(0x00), byte3_(0x00), 123 | modrm_byte_(0x00), sib_byte_(0x00), rex_byte_(0x00), rva_(rva), 124 | opcode_(&Opcode_invalid), prefix_(0x00000000), mandatory_prefix_(0x00000000), 125 | operand_count_(0), modrm_size_(0), sib_size_(0), disp_size_(0), prefix_size_(0), 126 | immediate_size_(0), rex_size_(0) { 127 | 128 | try { 129 | disassemble(); 130 | } catch(const invalid_instruction &) { 131 | opcode_ = &Opcode_invalid; 132 | //throw; 133 | } 134 | } 135 | 136 | 137 | template 138 | Instruction(In first, In last, uint64_t rva) : 139 | byte_stream_(new stream_iterator(first, last)), byte_index_(0), byte1_(0x00), byte2_(0x00), byte3_(0x00), 140 | modrm_byte_(0x00), sib_byte_(0x00), rex_byte_(0x00), rva_(rva), 141 | opcode_(&Opcode_invalid), prefix_(0x00000000), mandatory_prefix_(0x00000000), 142 | operand_count_(0), modrm_size_(0), sib_size_(0), disp_size_(0), prefix_size_(0), 143 | immediate_size_(0), rex_size_(0) { 144 | 145 | disassemble(); 146 | } 147 | 148 | ~Instruction(); 149 | 150 | public: 151 | Instruction(const Instruction &); 152 | Instruction &operator=(const Instruction &); 153 | 154 | public: 155 | void swap(Instruction &other); 156 | 157 | private: 158 | void disassemble(); 159 | 160 | public: 161 | enum Flags { 162 | FLAG_NONE = 0x00000000, 163 | FLAG_R_FLAGS = 0x00000001, 164 | FLAG_W_FLAGS = 0x00000002, 165 | FLAG_RW_FLAGS = (FLAG_R_FLAGS | FLAG_W_FLAGS), 166 | FLAG_STACK = 0x00000004, 167 | FLAG_RING0 = 0x00000008, 168 | FLAG_UNDOCUMENTED = 0x00000010, 169 | FLAG_AMD = 0x00000020, 170 | FLAG_INTEL = 0x00000040, 171 | FLAG_32BIT_ONLY = 0x00000080, 172 | FLAG_64BIT_ONLY = 0x00000100, 173 | FLAG_FPU = 0x00000200, 174 | FLAG_286_ONLY = 0x00000400, 175 | FLAG_MMX = 0x00000800, 176 | FLAG_SSE = 0x00001000, 177 | FLAG_SSE2 = 0x00002000, 178 | FLAG_SSE3 = 0x00004000, 179 | FLAG_SSSE3 = 0x00008000, 180 | FLAG_SSE4 = 0x00010000, 181 | FLAG_SSE4a = 0x00020000, 182 | FLAG_SSE4_1 = 0x00040000, 183 | FLAG_SSE4_2 = 0x00080000, 184 | FLAG_PENTIUM_PRO = 0x00100000, 185 | FLAG_VMX = 0x00200000 186 | }; 187 | 188 | enum Prefix { 189 | PREFIX_NONE = 0x00000000, 190 | PREFIX_LOCK = 0x00000001, 191 | PREFIX_REPNE = 0x00000002, 192 | PREFIX_REP = 0x00000004, 193 | 194 | PREFIX_CS = 0x00000100, 195 | PREFIX_SS = 0x00000200, 196 | PREFIX_DS = 0x00000400, 197 | PREFIX_ES = 0x00000800, 198 | PREFIX_FS = 0x00001000, 199 | PREFIX_GS = 0x00002000, 200 | PREFIX_BRANCH_NOT_TAKEN = 0x00004000, 201 | PREFIX_BRANCH_TAKEN = 0x00008000, 202 | 203 | PREFIX_OPERAND = 0x00010000, 204 | 205 | PREFIX_ADDRESS = 0x01000000 206 | }; 207 | 208 | enum Type { 209 | // invalid 210 | OP_INVALID = 0x00000000, 211 | 212 | // data transfer 213 | OP_MOV, 214 | OP_CMOVCC, 215 | OP_XCHG, 216 | OP_BSWAP, 217 | OP_XADD, 218 | OP_CMPXCHG, 219 | OP_PUSH, 220 | OP_PUSHA, 221 | OP_POP, 222 | OP_POPA, 223 | OP_CWD, 224 | OP_CDQ, 225 | OP_CQO, 226 | OP_CDQE, 227 | OP_CBW, 228 | OP_CWDE, 229 | OP_MOVSX, 230 | OP_MOVZX, 231 | OP_MOVSXD, 232 | OP_MOVBE, 233 | 234 | // arithmetic 235 | OP_AAA, 236 | OP_AAD, 237 | OP_AAM, 238 | OP_AAS, 239 | OP_ADC, 240 | OP_ADCX, 241 | OP_ADD, 242 | OP_CMP, 243 | OP_DAA, 244 | OP_DAS, 245 | OP_DEC, 246 | OP_DIV, 247 | OP_IDIV, 248 | OP_IMUL, 249 | OP_INC, 250 | OP_MUL, 251 | OP_NEG, 252 | OP_SALC, 253 | OP_SBB, 254 | OP_SUB, 255 | 256 | // logic 257 | OP_AND, 258 | OP_OR, 259 | OP_XOR, 260 | OP_NOT, 261 | 262 | // shift/rotate 263 | OP_SAR, 264 | OP_SAL, 265 | OP_SHR, 266 | OP_SHL, 267 | OP_SHRD, 268 | OP_SHLD, 269 | OP_ROR, 270 | OP_ROL, 271 | OP_RCR, 272 | OP_RCL, 273 | 274 | // bit/byte 275 | OP_BT, 276 | OP_BTS, 277 | OP_BTR, 278 | OP_BTC, 279 | OP_BSF, 280 | OP_BSR, 281 | OP_SETCC, 282 | OP_TEST, 283 | 284 | // control flow 285 | OP_JMP, 286 | OP_JCC, 287 | OP_LOOP, 288 | OP_LOOPE, 289 | OP_LOOPNE, 290 | OP_CALL, 291 | OP_RET, 292 | OP_RETF, 293 | OP_IRET, 294 | OP_INT, 295 | OP_INT3, 296 | OP_INTO, 297 | OP_BOUND, 298 | OP_ENTER, 299 | OP_LEAVE, 300 | 301 | // string 302 | OP_MOVS, 303 | OP_CMPS, 304 | OP_CMPSW, 305 | OP_SCAS, 306 | OP_LODS, 307 | OP_STOS, 308 | 309 | // I/O 310 | OP_IN, 311 | OP_OUT, 312 | OP_INS, 313 | OP_OUTS, 314 | 315 | // flag control 316 | OP_STC, 317 | OP_CLC, 318 | OP_CMC, 319 | OP_CLD, 320 | OP_STD, 321 | OP_LAHF, 322 | OP_SAHF, 323 | OP_PUSHF, 324 | OP_POPF, 325 | OP_STI, 326 | OP_CLI, 327 | 328 | // segment manipulation 329 | OP_LDS, 330 | OP_LES, 331 | OP_LFS, 332 | OP_LGS, 333 | OP_LSS, 334 | OP_SWAPGS, 335 | 336 | // misc 337 | OP_PEXTRQ, 338 | OP_PINSRQ, 339 | OP_LEA, 340 | OP_NOP, 341 | OP_UD, 342 | OP_UD2, 343 | OP_XLAT, 344 | OP_CPUID, 345 | OP_CRC32, 346 | OP_XSAVE, 347 | OP_XRSTOR, 348 | OP_GETSEC, 349 | OP_PBLENDVB, 350 | OP_BLENDVPS, 351 | OP_BLENDVPD, 352 | OP_PTEST, 353 | OP_PMOVSXBW, 354 | OP_PMOVSXBD, 355 | OP_PMOVSXBQ, 356 | OP_PMOVSXWD, 357 | OP_PMOVSXWQ, 358 | OP_PMOVSXDQ, 359 | OP_PMULDQ, 360 | OP_PCMPEQQ, 361 | OP_MOVNTDQA, 362 | OP_PACKUSDW, 363 | OP_PMOVZXBW, 364 | OP_PMOVZXBD, 365 | OP_PMOVZXBQ, 366 | OP_PMOVZXWD, 367 | OP_PMOVZXWQ, 368 | OP_PMOVZXDQ, 369 | OP_PCMPGTQ, 370 | OP_PMINSB, 371 | OP_PMINSD, 372 | OP_PMINUW, 373 | OP_PMINUD, 374 | OP_PMAXSB, 375 | OP_PMAXSD, 376 | OP_PMAXUW, 377 | OP_PMAXUD, 378 | OP_PMULLD, 379 | OP_PHMINPOSUW, 380 | OP_NVEPT, 381 | OP_NVVPID, 382 | OP_ROUNDPS, 383 | OP_ROUNDPD, 384 | OP_ROUNDSS, 385 | OP_ROUNDSD, 386 | OP_BLENDPS, 387 | OP_BLENDPD, 388 | OP_PBLENDW, 389 | OP_PEXTRB, 390 | OP_PEXTRD, 391 | OP_EXTRACTPS, 392 | OP_PINSRB, 393 | OP_INSERTPS, 394 | OP_PINSRD, 395 | OP_DPPS, 396 | OP_DPPD, 397 | OP_MPSADBW, 398 | OP_PCMPESTRM, 399 | OP_PCMPESTRI, 400 | OP_PCMPISTRM, 401 | OP_PCMPISTRI, 402 | 403 | // misc 404 | OP_CMPXCHG8B, 405 | OP_CMPXCHG16B, 406 | 407 | 408 | // VM 409 | OP_VMCALL, 410 | OP_VMCLEAR, 411 | OP_VMLAUNCH, 412 | OP_VMPTRLD, 413 | OP_VMPTRST, 414 | OP_VMRESUME, 415 | OP_VMXOFF, 416 | OP_VMXON, 417 | OP_VMREAD, 418 | OP_VMWRITE, 419 | OP_XGETBV, 420 | OP_XSETBV, 421 | 422 | // system 423 | OP_LGDT, 424 | OP_SGDT, 425 | OP_LLDT, 426 | OP_SLDT, 427 | OP_LTR, 428 | OP_STR, 429 | OP_LIDT, 430 | OP_SIDT, 431 | OP_LMSW, 432 | OP_SMSW, 433 | OP_CLTS, 434 | OP_ARPL, 435 | OP_LAR, 436 | OP_LSL, 437 | OP_VERR, 438 | OP_VERW, 439 | OP_INVD, 440 | OP_WBINVD, 441 | OP_INVLPG, 442 | OP_HLT, 443 | OP_RSM, 444 | OP_RDMSR, 445 | OP_WRMSR, 446 | OP_RDPMC, 447 | OP_RDTSC, 448 | OP_SYSENTER, 449 | OP_SYSEXIT, 450 | OP_SYSCALL, 451 | OP_SYSRET, 452 | 453 | // MMX 454 | OP_EMMS, 455 | OP_MOVD, 456 | OP_MOVQ, 457 | OP_PABSD, // intel says this is both MMX and SSSE3! 458 | OP_PACKSSDW, 459 | OP_PACKSSWB, 460 | OP_PACKUSWB, 461 | OP_PADDB, 462 | OP_PADDD, 463 | OP_PADDSB, 464 | OP_PADDSW, 465 | OP_PADDUSB, 466 | OP_PADDUSW, 467 | OP_PADDW, 468 | OP_PAND, 469 | OP_PANDN, 470 | OP_PCMPEQB, 471 | OP_PCMPEQD, 472 | OP_PCMPEQW, 473 | OP_PCMPGTB, 474 | OP_PCMPGTD, 475 | OP_PCMPGTW, 476 | OP_PMADDWD, 477 | OP_PMULHW, 478 | OP_PMULLW, 479 | OP_POR, 480 | OP_PSLLD, 481 | OP_PSLLQ, 482 | OP_PSLLW, 483 | OP_PSRAD, 484 | OP_PSRAW, 485 | OP_PSRLD, 486 | OP_PSRLQ, 487 | OP_PSRLW, 488 | OP_PSUBB, 489 | OP_PSUBD, 490 | OP_PSUBSB, 491 | OP_PSUBSW, 492 | OP_PSUBUSB, 493 | OP_PSUBUSW, 494 | OP_PSUBW, 495 | OP_PUNPCKHBW, 496 | OP_PUNPCKHDQ, 497 | OP_PUNPCKHWD, 498 | OP_PUNPCKLBW, 499 | OP_PUNPCKLDQ, 500 | OP_PUNPCKLWD, 501 | OP_PXOR, 502 | 503 | 504 | // SSE 505 | OP_MOVAPS, 506 | OP_MOVUPS, 507 | OP_MOVHPS, 508 | // TODO: MOVHLPS? where is it? 509 | OP_MOVLPS, 510 | // TODO: MOVLHPS? where is it? 511 | OP_MOVMSKPS, 512 | OP_MOVSS, 513 | OP_ADDPS, 514 | OP_ADDSS, 515 | OP_SUBPS, 516 | OP_SUBSS, 517 | OP_MULPS, 518 | OP_MULSS, 519 | OP_DIVPS, 520 | OP_DIVSS, 521 | OP_RCPPS, 522 | OP_RCPSS, 523 | OP_SQRTPS, 524 | OP_SQRTSS, 525 | OP_RSQRTPS, 526 | OP_RSQRTSS, 527 | OP_MAXPS, 528 | OP_MAXSS, 529 | OP_MINPS, 530 | OP_MINSS, 531 | OP_CMPPS, 532 | OP_CMPSS, 533 | OP_COMISS, 534 | OP_UCOMISS, 535 | OP_ANDPS, 536 | OP_ANDNPS, 537 | OP_ORPS, 538 | OP_XORPS, 539 | OP_SHUFPS, 540 | OP_UNPCKHPS, 541 | OP_UNPCKLPS, 542 | OP_CVTPI2PS, 543 | OP_CVTSI2SS, 544 | OP_CVTPS2PI, 545 | OP_CVTTPS2PI, 546 | OP_CVTSS2SI, 547 | OP_CVTTSS2SI, 548 | OP_LDMXCSR, 549 | OP_STMXCSR, 550 | OP_PAVGB, 551 | OP_PAVGW, // Introduced in MMX? 552 | OP_PEXTRW, 553 | OP_PINSRW, 554 | OP_PMAXUB, 555 | OP_PMAXSW, 556 | OP_PMINUB, 557 | OP_PMINSW, 558 | OP_PMOVMSKB, 559 | OP_PMULHUW, 560 | OP_PSADBW, 561 | OP_PSHUFW, 562 | OP_MASKMOVQ, 563 | OP_MOVNTQ, 564 | OP_MOVNTPS, 565 | OP_PREFETCHH, 566 | OP_SFENCE, 567 | 568 | // SSE2 569 | OP_ADDPD, 570 | OP_ADDSD, 571 | OP_ANDNPD, 572 | OP_ANDPD, 573 | OP_CLFLUSH, 574 | OP_CMPPD, 575 | OP_CMPSD, 576 | OP_COMISD, 577 | OP_CVTDQ2PD, 578 | OP_CVTDQ2PS, 579 | OP_CVTPD2DQ, 580 | OP_CVTPD2PI, 581 | OP_CVTPD2PS, 582 | OP_CVTPI2PD, 583 | OP_CVTPS2DQ, 584 | OP_CVTPS2PD, 585 | OP_CVTSD2SI, 586 | OP_CVTSD2SS, 587 | OP_CVTSI2SD, 588 | OP_CVTSS2SD, 589 | OP_CVTTPD2DQ, 590 | OP_CVTTPD2PI, 591 | OP_CVTTPS2DQ, 592 | OP_CVTTSD2SI, 593 | OP_DIVPD, 594 | OP_DIVSD, 595 | OP_LFENCE, 596 | OP_MASKMOVDQU, 597 | OP_MAXPD, 598 | OP_MAXSD, 599 | OP_MFENCE, 600 | OP_MINPD, 601 | OP_MINSD, 602 | OP_MOVAPD, 603 | OP_MOVDQ2Q, 604 | OP_MOVDQA, 605 | OP_MOVDQU, 606 | OP_MOVHPD, 607 | OP_MOVLPD, 608 | OP_MOVMSKPD, 609 | OP_MOVNTDQ, 610 | OP_MOVNTI, 611 | OP_MOVNTPD, 612 | OP_MOVQ2DQ, 613 | OP_MOVSD, 614 | OP_MOVUPD, 615 | OP_MULPD, 616 | OP_MULSD, 617 | OP_ORPD, 618 | OP_PADDQ, 619 | OP_PAUSE, 620 | OP_PMULUDQ, 621 | OP_PSHUFD, 622 | OP_PSHUFHW, 623 | OP_PSHUFLW, 624 | OP_PSLLDQ, 625 | OP_PSRLDQ, 626 | OP_PSUBQ, 627 | OP_PUNPCKHQDQ, 628 | OP_PUNPCKLQDQ, 629 | OP_SHUFPD, 630 | OP_SQRTPD, 631 | OP_SQRTSD, 632 | OP_SUBPD, 633 | OP_SUBSD, 634 | OP_UCOMISD, 635 | OP_UNPCKHPD, 636 | OP_UNPCKLPD, 637 | OP_XORPD, 638 | 639 | // SSE3 640 | OP_ADDSUBPD, 641 | OP_ADDSUBPS, 642 | OP_FISTTP, 643 | OP_HADDPD, 644 | OP_HADDPS, 645 | OP_HSUBPD, 646 | OP_HSUBPS, 647 | OP_LDDQU, 648 | OP_MONITOR, 649 | OP_MOVDDUP, 650 | OP_MOVSHDUP, 651 | OP_MOVSLDUP, 652 | OP_MWAIT, 653 | 654 | // SSSE3 655 | OP_PABSB, 656 | OP_PABSW, 657 | OP_PALIGNR, 658 | OP_PHADDD, 659 | OP_PHADDSW, 660 | OP_PHADDW, 661 | OP_PHSUBD, 662 | OP_PHSUBSW, 663 | OP_PHSUBW, 664 | OP_PMADDUBSW, 665 | OP_PMULHRSW, 666 | OP_PSHUFB, 667 | OP_PSIGNB, 668 | OP_PSIGND, 669 | OP_PSIGNW, 670 | 671 | // SSE4a 672 | OP_LZCNT, // TODO: implement in tables.. 673 | OP_MOVNTSD, // TODO: implement in tables.. 674 | OP_MOVNTSS, // TODO: implement in tables.. 675 | OP_POPCNT, 676 | 677 | // TODO: 3DNow! 678 | // TODO: EMMI 679 | // TODO: Athlon 680 | // TODO: Geode GX 681 | // TODO: Intel AVX FMA 682 | // TODO: Intel AES 683 | 684 | // FPU ops 685 | OP_F2XM1, 686 | OP_FABS, 687 | OP_FADD, 688 | OP_FADDP, 689 | OP_FBLD, 690 | OP_FBSTP, 691 | OP_FCHS, 692 | OP_FCLEX, 693 | OP_FCMOVB, 694 | OP_FCMOVBE, 695 | OP_FCMOVE, 696 | OP_FCMOVNB, 697 | OP_FCMOVNBE, 698 | OP_FCMOVNE, 699 | OP_FCMOVNU, 700 | OP_FCMOVU, 701 | OP_FCOM, 702 | OP_FCOMI, 703 | OP_FCOMIP, 704 | OP_FCOMP, 705 | OP_FCOMPP, 706 | OP_FCOS, 707 | OP_FDECSTP, 708 | OP_FDISI, 709 | OP_FDIV, 710 | OP_FDIVP, 711 | OP_FDIVR, 712 | OP_FDIVRP, 713 | OP_FENI, 714 | OP_FFREE, 715 | OP_FIADD, 716 | OP_FICOM, 717 | OP_FICOMP, 718 | OP_FIDIV, 719 | OP_FIDIVR, 720 | OP_FILD, 721 | OP_FIMUL, 722 | OP_FINCSTP, 723 | OP_FINIT, 724 | OP_FIST, 725 | OP_FISTP, 726 | OP_FISUB, 727 | OP_FISUBR, 728 | OP_FLD, 729 | OP_FLD1, 730 | OP_FLDCW, 731 | OP_FLDENV, 732 | OP_FLDL2E, 733 | OP_FLDL2T, 734 | OP_FLDLG2, 735 | OP_FLDLN2, 736 | OP_FLDPI, 737 | OP_FLDZ, 738 | OP_FMUL, 739 | OP_FMULP, 740 | OP_FNCLEX, 741 | OP_FNDISI, 742 | OP_FNENI, 743 | OP_FNINIT, 744 | OP_FNOP, 745 | OP_FNSAVE, 746 | OP_FNSETPM, 747 | OP_FNSTCW, 748 | OP_FNSTENV, 749 | OP_FNSTSW, 750 | OP_FPATAN, 751 | OP_FPREM, 752 | OP_FPREM1, 753 | OP_FPTAN, 754 | OP_FRNDINT, 755 | OP_FRSTOR, 756 | OP_FSAVE, 757 | OP_FSCALE, 758 | OP_FSETPM, 759 | OP_FSIN, 760 | OP_FSINCOS, 761 | OP_FSQRT, 762 | OP_FST, 763 | OP_FSTCW, 764 | OP_FSTENV, 765 | OP_FSTP, 766 | OP_FSTPNCE, 767 | OP_FSTSW, 768 | OP_FSUB, 769 | OP_FSUBP, 770 | OP_FSUBR, 771 | OP_FSUBRP, 772 | OP_FTST, 773 | OP_FUCOM, 774 | OP_FUCOMI, 775 | OP_FUCOMIP, 776 | OP_FUCOMP, 777 | OP_FUCOMPP, 778 | OP_FXAM, 779 | OP_FXCH, 780 | OP_FXRSTOR, 781 | OP_FXSAVE, 782 | OP_FXTRACT, 783 | OP_FYL2X, 784 | OP_FYL2XP1, 785 | OP_WAIT, 786 | 787 | // AMD extensions 788 | OP_CLGI, 789 | OP_INVLPGA, 790 | OP_RDTSCP, 791 | OP_SKINIT, 792 | OP_STGI, 793 | OP_VMLOAD, 794 | OP_VMMCALL, 795 | OP_VMRUN, 796 | OP_VMSAVE, 797 | 798 | // undocumented 799 | 800 | 801 | // these aren't really valid, should never been seen in any external API 802 | OP_GROUP, 803 | OP_PREFIX, 804 | OP_2BYTE, 805 | OP_3BYTE, 806 | OP_FPU 807 | }; 808 | 809 | private: 810 | void process_prefixes(); 811 | operand_type &next_operand(); 812 | uint8_t next_byte(); 813 | 814 | private: 815 | // convenience binders, 816 | template 817 | void decode3() { 818 | (this->*F1)(); 819 | (this->*F2)(); 820 | (this->*F3)(); 821 | } 822 | 823 | template 824 | void decode2() { 825 | (this->*F1)(); 826 | (this->*F2)(); 827 | } 828 | 829 | template 830 | void decode1() { 831 | (this->*F1)(); 832 | } 833 | 834 | void decode0() { 835 | } 836 | 837 | private: 838 | 839 | template 840 | void decode_size_sensitive(const T(&opcodes)[3]) { 841 | switch(operand_size()) { 842 | case 16: opcode_ = &opcodes[0]; break; 843 | case 32: opcode_ = &opcodes[1]; break; 844 | case 64: opcode_ = &opcodes[2]; break; 845 | } 846 | (this->*(opcode_->decoder))(); 847 | } 848 | 849 | // special FPU variants.. 850 | void wait_or_wait_prefix(); 851 | 852 | // special cased names 853 | void decode_cwd_cdq_cqo(); 854 | void decode_stosw_stosd_stosq(); 855 | void decode_lodsw_lodsd_lodsq(); 856 | void decode_cbw_cwde_cdqe(); 857 | void decode_scasw_scasd_scasq(); 858 | void decode_iretw_iret_iretq(); 859 | void decode_pushfw_pushfd_pushfq(); 860 | void decode_popfw_popfd_popfq(); 861 | void decode_movsw_movsd_movsq(); 862 | void decode_jcxz_jecxz_jrcxz(); 863 | 864 | void decode_invalid_cmpxchg8b_cmpxchg16b(); 865 | 866 | // no 64-bit variant 867 | void decode_cmpsw_cmpsd_cmpsq(); 868 | void decode_outsw_outsd_invalid(); 869 | void decode_insw_insd_invalid(); 870 | void decode_pushaw_pushad_invalid(); 871 | void decode_popaw_popad_invalid(); 872 | 873 | private: 874 | // groups 875 | void decode_group1(); 876 | void decode_group2(); 877 | void decode_group2D(); 878 | void decode_group3(); 879 | void decode_group4(); 880 | void decode_group5(); 881 | void decode_group6(); 882 | void decode_group7(); 883 | void decode_group8(); 884 | void decode_group9(); 885 | void decode_group10(); 886 | void decode_group11(); 887 | void decode_group12(); 888 | void decode_group13(); 889 | void decode_group14(); 890 | void decode_group15(); 891 | void decode_group16(); 892 | void decode_group17(); 893 | 894 | private: 895 | // invalid handler 896 | void decode_invalid(); 897 | 898 | private: 899 | // multibyte encodings 900 | void decode_x87(); 901 | void decode_2byte(); 902 | void decode_3byte_38(); 903 | void decode_3byte_3A(); 904 | 905 | private: 906 | uint8_t get_modrm(); 907 | uint8_t get_sib(); 908 | 909 | template 910 | void decode_Reg(); 911 | 912 | template 913 | void decode_const_Iq(); 914 | 915 | template 916 | void decode_const_Id(); 917 | 918 | template 919 | void decode_const_Iw(); 920 | 921 | template 922 | void decode_const_Ib(); 923 | 924 | int8_t get_immediate_s8(); 925 | int16_t get_immediate_s16(); 926 | int32_t get_immediate_s32(); 927 | int64_t get_immediate_s64(); 928 | uint8_t get_immediate_u8(); 929 | uint16_t get_immediate_u16(); 930 | uint32_t get_immediate_u32(); 931 | uint64_t get_immediate_u64(); 932 | 933 | int8_t get_displacement_s8(); 934 | int16_t get_displacement_s16(); 935 | int32_t get_displacement_s32(); 936 | int64_t get_displacement_s64(); 937 | 938 | template 939 | void decode_STi(); 940 | 941 | template 942 | void decode_Gx(); 943 | 944 | template 945 | void decode_ModRM_0_16(uint8_t modrm_byte, operand_type &op); 946 | 947 | template 948 | void decode_ModRM_1_16(uint8_t modrm_byte, operand_type &op); 949 | 950 | template 951 | void decode_ModRM_2_16(uint8_t modrm_byte, operand_type &op); 952 | 953 | template 954 | void decode_ModRM_0_32(uint8_t modrm_byte, operand_type &op); 955 | 956 | template 957 | void decode_ModRM_1_32(uint8_t modrm_byte, operand_type &op); 958 | 959 | template 960 | void decode_ModRM_2_32(uint8_t modrm_byte, operand_type &op); 961 | 962 | template 963 | void decode_ModRM_3_32(uint8_t modrm_byte, operand_type &op); 964 | 965 | template 966 | void decode_ModRM_Invalid(uint8_t modrm_byte, operand_type &op); 967 | 968 | template 969 | void decode_Ex(); 970 | 971 | private: 972 | // ModRM Reg or Memory 973 | void decode_Eb() { decode_Ex::index_to_reg_8>(); } 974 | void decode_Ew() { decode_Ex::index_to_reg_16>(); } 975 | void decode_Ed() { decode_Ex::index_to_reg_32>(); } 976 | void decode_Eq() { decode_Ex::index_to_reg_64>(); } 977 | void decode_Ev(); 978 | void decode_Ey(); 979 | 980 | void decode_Qd() { decode_Ex::index_to_reg_mmx>(); } 981 | void decode_Qq() { decode_Ex::index_to_reg_mmx>(); } 982 | void decode_Qo() { decode_Ex::index_to_reg_mmx>(); } 983 | void decode_Ww() { decode_Ex::index_to_reg_xmmx>(); } 984 | void decode_Wd() { decode_Ex::index_to_reg_xmmx>(); } 985 | void decode_Wq() { decode_Ex::index_to_reg_xmmx>(); } 986 | void decode_Wo() { decode_Ex::index_to_reg_xmmx>(); } 987 | 988 | 989 | // special cases for things like SMSW Rv/Mw 990 | template 991 | void decode_Reg_Mem() { 992 | const uint8_t modrm_byte = get_modrm(); 993 | 994 | if(modrm::mod(modrm_byte) == 0x03) { 995 | (this->*F1)(); 996 | } else { 997 | (this->*F2)(); 998 | } 999 | } 1000 | 1001 | void decode_Rv_Mw() { decode_Reg_Mem<&instruction_type::decode_Rv, &instruction_type::decode_Mw>(); } 1002 | void decode_Rq_Mw() { decode_Reg_Mem<&instruction_type::decode_Rq, &instruction_type::decode_Mw>(); } 1003 | void decode_Rd_Mw() { decode_Reg_Mem<&instruction_type::decode_Rd, &instruction_type::decode_Mw>(); } 1004 | void decode_Rd_Mb() { decode_Reg_Mem<&instruction_type::decode_Rd, &instruction_type::decode_Mb>(); } 1005 | void decode_Uo_Mw() { decode_Reg_Mem<&instruction_type::decode_Uo, &instruction_type::decode_Mw>(); } 1006 | void decode_Uo_Md() { decode_Reg_Mem<&instruction_type::decode_Uo, &instruction_type::decode_Md>(); } 1007 | void decode_Uo_Mq() { decode_Reg_Mem<&instruction_type::decode_Uo, &instruction_type::decode_Mq>(); } 1008 | 1009 | // TODO: throw an error if any of these return REG_INVALID 1010 | // ModRM Memory Only 1011 | void decode_Mo() { decode_Ex::index_to_reg_invalid>(); } 1012 | void decode_M() { decode_Ex::index_to_reg_invalid>(); } 1013 | void decode_Ms() { decode_Ex::index_to_reg_invalid>(); } 1014 | void decode_M108() { decode_Ex::index_to_reg_invalid>(); } // Note this can be 108 or 98, but we just say "expression" 1015 | void decode_M512() { decode_Ex::index_to_reg_invalid>(); } // Note this can be 512 or 256, but we just say "expression" 1016 | void decode_M28() { decode_Ex::index_to_reg_invalid>(); } // Note this can be 28 or 14, but we just say "expression" 1017 | void decode_Mw() { decode_Ex::index_to_reg_invalid>(); } 1018 | void decode_Mp() { decode_Ep();} 1019 | void decode_Mdq() { decode_Ex::index_to_reg_invalid>(); } 1020 | void decode_Mq() { decode_Ex::index_to_reg_invalid>(); } 1021 | void decode_Md() { decode_Ex::index_to_reg_invalid>(); } 1022 | void decode_Mb() { decode_Ex::index_to_reg_invalid>(); } 1023 | void decode_Ma() { if(prefix_ & PREFIX_OPERAND) { decode_Ex::index_to_reg_invalid>(); } else { decode_Ex::index_to_reg_invalid>(); } } 1024 | void decode_Mv(); 1025 | void decode_Ep() { if(prefix_ & PREFIX_OPERAND) { decode_Ex::index_to_reg_invalid>(); } else { decode_Ex::index_to_reg_invalid>(); } } 1026 | 1027 | 1028 | // FPU memory only 1029 | void decode_WordInteger() { decode_Ex::index_to_reg_invalid>(); } 1030 | void decode_SingleReal() { decode_Ex::index_to_reg_invalid>(); } 1031 | void decode_ShortInteger() { decode_Ex::index_to_reg_invalid>(); } 1032 | void decode_DoubleReal() { decode_Ex::index_to_reg_invalid>(); } 1033 | void decode_LongInteger() { decode_Ex::index_to_reg_invalid>(); } 1034 | void decode_ExtendedReal() { decode_Ex::index_to_reg_invalid>(); } 1035 | void decode_PackedBCD() { decode_Ex::index_to_reg_invalid>(); } 1036 | 1037 | // ModRM selects a register only (mod must be 0x3) 1038 | // TODO: throw an error if any of these return TYPE_INVALID 1039 | void decode_Rv(); 1040 | void decode_Rw() { decode_Ex::index_to_reg_16>(); } 1041 | void decode_Rd() { decode_Ex::index_to_reg_32>(); } 1042 | void decode_Rq() { decode_Ex::index_to_reg_64>(); } 1043 | void decode_Nq() { decode_Ex::index_to_reg_mmx>(); } 1044 | void decode_Uo() { decode_Ex::index_to_reg_xmmx>(); } 1045 | void decode_Uq() { decode_Ex::index_to_reg_xmmx>(); } 1046 | 1047 | // ModRM Reg Field 1048 | void decode_Gv(); 1049 | void decode_Gb() { decode_Gx<&Instruction::index_to_reg_8>(); } 1050 | void decode_Gw() { decode_Gx<&Instruction::index_to_reg_16>(); } 1051 | void decode_Gd() { decode_Gx<&Instruction::index_to_reg_32>(); } 1052 | void decode_Gq() { decode_Gx<&Instruction::index_to_reg_64>(); } 1053 | void decode_Gz() { if(prefix_ & PREFIX_OPERAND) { decode_Gx<&Instruction::index_to_reg_16>(); } else { decode_Gx<&Instruction::index_to_reg_32>(); } } 1054 | void decode_Gy() { if(prefix_ & PREFIX_OPERAND) { decode_Gx<&Instruction::index_to_reg_32>(); } else { decode_Gx<&Instruction::index_to_reg_64>(); } } 1055 | 1056 | void decode_Vo() { decode_Gx<&Instruction::index_to_reg_xmmx>(); } 1057 | void decode_Vd() { decode_Gx<&Instruction::index_to_reg_xmmx>(); } 1058 | void decode_Vq() { decode_Gx<&Instruction::index_to_reg_xmmx>(); } 1059 | void decode_Pq() { decode_Gx<&Instruction::index_to_reg_mmx>(); } 1060 | void decode_Pd() { decode_Gx<&Instruction::index_to_reg_mmx>(); } 1061 | 1062 | // Decode [S/C/D/T]Rx from ModRM reg 1063 | void decode_Sw() { decode_Gx<&Instruction::index_to_reg_seg>(); } 1064 | void decode_Cd() { decode_Gx<&Instruction::index_to_reg_cr>(); } 1065 | void decode_Dd() { decode_Gx<&Instruction::index_to_reg_dr>(); } 1066 | void decode_Td() { decode_Gx<&Instruction::index_to_reg_tr>(); } 1067 | 1068 | // Immediate 1069 | void decode_Ib(); 1070 | void decode_Iw(); 1071 | void decode_Id(); 1072 | void decode_Iq(); 1073 | void decode_Iv(); 1074 | void decode_Iz() { if(prefix_ & PREFIX_OPERAND) { decode_Iw(); } else { decode_Id(); } } 1075 | 1076 | // Immediate (with sign extension) 1077 | void decode_Ixb(); 1078 | void decode_Ixw(); 1079 | void decode_Ixd(); 1080 | void decode_Ixz() { if(prefix_ & PREFIX_OPERAND) { decode_Ixw(); } else { decode_Ixd(); } } 1081 | 1082 | // EIP relative 1083 | void decode_Jb(); 1084 | void decode_Jw(); 1085 | void decode_Jd(); 1086 | void decode_Jq(); 1087 | void decode_Jz() { if(prefix_ & PREFIX_OPERAND) { decode_Jw(); } else { decode_Jd(); } } 1088 | 1089 | // Direct offset 1090 | void decode_Ob(); 1091 | void decode_Ow(); 1092 | void decode_Od(); 1093 | void decode_Ov(); 1094 | 1095 | // Absolute address 1096 | void decode_Ap(); 1097 | 1098 | // Decode Specific Register 1099 | void decode_eAX(); 1100 | void decode_rAX(); 1101 | void decode_rAX_NOREX(); 1102 | void decode_rCX(); 1103 | void decode_rDX(); 1104 | void decode_rBX(); 1105 | void decode_rSP(); 1106 | void decode_rBP(); 1107 | void decode_rSI(); 1108 | void decode_rDI(); 1109 | void decode_AL(); 1110 | void decode_CL(); 1111 | void decode_DL(); 1112 | void decode_BL(); 1113 | void decode_AH(); 1114 | void decode_CH(); 1115 | void decode_DH(); 1116 | void decode_BH(); 1117 | void decode_AX() { decode_Reg(); } 1118 | void decode_DX() { decode_Reg(); } 1119 | 1120 | // simple wrappers around some of the these for cleaner tables 1121 | void decode_SegCS() { decode_Reg(); } 1122 | void decode_SegDS() { decode_Reg(); } 1123 | void decode_SegES() { decode_Reg(); } 1124 | void decode_SegFS() { decode_Reg(); } 1125 | void decode_SegGS() { decode_Reg(); } 1126 | void decode_SegSS() { decode_Reg(); } 1127 | void decode_Ev_Gv_CL() { decode_Ev_Gv_Reg(); } 1128 | 1129 | private: 1130 | // 2 operand modes 1131 | template 1132 | void decode_ST_STi() { decode2<&instruction_type::template decode_Reg, &instruction_type::template decode_STi >(); } 1133 | 1134 | template 1135 | void decode_STi_ST() { decode2<&instruction_type::template decode_STi, &instruction_type::template decode_Reg >(); } 1136 | 1137 | 1138 | // macro for easier maintenance of these modes 1139 | // only works for "simple" ones though (no template usage in params) 1140 | #define DECODE2(op1, op2) \ 1141 | void decode_ ## op1 ## _ ## op2() { \ 1142 | decode2<&instruction_type::decode_ ## op1, &instruction_type::decode_ ## op2>(); \ 1143 | } 1144 | 1145 | DECODE2(Gq, Mo) 1146 | DECODE2(Pd, Eq) 1147 | DECODE2(Pd, Ed) 1148 | DECODE2(Nq, Gq) 1149 | DECODE2(Gq, Wo) 1150 | DECODE2(Gd, Mo) 1151 | DECODE2(Vo, Wd) 1152 | DECODE2(Vo, Ww) 1153 | DECODE2(Gq, Eb) 1154 | DECODE2(Gq, Uo) 1155 | DECODE2(Gq, Eq) 1156 | DECODE2(Gd, Ev) 1157 | DECODE2(Eq, Pd) 1158 | DECODE2(Vd, Eq) 1159 | DECODE2(Vq, Eq) 1160 | DECODE2(Eq, Vo) 1161 | DECODE2(Gq, Wd) 1162 | DECODE2(Gq, Wq) 1163 | DECODE2(Pq, Eq) 1164 | DECODE2(Eq, Gq) 1165 | DECODE2(Vo, Eq) 1166 | DECODE2(Mv, Gv) 1167 | DECODE2(Gv, Mv) 1168 | DECODE2(Gd, Eb) 1169 | DECODE2(Ev, Gv) 1170 | DECODE2(Eb, Gb) 1171 | DECODE2(Eb, Ib) 1172 | DECODE2(Cd, Rd) // FIX 1173 | DECODE2(Ed, Gd) 1174 | DECODE2(Ed, Pd) 1175 | DECODE2(Ed, Vo) 1176 | DECODE2(Ev, Ib) 1177 | DECODE2(Ev, Ixb) 1178 | DECODE2(Ev, Iz) 1179 | DECODE2(Ev, Sw) 1180 | DECODE2(Ew, Gw) 1181 | DECODE2(Gb, Eb) 1182 | DECODE2(Gd, Ed) 1183 | DECODE2(Gd, Nq) 1184 | DECODE2(Gd, Uo) 1185 | DECODE2(Gd, Wd) 1186 | DECODE2(Gd, Wq) 1187 | DECODE2(Gv, Eb) 1188 | DECODE2(Gv, Ev) 1189 | DECODE2(Gy, Ey) 1190 | DECODE2(Gv, Ew) 1191 | DECODE2(Gv, M) 1192 | DECODE2(Gv, Ma) 1193 | DECODE2(Gv, Mp) 1194 | DECODE2(Gz, Mp) 1195 | DECODE2(Dd, Rd) 1196 | DECODE2(Ib, rAX) 1197 | DECODE2(Iw, Ib) 1198 | DECODE2(Md, Gd) 1199 | DECODE2(Mo, Vo) 1200 | DECODE2(Mq, Pq) 1201 | DECODE2(Mq, Vq) 1202 | DECODE2(rAX, Ib) 1203 | DECODE2(rAX, Iv) 1204 | DECODE2(rAX, Iz) 1205 | DECODE2(rAX, Ov) 1206 | DECODE2(rBP, Iv) 1207 | DECODE2(rBP, rAX) 1208 | DECODE2(rBX, Iv) 1209 | DECODE2(rBX, rAX) 1210 | DECODE2(rCX, Iv) 1211 | DECODE2(rCX, rAX) 1212 | DECODE2(rDI, Iv) 1213 | DECODE2(rDI, rAX) 1214 | DECODE2(rDX, Iv) 1215 | DECODE2(rDX, rAX) 1216 | DECODE2(rAX, rAX) 1217 | DECODE2(rSI, Iv) 1218 | DECODE2(rSI, rAX) 1219 | DECODE2(rSP, Iv) 1220 | DECODE2(rSP, rAX) 1221 | DECODE2(Ov, rAX) 1222 | DECODE2(Nq, Ib) 1223 | DECODE2(Pq, Ed) 1224 | DECODE2(Pq, Nq) 1225 | DECODE2(Pq, Qd) 1226 | DECODE2(Pq, Qq) 1227 | DECODE2(Pq, Uq) 1228 | DECODE2(Pq, Wo) 1229 | DECODE2(Pq, Wq) 1230 | DECODE2(Qq, Pq) 1231 | DECODE2(Rd, Cd) // FIX 1232 | DECODE2(Rd, Dd) 1233 | DECODE2(Sw, Ew) 1234 | DECODE2(Uo, Ib) 1235 | DECODE2(Vd, Ed) 1236 | DECODE2(Vd, Wd) 1237 | DECODE2(Vd, Wq) 1238 | DECODE2(Vo, Ed) 1239 | DECODE2(Vo, Mo) 1240 | DECODE2(Vo, Mq) 1241 | DECODE2(Vo, Nq) 1242 | DECODE2(Vo, Qq) 1243 | DECODE2(Vo, Uo) 1244 | DECODE2(Vo, Wo) 1245 | DECODE2(Gd, Wo) 1246 | DECODE2(Vo, Wq) 1247 | DECODE2(Vq, Ed) 1248 | DECODE2(Vq, Mq) 1249 | DECODE2(Vq, Wq) 1250 | DECODE2(Wd, Vd) 1251 | DECODE2(Wo, Vo) 1252 | DECODE2(Wq, Vq) 1253 | DECODE2(Qq, Wo) 1254 | DECODE2(Wq, Vo) 1255 | 1256 | DECODE2(rCX, rAX_NOREX) 1257 | DECODE2(rDX, rAX_NOREX) 1258 | DECODE2(rBX, rAX_NOREX) 1259 | DECODE2(rSP, rAX_NOREX) 1260 | DECODE2(rBP, rAX_NOREX) 1261 | DECODE2(rSI, rAX_NOREX) 1262 | DECODE2(rDI, rAX_NOREX) 1263 | DECODE2(eAX, Ib) 1264 | DECODE2(Ib, eAX) 1265 | DECODE2(eAX, DX) 1266 | DECODE2(DX, eAX) 1267 | 1268 | DECODE2(Vo, Uo_Mq) 1269 | DECODE2(Vo, Uo_Mw) 1270 | DECODE2(Vo, Uo_Md) 1271 | 1272 | #undef DECODE2 1273 | 1274 | void decode_rAX_rAX_NOREX(); 1275 | 1276 | void decode_AL_Ib() { decode2<&instruction_type::decode_AL, &instruction_type::decode_Ib>(); } 1277 | void decode_CL_Ib() { decode2<&instruction_type::decode_CL, &instruction_type::decode_Ib>(); } 1278 | void decode_DL_Ib() { decode2<&instruction_type::decode_DL, &instruction_type::decode_Ib>(); } 1279 | void decode_BL_Ib() { decode2<&instruction_type::decode_BL, &instruction_type::decode_Ib>(); } 1280 | void decode_AH_Ib() { decode2<&instruction_type::decode_AH, &instruction_type::decode_Ib>(); } 1281 | void decode_CH_Ib() { decode2<&instruction_type::decode_CH, &instruction_type::decode_Ib>(); } 1282 | void decode_DH_Ib() { decode2<&instruction_type::decode_DH, &instruction_type::decode_Ib>(); } 1283 | void decode_BH_Ib() { decode2<&instruction_type::decode_BH, &instruction_type::decode_Ib>(); } 1284 | 1285 | void decode_AL_DX() { decode2<&instruction_type::template decode_Reg, &instruction_type::template decode_Reg >(); } 1286 | void decode_AL_Ob() { decode2<&instruction_type::template decode_Reg, &instruction_type::decode_Ob>(); } 1287 | void decode_DX_AL() { decode2<&instruction_type::template decode_Reg, &instruction_type::template decode_Reg >(); } 1288 | void decode_DX_rAX() { decode2<&instruction_type::template decode_Reg, &instruction_type::decode_rAX >(); } 1289 | void decode_Eb_1() { decode2<&instruction_type::decode_Eb, &instruction_type::template decode_const_Ib<1> >(); } 1290 | void decode_Eb_CL() { decode2<&instruction_type::decode_Eb, &instruction_type::template decode_Reg >(); } 1291 | void decode_Ev_1() { decode2<&instruction_type::decode_Ev, &instruction_type::template decode_const_Id<1> >(); } 1292 | void decode_Ev_CL() { decode2<&instruction_type::decode_Ev, &instruction_type::template decode_Reg >(); } 1293 | void decode_Ib_AL() { decode2<&instruction_type::decode_Ib, &instruction_type::template decode_Reg >(); } 1294 | void decode_Ob_AL() { decode2<&instruction_type::decode_Ob, &instruction_type::template decode_Reg >(); } 1295 | void decode_rAX_DX() { decode2<&instruction_type::decode_rAX, &instruction_type::template decode_Reg >(); } 1296 | 1297 | 1298 | private: 1299 | 1300 | // macro for easier maintenance of these modes 1301 | // only works for "simple" ones though (no template usage in params) 1302 | #define DECODE3(op1, op2, op3) \ 1303 | void decode_ ## op1 ## _ ## op2 ## _ ## op3() { \ 1304 | decode3<&instruction_type::decode_ ## op1, &instruction_type::decode_ ## op2, &instruction_type::decode_ ## op3>(); \ 1305 | } 1306 | 1307 | // 3 operand modes 1308 | DECODE3(Ed, Vo, Ib) 1309 | DECODE3(Eq, Vo, Ib) 1310 | DECODE3(Ev, Gv, Ib) 1311 | DECODE3(Gd, Nq, Ib) 1312 | DECODE3(Gd, Uo, Ib) 1313 | DECODE3(Gv, Ev, Ib) 1314 | DECODE3(Gv, Ev, Iz) 1315 | DECODE3(Pq, Qq, Ib) 1316 | DECODE3(Vo, Ed, Ib) 1317 | DECODE3(Vo, Eq, Ib) 1318 | DECODE3(Vo, Mb, Ib) 1319 | DECODE3(Vo, Md, Ib) 1320 | DECODE3(Vo, Wo, Ib) 1321 | 1322 | DECODE3(Ev, Vo, Ib) 1323 | 1324 | DECODE3(Pq, Rd_Mw, Ib) 1325 | DECODE3(Pq, Rq_Mw, Ib) 1326 | DECODE3(Vo, Rd_Mw, Ib) 1327 | DECODE3(Vo, Rq_Mw, Ib) 1328 | 1329 | DECODE3(Md_Gd, Vo, Ib) 1330 | DECODE3(Rd_Mb, Vo, Ib) 1331 | DECODE3(Rd_Mw, Vo, Ib) 1332 | DECODE3(Rq_Mw, Vo, Ib) 1333 | #undef DECODE3 1334 | 1335 | template 1336 | void decode_Ev_Gv_Reg() { decode3<&instruction_type::decode_Ev, &instruction_type::decode_Gv, &instruction_type::template decode_Reg >(); } 1337 | 1338 | private: 1339 | static typename operand_type::Register index_to_reg_invalid(uint8_t) { return operand_type::REG_INVALID; } 1340 | static typename operand_type::Register index_to_reg_8(uint8_t index) { return static_cast(operand_type::REG_AL + index); } 1341 | static typename operand_type::Register index_to_reg_16(uint8_t index) { return static_cast(operand_type::REG_AX + index); } 1342 | static typename operand_type::Register index_to_reg_32(uint8_t index) { return static_cast(operand_type::REG_EAX + index); } 1343 | static typename operand_type::Register index_to_reg_64(uint8_t index) { return static_cast(operand_type::REG_RAX + index); } 1344 | static typename operand_type::Register index_to_reg_seg(uint8_t index) { return static_cast(operand_type::REG_ES + index); } 1345 | static typename operand_type::Register index_to_reg_mmx(uint8_t index) { return static_cast(operand_type::REG_MM0 + index); } 1346 | static typename operand_type::Register index_to_reg_xmmx(uint8_t index) { return static_cast(operand_type::REG_XMM0 + index); } 1347 | static typename operand_type::Register index_to_reg_fpu(uint8_t index) { return static_cast(operand_type::REG_ST0 + index); } 1348 | static typename operand_type::Register index_to_reg_cr(uint8_t index) { return static_cast(operand_type::REG_CR0 + index); } 1349 | static typename operand_type::Register index_to_reg_dr(uint8_t index) { return static_cast(operand_type::REG_DR0 + index); } 1350 | static typename operand_type::Register index_to_reg_tr(uint8_t index) { return static_cast(operand_type::REG_TR0 + index); } 1351 | 1352 | public: 1353 | unsigned int flags() const { return opcode_->flags; } 1354 | Type type() const { return opcode_->type; } 1355 | uint64_t rva() const { return rva_; } 1356 | bool valid() const { return type() != OP_INVALID; } 1357 | const operand_type *operands() const { return operands_; } 1358 | const uint8_t *bytes() const { return bytes_; } 1359 | operator void *() const { return reinterpret_cast(valid()); } 1360 | std::string mnemonic() const { return opcode_->mnemonic; } 1361 | uint32_t prefix() const { return prefix_; } 1362 | uint32_t mandatory_prefix() const { return mandatory_prefix_; } 1363 | unsigned int operand_count() const { return operand_count_; } 1364 | unsigned int prefix_size() const { return prefix_size_; } 1365 | unsigned int size() const { return byte_index_; } 1366 | 1367 | private: 1368 | int operand_size() const; 1369 | int address_size() const; 1370 | 1371 | private: 1372 | struct opcode_entry { 1373 | const char *mnemonic; 1374 | decoder_t decoder; 1375 | Type type; 1376 | unsigned int flags; 1377 | }; 1378 | 1379 | private: 1380 | static const opcode_entry Opcodes_x87_Lo[64]; 1381 | static const opcode_entry Opcodes_x87_Hi[0x200]; 1382 | 1383 | static const opcode_entry Opcodes[0x100]; 1384 | static const opcode_entry Opcodes_2Byte_NA[0x100]; 1385 | static const opcode_entry Opcodes_2Byte_66[0x100]; 1386 | static const opcode_entry Opcodes_2Byte_F2[0x100]; 1387 | static const opcode_entry Opcodes_2Byte_F3[0x100]; 1388 | static const opcode_entry Opcodes_3Byte_38_NA[0x100]; 1389 | static const opcode_entry Opcodes_3Byte_38_66[0x100]; 1390 | static const opcode_entry Opcodes_3Byte_38_F2[0x100]; 1391 | static const opcode_entry Opcodes_3Byte_3A_NA[0x100]; 1392 | static const opcode_entry Opcodes_3Byte_3A_66[0x100]; 1393 | 1394 | private: 1395 | static const opcode_entry Opcodes_Group1[32]; 1396 | static const opcode_entry Opcodes_Group2[16]; 1397 | static const opcode_entry Opcodes_Group2D[32]; 1398 | static const opcode_entry Opcodes_Group3[16]; 1399 | static const opcode_entry Opcodes_Group4[8]; 1400 | static const opcode_entry Opcodes_Group5[8]; 1401 | static const opcode_entry Opcodes_Group6[8]; 1402 | static const opcode_entry Opcodes_Group7[8]; 1403 | static const opcode_entry Opcodes_Group7A[64]; 1404 | static const opcode_entry Opcodes_Group8[8]; 1405 | static const opcode_entry Opcodes_Group9[8]; 1406 | static const opcode_entry Opcodes_Group9_66[8]; 1407 | static const opcode_entry Opcodes_Group9_F3[8]; 1408 | static const opcode_entry Opcodes_Group10[8]; 1409 | static const opcode_entry Opcodes_Group11[8]; 1410 | static const opcode_entry Opcodes_Group12[16]; 1411 | static const opcode_entry Opcodes_Group13[8]; 1412 | static const opcode_entry Opcodes_Group13_66[8]; 1413 | static const opcode_entry Opcodes_Group14[8]; 1414 | static const opcode_entry Opcodes_Group14_66[8]; 1415 | static const opcode_entry Opcodes_Group15[8]; 1416 | static const opcode_entry Opcodes_Group15_66[8]; 1417 | static const opcode_entry Opcodes_Group16_Reg[8]; 1418 | static const opcode_entry Opcodes_Group16_Mem[8]; 1419 | static const opcode_entry Opcodes_Group17[64]; 1420 | 1421 | private: 1422 | // other 1423 | static const opcode_entry Opcodes_nop_pause_xchg[3]; 1424 | static const opcode_entry Opcodes_cbw_cwde_cdqe[3]; 1425 | static const opcode_entry Opcodes_cwd_cdq_cqo[3]; 1426 | static const opcode_entry Opcodes_stosw_stosd_stosq[3]; 1427 | static const opcode_entry Opcodes_lodsw_lodsd_lodsq[3]; 1428 | static const opcode_entry Opcodes_scasw_scasd_scasq[3]; 1429 | static const opcode_entry Opcodes_iretw_iret_iretq[3]; 1430 | static const opcode_entry Opcodes_movsw_movsd_movsq[3]; 1431 | static const opcode_entry Opcodes_popfw_popfd_popfq[3]; 1432 | static const opcode_entry Opcodes_pushfw_pushfd_pushfq[3]; 1433 | static const opcode_entry Opcodes_invalid_cmpxchg8b_cmpxchg16b[3]; 1434 | static const opcode_entry Opcodes_insw_insd_invalid[3]; 1435 | static const opcode_entry Opcodes_outsw_outsd_invalid[3]; 1436 | static const opcode_entry Opcodes_cmpsw_cmpsd_cmpsq[3]; 1437 | static const opcode_entry Opcodes_pushaw_pushad_invalid[3]; 1438 | static const opcode_entry Opcodes_popaw_popad_invalid[3]; 1439 | 1440 | private: 1441 | static const opcode_entry Opcode_invalid; 1442 | 1443 | private: 1444 | stream_base *byte_stream_; 1445 | 1446 | operand_type operands_[MAX_OPERANDS]; 1447 | uint8_t bytes_[MAX_SIZE]; 1448 | uint8_t byte_index_; 1449 | 1450 | uint8_t byte1_; 1451 | uint8_t byte2_; 1452 | uint8_t byte3_; 1453 | uint8_t modrm_byte_; 1454 | uint8_t sib_byte_; 1455 | uint8_t rex_byte_; 1456 | 1457 | uint64_t rva_; 1458 | const opcode_entry *opcode_; 1459 | 1460 | uint32_t prefix_; 1461 | uint32_t mandatory_prefix_; 1462 | uint8_t operand_count_; 1463 | 1464 | uint8_t modrm_size_; 1465 | uint8_t sib_size_; 1466 | uint8_t disp_size_; 1467 | uint8_t prefix_size_; 1468 | uint8_t immediate_size_; 1469 | uint8_t rex_size_; 1470 | }; 1471 | 1472 | #if __cplusplus >= 201103L 1473 | extern template class Instruction; 1474 | extern template class Instruction; 1475 | #endif 1476 | 1477 | } 1478 | 1479 | #include "edisassm_ops.h" 1480 | #include "edisassm_functions.h" 1481 | #endif 1482 | --------------------------------------------------------------------------------