1 : // Copyright 2014 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 implementation classes to generate assembly code.
16 : // The API to the assembler is intentionally very close to the API exposed
17 : // by the V8 assembler (see src/ia32/assembler-ia32.* in V8 repository).
18 :
19 : #ifndef SYZYGY_ASSM_OPERAND_BASE_H_
20 : #define SYZYGY_ASSM_OPERAND_BASE_H_
21 :
22 : #include "syzygy/assm/value_base.h"
23 :
24 : namespace assm {
25 :
26 : // Selects a scale for the Operand addressing modes.
27 : // The values match the encoding in the x86 SIB bytes.
28 : enum ScaleFactor {
29 : kTimes1 = 0,
30 : kTimes2 = 1,
31 : kTimes4 = 2,
32 : kTimes8 = 3,
33 : };
34 :
35 : // An operand implies indirection to memory through one of the myriad
36 : // modes supported by IA32.
37 : template <class ReferenceType>
38 : class OperandBase {
39 : public:
40 : typedef DisplacementBase<ReferenceType> DisplacementBase;
41 :
42 : // A register-indirect mode.
43 : explicit OperandBase(const Register32& base);
44 :
45 : // A register-indirect with displacement mode.
46 : OperandBase(const Register32& base, const DisplacementBase& displ);
47 :
48 : // A displacement-only mode.
49 : explicit OperandBase(const DisplacementBase& displ);
50 :
51 : // The full [base + index * scale + displ32] mode.
52 : // @note esp cannot be used as an index register.
53 : OperandBase(const Register32& base,
54 : const Register32& index,
55 : ScaleFactor scale,
56 : const DisplacementBase& displ);
57 :
58 : // The [base + index * scale] mode.
59 : // @note esp cannot be used as an index register.
60 : OperandBase(const Register32& base,
61 : const Register32& index,
62 : ScaleFactor scale);
63 :
64 : // The [index * scale + displ32] mode - e.g. no base.
65 : // @note esp cannot be used as an index register.
66 : OperandBase(const Register32& index,
67 : ScaleFactor scale,
68 : const DisplacementBase& displ);
69 :
70 : // Low-level constructor, none of the parameters are checked.
71 : OperandBase(RegisterId base,
72 : RegisterId index,
73 : ScaleFactor scale,
74 : const DisplacementBase& displacement);
75 :
76 : // @name Accessors.
77 : // @{
78 E : RegisterId base() const { return base_; }
79 E : RegisterId index() const { return index_; }
80 E : ScaleFactor scale() const { return scale_; }
81 E : const DisplacementBase& displacement() const { return displacement_; }
82 : // @}
83 :
84 : private:
85 : // The base register involved, or none.
86 : RegisterId base_;
87 : // The index register involved, or none.
88 : RegisterId index_;
89 : // The scaling factor, must be kTimes1 if no index register.
90 : ScaleFactor scale_;
91 : // The displacement, if any.
92 : DisplacementBase displacement_;
93 : };
94 :
95 : template <class ReferenceType>
96 : OperandBase<ReferenceType>::OperandBase(const Register32& base)
97 : : base_(base.id()),
98 : index_(kRegisterNone),
99 E : scale_(kTimes1) {
100 E : }
101 :
102 : template <class ReferenceType>
103 : OperandBase<ReferenceType>::OperandBase(
104 : const Register32& base, const DisplacementBase& displacement) :
105 : base_(base.id()),
106 : index_(kRegisterNone),
107 : scale_(kTimes1),
108 E : displacement_(displacement) {
109 : // There must be a base register.
110 E : DCHECK_NE(kRegisterNone, base_);
111 E : }
112 :
113 : template <class ReferenceType>
114 : OperandBase<ReferenceType>::OperandBase(const DisplacementBase& displacement) :
115 : base_(kRegisterNone),
116 : index_(kRegisterNone),
117 : scale_(kTimes1),
118 E : displacement_(displacement) {
119 E : DCHECK_NE(kSizeNone, displacement.size());
120 E : }
121 :
122 : template <class ReferenceType>
123 : OperandBase<ReferenceType>::OperandBase(
124 : const Register32& base, const Register32& index,
125 : ScaleFactor scale, const DisplacementBase& displacement) :
126 : base_(base.id()),
127 : index_(index.id()),
128 : scale_(scale),
129 E : displacement_(displacement) {
130 : // ESP cannot be used as an index register.
131 E : DCHECK_NE(kRegisterEsp, index.id());
132 E : DCHECK_NE(kSizeNone, displacement.size());
133 E : }
134 :
135 : template <class ReferenceType>
136 : OperandBase<ReferenceType>::OperandBase(
137 : const Register32& base, const Register32& index, ScaleFactor scale) :
138 E : base_(base.id()), index_(index.id()), scale_(scale) {
139 : // ESP cannot be used as an index register.
140 E : DCHECK_NE(kRegisterEsp, index.id());
141 E : DCHECK_EQ(kSizeNone, displacement_.size());
142 E : }
143 :
144 : template <class ReferenceType>
145 : OperandBase<ReferenceType>::OperandBase(
146 : const Register32& index, ScaleFactor scale,
147 : const DisplacementBase& displacement) :
148 : base_(kRegisterNone), index_(index.id()), scale_(scale),
149 E : displacement_(displacement) {
150 : // ESP cannot be used as an index register.
151 E : DCHECK_NE(kRegisterEsp, index.id());
152 E : DCHECK_NE(kSizeNone, displacement.size());
153 E : }
154 :
155 : template <class ReferenceType>
156 : OperandBase<ReferenceType>::OperandBase(
157 : RegisterId base, RegisterId index, ScaleFactor scale,
158 : const DisplacementBase& displacement) :
159 : base_(base), index_(index), scale_(scale),
160 : displacement_(displacement) {
161 : }
162 :
163 : } // namespace assm
164 :
165 : #endif // SYZYGY_ASSM_OPERAND_BASE_H_
|