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 : #include "gtest/gtest.h"
18 :
19 : namespace block_graph {
20 :
21 : namespace {
22 :
23 : class BasicBlockAssemblerTest : public testing::Test {
24 : public:
25 : typedef BlockGraph::RelativeAddress RelativeAddress;
26 : typedef BlockGraph::Block::SourceRange SourceRange;
27 :
28 : BasicBlockAssemblerTest();
29 :
30 E : void SetUp() OVERRIDE {
31 E : }
32 :
33 E : void TearDown() OVERRIDE {
34 E : }
35 :
36 : protected:
37 : struct Ref {
38 : size_t offset;
39 : BasicBlockReference::ReferredType type;
40 : const void* reference;
41 : };
42 :
43 : template <size_t N>
44 E : void AssertRefs(const Ref(& refs)[N]) {
45 E : ASSERT_EQ(1, instructions_.size());
46 E : const Instruction& instr = instructions_.front();
47 :
48 E : for (size_t i = 0; i < N; ++i) {
49 : BasicBlock::BasicBlockReferenceMap::const_iterator it =
50 E : instr.references().find(refs[i].offset);
51 E : ASSERT_NE(instr.references().end(), it);
52 E : ASSERT_EQ(refs[i].type, it->second.referred_type());
53 E : switch (refs[i].type) {
54 : case BasicBlockReference::REFERRED_TYPE_BLOCK:
55 E : ASSERT_EQ(refs[i].reference, it->second.block());
56 E : break;
57 : case BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK:
58 E : ASSERT_EQ(refs[i].reference, it->second.basic_block());
59 E : break;
60 : default:
61 i : ASSERT_TRUE(false);
62 : }
63 :
64 E : ASSERT_EQ(refs[i].type, it->second.referred_type());
65 E : }
66 :
67 E : instructions_.clear();
68 E : }
69 :
70 E : void AssertNoRefs() {
71 E : ASSERT_EQ(1, instructions_.size());
72 E : ASSERT_EQ(0, instructions_.front().references().size());
73 E : instructions_.clear();
74 E : }
75 :
76 : BlockGraph block_graph_;
77 : BlockGraph::Block* test_block_;
78 : BasicCodeBlock test_bb_;
79 : BasicBlock::Instructions instructions_;
80 : BasicBlockAssembler asm_;
81 : };
82 :
83 : #define ASSERT_REFS(...) \
84 : do { \
85 : const Ref refs[] = { __VA_ARGS__ }; \
86 : ASSERT_NO_FATAL_FAILURE(AssertRefs(refs)); \
87 : } while (0)
88 :
89 : #define ASSERT_NO_REFS() ASSERT_NO_FATAL_FAILURE(AssertNoRefs())
90 :
91 : BasicBlockAssemblerTest::BasicBlockAssemblerTest()
92 : : test_block_(NULL),
93 : test_bb_("foo"),
94 E : asm_(instructions_.end(), &instructions_) {
95 E : test_block_ = block_graph_.AddBlock(BlockGraph::CODE_BLOCK, 10, "test block");
96 E : }
97 :
98 : void TestValue(const Value& value,
99 : uint32 expected_value,
100 E : core::ValueSize expected_size) {
101 E : EXPECT_EQ(expected_size, value.size());
102 E : EXPECT_EQ(expected_value, value.value());
103 : EXPECT_EQ(BasicBlockReference::REFERRED_TYPE_UNKNOWN,
104 E : value.reference().referred_type());
105 :
106 E : Value value_copy(value);
107 E : EXPECT_EQ(expected_size, value_copy.size());
108 E : EXPECT_EQ(expected_value, value_copy.value());
109 : EXPECT_EQ(BasicBlockReference::REFERRED_TYPE_UNKNOWN,
110 E : value_copy.reference().referred_type());
111 :
112 E : EXPECT_TRUE(value == value_copy);
113 :
114 E : Value value_diff(expected_value - 1);
115 E : EXPECT_FALSE(value == value_diff);
116 E : }
117 :
118 E : void Test8BitValue(uint32 input_value, uint32 expected_value) {
119 E : TestValue(Value(input_value), expected_value, core::kSize8Bit);
120 : TestValue(
121 E : Value(input_value, core::kSize8Bit), expected_value, core::kSize8Bit);
122 E : }
123 :
124 E : void Test32BitValue(uint32 input_value, uint32 expected_value) {
125 E : TestValue(Value(input_value), expected_value, core::kSize32Bit);
126 : TestValue(
127 E : Value(input_value, core::kSize32Bit), expected_value, core::kSize32Bit);
128 E : }
129 :
130 : typedef BasicBlockAssemblerTest ValueTest;
131 :
132 E : void TestValueCopy(const Value& input) {
133 : // Make sure copy-constructing the value works.
134 E : Value copy(input);
135 :
136 E : ASSERT_EQ(input.value(), copy.value());
137 E : ASSERT_EQ(input.size(), copy.size());
138 : ASSERT_EQ(input.reference().referred_type(),
139 E : copy.reference().referred_type());
140 E : ASSERT_EQ(input.reference().block(), copy.reference().block());
141 E : ASSERT_EQ(input.reference().basic_block(), copy.reference().basic_block());
142 E : ASSERT_EQ(input.reference().offset(), copy.reference().offset());
143 E : ASSERT_EQ(input.reference().base(), copy.reference().base());
144 :
145 : // Make sure assignment operator works.
146 E : Value copy2;
147 E : copy2 = input;
148 E : ASSERT_EQ(input.value(), copy2.value());
149 E : ASSERT_EQ(input.size(), copy2.size());
150 : ASSERT_EQ(input.reference().referred_type(),
151 E : copy2.reference().referred_type());
152 E : ASSERT_EQ(input.reference().block(), copy2.reference().block());
153 E : ASSERT_EQ(input.reference().basic_block(), copy2.reference().basic_block());
154 E : ASSERT_EQ(input.reference().offset(), copy2.reference().offset());
155 E : ASSERT_EQ(input.reference().base(), copy2.reference().base());
156 E : }
157 :
158 : } // namespace
159 :
160 E : TEST(UntypedReferenceTest, DefaultConstructor) {
161 E : UntypedReference r;
162 E : EXPECT_EQ(NULL, r.basic_block());
163 E : EXPECT_EQ(NULL, r.block());
164 E : EXPECT_EQ(0, r.offset());
165 E : EXPECT_EQ(0, r.base());
166 E : EXPECT_FALSE(r.IsValid());
167 E : EXPECT_EQ(BasicBlockReference::REFERRED_TYPE_UNKNOWN, r.referred_type());
168 E : }
169 :
170 E : TEST(UntypedReferenceTest, BasicBlockReferenceToBasicBlockConstructor) {
171 E : BasicCodeBlock bcb("foo");
172 E : BasicBlock* bb = &bcb;
173 E : BasicBlockReference bbref(BlockGraph::ABSOLUTE_REF, 4, &bcb);
174 E : UntypedReference r(bbref);
175 E : EXPECT_EQ(bb, r.basic_block());
176 E : EXPECT_EQ(NULL, r.block());
177 E : EXPECT_EQ(0, r.offset());
178 E : EXPECT_EQ(0, r.base());
179 E : EXPECT_TRUE(r.IsValid());
180 E : EXPECT_EQ(BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, r.referred_type());
181 E : }
182 :
183 E : TEST(UntypedReferenceTest, BasicBlockReferenceToBlockConstructor) {
184 E : BlockGraph block_graph;
185 : BlockGraph::Block* b =
186 E : block_graph.AddBlock(BlockGraph::CODE_BLOCK, 20, "foo");
187 E : BasicBlockReference bbref(BlockGraph::ABSOLUTE_REF, 4, b, 4, 10);
188 E : UntypedReference r(bbref);
189 E : EXPECT_EQ(NULL, r.basic_block());
190 E : EXPECT_EQ(b, r.block());
191 E : EXPECT_EQ(4, r.offset());
192 E : EXPECT_EQ(10, r.base());
193 E : EXPECT_TRUE(r.IsValid());
194 E : EXPECT_EQ(BasicBlockReference::REFERRED_TYPE_BLOCK, r.referred_type());
195 E : }
196 :
197 E : TEST(UntypedReferenceTest, BasicBlockConstructor) {
198 E : BasicCodeBlock bcb("foo");
199 E : BasicBlock* bb = &bcb;
200 E : UntypedReference r(&bcb);
201 E : EXPECT_EQ(bb, r.basic_block());
202 E : EXPECT_EQ(NULL, r.block());
203 E : EXPECT_EQ(0, r.offset());
204 E : EXPECT_EQ(0, r.base());
205 E : EXPECT_TRUE(r.IsValid());
206 E : EXPECT_EQ(BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, r.referred_type());
207 E : }
208 :
209 E : TEST(UntypedReferenceTest, BlockConstructor) {
210 E : BlockGraph block_graph;
211 E : BlockGraph::Block b(0, BlockGraph::CODE_BLOCK, 0, "dummy", &block_graph);
212 E : UntypedReference r(&b, 4, 10);
213 E : EXPECT_EQ(NULL, r.basic_block());
214 E : EXPECT_EQ(&b, r.block());
215 E : EXPECT_EQ(4, r.offset());
216 E : EXPECT_EQ(10, r.base());
217 E : EXPECT_TRUE(r.IsValid());
218 E : EXPECT_EQ(BasicBlockReference::REFERRED_TYPE_BLOCK, r.referred_type());
219 E : }
220 :
221 E : TEST(UntypedReferenceTest, CopyConstructor) {
222 E : BlockGraph block_graph;
223 E : BlockGraph::Block b(0, BlockGraph::CODE_BLOCK, 0, "dummy", &block_graph);
224 E : UntypedReference r1(&b, 4, 10);
225 :
226 E : UntypedReference r2(r1);
227 E : EXPECT_EQ(r1.basic_block(), r2.basic_block());
228 E : EXPECT_EQ(r1.block(), r2.block());
229 E : EXPECT_EQ(r1.offset(), r2.offset());
230 E : EXPECT_EQ(r1.base(), r2.base());
231 E : EXPECT_EQ(r1.IsValid(), r2.IsValid());
232 E : }
233 :
234 E : TEST(UntypedReferenceTest, Comparison) {
235 E : BlockGraph block_graph;
236 E : BlockGraph::Block b(0, BlockGraph::CODE_BLOCK, 0, "dummy", &block_graph);
237 E : UntypedReference r1(&b, 4, 10);
238 :
239 E : UntypedReference r2(&b, 0, 0);
240 E : EXPECT_FALSE(r1 == r2);
241 :
242 E : BasicCodeBlock bcb("foo");
243 E : BasicBlock* bb = &bcb;
244 E : UntypedReference r3(&bcb);
245 E : EXPECT_FALSE(r1 == r3);
246 E : EXPECT_FALSE(r2 == r3);
247 :
248 E : UntypedReference r4(r1);
249 E : EXPECT_TRUE(r1 == r4);
250 :
251 E : UntypedReference r5(r2);
252 E : EXPECT_TRUE(r2 == r5);
253 E : }
254 :
255 E : TEST_F(ValueTest, Construction) {
256 : {
257 E : Value value_empty;
258 E : ASSERT_EQ(0, value_empty.value());
259 E : ASSERT_EQ(core::kSizeNone, value_empty.size());
260 : ASSERT_EQ(BasicBlockReference::REFERRED_TYPE_UNKNOWN,
261 E : value_empty.reference().referred_type());
262 :
263 E : TestValueCopy(value_empty);
264 E : }
265 :
266 E : Test8BitValue(0, 0);
267 E : Test8BitValue(127, 127);
268 :
269 E : Test8BitValue(-128, 0xFFFFFF80);
270 E : Test8BitValue(0, 0);
271 E : Test8BitValue(127, 0x0000007F);
272 :
273 E : Test32BitValue(128, 0x00000080);
274 E : Test32BitValue(0xCAFEBABE, 0xCAFEBABE);
275 :
276 E : Test32BitValue(-129, 0xFFFFFF7F);
277 E : Test32BitValue(128, 0x000000080);
278 E : Test32BitValue(0xBABE, 0xBABE);
279 :
280 : {
281 E : const BlockGraph::Offset kOffs = 10;
282 E : Value value_block_ref(test_block_, kOffs);
283 :
284 E : ASSERT_EQ(0, value_block_ref.value());
285 E : ASSERT_EQ(core::kSize32Bit, value_block_ref.size());
286 : ASSERT_EQ(BasicBlockReference::REFERRED_TYPE_BLOCK,
287 E : value_block_ref.reference().referred_type());
288 E : ASSERT_EQ(test_block_, value_block_ref.reference().block());
289 E : ASSERT_EQ(kOffs, value_block_ref.reference().offset());
290 E : ASSERT_EQ(kOffs, value_block_ref.reference().base());
291 :
292 E : TestValueCopy(value_block_ref);
293 E : }
294 :
295 : {
296 E : Value value_bb_ref(&test_bb_);
297 :
298 E : ASSERT_EQ(0, value_bb_ref.value());
299 E : ASSERT_EQ(core::kSize32Bit, value_bb_ref.size());
300 : ASSERT_EQ(BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK,
301 E : value_bb_ref.reference().referred_type());
302 E : ASSERT_EQ(&test_bb_, value_bb_ref.reference().basic_block());
303 E : ASSERT_EQ(0, value_bb_ref.reference().offset());
304 E : ASSERT_EQ(0, value_bb_ref.reference().base());
305 :
306 E : TestValueCopy(value_bb_ref);
307 E : }
308 :
309 : {
310 : // Explicitly specified size and reference info.
311 E : UntypedReference ref(test_block_, 1, 2);
312 E : Value value_expl_ref(0xBE, core::kSize8Bit, ref);
313 :
314 E : ASSERT_EQ(0xBE, value_expl_ref.value());
315 E : ASSERT_EQ(core::kSize8Bit, value_expl_ref.size());
316 : ASSERT_EQ(BasicBlockReference::REFERRED_TYPE_BLOCK,
317 E : value_expl_ref.reference().referred_type());
318 E : ASSERT_EQ(test_block_, value_expl_ref.reference().block());
319 E : ASSERT_EQ(1, value_expl_ref.reference().offset());
320 E : ASSERT_EQ(2, value_expl_ref.reference().base());
321 :
322 E : TestValueCopy(value_expl_ref);
323 E : }
324 E : }
325 :
326 : typedef BasicBlockAssemblerTest OperandTest;
327 :
328 E : void TestOperandCopy(const Operand& input) {
329 E : Operand copy(input);
330 :
331 E : ASSERT_EQ(input.base(), copy.base());
332 E : ASSERT_EQ(input.index(), copy.index());
333 E : ASSERT_EQ(input.scale(), copy.scale());
334 E : ASSERT_EQ(input.displacement().value(), copy.displacement().value());
335 E : ASSERT_EQ(input.displacement().size(), copy.displacement().size());
336 E : ASSERT_EQ(input.displacement().reference(), copy.displacement().reference());
337 :
338 E : Operand copy2(core::eax);
339 :
340 E : copy2 = input;
341 E : ASSERT_EQ(input.base(), copy2.base());
342 E : ASSERT_EQ(input.index(), copy2.index());
343 E : ASSERT_EQ(input.scale(), copy2.scale());
344 E : ASSERT_EQ(input.displacement().value(), copy2.displacement().value());
345 E : ASSERT_EQ(input.displacement().size(), copy2.displacement().size());
346 E : ASSERT_EQ(input.displacement().reference(), copy2.displacement().reference());
347 E : }
348 :
349 E : TEST_F(OperandTest, Construction) {
350 : // A register-indirect.
351 E : TestOperandCopy(Operand(core::eax));
352 :
353 : // Register-indirect with displacement.
354 E : TestOperandCopy(Operand(core::eax, Displacement(100)));
355 E : TestOperandCopy(Operand(core::eax, Displacement(test_block_, 2)));
356 E : TestOperandCopy(Operand(core::eax, Displacement(&test_bb_)));
357 :
358 : // Displacement-only mode.
359 E : TestOperandCopy(Operand(Displacement(100)));
360 E : TestOperandCopy(Operand(Displacement(test_block_, 2)));
361 E : TestOperandCopy(Operand(Displacement(&test_bb_)));
362 :
363 : TestOperandCopy(Operand(core::eax,
364 : core::ebp,
365 : core::kTimes2,
366 E : Displacement(100)));
367 : TestOperandCopy(Operand(core::eax,
368 : core::ebp,
369 : core::kTimes2,
370 E : Displacement(test_block_, 2)));
371 : TestOperandCopy(Operand(core::eax,
372 : core::ebp,
373 : core::kTimes2,
374 E : Displacement(&test_bb_)));
375 :
376 : // The [base + index * scale] mode - no displ.
377 E : TestOperandCopy(Operand(core::eax, core::ebp, core::kTimes2));
378 :
379 : // The [index * scale + displ32] mode - no base.
380 : TestOperandCopy(Operand(core::ebp,
381 : core::kTimes2,
382 E : Displacement(100)));
383 : TestOperandCopy(Operand(core::ebp,
384 : core::kTimes2,
385 E : Displacement(test_block_, 2)));
386 : TestOperandCopy(Operand(core::ebp,
387 : core::kTimes2,
388 E : Displacement(&test_bb_)));
389 E : }
390 :
391 E : TEST_F(BasicBlockAssemblerTest, call) {
392 E : asm_.call(Immediate(test_block_, 0));
393 E : ASSERT_REFS(1, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
394 :
395 E : asm_.call(Operand(Displacement(&test_bb_)));
396 E : ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, &test_bb_);
397 E : }
398 :
399 E : TEST_F(BasicBlockAssemblerTest, jmp) {
400 E : asm_.jmp(Immediate(test_block_, 0));
401 E : ASSERT_REFS(1, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
402 :
403 E : asm_.jmp(Operand(Displacement(&test_bb_)));
404 E : ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, &test_bb_);
405 E : }
406 :
407 E : TEST_F(BasicBlockAssemblerTest, mov_b) {
408 : // mov BYTE PTR [base + index * scale + displ], immediate
409 : asm_.mov_b(Operand(core::eax, core::ebx, core::kTimes4,
410 : Displacement(test_block_, 0)),
411 E : Immediate(10));
412 E : ASSERT_REFS(3, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
413 E : }
414 :
415 E : TEST_F(BasicBlockAssemblerTest, movzx_b) {
416 : // movzx eax, BYTE PTR [base + index * scale + displ]
417 : asm_.movzx_b(core::eax,
418 : Operand(core::eax, core::ebx, core::kTimes4,
419 E : Displacement(test_block_, 0)));
420 E : ASSERT_REFS(4, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
421 E : }
422 :
423 E : TEST_F(BasicBlockAssemblerTest, mov) {
424 : // Simple register-register move.
425 E : asm_.mov(core::eax, core::ebx);
426 E : ASSERT_NO_REFS();
427 :
428 : // Simple immediate-register move.
429 E : asm_.mov(core::eax, Immediate(10));
430 E : ASSERT_NO_REFS();
431 :
432 : // Immediate-with reference to register.
433 E : asm_.mov(core::eax, Immediate(test_block_, 0));
434 E : ASSERT_REFS(1, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
435 :
436 : // Torture test; mov [displ], immediate,
437 : // both src and dst contain references.
438 E : asm_.mov(Operand(Displacement(test_block_, 0)), Immediate(&test_bb_));
439 : ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_,
440 E : 6, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, &test_bb_);
441 :
442 : // Torture test; mov [base + index * scale + displ], immediate,
443 : // both src and dst contain references.
444 : asm_.mov(Operand(core::eax, core::ebx, core::kTimes4,
445 : Displacement(test_block_, 0)),
446 E : Immediate(&test_bb_));
447 : ASSERT_REFS(3, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_,
448 E : 7, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, &test_bb_);
449 E : }
450 :
451 E : TEST_F(BasicBlockAssemblerTest, mov_fs) {
452 : asm_.mov_fs(Operand(core::eax, core::ebx, core::kTimes4,
453 : Displacement(test_block_, 0)),
454 E : core::eax);
455 E : ASSERT_REFS(4, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
456 :
457 : asm_.mov_fs(core::eax,
458 : Operand(core::eax, core::ebx, core::kTimes4,
459 E : Displacement(test_block_, 0)));
460 E : ASSERT_REFS(4, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
461 E : }
462 :
463 E : TEST_F(BasicBlockAssemblerTest, lea) {
464 E : asm_.lea(core::eax, Operand(core::eax));
465 E : ASSERT_NO_REFS();
466 :
467 : asm_.lea(core::eax,
468 : Operand(core::eax, core::ebx, core::kTimes4,
469 E : Displacement(&test_bb_)));
470 E : ASSERT_REFS(3, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, &test_bb_);
471 E : }
472 :
473 E : TEST_F(BasicBlockAssemblerTest, push) {
474 E : asm_.push(core::esp);
475 E : ASSERT_NO_REFS();
476 :
477 E : asm_.push(Immediate(test_block_, 0));
478 E : ASSERT_REFS(1, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
479 :
480 : asm_.push(Operand(core::eax, core::ebx, core::kTimes4,
481 E : Displacement(&test_bb_)));
482 E : ASSERT_REFS(3, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, &test_bb_);
483 E : }
484 :
485 E : TEST_F(BasicBlockAssemblerTest, pop) {
486 E : asm_.pop(core::ebp);
487 E : ASSERT_NO_REFS();
488 :
489 : asm_.pop(Operand(core::eax, core::ebx, core::kTimes4,
490 E : Displacement(&test_bb_)));
491 E : ASSERT_REFS(3, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, &test_bb_);
492 E : }
493 :
494 E : TEST_F(BasicBlockAssemblerTest, pushfd) {
495 E : asm_.pushfd();
496 E : ASSERT_NO_REFS();
497 E : }
498 :
499 E : TEST_F(BasicBlockAssemblerTest, popfd) {
500 E : asm_.popfd();
501 E : ASSERT_NO_REFS();
502 E : }
503 :
504 E : TEST_F(BasicBlockAssemblerTest, lahf) {
505 E : asm_.lahf();
506 E : ASSERT_NO_REFS();
507 E : }
508 :
509 E : TEST_F(BasicBlockAssemblerTest, sahf) {
510 E : asm_.sahf();
511 E : ASSERT_NO_REFS();
512 E : }
513 :
514 E : TEST_F(BasicBlockAssemblerTest, setxx) {
515 : // Simple register-register operation.
516 E : asm_.set(core::kParityEven, core::eax);
517 E : ASSERT_NO_REFS();
518 :
519 E : asm_.set(core::kOverflow, core::ebx);
520 E : ASSERT_NO_REFS();
521 E : }
522 :
523 E : TEST_F(BasicBlockAssemblerTest, test_b) {
524 : // Simple register-register operation.
525 E : asm_.test_b(core::eax, core::ebx);
526 E : ASSERT_NO_REFS();
527 :
528 : // Simple immediate-register operation.
529 E : asm_.test_b(core::eax, Immediate(10, core::kSize8Bit));
530 E : ASSERT_NO_REFS();
531 E : }
532 :
533 E : TEST_F(BasicBlockAssemblerTest, test) {
534 : // Simple register-register operation.
535 E : asm_.test(core::eax, core::ebx);
536 E : ASSERT_NO_REFS();
537 :
538 : // Simple immediate-register operation.
539 E : asm_.test(core::eax, Immediate(10));
540 E : ASSERT_NO_REFS();
541 :
542 : // Immediate-with reference to register.
543 E : asm_.test(core::eax, Immediate(test_block_, 0));
544 E : ASSERT_REFS(1, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
545 :
546 : // Torture test: both src and dst contain references.
547 E : asm_.test(Operand(Displacement(test_block_, 0)), Immediate(&test_bb_));
548 : ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_,
549 E : 6, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, &test_bb_);
550 :
551 E : asm_.test(Operand(Displacement(test_block_, 0)), Immediate(10));
552 E : ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
553 E : }
554 :
555 E : TEST_F(BasicBlockAssemblerTest, cmp_b) {
556 : // Simple register-register operation.
557 E : asm_.cmp_b(core::eax, core::ebx);
558 E : ASSERT_NO_REFS();
559 :
560 : // Simple immediate-register operation.
561 E : asm_.cmp_b(core::eax, Immediate(10, core::kSize8Bit));
562 E : ASSERT_NO_REFS();
563 E : }
564 :
565 E : TEST_F(BasicBlockAssemblerTest, cmp) {
566 : // Simple register-register operation.
567 E : asm_.cmp(core::eax, core::ebx);
568 E : ASSERT_NO_REFS();
569 :
570 : // Simple immediate-register operation.
571 E : asm_.cmp(core::eax, Immediate(10));
572 E : ASSERT_NO_REFS();
573 :
574 : // Immediate-with reference to register.
575 E : asm_.cmp(core::eax, Immediate(test_block_, 0));
576 E : ASSERT_REFS(1, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
577 :
578 : // Torture test: both src and dst contain references.
579 E : asm_.cmp(Operand(Displacement(test_block_, 0)), Immediate(&test_bb_));
580 : ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_,
581 E : 6, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, &test_bb_);
582 :
583 E : asm_.cmp(Operand(Displacement(test_block_, 0)), Immediate(10));
584 E : ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
585 E : }
586 :
587 E : TEST_F(BasicBlockAssemblerTest, add_b) {
588 : // Simple register-register operation.
589 E : asm_.add_b(core::eax, core::ebx);
590 E : ASSERT_NO_REFS();
591 :
592 : // Simple immediate-register operation.
593 E : asm_.add_b(core::eax, Immediate(10, core::kSize8Bit));
594 E : ASSERT_NO_REFS();
595 E : }
596 :
597 E : TEST_F(BasicBlockAssemblerTest, add) {
598 : // Simple register-register operation.
599 E : asm_.add(core::eax, core::ebx);
600 E : ASSERT_NO_REFS();
601 :
602 : // Simple immediate-register operation.
603 E : asm_.add(core::eax, Immediate(10));
604 E : ASSERT_NO_REFS();
605 :
606 : // Immediate-with reference to register.
607 E : asm_.add(core::eax, Immediate(test_block_, 0));
608 E : ASSERT_REFS(1, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
609 :
610 : // Torture test: both src and dst contain references.
611 E : asm_.add(Operand(Displacement(test_block_, 0)), Immediate(&test_bb_));
612 : ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_,
613 E : 6, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, &test_bb_);
614 :
615 E : asm_.add(Operand(Displacement(test_block_, 0)), Immediate(10));
616 E : ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
617 E : }
618 :
619 E : TEST_F(BasicBlockAssemblerTest, sub_b) {
620 : // Simple register-register operation.
621 E : asm_.sub_b(core::eax, core::ebx);
622 E : ASSERT_NO_REFS();
623 :
624 : // Simple immediate-register operation.
625 E : asm_.sub_b(core::eax, Immediate(10, core::kSize8Bit));
626 E : ASSERT_NO_REFS();
627 E : }
628 :
629 E : TEST_F(BasicBlockAssemblerTest, sub) {
630 : // Simple register-register operation.
631 E : asm_.sub(core::eax, core::ebx);
632 E : ASSERT_NO_REFS();
633 :
634 : // Simple immediate-register operation.
635 E : asm_.sub(core::eax, Immediate(10));
636 E : ASSERT_NO_REFS();
637 :
638 : // Immediate-with reference to register.
639 E : asm_.sub(core::eax, Immediate(test_block_, 0));
640 E : ASSERT_REFS(1, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
641 :
642 : // Torture test: both src and dst contain references.
643 E : asm_.sub(Operand(Displacement(test_block_, 0)), Immediate(&test_bb_));
644 : ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_,
645 E : 6, BasicBlockReference::REFERRED_TYPE_BASIC_BLOCK, &test_bb_);
646 :
647 E : asm_.sub(Operand(Displacement(test_block_, 0)), Immediate(10));
648 E : ASSERT_REFS(2, BasicBlockReference::REFERRED_TYPE_BLOCK, test_block_);
649 E : }
650 :
651 E : TEST_F(BasicBlockAssemblerTest, shl) {
652 : // Simple immediate-register operation.
653 E : asm_.shl(core::eax, Immediate(1));
654 E : ASSERT_NO_REFS();
655 E : }
656 :
657 E : TEST_F(BasicBlockAssemblerTest, shr) {
658 : // Simple immediate-register operation.
659 E : asm_.shr(core::eax, Immediate(1));
660 E : ASSERT_NO_REFS();
661 E : }
662 :
663 E : TEST_F(BasicBlockAssemblerTest, ret) {
664 E : asm_.ret();
665 E : ASSERT_NO_REFS();
666 :
667 E : asm_.ret(4);
668 E : ASSERT_NO_REFS();
669 E : }
670 :
671 E : TEST_F(BasicBlockAssemblerTest, UndefinedSourceRange) {
672 E : ASSERT_EQ(asm_.source_range(), SourceRange());
673 E : asm_.call(Immediate(test_block_, 0));
674 E : ASSERT_EQ(instructions_.back().source_range(), SourceRange());
675 E : }
676 :
677 E : TEST_F(BasicBlockAssemblerTest, SetSourceRange) {
678 E : SourceRange range(RelativeAddress(10), 10);
679 E : asm_.set_source_range(range);
680 E : asm_.call(Immediate(test_block_, 0));
681 E : ASSERT_EQ(instructions_.back().source_range(), range);
682 E : }
683 :
684 E : TEST_F(BasicBlockAssemblerTest, SetMultipleSourceRange) {
685 E : SourceRange range1(RelativeAddress(10), 10);
686 E : SourceRange range2(RelativeAddress(20), 20);
687 :
688 E : asm_.set_source_range(range1);
689 E : asm_.call(Immediate(test_block_, 0));
690 E : ASSERT_EQ(instructions_.back().source_range(), range1);
691 :
692 E : asm_.set_source_range(range2);
693 E : asm_.pop(core::ebp);
694 E : ASSERT_EQ(instructions_.back().source_range(), range2);
695 :
696 E : asm_.ret(4);
697 E : ASSERT_EQ(instructions_.back().source_range(), range2);
698 E : }
699 :
700 : } // namespace block_graph
|