1 : // Copyright 2012 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 : #include "syzygy/block_graph/basic_block_assembler.h"
16 :
17 : namespace block_graph {
18 :
19 : namespace {
20 :
21 E : core::ValueSize ValueSizeFromConstant(uint32 input_value) {
22 : // IA32 assembly may/will sign-extend 8-bit literals, so we attempt to encode
23 : // in 8 bits only those literals whose value will be unchanged by that
24 : // treatment.
25 E : input_value |= 0x7F;
26 :
27 E : if (input_value == 0xFFFFFFFF || input_value == 0x7F)
28 E : return core::kSize8Bit;
29 :
30 E : return core::kSize32Bit;
31 E : }
32 :
33 : core::ValueImpl CopyValue(const BasicBlockReference* ref,
34 E : const core::ValueImpl& value) {
35 : return core::ValueImpl(value.value(),
36 : value.size(),
37 E : value.reference() ? ref : NULL);
38 E : }
39 :
40 : } // namespace
41 :
42 E : Value::Value() {
43 E : }
44 :
45 E : Value::Value(uint32 value) : value_(value, ValueSizeFromConstant(value)) {
46 E : }
47 :
48 E : Value::Value(uint32 value, core::ValueSize size) : value_(value, size) {
49 E : }
50 :
51 : Value::Value(BasicBlock* bb)
52 : : reference_(BlockGraph::ABSOLUTE_REF, sizeof(core::AbsoluteAddress), bb),
53 E : value_(0, core::kSize32Bit, &reference_) {
54 E : }
55 :
56 : Value::Value(BlockGraph::Block* block, BlockGraph::Offset offset)
57 : : reference_(BlockGraph::ABSOLUTE_REF, sizeof(core::AbsoluteAddress),
58 : block, offset, 0),
59 E : value_(0, core::kSize32Bit, &reference_) {
60 E : }
61 :
62 : Value::Value(uint32 value, ValueSize size, const BasicBlockReference& ref)
63 E : : reference_(ref), value_(value, size, &reference_) {
64 E : }
65 :
66 : Value::Value(const Value& o)
67 E : : reference_(o.reference()), value_(CopyValue(&reference_, o.value_)) {
68 E : }
69 :
70 : Value::Value(const BasicBlockReference& ref, const core::ValueImpl& value)
71 E : : reference_(ref), value_(CopyValue(&reference_, value)) {
72 E : }
73 :
74 E : Value::~Value() {
75 : #ifndef NDEBUG
76 E : if (reference_.IsValid()) {
77 E : DCHECK(value_.reference() == &reference_);
78 E : } else {
79 E : DCHECK(value_.reference() == NULL);
80 : }
81 : #endif
82 E : }
83 :
84 E : const Value& Value::operator=(const Value& other) {
85 E : reference_ = other.reference_;
86 E : value_ = CopyValue(&reference_, other.value_);
87 E : return *this;
88 E : }
89 :
90 E : bool Value::operator==(const Value& rhs) const {
91 E : if (reference_.IsValid())
92 i : return reference_ == rhs.reference();
93 E : return value_ == rhs.value_;
94 E : }
95 :
96 E : Operand::Operand(core::Register base) : operand_(base) {
97 E : }
98 :
99 : Operand::Operand(core::Register base, const Displacement& displ)
100 : : reference_(displ.reference()),
101 E : operand_(base, CopyValue(&reference_, displ.value_)) {
102 E : }
103 :
104 : Operand::Operand(const Displacement& displ)
105 : : reference_(displ.reference()),
106 E : operand_(CopyValue(&reference_, displ.value_)) {
107 E : }
108 :
109 : Operand::Operand(core::Register base,
110 : core::Register index,
111 : core::ScaleFactor scale,
112 : const Displacement& displ)
113 : : reference_(displ.reference_),
114 E : operand_(base, index, scale, CopyValue(&reference_, displ.value_)) {
115 E : }
116 :
117 : Operand::Operand(core::Register base,
118 : core::Register index,
119 : core::ScaleFactor scale)
120 E : : operand_(base, index, scale) {
121 E : }
122 :
123 : Operand::Operand(core::Register index,
124 : core::ScaleFactor scale,
125 : const Displacement& displ)
126 : : reference_(displ.reference_),
127 E : operand_(index, scale, CopyValue(&reference_, displ.value_)) {
128 E : }
129 :
130 : Operand::Operand(const Operand& o)
131 : : reference_(o.reference_),
132 : operand_(o.base(), o.index(), o.scale(),
133 E : CopyValue(&reference_, o.operand_.displacement())) {
134 E : }
135 :
136 E : Operand::~Operand() {
137 : #ifndef NDEBUG
138 E : if (reference_.IsValid()) {
139 E : DCHECK(operand_.displacement().reference() == &reference_);
140 E : } else {
141 E : DCHECK(operand_.displacement().reference() == NULL);
142 : }
143 : #endif
144 E : }
145 :
146 E : const Operand& Operand::operator=(const Operand& other) {
147 E : reference_ = other.reference_;
148 : operand_ =
149 : core::OperandImpl(other.base(), other.index(), other.scale(),
150 E : CopyValue(&reference_, other.operand_.displacement()));
151 E : return *this;
152 E : }
153 :
154 : BasicBlockAssembler::BasicBlockSerializer::BasicBlockSerializer(
155 : const Instructions::iterator& where, Instructions* list)
156 E : : where_(where), list_(list) {
157 E : DCHECK(list != NULL);
158 E : }
159 :
160 : void BasicBlockAssembler::BasicBlockSerializer::AppendInstruction(
161 : uint32 location, const uint8* bytes, size_t num_bytes,
162 E : const size_t *ref_locations, const void* const* refs, size_t num_refs) {
163 E : Instruction instruction;
164 E : CHECK(Instruction::FromBuffer(bytes, num_bytes, &instruction));
165 E : instruction.set_source_range(source_range_);
166 :
167 E : Instructions::iterator it = list_->insert(where_, instruction);
168 :
169 E : for (size_t i = 0; i < num_refs; ++i) {
170 : const BasicBlockReference* ref =
171 E : reinterpret_cast<const BasicBlockReference*>(refs[i]);
172 E : DCHECK(ref != NULL);
173 :
174 E : it->SetReference(ref_locations[i], *ref);
175 E : }
176 E : }
177 :
178 : BasicBlockAssembler::BasicBlockAssembler(const Instructions::iterator& where,
179 : Instructions* list)
180 E : : serializer_(where, list), asm_(0, &serializer_) {
181 E : }
182 :
183 : BasicBlockAssembler::BasicBlockAssembler(uint32 location,
184 : const Instructions::iterator& where,
185 : Instructions* list)
186 E : : serializer_(where, list), asm_(location, &serializer_) {
187 E : }
188 :
189 E : void BasicBlockAssembler::call(const Immediate& dst) {
190 E : asm_.call(dst.value_);
191 E : }
192 :
193 E : void BasicBlockAssembler::call(const Operand& dst) {
194 E : asm_.call(dst.operand_);
195 E : }
196 :
197 E : void BasicBlockAssembler::jmp(const Immediate& dst) {
198 E : asm_.jmp(dst.value_);
199 E : }
200 :
201 E : void BasicBlockAssembler::jmp(const Operand& dst) {
202 E : asm_.jmp(dst.operand_);
203 E : }
204 :
205 E : void BasicBlockAssembler::j(ConditionCode code, const Immediate& dst) {
206 E : asm_.j(code, dst.value_);
207 E : }
208 :
209 E : void BasicBlockAssembler::mov_b(const Operand& dst, const Immediate& src) {
210 E : asm_.mov_b(dst.operand_, src.value_);
211 E : }
212 :
213 E : void BasicBlockAssembler::mov(Register dst, Register src) {
214 E : asm_.mov(dst, src);
215 E : }
216 :
217 E : void BasicBlockAssembler::mov(Register dst, const Operand& src) {
218 E : asm_.mov(dst, src.operand_);
219 E : }
220 :
221 E : void BasicBlockAssembler::mov(const Operand& dst, Register src) {
222 E : asm_.mov(dst.operand_, src);
223 E : }
224 :
225 E : void BasicBlockAssembler::mov(Register dst, const Immediate& src) {
226 E : asm_.mov(dst, src.value_);
227 E : }
228 :
229 E : void BasicBlockAssembler::mov(const Operand& dst, const Immediate& src) {
230 E : asm_.mov(dst.operand_, src.value_);
231 E : }
232 :
233 E : void BasicBlockAssembler::lea(Register dst, const Operand& src) {
234 E : asm_.lea(dst, src.operand_);
235 E : }
236 :
237 E : void BasicBlockAssembler::push(Register src) {
238 E : asm_.push(src);
239 E : }
240 :
241 E : void BasicBlockAssembler::push(const Immediate& src) {
242 E : asm_.push(src.value_);
243 E : }
244 :
245 E : void BasicBlockAssembler::push(const Operand& src) {
246 E : asm_.push(src.operand_);
247 E : }
248 :
249 E : void BasicBlockAssembler::pop(Register src) {
250 E : asm_.pop(src);
251 E : }
252 :
253 E : void BasicBlockAssembler::pop(const Operand& src) {
254 E : asm_.pop(src.operand_);
255 E : }
256 :
257 E : void BasicBlockAssembler::ret() {
258 E : asm_.ret();
259 E : }
260 :
261 E : void BasicBlockAssembler::ret(uint16 n) {
262 E : asm_.ret(n);
263 E : }
264 :
265 : } // namespace block_graph
|