Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
assembler_ia32_test.cc
Go to the documentation of this file.
1// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/globals.h"
6#if defined(TARGET_ARCH_IA32)
7
9#include "vm/cpu.h"
10#include "vm/os.h"
11#include "vm/unit_test.h"
12#include "vm/virtual_memory.h"
13
14#if defined(PRODUCT)
15#define EXPECT_DISASSEMBLY(expected)
16#else
17#define EXPECT_DISASSEMBLY(expected) \
18 EXPECT_STREQ(expected, test->RelativeDisassembly())
19#endif
20
21namespace dart {
22namespace compiler {
23
24#define __ assembler->
25
26ASSEMBLER_TEST_GENERATE(Simple, assembler) {
27 __ movl(EAX, Immediate(42));
28 __ ret();
29}
30
31ASSEMBLER_TEST_RUN(Simple, test) {
32 typedef int (*SimpleCode)();
33 EXPECT_EQ(42, reinterpret_cast<SimpleCode>(test->entry())());
34 EXPECT_DISASSEMBLY(
35 "mov eax,0x2a\n"
36 "ret\n");
37}
38
39ASSEMBLER_TEST_GENERATE(ReadArgument, assembler) {
40 __ movl(EAX, Address(ESP, target::kWordSize));
41 __ ret();
42}
43
44ASSEMBLER_TEST_RUN(ReadArgument, test) {
45 typedef int (*ReadArgumentCode)(int n);
46 EXPECT_EQ(42, reinterpret_cast<ReadArgumentCode>(test->entry())(42));
47 EXPECT_EQ(87, reinterpret_cast<ReadArgumentCode>(test->entry())(87));
48 EXPECT_DISASSEMBLY(
49 "mov eax,[esp+0x4]\n"
50 "ret\n");
51}
52
53ASSEMBLER_TEST_GENERATE(AddressingModes, assembler) {
54 __ movl(EAX, Address(ESP, 0));
55 __ movl(EAX, Address(EBP, 0));
56 __ movl(EAX, Address(EAX, 0));
57
58 __ movl(EAX, Address(ESP, target::kWordSize));
59 __ movl(EAX, Address(EBP, target::kWordSize));
60 __ movl(EAX, Address(EAX, target::kWordSize));
61
62 __ movl(EAX, Address(ESP, -target::kWordSize));
63 __ movl(EAX, Address(EBP, -target::kWordSize));
64 __ movl(EAX, Address(EAX, -target::kWordSize));
65
66 __ movl(EAX, Address(ESP, 256 * target::kWordSize));
67 __ movl(EAX, Address(EBP, 256 * target::kWordSize));
68 __ movl(EAX, Address(EAX, 256 * target::kWordSize));
69
70 __ movl(EAX, Address(ESP, -256 * target::kWordSize));
71 __ movl(EAX, Address(EBP, -256 * target::kWordSize));
72 __ movl(EAX, Address(EAX, -256 * target::kWordSize));
73
74 __ movl(EAX, Address(EAX, TIMES_1));
75 __ movl(EAX, Address(EAX, TIMES_2));
76 __ movl(EAX, Address(EAX, TIMES_4));
77 __ movl(EAX, Address(EAX, TIMES_8));
78
79 __ movl(EAX, Address(EBP, TIMES_2));
80 __ movl(EAX, Address(EAX, TIMES_2));
81
82 __ movl(EAX, Address(EBP, TIMES_2, target::kWordSize));
83 __ movl(EAX, Address(EAX, TIMES_2, target::kWordSize));
84
85 __ movl(EAX, Address(EBP, TIMES_2, 256 * target::kWordSize));
86 __ movl(EAX, Address(EAX, TIMES_2, 256 * target::kWordSize));
87
88 __ movl(EAX, Address(EAX, EBP, TIMES_2, 0));
89 __ movl(EAX, Address(EAX, EAX, TIMES_2, 0));
90 __ movl(EAX, Address(EBP, EBP, TIMES_2, 0));
91 __ movl(EAX, Address(EBP, EAX, TIMES_2, 0));
92 __ movl(EAX, Address(ESP, EBP, TIMES_2, 0));
93 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0));
94
95 __ movl(EAX, Address(EAX, EBP, TIMES_2, target::kWordSize));
96 __ movl(EAX, Address(EAX, EAX, TIMES_2, target::kWordSize));
97 __ movl(EAX, Address(EBP, EBP, TIMES_2, target::kWordSize));
98 __ movl(EAX, Address(EBP, EAX, TIMES_2, target::kWordSize));
99 __ movl(EAX, Address(ESP, EBP, TIMES_2, target::kWordSize));
100 __ movl(EAX, Address(ESP, EAX, TIMES_2, target::kWordSize));
101
102 __ movl(EAX, Address(EAX, EBP, TIMES_2, 256 * target::kWordSize));
103 __ movl(EAX, Address(EAX, EAX, TIMES_2, 256 * target::kWordSize));
104 __ movl(EAX, Address(EBP, EBP, TIMES_2, 256 * target::kWordSize));
105 __ movl(EAX, Address(EBP, EAX, TIMES_2, 256 * target::kWordSize));
106 __ movl(EAX, Address(ESP, EBP, TIMES_2, 256 * target::kWordSize));
107 __ movl(EAX, Address(ESP, EAX, TIMES_2, 256 * target::kWordSize));
108}
109
110ASSEMBLER_TEST_RUN(AddressingModes, test) {
111 // Avoid running the code since it is constructed to lead to crashes.
112 EXPECT_DISASSEMBLY(
113 "mov eax,[esp]\n"
114 "mov eax,[ebp+0]\n"
115 "mov eax,[eax]\n"
116 "mov eax,[esp+0x4]\n"
117 "mov eax,[ebp+0x4]\n"
118 "mov eax,[eax+0x4]\n"
119 "mov eax,[esp-0x4]\n"
120 "mov eax,[ebp-0x4]\n"
121 "mov eax,[eax-0x4]\n"
122 "mov eax,[esp+0x400]\n"
123 "mov eax,[ebp+0x400]\n"
124 "mov eax,[eax+0x400]\n"
125 "mov eax,[esp-0x400]\n"
126 "mov eax,[ebp-0x400]\n"
127 "mov eax,[eax-0x400]\n"
128 "mov eax,[eax]\n"
129 "mov eax,[eax+0x1]\n"
130 "mov eax,[eax+0x2]\n"
131 "mov eax,[eax+0x3]\n"
132 "mov eax,[ebp+0x1]\n"
133 "mov eax,[eax+0x1]\n"
134 "mov eax,[ebp*2+0x4]\n"
135 "mov eax,[eax*2+0x4]\n"
136 "mov eax,[ebp*2+0x400]\n"
137 "mov eax,[eax*2+0x400]\n"
138 "mov eax,[eax+ebp*2]\n"
139 "mov eax,[eax+eax*2]\n"
140 "mov eax,[ebp+ebp*2+0]\n"
141 "mov eax,[ebp+eax*2+0]\n"
142 "mov eax,[esp+ebp*2]\n"
143 "mov eax,[esp+eax*2]\n"
144 "mov eax,[eax+ebp*2+0x4]\n"
145 "mov eax,[eax+eax*2+0x4]\n"
146 "mov eax,[ebp+ebp*2+0x4]\n"
147 "mov eax,[ebp+eax*2+0x4]\n"
148 "mov eax,[esp+ebp*2+0x4]\n"
149 "mov eax,[esp+eax*2+0x4]\n"
150 "mov eax,[eax+ebp*2+0x400]\n"
151 "mov eax,[eax+eax*2+0x400]\n"
152 "mov eax,[ebp+ebp*2+0x400]\n"
153 "mov eax,[ebp+eax*2+0x400]\n"
154 "mov eax,[esp+ebp*2+0x400]\n"
155 "mov eax,[esp+eax*2+0x400]\n");
156}
157
158ASSEMBLER_TEST_GENERATE(JumpAroundCrash, assembler) {
159 Label done;
160 // Make sure all the condition jumps work.
161 for (Condition condition = OVERFLOW; condition <= GREATER;
162 condition = static_cast<Condition>(condition + 1)) {
163 __ j(condition, &done);
164 }
165 // This isn't strictly necessary, but we do an unconditional
166 // jump around the crashing code anyway.
167 __ jmp(&done);
168
169 // Be sure to skip this crashing code.
170 __ movl(EAX, Immediate(0));
171 __ movl(Address(EAX, 0), EAX);
172
173 __ Bind(&done);
174 __ ret();
175}
176
177ASSEMBLER_TEST_RUN(JumpAroundCrash, test) {
178 Instr* instr = Instr::At(test->entry());
179 EXPECT(!instr->IsBreakPoint());
180 typedef void (*JumpAroundCrashCode)();
181 reinterpret_cast<JumpAroundCrashCode>(test->entry())();
182 EXPECT_DISASSEMBLY(
183 "jo +108\n"
184 "jno +102\n"
185 "jc +96\n"
186 "jnc +90\n"
187 "jz +84\n"
188 "jnz +78\n"
189 "jna +72\n"
190 "ja +66\n"
191 "js +60\n"
192 "jns +54\n"
193 "jpe +48\n"
194 "jpo +42\n"
195 "jl +36\n"
196 "jge +30\n"
197 "jle +24\n"
198 "jg +18\n"
199 "jmp +12\n"
200 "mov eax,0\n"
201 "mov [eax],eax\n"
202 "ret\n");
203}
204
205ASSEMBLER_TEST_GENERATE(NearJumpAroundCrash, assembler) {
206 Label done;
207 // Make sure all the condition jumps work.
208 for (Condition condition = OVERFLOW; condition <= GREATER;
209 condition = static_cast<Condition>(condition + 1)) {
210 __ j(condition, &done, Assembler::kNearJump);
211 }
212 // This isn't strictly necessary, but we do an unconditional
213 // jump around the crashing code anyway.
215
216 // Be sure to skip this crashing code.
217 __ movl(EAX, Immediate(0));
218 __ movl(Address(EAX, 0), EAX);
219
220 __ Bind(&done);
221 __ ret();
222}
223
224ASSEMBLER_TEST_RUN(NearJumpAroundCrash, test) {
225 typedef void (*NearJumpAroundCrashCode)();
226 reinterpret_cast<NearJumpAroundCrashCode>(test->entry())();
227 EXPECT_DISASSEMBLY(
228 "jo +41\n"
229 "jno +39\n"
230 "jc +37\n"
231 "jnc +35\n"
232 "jz +33\n"
233 "jnz +31\n"
234 "jna +29\n"
235 "ja +27\n"
236 "js +25\n"
237 "jns +23\n"
238 "jpe +21\n"
239 "jpo +19\n"
240 "jl +17\n"
241 "jge +15\n"
242 "jle +13\n"
243 "jg +11\n"
244 "jmp +9\n"
245 "mov eax,0\n"
246 "mov [eax],eax\n"
247 "ret\n");
248}
249
250ASSEMBLER_TEST_GENERATE(SimpleLoop, assembler) {
251 __ movl(EAX, Immediate(0));
252 __ movl(ECX, Immediate(0));
253 Label loop;
254 __ Bind(&loop);
255 __ addl(EAX, Immediate(2));
256 __ incl(ECX);
257 __ cmpl(ECX, Immediate(87));
258 __ j(LESS, &loop);
259 __ ret();
260}
261
262ASSEMBLER_TEST_RUN(SimpleLoop, test) {
263 typedef int (*SimpleLoopCode)();
264 EXPECT_EQ(2 * 87, reinterpret_cast<SimpleLoopCode>(test->entry())());
265 EXPECT_DISASSEMBLY(
266 "mov eax,0\n"
267 "mov ecx,0\n"
268 "add eax,2\n"
269 "inc ecx\n"
270 "cmp ecx,0x57\n"
271 "jl -7\n"
272 "ret\n");
273}
274
275ASSEMBLER_TEST_GENERATE(Cmpb, assembler) {
276 Label done;
277 __ movl(EAX, Immediate(1));
278 __ pushl(Immediate(0xffffff11));
279 __ cmpb(Address(ESP, 0), Immediate(0x11));
281 __ movl(EAX, Immediate(0));
282 __ Bind(&done);
283 __ popl(ECX);
284 __ ret();
285}
286
288 typedef int (*CmpbCode)();
289 EXPECT_EQ(1, reinterpret_cast<CmpbCode>(test->entry())());
290 EXPECT_DISASSEMBLY(
291 "mov eax,1\n"
292 "push 0xffffff11\n"
293 "cmpb [esp],0x11\n"
294 "jz +7\n"
295 "mov eax,0\n"
296 "pop ecx\n"
297 "ret\n");
298}
299
300ASSEMBLER_TEST_GENERATE(Testb, assembler) {
301 __ movl(EAX, Immediate(1));
302 __ movl(ECX, Immediate(0));
303 __ pushl(Immediate(0xffffff11));
304 __ testb(Address(ESP, 0), Immediate(0x10));
305 // Fail if zero flag set.
306 __ cmove(EAX, ECX);
307 __ testb(Address(ESP, 0), Immediate(0x20));
308 // Fail if zero flag not set.
309 __ cmovne(EAX, ECX);
310 __ popl(ECX);
311 __ ret();
312}
313
314ASSEMBLER_TEST_RUN(Testb, test) {
315 typedef int (*TestbCode)();
316 EXPECT_EQ(1, reinterpret_cast<TestbCode>(test->entry())());
317 EXPECT_DISASSEMBLY(
318 "mov eax,1\n"
319 "mov ecx,0\n"
320 "push 0xffffff11\n"
321 "testb [esp],0x10\n"
322 "cmovz eax,ecx\n"
323 "testb [esp],0x20\n"
324 "cmovnz eax,ecx\n"
325 "pop ecx\n"
326 "ret\n");
327}
328
329ASSEMBLER_TEST_GENERATE(Bsf, assembler) {
330 __ movl(ECX, Immediate(12));
331 __ bsfl(EAX, ECX);
332 __ ret();
333}
334
336 typedef int (*BsfCode)();
337 EXPECT_EQ(2, reinterpret_cast<BsfCode>(test->entry())());
338 EXPECT_DISASSEMBLY(
339 "mov ecx,0xc\n"
340 "bsf eax,ecx\n"
341 "ret\n");
342}
343
344ASSEMBLER_TEST_GENERATE(Bsr, assembler) {
345 __ movl(ECX, Immediate(12));
346 __ bsrl(EAX, ECX);
347 __ ret();
348}
349
351 typedef int (*BsrCode)();
352 EXPECT_EQ(3, reinterpret_cast<BsrCode>(test->entry())());
353 EXPECT_DISASSEMBLY(
354 "mov ecx,0xc\n"
355 "bsr eax,ecx\n"
356 "ret\n");
357}
358
359ASSEMBLER_TEST_GENERATE(Popcnt, assembler) {
360 __ movl(ECX, Immediate(-1));
361 __ popcntl(EAX, ECX);
362 __ movl(ECX, Immediate(0xf));
363 __ popcntl(ECX, ECX);
364 __ addl(EAX, ECX);
365 __ ret();
366}
367
368ASSEMBLER_TEST_RUN(Popcnt, test) {
370 return;
371 }
372 typedef int (*PopcntCode)();
373 EXPECT_EQ(36, reinterpret_cast<PopcntCode>(test->entry())());
374 EXPECT_DISASSEMBLY(
375 "mov ecx,0xffffffff\n"
376 "popcnt eax,ecx\n"
377 "mov ecx,0xf\n"
378 "popcnt ecx,ecx\n"
379 "add eax,ecx\n"
380 "ret\n");
381}
382
383ASSEMBLER_TEST_GENERATE(Lzcnt, assembler) {
384 __ movl(ECX, Immediate(0x0f00));
385 __ lzcntl(EAX, ECX);
386 __ movl(ECX, Immediate(0x00f0));
387 __ lzcntl(ECX, ECX);
388 __ addl(EAX, ECX);
389 __ ret();
390}
391
392ASSEMBLER_TEST_RUN(Lzcnt, test) {
394 return;
395 }
396 typedef int (*LzcntCode)();
397 EXPECT_EQ(44, reinterpret_cast<LzcntCode>(test->entry())());
398 EXPECT_DISASSEMBLY(
399 "mov ecx,0xf00\n"
400 "lzcnt eax,ecx\n"
401 "mov ecx,0xf0\n"
402 "lzcnt ecx,ecx\n"
403 "add eax,ecx\n"
404 "ret\n");
405}
406
407struct JumpAddress {
408 uword filler1;
409 uword filler2;
410 uword filler3;
411 uword filler4;
412 uword filler5;
414 uword filler6;
415 uword filler7;
416 uword filler8;
417};
418static JumpAddress jump_address;
419static uword jump_address_offset;
420
421ASSEMBLER_TEST_GENERATE(JumpAddress, assembler) {
422 __ movl(EAX, Address(ESP, 4));
423 __ jmp(Address(EAX, OFFSET_OF(JumpAddress, target)));
424 __ int3();
425 __ int3();
426 __ int3();
427 __ int3();
428 __ int3();
429 jump_address_offset = __ CodeSize();
430 __ movl(EAX, Immediate(42));
431 __ ret();
432}
433
434ASSEMBLER_TEST_RUN(JumpAddress, test) {
435 memset(&jump_address, 0, sizeof(jump_address));
436 jump_address.target = test->entry() + jump_address_offset;
437
438 typedef int (*TestCode)(void*);
439 EXPECT_EQ(42, reinterpret_cast<TestCode>(test->entry())(&jump_address));
440 EXPECT_DISASSEMBLY(
441 "mov eax,[esp+0x4]\n"
442 "jmp [eax+0x14]\n"
443 "int3\n"
444 "int3\n"
445 "int3\n"
446 "int3\n"
447 "int3\n"
448 "mov eax,0x2a\n"
449 "ret\n");
450}
451
452ASSEMBLER_TEST_GENERATE(Increment, assembler) {
453 __ movl(EAX, Immediate(0));
454 __ pushl(EAX);
455 __ incl(Address(ESP, 0));
456 __ movl(ECX, Address(ESP, 0));
457 __ incl(ECX);
458 __ popl(EAX);
459 __ movl(EAX, ECX);
460 __ ret();
461}
462
463ASSEMBLER_TEST_RUN(Increment, test) {
464 typedef int (*IncrementCode)();
465 EXPECT_EQ(2, reinterpret_cast<IncrementCode>(test->entry())());
466 EXPECT_DISASSEMBLY(
467 "mov eax,0\n"
468 "push eax\n"
469 "inc [esp]\n"
470 "mov ecx,[esp]\n"
471 "inc ecx\n"
472 "pop eax\n"
473 "mov eax,ecx\n"
474 "ret\n");
475}
476
477ASSEMBLER_TEST_GENERATE(Decrement, assembler) {
478 __ movl(EAX, Immediate(2));
479 __ pushl(EAX);
480 __ decl(Address(ESP, 0));
481 __ movl(ECX, Address(ESP, 0));
482 __ decl(ECX);
483 __ popl(EAX);
484 __ movl(EAX, ECX);
485 __ ret();
486}
487
488ASSEMBLER_TEST_RUN(Decrement, test) {
489 typedef int (*DecrementCode)();
490 EXPECT_EQ(0, reinterpret_cast<DecrementCode>(test->entry())());
491 EXPECT_DISASSEMBLY(
492 "mov eax,2\n"
493 "push eax\n"
494 "dec [esp]\n"
495 "mov ecx,[esp]\n"
496 "dec ecx\n"
497 "pop eax\n"
498 "mov eax,ecx\n"
499 "ret\n");
500}
501
502ASSEMBLER_TEST_GENERATE(AddressBinOp, assembler) {
503 __ movl(EAX, Address(ESP, target::kWordSize));
504 __ addl(EAX, Address(ESP, target::kWordSize));
505 __ incl(EAX);
506 __ subl(EAX, Address(ESP, target::kWordSize));
507 __ imull(EAX, Address(ESP, target::kWordSize));
508 __ ret();
509}
510
511ASSEMBLER_TEST_RUN(AddressBinOp, test) {
512 typedef int (*AddressBinOpCode)(int a);
513 EXPECT_EQ((2 + 2 + 1 - 2) * 2,
514 reinterpret_cast<AddressBinOpCode>(test->entry())(2));
515 EXPECT_DISASSEMBLY(
516 "mov eax,[esp+0x4]\n"
517 "add eax,[esp+0x4]\n"
518 "inc eax\n"
519 "sub eax,[esp+0x4]\n"
520 "imul eax,[esp+0x4]\n"
521 "ret\n");
522}
523
524ASSEMBLER_TEST_GENERATE(SignedMultiply, assembler) {
525 __ movl(EAX, Immediate(2));
526 __ movl(ECX, Immediate(4));
527 __ imull(EAX, ECX);
528 __ imull(EAX, Immediate(1000));
529 __ ret();
530}
531
532ASSEMBLER_TEST_RUN(SignedMultiply, test) {
533 typedef int (*SignedMultiply)();
534 EXPECT_EQ(8000, reinterpret_cast<SignedMultiply>(test->entry())());
535 EXPECT_DISASSEMBLY(
536 "mov eax,2\n"
537 "mov ecx,4\n"
538 "imul eax,ecx\n"
539 "imul eax,eax,0x3e8\n"
540 "ret\n");
541}
542
543ASSEMBLER_TEST_GENERATE(OverflowSignedMultiply, assembler) {
544 __ movl(EDX, Immediate(0));
545 __ movl(EAX, Immediate(0x0fffffff));
546 __ movl(ECX, Immediate(0x0fffffff));
547 __ imull(EAX, ECX);
548 __ imull(EAX, EDX);
549 __ ret();
550}
551
552ASSEMBLER_TEST_RUN(OverflowSignedMultiply, test) {
553 typedef int (*OverflowSignedMultiply)();
554 EXPECT_EQ(0, reinterpret_cast<OverflowSignedMultiply>(test->entry())());
555 EXPECT_DISASSEMBLY(
556 "mov edx,0\n"
557 "mov eax,0x0fffffff\n"
558 "mov ecx,0x0fffffff\n"
559 "imul eax,ecx\n"
560 "imul eax,edx\n"
561 "ret\n");
562}
563
564ASSEMBLER_TEST_GENERATE(SignedMultiply1, assembler) {
565 __ pushl(EBX); // preserve EBX.
566 __ movl(EBX, Immediate(2));
567 __ movl(ECX, Immediate(4));
568 __ imull(EBX, ECX);
569 __ imull(EBX, Immediate(1000));
570 __ movl(EAX, EBX);
571 __ popl(EBX); // restore EBX.
572 __ ret();
573}
574
575ASSEMBLER_TEST_RUN(SignedMultiply1, test) {
576 typedef int (*SignedMultiply1)();
577 EXPECT_EQ(8000, reinterpret_cast<SignedMultiply1>(test->entry())());
578 EXPECT_DISASSEMBLY(
579 "push ebx\n"
580 "mov ebx,2\n"
581 "mov ecx,4\n"
582 "imul ebx,ecx\n"
583 "imul ebx,ebx,0x3e8\n"
584 "mov eax,ebx\n"
585 "pop ebx\n"
586 "ret\n");
587}
588
589ASSEMBLER_TEST_GENERATE(Negate, assembler) {
590 __ movl(ECX, Immediate(42));
591 __ negl(ECX);
592 __ movl(EAX, ECX);
593 __ ret();
594}
595
596ASSEMBLER_TEST_RUN(Negate, test) {
597 typedef int (*Negate)();
598 EXPECT_EQ(-42, reinterpret_cast<Negate>(test->entry())());
599 EXPECT_DISASSEMBLY(
600 "mov ecx,0x2a\n"
601 "neg ecx\n"
602 "mov eax,ecx\n"
603 "ret\n");
604}
605
606ASSEMBLER_TEST_GENERATE(BitScanReverseTest, assembler) {
607 __ movl(ECX, Address(ESP, target::kWordSize));
608 __ movl(EAX, Immediate(666)); // Marker for conditional write.
609 __ bsrl(EAX, ECX);
610 __ ret();
611}
612
613ASSEMBLER_TEST_RUN(BitScanReverseTest, test) {
614 typedef int (*Bsr)(int input);
615 Bsr call = reinterpret_cast<Bsr>(test->entry());
616 EXPECT_EQ(666, call(0));
617 EXPECT_EQ(0, call(1));
618 EXPECT_EQ(1, call(2));
619 EXPECT_EQ(1, call(3));
620 EXPECT_EQ(2, call(4));
621 EXPECT_EQ(5, call(42));
622 EXPECT_EQ(31, call(-1));
623 EXPECT_DISASSEMBLY(
624 "mov ecx,[esp+0x4]\n"
625 "mov eax,0x29a\n"
626 "bsr eax,ecx\n"
627 "ret\n");
628}
629
630ASSEMBLER_TEST_GENERATE(MoveExtend, assembler) {
631 __ pushl(EBX); // preserve EBX.
632 __ movl(EDX, Immediate(0x1234ffff));
633 __ movzxb(EAX, DL); // EAX = 0xff
634 __ movsxw(EBX, EDX); // EBX = -1
635 __ movzxw(ECX, EDX); // ECX = 0xffff
636 __ addl(EBX, ECX);
637 __ addl(EAX, EBX);
638 __ popl(EBX); // restore EBX.
639 __ ret();
640}
641
642ASSEMBLER_TEST_RUN(MoveExtend, test) {
643 typedef int (*MoveExtend)();
644 EXPECT_EQ(0xff - 1 + 0xffff, reinterpret_cast<MoveExtend>(test->entry())());
645 EXPECT_DISASSEMBLY(
646 "push ebx\n"
647 "mov edx,0x1234ffff\n"
648 "movzxb eax,edx\n"
649 "movsxw ebx,edx\n"
650 "movzxw ecx,edx\n"
651 "add ebx,ecx\n"
652 "add eax,ebx\n"
653 "pop ebx\n"
654 "ret\n");
655}
656
657ASSEMBLER_TEST_GENERATE(MoveExtendMemory, assembler) {
658 __ pushl(EBX); // preserve EBX.
659 __ movl(EDX, Immediate(0x1234ffff));
660
661 __ pushl(EDX);
662 __ movzxb(EAX, Address(ESP, 0)); // EAX = 0xff
663 __ movsxw(EBX, Address(ESP, 0)); // EBX = -1
664 __ movzxw(ECX, Address(ESP, 0)); // ECX = 0xffff
665 __ addl(ESP, Immediate(target::kWordSize));
666
667 __ addl(EBX, ECX);
668 __ addl(EAX, EBX);
669 __ popl(EBX); // restore EBX.
670 __ ret();
671}
672
673ASSEMBLER_TEST_RUN(MoveExtendMemory, test) {
674 typedef int (*MoveExtendMemory)();
675 EXPECT_EQ(0xff - 1 + 0xffff,
676 reinterpret_cast<MoveExtendMemory>(test->entry())());
677 EXPECT_DISASSEMBLY(
678 "push ebx\n"
679 "mov edx,0x1234ffff\n"
680 "push edx\n"
681 "movzxb eax,[esp]\n"
682 "movsxw ebx,[esp]\n"
683 "movzxw ecx,[esp]\n"
684 "add esp,4\n"
685 "add ebx,ecx\n"
686 "add eax,ebx\n"
687 "pop ebx\n"
688 "ret\n");
689}
690
691ASSEMBLER_TEST_GENERATE(Bitwise, assembler) {
692 __ movl(ECX, Immediate(42));
693 __ xorl(ECX, ECX);
694 __ orl(ECX, Immediate(0x100));
695 __ movl(EAX, Immediate(0x648));
696 __ orl(ECX, EAX); // 0x748.
697 __ movl(EAX, Immediate(0xfff0));
698 __ andl(ECX, EAX); // 0x740.
699 __ pushl(Immediate(0xF6FF));
700 __ andl(ECX, Address(ESP, 0)); // 0x640.
701 __ popl(EAX); // Discard.
702 __ movl(EAX, Immediate(1));
703 __ orl(ECX, EAX); // 0x641.
704 __ pushl(Immediate(0x7));
705 __ orl(ECX, Address(ESP, 0)); // 0x647.
706 __ popl(EAX); // Discard.
707 __ xorl(ECX, Immediate(0)); // 0x647.
708 __ pushl(Immediate(0x1C));
709 __ xorl(ECX, Address(ESP, 0)); // 0x65B.
710 __ popl(EAX); // Discard.
711 __ movl(EAX, Address(ESP, target::kWordSize));
712 __ movl(EDX, Immediate(0xB0));
713 __ orl(Address(EAX, 0), EDX);
714 __ movl(EAX, ECX);
715 __ ret();
716}
717
718ASSEMBLER_TEST_RUN(Bitwise, test) {
719 typedef int (*Bitwise)(int* value);
720 int value = 0xA;
721 const int result = reinterpret_cast<Bitwise>(test->entry())(&value);
722 EXPECT_EQ(0x65B, result);
723 EXPECT_EQ(0xBA, value);
724 EXPECT_DISASSEMBLY(
725 "mov ecx,0x2a\n"
726 "xor ecx,ecx\n"
727 "or ecx,0x100\n"
728 "mov eax,0x648\n"
729 "or ecx,eax\n"
730 "mov eax,0xfff0\n"
731 "and ecx,eax\n"
732 "push 0xf6ff\n"
733 "and ecx,[esp]\n"
734 "pop eax\n"
735 "mov eax,1\n"
736 "or ecx,eax\n"
737 "push 7\n"
738 "or ecx,[esp]\n"
739 "pop eax\n"
740 "xor ecx,0\n"
741 "push 0x1c\n"
742 "xor ecx,[esp]\n"
743 "pop eax\n"
744 "mov eax,[esp+0x4]\n"
745 "mov edx,0xb0\n"
746 "or [eax],edx\n"
747 "mov eax,ecx\n"
748 "ret\n");
749}
750
751ASSEMBLER_TEST_GENERATE(LogicalOps, assembler) {
752 Label donetest1;
753 __ movl(EAX, Immediate(4));
754 __ andl(EAX, Immediate(2));
755 __ cmpl(EAX, Immediate(0));
756 __ j(EQUAL, &donetest1);
757 // Be sure to skip this crashing code.
758 __ movl(EAX, Immediate(0));
759 __ movl(Address(EAX, 0), EAX);
760 __ Bind(&donetest1);
761
762 Label donetest2;
763 __ movl(ECX, Immediate(4));
764 __ andl(ECX, Immediate(4));
765 __ cmpl(ECX, Immediate(0));
766 __ j(NOT_EQUAL, &donetest2);
767 // Be sure to skip this crashing code.
768 __ movl(EAX, Immediate(0));
769 __ movl(Address(EAX, 0), EAX);
770 __ Bind(&donetest2);
771
772 Label donetest3;
773 __ movl(EAX, Immediate(0));
774 __ orl(EAX, Immediate(0));
775 __ cmpl(EAX, Immediate(0));
776 __ j(EQUAL, &donetest3);
777 // Be sure to skip this crashing code.
778 __ movl(EAX, Immediate(0));
779 __ movl(Address(EAX, 0), EAX);
780 __ Bind(&donetest3);
781
782 Label donetest4;
783 __ movl(EAX, Immediate(4));
784 __ orl(EAX, Immediate(0));
785 __ cmpl(EAX, Immediate(0));
786 __ j(NOT_EQUAL, &donetest4);
787 // Be sure to skip this crashing code.
788 __ movl(EAX, Immediate(0));
789 __ movl(Address(EAX, 0), EAX);
790 __ Bind(&donetest4);
791
792 Label donetest5;
793 __ movl(EAX, Immediate(1));
794 __ shll(EAX, Immediate(1));
795 __ cmpl(EAX, Immediate(2));
796 __ j(EQUAL, &donetest5);
797 // Be sure to skip this crashing code.
798 __ movl(EAX, Immediate(0));
799 __ movl(Address(EAX, 0), EAX);
800 __ Bind(&donetest5);
801
802 Label donetest6;
803 __ movl(EAX, Immediate(1));
804 __ shll(EAX, Immediate(3));
805 __ cmpl(EAX, Immediate(8));
806 __ j(EQUAL, &donetest6);
807 // Be sure to skip this crashing code.
808 __ movl(EAX, Immediate(0));
809 __ movl(Address(EAX, 0), EAX);
810 __ Bind(&donetest6);
811
812 Label donetest7;
813 __ movl(EAX, Immediate(2));
814 __ shrl(EAX, Immediate(1));
815 __ cmpl(EAX, Immediate(1));
816 __ j(EQUAL, &donetest7);
817 // Be sure to skip this crashing code.
818 __ movl(EAX, Immediate(0));
819 __ movl(Address(EAX, 0), EAX);
820 __ Bind(&donetest7);
821
822 Label donetest8;
823 __ movl(EAX, Immediate(8));
824 __ shrl(EAX, Immediate(3));
825 __ cmpl(EAX, Immediate(1));
826 __ j(EQUAL, &donetest8);
827 // Be sure to skip this crashing code.
828 __ movl(EAX, Immediate(0));
829 __ movl(Address(EAX, 0), EAX);
830 __ Bind(&donetest8);
831
832 Label donetest9;
833 __ movl(EAX, Immediate(1));
834 __ movl(ECX, Immediate(3));
835 __ shll(EAX, ECX);
836 __ cmpl(EAX, Immediate(8));
837 __ j(EQUAL, &donetest9);
838 // Be sure to skip this crashing code.
839 __ movl(EAX, Immediate(0));
840 __ movl(Address(EAX, 0), EAX);
841 __ Bind(&donetest9);
842
843 Label donetest10;
844 __ movl(EAX, Immediate(8));
845 __ movl(ECX, Immediate(3));
846 __ shrl(EAX, ECX);
847 __ cmpl(EAX, Immediate(1));
848 __ j(EQUAL, &donetest10);
849 // Be sure to skip this crashing code.
850 __ movl(EAX, Immediate(0));
851 __ movl(Address(EAX, 0), EAX);
852 __ Bind(&donetest10);
853
854 Label donetest11;
855 __ movl(EAX, Immediate(1));
856 __ shll(EAX, Immediate(31));
857 __ shrl(EAX, Immediate(3));
858 __ cmpl(EAX, Immediate(0x10000000));
859 __ j(EQUAL, &donetest11);
860 // Be sure to skip this crashing code.
861 __ movl(EAX, Immediate(0));
862 __ movl(Address(EAX, 0), EAX);
863 __ Bind(&donetest11);
864
865 Label donetest12;
866 __ movl(EAX, Immediate(1));
867 __ shll(EAX, Immediate(31));
868 __ sarl(EAX, Immediate(3));
869 __ cmpl(EAX, Immediate(0xf0000000));
870 __ j(EQUAL, &donetest12);
871 // Be sure to skip this crashing code.
872 __ movl(EAX, Immediate(0));
873 __ movl(Address(EAX, 0), EAX);
874 __ Bind(&donetest12);
875
876 Label donetest13;
877 __ movl(EAX, Immediate(1));
878 __ movl(ECX, Immediate(3));
879 __ shll(EAX, Immediate(31));
880 __ sarl(EAX, ECX);
881 __ cmpl(EAX, Immediate(0xf0000000));
882 __ j(EQUAL, &donetest13);
883 // Be sure to skip this crashing code.
884 __ movl(EAX, Immediate(0));
885 __ movl(Address(EAX, 0), EAX);
886 __ Bind(&donetest13);
887
888 Label donetest14;
889 __ subl(ESP, Immediate(target::kWordSize));
890 __ movl(Address(ESP, 0), Immediate(0x80000000));
891 __ movl(EAX, Immediate(0));
892 __ movl(ECX, Immediate(3));
893 __ sarl(Address(ESP, 0), ECX);
894 __ shrdl(Address(ESP, 0), EAX, ECX);
895 __ cmpl(Address(ESP, 0), Immediate(0x1e000000));
896 __ j(EQUAL, &donetest14);
897 __ int3();
898 __ Bind(&donetest14);
899 __ addl(ESP, Immediate(target::kWordSize));
900
901 Label donetest15;
902 __ subl(ESP, Immediate(target::kWordSize));
903 __ movl(Address(ESP, 0), Immediate(0xFF000000));
904 __ movl(EAX, Immediate(-1));
905 __ movl(ECX, Immediate(2));
906 __ shll(Address(ESP, 0), ECX);
907 __ shldl(Address(ESP, 0), EAX, ECX);
908 __ cmpl(Address(ESP, 0), Immediate(0xF0000003));
909 __ j(EQUAL, &donetest15);
910 __ int3();
911 __ Bind(&donetest15);
912 __ addl(ESP, Immediate(target::kWordSize));
913
914 Label donetest16;
915 __ movl(EDX, Immediate(0x80000000));
916 __ movl(EAX, Immediate(0));
917 __ movl(ECX, Immediate(3));
918 __ sarl(EDX, Immediate(3));
919 __ shrdl(EDX, EAX, Immediate(3));
920 __ cmpl(EDX, Immediate(0x1e000000));
921 __ j(EQUAL, &donetest16);
922 __ int3();
923 __ Bind(&donetest16);
924
925 Label donetest17;
926 __ movl(EDX, Immediate(0xFF000000));
927 __ movl(EAX, Immediate(-1));
928 __ shll(EDX, Immediate(2));
929 __ shldl(EDX, EAX, Immediate(2));
930 __ cmpl(EDX, Immediate(0xF0000003));
931 __ j(EQUAL, &donetest17);
932 __ int3();
933 __ Bind(&donetest17);
934
935 __ movl(EAX, Immediate(0));
936 __ ret();
937}
938
939ASSEMBLER_TEST_RUN(LogicalOps, test) {
940 typedef int (*LogicalOpsCode)();
941 EXPECT_EQ(0, reinterpret_cast<LogicalOpsCode>(test->entry())());
942 EXPECT_DISASSEMBLY(
943 "mov eax,4\n"
944 "and eax,2\n"
945 "cmp eax,0\n"
946 "jz +13\n"
947 "mov eax,0\n"
948 "mov [eax],eax\n"
949 "mov ecx,4\n"
950 "and ecx,4\n"
951 "cmp ecx,0\n"
952 "jnz +13\n"
953 "mov eax,0\n"
954 "mov [eax],eax\n"
955 "mov eax,0\n"
956 "or eax,0\n"
957 "cmp eax,0\n"
958 "jz +13\n"
959 "mov eax,0\n"
960 "mov [eax],eax\n"
961 "mov eax,4\n"
962 "or eax,0\n"
963 "cmp eax,0\n"
964 "jnz +13\n"
965 "mov eax,0\n"
966 "mov [eax],eax\n"
967 "mov eax,1\n"
968 "shl eax,1\n"
969 "cmp eax,2\n"
970 "jz +13\n"
971 "mov eax,0\n"
972 "mov [eax],eax\n"
973 "mov eax,1\n"
974 "shl eax,3\n"
975 "cmp eax,8\n"
976 "jz +13\n"
977 "mov eax,0\n"
978 "mov [eax],eax\n"
979 "mov eax,2\n"
980 "shr eax,1\n"
981 "cmp eax,1\n"
982 "jz +13\n"
983 "mov eax,0\n"
984 "mov [eax],eax\n"
985 "mov eax,8\n"
986 "shr eax,3\n"
987 "cmp eax,1\n"
988 "jz +13\n"
989 "mov eax,0\n"
990 "mov [eax],eax\n"
991 "mov eax,1\n"
992 "mov ecx,3\n"
993 "shl eax,cl\n"
994 "cmp eax,8\n"
995 "jz +13\n"
996 "mov eax,0\n"
997 "mov [eax],eax\n"
998 "mov eax,8\n"
999 "mov ecx,3\n"
1000 "shr eax,cl\n"
1001 "cmp eax,1\n"
1002 "jz +13\n"
1003 "mov eax,0\n"
1004 "mov [eax],eax\n"
1005 "mov eax,1\n"
1006 "shl eax,31\n"
1007 "shr eax,3\n"
1008 "cmp eax,0x10000000\n"
1009 "jz +13\n"
1010 "mov eax,0\n"
1011 "mov [eax],eax\n"
1012 "mov eax,1\n"
1013 "shl eax,31\n"
1014 "sar eax,3\n"
1015 "cmp eax,0xf0000000\n"
1016 "jz +13\n"
1017 "mov eax,0\n"
1018 "mov [eax],eax\n"
1019 "mov eax,1\n"
1020 "mov ecx,3\n"
1021 "shl eax,31\n"
1022 "sar eax,cl\n"
1023 "cmp eax,0xf0000000\n"
1024 "jz +13\n"
1025 "mov eax,0\n"
1026 "mov [eax],eax\n"
1027 "sub esp,4\n"
1028 "mov [esp],-0x80000000\n"
1029 "mov eax,0\n"
1030 "mov ecx,3\n"
1031 "sar [esp],cl\n"
1032 "shrd [esp],eax,cl\n"
1033 "cmp [esp],0x1e000000\n"
1034 "jz +7\n"
1035 "int3\n"
1036 "add esp,4\n"
1037 "sub esp,4\n"
1038 "mov [esp],-0x01000000\n"
1039 "mov eax,0xffffffff\n"
1040 "mov ecx,2\n"
1041 "shl [esp],cl\n"
1042 "shld [esp],eax,cl\n"
1043 "cmp [esp],0xf0000003\n"
1044 "jz +7\n"
1045 "int3\n"
1046 "add esp,4\n"
1047 "mov edx,0x80000000\n"
1048 "mov eax,0\n"
1049 "mov ecx,3\n"
1050 "sar edx,3\n"
1051 "shrd edx,eax,3\n"
1052 "cmp edx,0x1e000000\n"
1053 "jz +7\n"
1054 "int3\n"
1055 "mov edx,0xff000000\n"
1056 "mov eax,0xffffffff\n"
1057 "shl edx,2\n"
1058 "shld edx,eax,2\n"
1059 "cmp edx,0xf0000003\n"
1060 "jz +7\n"
1061 "int3\n"
1062 "mov eax,0\n"
1063 "ret\n");
1064}
1065
1066ASSEMBLER_TEST_GENERATE(LogicalTest, assembler) {
1067 __ pushl(EBX); // save EBX.
1068 Label donetest1;
1069 __ movl(EAX, Immediate(4));
1070 __ movl(ECX, Immediate(2));
1071 __ testl(EAX, ECX);
1072 __ j(EQUAL, &donetest1);
1073 // Be sure to skip this crashing code.
1074 __ movl(EAX, Immediate(0));
1075 __ movl(Address(EAX, 0), EAX);
1076 __ Bind(&donetest1);
1077
1078 Label donetest2;
1079 __ movl(EDX, Immediate(4));
1080 __ movl(ECX, Immediate(4));
1081 __ testl(EDX, ECX);
1082 __ j(NOT_EQUAL, &donetest2);
1083 // Be sure to skip this crashing code.
1084 __ movl(EAX, Immediate(0));
1085 __ movl(Address(EAX, 0), EAX);
1086 __ Bind(&donetest2);
1087
1088 Label donetest3;
1089 __ movl(EAX, Immediate(0));
1090 __ testl(EAX, Immediate(0));
1091 __ j(EQUAL, &donetest3);
1092 // Be sure to skip this crashing code.
1093 __ movl(EAX, Immediate(0));
1094 __ movl(Address(EAX, 0), EAX);
1095 __ Bind(&donetest3);
1096
1097 Label donetest4;
1098 __ movl(EBX, Immediate(4));
1099 __ testl(EBX, Immediate(4));
1100 __ j(NOT_EQUAL, &donetest4);
1101 // Be sure to skip this crashing code.
1102 __ movl(EAX, Immediate(0));
1103 __ movl(Address(EAX, 0), EAX);
1104 __ Bind(&donetest4);
1105
1106 Label donetest5;
1107 __ movl(EBX, Immediate(0xff));
1108 __ testl(EBX, Immediate(0xff));
1109 __ j(NOT_EQUAL, &donetest5);
1110 // Be sure to skip this crashing code.
1111 __ movl(EAX, Immediate(0));
1112 __ movl(Address(EAX, 0), EAX);
1113 __ Bind(&donetest5);
1114
1115 __ movl(EAX, Immediate(0));
1116 __ popl(EBX); // restore EBX.
1117 __ ret();
1118}
1119
1120ASSEMBLER_TEST_RUN(LogicalTest, test) {
1121 typedef int (*LogicalTestCode)();
1122 EXPECT_EQ(0, reinterpret_cast<LogicalTestCode>(test->entry())());
1123 EXPECT_DISASSEMBLY(
1124 "push ebx\n"
1125 "mov eax,4\n"
1126 "mov ecx,2\n"
1127 "test eax,ecx\n"
1128 "jz +13\n"
1129 "mov eax,0\n"
1130 "mov [eax],eax\n"
1131 "mov edx,4\n"
1132 "mov ecx,4\n"
1133 "test edx,ecx\n"
1134 "jnz +13\n"
1135 "mov eax,0\n"
1136 "mov [eax],eax\n"
1137 "mov eax,0\n"
1138 "test al,0\n"
1139 "jz +13\n"
1140 "mov eax,0\n"
1141 "mov [eax],eax\n"
1142 "mov ebx,4\n"
1143 "testb ebx,4\n"
1144 "jnz +13\n"
1145 "mov eax,0\n"
1146 "mov [eax],eax\n"
1147 "mov ebx,0xff\n"
1148 "testb ebx,0xff\n"
1149 "jnz +13\n"
1150 "mov eax,0\n"
1151 "mov [eax],eax\n"
1152 "mov eax,0\n"
1153 "pop ebx\n"
1154 "ret\n");
1155}
1156
1157ASSEMBLER_TEST_GENERATE(CompareSwapEQ, assembler) {
1158 __ movl(EAX, Immediate(0));
1159 __ pushl(EAX);
1160 __ movl(EAX, Immediate(4));
1161 __ movl(ECX, Immediate(0));
1162 __ movl(Address(ESP, 0), EAX);
1163 __ LockCmpxchgl(Address(ESP, 0), ECX);
1164 __ popl(EAX);
1165 __ ret();
1166}
1167
1168ASSEMBLER_TEST_RUN(CompareSwapEQ, test) {
1169 typedef int (*CompareSwapEQCode)();
1170 EXPECT_EQ(0, reinterpret_cast<CompareSwapEQCode>(test->entry())());
1171 EXPECT_DISASSEMBLY(
1172 "mov eax,0\n"
1173 "push eax\n"
1174 "mov eax,4\n"
1175 "mov ecx,0\n"
1176 "mov [esp],eax\n"
1177 "lock cmpxchg ecx,[esp]\n"
1178 "pop eax\n"
1179 "ret\n");
1180}
1181
1182ASSEMBLER_TEST_GENERATE(CompareSwapNEQ, assembler) {
1183 __ movl(EAX, Immediate(0));
1184 __ pushl(EAX);
1185 __ movl(EAX, Immediate(2));
1186 __ movl(ECX, Immediate(4));
1187 __ movl(Address(ESP, 0), ECX);
1188 __ LockCmpxchgl(Address(ESP, 0), ECX);
1189 __ popl(EAX);
1190 __ ret();
1191}
1192
1193ASSEMBLER_TEST_RUN(CompareSwapNEQ, test) {
1194 typedef int (*CompareSwapNEQCode)();
1195 EXPECT_EQ(4, reinterpret_cast<CompareSwapNEQCode>(test->entry())());
1196 EXPECT_DISASSEMBLY(
1197 "mov eax,0\n"
1198 "push eax\n"
1199 "mov eax,2\n"
1200 "mov ecx,4\n"
1201 "mov [esp],ecx\n"
1202 "lock cmpxchg ecx,[esp]\n"
1203 "pop eax\n"
1204 "ret\n");
1205}
1206
1207ASSEMBLER_TEST_GENERATE(SignedDivide, assembler) {
1208 __ movl(EAX, Immediate(-87));
1209 __ movl(EDX, Immediate(123));
1210 __ cdq();
1211 __ movl(ECX, Immediate(42));
1212 __ idivl(ECX);
1213 __ ret();
1214}
1215
1216ASSEMBLER_TEST_RUN(SignedDivide, test) {
1217 typedef int (*SignedDivide)();
1218 EXPECT_EQ(-87 / 42, reinterpret_cast<SignedDivide>(test->entry())());
1219 EXPECT_DISASSEMBLY(
1220 "mov eax,0xffffffa9\n"
1221 "mov edx,0x7b\n"
1222 "cdq\n"
1223 "mov ecx,0x2a\n"
1224 "idiv (eax,edx),ecx\n"
1225 "ret\n");
1226}
1227
1228ASSEMBLER_TEST_GENERATE(UnsignedDivide, assembler) {
1229 __ movl(EAX, Immediate(0xffffffbe));
1230 __ movl(EDX, Immediate(0x41));
1231 __ movl(ECX, Immediate(-1));
1232 __ divl(ECX);
1233 __ ret();
1234}
1235
1236ASSEMBLER_TEST_RUN(UnsignedDivide, test) {
1237 typedef int (*UnsignedDivide)();
1238 EXPECT_EQ(0x42, reinterpret_cast<UnsignedDivide>(test->entry())());
1239 EXPECT_DISASSEMBLY(
1240 "mov eax,0xffffffbe\n"
1241 "mov edx,0x41\n"
1242 "mov ecx,0xffffffff\n"
1243 "div (eax,edx),ecx\n"
1244 "ret\n");
1245}
1246
1247ASSEMBLER_TEST_GENERATE(Exchange, assembler) {
1248 __ movl(EAX, Immediate(123456789));
1249 __ movl(EDX, Immediate(987654321));
1250 __ xchgl(EAX, EDX);
1251 __ subl(EAX, EDX);
1252 __ ret();
1253}
1254
1255ASSEMBLER_TEST_RUN(Exchange, test) {
1256 typedef int (*Exchange)();
1257 EXPECT_EQ(987654321 - 123456789, reinterpret_cast<Exchange>(test->entry())());
1258 EXPECT_DISASSEMBLY(
1259 "mov eax,0x075bcd15\n"
1260 "mov edx,0x3ade68b1\n"
1261 "xchg eax,edx\n"
1262 "sub eax,edx\n"
1263 "ret\n");
1264}
1265
1266static int ComputeStackSpaceReservation(int needed, int fixed) {
1267 return (OS::ActivationFrameAlignment() > 1)
1268 ? Utils::RoundUp(needed + fixed, OS::ActivationFrameAlignment()) -
1269 fixed
1270 : needed;
1271}
1272
1273static int LeafReturn42() {
1274 return 42;
1275}
1276
1277static int LeafReturnArgument(int x) {
1278 return x + 87;
1279}
1280
1281ASSEMBLER_TEST_GENERATE(CallSimpleLeaf, assembler) {
1282 ExternalLabel call1(reinterpret_cast<uword>(LeafReturn42));
1283 ExternalLabel call2(reinterpret_cast<uword>(LeafReturnArgument));
1284 int space = ComputeStackSpaceReservation(0, 4);
1285 __ AddImmediate(ESP, Immediate(-space));
1286 __ call(&call1);
1287 __ AddImmediate(ESP, Immediate(space));
1288 space = ComputeStackSpaceReservation(4, 4);
1289 __ AddImmediate(ESP, Immediate(-space));
1290 __ movl(Address(ESP, 0), EAX);
1291 __ call(&call2);
1292 __ AddImmediate(ESP, Immediate(space));
1293 __ ret();
1294}
1295
1296ASSEMBLER_TEST_RUN(CallSimpleLeaf, test) {
1297 typedef int (*CallSimpleLeafCode)();
1298 EXPECT_EQ(42 + 87, reinterpret_cast<CallSimpleLeafCode>(test->entry())());
1299}
1300
1301ASSEMBLER_TEST_GENERATE(JumpSimpleLeaf, assembler) {
1302 ExternalLabel call1(reinterpret_cast<uword>(LeafReturn42));
1303 Label L;
1304 int space = ComputeStackSpaceReservation(0, 4);
1305 __ AddImmediate(ESP, Immediate(-space));
1306 __ call(&L);
1307 __ AddImmediate(ESP, Immediate(space));
1308 __ ret();
1309 __ Bind(&L);
1310 __ jmp(&call1);
1311}
1312
1313ASSEMBLER_TEST_RUN(JumpSimpleLeaf, test) {
1314 typedef int (*JumpSimpleLeafCode)();
1315 EXPECT_EQ(42, reinterpret_cast<JumpSimpleLeafCode>(test->entry())());
1316}
1317
1318ASSEMBLER_TEST_GENERATE(JumpConditionalSimpleLeaf, assembler) {
1319 ExternalLabel call1(reinterpret_cast<uword>(LeafReturn42));
1320 Label L;
1321 int space = ComputeStackSpaceReservation(0, 4);
1322 __ AddImmediate(ESP, Immediate(-space));
1323 __ call(&L);
1324 __ AddImmediate(ESP, Immediate(space));
1325 __ ret();
1326 __ Bind(&L);
1327 __ cmpl(EAX, EAX);
1328 __ j(EQUAL, &call1);
1329 __ int3();
1330}
1331
1332ASSEMBLER_TEST_RUN(JumpConditionalSimpleLeaf, test) {
1333 typedef int (*JumpConditionalSimpleLeafCode)();
1334 EXPECT_EQ(42,
1335 reinterpret_cast<JumpConditionalSimpleLeafCode>(test->entry())());
1336}
1337
1338ASSEMBLER_TEST_GENERATE(SingleFPMoves, assembler) {
1339 __ movl(EAX, Immediate(bit_cast<int32_t, float>(234.0f)));
1340 __ movd(XMM0, EAX);
1341 __ movss(XMM1, XMM0);
1342 __ movss(XMM2, XMM1);
1343 __ movss(XMM3, XMM2);
1344 __ movss(XMM4, XMM3);
1345 __ movss(XMM5, XMM4);
1346 __ movss(XMM6, XMM5);
1347 __ movss(XMM7, XMM6);
1348 __ pushl(EAX);
1349 __ movl(Address(ESP, 0), Immediate(0));
1350 __ movss(Address(ESP, 0), XMM7);
1351 __ flds(Address(ESP, 0));
1352 __ popl(EAX);
1353 __ ret();
1354}
1355
1356ASSEMBLER_TEST_RUN(SingleFPMoves, test) {
1357 typedef float (*SingleFPMovesCode)();
1358 float res = reinterpret_cast<SingleFPMovesCode>(test->entry())();
1359 EXPECT_EQ(234.0f, res);
1360 EXPECT_DISASSEMBLY(
1361 "mov eax,0x436a0000\n"
1362 "movd xmm0,eax\n"
1363 "movss ecx,xmm0\n"
1364 "movss edx,xmm1\n"
1365 "movss ebx,xmm2\n"
1366 "movss esp,xmm3\n"
1367 "movss ebp,xmm4\n"
1368 "movss esi,xmm5\n"
1369 "movss edi,xmm6\n"
1370 "push eax\n"
1371 "mov [esp],0\n"
1372 "movss [esp],xmm7\n"
1373 "fld_s [esp]\n"
1374 "pop eax\n"
1375 "ret\n");
1376}
1377
1378ASSEMBLER_TEST_GENERATE(SingleFPMoves2, assembler) {
1379 __ pushl(EBX); // preserve EBX.
1380 __ pushl(ECX); // preserve ECX.
1381 __ movl(EBX, Immediate(bit_cast<int32_t, float>(234.0f)));
1382 __ movd(XMM0, EBX);
1383 __ movss(XMM1, XMM0);
1384 __ movd(ECX, XMM1);
1385 __ pushl(ECX);
1386 __ flds(Address(ESP, 0));
1387 __ popl(EAX);
1388 __ popl(ECX);
1389 __ popl(EBX);
1390 __ ret();
1391}
1392
1393ASSEMBLER_TEST_RUN(SingleFPMoves2, test) {
1394 typedef float (*SingleFPMoves2Code)();
1395 float res = reinterpret_cast<SingleFPMoves2Code>(test->entry())();
1396 EXPECT_EQ(234.0f, res);
1397 EXPECT_DISASSEMBLY(
1398 "push ebx\n"
1399 "push ecx\n"
1400 "mov ebx,0x436a0000\n"
1401 "movd xmm0,ebx\n"
1402 "movss ecx,xmm0\n"
1403 "movd ecx,xmm1\n"
1404 "push ecx\n"
1405 "fld_s [esp]\n"
1406 "pop eax\n"
1407 "pop ecx\n"
1408 "pop ebx\n"
1409 "ret\n");
1410}
1411
1412ASSEMBLER_TEST_GENERATE(SingleFPUStackMoves, assembler) {
1413 __ movl(EAX, Immediate(1131020288)); // 234.0f
1414 __ pushl(EAX);
1415 __ flds(Address(ESP, 0));
1416 __ xorl(ECX, ECX);
1417 __ pushl(ECX);
1418 __ fstps(Address(ESP, 0));
1419 __ popl(EAX);
1420 __ popl(ECX);
1421 __ ret();
1422}
1423
1424ASSEMBLER_TEST_RUN(SingleFPUStackMoves, test) {
1425 typedef int (*SingleFPUStackMovesCode)();
1426 int res = reinterpret_cast<SingleFPUStackMovesCode>(test->entry())();
1427 EXPECT_EQ(234.0f, (bit_cast<float, int>(res)));
1428 EXPECT_DISASSEMBLY(
1429 "mov eax,0x436a0000\n"
1430 "push eax\n"
1431 "fld_s [esp]\n"
1432 "xor ecx,ecx\n"
1433 "push ecx\n"
1434 "fstp_s [esp]\n"
1435 "pop eax\n"
1436 "pop ecx\n"
1437 "ret\n");
1438}
1439
1440ASSEMBLER_TEST_GENERATE(SingleFPOperations, assembler) {
1441 __ movl(EAX, Immediate(bit_cast<int32_t, float>(12.3f)));
1442 __ movd(XMM0, EAX);
1443 __ movl(EAX, Immediate(bit_cast<int32_t, float>(3.4f)));
1444 __ movd(XMM1, EAX);
1445 __ addss(XMM0, XMM1); // 15.7f
1446 __ mulss(XMM0, XMM1); // 53.38f
1447 __ subss(XMM0, XMM1); // 49.98f
1448 __ divss(XMM0, XMM1); // 14.7f
1449 __ pushl(EAX);
1450 __ movss(Address(ESP, 0), XMM0);
1451 __ flds(Address(ESP, 0));
1452 __ popl(EAX);
1453 __ ret();
1454}
1455
1456ASSEMBLER_TEST_RUN(SingleFPOperations, test) {
1457 typedef float (*SingleFPOperationsCode)();
1458 float res = reinterpret_cast<SingleFPOperationsCode>(test->entry())();
1459 EXPECT_FLOAT_EQ(14.7f, res, 0.001f);
1460 EXPECT_DISASSEMBLY(
1461 "mov eax,0x4144cccd\n"
1462 "movd xmm0,eax\n"
1463 "mov eax,0x4059999a\n"
1464 "movd xmm1,eax\n"
1465 "addss xmm0,xmm1\n"
1466 "mulss xmm0,xmm1\n"
1467 "subss xmm0,xmm1\n"
1468 "divss xmm0,xmm1\n"
1469 "push eax\n"
1470 "movss [esp],xmm0\n"
1471 "fld_s [esp]\n"
1472 "pop eax\n"
1473 "ret\n");
1474}
1475
1476ASSEMBLER_TEST_GENERATE(PackedFPOperations, assembler) {
1477 __ movl(EAX, Immediate(bit_cast<int32_t, float>(12.3f)));
1478 __ movd(XMM0, EAX);
1479 __ shufps(XMM0, XMM0, Immediate(0x0));
1480 __ movl(EAX, Immediate(bit_cast<int32_t, float>(3.4f)));
1481 __ movd(XMM1, EAX);
1482 __ shufps(XMM1, XMM1, Immediate(0x0));
1483 __ addps(XMM0, XMM1); // 15.7f
1484 __ mulps(XMM0, XMM1); // 53.38f
1485 __ subps(XMM0, XMM1); // 49.98f
1486 __ divps(XMM0, XMM1); // 14.7f
1487 __ shufps(XMM0, XMM0, Immediate(0x55)); // Copy second lane into all 4 lanes.
1488 __ pushl(EAX);
1489 // Copy the low lane at ESP.
1490 __ movss(Address(ESP, 0), XMM0);
1491 __ flds(Address(ESP, 0));
1492 __ popl(EAX);
1493 __ ret();
1494}
1495
1496ASSEMBLER_TEST_RUN(PackedFPOperations, test) {
1497 typedef float (*PackedFPOperationsCode)();
1498 float res = reinterpret_cast<PackedFPOperationsCode>(test->entry())();
1499 EXPECT_FLOAT_EQ(14.7f, res, 0.001f);
1500 EXPECT_DISASSEMBLY(
1501 "mov eax,0x4144cccd\n"
1502 "movd xmm0,eax\n"
1503 "shufps xmm0,xmm0 [0]\n"
1504 "mov eax,0x4059999a\n"
1505 "movd xmm1,eax\n"
1506 "shufps xmm1,xmm1 [0]\n"
1507 "addps xmm0,xmm1\n"
1508 "mulps xmm0,xmm1\n"
1509 "subps xmm0,xmm1\n"
1510 "divps xmm0,xmm1\n"
1511 "shufps xmm0,xmm0 [55]\n"
1512 "push eax\n"
1513 "movss [esp],xmm0\n"
1514 "fld_s [esp]\n"
1515 "pop eax\n"
1516 "ret\n");
1517}
1518
1519ASSEMBLER_TEST_GENERATE(PackedIntOperations, assembler) {
1520 __ movl(EAX, Immediate(0x2));
1521 __ movd(XMM0, EAX);
1522 __ shufps(XMM0, XMM0, Immediate(0x0));
1523 __ movl(EAX, Immediate(0x1));
1524 __ movd(XMM1, EAX);
1525 __ shufps(XMM1, XMM1, Immediate(0x0));
1526 __ addpl(XMM0, XMM1); // 0x3
1527 __ addpl(XMM0, XMM0); // 0x6
1528 __ subpl(XMM0, XMM1); // 0x5
1529 // Copy the low lane at ESP.
1530 __ pushl(EAX);
1531 __ movss(Address(ESP, 0), XMM0);
1532 __ popl(EAX);
1533 __ ret();
1534}
1535
1536ASSEMBLER_TEST_RUN(PackedIntOperations, test) {
1537 typedef uint32_t (*PackedIntOperationsCode)();
1538 uint32_t res = reinterpret_cast<PackedIntOperationsCode>(test->entry())();
1539 EXPECT_EQ(static_cast<uword>(0x5), res);
1540 EXPECT_DISASSEMBLY(
1541 "mov eax,2\n"
1542 "movd xmm0,eax\n"
1543 "shufps xmm0,xmm0 [0]\n"
1544 "mov eax,1\n"
1545 "movd xmm1,eax\n"
1546 "shufps xmm1,xmm1 [0]\n"
1547 "paddd xmm0,xmm1\n"
1548 "paddd xmm0,xmm0\n"
1549 "psubd xmm0,xmm1\n"
1550 "push eax\n"
1551 "movss [esp],xmm0\n"
1552 "pop eax\n"
1553 "ret\n");
1554}
1555
1556ASSEMBLER_TEST_GENERATE(PackedFPOperations2, assembler) {
1557 __ movl(EAX, Immediate(bit_cast<int32_t, float>(4.0f)));
1558 __ movd(XMM0, EAX);
1559 __ shufps(XMM0, XMM0, Immediate(0x0));
1560
1561 __ movaps(XMM1, XMM0); // Copy XMM0
1562 __ reciprocalps(XMM1); // 0.25
1563 __ sqrtps(XMM1); // 0.5
1564 __ rsqrtps(XMM0); // ~0.5
1565 __ subps(XMM0, XMM1); // ~0.0
1566 __ shufps(XMM0, XMM0, Immediate(0x00)); // Copy second lane into all 4 lanes.
1567 __ pushl(EAX);
1568 // Copy the low lane at ESP.
1569 __ movss(Address(ESP, 0), XMM0);
1570 __ flds(Address(ESP, 0));
1571 __ popl(EAX);
1572 __ ret();
1573}
1574
1575ASSEMBLER_TEST_RUN(PackedFPOperations2, test) {
1576 typedef float (*PackedFPOperations2Code)();
1577 float res = reinterpret_cast<PackedFPOperations2Code>(test->entry())();
1578 EXPECT_FLOAT_EQ(0.0f, res, 0.001f);
1579 EXPECT_DISASSEMBLY(
1580 "mov eax,0x40800000\n"
1581 "movd xmm0,eax\n"
1582 "shufps xmm0,xmm0 [0]\n"
1583 "movaps xmm1,xmm0\n"
1584 "rcpps xmm1,xmm1\n"
1585 "sqrtps xmm1,xmm1\n"
1586 "rsqrtps xmm0,xmm0\n"
1587 "subps xmm0,xmm1\n"
1588 "shufps xmm0,xmm0 [0]\n"
1589 "push eax\n"
1590 "movss [esp],xmm0\n"
1591 "fld_s [esp]\n"
1592 "pop eax\n"
1593 "ret\n");
1594}
1595
1596ASSEMBLER_TEST_GENERATE(PackedCompareEQ, assembler) {
1597 __ set1ps(XMM0, EAX, Immediate(bit_cast<int32_t, float>(2.0f)));
1598 __ set1ps(XMM1, EAX, Immediate(bit_cast<int32_t, float>(4.0f)));
1599 __ cmppseq(XMM0, XMM1);
1600 // Copy the low lane at ESP.
1601 __ pushl(EAX);
1602 __ movss(Address(ESP, 0), XMM0);
1603 __ flds(Address(ESP, 0));
1604 __ popl(EAX);
1605 __ ret();
1606}
1607
1608ASSEMBLER_TEST_RUN(PackedCompareEQ, test) {
1609 typedef uint32_t (*PackedCompareEQCode)();
1610 uint32_t res = reinterpret_cast<PackedCompareEQCode>(test->entry())();
1611 EXPECT_EQ(static_cast<uword>(0x0), res);
1612 EXPECT_DISASSEMBLY(
1613 "mov eax,0x40000000\n"
1614 "movd xmm0,eax\n"
1615 "shufps xmm0,xmm0 [0]\n"
1616 "mov eax,0x40800000\n"
1617 "movd xmm1,eax\n"
1618 "shufps xmm1,xmm1 [0]\n"
1619 "cmpps xmm0,xmm1 [eq]\n"
1620 "push eax\n"
1621 "movss [esp],xmm0\n"
1622 "fld_s [esp]\n"
1623 "pop eax\n"
1624 "ret\n");
1625}
1626
1627ASSEMBLER_TEST_GENERATE(PackedCompareNEQ, assembler) {
1628 __ set1ps(XMM0, EAX, Immediate(bit_cast<int32_t, float>(2.0f)));
1629 __ set1ps(XMM1, EAX, Immediate(bit_cast<int32_t, float>(4.0f)));
1630 __ cmppsneq(XMM0, XMM1);
1631 // Copy the low lane at ESP.
1632 __ pushl(EAX);
1633 __ movss(Address(ESP, 0), XMM0);
1634 __ flds(Address(ESP, 0));
1635 __ popl(EAX);
1636 __ ret();
1637}
1638
1639ASSEMBLER_TEST_RUN(PackedCompareNEQ, test) {
1640 typedef uint32_t (*PackedCompareNEQCode)();
1641 uint32_t res = reinterpret_cast<PackedCompareNEQCode>(test->entry())();
1642 EXPECT_EQ(static_cast<uword>(0xFFFFFFFF), res);
1643 EXPECT_DISASSEMBLY(
1644 "mov eax,0x40000000\n"
1645 "movd xmm0,eax\n"
1646 "shufps xmm0,xmm0 [0]\n"
1647 "mov eax,0x40800000\n"
1648 "movd xmm1,eax\n"
1649 "shufps xmm1,xmm1 [0]\n"
1650 "cmpps xmm0,xmm1 [neq]\n"
1651 "push eax\n"
1652 "movss [esp],xmm0\n"
1653 "fld_s [esp]\n"
1654 "pop eax\n"
1655 "ret\n");
1656}
1657
1658ASSEMBLER_TEST_GENERATE(PackedCompareLT, assembler) {
1659 __ set1ps(XMM0, EAX, Immediate(bit_cast<int32_t, float>(2.0f)));
1660 __ set1ps(XMM1, EAX, Immediate(bit_cast<int32_t, float>(4.0f)));
1661 __ cmppslt(XMM0, XMM1);
1662 // Copy the low lane at ESP.
1663 __ pushl(EAX);
1664 __ movss(Address(ESP, 0), XMM0);
1665 __ flds(Address(ESP, 0));
1666 __ popl(EAX);
1667 __ ret();
1668}
1669
1670ASSEMBLER_TEST_RUN(PackedCompareLT, test) {
1671 typedef uint32_t (*PackedCompareLTCode)();
1672 uint32_t res = reinterpret_cast<PackedCompareLTCode>(test->entry())();
1673 EXPECT_EQ(static_cast<uword>(0xFFFFFFFF), res);
1674 EXPECT_DISASSEMBLY(
1675 "mov eax,0x40000000\n"
1676 "movd xmm0,eax\n"
1677 "shufps xmm0,xmm0 [0]\n"
1678 "mov eax,0x40800000\n"
1679 "movd xmm1,eax\n"
1680 "shufps xmm1,xmm1 [0]\n"
1681 "cmpps xmm0,xmm1 [lt]\n"
1682 "push eax\n"
1683 "movss [esp],xmm0\n"
1684 "fld_s [esp]\n"
1685 "pop eax\n"
1686 "ret\n");
1687}
1688
1689ASSEMBLER_TEST_GENERATE(PackedCompareLE, assembler) {
1690 __ set1ps(XMM0, EAX, Immediate(bit_cast<int32_t, float>(2.0f)));
1691 __ set1ps(XMM1, EAX, Immediate(bit_cast<int32_t, float>(4.0f)));
1692 __ cmppsle(XMM0, XMM1);
1693 // Copy the low lane at ESP.
1694 __ pushl(EAX);
1695 __ movss(Address(ESP, 0), XMM0);
1696 __ flds(Address(ESP, 0));
1697 __ popl(EAX);
1698 __ ret();
1699}
1700
1701ASSEMBLER_TEST_RUN(PackedCompareLE, test) {
1702 typedef uint32_t (*PackedCompareLECode)();
1703 uint32_t res = reinterpret_cast<PackedCompareLECode>(test->entry())();
1704 EXPECT_EQ(static_cast<uword>(0xFFFFFFFF), res);
1705 EXPECT_DISASSEMBLY(
1706 "mov eax,0x40000000\n"
1707 "movd xmm0,eax\n"
1708 "shufps xmm0,xmm0 [0]\n"
1709 "mov eax,0x40800000\n"
1710 "movd xmm1,eax\n"
1711 "shufps xmm1,xmm1 [0]\n"
1712 "cmpps xmm0,xmm1 [le]\n"
1713 "push eax\n"
1714 "movss [esp],xmm0\n"
1715 "fld_s [esp]\n"
1716 "pop eax\n"
1717 "ret\n");
1718}
1719
1720ASSEMBLER_TEST_GENERATE(PackedCompareNLT, assembler) {
1721 __ set1ps(XMM0, EAX, Immediate(bit_cast<int32_t, float>(2.0f)));
1722 __ set1ps(XMM1, EAX, Immediate(bit_cast<int32_t, float>(4.0f)));
1723 __ cmppsnlt(XMM0, XMM1);
1724 // Copy the low lane at ESP.
1725 __ pushl(EAX);
1726 __ movss(Address(ESP, 0), XMM0);
1727 __ flds(Address(ESP, 0));
1728 __ popl(EAX);
1729 __ ret();
1730}
1731
1732ASSEMBLER_TEST_RUN(PackedCompareNLT, test) {
1733 typedef uint32_t (*PackedCompareNLTCode)();
1734 uint32_t res = reinterpret_cast<PackedCompareNLTCode>(test->entry())();
1735 EXPECT_EQ(static_cast<uword>(0x0), res);
1736 EXPECT_DISASSEMBLY(
1737 "mov eax,0x40000000\n"
1738 "movd xmm0,eax\n"
1739 "shufps xmm0,xmm0 [0]\n"
1740 "mov eax,0x40800000\n"
1741 "movd xmm1,eax\n"
1742 "shufps xmm1,xmm1 [0]\n"
1743 "cmpps xmm0,xmm1 [nlt]\n"
1744 "push eax\n"
1745 "movss [esp],xmm0\n"
1746 "fld_s [esp]\n"
1747 "pop eax\n"
1748 "ret\n");
1749}
1750
1751ASSEMBLER_TEST_GENERATE(PackedCompareNLE, assembler) {
1752 __ set1ps(XMM0, EAX, Immediate(bit_cast<int32_t, float>(2.0f)));
1753 __ set1ps(XMM1, EAX, Immediate(bit_cast<int32_t, float>(4.0f)));
1754 __ cmppsnle(XMM0, XMM1);
1755 // Copy the low lane at ESP.
1756 __ pushl(EAX);
1757 __ movss(Address(ESP, 0), XMM0);
1758 __ flds(Address(ESP, 0));
1759 __ popl(EAX);
1760 __ ret();
1761}
1762
1763ASSEMBLER_TEST_RUN(PackedCompareNLE, test) {
1764 typedef uint32_t (*PackedCompareNLECode)();
1765 uint32_t res = reinterpret_cast<PackedCompareNLECode>(test->entry())();
1766 EXPECT_EQ(static_cast<uword>(0x0), res);
1767 EXPECT_DISASSEMBLY(
1768 "mov eax,0x40000000\n"
1769 "movd xmm0,eax\n"
1770 "shufps xmm0,xmm0 [0]\n"
1771 "mov eax,0x40800000\n"
1772 "movd xmm1,eax\n"
1773 "shufps xmm1,xmm1 [0]\n"
1774 "cmpps xmm0,xmm1 [nle]\n"
1775 "push eax\n"
1776 "movss [esp],xmm0\n"
1777 "fld_s [esp]\n"
1778 "pop eax\n"
1779 "ret\n");
1780}
1781
1782ASSEMBLER_TEST_GENERATE(PackedNegate, assembler) {
1783 __ movl(EAX, Immediate(bit_cast<int32_t, float>(12.3f)));
1784 __ movd(XMM0, EAX);
1785 __ shufps(XMM0, XMM0, Immediate(0x0));
1786 __ negateps(XMM0);
1787 __ shufps(XMM0, XMM0, Immediate(0xAA)); // Copy third lane into all 4 lanes.
1788 __ pushl(EAX);
1789 // Copy the low lane at ESP.
1790 __ movss(Address(ESP, 0), XMM0);
1791 __ flds(Address(ESP, 0));
1792 __ popl(EAX);
1793 __ ret();
1794}
1795
1796ASSEMBLER_TEST_RUN(PackedNegate, test) {
1797 typedef float (*PackedNegateCode)();
1798 float res = reinterpret_cast<PackedNegateCode>(test->entry())();
1799 EXPECT_FLOAT_EQ(-12.3f, res, 0.001f);
1800 EXPECT_DISASSEMBLY(
1801 "mov eax,0x4144cccd\n"
1802 "movd xmm0,eax\n"
1803 "shufps xmm0,xmm0 [0]\n"
1804 "xorps xmm0,[0x........]\n"
1805 "shufps xmm0,xmm0 [aa]\n"
1806 "push eax\n"
1807 "movss [esp],xmm0\n"
1808 "fld_s [esp]\n"
1809 "pop eax\n"
1810 "ret\n");
1811}
1812
1813ASSEMBLER_TEST_GENERATE(PackedAbsolute, assembler) {
1814 __ movl(EAX, Immediate(bit_cast<int32_t, float>(-15.3f)));
1815 __ movd(XMM0, EAX);
1816 __ shufps(XMM0, XMM0, Immediate(0x0));
1817 __ absps(XMM0);
1818 __ shufps(XMM0, XMM0, Immediate(0xAA)); // Copy third lane into all 4 lanes.
1819 // Copy the low lane at ESP.
1820 __ pushl(EAX);
1821 __ movss(Address(ESP, 0), XMM0);
1822 __ flds(Address(ESP, 0));
1823 __ popl(EAX);
1824 __ ret();
1825}
1826
1827ASSEMBLER_TEST_RUN(PackedAbsolute, test) {
1828 typedef float (*PackedAbsoluteCode)();
1829 float res = reinterpret_cast<PackedAbsoluteCode>(test->entry())();
1830 EXPECT_FLOAT_EQ(15.3f, res, 0.001f);
1831 EXPECT_DISASSEMBLY(
1832 "mov eax,0xc174cccd\n"
1833 "movd xmm0,eax\n"
1834 "shufps xmm0,xmm0 [0]\n"
1835 "andps xmm0,[0x........]\n"
1836 "shufps xmm0,xmm0 [aa]\n"
1837 "push eax\n"
1838 "movss [esp],xmm0\n"
1839 "fld_s [esp]\n"
1840 "pop eax\n"
1841 "ret\n");
1842}
1843
1844ASSEMBLER_TEST_GENERATE(PackedSetWZero, assembler) {
1845 __ set1ps(XMM0, EAX, Immediate(bit_cast<int32_t, float>(12.3f)));
1846 __ zerowps(XMM0);
1847 __ shufps(XMM0, XMM0, Immediate(0xFF)); // Copy the W lane which is now 0.0.
1848 // Copy the low lane at ESP.
1849 __ pushl(EAX);
1850 __ movss(Address(ESP, 0), XMM0);
1851 __ flds(Address(ESP, 0));
1852 __ popl(EAX);
1853 __ ret();
1854}
1855
1856ASSEMBLER_TEST_RUN(PackedSetWZero, test) {
1857 typedef float (*PackedSetWZeroCode)();
1858 float res = reinterpret_cast<PackedSetWZeroCode>(test->entry())();
1859 EXPECT_FLOAT_EQ(0.0f, res, 0.001f);
1860 EXPECT_DISASSEMBLY(
1861 "mov eax,0x4144cccd\n"
1862 "movd xmm0,eax\n"
1863 "shufps xmm0,xmm0 [0]\n"
1864 "andps xmm0,[0x........]\n"
1865 "shufps xmm0,xmm0 [ff]\n"
1866 "push eax\n"
1867 "movss [esp],xmm0\n"
1868 "fld_s [esp]\n"
1869 "pop eax\n"
1870 "ret\n");
1871}
1872
1873ASSEMBLER_TEST_GENERATE(PackedMin, assembler) {
1874 __ set1ps(XMM0, EAX, Immediate(bit_cast<int32_t, float>(2.0f)));
1875 __ set1ps(XMM1, EAX, Immediate(bit_cast<int32_t, float>(4.0f)));
1876 __ minps(XMM0, XMM1);
1877 // Copy the low lane at ESP.
1878 __ pushl(EAX);
1879 __ movss(Address(ESP, 0), XMM0);
1880 __ flds(Address(ESP, 0));
1881 __ popl(EAX);
1882 __ ret();
1883}
1884
1885ASSEMBLER_TEST_RUN(PackedMin, test) {
1886 typedef float (*PackedMinCode)();
1887 float res = reinterpret_cast<PackedMinCode>(test->entry())();
1888 EXPECT_FLOAT_EQ(2.0f, res, 0.001f);
1889 EXPECT_DISASSEMBLY(
1890 "mov eax,0x40000000\n"
1891 "movd xmm0,eax\n"
1892 "shufps xmm0,xmm0 [0]\n"
1893 "mov eax,0x40800000\n"
1894 "movd xmm1,eax\n"
1895 "shufps xmm1,xmm1 [0]\n"
1896 "minps xmm0,xmm1\n"
1897 "push eax\n"
1898 "movss [esp],xmm0\n"
1899 "fld_s [esp]\n"
1900 "pop eax\n"
1901 "ret\n");
1902}
1903
1904ASSEMBLER_TEST_GENERATE(PackedMax, assembler) {
1905 __ set1ps(XMM0, EAX, Immediate(bit_cast<int32_t, float>(2.0f)));
1906 __ set1ps(XMM1, EAX, Immediate(bit_cast<int32_t, float>(4.0f)));
1907 __ maxps(XMM0, XMM1);
1908 // Copy the low lane at ESP.
1909 __ pushl(EAX);
1910 __ movss(Address(ESP, 0), XMM0);
1911 __ flds(Address(ESP, 0));
1912 __ popl(EAX);
1913 __ ret();
1914}
1915
1916ASSEMBLER_TEST_RUN(PackedMax, test) {
1917 typedef float (*PackedMaxCode)();
1918 float res = reinterpret_cast<PackedMaxCode>(test->entry())();
1919 EXPECT_FLOAT_EQ(4.0f, res, 0.001f);
1920 EXPECT_DISASSEMBLY(
1921 "mov eax,0x40000000\n"
1922 "movd xmm0,eax\n"
1923 "shufps xmm0,xmm0 [0]\n"
1924 "mov eax,0x40800000\n"
1925 "movd xmm1,eax\n"
1926 "shufps xmm1,xmm1 [0]\n"
1927 "maxps xmm0,xmm1\n"
1928 "push eax\n"
1929 "movss [esp],xmm0\n"
1930 "fld_s [esp]\n"
1931 "pop eax\n"
1932 "ret\n");
1933}
1934
1935ASSEMBLER_TEST_GENERATE(PackedLogicalOr, assembler) {
1936 static const struct ALIGN16 {
1937 uint32_t a;
1938 uint32_t b;
1939 uint32_t c;
1940 uint32_t d;
1941 } constant1 = {0xF0F0F0F0, 0xF0F0F0F0, 0xF0F0F0F0, 0xF0F0F0F0};
1942 static const struct ALIGN16 {
1943 uint32_t a;
1944 uint32_t b;
1945 uint32_t c;
1946 uint32_t d;
1947 } constant2 = {0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F};
1948 __ movups(XMM0, Address::Absolute(reinterpret_cast<uword>(&constant1)));
1949 __ movups(XMM1, Address::Absolute(reinterpret_cast<uword>(&constant2)));
1950 __ orps(XMM0, XMM1);
1951 // Copy the low lane at ESP.
1952 __ pushl(EAX);
1953 __ movss(Address(ESP, 0), XMM0);
1954 __ flds(Address(ESP, 0));
1955 __ popl(EAX);
1956 __ ret();
1957}
1958
1959ASSEMBLER_TEST_RUN(PackedLogicalOr, test) {
1960 typedef uint32_t (*PackedLogicalOrCode)();
1961 uint32_t res = reinterpret_cast<PackedLogicalOrCode>(test->entry())();
1962 EXPECT_EQ(0xFFFFFFFF, res);
1963 EXPECT_DISASSEMBLY(
1964 "movups xmm0,[0x........]\n"
1965 "movups xmm1,[0x........]\n"
1966 "orps xmm0,xmm1\n"
1967 "push eax\n"
1968 "movss [esp],xmm0\n"
1969 "fld_s [esp]\n"
1970 "pop eax\n"
1971 "ret\n");
1972}
1973
1974ASSEMBLER_TEST_GENERATE(PackedLogicalAnd, assembler) {
1975 static const struct ALIGN16 {
1976 uint32_t a;
1977 uint32_t b;
1978 uint32_t c;
1979 uint32_t d;
1980 } constant1 = {0xF0F0F0F0, 0xF0F0F0F0, 0xF0F0F0F0, 0xF0F0F0F0};
1981 static const struct ALIGN16 {
1982 uint32_t a;
1983 uint32_t b;
1984 uint32_t c;
1985 uint32_t d;
1986 } constant2 = {0x0F0FFF0F, 0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F};
1987 __ movups(XMM0, Address::Absolute(reinterpret_cast<uword>(&constant1)));
1988 __ andps(XMM0, Address::Absolute(reinterpret_cast<uword>(&constant2)));
1989 // Copy the low lane at ESP.
1990 __ pushl(EAX);
1991 __ movss(Address(ESP, 0), XMM0);
1992 __ flds(Address(ESP, 0));
1993 __ popl(EAX);
1994 __ ret();
1995}
1996
1997ASSEMBLER_TEST_RUN(PackedLogicalAnd, test) {
1998 typedef uint32_t (*PackedLogicalAndCode)();
1999 uint32_t res = reinterpret_cast<PackedLogicalAndCode>(test->entry())();
2000 EXPECT_EQ(static_cast<uword>(0x0000F000), res);
2001 EXPECT_DISASSEMBLY(
2002 "movups xmm0,[0x........]\n"
2003 "andps xmm0,[0x........]\n"
2004 "push eax\n"
2005 "movss [esp],xmm0\n"
2006 "fld_s [esp]\n"
2007 "pop eax\n"
2008 "ret\n");
2009}
2010
2011ASSEMBLER_TEST_GENERATE(PackedLogicalNot, assembler) {
2012 static const struct ALIGN16 {
2013 uint32_t a;
2014 uint32_t b;
2015 uint32_t c;
2016 uint32_t d;
2017 } constant1 = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
2018 __ movups(XMM0, Address::Absolute(reinterpret_cast<uword>(&constant1)));
2019 __ notps(XMM0);
2020 // Copy the low lane at ESP.
2021 __ pushl(EAX);
2022 __ movss(Address(ESP, 0), XMM0);
2023 __ flds(Address(ESP, 0));
2024 __ popl(EAX);
2025 __ ret();
2026}
2027
2028ASSEMBLER_TEST_RUN(PackedLogicalNot, test) {
2029 typedef uint32_t (*PackedLogicalNotCode)();
2030 uint32_t res = reinterpret_cast<PackedLogicalNotCode>(test->entry())();
2031 EXPECT_EQ(static_cast<uword>(0x0), res);
2032 EXPECT_DISASSEMBLY(
2033 "movups xmm0,[0x........]\n"
2034 "xorps xmm0,[0x........]\n"
2035 "push eax\n"
2036 "movss [esp],xmm0\n"
2037 "fld_s [esp]\n"
2038 "pop eax\n"
2039 "ret\n");
2040}
2041
2042ASSEMBLER_TEST_GENERATE(PackedMoveHighLow, assembler) {
2043 static const struct ALIGN16 {
2044 float a;
2045 float b;
2046 float c;
2047 float d;
2048 } constant0 = {1.0, 2.0, 3.0, 4.0};
2049 static const struct ALIGN16 {
2050 float a;
2051 float b;
2052 float c;
2053 float d;
2054 } constant1 = {5.0, 6.0, 7.0, 8.0};
2055 // XMM0 = 1.0f, 2.0f, 3.0f, 4.0f.
2056 __ movups(XMM0, Address::Absolute(reinterpret_cast<uword>(&constant0)));
2057 // XMM1 = 5.0f, 6.0f, 7.0f, 8.0f.
2058 __ movups(XMM1, Address::Absolute(reinterpret_cast<uword>(&constant1)));
2059 // XMM0 = 7.0f, 8.0f, 3.0f, 4.0f.
2060 __ movhlps(XMM0, XMM1);
2061 __ xorps(XMM1, XMM1);
2062 // XMM1 = 7.0f, 8.0f, 3.0f, 4.0f.
2063 __ movaps(XMM1, XMM0);
2064 __ shufps(XMM0, XMM0, Immediate(0x00)); // 7.0f.
2065 __ shufps(XMM1, XMM1, Immediate(0x55)); // 8.0f.
2066 __ addss(XMM0, XMM1); // 15.0f.
2067 __ pushl(EAX);
2068 __ movss(Address(ESP, 0), XMM0);
2069 __ flds(Address(ESP, 0));
2070 __ popl(EAX);
2071 __ ret();
2072}
2073
2074ASSEMBLER_TEST_RUN(PackedMoveHighLow, test) {
2075 typedef float (*PackedMoveHighLow)();
2076 float res = reinterpret_cast<PackedMoveHighLow>(test->entry())();
2077 EXPECT_FLOAT_EQ(15.0f, res, 0.001f);
2078 EXPECT_DISASSEMBLY(
2079 "movups xmm0,[0x........]\n"
2080 "movups xmm1,[0x........]\n"
2081 "movhlps xmm0,xmm1\n"
2082 "xorps xmm1,xmm1\n"
2083 "movaps xmm1,xmm0\n"
2084 "shufps xmm0,xmm0 [0]\n"
2085 "shufps xmm1,xmm1 [55]\n"
2086 "addss xmm0,xmm1\n"
2087 "push eax\n"
2088 "movss [esp],xmm0\n"
2089 "fld_s [esp]\n"
2090 "pop eax\n"
2091 "ret\n");
2092}
2093
2094ASSEMBLER_TEST_GENERATE(PackedMoveLowHigh, assembler) {
2095 static const struct ALIGN16 {
2096 float a;
2097 float b;
2098 float c;
2099 float d;
2100 } constant0 = {1.0, 2.0, 3.0, 4.0};
2101 static const struct ALIGN16 {
2102 float a;
2103 float b;
2104 float c;
2105 float d;
2106 } constant1 = {5.0, 6.0, 7.0, 8.0};
2107 // XMM0 = 1.0f, 2.0f, 3.0f, 4.0f.
2108 __ movups(XMM0, Address::Absolute(reinterpret_cast<uword>(&constant0)));
2109 // XMM1 = 5.0f, 6.0f, 7.0f, 8.0f.
2110 __ movups(XMM1, Address::Absolute(reinterpret_cast<uword>(&constant1)));
2111 // XMM0 = 1.0f, 2.0f, 5.0f, 6.0f
2112 __ movlhps(XMM0, XMM1);
2113 __ xorps(XMM1, XMM1);
2114 // XMM1 = 1.0f, 2.0f, 5.0f, 6.0f
2115 __ movaps(XMM1, XMM0);
2116 __ shufps(XMM0, XMM0, Immediate(0xAA)); // 5.0f.
2117 __ shufps(XMM1, XMM1, Immediate(0xFF)); // 6.0f.
2118 __ addss(XMM0, XMM1); // 11.0f.
2119 __ pushl(EAX);
2120 __ movss(Address(ESP, 0), XMM0);
2121 __ flds(Address(ESP, 0));
2122 __ popl(EAX);
2123 __ ret();
2124}
2125
2126ASSEMBLER_TEST_RUN(PackedMoveLowHigh, test) {
2127 typedef float (*PackedMoveLowHigh)();
2128 float res = reinterpret_cast<PackedMoveLowHigh>(test->entry())();
2129 EXPECT_FLOAT_EQ(11.0f, res, 0.001f);
2130 EXPECT_DISASSEMBLY(
2131 "movups xmm0,[0x........]\n"
2132 "movups xmm1,[0x........]\n"
2133 "movlhps xmm0,xmm1\n"
2134 "xorps xmm1,xmm1\n"
2135 "movaps xmm1,xmm0\n"
2136 "shufps xmm0,xmm0 [aa]\n"
2137 "shufps xmm1,xmm1 [ff]\n"
2138 "addss xmm0,xmm1\n"
2139 "push eax\n"
2140 "movss [esp],xmm0\n"
2141 "fld_s [esp]\n"
2142 "pop eax\n"
2143 "ret\n");
2144}
2145
2146ASSEMBLER_TEST_GENERATE(PackedUnpackLow, assembler) {
2147 static const struct ALIGN16 {
2148 float a;
2149 float b;
2150 float c;
2151 float d;
2152 } constant0 = {1.0, 2.0, 3.0, 4.0};
2153 static const struct ALIGN16 {
2154 float a;
2155 float b;
2156 float c;
2157 float d;
2158 } constant1 = {5.0, 6.0, 7.0, 8.0};
2159 // XMM0 = 1.0f, 2.0f, 3.0f, 4.0f.
2160 __ movups(XMM0, Address::Absolute(reinterpret_cast<uword>(&constant0)));
2161 // XMM1 = 5.0f, 6.0f, 7.0f, 8.0f.
2162 __ movups(XMM1, Address::Absolute(reinterpret_cast<uword>(&constant1)));
2163 // XMM0 = 1.0f, 5.0f, 2.0f, 6.0f.
2164 __ unpcklps(XMM0, XMM1);
2165 // XMM1 = 1.0f, 5.0f, 2.0f, 6.0f.
2166 __ movaps(XMM1, XMM0);
2167 __ shufps(XMM0, XMM0, Immediate(0x55));
2168 __ shufps(XMM1, XMM1, Immediate(0xFF));
2169 __ addss(XMM0, XMM1); // 11.0f.
2170 __ pushl(EAX);
2171 __ movss(Address(ESP, 0), XMM0);
2172 __ flds(Address(ESP, 0));
2173 __ popl(EAX);
2174 __ ret();
2175}
2176
2177ASSEMBLER_TEST_RUN(PackedUnpackLow, test) {
2178 typedef float (*PackedUnpackLow)();
2179 float res = reinterpret_cast<PackedUnpackLow>(test->entry())();
2180 EXPECT_FLOAT_EQ(11.0f, res, 0.001f);
2181 EXPECT_DISASSEMBLY(
2182 "movups xmm0,[0x........]\n"
2183 "movups xmm1,[0x........]\n"
2184 "unpcklps xmm0,xmm1\n"
2185 "movaps xmm1,xmm0\n"
2186 "shufps xmm0,xmm0 [55]\n"
2187 "shufps xmm1,xmm1 [ff]\n"
2188 "addss xmm0,xmm1\n"
2189 "push eax\n"
2190 "movss [esp],xmm0\n"
2191 "fld_s [esp]\n"
2192 "pop eax\n"
2193 "ret\n");
2194}
2195
2196ASSEMBLER_TEST_GENERATE(PackedUnpackHigh, assembler) {
2197 static const struct ALIGN16 {
2198 float a;
2199 float b;
2200 float c;
2201 float d;
2202 } constant0 = {1.0, 2.0, 3.0, 4.0};
2203 static const struct ALIGN16 {
2204 float a;
2205 float b;
2206 float c;
2207 float d;
2208 } constant1 = {5.0, 6.0, 7.0, 8.0};
2209 // XMM0 = 1.0f, 2.0f, 3.0f, 4.0f.
2210 __ movups(XMM0, Address::Absolute(reinterpret_cast<uword>(&constant0)));
2211 // XMM1 = 5.0f, 6.0f, 7.0f, 8.0f.
2212 __ movups(XMM1, Address::Absolute(reinterpret_cast<uword>(&constant1)));
2213 // XMM0 = 3.0f, 7.0f, 4.0f, 8.0f.
2214 __ unpckhps(XMM0, XMM1);
2215 // XMM1 = 3.0f, 7.0f, 4.0f, 8.0f.
2216 __ movaps(XMM1, XMM0);
2217 __ shufps(XMM0, XMM0, Immediate(0x00));
2218 __ shufps(XMM1, XMM1, Immediate(0xAA));
2219 __ addss(XMM0, XMM1); // 7.0f.
2220 __ pushl(EAX);
2221 __ movss(Address(ESP, 0), XMM0);
2222 __ flds(Address(ESP, 0));
2223 __ popl(EAX);
2224 __ ret();
2225}
2226
2227ASSEMBLER_TEST_RUN(PackedUnpackHigh, test) {
2228 typedef float (*PackedUnpackHigh)();
2229 float res = reinterpret_cast<PackedUnpackHigh>(test->entry())();
2230 EXPECT_FLOAT_EQ(7.0f, res, 0.001f);
2231 EXPECT_DISASSEMBLY(
2232 "movups xmm0,[0x........]\n"
2233 "movups xmm1,[0x........]\n"
2234 "unpckhps xmm0,xmm1\n"
2235 "movaps xmm1,xmm0\n"
2236 "shufps xmm0,xmm0 [0]\n"
2237 "shufps xmm1,xmm1 [aa]\n"
2238 "addss xmm0,xmm1\n"
2239 "push eax\n"
2240 "movss [esp],xmm0\n"
2241 "fld_s [esp]\n"
2242 "pop eax\n"
2243 "ret\n");
2244}
2245
2246ASSEMBLER_TEST_GENERATE(PackedUnpackLowPair, assembler) {
2247 static const struct ALIGN16 {
2248 float a;
2249 float b;
2250 float c;
2251 float d;
2252 } constant0 = {1.0, 2.0, 3.0, 4.0};
2253 static const struct ALIGN16 {
2254 float a;
2255 float b;
2256 float c;
2257 float d;
2258 } constant1 = {5.0, 6.0, 7.0, 8.0};
2259 // XMM0 = 1.0f, 2.0f, 3.0f, 4.0f.
2260 __ movups(XMM0, Address::Absolute(reinterpret_cast<uword>(&constant0)));
2261 // XMM1 = 5.0f, 6.0f, 7.0f, 8.0f.
2262 __ movups(XMM1, Address::Absolute(reinterpret_cast<uword>(&constant1)));
2263 // XMM0 = 1.0f, 2.0f, 5.0f, 6.0f.
2264 __ unpcklpd(XMM0, XMM1);
2265 // XMM1 = 1.0f, 2.0f, 5.0f, 6.0f.
2266 __ movaps(XMM1, XMM0);
2267 __ shufps(XMM0, XMM0, Immediate(0x00));
2268 __ shufps(XMM1, XMM1, Immediate(0xAA));
2269 __ addss(XMM0, XMM1); // 6.0f.
2270 __ pushl(EAX);
2271 __ movss(Address(ESP, 0), XMM0);
2272 __ flds(Address(ESP, 0));
2273 __ popl(EAX);
2274 __ ret();
2275}
2276
2277ASSEMBLER_TEST_RUN(PackedUnpackLowPair, test) {
2278 typedef float (*PackedUnpackLowPair)();
2279 float res = reinterpret_cast<PackedUnpackLowPair>(test->entry())();
2280 EXPECT_FLOAT_EQ(6.0f, res, 0.001f);
2281 EXPECT_DISASSEMBLY(
2282 "movups xmm0,[0x........]\n"
2283 "movups xmm1,[0x........]\n"
2284 "unpcklpd xmm0,xmm1\n"
2285 "movaps xmm1,xmm0\n"
2286 "shufps xmm0,xmm0 [0]\n"
2287 "shufps xmm1,xmm1 [aa]\n"
2288 "addss xmm0,xmm1\n"
2289 "push eax\n"
2290 "movss [esp],xmm0\n"
2291 "fld_s [esp]\n"
2292 "pop eax\n"
2293 "ret\n");
2294}
2295
2296ASSEMBLER_TEST_GENERATE(PackedUnpackHighPair, assembler) {
2297 static const struct ALIGN16 {
2298 float a;
2299 float b;
2300 float c;
2301 float d;
2302 } constant0 = {1.0, 2.0, 3.0, 4.0};
2303 static const struct ALIGN16 {
2304 float a;
2305 float b;
2306 float c;
2307 float d;
2308 } constant1 = {5.0, 6.0, 7.0, 8.0};
2309 // XMM0 = 1.0f, 2.0f, 3.0f, 4.0f.
2310 __ movups(XMM0, Address::Absolute(reinterpret_cast<uword>(&constant0)));
2311 // XMM1 = 5.0f, 6.0f, 7.0f, 8.0f.
2312 __ movups(XMM1, Address::Absolute(reinterpret_cast<uword>(&constant1)));
2313 // XMM0 = 3.0f, 4.0f, 7.0f, 8.0f.
2314 __ unpckhpd(XMM0, XMM1);
2315 // XMM1 = 3.0f, 4.0f, 7.0f, 8.0f.
2316 __ movaps(XMM1, XMM0);
2317 __ shufps(XMM0, XMM0, Immediate(0x55));
2318 __ shufps(XMM1, XMM1, Immediate(0xFF));
2319 __ addss(XMM0, XMM1); // 12.0f.
2320 __ pushl(EAX);
2321 __ movss(Address(ESP, 0), XMM0);
2322 __ flds(Address(ESP, 0));
2323 __ popl(EAX);
2324 __ ret();
2325}
2326
2327ASSEMBLER_TEST_RUN(PackedUnpackHighPair, test) {
2328 typedef float (*PackedUnpackHighPair)();
2329 float res = reinterpret_cast<PackedUnpackHighPair>(test->entry())();
2330 EXPECT_FLOAT_EQ(12.0f, res, 0.001f);
2331 EXPECT_DISASSEMBLY(
2332 "movups xmm0,[0x........]\n"
2333 "movups xmm1,[0x........]\n"
2334 "unpckhpd xmm0,xmm1\n"
2335 "movaps xmm1,xmm0\n"
2336 "shufps xmm0,xmm0 [55]\n"
2337 "shufps xmm1,xmm1 [ff]\n"
2338 "addss xmm0,xmm1\n"
2339 "push eax\n"
2340 "movss [esp],xmm0\n"
2341 "fld_s [esp]\n"
2342 "pop eax\n"
2343 "ret\n");
2344}
2345
2346ASSEMBLER_TEST_GENERATE(PackedDoubleAdd, assembler) {
2347 static const struct ALIGN16 {
2348 double a;
2349 double b;
2350 } constant0 = {1.0, 2.0};
2351 static const struct ALIGN16 {
2352 double a;
2353 double b;
2354 } constant1 = {3.0, 4.0};
2355 __ movups(XMM0, Address::Absolute(reinterpret_cast<uword>(&constant0)));
2356 __ movups(XMM1, Address::Absolute(reinterpret_cast<uword>(&constant1)));
2357 __ addpd(XMM0, XMM1);
2358 __ pushl(EAX);
2359 __ pushl(EAX);
2360 __ movsd(Address(ESP, 0), XMM0);
2361 __ fldl(Address(ESP, 0));
2362 __ popl(EAX);
2363 __ popl(EAX);
2364 __ ret();
2365}
2366
2367ASSEMBLER_TEST_RUN(PackedDoubleAdd, test) {
2368 typedef double (*PackedDoubleAdd)();
2369 double res = reinterpret_cast<PackedDoubleAdd>(test->entry())();
2370 EXPECT_FLOAT_EQ(4.0, res, 0.000001f);
2371 EXPECT_DISASSEMBLY(
2372 "movups xmm0,[0x........]\n"
2373 "movups xmm1,[0x........]\n"
2374 "addpd xmm0,xmm1\n"
2375 "push eax\n"
2376 "push eax\n"
2377 "movsd [esp],xmm0\n"
2378 "fld_d [esp]\n"
2379 "pop eax\n"
2380 "pop eax\n"
2381 "ret\n");
2382}
2383
2384ASSEMBLER_TEST_GENERATE(PackedDoubleSub, assembler) {
2385 static const struct ALIGN16 {
2386 double a;
2387 double b;
2388 } constant0 = {1.0, 2.0};
2389 static const struct ALIGN16 {
2390 double a;
2391 double b;
2392 } constant1 = {3.0, 4.0};
2393 __ movups(XMM0, Address::Absolute(reinterpret_cast<uword>(&constant0)));
2394 __ movups(XMM1, Address::Absolute(reinterpret_cast<uword>(&constant1)));
2395 __ subpd(XMM0, XMM1);
2396 __ pushl(EAX);
2397 __ pushl(EAX);
2398 __ movsd(Address(ESP, 0), XMM0);
2399 __ fldl(Address(ESP, 0));
2400 __ popl(EAX);
2401 __ popl(EAX);
2402 __ ret();
2403}
2404
2405ASSEMBLER_TEST_RUN(PackedDoubleSub, test) {
2406 typedef double (*PackedDoubleSub)();
2407 double res = reinterpret_cast<PackedDoubleSub>(test->entry())();
2408 EXPECT_FLOAT_EQ(-2.0, res, 0.000001f);
2409 EXPECT_DISASSEMBLY(
2410 "movups xmm0,[0x........]\n"
2411 "movups xmm1,[0x........]\n"
2412 "subpd xmm0,xmm1\n"
2413 "push eax\n"
2414 "push eax\n"
2415 "movsd [esp],xmm0\n"
2416 "fld_d [esp]\n"
2417 "pop eax\n"
2418 "pop eax\n"
2419 "ret\n");
2420}
2421
2422ASSEMBLER_TEST_GENERATE(PackedDoubleNegate, assembler) {
2423 static const struct ALIGN16 {
2424 double a;
2425 double b;
2426 } constant0 = {1.0, 2.0};
2427 __ movups(XMM0, Address::Absolute(reinterpret_cast<uword>(&constant0)));
2428 __ negatepd(XMM0);
2429 __ pushl(EAX);
2430 __ pushl(EAX);
2431 __ movsd(Address(ESP, 0), XMM0);
2432 __ fldl(Address(ESP, 0));
2433 __ popl(EAX);
2434 __ popl(EAX);
2435 __ ret();
2436}
2437
2438ASSEMBLER_TEST_RUN(PackedDoubleNegate, test) {
2439 typedef double (*PackedDoubleNegate)();
2440 double res = reinterpret_cast<PackedDoubleNegate>(test->entry())();
2441 EXPECT_FLOAT_EQ(-1.0, res, 0.000001f);
2442 EXPECT_DISASSEMBLY(
2443 "movups xmm0,[0x........]\n"
2444 "xorpd xmm0,[0x........]\n"
2445 "push eax\n"
2446 "push eax\n"
2447 "movsd [esp],xmm0\n"
2448 "fld_d [esp]\n"
2449 "pop eax\n"
2450 "pop eax\n"
2451 "ret\n");
2452}
2453
2454ASSEMBLER_TEST_GENERATE(PackedDoubleAbsolute, assembler) {
2455 static const struct ALIGN16 {
2456 double a;
2457 double b;
2458 } constant0 = {-1.0, 2.0};
2459 __ movups(XMM0, Address::Absolute(reinterpret_cast<uword>(&constant0)));
2460 __ abspd(XMM0);
2461 __ pushl(EAX);
2462 __ pushl(EAX);
2463 __ movsd(Address(ESP, 0), XMM0);
2464 __ fldl(Address(ESP, 0));
2465 __ popl(EAX);
2466 __ popl(EAX);
2467 __ ret();
2468}
2469
2470ASSEMBLER_TEST_RUN(PackedDoubleAbsolute, test) {
2471 typedef double (*PackedDoubleAbsolute)();
2472 double res = reinterpret_cast<PackedDoubleAbsolute>(test->entry())();
2473 EXPECT_FLOAT_EQ(1.0, res, 0.000001f);
2474 EXPECT_DISASSEMBLY(
2475 "movups xmm0,[0x........]\n"
2476 "andpd xmm0,[0x........]\n"
2477 "push eax\n"
2478 "push eax\n"
2479 "movsd [esp],xmm0\n"
2480 "fld_d [esp]\n"
2481 "pop eax\n"
2482 "pop eax\n"
2483 "ret\n");
2484}
2485
2486ASSEMBLER_TEST_GENERATE(PackedDoubleMul, assembler) {
2487 static const struct ALIGN16 {
2488 double a;
2489 double b;
2490 } constant0 = {3.0, 2.0};
2491 static const struct ALIGN16 {
2492 double a;
2493 double b;
2494 } constant1 = {3.0, 4.0};
2495 __ movups(XMM0, Address::Absolute(reinterpret_cast<uword>(&constant0)));
2496 __ movups(XMM1, Address::Absolute(reinterpret_cast<uword>(&constant1)));
2497 __ mulpd(XMM0, XMM1);
2498 __ pushl(EAX);
2499 __ pushl(EAX);
2500 __ movsd(Address(ESP, 0), XMM0);
2501 __ fldl(Address(ESP, 0));
2502 __ popl(EAX);
2503 __ popl(EAX);
2504 __ ret();
2505}
2506
2507ASSEMBLER_TEST_RUN(PackedDoubleMul, test) {
2508 typedef double (*PackedDoubleMul)();
2509 double res = reinterpret_cast<PackedDoubleMul>(test->entry())();
2510 EXPECT_FLOAT_EQ(9.0, res, 0.000001f);
2511 EXPECT_DISASSEMBLY(
2512 "movups xmm0,[0x........]\n"
2513 "movups xmm1,[0x........]\n"
2514 "mulpd xmm0,xmm1\n"
2515 "push eax\n"
2516 "push eax\n"
2517 "movsd [esp],xmm0\n"
2518 "fld_d [esp]\n"
2519 "pop eax\n"
2520 "pop eax\n"
2521 "ret\n");
2522}
2523
2524ASSEMBLER_TEST_GENERATE(PackedDoubleDiv, assembler) {
2525 static const struct ALIGN16 {
2526 double a;
2527 double b;
2528 } constant0 = {9.0, 2.0};
2529 static const struct ALIGN16 {
2530 double a;
2531 double b;
2532 } constant1 = {3.0, 4.0};
2533 __ movups(XMM0, Address::Absolute(reinterpret_cast<uword>(&constant0)));
2534 __ movups(XMM1, Address::Absolute(reinterpret_cast<uword>(&constant1)));
2535 __ divpd(XMM0, XMM1);
2536 __ pushl(EAX);
2537 __ pushl(EAX);
2538 __ movsd(Address(ESP, 0), XMM0);
2539 __ fldl(Address(ESP, 0));
2540 __ popl(EAX);
2541 __ popl(EAX);
2542 __ ret();
2543}
2544
2545ASSEMBLER_TEST_RUN(PackedDoubleDiv, test) {
2546 typedef double (*PackedDoubleDiv)();
2547 double res = reinterpret_cast<PackedDoubleDiv>(test->entry())();
2548 EXPECT_FLOAT_EQ(3.0, res, 0.000001f);
2549 EXPECT_DISASSEMBLY(
2550 "movups xmm0,[0x........]\n"
2551 "movups xmm1,[0x........]\n"
2552 "divpd xmm0,xmm1\n"
2553 "push eax\n"
2554 "push eax\n"
2555 "movsd [esp],xmm0\n"
2556 "fld_d [esp]\n"
2557 "pop eax\n"
2558 "pop eax\n"
2559 "ret\n");
2560}
2561
2562ASSEMBLER_TEST_GENERATE(PackedDoubleSqrt, assembler) {
2563 static const struct ALIGN16 {
2564 double a;
2565 double b;
2566 } constant0 = {16.0, 2.0};
2567 __ movups(XMM0, Address::Absolute(reinterpret_cast<uword>(&constant0)));
2568 __ sqrtpd(XMM0);
2569 __ pushl(EAX);
2570 __ pushl(EAX);
2571 __ movsd(Address(ESP, 0), XMM0);
2572 __ fldl(Address(ESP, 0));
2573 __ popl(EAX);
2574 __ popl(EAX);
2575 __ ret();
2576}
2577
2578ASSEMBLER_TEST_RUN(PackedDoubleSqrt, test) {
2579 typedef double (*PackedDoubleSqrt)();
2580 double res = reinterpret_cast<PackedDoubleSqrt>(test->entry())();
2581 EXPECT_FLOAT_EQ(4.0, res, 0.000001f);
2582 EXPECT_DISASSEMBLY(
2583 "movups xmm0,[0x........]\n"
2584 "sqrtpd xmm0,xmm0\n"
2585 "push eax\n"
2586 "push eax\n"
2587 "movsd [esp],xmm0\n"
2588 "fld_d [esp]\n"
2589 "pop eax\n"
2590 "pop eax\n"
2591 "ret\n");
2592}
2593
2594ASSEMBLER_TEST_GENERATE(PackedDoubleMin, assembler) {
2595 static const struct ALIGN16 {
2596 double a;
2597 double b;
2598 } constant0 = {9.0, 2.0};
2599 static const struct ALIGN16 {
2600 double a;
2601 double b;
2602 } constant1 = {3.0, 4.0};
2603 __ movups(XMM0, Address::Absolute(reinterpret_cast<uword>(&constant0)));
2604 __ movups(XMM1, Address::Absolute(reinterpret_cast<uword>(&constant1)));
2605 __ minpd(XMM0, XMM1);
2606 __ pushl(EAX);
2607 __ pushl(EAX);
2608 __ movsd(Address(ESP, 0), XMM0);
2609 __ fldl(Address(ESP, 0));
2610 __ popl(EAX);
2611 __ popl(EAX);
2612 __ ret();
2613}
2614
2615ASSEMBLER_TEST_RUN(PackedDoubleMin, test) {
2616 typedef double (*PackedDoubleMin)();
2617 double res = reinterpret_cast<PackedDoubleMin>(test->entry())();
2618 EXPECT_FLOAT_EQ(3.0, res, 0.000001f);
2619 EXPECT_DISASSEMBLY(
2620 "movups xmm0,[0x........]\n"
2621 "movups xmm1,[0x........]\n"
2622 "minpd xmm0,xmm1\n"
2623 "push eax\n"
2624 "push eax\n"
2625 "movsd [esp],xmm0\n"
2626 "fld_d [esp]\n"
2627 "pop eax\n"
2628 "pop eax\n"
2629 "ret\n");
2630}
2631
2632ASSEMBLER_TEST_GENERATE(PackedDoubleMax, assembler) {
2633 static const struct ALIGN16 {
2634 double a;
2635 double b;
2636 } constant0 = {9.0, 2.0};
2637 static const struct ALIGN16 {
2638 double a;
2639 double b;
2640 } constant1 = {3.0, 4.0};
2641 __ movups(XMM0, Address::Absolute(reinterpret_cast<uword>(&constant0)));
2642 __ movups(XMM1, Address::Absolute(reinterpret_cast<uword>(&constant1)));
2643 __ maxpd(XMM0, XMM1);
2644 __ pushl(EAX);
2645 __ pushl(EAX);
2646 __ movsd(Address(ESP, 0), XMM0);
2647 __ fldl(Address(ESP, 0));
2648 __ popl(EAX);
2649 __ popl(EAX);
2650 __ ret();
2651}
2652
2653ASSEMBLER_TEST_RUN(PackedDoubleMax, test) {
2654 typedef double (*PackedDoubleMax)();
2655 double res = reinterpret_cast<PackedDoubleMax>(test->entry())();
2656 EXPECT_FLOAT_EQ(9.0, res, 0.000001f);
2657 EXPECT_DISASSEMBLY(
2658 "movups xmm0,[0x........]\n"
2659 "movups xmm1,[0x........]\n"
2660 "maxpd xmm0,xmm1\n"
2661 "push eax\n"
2662 "push eax\n"
2663 "movsd [esp],xmm0\n"
2664 "fld_d [esp]\n"
2665 "pop eax\n"
2666 "pop eax\n"
2667 "ret\n");
2668}
2669
2670ASSEMBLER_TEST_GENERATE(PackedDoubleShuffle, assembler) {
2671 static const struct ALIGN16 {
2672 double a;
2673 double b;
2674 } constant0 = {2.0, 9.0};
2675 __ movups(XMM0, Address::Absolute(reinterpret_cast<uword>(&constant0)));
2676 // Splat Y across all lanes.
2677 __ shufpd(XMM0, XMM0, Immediate(0x33));
2678 // Splat X across all lanes.
2679 __ shufpd(XMM0, XMM0, Immediate(0x0));
2680 // Set return value.
2681 __ pushl(EAX);
2682 __ pushl(EAX);
2683 __ movsd(Address(ESP, 0), XMM0);
2684 __ fldl(Address(ESP, 0));
2685 __ popl(EAX);
2686 __ popl(EAX);
2687 __ ret();
2688}
2689
2690ASSEMBLER_TEST_RUN(PackedDoubleShuffle, test) {
2691 typedef double (*PackedDoubleShuffle)();
2692 double res = reinterpret_cast<PackedDoubleShuffle>(test->entry())();
2693 EXPECT_FLOAT_EQ(9.0, res, 0.000001f);
2694 EXPECT_DISASSEMBLY(
2695 "movups xmm0,[0x........]\n"
2696 "shufpd xmm0, xmm0 [33]\n"
2697 "shufpd xmm0, xmm0 [0]\n"
2698 "push eax\n"
2699 "push eax\n"
2700 "movsd [esp],xmm0\n"
2701 "fld_d [esp]\n"
2702 "pop eax\n"
2703 "pop eax\n"
2704 "ret\n");
2705}
2706
2707ASSEMBLER_TEST_GENERATE(PackedDoubleToSingle, assembler) {
2708 static const struct ALIGN16 {
2709 double a;
2710 double b;
2711 } constant0 = {9.0, 2.0};
2712 __ movups(XMM1, Address::Absolute(reinterpret_cast<uword>(&constant0)));
2713 __ cvtpd2ps(XMM0, XMM1);
2714 __ pushl(EAX);
2715 __ movss(Address(ESP, 0), XMM0);
2716 __ flds(Address(ESP, 0));
2717 __ popl(EAX);
2718 __ ret();
2719}
2720
2721ASSEMBLER_TEST_RUN(PackedDoubleToSingle, test) {
2722 typedef float (*PackedDoubleToSingle)();
2723 float res = reinterpret_cast<PackedDoubleToSingle>(test->entry())();
2724 EXPECT_FLOAT_EQ(9.0f, res, 0.000001f);
2725 EXPECT_DISASSEMBLY(
2726 "movups xmm1,[0x........]\n"
2727 "cvtpd2ps xmm0,xmm1\n"
2728 "push eax\n"
2729 "movss [esp],xmm0\n"
2730 "fld_s [esp]\n"
2731 "pop eax\n"
2732 "ret\n");
2733}
2734
2735ASSEMBLER_TEST_GENERATE(PackedSingleToDouble, assembler) {
2736 static const struct ALIGN16 {
2737 float a;
2738 float b;
2739 float c;
2740 float d;
2741 } constant0 = {9.0f, 2.0f, 3.0f, 4.0f};
2742 __ movups(XMM1, Address::Absolute(reinterpret_cast<uword>(&constant0)));
2743 __ cvtps2pd(XMM0, XMM1);
2744 __ pushl(EAX);
2745 __ pushl(EAX);
2746 __ movsd(Address(ESP, 0), XMM0);
2747 __ fldl(Address(ESP, 0));
2748 __ popl(EAX);
2749 __ popl(EAX);
2750 __ ret();
2751}
2752
2753ASSEMBLER_TEST_RUN(PackedSingleToDouble, test) {
2754 typedef double (*PackedSingleToDouble)();
2755 double res = reinterpret_cast<PackedSingleToDouble>(test->entry())();
2756 EXPECT_FLOAT_EQ(9.0f, res, 0.000001f);
2757 EXPECT_DISASSEMBLY(
2758 "movups xmm1,[0x........]\n"
2759 "cvtps2pd xmm0,xmm1\n"
2760 "push eax\n"
2761 "push eax\n"
2762 "movsd [esp],xmm0\n"
2763 "fld_d [esp]\n"
2764 "pop eax\n"
2765 "pop eax\n"
2766 "ret\n");
2767}
2768
2769ASSEMBLER_TEST_GENERATE(SingleFPOperationsStack, assembler) {
2770 __ movl(EAX, Immediate(bit_cast<int32_t, float>(12.3f)));
2771 __ movd(XMM0, EAX);
2772 __ addss(XMM0, Address(ESP, target::kWordSize)); // 15.7f
2773 __ mulss(XMM0, Address(ESP, target::kWordSize)); // 53.38f
2774 __ subss(XMM0, Address(ESP, target::kWordSize)); // 49.98f
2775 __ divss(XMM0, Address(ESP, target::kWordSize)); // 14.7f
2776 __ pushl(EAX);
2777 __ movss(Address(ESP, 0), XMM0);
2778 __ flds(Address(ESP, 0));
2779 __ popl(EAX);
2780 __ ret();
2781}
2782
2783ASSEMBLER_TEST_RUN(SingleFPOperationsStack, test) {
2784 typedef float (*SingleFPOperationsStackCode)(float f);
2785 float res = reinterpret_cast<SingleFPOperationsStackCode>(test->entry())(3.4);
2786 EXPECT_FLOAT_EQ(14.7f, res, 0.001f);
2787 EXPECT_DISASSEMBLY(
2788 "mov eax,0x4144cccd\n"
2789 "movd xmm0,eax\n"
2790 "addss xmm0,[esp+0x4]\n"
2791 "mulss xmm0,[esp+0x4]\n"
2792 "subss xmm0,[esp+0x4]\n"
2793 "divss xmm0,[esp+0x4]\n"
2794 "push eax\n"
2795 "movss [esp],xmm0\n"
2796 "fld_s [esp]\n"
2797 "pop eax\n"
2798 "ret\n");
2799}
2800
2801ASSEMBLER_TEST_GENERATE(DoubleFPMoves, assembler) {
2802 int64_t l = bit_cast<int64_t, double>(1024.67);
2803 __ movl(EAX, Immediate(Utils::High32Bits(l)));
2804 __ pushl(EAX);
2805 __ movl(EAX, Immediate(Utils::Low32Bits(l)));
2806 __ pushl(EAX);
2807 __ movsd(XMM0, Address(ESP, 0));
2808 __ movsd(XMM1, XMM0);
2809 __ movsd(XMM2, XMM1);
2810 __ movsd(XMM3, XMM2);
2811 __ movsd(XMM4, XMM3);
2812 __ movsd(XMM5, XMM4);
2813 __ movsd(XMM6, XMM5);
2814 __ movsd(XMM7, XMM6);
2815 __ movl(Address(ESP, 0), Immediate(0));
2816 __ movl(Address(ESP, target::kWordSize), Immediate(0));
2817 __ movsd(XMM0, Address(ESP, 0));
2818 __ movsd(Address(ESP, 0), XMM7);
2819 __ movsd(XMM7, Address(ESP, 0));
2820 __ movaps(XMM6, XMM7);
2821 __ movaps(XMM5, XMM6);
2822 __ movaps(XMM4, XMM5);
2823 __ movaps(XMM3, XMM4);
2824 __ movaps(XMM2, XMM3);
2825 __ movaps(XMM1, XMM2);
2826 __ movaps(XMM0, XMM1);
2827 __ movl(Address(ESP, 0), Immediate(0));
2828 __ movl(Address(ESP, target::kWordSize), Immediate(0));
2829 __ movsd(Address(ESP, 0), XMM0);
2830 __ fldl(Address(ESP, 0));
2831 __ popl(EAX);
2832 __ popl(EAX);
2833 __ ret();
2834}
2835
2836ASSEMBLER_TEST_RUN(DoubleFPMoves, test) {
2837 typedef double (*DoubleFPMovesCode)();
2838 double res = reinterpret_cast<DoubleFPMovesCode>(test->entry())();
2839 EXPECT_FLOAT_EQ(1024.67, res, 0.0001);
2840 EXPECT_DISASSEMBLY(
2841 "mov eax,0x409002ae\n"
2842 "push eax\n"
2843 "mov eax,0x147ae148\n"
2844 "push eax\n"
2845 "movsd xmm0,[esp]\n"
2846 "movsd xmm1,xmm0\n"
2847 "movsd xmm2,xmm1\n"
2848 "movsd xmm3,xmm2\n"
2849 "movsd xmm4,xmm3\n"
2850 "movsd xmm5,xmm4\n"
2851 "movsd xmm6,xmm5\n"
2852 "movsd xmm7,xmm6\n"
2853 "mov [esp],0\n"
2854 "mov [esp+0x4],0\n"
2855 "movsd xmm0,[esp]\n"
2856 "movsd [esp],xmm7\n"
2857 "movsd xmm7,[esp]\n"
2858 "movaps xmm6,xmm7\n"
2859 "movaps xmm5,xmm6\n"
2860 "movaps xmm4,xmm5\n"
2861 "movaps xmm3,xmm4\n"
2862 "movaps xmm2,xmm3\n"
2863 "movaps xmm1,xmm2\n"
2864 "movaps xmm0,xmm1\n"
2865 "mov [esp],0\n"
2866 "mov [esp+0x4],0\n"
2867 "movsd [esp],xmm0\n"
2868 "fld_d [esp]\n"
2869 "pop eax\n"
2870 "pop eax\n"
2871 "ret\n");
2872}
2873
2874ASSEMBLER_TEST_GENERATE(DoubleFPUStackMoves, assembler) {
2875 int64_t l = bit_cast<int64_t, double>(1024.67);
2876 __ movl(EAX, Immediate(Utils::High32Bits(l)));
2877 __ pushl(EAX);
2878 __ movl(EAX, Immediate(Utils::Low32Bits(l)));
2879 __ pushl(EAX);
2880 __ fldl(Address(ESP, 0));
2881 __ movl(Address(ESP, 0), Immediate(0));
2882 __ movl(Address(ESP, target::kWordSize), Immediate(0));
2883 __ fstpl(Address(ESP, 0));
2884 __ popl(EAX);
2885 __ popl(EDX);
2886 __ ret();
2887}
2888
2889ASSEMBLER_TEST_RUN(DoubleFPUStackMoves, test) {
2890 typedef int64_t (*DoubleFPUStackMovesCode)();
2891 int64_t res = reinterpret_cast<DoubleFPUStackMovesCode>(test->entry())();
2892 EXPECT_FLOAT_EQ(1024.67, (bit_cast<double, int64_t>(res)), 0.001);
2893 EXPECT_DISASSEMBLY(
2894 "mov eax,0x409002ae\n"
2895 "push eax\n"
2896 "mov eax,0x147ae148\n"
2897 "push eax\n"
2898 "fld_d [esp]\n"
2899 "mov [esp],0\n"
2900 "mov [esp+0x4],0\n"
2901 "fstp_d [esp]\n"
2902 "pop eax\n"
2903 "pop edx\n"
2904 "ret\n");
2905}
2906
2907ASSEMBLER_TEST_GENERATE(DoubleFPOperations, assembler) {
2908 int64_t l = bit_cast<int64_t, double>(12.3);
2909 __ movl(EAX, Immediate(Utils::High32Bits(l)));
2910 __ pushl(EAX);
2911 __ movl(EAX, Immediate(Utils::Low32Bits(l)));
2912 __ pushl(EAX);
2913 __ movsd(XMM0, Address(ESP, 0));
2914 __ popl(EAX);
2915 __ popl(EAX);
2916 l = bit_cast<int64_t, double>(3.4);
2917 __ movl(EAX, Immediate(Utils::High32Bits(l)));
2918 __ pushl(EAX);
2919 __ movl(EAX, Immediate(Utils::Low32Bits(l)));
2920 __ pushl(EAX);
2921 __ movsd(XMM1, Address(ESP, 0));
2922 __ addsd(XMM0, XMM1); // 15.7
2923 __ mulsd(XMM0, XMM1); // 53.38
2924 __ subsd(XMM0, XMM1); // 49.98
2925 __ divsd(XMM0, XMM1); // 14.7
2926 __ movsd(Address(ESP, 0), XMM0);
2927 __ fldl(Address(ESP, 0));
2928 __ popl(EAX);
2929 __ popl(EAX);
2930 __ ret();
2931}
2932
2933ASSEMBLER_TEST_RUN(DoubleFPOperations, test) {
2934 typedef double (*DoubleFPOperationsCode)();
2935 double res = reinterpret_cast<DoubleFPOperationsCode>(test->entry())();
2936 EXPECT_FLOAT_EQ(14.7, res, 0.001);
2937 EXPECT_DISASSEMBLY(
2938 "mov eax,0x40289999\n"
2939 "push eax\n"
2940 "mov eax,0x9999999a\n"
2941 "push eax\n"
2942 "movsd xmm0,[esp]\n"
2943 "pop eax\n"
2944 "pop eax\n"
2945 "mov eax,0x400b3333\n"
2946 "push eax\n"
2947 "mov eax,0x33333333\n"
2948 "push eax\n"
2949 "movsd xmm1,[esp]\n"
2950 "addsd xmm0,xmm1\n"
2951 "mulsd xmm0,xmm1\n"
2952 "subsd xmm0,xmm1\n"
2953 "divsd xmm0,xmm1\n"
2954 "movsd [esp],xmm0\n"
2955 "fld_d [esp]\n"
2956 "pop eax\n"
2957 "pop eax\n"
2958 "ret\n");
2959}
2960
2961ASSEMBLER_TEST_GENERATE(DoubleFPOperationsStack, assembler) {
2962 int64_t l = bit_cast<int64_t, double>(12.3);
2963 __ movl(EAX, Immediate(Utils::High32Bits(l)));
2964 __ pushl(EAX);
2965 __ movl(EAX, Immediate(Utils::Low32Bits(l)));
2966 __ pushl(EAX);
2967 __ movsd(XMM0, Address(ESP, 0));
2968 __ popl(EAX);
2969 __ popl(EAX);
2970
2971 __ addsd(XMM0, Address(ESP, target::kWordSize)); // 15.7
2972 __ mulsd(XMM0, Address(ESP, target::kWordSize)); // 53.38
2973 __ subsd(XMM0, Address(ESP, target::kWordSize)); // 49.98
2974 __ divsd(XMM0, Address(ESP, target::kWordSize)); // 14.7
2975
2976 __ pushl(EAX);
2977 __ pushl(EAX);
2978 __ movsd(Address(ESP, 0), XMM0);
2979 __ fldl(Address(ESP, 0));
2980 __ popl(EAX);
2981 __ popl(EAX);
2982 __ ret();
2983}
2984
2985ASSEMBLER_TEST_RUN(DoubleFPOperationsStack, test) {
2986 typedef double (*DoubleFPOperationsStackCode)(double d);
2987 double res =
2988 reinterpret_cast<DoubleFPOperationsStackCode>(test->entry())(3.4);
2989 EXPECT_FLOAT_EQ(14.7, res, 0.001);
2990 EXPECT_DISASSEMBLY(
2991 "mov eax,0x40289999\n"
2992 "push eax\n"
2993 "mov eax,0x9999999a\n"
2994 "push eax\n"
2995 "movsd xmm0,[esp]\n"
2996 "pop eax\n"
2997 "pop eax\n"
2998 "addsd xmm0,[esp+0x4]\n"
2999 "mulsd xmm0,[esp+0x4]\n"
3000 "subsd xmm0,[esp+0x4]\n"
3001 "divsd xmm0,[esp+0x4]\n"
3002 "push eax\n"
3003 "push eax\n"
3004 "movsd [esp],xmm0\n"
3005 "fld_d [esp]\n"
3006 "pop eax\n"
3007 "pop eax\n"
3008 "ret\n");
3009}
3010
3011ASSEMBLER_TEST_GENERATE(IntToDoubleConversion, assembler) {
3012 __ movl(EDX, Immediate(6));
3013 __ cvtsi2sd(XMM1, EDX);
3014 __ pushl(EAX);
3015 __ pushl(EAX);
3016 __ movsd(Address(ESP, 0), XMM1);
3017 __ fldl(Address(ESP, 0));
3018 __ popl(EAX);
3019 __ popl(EAX);
3020 __ ret();
3021}
3022
3023ASSEMBLER_TEST_RUN(IntToDoubleConversion, test) {
3024 typedef double (*IntToDoubleConversionCode)();
3025 double res = reinterpret_cast<IntToDoubleConversionCode>(test->entry())();
3026 EXPECT_FLOAT_EQ(6.0, res, 0.001);
3027 EXPECT_DISASSEMBLY(
3028 "mov edx,6\n"
3029 "cvtsi2sd xmm1,edx\n"
3030 "push eax\n"
3031 "push eax\n"
3032 "movsd [esp],xmm1\n"
3033 "fld_d [esp]\n"
3034 "pop eax\n"
3035 "pop eax\n"
3036 "ret\n");
3037}
3038
3039ASSEMBLER_TEST_GENERATE(IntToDoubleConversion2, assembler) {
3040 __ filds(Address(ESP, target::kWordSize));
3041 __ ret();
3042}
3043
3044ASSEMBLER_TEST_RUN(IntToDoubleConversion2, test) {
3045 typedef double (*IntToDoubleConversion2Code)(int i);
3046 double res = reinterpret_cast<IntToDoubleConversion2Code>(test->entry())(3);
3047 EXPECT_FLOAT_EQ(3.0, res, 0.001);
3048 EXPECT_DISASSEMBLY(
3049 "fild_s [esp+0x4]\n"
3050 "ret\n");
3051}
3052
3053ASSEMBLER_TEST_GENERATE(Int64ToDoubleConversion, assembler) {
3054 __ movl(EAX, Immediate(0));
3055 __ movl(EDX, Immediate(6));
3056 __ pushl(EAX);
3057 __ pushl(EDX);
3058 __ fildl(Address(ESP, 0));
3059 __ popl(EAX);
3060 __ popl(EAX);
3061 __ ret();
3062}
3063
3064ASSEMBLER_TEST_RUN(Int64ToDoubleConversion, test) {
3065 typedef double (*Int64ToDoubleConversionCode)();
3066 double res = reinterpret_cast<Int64ToDoubleConversionCode>(test->entry())();
3067 EXPECT_EQ(6.0, res);
3068 EXPECT_DISASSEMBLY(
3069 "mov eax,0\n"
3070 "mov edx,6\n"
3071 "push eax\n"
3072 "push edx\n"
3073 "fild_d [esp]\n"
3074 "pop eax\n"
3075 "pop eax\n"
3076 "ret\n");
3077}
3078
3079ASSEMBLER_TEST_GENERATE(NegativeInt64ToDoubleConversion, assembler) {
3080 __ movl(EAX, Immediate(0xFFFFFFFF));
3081 __ movl(EDX, Immediate(0xFFFFFFFA));
3082 __ pushl(EAX);
3083 __ pushl(EDX);
3084 __ fildl(Address(ESP, 0));
3085 __ popl(EAX);
3086 __ popl(EAX);
3087 __ ret();
3088}
3089
3090ASSEMBLER_TEST_RUN(NegativeInt64ToDoubleConversion, test) {
3091 typedef double (*NegativeInt64ToDoubleConversionCode)();
3092 double res =
3093 reinterpret_cast<NegativeInt64ToDoubleConversionCode>(test->entry())();
3094 EXPECT_EQ(-6.0, res);
3095 EXPECT_DISASSEMBLY(
3096 "mov eax,0xffffffff\n"
3097 "mov edx,0xfffffffa\n"
3098 "push eax\n"
3099 "push edx\n"
3100 "fild_d [esp]\n"
3101 "pop eax\n"
3102 "pop eax\n"
3103 "ret\n");
3104}
3105
3106ASSEMBLER_TEST_GENERATE(IntToFloatConversion, assembler) {
3107 __ movl(EDX, Immediate(6));
3108 __ cvtsi2ss(XMM1, EDX);
3109 __ pushl(EAX);
3110 __ movss(Address(ESP, 0), XMM1);
3111 __ flds(Address(ESP, 0));
3112 __ popl(EAX);
3113 __ ret();
3114}
3115
3116ASSEMBLER_TEST_RUN(IntToFloatConversion, test) {
3117 typedef float (*IntToFloatConversionCode)();
3118 float res = reinterpret_cast<IntToFloatConversionCode>(test->entry())();
3119 EXPECT_FLOAT_EQ(6.0, res, 0.001);
3120 EXPECT_DISASSEMBLY(
3121 "mov edx,6\n"
3122 "cvtsi2ss xmm1,edx\n"
3123 "push eax\n"
3124 "movss [esp],xmm1\n"
3125 "fld_s [esp]\n"
3126 "pop eax\n"
3127 "ret\n");
3128}
3129
3130ASSEMBLER_TEST_GENERATE(FloatToIntConversionRound, assembler) {
3131 __ movsd(XMM1, Address(ESP, target::kWordSize));
3132 __ cvtss2si(EDX, XMM1);
3133 __ movl(EAX, EDX);
3134 __ ret();
3135}
3136
3137ASSEMBLER_TEST_RUN(FloatToIntConversionRound, test) {
3138 typedef int (*FloatToIntConversionRoundCode)(float f);
3139 int res =
3140 reinterpret_cast<FloatToIntConversionRoundCode>(test->entry())(12.3);
3141 EXPECT_EQ(12, res);
3142 res = reinterpret_cast<FloatToIntConversionRoundCode>(test->entry())(12.8);
3143 EXPECT_EQ(13, res);
3144 EXPECT_DISASSEMBLY(
3145 "movsd xmm1,[esp+0x4]\n"
3146 "cvtss2si edx,xmm1\n"
3147 "mov eax,edx\n"
3148 "ret\n");
3149}
3150
3151ASSEMBLER_TEST_GENERATE(FloatToIntConversionTrunc, assembler) {
3152 __ movsd(XMM1, Address(ESP, target::kWordSize));
3153 __ cvttss2si(EDX, XMM1);
3154 __ movl(EAX, EDX);
3155 __ ret();
3156}
3157
3158ASSEMBLER_TEST_RUN(FloatToIntConversionTrunc, test) {
3159 typedef int (*FloatToIntConversionTruncCode)(float f);
3160 int res =
3161 reinterpret_cast<FloatToIntConversionTruncCode>(test->entry())(12.3);
3162 EXPECT_EQ(12, res);
3163 res = reinterpret_cast<FloatToIntConversionTruncCode>(test->entry())(12.8);
3164 EXPECT_EQ(12, res);
3165 EXPECT_DISASSEMBLY(
3166 "movsd xmm1,[esp+0x4]\n"
3167 "cvttss2si edx,xmm1\n"
3168 "mov eax,edx\n"
3169 "ret\n");
3170}
3171
3172ASSEMBLER_TEST_GENERATE(FloatToDoubleConversion, assembler) {
3173 __ movl(EAX, Immediate(bit_cast<int32_t, float>(12.3f)));
3174 __ movd(XMM1, EAX);
3175 __ xorl(EAX, EAX);
3176 __ cvtss2sd(XMM2, XMM1);
3177 __ pushl(EAX);
3178 __ pushl(EAX);
3179 __ movsd(Address(ESP, 0), XMM2);
3180 __ fldl(Address(ESP, 0));
3181 __ popl(EAX);
3182 __ popl(EAX);
3183 __ ret();
3184}
3185
3186ASSEMBLER_TEST_RUN(FloatToDoubleConversion, test) {
3187 typedef double (*FloatToDoubleConversionCode)();
3188 double res = reinterpret_cast<FloatToDoubleConversionCode>(test->entry())();
3189 EXPECT_FLOAT_EQ(12.3, res, 0.001);
3190 EXPECT_DISASSEMBLY(
3191 "mov eax,0x4144cccd\n"
3192 "movd xmm1,eax\n"
3193 "xor eax,eax\n"
3194 "cvtss2sd xmm2,xmm1\n"
3195 "push eax\n"
3196 "push eax\n"
3197 "movsd [esp],xmm2\n"
3198 "fld_d [esp]\n"
3199 "pop eax\n"
3200 "pop eax\n"
3201 "ret\n");
3202}
3203
3204ASSEMBLER_TEST_GENERATE(FloatCompare, assembler) {
3205 // Count errors in EAX. EAX is zero if no errors found.
3206 Label is_nan, is_above, is_ok, cont_1, cont_2;
3207 // Test 12.3f vs 12.5f.
3208 __ xorl(EAX, EAX);
3209 __ movl(EDX, Immediate(bit_cast<int32_t, float>(12.3f)));
3210 __ movd(XMM0, EDX);
3211 __ movl(EDX, Immediate(bit_cast<int32_t, float>(12.5f)));
3212 __ movd(XMM1, EDX);
3213 __ comiss(XMM0, XMM1);
3214 __ j(PARITY_EVEN, &is_nan);
3215 __ Bind(&cont_1);
3216 __ j(ABOVE, &is_above);
3217 __ Bind(&cont_2);
3218 __ j(BELOW, &is_ok);
3219 __ incl(EAX);
3220 __ Bind(&is_ok);
3221
3222 // Test NaN.
3223 Label is_nan_ok;
3224 // Create NaN by dividing 0.0f/0.0f.
3225 __ movl(EDX, Immediate(bit_cast<int32_t, float>(0.0f)));
3226 __ movd(XMM1, EDX);
3227 __ divss(XMM1, XMM1);
3228 __ comiss(XMM1, XMM1);
3229 __ j(PARITY_EVEN, &is_nan_ok);
3230 __ incl(EAX);
3231 __ Bind(&is_nan_ok);
3232
3233 // EAX is 0 if all tests passed.
3234 __ ret();
3235
3236 __ Bind(&is_nan);
3237 __ incl(EAX);
3238 __ jmp(&cont_1);
3239
3240 __ Bind(&is_above);
3241 __ incl(EAX);
3242 __ jmp(&cont_2);
3243}
3244
3245ASSEMBLER_TEST_RUN(FloatCompare, test) {
3246 typedef int (*FloatCompareCode)();
3247 int res = reinterpret_cast<FloatCompareCode>(test->entry())();
3248 EXPECT_EQ(0, res);
3249 EXPECT_DISASSEMBLY(
3250 "xor eax,eax\n"
3251 "mov edx,0x4144cccd\n"
3252 "movd xmm0,edx\n"
3253 "mov edx,0x41480000\n"
3254 "movd xmm1,edx\n"
3255 "comiss xmm0,xmm1\n"
3256 "jpe +43\n"
3257 "ja +40\n"
3258 "jc +7\n"
3259 "inc eax\n"
3260 "mov edx,0\n"
3261 "movd xmm1,edx\n"
3262 "divss xmm1,xmm1\n"
3263 "comiss xmm1,xmm1\n"
3264 "jpe +7\n"
3265 "inc eax\n"
3266 "ret\n"
3267 "inc eax\n"
3268 "jmp -38\n"
3269 "inc eax\n"
3270 "jmp -35\n");
3271}
3272
3273ASSEMBLER_TEST_GENERATE(DoubleCompare, assembler) {
3274 int64_t a = bit_cast<int64_t, double>(12.3);
3275 int64_t b = bit_cast<int64_t, double>(12.5);
3276
3277 __ movl(EDX, Immediate(Utils::High32Bits(a)));
3278 __ pushl(EDX);
3279 __ movl(EDX, Immediate(Utils::Low32Bits(a)));
3280 __ pushl(EDX);
3281 __ movsd(XMM0, Address(ESP, 0));
3282 __ popl(EDX);
3283 __ popl(EDX);
3284
3285 __ movl(EDX, Immediate(Utils::High32Bits(b)));
3286 __ pushl(EDX);
3287 __ movl(EDX, Immediate(Utils::Low32Bits(b)));
3288 __ pushl(EDX);
3289 __ movsd(XMM1, Address(ESP, 0));
3290 __ popl(EDX);
3291 __ popl(EDX);
3292
3293 // Count errors in EAX. EAX is zero if no errors found.
3294 Label is_nan, is_above, is_ok, cont_1, cont_2;
3295 // Test 12.3 vs 12.5.
3296 __ xorl(EAX, EAX);
3297 __ comisd(XMM0, XMM1);
3298 __ j(PARITY_EVEN, &is_nan);
3299 __ Bind(&cont_1);
3300 __ j(ABOVE, &is_above);
3301 __ Bind(&cont_2);
3302 __ j(BELOW, &is_ok);
3303 __ incl(EAX);
3304 __ Bind(&is_ok);
3305
3306 // Test NaN.
3307 Label is_nan_ok;
3308 // Create NaN by dividing 0.0d/0.0d.
3309 int64_t zero = bit_cast<int64_t, double>(0.0);
3310 __ movl(EDX, Immediate(Utils::High32Bits(zero)));
3311 __ pushl(EDX);
3312 __ movl(EDX, Immediate(Utils::Low32Bits(zero)));
3313 __ pushl(EDX);
3314 __ movsd(XMM1, Address(ESP, 0));
3315 __ popl(EDX);
3316 __ popl(EDX);
3317
3318 __ divsd(XMM1, XMM1);
3319 __ comisd(XMM1, XMM1);
3320 __ j(PARITY_EVEN, &is_nan_ok);
3321 __ incl(EAX);
3322 __ Bind(&is_nan_ok);
3323
3324 // EAX is 0 if all tests passed.
3325 __ ret();
3326
3327 __ Bind(&is_nan);
3328 __ incl(EAX);
3329 __ jmp(&cont_1);
3330
3331 __ Bind(&is_above);
3332 __ incl(EAX);
3333 __ jmp(&cont_2);
3334}
3335
3336ASSEMBLER_TEST_RUN(DoubleCompare, test) {
3337 typedef int (*DoubleCompareCode)();
3338 int res = reinterpret_cast<DoubleCompareCode>(test->entry())();
3339 EXPECT_EQ(0, res);
3340 EXPECT_DISASSEMBLY(
3341 "mov edx,0x40289999\n"
3342 "push edx\n"
3343 "mov edx,0x9999999a\n"
3344 "push edx\n"
3345 "movsd xmm0,[esp]\n"
3346 "pop edx\n"
3347 "pop edx\n"
3348 "mov edx,0x40290000\n"
3349 "push edx\n"
3350 "mov edx,0\n"
3351 "push edx\n"
3352 "movsd xmm1,[esp]\n"
3353 "pop edx\n"
3354 "pop edx\n"
3355 "xor eax,eax\n"
3356 "comisd xmm0,xmm1\n"
3357 "jpe +54\n"
3358 "ja +51\n"
3359 "jc +7\n"
3360 "inc eax\n"
3361 "mov edx,0\n"
3362 "push edx\n"
3363 "mov edx,0\n"
3364 "push edx\n"
3365 "movsd xmm1,[esp]\n"
3366 "pop edx\n"
3367 "pop edx\n"
3368 "divsd xmm1,xmm1\n"
3369 "comisd xmm1,xmm1\n"
3370 "jpe +7\n"
3371 "inc eax\n"
3372 "ret\n"
3373 "inc eax\n"
3374 "jmp -49\n"
3375 "inc eax\n"
3376 "jmp -46\n");
3377}
3378
3379ASSEMBLER_TEST_GENERATE(DoubleToFloatConversion, assembler) {
3380 int64_t l = bit_cast<int64_t, double>(12.3);
3381 __ movl(EAX, Immediate(Utils::High32Bits(l)));
3382 __ pushl(EAX);
3383 __ movl(EAX, Immediate(Utils::Low32Bits(l)));
3384 __ pushl(EAX);
3385 __ movsd(XMM0, Address(ESP, 0));
3386 __ cvtsd2ss(XMM1, XMM0);
3387 __ movss(Address(ESP, 0), XMM1);
3388 __ flds(Address(ESP, 0));
3389 __ popl(EAX);
3390 __ popl(EAX);
3391 __ ret();
3392}
3393
3394ASSEMBLER_TEST_RUN(DoubleToFloatConversion, test) {
3395 typedef float (*DoubleToFloatConversionCode)();
3396 float res = reinterpret_cast<DoubleToFloatConversionCode>(test->entry())();
3397 EXPECT_FLOAT_EQ(12.3f, res, 0.001);
3398 EXPECT_DISASSEMBLY(
3399 "mov eax,0x40289999\n"
3400 "push eax\n"
3401 "mov eax,0x9999999a\n"
3402 "push eax\n"
3403 "movsd xmm0,[esp]\n"
3404 "cvtsd2ss xmm1,xmm0\n"
3405 "movss [esp],xmm1\n"
3406 "fld_s [esp]\n"
3407 "pop eax\n"
3408 "pop eax\n"
3409 "ret\n");
3410}
3411
3412ASSEMBLER_TEST_GENERATE(DoubleToIntConversionRound, assembler) {
3413 __ movsd(XMM3, Address(ESP, target::kWordSize));
3414 __ cvtsd2si(EAX, XMM3);
3415 __ ret();
3416}
3417
3418ASSEMBLER_TEST_RUN(DoubleToIntConversionRound, test) {
3419 typedef int (*DoubleToIntConversionRoundCode)(double d);
3420 int res =
3421 reinterpret_cast<DoubleToIntConversionRoundCode>(test->entry())(12.3);
3422 EXPECT_EQ(12, res);
3423 res = reinterpret_cast<DoubleToIntConversionRoundCode>(test->entry())(12.8);
3424 EXPECT_EQ(13, res);
3425 EXPECT_DISASSEMBLY(
3426 "movsd xmm3,[esp+0x4]\n"
3427 "cvtsd2si eax,xmm3\n"
3428 "ret\n");
3429}
3430
3431ASSEMBLER_TEST_GENERATE(DoubleToIntConversionTrunc, assembler) {
3432 __ movsd(XMM3, Address(ESP, target::kWordSize));
3433 __ cvttsd2si(EAX, XMM3);
3434 __ ret();
3435}
3436
3437ASSEMBLER_TEST_RUN(DoubleToIntConversionTrunc, test) {
3438 typedef int (*DoubleToIntConversionTruncCode)(double d);
3439 int res =
3440 reinterpret_cast<DoubleToIntConversionTruncCode>(test->entry())(12.3);
3441 EXPECT_EQ(12, res);
3442 res = reinterpret_cast<DoubleToIntConversionTruncCode>(test->entry())(12.8);
3443 EXPECT_EQ(12, res);
3444 EXPECT_DISASSEMBLY(
3445 "movsd xmm3,[esp+0x4]\n"
3446 "cvttsd2si eax,xmm3\n"
3447 "ret\n");
3448}
3449
3450ASSEMBLER_TEST_GENERATE(DoubleToDoubleTrunc, assembler) {
3451 __ movsd(XMM3, Address(ESP, target::kWordSize));
3453 __ pushl(EAX);
3454 __ pushl(EAX);
3455 __ movsd(Address(ESP, 0), XMM2);
3456 __ fldl(Address(ESP, 0));
3457 __ popl(EAX);
3458 __ popl(EAX);
3459 __ ret();
3460}
3461
3462ASSEMBLER_TEST_RUN(DoubleToDoubleTrunc, test) {
3463 typedef double (*DoubleToDoubleTruncCode)(double d);
3464 double res = reinterpret_cast<DoubleToDoubleTruncCode>(test->entry())(12.3);
3465 EXPECT_EQ(12.0, res);
3466 res = reinterpret_cast<DoubleToDoubleTruncCode>(test->entry())(12.8);
3467 EXPECT_EQ(12.0, res);
3468 res = reinterpret_cast<DoubleToDoubleTruncCode>(test->entry())(-12.3);
3469 EXPECT_EQ(-12.0, res);
3470 res = reinterpret_cast<DoubleToDoubleTruncCode>(test->entry())(-12.8);
3471 EXPECT_EQ(-12.0, res);
3472 EXPECT_DISASSEMBLY(
3473 "movsd xmm3,[esp+0x4]\n"
3474 "roundsd edx, ebx, 3\n"
3475 "push eax\n"
3476 "push eax\n"
3477 "movsd [esp],xmm2\n"
3478 "fld_d [esp]\n"
3479 "pop eax\n"
3480 "pop eax\n"
3481 "ret\n");
3482}
3483
3484static const double kDoubleConst = 3.226;
3485
3486ASSEMBLER_TEST_GENERATE(GlobalAddress, assembler) {
3487 __ movsd(XMM0, Address::Absolute(reinterpret_cast<uword>(&kDoubleConst)));
3488 __ pushl(EAX);
3489 __ pushl(EAX);
3490 __ movsd(Address(ESP, 0), XMM0);
3491 __ fldl(Address(ESP, 0));
3492 __ popl(EAX);
3493 __ popl(EAX);
3494 __ ret();
3495}
3496
3497ASSEMBLER_TEST_RUN(GlobalAddress, test) {
3498 typedef double (*GlobalAddressCode)();
3499 double res = reinterpret_cast<GlobalAddressCode>(test->entry())();
3500 EXPECT_FLOAT_EQ(kDoubleConst, res, 0.000001);
3501 EXPECT_DISASSEMBLY(
3502 "movsd xmm0,[0x........]\n"
3503 "push eax\n"
3504 "push eax\n"
3505 "movsd [esp],xmm0\n"
3506 "fld_d [esp]\n"
3507 "pop eax\n"
3508 "pop eax\n"
3509 "ret\n");
3510}
3511
3512ASSEMBLER_TEST_GENERATE(Sine, assembler) {
3513 __ flds(Address(ESP, target::kWordSize));
3514 __ fsin();
3515 __ ret();
3516}
3517
3518ASSEMBLER_TEST_RUN(Sine, test) {
3519 typedef float (*SineCode)(float f);
3520 const float kFloatConst = 0.7;
3521 float res = reinterpret_cast<SineCode>(test->entry())(kFloatConst);
3522 EXPECT_FLOAT_EQ(sin(kFloatConst), res, 0.0001);
3523 EXPECT_DISASSEMBLY(
3524 "fld_s [esp+0x4]\n"
3525 "fsin\n"
3526 "ret\n");
3527}
3528
3529ASSEMBLER_TEST_GENERATE(Cosine, assembler) {
3530 __ flds(Address(ESP, target::kWordSize));
3531 __ fcos();
3532 __ ret();
3533}
3534
3535ASSEMBLER_TEST_RUN(Cosine, test) {
3536 typedef float (*CosineCode)(float f);
3537 const float kFloatConst = 0.7;
3538 float res = reinterpret_cast<CosineCode>(test->entry())(kFloatConst);
3539 EXPECT_FLOAT_EQ(cos(kFloatConst), res, 0.0001);
3540 EXPECT_DISASSEMBLY(
3541 "fld_s [esp+0x4]\n"
3542 "fcos\n"
3543 "ret\n");
3544}
3545
3546ASSEMBLER_TEST_GENERATE(SinCos, assembler) {
3547 __ fldl(Address(ESP, target::kWordSize));
3548 __ fsincos();
3549 __ subl(ESP, Immediate(2 * target::kWordSize));
3550 __ fstpl(Address(ESP, 0)); // cos result.
3551 __ movsd(XMM0, Address(ESP, 0));
3552 __ fstpl(Address(ESP, 0)); // sin result.
3553 __ movsd(XMM1, Address(ESP, 0));
3554 __ subsd(XMM1, XMM0); // sin - cos.
3555 __ movsd(Address(ESP, 0), XMM1);
3556 __ fldl(Address(ESP, 0));
3557 __ addl(ESP, Immediate(2 * target::kWordSize));
3558 __ ret();
3559}
3560
3561ASSEMBLER_TEST_RUN(SinCos, test) {
3562 typedef double (*SinCosCode)(double d);
3563 const double arg = 1.2345;
3564 const double expected = sin(arg) - cos(arg);
3565 double res = reinterpret_cast<SinCosCode>(test->entry())(arg);
3566 EXPECT_FLOAT_EQ(expected, res, 0.000001);
3567 EXPECT_DISASSEMBLY(
3568 "fld_d [esp+0x4]\n"
3569 "fsincos\n"
3570 "sub esp,8\n"
3571 "fstp_d [esp]\n"
3572 "movsd xmm0,[esp]\n"
3573 "fstp_d [esp]\n"
3574 "movsd xmm1,[esp]\n"
3575 "subsd xmm1,xmm0\n"
3576 "movsd [esp],xmm1\n"
3577 "fld_d [esp]\n"
3578 "add esp,8\n"
3579 "ret\n");
3580}
3581
3582ASSEMBLER_TEST_GENERATE(Tangent, assembler) {
3583 __ fldl(Address(ESP, target::kWordSize));
3584 __ fptan();
3585 __ ffree(0);
3586 __ fincstp();
3587 __ ret();
3588}
3589
3590ASSEMBLER_TEST_RUN(Tangent, test) {
3591 typedef double (*TangentCode)(double d);
3592 const double kDoubleConst = 0.6108652375000001;
3593 double res = reinterpret_cast<TangentCode>(test->entry())(kDoubleConst);
3594 EXPECT_FLOAT_EQ(tan(kDoubleConst), res, 0.0001);
3595 EXPECT_DISASSEMBLY(
3596 "fld_d [esp+0x4]\n"
3597 "fptan\n"
3598 "ffree st0\n"
3599 "fincstp\n"
3600 "ret\n");
3601}
3602
3603ASSEMBLER_TEST_GENERATE(SquareRootFloat, assembler) {
3604 __ movss(XMM0, Address(ESP, target::kWordSize));
3605 __ sqrtss(XMM1, XMM0);
3606 __ pushl(EAX);
3607 __ movss(Address(ESP, 0), XMM1);
3608 __ flds(Address(ESP, 0));
3609 __ popl(EAX);
3610 __ ret();
3611}
3612
3613ASSEMBLER_TEST_RUN(SquareRootFloat, test) {
3614 typedef float (*SquareRootFloatCode)(float f);
3615 const float kFloatConst = 0.7;
3616 float res = reinterpret_cast<SquareRootFloatCode>(test->entry())(kFloatConst);
3617 EXPECT_FLOAT_EQ(sqrt(kFloatConst), res, 0.0001);
3618 EXPECT_DISASSEMBLY(
3619 "movss xmm0,[esp+0x4]\n"
3620 "sqrtss xmm1,xmm0\n"
3621 "push eax\n"
3622 "movss [esp],xmm1\n"
3623 "fld_s [esp]\n"
3624 "pop eax\n"
3625 "ret\n");
3626}
3627
3628ASSEMBLER_TEST_GENERATE(SquareRootDouble, assembler) {
3629 __ movsd(XMM0, Address(ESP, target::kWordSize));
3630 __ sqrtsd(XMM1, XMM0);
3631 __ pushl(EAX);
3632 __ pushl(EAX);
3633 __ movsd(Address(ESP, 0), XMM1);
3634 __ fldl(Address(ESP, 0));
3635 __ popl(EAX);
3636 __ popl(EAX);
3637 __ ret();
3638}
3639
3640ASSEMBLER_TEST_RUN(SquareRootDouble, test) {
3641 typedef double (*SquareRootDoubleCode)(double d);
3642 const double kDoubleConst = .7;
3643 double res =
3644 reinterpret_cast<SquareRootDoubleCode>(test->entry())(kDoubleConst);
3645 EXPECT_FLOAT_EQ(sqrt(kDoubleConst), res, 0.0001);
3646 EXPECT_DISASSEMBLY(
3647 "movsd xmm0,[esp+0x4]\n"
3648 "sqrtsd xmm1,xmm0\n"
3649 "push eax\n"
3650 "push eax\n"
3651 "movsd [esp],xmm1\n"
3652 "fld_d [esp]\n"
3653 "pop eax\n"
3654 "pop eax\n"
3655 "ret\n");
3656}
3657
3658ASSEMBLER_TEST_GENERATE(XmmAlu, assembler) {
3659 // Test the disassembler.
3660 __ addss(XMM0, XMM0);
3661 __ addsd(XMM0, XMM0);
3662 __ addps(XMM0, XMM0);
3663 __ addpd(XMM0, XMM0);
3664 __ cvtss2sd(XMM0, XMM0);
3665 __ cvtsd2ss(XMM0, XMM0);
3666 __ cvtps2pd(XMM0, XMM0);
3667 __ cvtpd2ps(XMM0, XMM0);
3668 __ movl(EAX, Immediate(0));
3669 __ ret();
3670}
3671
3672ASSEMBLER_TEST_RUN(XmmAlu, test) {
3673 typedef intptr_t (*XmmAluTest)();
3674 intptr_t res = reinterpret_cast<XmmAluTest>(test->entry())();
3675 EXPECT_EQ(res, 0);
3676 EXPECT_DISASSEMBLY(
3677 "addss xmm0,xmm0\n"
3678 "addsd xmm0,xmm0\n"
3679 "addps xmm0,xmm0\n"
3680 "addpd xmm0,xmm0\n"
3681 "cvtss2sd xmm0,xmm0\n"
3682 "cvtsd2ss xmm0,xmm0\n"
3683 "cvtps2pd xmm0,xmm0\n"
3684 "cvtpd2ps xmm0,xmm0\n"
3685 "mov eax,0\n"
3686 "ret\n");
3687}
3688
3689ASSEMBLER_TEST_GENERATE(FloatNegate, assembler) {
3690 __ movss(XMM0, Address(ESP, target::kWordSize));
3691 __ FloatNegate(XMM0);
3692 __ pushl(EAX);
3693 __ movss(Address(ESP, 0), XMM0);
3694 __ flds(Address(ESP, 0));
3695 __ popl(EAX);
3696 __ ret();
3697}
3698
3699ASSEMBLER_TEST_RUN(FloatNegate, test) {
3700 typedef float (*FloatNegateCode)(float f);
3701 const float kFloatConst = 12.345;
3702 float res = reinterpret_cast<FloatNegateCode>(test->entry())(kFloatConst);
3703 EXPECT_FLOAT_EQ(-kFloatConst, res, 0.0001);
3704 EXPECT_DISASSEMBLY(
3705 "movss xmm0,[esp+0x4]\n"
3706 "xorps xmm0,[0x........]\n"
3707 "push eax\n"
3708 "movss [esp],xmm0\n"
3709 "fld_s [esp]\n"
3710 "pop eax\n"
3711 "ret\n");
3712}
3713
3714ASSEMBLER_TEST_GENERATE(DoubleNegate, assembler) {
3715 __ movsd(XMM0, Address(ESP, target::kWordSize));
3716 __ DoubleNegate(XMM0);
3717 __ pushl(EAX);
3718 __ pushl(EAX);
3719 __ movsd(Address(ESP, 0), XMM0);
3720 __ fldl(Address(ESP, 0));
3721 __ popl(EAX);
3722 __ popl(EAX);
3723 __ ret();
3724}
3725
3726ASSEMBLER_TEST_RUN(DoubleNegate, test) {
3727 typedef double (*DoubleNegateCode)(double f);
3728 const double kDoubleConst = 12.345;
3729 double res = reinterpret_cast<DoubleNegateCode>(test->entry())(kDoubleConst);
3730 EXPECT_FLOAT_EQ(-kDoubleConst, res, 0.0001);
3731 EXPECT_DISASSEMBLY(
3732 "movsd xmm0,[esp+0x4]\n"
3733 "xorpd xmm0,[0x........]\n"
3734 "push eax\n"
3735 "push eax\n"
3736 "movsd [esp],xmm0\n"
3737 "fld_d [esp]\n"
3738 "pop eax\n"
3739 "pop eax\n"
3740 "ret\n");
3741}
3742
3743ASSEMBLER_TEST_GENERATE(LongMulReg, assembler) {
3744 __ movl(ECX, Address(ESP, target::kWordSize));
3745 __ movl(EAX, Address(ESP, 2 * target::kWordSize));
3746 __ imull(ECX);
3747 __ ret();
3748}
3749
3750ASSEMBLER_TEST_RUN(LongMulReg, test) {
3751 typedef int64_t (*LongMulRegCode)(int a, int b);
3752 const int a = -12;
3753 const int b = 13;
3754 const int64_t mul_res = a * b;
3755 int64_t res = reinterpret_cast<LongMulRegCode>(test->entry())(a, b);
3756 EXPECT_EQ(mul_res, res);
3757 EXPECT_DISASSEMBLY(
3758 "mov ecx,[esp+0x4]\n"
3759 "mov eax,[esp+0x8]\n"
3760 "imul (eax,edx),ecx\n"
3761 "ret\n");
3762}
3763
3764ASSEMBLER_TEST_GENERATE(LongMulAddress, assembler) {
3765 __ movl(EAX, Address(ESP, 2 * target::kWordSize));
3766 __ imull(Address(ESP, target::kWordSize));
3767 __ ret();
3768}
3769
3770ASSEMBLER_TEST_RUN(LongMulAddress, test) {
3771 typedef int64_t (*LongMulAddressCode)(int a, int b);
3772 const int a = -12;
3773 const int b = 13;
3774 const int64_t mul_res = a * b;
3775 int64_t res = reinterpret_cast<LongMulAddressCode>(test->entry())(a, b);
3776 EXPECT_EQ(mul_res, res);
3777 EXPECT_DISASSEMBLY(
3778 "mov eax,[esp+0x8]\n"
3779 "imul (eax,edx),[esp+0x4]\n"
3780 "ret\n");
3781}
3782
3783ASSEMBLER_TEST_GENERATE(LongUnsignedMulReg, assembler) {
3784 __ movl(ECX, Address(ESP, target::kWordSize));
3785 __ movl(EAX, Address(ESP, 2 * target::kWordSize));
3786 __ mull(ECX);
3787 __ ret();
3788}
3789
3790ASSEMBLER_TEST_RUN(LongUnsignedMulReg, test) {
3791 typedef uint64_t (*LongUnsignedMulRegCode)(uint32_t a, uint32_t b);
3792 uint32_t a = 3;
3793 uint32_t b = 13;
3794 uint64_t mul_res = a * b;
3795 uint64_t res = reinterpret_cast<LongUnsignedMulRegCode>(test->entry())(a, b);
3796 EXPECT_EQ(mul_res, res);
3797 a = 4021288948u;
3798 b = 13;
3799 res = reinterpret_cast<LongUnsignedMulRegCode>(test->entry())(a, b);
3800 mul_res = static_cast<uint64_t>(a) * static_cast<uint64_t>(b);
3801 EXPECT_EQ(mul_res, res);
3802 EXPECT_DISASSEMBLY(
3803 "mov ecx,[esp+0x4]\n"
3804 "mov eax,[esp+0x8]\n"
3805 "mul (eax,edx),ecx\n"
3806 "ret\n");
3807}
3808
3809ASSEMBLER_TEST_GENERATE(LongUnsignedMulAddress, assembler) {
3810 __ movl(EAX, Address(ESP, 2 * target::kWordSize));
3811 __ mull(Address(ESP, target::kWordSize));
3812 __ ret();
3813}
3814
3815ASSEMBLER_TEST_RUN(LongUnsignedMulAddress, test) {
3816 typedef uint64_t (*LongUnsignedMulAddressCode)(uint32_t a, uint32_t b);
3817 uint32_t a = 12;
3818 uint32_t b = 13;
3819 uint64_t mul_res = a * b;
3820 uint64_t res =
3821 reinterpret_cast<LongUnsignedMulAddressCode>(test->entry())(a, b);
3822 EXPECT_EQ(mul_res, res);
3823 a = 4294967284u;
3824 b = 13;
3825 res = reinterpret_cast<LongUnsignedMulAddressCode>(test->entry())(a, b);
3826 mul_res = static_cast<uint64_t>(a) * static_cast<uint64_t>(b);
3827 EXPECT_EQ(mul_res, res);
3828 EXPECT_DISASSEMBLY(
3829 "mov eax,[esp+0x8]\n"
3830 "mul (eax,edx),[esp+0x4]\n"
3831 "ret\n");
3832}
3833
3834ASSEMBLER_TEST_GENERATE(LongAddReg, assembler) {
3835 // Preserve clobbered callee-saved register (EBX).
3836 __ pushl(EBX);
3837 __ movl(EAX, Address(ESP, 2 * target::kWordSize)); // left low.
3838 __ movl(EDX, Address(ESP, 3 * target::kWordSize)); // left high.
3839 __ movl(ECX, Address(ESP, 4 * target::kWordSize)); // right low.
3840 __ movl(EBX, Address(ESP, 5 * target::kWordSize)); // right high
3841 __ addl(EAX, ECX);
3842 __ adcl(EDX, EBX);
3843 __ popl(EBX);
3844 // Result is in EAX/EDX.
3845 __ ret();
3846}
3847
3848ASSEMBLER_TEST_RUN(LongAddReg, test) {
3849 typedef int64_t (*LongAddRegCode)(int64_t a, int64_t b);
3850 int64_t a = 12;
3851 int64_t b = 14;
3852 int64_t res = reinterpret_cast<LongAddRegCode>(test->entry())(a, b);
3853 EXPECT_EQ((a + b), res);
3854 a = 2147483647;
3855 b = 600000;
3856 res = reinterpret_cast<LongAddRegCode>(test->entry())(a, b);
3857 EXPECT_EQ((a + b), res);
3858 EXPECT_DISASSEMBLY(
3859 "push ebx\n"
3860 "mov eax,[esp+0x8]\n"
3861 "mov edx,[esp+0xc]\n"
3862 "mov ecx,[esp+0x10]\n"
3863 "mov ebx,[esp+0x14]\n"
3864 "add eax,ecx\n"
3865 "adc edx,ebx\n"
3866 "pop ebx\n"
3867 "ret\n");
3868}
3869
3870ASSEMBLER_TEST_GENERATE(LongAddAddress, assembler) {
3871 __ movl(EAX, Address(ESP, 1 * target::kWordSize)); // left low.
3872 __ movl(EDX, Address(ESP, 2 * target::kWordSize)); // left high.
3873 __ addl(EAX, Address(ESP, 3 * target::kWordSize)); // low.
3874 __ adcl(EDX, Address(ESP, 4 * target::kWordSize)); // high.
3875 // Result is in EAX/EDX.
3876 __ ret();
3877}
3878
3879ASSEMBLER_TEST_RUN(LongAddAddress, test) {
3880 typedef int64_t (*LongAddAddressCode)(int64_t a, int64_t b);
3881 int64_t a = 12;
3882 int64_t b = 14;
3883 int64_t res = reinterpret_cast<LongAddAddressCode>(test->entry())(a, b);
3884 EXPECT_EQ((a + b), res);
3885 a = 2147483647;
3886 b = 600000;
3887 res = reinterpret_cast<LongAddAddressCode>(test->entry())(a, b);
3888 EXPECT_EQ((a + b), res);
3889 EXPECT_DISASSEMBLY(
3890 "mov eax,[esp+0x4]\n"
3891 "mov edx,[esp+0x8]\n"
3892 "add eax,[esp+0xc]\n"
3893 "adc edx,[esp+0x10]\n"
3894 "ret\n");
3895}
3896
3897ASSEMBLER_TEST_GENERATE(LongSubReg, assembler) {
3898 // Preserve clobbered callee-saved register (EBX).
3899 __ pushl(EBX);
3900 __ movl(EAX, Address(ESP, 2 * target::kWordSize)); // left low.
3901 __ movl(EDX, Address(ESP, 3 * target::kWordSize)); // left high.
3902 __ movl(ECX, Address(ESP, 4 * target::kWordSize)); // right low.
3903 __ movl(EBX, Address(ESP, 5 * target::kWordSize)); // right high
3904 __ subl(EAX, ECX);
3905 __ sbbl(EDX, EBX);
3906 __ popl(EBX);
3907 // Result is in EAX/EDX.
3908 __ ret();
3909}
3910
3911ASSEMBLER_TEST_RUN(LongSubReg, test) {
3912 typedef int64_t (*LongSubRegCode)(int64_t a, int64_t b);
3913 int64_t a = 12;
3914 int64_t b = 14;
3915 int64_t res = reinterpret_cast<LongSubRegCode>(test->entry())(a, b);
3916 EXPECT_EQ((a - b), res);
3917 a = 600000;
3918 b = 2147483647;
3919 res = reinterpret_cast<LongSubRegCode>(test->entry())(a, b);
3920 EXPECT_EQ((a - b), res);
3921 EXPECT_DISASSEMBLY(
3922 "push ebx\n"
3923 "mov eax,[esp+0x8]\n"
3924 "mov edx,[esp+0xc]\n"
3925 "mov ecx,[esp+0x10]\n"
3926 "mov ebx,[esp+0x14]\n"
3927 "sub eax,ecx\n"
3928 "sbb edx,ebx\n"
3929 "pop ebx\n"
3930 "ret\n");
3931}
3932
3933ASSEMBLER_TEST_GENERATE(LongSubAddress, assembler) {
3934 __ movl(EAX, Address(ESP, 1 * target::kWordSize)); // left low.
3935 __ movl(EDX, Address(ESP, 2 * target::kWordSize)); // left high.
3936 __ subl(EAX, Address(ESP, 3 * target::kWordSize)); // low.
3937 __ sbbl(EDX, Address(ESP, 4 * target::kWordSize)); // high.
3938 // Result is in EAX/EDX.
3939 __ ret();
3940}
3941
3942ASSEMBLER_TEST_RUN(LongSubAddress, test) {
3943 typedef int64_t (*LongSubAddressCode)(int64_t a, int64_t b);
3944 int64_t a = 12;
3945 int64_t b = 14;
3946 int64_t res = reinterpret_cast<LongSubAddressCode>(test->entry())(a, b);
3947 EXPECT_EQ((a - b), res);
3948 a = 600000;
3949 b = 2147483647;
3950 res = reinterpret_cast<LongSubAddressCode>(test->entry())(a, b);
3951 EXPECT_EQ((a - b), res);
3952 EXPECT_DISASSEMBLY(
3953 "mov eax,[esp+0x4]\n"
3954 "mov edx,[esp+0x8]\n"
3955 "sub eax,[esp+0xc]\n"
3956 "sbb edx,[esp+0x10]\n"
3957 "ret\n");
3958}
3959
3960ASSEMBLER_TEST_GENERATE(LongSubAddress2, assembler) {
3961 // Preserve clobbered callee-saved register (EBX).
3962 __ pushl(EBX);
3963 __ movl(EAX, Address(ESP, 2 * target::kWordSize)); // left low.
3964 __ movl(EDX, Address(ESP, 3 * target::kWordSize)); // left high.
3965 __ movl(ECX, Address(ESP, 4 * target::kWordSize)); // right low.
3966 __ movl(EBX, Address(ESP, 5 * target::kWordSize)); // right high
3967 __ subl(ESP, Immediate(2 * target::kWordSize));
3968 __ movl(Address(ESP, 0 * target::kWordSize), EAX); // left low.
3969 __ movl(Address(ESP, 1 * target::kWordSize), EDX); // left high.
3970 __ subl(Address(ESP, 0 * target::kWordSize), ECX);
3971 __ sbbl(Address(ESP, 1 * target::kWordSize), EBX);
3972 __ movl(EAX, Address(ESP, 0 * target::kWordSize));
3973 __ movl(EDX, Address(ESP, 1 * target::kWordSize));
3974 __ addl(ESP, Immediate(2 * target::kWordSize));
3975 __ popl(EBX);
3976 // Result is in EAX/EDX.
3977 __ ret();
3978}
3979
3980ASSEMBLER_TEST_RUN(LongSubAddress2, test) {
3981 typedef int64_t (*LongSubAddress2Code)(int64_t a, int64_t b);
3982 int64_t a = 12;
3983 int64_t b = 14;
3984 int64_t res = reinterpret_cast<LongSubAddress2Code>(test->entry())(a, b);
3985 EXPECT_EQ((a - b), res);
3986 a = 600000;
3987 b = 2147483647;
3988 res = reinterpret_cast<LongSubAddress2Code>(test->entry())(a, b);
3989 EXPECT_EQ((a - b), res);
3990 EXPECT_DISASSEMBLY(
3991 "push ebx\n"
3992 "mov eax,[esp+0x8]\n"
3993 "mov edx,[esp+0xc]\n"
3994 "mov ecx,[esp+0x10]\n"
3995 "mov ebx,[esp+0x14]\n"
3996 "sub esp,8\n"
3997 "mov [esp],eax\n"
3998 "mov [esp+0x4],edx\n"
3999 "sub [esp],ecx\n"
4000 "sbb [esp+0x4],ebx\n"
4001 "mov eax,[esp]\n"
4002 "mov edx,[esp+0x4]\n"
4003 "add esp,8\n"
4004 "pop ebx\n"
4005 "ret\n");
4006}
4007
4008ASSEMBLER_TEST_GENERATE(LongAddAddress2, assembler) {
4009 // Preserve clobbered callee-saved register (EBX).
4010 __ pushl(EBX);
4011 __ movl(EAX, Address(ESP, 2 * target::kWordSize)); // left low.
4012 __ movl(EDX, Address(ESP, 3 * target::kWordSize)); // left high.
4013 __ movl(ECX, Address(ESP, 4 * target::kWordSize)); // right low.
4014 __ movl(EBX, Address(ESP, 5 * target::kWordSize)); // right high
4015 __ subl(ESP, Immediate(2 * target::kWordSize));
4016 __ movl(Address(ESP, 0 * target::kWordSize), EAX); // left low.
4017 __ movl(Address(ESP, 1 * target::kWordSize), EDX); // left high.
4018 __ addl(Address(ESP, 0 * target::kWordSize), ECX);
4019 __ adcl(Address(ESP, 1 * target::kWordSize), EBX);
4020 __ movl(EAX, Address(ESP, 0 * target::kWordSize));
4021 __ movl(EDX, Address(ESP, 1 * target::kWordSize));
4022 __ addl(ESP, Immediate(2 * target::kWordSize));
4023 __ popl(EBX);
4024 // Result is in EAX/EDX.
4025 __ ret();
4026}
4027
4028ASSEMBLER_TEST_RUN(LongAddAddress2, test) {
4029 typedef int64_t (*LongAddAddress2Code)(int64_t a, int64_t b);
4030 int64_t a = 12;
4031 int64_t b = 14;
4032 int64_t res = reinterpret_cast<LongAddAddress2Code>(test->entry())(a, b);
4033 EXPECT_EQ((a + b), res);
4034 a = 600000;
4035 b = 2147483647;
4036 res = reinterpret_cast<LongAddAddress2Code>(test->entry())(a, b);
4037 EXPECT_EQ((a + b), res);
4038 EXPECT_DISASSEMBLY(
4039 "push ebx\n"
4040 "mov eax,[esp+0x8]\n"
4041 "mov edx,[esp+0xc]\n"
4042 "mov ecx,[esp+0x10]\n"
4043 "mov ebx,[esp+0x14]\n"
4044 "sub esp,8\n"
4045 "mov [esp],eax\n"
4046 "mov [esp+0x4],edx\n"
4047 "add [esp],ecx\n"
4048 "adc [esp+0x4],ebx\n"
4049 "mov eax,[esp]\n"
4050 "mov edx,[esp+0x4]\n"
4051 "add esp,8\n"
4052 "pop ebx\n"
4053 "ret\n");
4054}
4055
4056// Testing only the lower 64-bit value of 'cvtdq2pd'.
4057ASSEMBLER_TEST_GENERATE(IntegerToDoubleConversion, assembler) {
4058 __ movsd(XMM1, Address(ESP, target::kWordSize));
4059 __ cvtdq2pd(XMM2, XMM1);
4060 __ pushl(EAX);
4061 __ pushl(EAX);
4062 __ movsd(Address(ESP, 0), XMM2);
4063 __ fldl(Address(ESP, 0));
4064 __ popl(EAX);
4065 __ popl(EAX);
4066 __ ret();
4067}
4068
4069ASSEMBLER_TEST_RUN(IntegerToDoubleConversion, test) {
4070 typedef double (*IntegerToDoubleConversionCode)(int32_t);
4071 const int32_t val = -12;
4072 double res =
4073 reinterpret_cast<IntegerToDoubleConversionCode>(test->entry())(val);
4074 EXPECT_FLOAT_EQ(static_cast<double>(val), res, 0.001);
4075 EXPECT_DISASSEMBLY(
4076 "movsd xmm1,[esp+0x4]\n"
4077 "cvtdq2pd xmm2,xmm1\n"
4078 "push eax\n"
4079 "push eax\n"
4080 "movsd [esp],xmm2\n"
4081 "fld_d [esp]\n"
4082 "pop eax\n"
4083 "pop eax\n"
4084 "ret\n");
4085}
4086
4087// Implement with truncation.
4088ASSEMBLER_TEST_GENERATE(FPUStoreLong, assembler) {
4089 __ fldl(Address(ESP, target::kWordSize));
4090 __ pushl(EAX);
4091 __ pushl(EAX);
4092 __ fnstcw(Address(ESP, 0));
4093 __ movzxw(EAX, Address(ESP, 0));
4094 __ orl(EAX, Immediate(0x0c00));
4095 __ movw(Address(ESP, target::kWordSize), EAX);
4096 __ fldcw(Address(ESP, target::kWordSize));
4097 __ pushl(EAX);
4098 __ pushl(EAX);
4099 __ fistpl(Address(ESP, 0));
4100 __ popl(EAX);
4101 __ popl(EDX);
4102 __ fldcw(Address(ESP, 0));
4103 __ addl(ESP, Immediate(target::kWordSize * 2));
4104 __ ret();
4105}
4106
4107ASSEMBLER_TEST_RUN(FPUStoreLong, test) {
4108 typedef int64_t (*FPUStoreLongCode)(double d);
4109 double val = 12.2;
4110 int64_t res = reinterpret_cast<FPUStoreLongCode>(test->entry())(val);
4111 EXPECT_EQ(static_cast<int64_t>(val), res);
4112 val = -12.2;
4113 res = reinterpret_cast<FPUStoreLongCode>(test->entry())(val);
4114 EXPECT_EQ(static_cast<int64_t>(val), res);
4115 val = 12.8;
4116 res = reinterpret_cast<FPUStoreLongCode>(test->entry())(val);
4117 EXPECT_EQ(static_cast<int64_t>(val), res);
4118 val = -12.8;
4119 res = reinterpret_cast<FPUStoreLongCode>(test->entry())(val);
4120 EXPECT_EQ(static_cast<int64_t>(val), res);
4121 EXPECT_DISASSEMBLY(
4122 "fld_d [esp+0x4]\n"
4123 "push eax\n"
4124 "push eax\n"
4125 "fnstcw [esp]\n"
4126 "movzxw eax,[esp]\n"
4127 "or eax,0xc00\n"
4128 "movw [esp+0x4],eax\n"
4129 "fldcw [esp+0x4]\n"
4130 "push eax\n"
4131 "push eax\n"
4132 "fistp_d [esp]\n"
4133 "pop eax\n"
4134 "pop edx\n"
4135 "fldcw [esp]\n"
4136 "add esp,8\n"
4137 "ret\n");
4138}
4139
4140ASSEMBLER_TEST_GENERATE(XorpdZeroing, assembler) {
4141 __ movsd(XMM0, Address(ESP, target::kWordSize));
4142 __ xorpd(XMM0, XMM0);
4143 __ pushl(EAX);
4144 __ pushl(EAX);
4145 __ movsd(Address(ESP, 0), XMM0);
4146 __ fldl(Address(ESP, 0));
4147 __ popl(EAX);
4148 __ popl(EAX);
4149 __ ret();
4150}
4151
4152ASSEMBLER_TEST_RUN(XorpdZeroing, test) {
4153 typedef double (*XorpdZeroingCode)(double d);
4154 double res = reinterpret_cast<XorpdZeroingCode>(test->entry())(12.56e3);
4155 EXPECT_FLOAT_EQ(0.0, res, 0.0001);
4156 EXPECT_DISASSEMBLY(
4157 "movsd xmm0,[esp+0x4]\n"
4158 "xorpd xmm0,xmm0\n"
4159 "push eax\n"
4160 "push eax\n"
4161 "movsd [esp],xmm0\n"
4162 "fld_d [esp]\n"
4163 "pop eax\n"
4164 "pop eax\n"
4165 "ret\n");
4166}
4167
4168ASSEMBLER_TEST_GENERATE(Pxor, assembler) {
4169 __ movsd(XMM0, Address(ESP, target::kWordSize));
4170 __ pxor(XMM0, XMM0);
4171 __ pushl(EAX);
4172 __ pushl(EAX);
4173 __ movsd(Address(ESP, 0), XMM0);
4174 __ fldl(Address(ESP, 0));
4175 __ popl(EAX);
4176 __ popl(EAX);
4177 __ ret();
4178}
4179
4180ASSEMBLER_TEST_RUN(Pxor, test) {
4181 typedef double (*PxorCode)(double d);
4182 double res = reinterpret_cast<PxorCode>(test->entry())(12.3456e3);
4183 EXPECT_FLOAT_EQ(0.0, res, 0.0);
4184 EXPECT_DISASSEMBLY(
4185 "movsd xmm0,[esp+0x4]\n"
4186 "pxor xmm0,xmm0\n"
4187 "push eax\n"
4188 "push eax\n"
4189 "movsd [esp],xmm0\n"
4190 "fld_d [esp]\n"
4191 "pop eax\n"
4192 "pop eax\n"
4193 "ret\n");
4194}
4195
4196ASSEMBLER_TEST_GENERATE(Orpd, assembler) {
4197 __ movsd(XMM0, Address(ESP, target::kWordSize));
4198 __ xorpd(XMM1, XMM1);
4199 __ DoubleNegate(XMM1);
4200 __ orpd(XMM0, XMM1);
4201 __ pushl(EAX);
4202 __ pushl(EAX);
4203 __ movsd(Address(ESP, 0), XMM0);
4204 __ fldl(Address(ESP, 0));
4205 __ popl(EAX);
4206 __ popl(EAX);
4207 __ ret();
4208}
4209
4210ASSEMBLER_TEST_RUN(Orpd, test) {
4211 typedef double (*OrpdCode)(double d);
4212 double res = reinterpret_cast<OrpdCode>(test->entry())(12.56e3);
4213 EXPECT_FLOAT_EQ(-12.56e3, res, 0.0);
4214 EXPECT_DISASSEMBLY(
4215 "movsd xmm0,[esp+0x4]\n"
4216 "xorpd xmm1,xmm1\n"
4217 "xorpd xmm1,[0x........]\n"
4218 "orpd xmm0,xmm1\n"
4219 "push eax\n"
4220 "push eax\n"
4221 "movsd [esp],xmm0\n"
4222 "fld_d [esp]\n"
4223 "pop eax\n"
4224 "pop eax\n"
4225 "ret\n");
4226}
4227
4228ASSEMBLER_TEST_GENERATE(Pextrd0, assembler) {
4230 __ movsd(XMM0, Address(ESP, target::kWordSize));
4231 __ pextrd(EAX, XMM0, Immediate(0));
4232 }
4233 __ ret();
4234}
4235
4236ASSEMBLER_TEST_RUN(Pextrd0, test) {
4238 typedef int32_t (*PextrdCode0)(double d);
4239 int32_t res = reinterpret_cast<PextrdCode0>(test->entry())(123456789);
4240 EXPECT_EQ(0x54000000, res);
4241 }
4242 EXPECT_DISASSEMBLY(
4243 "movsd xmm0,[esp+0x4]\n"
4244 "pextrd eax,xmm0,0\n"
4245 "ret\n");
4246}
4247
4248ASSEMBLER_TEST_GENERATE(Pextrd1, assembler) {
4250 __ movsd(XMM0, Address(ESP, target::kWordSize));
4251 __ pextrd(EAX, XMM0, Immediate(1));
4252 }
4253 __ ret();
4254}
4255
4256ASSEMBLER_TEST_RUN(Pextrd1, test) {
4258 typedef int32_t (*PextrdCode1)(double d);
4259 int32_t res = reinterpret_cast<PextrdCode1>(test->entry())(123456789);
4260 EXPECT_EQ(0x419d6f34, res);
4261 }
4262 EXPECT_DISASSEMBLY(
4263 "movsd xmm0,[esp+0x4]\n"
4264 "pextrd eax,xmm0,1\n"
4265 "ret\n");
4266}
4267
4268ASSEMBLER_TEST_GENERATE(Pmovsxdq, assembler) {
4270 __ movsd(XMM0, Address(ESP, target::kWordSize));
4271 __ pmovsxdq(XMM0, XMM0);
4272 __ pextrd(EAX, XMM0, Immediate(1));
4273 }
4274 __ ret();
4275}
4276
4277ASSEMBLER_TEST_RUN(Pmovsxdq, test) {
4279 typedef int32_t (*PmovsxdqCode)(double d);
4280 int32_t res = reinterpret_cast<PmovsxdqCode>(test->entry())(123456789);
4281 EXPECT_EQ(0, res);
4282 }
4283 EXPECT_DISASSEMBLY(
4284 "movsd xmm0,[esp+0x4]\n"
4285 "pmovsxdq xmm0,xmm0\n"
4286 "pextrd eax,xmm0,1\n"
4287 "ret\n");
4288}
4289
4290ASSEMBLER_TEST_GENERATE(Pcmpeqq, assembler) {
4292 __ movsd(XMM0, Address(ESP, target::kWordSize));
4293 __ xorpd(XMM1, XMM1);
4294 __ pcmpeqq(XMM0, XMM1);
4295 __ movd(EAX, XMM0);
4296 }
4297 __ ret();
4298}
4299
4300ASSEMBLER_TEST_RUN(Pcmpeqq, test) {
4302 typedef int32_t (*PcmpeqqCode)(double d);
4303 int32_t res = reinterpret_cast<PcmpeqqCode>(test->entry())(0);
4304 EXPECT_EQ(-1, res);
4305 }
4306 EXPECT_DISASSEMBLY(
4307 "movsd xmm0,[esp+0x4]\n"
4308 "xorpd xmm1,xmm1\n"
4309 "pcmpeqq xmm0,xmm1\n"
4310 "movd eax,xmm0\n"
4311 "ret\n");
4312}
4313
4314ASSEMBLER_TEST_GENERATE(AndPd, assembler) {
4315 __ movsd(XMM0, Address(ESP, target::kWordSize));
4316 __ andpd(XMM0, XMM0);
4317 __ pushl(EAX);
4318 __ pushl(EAX);
4319 __ movsd(Address(ESP, 0), XMM0);
4320 __ fldl(Address(ESP, 0));
4321 __ popl(EAX);
4322 __ popl(EAX);
4323 __ ret();
4324}
4325
4326ASSEMBLER_TEST_RUN(AndPd, test) {
4327 typedef double (*AndpdCode)(double d);
4328 double res = reinterpret_cast<AndpdCode>(test->entry())(12.56e3);
4329 EXPECT_FLOAT_EQ(12.56e3, res, 0.0);
4330 EXPECT_DISASSEMBLY(
4331 "movsd xmm0,[esp+0x4]\n"
4332 "andpd xmm0,xmm0\n"
4333 "push eax\n"
4334 "push eax\n"
4335 "movsd [esp],xmm0\n"
4336 "fld_d [esp]\n"
4337 "pop eax\n"
4338 "pop eax\n"
4339 "ret\n");
4340}
4341
4342ASSEMBLER_TEST_GENERATE(Movq, assembler) {
4343 __ movq(XMM0, Address(ESP, target::kWordSize));
4344 __ subl(ESP, Immediate(kDoubleSize));
4345 __ movq(Address(ESP, 0), XMM0);
4346 __ fldl(Address(ESP, 0));
4347 __ addl(ESP, Immediate(kDoubleSize));
4348 __ ret();
4349}
4350
4351ASSEMBLER_TEST_RUN(Movq, test) {
4352 typedef double (*MovqCode)(double d);
4353 double res = reinterpret_cast<MovqCode>(test->entry())(12.34e5);
4354 EXPECT_FLOAT_EQ(12.34e5, res, 0.0);
4355 EXPECT_DISASSEMBLY(
4356 "movq xmm0, [esp+0x4]\n"
4357 "sub esp,8\n"
4358 "movq [esp],xmm0\n"
4359 "fld_d [esp]\n"
4360 "add esp,8\n"
4361 "ret\n");
4362}
4363
4364ASSEMBLER_TEST_GENERATE(DoubleAbs, assembler) {
4365 __ movsd(XMM0, Address(ESP, target::kWordSize));
4366 __ DoubleAbs(XMM0);
4367 __ pushl(EAX);
4368 __ pushl(EAX);
4369 __ movsd(Address(ESP, 0), XMM0);
4370 __ fldl(Address(ESP, 0));
4371 __ popl(EAX);
4372 __ popl(EAX);
4373 __ ret();
4374}
4375
4376ASSEMBLER_TEST_RUN(DoubleAbs, test) {
4377 typedef double (*DoubleAbsCode)(double d);
4378 double val = -12.45;
4379 double res = reinterpret_cast<DoubleAbsCode>(test->entry())(val);
4380 EXPECT_FLOAT_EQ(-val, res, 0.001);
4381 val = 12.45;
4382 res = reinterpret_cast<DoubleAbsCode>(test->entry())(val);
4383 EXPECT_FLOAT_EQ(val, res, 0.001);
4384 EXPECT_DISASSEMBLY(
4385 "movsd xmm0,[esp+0x4]\n"
4386 "andpd xmm0,[0x........]\n"
4387 "push eax\n"
4388 "push eax\n"
4389 "movsd [esp],xmm0\n"
4390 "fld_d [esp]\n"
4391 "pop eax\n"
4392 "pop eax\n"
4393 "ret\n");
4394}
4395
4396ASSEMBLER_TEST_GENERATE(ExtractSignBits, assembler) {
4397 __ movsd(XMM0, Address(ESP, target::kWordSize));
4398 __ movmskpd(EAX, XMM0);
4399 __ andl(EAX, Immediate(0x1));
4400 __ ret();
4401}
4402
4403ASSEMBLER_TEST_RUN(ExtractSignBits, test) {
4404 typedef int (*ExtractSignBits)(double d);
4405 int res = reinterpret_cast<ExtractSignBits>(test->entry())(1.0);
4406 EXPECT_EQ(0, res);
4407 res = reinterpret_cast<ExtractSignBits>(test->entry())(-1.0);
4408 EXPECT_EQ(1, res);
4409 res = reinterpret_cast<ExtractSignBits>(test->entry())(-0.0);
4410 EXPECT_EQ(1, res);
4411 EXPECT_DISASSEMBLY(
4412 "movsd xmm0,[esp+0x4]\n"
4413 "movmskpd eax,xmm0\n"
4414 "and eax,1\n"
4415 "ret\n");
4416}
4417
4418// Return -1 if signed, 1 if not signed and 0 otherwise.
4419ASSEMBLER_TEST_GENERATE(ConditionalMovesSign, assembler) {
4420 // Preserve clobbered callee-saved register (EBX).
4421 __ pushl(EBX);
4422
4423 __ movl(EDX, Address(ESP, 2 * target::kWordSize));
4424 __ xorl(EAX, EAX);
4425 __ movl(EBX, Immediate(1));
4426 __ movl(ECX, Immediate(-1));
4427 __ testl(EDX, EDX);
4428 __ cmovs(EAX, ECX); // return -1.
4429 __ testl(EDX, EDX);
4430 __ cmovns(EAX, EBX); // return 1.
4431
4432 // Restore callee-saved register (EBX) and return.
4433 __ popl(EBX);
4434 __ ret();
4435}
4436
4437ASSEMBLER_TEST_RUN(ConditionalMovesSign, test) {
4438 typedef int (*ConditionalMovesSignCode)(int i);
4439 int res = reinterpret_cast<ConditionalMovesSignCode>(test->entry())(785);
4440 EXPECT_EQ(1, res);
4441 res = reinterpret_cast<ConditionalMovesSignCode>(test->entry())(-12);
4442 EXPECT_EQ(-1, res);
4443 EXPECT_DISASSEMBLY(
4444 "push ebx\n"
4445 "mov edx,[esp+0x8]\n"
4446 "xor eax,eax\n"
4447 "mov ebx,1\n"
4448 "mov ecx,0xffffffff\n"
4449 "test edx,edx\n"
4450 "cmovs eax,ecx\n"
4451 "test edx,edx\n"
4452 "cmovns eax,ebx\n"
4453 "pop ebx\n"
4454 "ret\n");
4455}
4456
4457// Return 1 if overflow, 0 if no overflow.
4458ASSEMBLER_TEST_GENERATE(ConditionalMovesNoOverflow, assembler) {
4459 __ movl(EDX, Address(ESP, 1 * target::kWordSize));
4460 __ addl(EDX, Address(ESP, 2 * target::kWordSize));
4461 __ movl(EAX, Immediate(1));
4462 __ movl(ECX, Immediate(0));
4463 __ cmovno(EAX, ECX);
4464 __ ret();
4465}
4466
4467ASSEMBLER_TEST_RUN(ConditionalMovesNoOverflow, test) {
4468 typedef int (*ConditionalMovesNoOverflowCode)(int i, int j);
4469 int res = reinterpret_cast<ConditionalMovesNoOverflowCode>(test->entry())(
4470 0x7fffffff, 2);
4471 EXPECT_EQ(1, res);
4472 res = reinterpret_cast<ConditionalMovesNoOverflowCode>(test->entry())(1, 1);
4473 EXPECT_EQ(0, res);
4474 EXPECT_DISASSEMBLY(
4475 "mov edx,[esp+0x4]\n"
4476 "add edx,[esp+0x8]\n"
4477 "mov eax,1\n"
4478 "mov ecx,0\n"
4479 "cmovno eax,ecx\n"
4480 "ret\n");
4481}
4482
4483// Return 1 if equal, 0 if not equal.
4484ASSEMBLER_TEST_GENERATE(ConditionalMovesEqual, assembler) {
4485 __ xorl(EAX, EAX);
4486 __ movl(ECX, Immediate(1));
4487 __ movl(EDX, Address(ESP, 1 * target::kWordSize));
4488 __ cmpl(EDX, Immediate(785));
4489 __ cmove(EAX, ECX);
4490 __ ret();
4491}
4492
4493ASSEMBLER_TEST_RUN(ConditionalMovesEqual, test) {
4494 typedef int (*ConditionalMovesEqualCode)(int i);
4495 int res = reinterpret_cast<ConditionalMovesEqualCode>(test->entry())(785);
4496 EXPECT_EQ(1, res);
4497 res = reinterpret_cast<ConditionalMovesEqualCode>(test->entry())(-12);
4498 EXPECT_EQ(0, res);
4499 EXPECT_DISASSEMBLY(
4500 "xor eax,eax\n"
4501 "mov ecx,1\n"
4502 "mov edx,[esp+0x4]\n"
4503 "cmp edx,0x311\n"
4504 "cmovz eax,ecx\n"
4505 "ret\n");
4506}
4507
4508// Return 1 if not equal, 0 if equal.
4509ASSEMBLER_TEST_GENERATE(ConditionalMovesNotEqual, assembler) {
4510 __ xorl(EAX, EAX);
4511 __ movl(ECX, Immediate(1));
4512 __ movl(EDX, Address(ESP, 1 * target::kWordSize));
4513 __ cmpl(EDX, Immediate(785));
4514 __ cmovne(EAX, ECX);
4515 __ ret();
4516}
4517
4518ASSEMBLER_TEST_RUN(ConditionalMovesNotEqual, test) {
4519 typedef int (*ConditionalMovesNotEqualCode)(int i);
4520 int res = reinterpret_cast<ConditionalMovesNotEqualCode>(test->entry())(785);
4521 EXPECT_EQ(0, res);
4522 res = reinterpret_cast<ConditionalMovesNotEqualCode>(test->entry())(-12);
4523 EXPECT_EQ(1, res);
4524 EXPECT_DISASSEMBLY(
4525 "xor eax,eax\n"
4526 "mov ecx,1\n"
4527 "mov edx,[esp+0x4]\n"
4528 "cmp edx,0x311\n"
4529 "cmovnz eax,ecx\n"
4530 "ret\n");
4531}
4532
4533ASSEMBLER_TEST_GENERATE(ConditionalMovesCompare, assembler) {
4534 __ movl(EDX, Immediate(1)); // Greater equal.
4535 __ movl(ECX, Immediate(-1)); // Less
4536 __ movl(EAX, Address(ESP, 1 * target::kWordSize));
4537 __ cmpl(EAX, Address(ESP, 2 * target::kWordSize));
4538 __ cmovlessl(EAX, ECX);
4539 __ cmovgel(EAX, EDX);
4540 __ ret();
4541}
4542
4543ASSEMBLER_TEST_RUN(ConditionalMovesCompare, test) {
4544 typedef int (*ConditionalMovesCompareCode)(int i, int j);
4545 int res = reinterpret_cast<ConditionalMovesCompareCode>(test->entry())(10, 5);
4546 EXPECT_EQ(1, res); // Greater equal.
4547 res = reinterpret_cast<ConditionalMovesCompareCode>(test->entry())(5, 5);
4548 EXPECT_EQ(1, res); // Greater equal.
4549 res = reinterpret_cast<ConditionalMovesCompareCode>(test->entry())(2, 5);
4550 EXPECT_EQ(-1, res); // Less.
4551 EXPECT_DISASSEMBLY(
4552 "mov edx,1\n"
4553 "mov ecx,0xffffffff\n"
4554 "mov eax,[esp+0x4]\n"
4555 "cmp eax,[esp+0x8]\n"
4556 "cmovl eax,ecx\n"
4557 "cmovge eax,edx\n"
4558 "ret\n");
4559}
4560
4561ASSEMBLER_TEST_GENERATE(TestLoadDImmediate, assembler) {
4562 __ LoadDImmediate(XMM3, -12.34);
4563 __ pushl(EAX);
4564 __ pushl(EAX);
4565 __ movsd(Address(ESP, 0), XMM3);
4566 __ fldl(Address(ESP, 0));
4567 __ popl(EAX);
4568 __ popl(EAX);
4569 __ ret();
4570}
4571
4572ASSEMBLER_TEST_RUN(TestLoadDImmediate, test) {
4573 typedef double (*TestLoadDImmediateCode)();
4574 double res = reinterpret_cast<TestLoadDImmediateCode>(test->entry())();
4575 EXPECT_FLOAT_EQ(-12.34, res, 0.0001);
4576 EXPECT_DISASSEMBLY(
4577 "push 0xc028ae14\n"
4578 "push 0x7ae147ae\n"
4579 "movsd xmm3,[esp]\n"
4580 "add esp,8\n"
4581 "push eax\n"
4582 "push eax\n"
4583 "movsd [esp],xmm3\n"
4584 "fld_d [esp]\n"
4585 "pop eax\n"
4586 "pop eax\n"
4587 "ret\n");
4588}
4589
4590ASSEMBLER_TEST_GENERATE(TestObjectCompare, assembler) {
4591 ObjectStore* object_store = IsolateGroup::Current()->object_store();
4592 const Object& obj = Object::ZoneHandle(object_store->smi_class());
4593 Label fail;
4594 __ LoadObject(EAX, obj);
4595 __ CompareObject(EAX, obj);
4596 __ j(NOT_EQUAL, &fail);
4597 __ LoadObject(ECX, obj);
4598 __ CompareObject(ECX, obj);
4599 __ j(NOT_EQUAL, &fail);
4600 __ movl(EAX, Immediate(1)); // OK
4601 __ ret();
4602 __ Bind(&fail);
4603 __ movl(EAX, Immediate(0)); // Fail.
4604 __ ret();
4605}
4606
4607ASSEMBLER_TEST_RUN(TestObjectCompare, test) {
4608 typedef bool (*TestObjectCompare)();
4609 bool res = reinterpret_cast<TestObjectCompare>(test->entry())();
4610 EXPECT_EQ(true, res);
4611 // Disassembly contains absolute addresses of objects that vary between runs.
4612}
4613
4614ASSEMBLER_TEST_GENERATE(TestSetCC, assembler) {
4615 __ movl(EAX, Immediate(0xFFFFFFFF));
4616 __ cmpl(EAX, EAX);
4617 __ setcc(NOT_EQUAL, AL);
4618 __ ret();
4619}
4620
4621ASSEMBLER_TEST_RUN(TestSetCC, test) {
4622 typedef uword (*TestSetCC)();
4623 uword res = reinterpret_cast<TestSetCC>(test->entry())();
4624 EXPECT_EQ(0xFFFFFF00, res);
4625 EXPECT_DISASSEMBLY(
4626 "mov eax,0xffffffff\n"
4627 "cmp eax,eax\n"
4628 "setnz al\n"
4629 "ret\n");
4630}
4631
4632ASSEMBLER_TEST_GENERATE(TestNop, assembler) {
4633 __ nop(1);
4634 __ nop(2);
4635 __ nop(3);
4636 __ nop(4);
4637 __ nop(5);
4638 __ nop(6);
4639 __ nop(7);
4640 __ nop(8);
4641 __ movl(EAX, Immediate(assembler->CodeSize())); // Return code size.
4642 __ ret();
4643}
4644
4645ASSEMBLER_TEST_RUN(TestNop, test) {
4646 typedef int (*TestNop)();
4647 int res = reinterpret_cast<TestNop>(test->entry())();
4648 EXPECT_EQ(36, res); // 36 nop bytes emitted.
4649 EXPECT_DISASSEMBLY(
4650 "nop\n"
4651 "nop\n"
4652 "nop\n"
4653 "nop\n"
4654 "nop\n"
4655 "nop\n"
4656 "nop\n"
4657 "nop\n"
4658 "mov eax,0x24\n"
4659 "ret\n");
4660}
4661
4662ASSEMBLER_TEST_GENERATE(TestAlign0, assembler) {
4663 __ Align(4, 0);
4664 __ movl(EAX, Immediate(assembler->CodeSize())); // Return code size.
4665 __ ret();
4666}
4667
4668ASSEMBLER_TEST_RUN(TestAlign0, test) {
4669 typedef int (*TestAlign0)();
4670 int res = reinterpret_cast<TestAlign0>(test->entry())();
4671 EXPECT_EQ(0, res); // 0 bytes emitted.
4672 EXPECT_DISASSEMBLY(
4673 "mov eax,0\n"
4674 "ret\n");
4675}
4676
4677ASSEMBLER_TEST_GENERATE(TestAlign1, assembler) {
4678 __ nop(1);
4679 __ Align(4, 0);
4680 __ movl(EAX, Immediate(assembler->CodeSize())); // Return code size.
4681 __ ret();
4682}
4683
4684ASSEMBLER_TEST_RUN(TestAlign1, test) {
4685 typedef int (*TestAlign1)();
4686 int res = reinterpret_cast<TestAlign1>(test->entry())();
4687 EXPECT_EQ(4, res); // 4 bytes emitted.
4688 EXPECT_DISASSEMBLY(
4689 "nop\n"
4690 "nop\n"
4691 "mov eax,4\n"
4692 "ret\n");
4693}
4694
4695ASSEMBLER_TEST_GENERATE(TestAlign1Offset1, assembler) {
4696 __ nop(1);
4697 __ Align(4, 1);
4698 __ movl(EAX, Immediate(assembler->CodeSize())); // Return code size.
4699 __ ret();
4700}
4701
4702ASSEMBLER_TEST_RUN(TestAlign1Offset1, test) {
4703 typedef int (*TestAlign1Offset1)();
4704 int res = reinterpret_cast<TestAlign1Offset1>(test->entry())();
4705 EXPECT_EQ(3, res); // 3 bytes emitted.
4706 EXPECT_DISASSEMBLY(
4707 "nop\n"
4708 "nop\n"
4709 "mov eax,3\n"
4710 "ret\n");
4711}
4712
4713ASSEMBLER_TEST_GENERATE(TestAlignLarge, assembler) {
4714 __ nop(1);
4715 __ Align(16, 0);
4716 __ movl(EAX, Immediate(assembler->CodeSize())); // Return code size.
4717 __ ret();
4718}
4719
4720ASSEMBLER_TEST_RUN(TestAlignLarge, test) {
4721 typedef int (*TestAlignLarge)();
4722 int res = reinterpret_cast<TestAlignLarge>(test->entry())();
4723 EXPECT_EQ(16, res); // 16 bytes emitted.
4724 EXPECT_DISASSEMBLY(
4725 "nop\n"
4726 "nop\n"
4727 "nop\n"
4728 "mov eax,0x10\n"
4729 "ret\n");
4730}
4731
4732ASSEMBLER_TEST_GENERATE(TestRepMovsBytes, assembler) {
4733 // Preserve registers.
4734 __ pushl(ESI);
4735 __ pushl(EDI);
4736 __ pushl(ECX);
4737 __ movl(ESI, Address(ESP, 4 * target::kWordSize)); // from.
4738 __ movl(EDI, Address(ESP, 5 * target::kWordSize)); // to.
4739 __ movl(ECX, Address(ESP, 6 * target::kWordSize)); // count.
4740 __ rep_movsb();
4741 __ popl(ECX);
4742 __ popl(EDI);
4743 __ popl(ESI);
4744 __ ret();
4745}
4746
4747ASSEMBLER_TEST_RUN(TestRepMovsBytes, test) {
4748 const char* from = "0123456789x";
4749 char* to = new char[11]{0};
4750 to[10] = 'y';
4751 typedef void (*TestRepMovsBytes)(const char* from, char* to, int count);
4752 reinterpret_cast<TestRepMovsBytes>(test->entry())(from, to, 10);
4753 EXPECT_EQ(to[0], '0');
4754 for (int i = 0; i < 10; i++) {
4755 EXPECT_EQ(from[i], to[i]);
4756 }
4757 EXPECT_EQ(to[10], 'y');
4758 delete[] to;
4759 EXPECT_DISASSEMBLY(
4760 "push esi\n"
4761 "push edi\n"
4762 "push ecx\n"
4763 "mov esi,[esp+0x10]\n"
4764 "mov edi,[esp+0x14]\n"
4765 "mov ecx,[esp+0x18]\n"
4766 "rep movsb\n"
4767 "pop ecx\n"
4768 "pop edi\n"
4769 "pop esi\n"
4770 "ret\n");
4771}
4772
4773ASSEMBLER_TEST_GENERATE(TestRepMovsWords, assembler) {
4774 // Preserve registers.
4775 __ pushl(ESI);
4776 __ pushl(EDI);
4777 __ pushl(ECX);
4778 __ movl(ESI, Address(ESP, 4 * target::kWordSize)); // from.
4779 __ movl(EDI, Address(ESP, 5 * target::kWordSize)); // to.
4780 __ movl(ECX, Address(ESP, 6 * target::kWordSize)); // count.
4781 __ rep_movsw();
4782 __ popl(ECX);
4783 __ popl(EDI);
4784 __ popl(ESI);
4785 __ ret();
4786}
4787
4788ASSEMBLER_TEST_RUN(TestRepMovsWords, test) {
4789 const uint16_t from[11] = {0x0123, 0x1234, 0x2345, 0x3456, 0x4567, 0x5678,
4790 0x6789, 0x789A, 0x89AB, 0x9ABC, 0xABCD};
4791 uint16_t* to = new uint16_t[11]{0};
4792 to[10] = 0xFEFE;
4793 typedef void (*TestRepMovsWords)(const uint16_t* from, uint16_t* to,
4794 int count);
4795 reinterpret_cast<TestRepMovsWords>(test->entry())(from, to, 10);
4796 EXPECT_EQ(to[0], 0x0123u);
4797 for (int i = 0; i < 10; i++) {
4798 EXPECT_EQ(from[i], to[i]);
4799 }
4800 EXPECT_EQ(to[10], 0xFEFEu);
4801 delete[] to;
4802 EXPECT_DISASSEMBLY(
4803 "push esi\n"
4804 "push edi\n"
4805 "push ecx\n"
4806 "mov esi,[esp+0x10]\n"
4807 "mov edi,[esp+0x14]\n"
4808 "mov ecx,[esp+0x18]\n"
4809 "rep movsw\n"
4810 "pop ecx\n"
4811 "pop edi\n"
4812 "pop esi\n"
4813 "ret\n");
4814}
4815
4816ASSEMBLER_TEST_GENERATE(TestRepMovsDwords, assembler) {
4817 // Preserve registers.
4818 __ pushl(ESI);
4819 __ pushl(EDI);
4820 __ pushl(ECX);
4821 __ movl(ESI, Address(ESP, 4 * target::kWordSize)); // from.
4822 __ movl(EDI, Address(ESP, 5 * target::kWordSize)); // to.
4823 __ movl(ECX, Address(ESP, 6 * target::kWordSize)); // count.
4824 __ rep_movsd();
4825 __ popl(ECX);
4826 __ popl(EDI);
4827 __ popl(ESI);
4828 __ ret();
4829}
4830
4831ASSEMBLER_TEST_RUN(TestRepMovsDwords, test) {
4832 const uint32_t from[11] = {0x01234567, 0x12345678, 0x23456789, 0x3456789A,
4833 0x456789AB, 0x56789ABC, 0x6789ABCD, 0x789ABCDE,
4834 0x89ABCDEF, 0x9ABCDEF0, 0xABCDEF01};
4835 uint32_t* to = new uint32_t[11]{0};
4836 to[10] = 0xFEFEFEFE;
4837 typedef void (*TestRepMovsDwords)(const uint32_t* from, uint32_t* to,
4838 int count);
4839 reinterpret_cast<TestRepMovsDwords>(test->entry())(from, to, 10);
4840 EXPECT_EQ(to[0], 0x01234567u);
4841 for (int i = 0; i < 10; i++) {
4842 EXPECT_EQ(from[i], to[i]);
4843 }
4844 EXPECT_EQ(to[10], 0xFEFEFEFEu);
4845 delete[] to;
4846 EXPECT_DISASSEMBLY(
4847 "push esi\n"
4848 "push edi\n"
4849 "push ecx\n"
4850 "mov esi,[esp+0x10]\n"
4851 "mov edi,[esp+0x14]\n"
4852 "mov ecx,[esp+0x18]\n"
4853 "rep movsl\n"
4854 "pop ecx\n"
4855 "pop edi\n"
4856 "pop esi\n"
4857 "ret\n");
4858}
4859
4860// Called from assembler_test.cc.
4861ASSEMBLER_TEST_GENERATE(StoreIntoObject, assembler) {
4862 __ pushl(THR);
4863 __ movl(EAX, Address(ESP, 2 * target::kWordSize));
4864 __ movl(ECX, Address(ESP, 3 * target::kWordSize));
4865 __ movl(THR, Address(ESP, 4 * target::kWordSize));
4866 __ pushl(EAX);
4867 __ StoreIntoObject(ECX, FieldAddress(ECX, GrowableObjectArray::data_offset()),
4868 EAX);
4869 __ popl(EAX);
4870 __ popl(THR);
4871 __ ret();
4872}
4873
4874ASSEMBLER_TEST_GENERATE(BitTestTest, assembler) {
4875 __ movl(EAX, Immediate(4));
4876 __ movl(ECX, Immediate(2));
4877 __ bt(EAX, ECX);
4878 Label ok;
4879 __ j(CARRY, &ok);
4880 __ int3();
4881 __ Bind(&ok);
4882 __ movl(EAX, Immediate(1));
4883 __ ret();
4884}
4885
4886ASSEMBLER_TEST_RUN(BitTestTest, test) {
4887 typedef int (*BitTest)();
4888 EXPECT_EQ(1, reinterpret_cast<BitTest>(test->entry())());
4889 EXPECT_DISASSEMBLY(
4890 "mov eax,4\n"
4891 "mov ecx,2\n"
4892 "bt eax,ecx\n"
4893 "jc +7\n"
4894 "int3\n"
4895 "mov eax,1\n"
4896 "ret\n");
4897}
4898
4899ASSEMBLER_TEST_GENERATE(BitTestImmediate, assembler) {
4900 __ movl(ECX, Immediate(32));
4901 __ bt(ECX, 5);
4902 Label ok;
4903 __ j(CARRY, &ok);
4904 __ int3();
4905 __ Bind(&ok);
4906 __ movl(EAX, Immediate(1));
4907 __ ret();
4908}
4909
4910ASSEMBLER_TEST_RUN(BitTestImmediate, test) {
4911 typedef int (*BitTestImmediate)();
4912 EXPECT_EQ(1, reinterpret_cast<BitTestImmediate>(test->entry())());
4913 EXPECT_DISASSEMBLY(
4914 "mov ecx,0x20\n"
4915 "bt ecx,5\n"
4916 "jc +7\n"
4917 "int3\n"
4918 "mov eax,1\n"
4919 "ret\n");
4920}
4921
4922// clang-format off
4923#define ALU_TEST(NAME, WIDTH, INTRO, LHS, RHS, OUTRO) \
4924 ASSEMBLER_TEST_GENERATE(NAME, assembler) { \
4925 __ movl(EAX, Immediate(0x87654321)); \
4926 __ movl(ECX, Immediate(0x12345678)); \
4927 \
4928 INTRO; \
4929 \
4930 __ and##WIDTH(LHS, RHS); \
4931 __ or##WIDTH(RHS, LHS); \
4932 __ xor##WIDTH(LHS, RHS); \
4933 __ add##WIDTH(RHS, LHS); \
4934 __ cmp##WIDTH(LHS, RHS); \
4935 __ adc##WIDTH(LHS, RHS); \
4936 __ sub##WIDTH(RHS, LHS); \
4937 __ sbb##WIDTH(LHS, RHS); \
4938 \
4939 OUTRO; \
4940 /* A sort of movx(EAX, EAX) */ \
4941 __ xorl(ECX, ECX); \
4942 __ add##WIDTH(ECX, EAX); \
4943 __ andl(EAX, ECX); \
4944 __ ret(); \
4945 } \
4946 \
4947 ASSEMBLER_TEST_RUN(NAME, test) { \
4948 typedef uint32_t (*NAME)(); \
4949 uint32_t expectation_l = 0x42649381; \
4950 uint16_t expectation_w = expectation_l; \
4951 uint32_t expectation = expectation_##WIDTH | expectation_w; \
4952 EXPECT_EQ(expectation, reinterpret_cast<NAME>(test->entry())()); \
4953 }
4954// clang-format on
4955
4956ALU_TEST(RegRegW, w, , EAX, ECX, )
4957ALU_TEST(RegAddrW1, w, __ pushl(EAX), Address(ESP, 0), ECX, __ popl(EAX))
4958ALU_TEST(RegAddrW2, w, __ pushl(ECX), EAX, Address(ESP, 0), __ popl(ECX))
4959ALU_TEST(RegRegL, l, , EAX, ECX, )
4960ALU_TEST(RegAddrL1, l, __ pushl(EAX), Address(ESP, 0), ECX, __ popl(EAX))
4961ALU_TEST(RegAddrL2, l, __ pushl(ECX), EAX, Address(ESP, 0), __ popl(ECX))
4962
4963#define IMMEDIATE_TEST(NAME, REG, MASK, INTRO, VALUE, OUTRO) \
4964 ASSEMBLER_TEST_GENERATE(NAME, assembler) { \
4965 __ movl(REG, Immediate(0x87654321)); \
4966 \
4967 INTRO; \
4968 \
4969 __ andl(VALUE, Immediate(0xa8df51d3 & MASK)); \
4970 __ orl(VALUE, Immediate(0x1582a681 & MASK)); \
4971 __ xorl(VALUE, Immediate(0xa5a5a5a5 & MASK)); \
4972 __ addl(VALUE, Immediate(0x7fffffff & MASK)); \
4973 __ cmpl(VALUE, Immediate(0x40404040 & MASK)); \
4974 __ adcl(VALUE, Immediate(0x6eeeeeee & MASK)); \
4975 __ subl(VALUE, Immediate(0x7eeeeeee & MASK)); \
4976 __ sbbl(VALUE, Immediate(0x6fffffff & MASK)); \
4977 \
4978 OUTRO; \
4979 \
4980 __ movl(EAX, REG); \
4981 __ ret(); \
4982 } \
4983 \
4984 ASSEMBLER_TEST_RUN(NAME, test) { \
4985 typedef uint32_t (*NAME)(); \
4986 uint32_t expectation = MASK < 0x100 ? 0x24 : 0x30624223; \
4987 EXPECT_EQ(expectation, reinterpret_cast<NAME>(test->entry())()); \
4988 }
4989
4990// EAX-based instructions have different encodings so we test both EAX and ECX.
4991// If the immediate can be encoded as one byte there is also a different
4992// encoding, so test that too.
4993IMMEDIATE_TEST(RegImmEAX, EAX, 0xffffffff, , EAX, )
4994IMMEDIATE_TEST(RegImmECX, ECX, 0xffffffff, , ECX, )
4995IMMEDIATE_TEST(RegImmEAXByte, EAX, 0x7f, , EAX, )
4996IMMEDIATE_TEST(RegImmECXByte, ECX, 0x7f, , ECX, )
4997IMMEDIATE_TEST(AddrImmEAX,
4998 EAX,
4999 0xffffffff,
5000 __ pushl(EAX),
5001 Address(ESP, 0),
5002 __ popl(EAX))
5003IMMEDIATE_TEST(AddrImmEAXByte,
5004 EAX,
5005 0x7f,
5006 __ pushl(EAX),
5007 Address(ESP, 0),
5008 __ popl(EAX))
5009
5010static void RangeCheck(Assembler* assembler, Register value, Register temp) {
5011 const Register return_reg = CallingConventions::kReturnReg;
5012 Label in_range;
5013 __ RangeCheck(value, temp, kFirstErrorCid, kLastErrorCid,
5014 AssemblerBase::kIfInRange, &in_range);
5015 __ movl(return_reg, Immediate(0));
5016 __ ret();
5017 __ Bind(&in_range);
5018 __ movl(return_reg, Immediate(1));
5019 __ ret();
5020}
5021
5022ASSEMBLER_TEST_GENERATE(RangeCheckNoTemp, assembler) {
5024 const Register temp = kNoRegister;
5025 __ movl(value, compiler::Address(ESP, 4));
5026 RangeCheck(assembler, value, temp);
5027}
5028
5029ASSEMBLER_TEST_RUN(RangeCheckNoTemp, test) {
5030 intptr_t result;
5031 result = test->Invoke<intptr_t, intptr_t>(kErrorCid);
5032 EXPECT_EQ(1, result);
5033 result = test->Invoke<intptr_t, intptr_t>(kUnwindErrorCid);
5034 EXPECT_EQ(1, result);
5035 result = test->Invoke<intptr_t, intptr_t>(kFunctionCid);
5036 EXPECT_EQ(0, result);
5037 result = test->Invoke<intptr_t, intptr_t>(kMintCid);
5038 EXPECT_EQ(0, result);
5039}
5040
5041ASSEMBLER_TEST_GENERATE(RangeCheckWithTemp, assembler) {
5044 __ movl(value, compiler::Address(ESP, 4));
5045 RangeCheck(assembler, value, temp);
5046}
5047
5048ASSEMBLER_TEST_RUN(RangeCheckWithTemp, test) {
5049 intptr_t result;
5050 result = test->Invoke<intptr_t, intptr_t>(kErrorCid);
5051 EXPECT_EQ(1, result);
5052 result = test->Invoke<intptr_t, intptr_t>(kUnwindErrorCid);
5053 EXPECT_EQ(1, result);
5054 result = test->Invoke<intptr_t, intptr_t>(kFunctionCid);
5055 EXPECT_EQ(0, result);
5056 result = test->Invoke<intptr_t, intptr_t>(kMintCid);
5057 EXPECT_EQ(0, result);
5058}
5059
5060ASSEMBLER_TEST_GENERATE(RangeCheckWithTempReturnValue, assembler) {
5063 const Register return_reg = CallingConventions::kReturnReg;
5064 Label in_range;
5065 __ movl(value, compiler::Address(ESP, 4));
5066 __ RangeCheck(value, temp, kFirstErrorCid, kLastErrorCid,
5067 AssemblerBase::kIfInRange, &in_range);
5068 __ Bind(&in_range);
5069 __ movl(return_reg, value);
5070 __ ret();
5071}
5072
5073ASSEMBLER_TEST_RUN(RangeCheckWithTempReturnValue, test) {
5074 intptr_t result;
5075 result = test->Invoke<intptr_t, intptr_t>(kErrorCid);
5076 EXPECT_EQ(kErrorCid, result);
5077 result = test->Invoke<intptr_t, intptr_t>(kUnwindErrorCid);
5078 EXPECT_EQ(kUnwindErrorCid, result);
5079 result = test->Invoke<intptr_t, intptr_t>(kFunctionCid);
5080 EXPECT_EQ(kFunctionCid, result);
5081 result = test->Invoke<intptr_t, intptr_t>(kMintCid);
5082 EXPECT_EQ(kMintCid, result);
5083}
5084
5085void EnterTestFrame(Assembler* assembler) {
5086 __ EnterFrame(0);
5087 __ pushl(CODE_REG);
5088 __ pushl(THR);
5089 __ LoadFromOffset(CODE_REG, EBP, target::kWordSize * 2);
5090 __ LoadFromOffset(THR, EBP, target::kWordSize * 3);
5091}
5092
5093void LeaveTestFrame(Assembler* assembler) {
5094 __ popl(THR);
5095 __ popl(CODE_REG);
5096 __ LeaveFrame();
5097}
5098
5099} // namespace compiler
5100} // namespace dart
5101
5102#endif // defined TARGET_ARCH_IA32
Align
static void done(const char *config, const char *src, const char *srcOptions, const char *name)
Definition DM.cpp:263
static void fail(const SkString &err)
Definition DM.cpp:234
int count
static bool ok(int result)
#define EXPECT(type, expectedAlignment, expectedSize)
#define __
Type::kYUV Type::kRGBA() int(0.7 *637)
static constexpr Register kFirstNonArgumentRegister
static constexpr Register kReturnReg
static constexpr Register kSecondNonArgumentRegister
static intptr_t data_offset()
Definition object.h:11110
static bool popcnt_supported()
Definition cpu_ia32.h:35
static bool abm_supported()
Definition cpu_ia32.h:39
static Instr * At(uword pc)
ObjectStore * object_store() const
Definition isolate.h:505
static IsolateGroup * Current()
Definition isolate.h:534
static intptr_t ActivationFrameAlignment()
static Object & ZoneHandle()
Definition object.h:419
static bool sse4_1_supported()
Definition cpu_ia32.h:61
static int32_t Low32Bits(int64_t value)
Definition utils.h:354
static int32_t High32Bits(int64_t value)
Definition utils.h:358
static constexpr T RoundUp(T x, uintptr_t alignment, uintptr_t offset=0)
Definition utils.h:105
static Address Absolute(const uword addr)
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE auto & d
Definition main.cc:19
static bool b
struct MyStruct a[10]
uint8_t value
GAsyncResult * result
uint32_t * target
double x
void LeaveTestFrame(Assembler *assembler)
void EnterTestFrame(Assembler *assembler)
const Register THR
static const ClassId kLastErrorCid
Definition class_id.h:311
static const ClassId kFirstErrorCid
Definition class_id.h:310
uintptr_t uword
Definition globals.h:501
const Register CODE_REG
@ PARITY_EVEN
@ kNoRegister
constexpr intptr_t kDoubleSize
Definition globals.h:456
call(args)
Definition dom.py:159
SIN Vec< N, float > sqrt(const Vec< N, float > &x)
Definition SkVx.h:706
SIN Vec< N, uint16_t > mull(const Vec< N, uint8_t > &x, const Vec< N, uint8_t > &y)
Definition SkVx.h:906
SkScalar w
#define ASSEMBLER_TEST_GENERATE(name, assembler)
Definition unit_test.h:89
#define ASSEMBLER_TEST_RUN(name, test)
Definition unit_test.h:127
#define OFFSET_OF(type, field)
Definition globals.h:138
#define ALIGN16
Definition globals.h:172