X86ModRMFilters.h revision 3cc52ea33c0b96d1682f14fc45c45b57df0f39b6
18ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan//===- X86ModRMFilters.h - Disassembler ModR/M filterss ---------*- C++ -*-===// 28ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// 38ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// The LLVM Compiler Infrastructure 48ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// 58ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// This file is distributed under the University of Illinois Open Source 68ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// License. See LICENSE.TXT for details. 78ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// 88ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan//===----------------------------------------------------------------------===// 98ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// 108ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// This file is part of the X86 Disassembler Emitter. 118ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// It contains ModR/M filters that determine which values of the ModR/M byte 128ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// are valid for a partiuclar instruction. 138ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// Documentation for the disassembler emitter in general can be found in 148ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// X86DisasemblerEmitter.h. 158ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan// 168ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan//===----------------------------------------------------------------------===// 178ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 188ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#ifndef X86MODRMFILTERS_H 198ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan#define X86MODRMFILTERS_H 208ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 213cc52ea33c0b96d1682f14fc45c45b57df0f39b6Michael J. Spencer#include "llvm/Support/DataTypes.h" 228ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 238ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanannamespace llvm { 248ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 258ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanannamespace X86Disassembler { 268ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 278ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// ModRMFilter - Abstract base class for clases that recognize patterns in 288ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// ModR/M bytes. 298ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananclass ModRMFilter { 308ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananpublic: 318ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// Destructor - Override as necessary. 328ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan virtual ~ModRMFilter() { } 338ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 348ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// isDumb - Indicates whether this filter returns the same value for 358ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// any value of the ModR/M byte. 368ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// 378ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// @result - True if the filter returns the same value for any ModR/M 388ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// byte; false if not. 398ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan virtual bool isDumb() const { return false; } 408ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 418ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// accepts - Indicates whether the filter accepts a particular ModR/M 428ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// byte value. 438ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// 448ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// @result - True if the filter accepts the ModR/M byte; false if not. 458ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan virtual bool accepts(uint8_t modRM) const = 0; 468ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan}; 478ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 488ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// DumbFilter - Accepts any ModR/M byte. Used for instructions that do not 498ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// require a ModR/M byte or instructions where the entire ModR/M byte is used 508ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// for operands. 518ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananclass DumbFilter : public ModRMFilter { 528ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananpublic: 538ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan bool isDumb() const { 548ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan return true; 558ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 568ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 578ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan bool accepts(uint8_t modRM) const { 588ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan return true; 598ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 608ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan}; 618ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 628ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// ModFilter - Filters based on the mod bits [bits 7-6] of the ModR/M byte. 638ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// Some instructions are classified based on whether they are 11 or anything 648ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// else. This filter performs that classification. 658ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananclass ModFilter : public ModRMFilter { 668ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananprivate: 678ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan bool R; 688ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananpublic: 698ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// Constructor 708ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// 718ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// @r - True if the mod bits of the ModR/M byte must be 11; false 728ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// otherwise. The name r derives from the fact that the mod 738ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// bits indicate whether the R/M bits [bits 2-0] signify a 748ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// register or a memory operand. 758ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ModFilter(bool r) : 768ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ModRMFilter(), 778ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan R(r) { 788ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 798ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 808ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan bool accepts(uint8_t modRM) const { 818ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan if (R == ((modRM & 0xc0) == 0xc0)) 828ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan return true; 838ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan else 848ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan return false; 858ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 868ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan}; 878ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 888ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// EscapeFilter - Filters escape opcodes, which are classified in two ways. If 898ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// the ModR/M byte is between 0xc0 and 0xff, then there is one slot for each 908ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// possible value. Otherwise, there is one instruction for each value of the 918ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// nnn field [bits 5-3], known elsewhere as the reg field. 928ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananclass EscapeFilter : public ModRMFilter { 938ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananprivate: 948ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan bool C0_FF; 958ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan uint8_t NNN_or_ModRM; 968ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananpublic: 978ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// Constructor 988ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// 998ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// @c0_ff - True if the ModR/M byte must fall between 0xc0 and 0xff; 1008ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// false otherwise. 1018ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// @nnn_or_modRM - If c0_ff is true, the required value of the entire ModR/M 1028ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// byte. If c0_ff is false, the required value of the nnn 1038ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// field. 1048ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan EscapeFilter(bool c0_ff, uint8_t nnn_or_modRM) : 1058ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ModRMFilter(), 1068ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan C0_FF(c0_ff), 1078ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan NNN_or_ModRM(nnn_or_modRM) { 1088ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 1098ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1108ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan bool accepts(uint8_t modRM) const { 1118ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan if ((C0_FF && modRM >= 0xc0 && (modRM == NNN_or_ModRM)) || 1128ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan (!C0_FF && modRM < 0xc0 && ((modRM & 0x38) >> 3) == NNN_or_ModRM)) 1138ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan return true; 1148ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan else 1158ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan return false; 1168ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 1178ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan}; 1188ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1198ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// AddRegEscapeFilter - Some escape opcodes have one of the register operands 1208ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// added to the ModR/M byte, meaning that a range of eight ModR/M values 1218ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// maps to a single instruction. Such instructions require the ModR/M byte 1228ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// to fall between 0xc0 and 0xff. 1238ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananclass AddRegEscapeFilter : public ModRMFilter { 1248ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananprivate: 1258ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan uint8_t ModRM; 1268ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananpublic: 1278ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// Constructor 1288ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// 1298ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// @modRM - The value of the ModR/M byte when the register operand 1308ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// refers to the first register in the register set. 1318ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan AddRegEscapeFilter(uint8_t modRM) : ModRM(modRM) { 1328ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 1338ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1348ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan bool accepts(uint8_t modRM) const { 1358ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan if (modRM >= ModRM && modRM < ModRM + 8) 1368ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan return true; 1378ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan else 1388ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan return false; 1398ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 1408ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan}; 1418ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1428ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// ExtendedFilter - Extended opcodes are classified based on the value of the 1438ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// mod field [bits 7-6] and the value of the nnn field [bits 5-3]. 1448ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananclass ExtendedFilter : public ModRMFilter { 1458ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananprivate: 1468ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan bool R; 1478ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan uint8_t NNN; 1488ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananpublic: 1498ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// Constructor 1508ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// 1518ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// @r - True if the mod field must be set to 11; false otherwise. 1528ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// The name is explained at ModFilter. 1538ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// @nnn - The required value of the nnn field. 1548ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ExtendedFilter(bool r, uint8_t nnn) : 1558ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ModRMFilter(), 1568ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan R(r), 1578ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan NNN(nnn) { 1588ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 1598ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1608ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan bool accepts(uint8_t modRM) const { 1618ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan if (((R && ((modRM & 0xc0) == 0xc0)) || 1628ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan (!R && ((modRM & 0xc0) != 0xc0))) && 1638ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan (((modRM & 0x38) >> 3) == NNN)) 1648ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan return true; 1658ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan else 1668ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan return false; 1678ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 1688ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan}; 1698ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1708ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// ExactFilter - The occasional extended opcode (such as VMCALL or MONITOR) 1718ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan/// requires the ModR/M byte to have a specific value. 1728ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananclass ExactFilter : public ModRMFilter 1738ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan{ 1748ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananprivate: 1758ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan uint8_t ModRM; 1768ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callananpublic: 1778ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// Constructor 1788ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// 1798ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan /// @modRM - The required value of the full ModR/M byte. 1808ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ExactFilter(uint8_t modRM) : 1818ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ModRMFilter(), 1828ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan ModRM(modRM) { 1838ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 1848ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1858ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan bool accepts(uint8_t modRM) const { 1868ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan if (ModRM == modRM) 1878ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan return true; 1888ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan else 1898ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan return false; 1908ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan } 1918ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan}; 1928ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1938ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} // namespace X86Disassembler 1948ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1958ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan} // namespace llvm 1968ed9f51663bc5533f36ca62e5668ae08e9a1313fSean Callanan 1979e6d1d1f5034347d237941f1bf08fba5c1583cd3Daniel Dunbar#endif 198