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