summaryrefslogtreecommitdiff
path: root/utils/TableGen/X86ModRMFilters.h
blob: 45cb07a3d393e57f4a80f6dea6c321b77f97dc04 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
//===- X86ModRMFilters.h - Disassembler ModR/M filterss ---------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is part of the X86 Disassembler Emitter.
// It contains ModR/M filters that determine which values of the ModR/M byte
//  are valid for a partiuclar instruction.
// Documentation for the disassembler emitter in general can be found in
//  X86DisasemblerEmitter.h.
//
//===----------------------------------------------------------------------===//

#ifndef X86MODRMFILTERS_H
#define X86MODRMFILTERS_H

#include "llvm/System/DataTypes.h"

namespace llvm {

namespace X86Disassembler {

/// ModRMFilter - Abstract base class for clases that recognize patterns in
///   ModR/M bytes.
class ModRMFilter {
public:
  /// Destructor    - Override as necessary.
  virtual ~ModRMFilter() { }

  /// isDumb        - Indicates whether this filter returns the same value for
  ///                 any value of the ModR/M byte.
  ///
  /// @result       - True if the filter returns the same value for any ModR/M
  ///                 byte; false if not.
  virtual bool isDumb() const { return false; }
  
  /// accepts       - Indicates whether the filter accepts a particular ModR/M
  ///                 byte value.
  ///
  /// @result       - True if the filter accepts the ModR/M byte; false if not.
  virtual bool accepts(uint8_t modRM) const = 0;
};

/// DumbFilter - Accepts any ModR/M byte.  Used for instructions that do not
///   require a ModR/M byte or instructions where the entire ModR/M byte is used
///   for operands.
class DumbFilter : public ModRMFilter {
public:
  bool isDumb() const {
    return true;
  }
  
  bool accepts(uint8_t modRM) const {
    return true;
  }
};

/// ModFilter - Filters based on the mod bits [bits 7-6] of the ModR/M byte.
///   Some instructions are classified based on whether they are 11 or anything
///   else.  This filter performs that classification.
class ModFilter : public ModRMFilter {
private:
  bool R;
public:
  /// Constructor
  ///
  /// @r            - True if the mod bits of the ModR/M byte must be 11; false
  ///                 otherwise.  The name r derives from the fact that the mod
  ///                 bits indicate whether the R/M bits [bits 2-0] signify a
  ///                 register or a memory operand.
  ModFilter(bool r) :
    ModRMFilter(),
    R(r) {
  }
    
  bool accepts(uint8_t modRM) const {
    if (R == ((modRM & 0xc0) == 0xc0))
      return true;
    else
      return false;
  }
};

/// EscapeFilter - Filters escape opcodes, which are classified in two ways.  If
///   the ModR/M byte is between 0xc0 and 0xff, then there is one slot for each
///   possible value.  Otherwise, there is one instruction for each value of the
///   nnn field [bits 5-3], known elsewhere as the reg field.
class EscapeFilter : public ModRMFilter {
private:
  bool C0_FF;
  uint8_t NNN_or_ModRM;
public:
  /// Constructor
  ///
  /// @c0_ff        - True if the ModR/M byte must fall between 0xc0 and 0xff;
  ///                 false otherwise.
  /// @nnn_or_modRM - If c0_ff is true, the required value of the entire ModR/M
  ///                 byte.  If c0_ff is false, the required value of the nnn
  ///                 field.
  EscapeFilter(bool c0_ff, uint8_t nnn_or_modRM) :
    ModRMFilter(),
    C0_FF(c0_ff),
    NNN_or_ModRM(nnn_or_modRM) {
  }
    
  bool accepts(uint8_t modRM) const {
    if ((C0_FF && modRM >= 0xc0 && (modRM == NNN_or_ModRM)) ||
        (!C0_FF && modRM < 0xc0  && ((modRM & 0x38) >> 3) == NNN_or_ModRM))
      return true;
    else
      return false;
  }
};

/// AddRegEscapeFilter - Some escape opcodes have one of the register operands
///   added to the ModR/M byte, meaning that a range of eight ModR/M values
///   maps to a single instruction.  Such instructions require the ModR/M byte
///   to fall between 0xc0 and 0xff.
class AddRegEscapeFilter : public ModRMFilter {
private:
  uint8_t ModRM;
public:
  /// Constructor
  ///
  /// @modRM        - The value of the ModR/M byte when the register operand
  ///                 refers to the first register in the register set.
  AddRegEscapeFilter(uint8_t modRM) : ModRM(modRM) {
  }
  
  bool accepts(uint8_t modRM) const {
    if (modRM >= ModRM && modRM < ModRM + 8)
      return true;
    else
      return false;
  }
};

/// ExtendedFilter - Extended opcodes are classified based on the value of the
///   mod field [bits 7-6] and the value of the nnn field [bits 5-3]. 
class ExtendedFilter : public ModRMFilter {
private:
  bool R;
  uint8_t NNN;
public:
  /// Constructor
  ///
  /// @r            - True if the mod field must be set to 11; false otherwise.
  ///                 The name is explained at ModFilter.
  /// @nnn          - The required value of the nnn field.
  ExtendedFilter(bool r, uint8_t nnn) : 
    ModRMFilter(),
    R(r),
    NNN(nnn) {
  }
    
  bool accepts(uint8_t modRM) const {
    if (((R  && ((modRM & 0xc0) == 0xc0)) ||
        (!R && ((modRM & 0xc0) != 0xc0))) &&
        (((modRM & 0x38) >> 3) == NNN))
      return true;
    else
      return false;
  }
};

/// ExactFilter - The occasional extended opcode (such as VMCALL or MONITOR)
///   requires the ModR/M byte to have a specific value.
class ExactFilter : public ModRMFilter
{
private:
  uint8_t ModRM;
public:
  /// Constructor
  ///
  /// @modRM        - The required value of the full ModR/M byte.
  ExactFilter(uint8_t modRM) :
    ModRMFilter(),
    ModRM(modRM) {
  }
    
  bool accepts(uint8_t modRM) const {
    if (ModRM == modRM)
      return true;
    else
      return false;
  }
};

} // namespace X86Disassembler

} // namespace llvm

#endif