1 : // Copyright 2013 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : //
15 : // This file declares the internal implementation details for classes that are
16 : // used to represent general purpose X86 registers. They are intended to be used
17 : // with the X86 assembly utilities declared in assembler.h, and are of no real
18 : // use on their own.
19 : //
20 : // The design of the register class has been crafted to allow easy extension
21 : // for X86-64 registers if the time comes.
22 : //
23 : // For converting between Syzygy registers and Distorm RegisterType refer to the
24 : // utilities in disassembler_util.
25 :
26 : #ifndef SYZYGY_ASSM_REGISTER_INTERNAL_H_
27 : #define SYZYGY_ASSM_REGISTER_INTERNAL_H_
28 :
29 : #include "base/basictypes.h"
30 : #include "base/logging.h"
31 :
32 : namespace assm {
33 :
34 : // An enum of known registers. The enums guarantee unique values for each
35 : // register at each precision. These are not intended to be used directly, but
36 : // can be used for iterating over known registers in static analysis, for
37 : // example.
38 : //
39 : // This enum has been constructed such that the lower 3-bits represents the
40 : // code associated with the register, which is used in ModR/M and SIB bytes.
41 : enum RegisterId {
42 : kRegisterNone = -1,
43 :
44 : // 8-bit registers.
45 : kRegisterAl = 0,
46 : kRegisterCl = 1,
47 : kRegisterDl = 2,
48 : kRegisterBl = 3,
49 : kRegisterAh = 4,
50 : kRegisterCh = 5,
51 : kRegisterDh = 6,
52 : kRegisterBh = 7,
53 :
54 : // 16-bit registers.
55 : kRegisterAx = 8,
56 : kRegisterCx = 9,
57 : kRegisterDx = 10,
58 : kRegisterBx = 11,
59 : kRegisterSp = 12,
60 : kRegisterBp = 13,
61 : kRegisterSi = 14,
62 : kRegisterDi = 15,
63 :
64 : // 32-bit registers.
65 : kRegisterEax = 16,
66 : kRegisterEcx = 17,
67 : kRegisterEdx = 18,
68 : kRegisterEbx = 19,
69 : kRegisterEsp = 20,
70 : kRegisterEbp = 21,
71 : kRegisterEsi = 22,
72 : kRegisterEdi = 23,
73 :
74 : // Ranges for various register types. These come at the end so that
75 : // preferentially the debugger will show proper register IDs for overloaded
76 : // enum values.
77 : kRegisterMin = 0,
78 : kRegister8Min = 0,
79 : kRegister8Max = 8,
80 : kRegister16Min = 8,
81 : kRegister16Max = 16,
82 : kRegister32Min = 16,
83 : kRegister32Max = 24,
84 : kRegisterMax = 24
85 : };
86 :
87 : // We use another enum for register code simply for type safety. This makes it
88 : // so that we can't accidentally use a RegisterId or a uint8 as a RegisterCode.
89 : enum RegisterCode {
90 : kRegisterCode000 = 0,
91 : kRegisterCode001 = 1,
92 : kRegisterCode010 = 2,
93 : kRegisterCode011 = 3,
94 : kRegisterCode100 = 4,
95 : kRegisterCode101 = 5,
96 : kRegisterCode110 = 6,
97 : kRegisterCode111 = 7
98 : };
99 :
100 : // Register sizes. The values double as the actual number of bits.
101 : enum RegisterSize {
102 : kSizeNone = 0,
103 : kSize8Bit = 8,
104 : kSize16Bit = 16,
105 : kSize32Bit = 32,
106 : };
107 :
108 : // The base class of all registers.
109 : class Register {
110 : public:
111 : // @returns the unique ID of this register.
112 E : RegisterId id() const { return id_; }
113 :
114 : // @returns the size of this register.
115 E : RegisterSize size() const { return size_; }
116 :
117 : // @returns the code associated with this register.
118 : // @note This is not unique, with multiple registers of different precisions
119 : // having the same code.
120 E : RegisterCode code() const { return Code(id_); }
121 :
122 : // Utility function for getting the code associated with the given register
123 : // ID.
124 E : static const RegisterCode Code(RegisterId id) {
125 E : return RegisterCode(id & 0x7);
126 E : }
127 :
128 : // Utility function for getting the register with the given ID.
129 : static const Register& Get(RegisterId id);
130 :
131 : // @name Comparison operators.
132 : // @{
133 E : bool operator==(const Register& reg) const {
134 E : return id_ == reg.id_ && size_ == reg.size_;
135 E : }
136 E : bool operator!=(const Register& reg) const {
137 E : return !operator==(reg);
138 E : }
139 : // @}
140 :
141 : protected:
142 E : Register(RegisterId id, RegisterSize size) : id_(id), size_(size) {
143 E : DCHECK_NE(kRegisterNone, id);
144 E : DCHECK_NE(kSizeNone, size);
145 E : }
146 :
147 : private:
148 : RegisterId id_;
149 : RegisterSize size_;
150 : };
151 :
152 : // A templated implementation class for register objects. This is parameterized
153 : // based on the register sizes so that registers of different sizes have
154 : // different types.
155 : // @tparam register_size The size of the register, in bits.
156 : template<RegisterSize register_size>
157 : class RegisterImpl : public Register {
158 : protected:
159 : // This class acts as registry factory in the .cc file.
160 : friend class RegisterBuilder;
161 :
162 : // Constructor. This is protected so that clients don't try to manually
163 : // construct register objects, but instead use the provided static register
164 : // objects.
165 E : explicit RegisterImpl(RegisterId id) : Register(id, register_size) {
166 E : }
167 : };
168 :
169 : // We declare different types for registers so that assembler functions can be
170 : // type checked. Functions that can seamlessly handle registers of various sizes
171 : // can simply accept object of type Register, and query them directly for size
172 : // information.
173 : typedef RegisterImpl<kSize8Bit> Register8;
174 : typedef RegisterImpl<kSize16Bit> Register16;
175 : typedef RegisterImpl<kSize32Bit> Register32;
176 :
177 : } // namespace assm
178 :
179 : #endif // SYZYGY_ASSM_REGISTER_INTERNAL_H_
|