1 : // Copyright 2012 Google Inc.
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(const Value& o)
63 E : : reference_(o.reference()), value_(CopyValue(&reference_, o.value_)) {
64 E : }
65 :
66 : Value::Value(const BasicBlockReference& ref, const core::ValueImpl& value)
67 E : : reference_(ref), value_(CopyValue(&reference_, value)) {
68 E : }
69 :
70 E : Value::~Value() {
71 : #ifndef NDEBUG
72 E : if (reference_.IsValid()) {
73 E : DCHECK(value_.reference() == &reference_);
74 E : } else {
75 E : DCHECK(value_.reference() == NULL);
76 : }
77 : #endif
78 E : }
79 :
80 E : const Value& Value::operator=(const Value& other) {
81 E : reference_ = other.reference_;
82 E : value_ = CopyValue(&reference_, other.value_);
83 E : return *this;
84 E : }
85 :
86 E : Operand::Operand(core::Register base) : operand_(base) {
87 E : }
88 :
89 : Operand::Operand(core::Register base, const Displacement& displ)
90 : : reference_(displ.reference()),
91 E : operand_(base, CopyValue(&reference_, displ.value_)) {
92 E : }
93 :
94 : Operand::Operand(const Displacement& displ)
95 : : reference_(displ.reference()),
96 E : operand_(CopyValue(&reference_, displ.value_)) {
97 E : }
98 :
99 : Operand::Operand(core::Register base,
100 : core::Register index,
101 : core::ScaleFactor scale,
102 : const Displacement& displ)
103 : : reference_(displ.reference_),
104 E : operand_(base, index, scale, CopyValue(&reference_, displ.value_)) {
105 E : }
106 :
107 : Operand::Operand(core::Register base,
108 : core::Register index,
109 : core::ScaleFactor scale)
110 E : : operand_(base, index, scale) {
111 E : }
112 :
113 : Operand::Operand(core::Register index,
114 : core::ScaleFactor scale,
115 : const Displacement& displ)
116 : : reference_(displ.reference_),
117 E : operand_(index, scale, CopyValue(&reference_, displ.value_)) {
118 E : }
119 :
120 : Operand::Operand(const Operand& o)
121 : : reference_(o.reference_),
122 : operand_(o.base(), o.index(), o.scale(),
123 E : CopyValue(&reference_, o.operand_.displacement())) {
124 E : }
125 :
126 E : Operand::~Operand() {
127 : #ifndef NDEBUG
128 E : if (reference_.IsValid()) {
129 E : DCHECK(operand_.displacement().reference() == &reference_);
130 E : } else {
131 E : DCHECK(operand_.displacement().reference() == NULL);
132 : }
133 : #endif
134 E : }
135 :
136 E : const Operand& Operand::operator=(const Operand& other) {
137 E : reference_ = other.reference_;
138 : operand_ =
139 : core::OperandImpl(other.base(), other.index(), other.scale(),
140 E : CopyValue(&reference_, other.operand_.displacement()));
141 E : return *this;
142 E : }
143 :
144 : BasicBlockAssembler::BasicBlockSerializer::BasicBlockSerializer(
145 : const Instructions::iterator& where, Instructions* list)
146 E : : where_(where), list_(list) {
147 E : DCHECK(list != NULL);
148 E : }
149 :
150 : void BasicBlockAssembler::BasicBlockSerializer::AppendInstruction(
151 : uint32 location, const uint8* bytes, size_t num_bytes,
152 E : const size_t *ref_locations, const void* const* refs, size_t num_refs) {
153 : Instructions::iterator it =
154 E : list_->insert(where_, Instruction(num_bytes, bytes));
155 :
156 E : for (size_t i = 0; i < num_refs; ++i) {
157 : const BasicBlockReference* ref =
158 E : reinterpret_cast<const BasicBlockReference*>(refs[i]);
159 E : DCHECK(ref != NULL);
160 :
161 E : it->SetReference(ref_locations[i], *ref);
162 E : }
163 E : }
164 :
165 : BasicBlockAssembler::BasicBlockAssembler(const Instructions::iterator& where,
166 : Instructions* list)
167 E : : serializer_(where, list), asm_(0, &serializer_) {
168 E : }
169 :
170 E : void BasicBlockAssembler::call(const Immediate& dst) {
171 E : asm_.call(dst.value_);
172 E : }
173 :
174 E : void BasicBlockAssembler::call(const Operand& dst) {
175 E : asm_.call(dst.operand_);
176 E : }
177 :
178 E : void BasicBlockAssembler::jmp(const Immediate& dst) {
179 E : asm_.jmp(dst.value_);
180 E : }
181 :
182 E : void BasicBlockAssembler::jmp(const Operand& dst) {
183 E : asm_.jmp(dst.operand_);
184 E : }
185 :
186 E : void BasicBlockAssembler::mov_b(const Operand& dst, const Immediate& src) {
187 E : asm_.mov_b(dst.operand_, src.value_);
188 E : }
189 :
190 E : void BasicBlockAssembler::mov(Register dst, Register src) {
191 E : asm_.mov(dst, src);
192 E : }
193 :
194 E : void BasicBlockAssembler::mov(Register dst, const Operand& src) {
195 E : asm_.mov(dst, src.operand_);
196 E : }
197 :
198 E : void BasicBlockAssembler::mov(const Operand& dst, Register src) {
199 E : asm_.mov(dst.operand_, src);
200 E : }
201 :
202 E : void BasicBlockAssembler::mov(Register dst, const Immediate& src) {
203 E : asm_.mov(dst, src.value_);
204 E : }
205 :
206 E : void BasicBlockAssembler::mov(const Operand& dst, const Immediate& src) {
207 E : asm_.mov(dst.operand_, src.value_);
208 E : }
209 :
210 E : void BasicBlockAssembler::lea(Register dst, const Operand& src) {
211 E : asm_.lea(dst, src.operand_);
212 E : }
213 :
214 E : void BasicBlockAssembler::push(Register src) {
215 E : asm_.push(src);
216 E : }
217 :
218 E : void BasicBlockAssembler::push(const Immediate& src) {
219 E : asm_.push(src.value_);
220 E : }
221 :
222 E : void BasicBlockAssembler::push(const Operand& src) {
223 E : asm_.push(src.operand_);
224 E : }
225 :
226 E : void BasicBlockAssembler::pop(Register src) {
227 E : asm_.pop(src);
228 E : }
229 :
230 E : void BasicBlockAssembler::pop(const Operand& src) {
231 E : asm_.pop(src.operand_);
232 E : }
233 :
234 : } // namespace block_graph
|