blob: e4cac56c150819521239afb0b2384492446d13bf [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include <stdlib.h>
29
Ben Murdochb8a8cc12014-11-26 15:28:44 +000030#include "src/v8.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000031
Ben Murdochb8a8cc12014-11-26 15:28:44 +000032#include "src/base/platform/platform.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000033#include "src/base/utils/random-number-generator.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000034#include "src/disassembler.h"
35#include "src/factory.h"
36#include "src/macro-assembler.h"
37#include "src/ostreams.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000038#include "test/cctest/cctest.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000039
40using namespace v8::internal;
41
42
43typedef int (*F0)();
44typedef int (*F1)(int x);
45typedef int (*F2)(int x, int y);
46
47
Steve Blocka7e24c12009-10-30 11:49:00 +000048#define __ assm.
49
50TEST(AssemblerIa320) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000051 CcTest::InitializeVM();
52 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
53 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000054
55 v8::internal::byte buffer[256];
Ben Murdochb8a8cc12014-11-26 15:28:44 +000056 Assembler assm(isolate, buffer, sizeof buffer);
Steve Blocka7e24c12009-10-30 11:49:00 +000057
58 __ mov(eax, Operand(esp, 4));
59 __ add(eax, Operand(esp, 8));
60 __ ret(0);
61
62 CodeDesc desc;
63 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000064 Handle<Code> code = isolate->factory()->NewCode(
65 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Steve Block9fac8402011-05-12 15:51:54 +010066#ifdef OBJECT_PRINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +000067 OFStream os(stdout);
68 code->Print(os);
Steve Blocka7e24c12009-10-30 11:49:00 +000069#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +000070 F2 f = FUNCTION_CAST<F2>(code->entry());
Steve Blocka7e24c12009-10-30 11:49:00 +000071 int res = f(3, 4);
72 ::printf("f() = %d\n", res);
73 CHECK_EQ(7, res);
74}
75
76
77TEST(AssemblerIa321) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000078 CcTest::InitializeVM();
79 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
80 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000081
82 v8::internal::byte buffer[256];
Ben Murdochb8a8cc12014-11-26 15:28:44 +000083 Assembler assm(isolate, buffer, sizeof buffer);
Steve Blocka7e24c12009-10-30 11:49:00 +000084 Label L, C;
85
86 __ mov(edx, Operand(esp, 4));
Ben Murdoch3ef787d2012-04-12 10:51:47 +010087 __ xor_(eax, eax); // clear eax
Steve Blocka7e24c12009-10-30 11:49:00 +000088 __ jmp(&C);
89
90 __ bind(&L);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010091 __ add(eax, edx);
92 __ sub(edx, Immediate(1));
Steve Blocka7e24c12009-10-30 11:49:00 +000093
94 __ bind(&C);
Ben Murdoch3ef787d2012-04-12 10:51:47 +010095 __ test(edx, edx);
Ben Murdoch257744e2011-11-30 15:57:28 +000096 __ j(not_zero, &L);
Steve Blocka7e24c12009-10-30 11:49:00 +000097 __ ret(0);
98
99 CodeDesc desc;
100 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000101 Handle<Code> code = isolate->factory()->NewCode(
102 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Steve Block9fac8402011-05-12 15:51:54 +0100103#ifdef OBJECT_PRINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000104 OFStream os(stdout);
105 code->Print(os);
Steve Blocka7e24c12009-10-30 11:49:00 +0000106#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000107 F1 f = FUNCTION_CAST<F1>(code->entry());
Steve Blocka7e24c12009-10-30 11:49:00 +0000108 int res = f(100);
109 ::printf("f() = %d\n", res);
110 CHECK_EQ(5050, res);
111}
112
113
114TEST(AssemblerIa322) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000115 CcTest::InitializeVM();
116 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
117 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000118
119 v8::internal::byte buffer[256];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000120 Assembler assm(isolate, buffer, sizeof buffer);
Steve Blocka7e24c12009-10-30 11:49:00 +0000121 Label L, C;
122
123 __ mov(edx, Operand(esp, 4));
124 __ mov(eax, 1);
125 __ jmp(&C);
126
127 __ bind(&L);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100128 __ imul(eax, edx);
129 __ sub(edx, Immediate(1));
Steve Blocka7e24c12009-10-30 11:49:00 +0000130
131 __ bind(&C);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100132 __ test(edx, edx);
Ben Murdoch257744e2011-11-30 15:57:28 +0000133 __ j(not_zero, &L);
Steve Blocka7e24c12009-10-30 11:49:00 +0000134 __ ret(0);
135
136 // some relocated stuff here, not executed
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000137 __ mov(eax, isolate->factory()->true_value());
Steve Blocka7e24c12009-10-30 11:49:00 +0000138 __ jmp(NULL, RelocInfo::RUNTIME_ENTRY);
139
140 CodeDesc desc;
141 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000142 Handle<Code> code = isolate->factory()->NewCode(
143 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Steve Block9fac8402011-05-12 15:51:54 +0100144#ifdef OBJECT_PRINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000145 OFStream os(stdout);
146 code->Print(os);
Steve Blocka7e24c12009-10-30 11:49:00 +0000147#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000148 F1 f = FUNCTION_CAST<F1>(code->entry());
Steve Blocka7e24c12009-10-30 11:49:00 +0000149 int res = f(10);
150 ::printf("f() = %d\n", res);
151 CHECK_EQ(3628800, res);
152}
153
154
155typedef int (*F3)(float x);
156
157TEST(AssemblerIa323) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000158 CcTest::InitializeVM();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100159
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000160 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
161 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000162
163 v8::internal::byte buffer[256];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000164 Assembler assm(isolate, buffer, sizeof buffer);
Steve Blocka7e24c12009-10-30 11:49:00 +0000165
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000166 __ cvttss2si(eax, Operand(esp, 4));
167 __ ret(0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000168
169 CodeDesc desc;
170 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000171 Handle<Code> code = isolate->factory()->NewCode(
172 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400173#ifdef OBJECT_PRINT
174 OFStream os(stdout);
175 code->Print(os);
176#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000177 F3 f = FUNCTION_CAST<F3>(code->entry());
178 int res = f(static_cast<float>(-3.1415));
179 ::printf("f() = %d\n", res);
180 CHECK_EQ(-3, res);
181}
182
183
184typedef int (*F4)(double x);
185
186TEST(AssemblerIa324) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000187 CcTest::InitializeVM();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100188
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000189 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
190 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000191
192 v8::internal::byte buffer[256];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000193 Assembler assm(isolate, buffer, sizeof buffer);
Steve Blocka7e24c12009-10-30 11:49:00 +0000194
Steve Blocka7e24c12009-10-30 11:49:00 +0000195 __ cvttsd2si(eax, Operand(esp, 4));
196 __ ret(0);
197
198 CodeDesc desc;
199 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000200 Handle<Code> code = isolate->factory()->NewCode(
201 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400202#ifdef OBJECT_PRINT
203 OFStream os(stdout);
204 code->Print(os);
205#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000206 F4 f = FUNCTION_CAST<F4>(code->entry());
207 int res = f(2.718281828);
208 ::printf("f() = %d\n", res);
209 CHECK_EQ(2, res);
210}
211
212
213static int baz = 42;
214TEST(AssemblerIa325) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000215 CcTest::InitializeVM();
216 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
217 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000218
219 v8::internal::byte buffer[256];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000220 Assembler assm(isolate, buffer, sizeof buffer);
Steve Blocka7e24c12009-10-30 11:49:00 +0000221
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000222 __ mov(eax, Operand(reinterpret_cast<intptr_t>(&baz), RelocInfo::NONE32));
Steve Blocka7e24c12009-10-30 11:49:00 +0000223 __ ret(0);
224
225 CodeDesc desc;
226 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000227 Handle<Code> code = isolate->factory()->NewCode(
228 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Steve Blocka7e24c12009-10-30 11:49:00 +0000229 F0 f = FUNCTION_CAST<F0>(code->entry());
230 int res = f();
231 CHECK_EQ(42, res);
232}
233
234
235typedef double (*F5)(double x, double y);
236
237TEST(AssemblerIa326) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238 CcTest::InitializeVM();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100239
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000240 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
241 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000242 v8::internal::byte buffer[256];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000243 Assembler assm(isolate, buffer, sizeof buffer);
Steve Blocka7e24c12009-10-30 11:49:00 +0000244
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000245 __ movsd(xmm0, Operand(esp, 1 * kPointerSize));
246 __ movsd(xmm1, Operand(esp, 3 * kPointerSize));
Steve Blocka7e24c12009-10-30 11:49:00 +0000247 __ addsd(xmm0, xmm1);
248 __ mulsd(xmm0, xmm1);
249 __ subsd(xmm0, xmm1);
250 __ divsd(xmm0, xmm1);
251 // Copy xmm0 to st(0) using eight bytes of stack.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100252 __ sub(esp, Immediate(8));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000253 __ movsd(Operand(esp, 0), xmm0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000254 __ fld_d(Operand(esp, 0));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100255 __ add(esp, Immediate(8));
Steve Blocka7e24c12009-10-30 11:49:00 +0000256 __ ret(0);
257
258 CodeDesc desc;
259 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000260 Handle<Code> code = isolate->factory()->NewCode(
261 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400262#ifdef OBJECT_PRINT
263 OFStream os(stdout);
264 code->Print(os);
Steve Blocka7e24c12009-10-30 11:49:00 +0000265#endif
266 F5 f = FUNCTION_CAST<F5>(code->entry());
267 double res = f(2.2, 1.1);
268 ::printf("f() = %f\n", res);
269 CHECK(2.29 < res && res < 2.31);
270}
271
272
273typedef double (*F6)(int x);
274
275TEST(AssemblerIa328) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000276 CcTest::InitializeVM();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100277
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000278 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
279 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000280 v8::internal::byte buffer[256];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000281 Assembler assm(isolate, buffer, sizeof buffer);
Steve Blocka7e24c12009-10-30 11:49:00 +0000282 __ mov(eax, Operand(esp, 4));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100283 __ cvtsi2sd(xmm0, eax);
Steve Blocka7e24c12009-10-30 11:49:00 +0000284 // Copy xmm0 to st(0) using eight bytes of stack.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100285 __ sub(esp, Immediate(8));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000286 __ movsd(Operand(esp, 0), xmm0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000287 __ fld_d(Operand(esp, 0));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100288 __ add(esp, Immediate(8));
Steve Blocka7e24c12009-10-30 11:49:00 +0000289 __ ret(0);
290 CodeDesc desc;
291 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000292 Handle<Code> code = isolate->factory()->NewCode(
293 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Steve Block9fac8402011-05-12 15:51:54 +0100294#ifdef OBJECT_PRINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000295 OFStream os(stdout);
296 code->Print(os);
Steve Blocka7e24c12009-10-30 11:49:00 +0000297#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000298 F6 f = FUNCTION_CAST<F6>(code->entry());
Steve Blocka7e24c12009-10-30 11:49:00 +0000299 double res = f(12);
300
301 ::printf("f() = %f\n", res);
302 CHECK(11.99 < res && res < 12.001);
303}
304
305
306typedef int (*F7)(double x, double y);
307
308TEST(AssemblerIa329) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000309 CcTest::InitializeVM();
310 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
311 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000312 v8::internal::byte buffer[256];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000313 MacroAssembler assm(isolate, buffer, sizeof(buffer),
314 v8::internal::CodeObjectRequired::kYes);
Steve Blocka7e24c12009-10-30 11:49:00 +0000315 enum { kEqual = 0, kGreater = 1, kLess = 2, kNaN = 3, kUndefined = 4 };
316 Label equal_l, less_l, greater_l, nan_l;
317 __ fld_d(Operand(esp, 3 * kPointerSize));
318 __ fld_d(Operand(esp, 1 * kPointerSize));
319 __ FCmp();
Ben Murdoch257744e2011-11-30 15:57:28 +0000320 __ j(parity_even, &nan_l);
321 __ j(equal, &equal_l);
322 __ j(below, &less_l);
323 __ j(above, &greater_l);
Steve Blocka7e24c12009-10-30 11:49:00 +0000324
325 __ mov(eax, kUndefined);
326 __ ret(0);
327
328 __ bind(&equal_l);
329 __ mov(eax, kEqual);
330 __ ret(0);
331
332 __ bind(&greater_l);
333 __ mov(eax, kGreater);
334 __ ret(0);
335
336 __ bind(&less_l);
337 __ mov(eax, kLess);
338 __ ret(0);
339
340 __ bind(&nan_l);
341 __ mov(eax, kNaN);
342 __ ret(0);
343
344
345 CodeDesc desc;
346 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000347 Handle<Code> code = isolate->factory()->NewCode(
348 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Steve Block9fac8402011-05-12 15:51:54 +0100349#ifdef OBJECT_PRINT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000350 OFStream os(stdout);
351 code->Print(os);
Steve Blocka7e24c12009-10-30 11:49:00 +0000352#endif
353
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000354 F7 f = FUNCTION_CAST<F7>(code->entry());
Steve Blocka7e24c12009-10-30 11:49:00 +0000355 CHECK_EQ(kLess, f(1.1, 2.2));
356 CHECK_EQ(kEqual, f(2.2, 2.2));
357 CHECK_EQ(kGreater, f(3.3, 2.2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000358 CHECK_EQ(kNaN, f(std::numeric_limits<double>::quiet_NaN(), 1.1));
Steve Blocka7e24c12009-10-30 11:49:00 +0000359}
360
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000361
362TEST(AssemblerIa3210) {
363 // Test chaining of label usages within instructions (issue 1644).
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000364 CcTest::InitializeVM();
365 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
366 HandleScope scope(isolate);
367 Assembler assm(isolate, NULL, 0);
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000368
369 Label target;
370 __ j(equal, &target);
371 __ j(not_equal, &target);
372 __ bind(&target);
373 __ nop();
374}
375
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100376
377TEST(AssemblerMultiByteNop) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000378 CcTest::InitializeVM();
379 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
380 HandleScope scope(isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100381 v8::internal::byte buffer[1024];
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000382 Assembler assm(isolate, buffer, sizeof(buffer));
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100383 __ push(ebx);
384 __ push(ecx);
385 __ push(edx);
386 __ push(edi);
387 __ push(esi);
388 __ mov(eax, 1);
389 __ mov(ebx, 2);
390 __ mov(ecx, 3);
391 __ mov(edx, 4);
392 __ mov(edi, 5);
393 __ mov(esi, 6);
394 for (int i = 0; i < 16; i++) {
395 int before = assm.pc_offset();
396 __ Nop(i);
397 CHECK_EQ(assm.pc_offset() - before, i);
398 }
399
400 Label fail;
401 __ cmp(eax, 1);
402 __ j(not_equal, &fail);
403 __ cmp(ebx, 2);
404 __ j(not_equal, &fail);
405 __ cmp(ecx, 3);
406 __ j(not_equal, &fail);
407 __ cmp(edx, 4);
408 __ j(not_equal, &fail);
409 __ cmp(edi, 5);
410 __ j(not_equal, &fail);
411 __ cmp(esi, 6);
412 __ j(not_equal, &fail);
413 __ mov(eax, 42);
414 __ pop(esi);
415 __ pop(edi);
416 __ pop(edx);
417 __ pop(ecx);
418 __ pop(ebx);
419 __ ret(0);
420 __ bind(&fail);
421 __ mov(eax, 13);
422 __ pop(esi);
423 __ pop(edi);
424 __ pop(edx);
425 __ pop(ecx);
426 __ pop(ebx);
427 __ ret(0);
428
429 CodeDesc desc;
430 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000431 Handle<Code> code = isolate->factory()->NewCode(
432 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100433 CHECK(code->IsCode());
434
435 F0 f = FUNCTION_CAST<F0>(code->entry());
436 int res = f();
437 CHECK_EQ(42, res);
438}
439
440
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000441#ifdef __GNUC__
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000442#define ELEMENT_COUNT 4u
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000443
444void DoSSE2(const v8::FunctionCallbackInfo<v8::Value>& args) {
445 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
446 HandleScope scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000447 v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000448
449 CHECK(args[0]->IsArray());
450 v8::Local<v8::Array> vec = v8::Local<v8::Array>::Cast(args[0]);
451 CHECK_EQ(ELEMENT_COUNT, vec->Length());
452
453 v8::internal::byte buffer[256];
454 Assembler assm(isolate, buffer, sizeof buffer);
455
456 // Remove return address from the stack for fix stack frame alignment.
457 __ pop(ecx);
458
459 // Store input vector on the stack.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000460 for (unsigned i = 0; i < ELEMENT_COUNT; ++i) {
461 __ push(Immediate(
462 vec->Get(context, i).ToLocalChecked()->Int32Value(context).FromJust()));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000463 }
464
465 // Read vector into a xmm register.
466 __ pxor(xmm0, xmm0);
467 __ movdqa(xmm0, Operand(esp, 0));
468 // Create mask and store it in the return register.
469 __ movmskps(eax, xmm0);
470
471 // Remove unused data from the stack.
472 __ add(esp, Immediate(ELEMENT_COUNT * sizeof(int32_t)));
473 // Restore return address.
474 __ push(ecx);
475
476 __ ret(0);
477
478 CodeDesc desc;
479 assm.GetCode(&desc);
480
481 Handle<Code> code = isolate->factory()->NewCode(
482 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
483
484 F0 f = FUNCTION_CAST<F0>(code->entry());
485 int res = f();
486 args.GetReturnValue().Set(v8::Integer::New(CcTest::isolate(), res));
487}
488
489
490TEST(StackAlignmentForSSE2) {
491 CcTest::InitializeVM();
492 CHECK_EQ(0, v8::base::OS::ActivationFrameAlignment() % 16);
493
494 v8::Isolate* isolate = CcTest::isolate();
495 v8::HandleScope handle_scope(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000496 v8::Local<v8::ObjectTemplate> global_template =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000497 v8::ObjectTemplate::New(isolate);
498 global_template->Set(v8_str("do_sse2"),
499 v8::FunctionTemplate::New(isolate, DoSSE2));
500
501 LocalContext env(NULL, global_template);
502 CompileRun(
503 "function foo(vec) {"
504 " return do_sse2(vec);"
505 "}");
506
507 v8::Local<v8::Object> global_object = env->Global();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000508 v8::Local<v8::Function> foo = v8::Local<v8::Function>::Cast(
509 global_object->Get(env.local(), v8_str("foo")).ToLocalChecked());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000510
511 int32_t vec[ELEMENT_COUNT] = { -1, 1, 1, 1 };
512 v8::Local<v8::Array> v8_vec = v8::Array::New(isolate, ELEMENT_COUNT);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000513 for (unsigned i = 0; i < ELEMENT_COUNT; i++) {
514 v8_vec->Set(env.local(), i, v8_num(vec[i])).FromJust();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000515 }
516
517 v8::Local<v8::Value> args[] = { v8_vec };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000518 v8::Local<v8::Value> result =
519 foo->Call(env.local(), global_object, 1, args).ToLocalChecked();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000520
521 // The mask should be 0b1000.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000522 CHECK_EQ(8, result->Int32Value(env.local()).FromJust());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000523}
524
525#undef ELEMENT_COUNT
526#endif // __GNUC__
527
528
529TEST(AssemblerIa32Extractps) {
530 CcTest::InitializeVM();
531 if (!CpuFeatures::IsSupported(SSE4_1)) return;
532
533 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
534 HandleScope scope(isolate);
535 v8::internal::byte buffer[256];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000536 MacroAssembler assm(isolate, buffer, sizeof(buffer),
537 v8::internal::CodeObjectRequired::kYes);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000538 { CpuFeatureScope fscope41(&assm, SSE4_1);
539 __ movsd(xmm1, Operand(esp, 4));
540 __ extractps(eax, xmm1, 0x1);
541 __ ret(0);
542 }
543
544 CodeDesc desc;
545 assm.GetCode(&desc);
546 Handle<Code> code = isolate->factory()->NewCode(
547 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
548#ifdef OBJECT_PRINT
549 OFStream os(stdout);
550 code->Print(os);
551#endif
552
553 F4 f = FUNCTION_CAST<F4>(code->entry());
554 uint64_t value1 = V8_2PART_UINT64_C(0x12345678, 87654321);
555 CHECK_EQ(0x12345678, f(uint64_to_double(value1)));
556 uint64_t value2 = V8_2PART_UINT64_C(0x87654321, 12345678);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000557 CHECK_EQ(static_cast<int>(0x87654321), f(uint64_to_double(value2)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000558}
559
560
561typedef int (*F8)(float x, float y);
562TEST(AssemblerIa32SSE) {
563 CcTest::InitializeVM();
564
565 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
566 HandleScope scope(isolate);
567 v8::internal::byte buffer[256];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000568 MacroAssembler assm(isolate, buffer, sizeof(buffer),
569 v8::internal::CodeObjectRequired::kYes);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000570 {
571 __ movss(xmm0, Operand(esp, kPointerSize));
572 __ movss(xmm1, Operand(esp, 2 * kPointerSize));
573 __ shufps(xmm0, xmm0, 0x0);
574 __ shufps(xmm1, xmm1, 0x0);
575 __ movaps(xmm2, xmm1);
576 __ addps(xmm2, xmm0);
577 __ mulps(xmm2, xmm1);
578 __ subps(xmm2, xmm0);
579 __ divps(xmm2, xmm1);
580 __ cvttss2si(eax, xmm2);
581 __ ret(0);
582 }
583
584 CodeDesc desc;
585 assm.GetCode(&desc);
586 Handle<Code> code = isolate->factory()->NewCode(
587 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
588#ifdef OBJECT_PRINT
589 OFStream os(stdout);
590 code->Print(os);
591#endif
592
593 F8 f = FUNCTION_CAST<F8>(code->entry());
594 CHECK_EQ(2, f(1.0, 2.0));
595}
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100596
597
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400598typedef int (*F9)(double x, double y, double z);
599TEST(AssemblerX64FMA_sd) {
600 CcTest::InitializeVM();
601 if (!CpuFeatures::IsSupported(FMA3)) return;
602
603 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
604 HandleScope scope(isolate);
605 v8::internal::byte buffer[1024];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000606 MacroAssembler assm(isolate, buffer, sizeof(buffer),
607 v8::internal::CodeObjectRequired::kYes);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400608 {
609 CpuFeatureScope fscope(&assm, FMA3);
610 Label exit;
611 __ movsd(xmm0, Operand(esp, 1 * kPointerSize));
612 __ movsd(xmm1, Operand(esp, 3 * kPointerSize));
613 __ movsd(xmm2, Operand(esp, 5 * kPointerSize));
614 // argument in xmm0, xmm1 and xmm2
615 // xmm0 * xmm1 + xmm2
616 __ movaps(xmm3, xmm0);
617 __ mulsd(xmm3, xmm1);
618 __ addsd(xmm3, xmm2); // Expected result in xmm3
619
620 __ sub(esp, Immediate(kDoubleSize)); // For memory operand
621 // vfmadd132sd
622 __ mov(eax, Immediate(1)); // Test number
623 __ movaps(xmm4, xmm0);
624 __ vfmadd132sd(xmm4, xmm2, xmm1);
625 __ ucomisd(xmm4, xmm3);
626 __ j(not_equal, &exit);
627 // vfmadd213sd
628 __ inc(eax);
629 __ movaps(xmm4, xmm1);
630 __ vfmadd213sd(xmm4, xmm0, xmm2);
631 __ ucomisd(xmm4, xmm3);
632 __ j(not_equal, &exit);
633 // vfmadd231sd
634 __ inc(eax);
635 __ movaps(xmm4, xmm2);
636 __ vfmadd231sd(xmm4, xmm0, xmm1);
637 __ ucomisd(xmm4, xmm3);
638 __ j(not_equal, &exit);
639
640 // vfmadd132sd
641 __ inc(eax);
642 __ movaps(xmm4, xmm0);
643 __ movsd(Operand(esp, 0), xmm1);
644 __ vfmadd132sd(xmm4, xmm2, Operand(esp, 0));
645 __ ucomisd(xmm4, xmm3);
646 __ j(not_equal, &exit);
647 // vfmadd213sd
648 __ inc(eax);
649 __ movaps(xmm4, xmm1);
650 __ movsd(Operand(esp, 0), xmm2);
651 __ vfmadd213sd(xmm4, xmm0, Operand(esp, 0));
652 __ ucomisd(xmm4, xmm3);
653 __ j(not_equal, &exit);
654 // vfmadd231sd
655 __ inc(eax);
656 __ movaps(xmm4, xmm2);
657 __ movsd(Operand(esp, 0), xmm1);
658 __ vfmadd231sd(xmm4, xmm0, Operand(esp, 0));
659 __ ucomisd(xmm4, xmm3);
660 __ j(not_equal, &exit);
661
662 // xmm0 * xmm1 - xmm2
663 __ movaps(xmm3, xmm0);
664 __ mulsd(xmm3, xmm1);
665 __ subsd(xmm3, xmm2); // Expected result in xmm3
666
667 // vfmsub132sd
668 __ inc(eax);
669 __ movaps(xmm4, xmm0);
670 __ vfmsub132sd(xmm4, xmm2, xmm1);
671 __ ucomisd(xmm4, xmm3);
672 __ j(not_equal, &exit);
673 // vfmadd213sd
674 __ inc(eax);
675 __ movaps(xmm4, xmm1);
676 __ vfmsub213sd(xmm4, xmm0, xmm2);
677 __ ucomisd(xmm4, xmm3);
678 __ j(not_equal, &exit);
679 // vfmsub231sd
680 __ inc(eax);
681 __ movaps(xmm4, xmm2);
682 __ vfmsub231sd(xmm4, xmm0, xmm1);
683 __ ucomisd(xmm4, xmm3);
684 __ j(not_equal, &exit);
685
686 // vfmsub132sd
687 __ inc(eax);
688 __ movaps(xmm4, xmm0);
689 __ movsd(Operand(esp, 0), xmm1);
690 __ vfmsub132sd(xmm4, xmm2, Operand(esp, 0));
691 __ ucomisd(xmm4, xmm3);
692 __ j(not_equal, &exit);
693 // vfmsub213sd
694 __ inc(eax);
695 __ movaps(xmm4, xmm1);
696 __ movsd(Operand(esp, 0), xmm2);
697 __ vfmsub213sd(xmm4, xmm0, Operand(esp, 0));
698 __ ucomisd(xmm4, xmm3);
699 __ j(not_equal, &exit);
700 // vfmsub231sd
701 __ inc(eax);
702 __ movaps(xmm4, xmm2);
703 __ movsd(Operand(esp, 0), xmm1);
704 __ vfmsub231sd(xmm4, xmm0, Operand(esp, 0));
705 __ ucomisd(xmm4, xmm3);
706 __ j(not_equal, &exit);
707
708
709 // - xmm0 * xmm1 + xmm2
710 __ movaps(xmm3, xmm0);
711 __ mulsd(xmm3, xmm1);
712 __ Move(xmm4, (uint64_t)1 << 63);
713 __ xorpd(xmm3, xmm4);
714 __ addsd(xmm3, xmm2); // Expected result in xmm3
715
716 // vfnmadd132sd
717 __ inc(eax);
718 __ movaps(xmm4, xmm0);
719 __ vfnmadd132sd(xmm4, xmm2, xmm1);
720 __ ucomisd(xmm4, xmm3);
721 __ j(not_equal, &exit);
722 // vfmadd213sd
723 __ inc(eax);
724 __ movaps(xmm4, xmm1);
725 __ vfnmadd213sd(xmm4, xmm0, xmm2);
726 __ ucomisd(xmm4, xmm3);
727 __ j(not_equal, &exit);
728 // vfnmadd231sd
729 __ inc(eax);
730 __ movaps(xmm4, xmm2);
731 __ vfnmadd231sd(xmm4, xmm0, xmm1);
732 __ ucomisd(xmm4, xmm3);
733 __ j(not_equal, &exit);
734
735 // vfnmadd132sd
736 __ inc(eax);
737 __ movaps(xmm4, xmm0);
738 __ movsd(Operand(esp, 0), xmm1);
739 __ vfnmadd132sd(xmm4, xmm2, Operand(esp, 0));
740 __ ucomisd(xmm4, xmm3);
741 __ j(not_equal, &exit);
742 // vfnmadd213sd
743 __ inc(eax);
744 __ movaps(xmm4, xmm1);
745 __ movsd(Operand(esp, 0), xmm2);
746 __ vfnmadd213sd(xmm4, xmm0, Operand(esp, 0));
747 __ ucomisd(xmm4, xmm3);
748 __ j(not_equal, &exit);
749 // vfnmadd231sd
750 __ inc(eax);
751 __ movaps(xmm4, xmm2);
752 __ movsd(Operand(esp, 0), xmm1);
753 __ vfnmadd231sd(xmm4, xmm0, Operand(esp, 0));
754 __ ucomisd(xmm4, xmm3);
755 __ j(not_equal, &exit);
756
757
758 // - xmm0 * xmm1 - xmm2
759 __ movaps(xmm3, xmm0);
760 __ mulsd(xmm3, xmm1);
761 __ Move(xmm4, (uint64_t)1 << 63);
762 __ xorpd(xmm3, xmm4);
763 __ subsd(xmm3, xmm2); // Expected result in xmm3
764
765 // vfnmsub132sd
766 __ inc(eax);
767 __ movaps(xmm4, xmm0);
768 __ vfnmsub132sd(xmm4, xmm2, xmm1);
769 __ ucomisd(xmm4, xmm3);
770 __ j(not_equal, &exit);
771 // vfmsub213sd
772 __ inc(eax);
773 __ movaps(xmm4, xmm1);
774 __ vfnmsub213sd(xmm4, xmm0, xmm2);
775 __ ucomisd(xmm4, xmm3);
776 __ j(not_equal, &exit);
777 // vfnmsub231sd
778 __ inc(eax);
779 __ movaps(xmm4, xmm2);
780 __ vfnmsub231sd(xmm4, xmm0, xmm1);
781 __ ucomisd(xmm4, xmm3);
782 __ j(not_equal, &exit);
783
784 // vfnmsub132sd
785 __ inc(eax);
786 __ movaps(xmm4, xmm0);
787 __ movsd(Operand(esp, 0), xmm1);
788 __ vfnmsub132sd(xmm4, xmm2, Operand(esp, 0));
789 __ ucomisd(xmm4, xmm3);
790 __ j(not_equal, &exit);
791 // vfnmsub213sd
792 __ inc(eax);
793 __ movaps(xmm4, xmm1);
794 __ movsd(Operand(esp, 0), xmm2);
795 __ vfnmsub213sd(xmm4, xmm0, Operand(esp, 0));
796 __ ucomisd(xmm4, xmm3);
797 __ j(not_equal, &exit);
798 // vfnmsub231sd
799 __ inc(eax);
800 __ movaps(xmm4, xmm2);
801 __ movsd(Operand(esp, 0), xmm1);
802 __ vfnmsub231sd(xmm4, xmm0, Operand(esp, 0));
803 __ ucomisd(xmm4, xmm3);
804 __ j(not_equal, &exit);
805
806
807 __ xor_(eax, eax);
808 __ bind(&exit);
809 __ add(esp, Immediate(kDoubleSize));
810 __ ret(0);
811 }
812
813 CodeDesc desc;
814 assm.GetCode(&desc);
815 Handle<Code> code = isolate->factory()->NewCode(
816 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
817#ifdef OBJECT_PRINT
818 OFStream os(stdout);
819 code->Print(os);
820#endif
821
822 F9 f = FUNCTION_CAST<F9>(code->entry());
823 CHECK_EQ(0, f(0.000092662107262076, -2.460774966188315, -1.0958787393627414));
824}
825
826
827typedef int (*F10)(float x, float y, float z);
828TEST(AssemblerX64FMA_ss) {
829 CcTest::InitializeVM();
830 if (!CpuFeatures::IsSupported(FMA3)) return;
831
832 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
833 HandleScope scope(isolate);
834 v8::internal::byte buffer[1024];
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000835 MacroAssembler assm(isolate, buffer, sizeof(buffer),
836 v8::internal::CodeObjectRequired::kYes);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400837 {
838 CpuFeatureScope fscope(&assm, FMA3);
839 Label exit;
840 __ movss(xmm0, Operand(esp, 1 * kPointerSize));
841 __ movss(xmm1, Operand(esp, 2 * kPointerSize));
842 __ movss(xmm2, Operand(esp, 3 * kPointerSize));
843 // arguments in xmm0, xmm1 and xmm2
844 // xmm0 * xmm1 + xmm2
845 __ movaps(xmm3, xmm0);
846 __ mulss(xmm3, xmm1);
847 __ addss(xmm3, xmm2); // Expected result in xmm3
848
849 __ sub(esp, Immediate(kDoubleSize)); // For memory operand
850 // vfmadd132ss
851 __ mov(eax, Immediate(1)); // Test number
852 __ movaps(xmm4, xmm0);
853 __ vfmadd132ss(xmm4, xmm2, xmm1);
854 __ ucomiss(xmm4, xmm3);
855 __ j(not_equal, &exit);
856 // vfmadd213ss
857 __ inc(eax);
858 __ movaps(xmm4, xmm1);
859 __ vfmadd213ss(xmm4, xmm0, xmm2);
860 __ ucomiss(xmm4, xmm3);
861 __ j(not_equal, &exit);
862 // vfmadd231ss
863 __ inc(eax);
864 __ movaps(xmm4, xmm2);
865 __ vfmadd231ss(xmm4, xmm0, xmm1);
866 __ ucomiss(xmm4, xmm3);
867 __ j(not_equal, &exit);
868
869 // vfmadd132ss
870 __ inc(eax);
871 __ movaps(xmm4, xmm0);
872 __ movss(Operand(esp, 0), xmm1);
873 __ vfmadd132ss(xmm4, xmm2, Operand(esp, 0));
874 __ ucomiss(xmm4, xmm3);
875 __ j(not_equal, &exit);
876 // vfmadd213ss
877 __ inc(eax);
878 __ movaps(xmm4, xmm1);
879 __ movss(Operand(esp, 0), xmm2);
880 __ vfmadd213ss(xmm4, xmm0, Operand(esp, 0));
881 __ ucomiss(xmm4, xmm3);
882 __ j(not_equal, &exit);
883 // vfmadd231ss
884 __ inc(eax);
885 __ movaps(xmm4, xmm2);
886 __ movss(Operand(esp, 0), xmm1);
887 __ vfmadd231ss(xmm4, xmm0, Operand(esp, 0));
888 __ ucomiss(xmm4, xmm3);
889 __ j(not_equal, &exit);
890
891 // xmm0 * xmm1 - xmm2
892 __ movaps(xmm3, xmm0);
893 __ mulss(xmm3, xmm1);
894 __ subss(xmm3, xmm2); // Expected result in xmm3
895
896 // vfmsub132ss
897 __ inc(eax);
898 __ movaps(xmm4, xmm0);
899 __ vfmsub132ss(xmm4, xmm2, xmm1);
900 __ ucomiss(xmm4, xmm3);
901 __ j(not_equal, &exit);
902 // vfmadd213ss
903 __ inc(eax);
904 __ movaps(xmm4, xmm1);
905 __ vfmsub213ss(xmm4, xmm0, xmm2);
906 __ ucomiss(xmm4, xmm3);
907 __ j(not_equal, &exit);
908 // vfmsub231ss
909 __ inc(eax);
910 __ movaps(xmm4, xmm2);
911 __ vfmsub231ss(xmm4, xmm0, xmm1);
912 __ ucomiss(xmm4, xmm3);
913 __ j(not_equal, &exit);
914
915 // vfmsub132ss
916 __ inc(eax);
917 __ movaps(xmm4, xmm0);
918 __ movss(Operand(esp, 0), xmm1);
919 __ vfmsub132ss(xmm4, xmm2, Operand(esp, 0));
920 __ ucomiss(xmm4, xmm3);
921 __ j(not_equal, &exit);
922 // vfmsub213ss
923 __ inc(eax);
924 __ movaps(xmm4, xmm1);
925 __ movss(Operand(esp, 0), xmm2);
926 __ vfmsub213ss(xmm4, xmm0, Operand(esp, 0));
927 __ ucomiss(xmm4, xmm3);
928 __ j(not_equal, &exit);
929 // vfmsub231ss
930 __ inc(eax);
931 __ movaps(xmm4, xmm2);
932 __ movss(Operand(esp, 0), xmm1);
933 __ vfmsub231ss(xmm4, xmm0, Operand(esp, 0));
934 __ ucomiss(xmm4, xmm3);
935 __ j(not_equal, &exit);
936
937
938 // - xmm0 * xmm1 + xmm2
939 __ movaps(xmm3, xmm0);
940 __ mulss(xmm3, xmm1);
941 __ Move(xmm4, (uint32_t)1 << 31);
942 __ xorps(xmm3, xmm4);
943 __ addss(xmm3, xmm2); // Expected result in xmm3
944
945 // vfnmadd132ss
946 __ inc(eax);
947 __ movaps(xmm4, xmm0);
948 __ vfnmadd132ss(xmm4, xmm2, xmm1);
949 __ ucomiss(xmm4, xmm3);
950 __ j(not_equal, &exit);
951 // vfmadd213ss
952 __ inc(eax);
953 __ movaps(xmm4, xmm1);
954 __ vfnmadd213ss(xmm4, xmm0, xmm2);
955 __ ucomiss(xmm4, xmm3);
956 __ j(not_equal, &exit);
957 // vfnmadd231ss
958 __ inc(eax);
959 __ movaps(xmm4, xmm2);
960 __ vfnmadd231ss(xmm4, xmm0, xmm1);
961 __ ucomiss(xmm4, xmm3);
962 __ j(not_equal, &exit);
963
964 // vfnmadd132ss
965 __ inc(eax);
966 __ movaps(xmm4, xmm0);
967 __ movss(Operand(esp, 0), xmm1);
968 __ vfnmadd132ss(xmm4, xmm2, Operand(esp, 0));
969 __ ucomiss(xmm4, xmm3);
970 __ j(not_equal, &exit);
971 // vfnmadd213ss
972 __ inc(eax);
973 __ movaps(xmm4, xmm1);
974 __ movss(Operand(esp, 0), xmm2);
975 __ vfnmadd213ss(xmm4, xmm0, Operand(esp, 0));
976 __ ucomiss(xmm4, xmm3);
977 __ j(not_equal, &exit);
978 // vfnmadd231ss
979 __ inc(eax);
980 __ movaps(xmm4, xmm2);
981 __ movss(Operand(esp, 0), xmm1);
982 __ vfnmadd231ss(xmm4, xmm0, Operand(esp, 0));
983 __ ucomiss(xmm4, xmm3);
984 __ j(not_equal, &exit);
985
986
987 // - xmm0 * xmm1 - xmm2
988 __ movaps(xmm3, xmm0);
989 __ mulss(xmm3, xmm1);
990 __ Move(xmm4, (uint32_t)1 << 31);
991 __ xorps(xmm3, xmm4);
992 __ subss(xmm3, xmm2); // Expected result in xmm3
993
994 // vfnmsub132ss
995 __ inc(eax);
996 __ movaps(xmm4, xmm0);
997 __ vfnmsub132ss(xmm4, xmm2, xmm1);
998 __ ucomiss(xmm4, xmm3);
999 __ j(not_equal, &exit);
1000 // vfmsub213ss
1001 __ inc(eax);
1002 __ movaps(xmm4, xmm1);
1003 __ vfnmsub213ss(xmm4, xmm0, xmm2);
1004 __ ucomiss(xmm4, xmm3);
1005 __ j(not_equal, &exit);
1006 // vfnmsub231ss
1007 __ inc(eax);
1008 __ movaps(xmm4, xmm2);
1009 __ vfnmsub231ss(xmm4, xmm0, xmm1);
1010 __ ucomiss(xmm4, xmm3);
1011 __ j(not_equal, &exit);
1012
1013 // vfnmsub132ss
1014 __ inc(eax);
1015 __ movaps(xmm4, xmm0);
1016 __ movss(Operand(esp, 0), xmm1);
1017 __ vfnmsub132ss(xmm4, xmm2, Operand(esp, 0));
1018 __ ucomiss(xmm4, xmm3);
1019 __ j(not_equal, &exit);
1020 // vfnmsub213ss
1021 __ inc(eax);
1022 __ movaps(xmm4, xmm1);
1023 __ movss(Operand(esp, 0), xmm2);
1024 __ vfnmsub213ss(xmm4, xmm0, Operand(esp, 0));
1025 __ ucomiss(xmm4, xmm3);
1026 __ j(not_equal, &exit);
1027 // vfnmsub231ss
1028 __ inc(eax);
1029 __ movaps(xmm4, xmm2);
1030 __ movss(Operand(esp, 0), xmm1);
1031 __ vfnmsub231ss(xmm4, xmm0, Operand(esp, 0));
1032 __ ucomiss(xmm4, xmm3);
1033 __ j(not_equal, &exit);
1034
1035
1036 __ xor_(eax, eax);
1037 __ bind(&exit);
1038 __ add(esp, Immediate(kDoubleSize));
1039 __ ret(0);
1040 }
1041
1042 CodeDesc desc;
1043 assm.GetCode(&desc);
1044 Handle<Code> code = isolate->factory()->NewCode(
1045 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1046#ifdef OBJECT_PRINT
1047 OFStream os(stdout);
1048 code->Print(os);
1049#endif
1050
1051 F10 f = FUNCTION_CAST<F10>(code->entry());
1052 CHECK_EQ(0, f(9.26621069e-05f, -2.4607749f, -1.09587872f));
1053}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001054
1055
1056TEST(AssemblerIa32BMI1) {
1057 CcTest::InitializeVM();
1058 if (!CpuFeatures::IsSupported(BMI1)) return;
1059
1060 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1061 HandleScope scope(isolate);
1062 v8::internal::byte buffer[1024];
1063 MacroAssembler assm(isolate, buffer, sizeof(buffer),
1064 v8::internal::CodeObjectRequired::kYes);
1065 {
1066 CpuFeatureScope fscope(&assm, BMI1);
1067 Label exit;
1068
1069 __ push(ebx); // save ebx
1070 __ mov(ecx, Immediate(0x55667788u)); // source operand
1071 __ push(ecx); // For memory operand
1072
1073 // andn
1074 __ mov(edx, Immediate(0x20000000u));
1075
1076 __ mov(eax, Immediate(1)); // Test number
1077 __ andn(ebx, edx, ecx);
1078 __ cmp(ebx, Immediate(0x55667788u)); // expected result
1079 __ j(not_equal, &exit);
1080
1081 __ inc(eax);
1082 __ andn(ebx, edx, Operand(esp, 0));
1083 __ cmp(ebx, Immediate(0x55667788u)); // expected result
1084 __ j(not_equal, &exit);
1085
1086 // bextr
1087 __ mov(edx, Immediate(0x00002808u));
1088
1089 __ inc(eax);
1090 __ bextr(ebx, ecx, edx);
1091 __ cmp(ebx, Immediate(0x00556677u)); // expected result
1092 __ j(not_equal, &exit);
1093
1094 __ inc(eax);
1095 __ bextr(ebx, Operand(esp, 0), edx);
1096 __ cmp(ebx, Immediate(0x00556677u)); // expected result
1097 __ j(not_equal, &exit);
1098
1099 // blsi
1100 __ inc(eax);
1101 __ blsi(ebx, ecx);
1102 __ cmp(ebx, Immediate(0x00000008u)); // expected result
1103 __ j(not_equal, &exit);
1104
1105 __ inc(eax);
1106 __ blsi(ebx, Operand(esp, 0));
1107 __ cmp(ebx, Immediate(0x00000008u)); // expected result
1108 __ j(not_equal, &exit);
1109
1110 // blsmsk
1111 __ inc(eax);
1112 __ blsmsk(ebx, ecx);
1113 __ cmp(ebx, Immediate(0x0000000fu)); // expected result
1114 __ j(not_equal, &exit);
1115
1116 __ inc(eax);
1117 __ blsmsk(ebx, Operand(esp, 0));
1118 __ cmp(ebx, Immediate(0x0000000fu)); // expected result
1119 __ j(not_equal, &exit);
1120
1121 // blsr
1122 __ inc(eax);
1123 __ blsr(ebx, ecx);
1124 __ cmp(ebx, Immediate(0x55667780u)); // expected result
1125 __ j(not_equal, &exit);
1126
1127 __ inc(eax);
1128 __ blsr(ebx, Operand(esp, 0));
1129 __ cmp(ebx, Immediate(0x55667780u)); // expected result
1130 __ j(not_equal, &exit);
1131
1132 // tzcnt
1133 __ inc(eax);
1134 __ tzcnt(ebx, ecx);
1135 __ cmp(ebx, Immediate(3)); // expected result
1136 __ j(not_equal, &exit);
1137
1138 __ inc(eax);
1139 __ tzcnt(ebx, Operand(esp, 0));
1140 __ cmp(ebx, Immediate(3)); // expected result
1141 __ j(not_equal, &exit);
1142
1143 __ xor_(eax, eax);
1144 __ bind(&exit);
1145 __ pop(ecx);
1146 __ pop(ebx);
1147 __ ret(0);
1148 }
1149
1150 CodeDesc desc;
1151 assm.GetCode(&desc);
1152 Handle<Code> code = isolate->factory()->NewCode(
1153 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1154#ifdef OBJECT_PRINT
1155 OFStream os(stdout);
1156 code->Print(os);
1157#endif
1158
1159 F0 f = FUNCTION_CAST<F0>(code->entry());
1160 CHECK_EQ(0, f());
1161}
1162
1163
1164TEST(AssemblerIa32LZCNT) {
1165 CcTest::InitializeVM();
1166 if (!CpuFeatures::IsSupported(LZCNT)) return;
1167
1168 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1169 HandleScope scope(isolate);
1170 v8::internal::byte buffer[256];
1171 MacroAssembler assm(isolate, buffer, sizeof(buffer),
1172 v8::internal::CodeObjectRequired::kYes);
1173 {
1174 CpuFeatureScope fscope(&assm, LZCNT);
1175 Label exit;
1176
1177 __ push(ebx); // save ebx
1178 __ mov(ecx, Immediate(0x55667788u)); // source operand
1179 __ push(ecx); // For memory operand
1180
1181 __ mov(eax, Immediate(1)); // Test number
1182 __ lzcnt(ebx, ecx);
1183 __ cmp(ebx, Immediate(1)); // expected result
1184 __ j(not_equal, &exit);
1185
1186 __ inc(eax);
1187 __ lzcnt(ebx, Operand(esp, 0));
1188 __ cmp(ebx, Immediate(1)); // expected result
1189 __ j(not_equal, &exit);
1190
1191 __ xor_(eax, eax);
1192 __ bind(&exit);
1193 __ pop(ecx);
1194 __ pop(ebx);
1195 __ ret(0);
1196 }
1197
1198 CodeDesc desc;
1199 assm.GetCode(&desc);
1200 Handle<Code> code = isolate->factory()->NewCode(
1201 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1202#ifdef OBJECT_PRINT
1203 OFStream os(stdout);
1204 code->Print(os);
1205#endif
1206
1207 F0 f = FUNCTION_CAST<F0>(code->entry());
1208 CHECK_EQ(0, f());
1209}
1210
1211
1212TEST(AssemblerIa32POPCNT) {
1213 CcTest::InitializeVM();
1214 if (!CpuFeatures::IsSupported(POPCNT)) return;
1215
1216 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1217 HandleScope scope(isolate);
1218 v8::internal::byte buffer[256];
1219 MacroAssembler assm(isolate, buffer, sizeof(buffer),
1220 v8::internal::CodeObjectRequired::kYes);
1221 {
1222 CpuFeatureScope fscope(&assm, POPCNT);
1223 Label exit;
1224
1225 __ push(ebx); // save ebx
1226 __ mov(ecx, Immediate(0x11111100u)); // source operand
1227 __ push(ecx); // For memory operand
1228
1229 __ mov(eax, Immediate(1)); // Test number
1230 __ popcnt(ebx, ecx);
1231 __ cmp(ebx, Immediate(6)); // expected result
1232 __ j(not_equal, &exit);
1233
1234 __ inc(eax);
1235 __ popcnt(ebx, Operand(esp, 0));
1236 __ cmp(ebx, Immediate(6)); // expected result
1237 __ j(not_equal, &exit);
1238
1239 __ xor_(eax, eax);
1240 __ bind(&exit);
1241 __ pop(ecx);
1242 __ pop(ebx);
1243 __ ret(0);
1244 }
1245
1246 CodeDesc desc;
1247 assm.GetCode(&desc);
1248 Handle<Code> code = isolate->factory()->NewCode(
1249 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1250#ifdef OBJECT_PRINT
1251 OFStream os(stdout);
1252 code->Print(os);
1253#endif
1254
1255 F0 f = FUNCTION_CAST<F0>(code->entry());
1256 CHECK_EQ(0, f());
1257}
1258
1259
1260TEST(AssemblerIa32BMI2) {
1261 CcTest::InitializeVM();
1262 if (!CpuFeatures::IsSupported(BMI2)) return;
1263
1264 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1265 HandleScope scope(isolate);
1266 v8::internal::byte buffer[2048];
1267 MacroAssembler assm(isolate, buffer, sizeof(buffer),
1268 v8::internal::CodeObjectRequired::kYes);
1269 {
1270 CpuFeatureScope fscope(&assm, BMI2);
1271 Label exit;
1272
1273 __ push(ebx); // save ebx
1274 __ push(esi); // save esi
1275 __ mov(ecx, Immediate(0x55667788u)); // source operand
1276 __ push(ecx); // For memory operand
1277
1278 // bzhi
1279 __ mov(edx, Immediate(9));
1280
1281 __ mov(eax, Immediate(1)); // Test number
1282 __ bzhi(ebx, ecx, edx);
1283 __ cmp(ebx, Immediate(0x00000188u)); // expected result
1284 __ j(not_equal, &exit);
1285
1286 __ inc(eax);
1287 __ bzhi(ebx, Operand(esp, 0), edx);
1288 __ cmp(ebx, Immediate(0x00000188u)); // expected result
1289 __ j(not_equal, &exit);
1290
1291 // mulx
1292 __ mov(edx, Immediate(0x00001000u));
1293
1294 __ inc(eax);
1295 __ mulx(ebx, esi, ecx);
1296 __ cmp(ebx, Immediate(0x00000556u)); // expected result
1297 __ j(not_equal, &exit);
1298 __ cmp(esi, Immediate(0x67788000u)); // expected result
1299 __ j(not_equal, &exit);
1300
1301 __ inc(eax);
1302 __ mulx(ebx, esi, Operand(esp, 0));
1303 __ cmp(ebx, Immediate(0x00000556u)); // expected result
1304 __ j(not_equal, &exit);
1305 __ cmp(esi, Immediate(0x67788000u)); // expected result
1306 __ j(not_equal, &exit);
1307
1308 // pdep
1309 __ mov(edx, Immediate(0xfffffff0u));
1310
1311 __ inc(eax);
1312 __ pdep(ebx, edx, ecx);
1313 __ cmp(ebx, Immediate(0x55667400u)); // expected result
1314 __ j(not_equal, &exit);
1315
1316 __ inc(eax);
1317 __ pdep(ebx, edx, Operand(esp, 0));
1318 __ cmp(ebx, Immediate(0x55667400u)); // expected result
1319 __ j(not_equal, &exit);
1320
1321 // pext
1322 __ mov(edx, Immediate(0xfffffff0u));
1323
1324 __ inc(eax);
1325 __ pext(ebx, edx, ecx);
1326 __ cmp(ebx, Immediate(0x0000fffeu)); // expected result
1327 __ j(not_equal, &exit);
1328
1329 __ inc(eax);
1330 __ pext(ebx, edx, Operand(esp, 0));
1331 __ cmp(ebx, Immediate(0x0000fffeu)); // expected result
1332 __ j(not_equal, &exit);
1333
1334 // sarx
1335 __ mov(edx, Immediate(4));
1336
1337 __ inc(eax);
1338 __ sarx(ebx, ecx, edx);
1339 __ cmp(ebx, Immediate(0x05566778u)); // expected result
1340 __ j(not_equal, &exit);
1341
1342 __ inc(eax);
1343 __ sarx(ebx, Operand(esp, 0), edx);
1344 __ cmp(ebx, Immediate(0x05566778u)); // expected result
1345 __ j(not_equal, &exit);
1346
1347 // shlx
1348 __ mov(edx, Immediate(4));
1349
1350 __ inc(eax);
1351 __ shlx(ebx, ecx, edx);
1352 __ cmp(ebx, Immediate(0x56677880u)); // expected result
1353 __ j(not_equal, &exit);
1354
1355 __ inc(eax);
1356 __ shlx(ebx, Operand(esp, 0), edx);
1357 __ cmp(ebx, Immediate(0x56677880u)); // expected result
1358 __ j(not_equal, &exit);
1359
1360 // shrx
1361 __ mov(edx, Immediate(4));
1362
1363 __ inc(eax);
1364 __ shrx(ebx, ecx, edx);
1365 __ cmp(ebx, Immediate(0x05566778u)); // expected result
1366 __ j(not_equal, &exit);
1367
1368 __ inc(eax);
1369 __ shrx(ebx, Operand(esp, 0), edx);
1370 __ cmp(ebx, Immediate(0x05566778u)); // expected result
1371 __ j(not_equal, &exit);
1372
1373 // rorx
1374 __ inc(eax);
1375 __ rorx(ebx, ecx, 0x4);
1376 __ cmp(ebx, Immediate(0x85566778u)); // expected result
1377 __ j(not_equal, &exit);
1378
1379 __ inc(eax);
1380 __ rorx(ebx, Operand(esp, 0), 0x4);
1381 __ cmp(ebx, Immediate(0x85566778u)); // expected result
1382 __ j(not_equal, &exit);
1383
1384 __ xor_(eax, eax);
1385 __ bind(&exit);
1386 __ pop(ecx);
1387 __ pop(esi);
1388 __ pop(ebx);
1389 __ ret(0);
1390 }
1391
1392 CodeDesc desc;
1393 assm.GetCode(&desc);
1394 Handle<Code> code = isolate->factory()->NewCode(
1395 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1396#ifdef OBJECT_PRINT
1397 OFStream os(stdout);
1398 code->Print(os);
1399#endif
1400
1401 F0 f = FUNCTION_CAST<F0>(code->entry());
1402 CHECK_EQ(0, f());
1403}
1404
1405
1406TEST(AssemblerIa32JumpTables1) {
1407 // Test jump tables with forward jumps.
1408 CcTest::InitializeVM();
1409 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1410 HandleScope scope(isolate);
1411 Assembler assm(isolate, nullptr, 0);
1412
1413 const int kNumCases = 512;
1414 int values[kNumCases];
1415 isolate->random_number_generator()->NextBytes(values, sizeof(values));
1416 Label labels[kNumCases];
1417
1418 Label done, table;
1419 __ mov(eax, Operand(esp, 4));
1420 __ jmp(Operand::JumpTable(eax, times_4, &table));
1421 __ ud2();
1422 __ bind(&table);
1423 for (int i = 0; i < kNumCases; ++i) {
1424 __ dd(&labels[i]);
1425 }
1426
1427 for (int i = 0; i < kNumCases; ++i) {
1428 __ bind(&labels[i]);
1429 __ mov(eax, Immediate(values[i]));
1430 __ jmp(&done);
1431 }
1432
1433 __ bind(&done);
1434 __ ret(0);
1435
1436 CodeDesc desc;
1437 assm.GetCode(&desc);
1438 Handle<Code> code = isolate->factory()->NewCode(
1439 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1440#ifdef OBJECT_PRINT
1441 OFStream os(stdout);
1442 code->Print(os);
1443#endif
1444 F1 f = FUNCTION_CAST<F1>(code->entry());
1445 for (int i = 0; i < kNumCases; ++i) {
1446 int res = f(i);
1447 ::printf("f(%d) = %d\n", i, res);
1448 CHECK_EQ(values[i], res);
1449 }
1450}
1451
1452
1453TEST(AssemblerIa32JumpTables2) {
1454 // Test jump tables with backward jumps.
1455 CcTest::InitializeVM();
1456 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1457 HandleScope scope(isolate);
1458 Assembler assm(isolate, nullptr, 0);
1459
1460 const int kNumCases = 512;
1461 int values[kNumCases];
1462 isolate->random_number_generator()->NextBytes(values, sizeof(values));
1463 Label labels[kNumCases];
1464
1465 Label done, table;
1466 __ mov(eax, Operand(esp, 4));
1467 __ jmp(Operand::JumpTable(eax, times_4, &table));
1468 __ ud2();
1469
1470 for (int i = 0; i < kNumCases; ++i) {
1471 __ bind(&labels[i]);
1472 __ mov(eax, Immediate(values[i]));
1473 __ jmp(&done);
1474 }
1475
1476 __ bind(&table);
1477 for (int i = 0; i < kNumCases; ++i) {
1478 __ dd(&labels[i]);
1479 }
1480
1481 __ bind(&done);
1482 __ ret(0);
1483
1484 CodeDesc desc;
1485 assm.GetCode(&desc);
1486 Handle<Code> code = isolate->factory()->NewCode(
1487 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1488#ifdef OBJECT_PRINT
1489 OFStream os(stdout);
1490 code->Print(os);
1491#endif
1492 F1 f = FUNCTION_CAST<F1>(code->entry());
1493 for (int i = 0; i < kNumCases; ++i) {
1494 int res = f(i);
1495 ::printf("f(%d) = %d\n", i, res);
1496 CHECK_EQ(values[i], res);
1497 }
1498}
1499
Ben Murdochc5610432016-08-08 18:44:38 +01001500TEST(Regress621926) {
1501 // Bug description:
1502 // The opcodes for cmpw r/m16, r16 and cmpw r16, r/m16 were swapped.
1503 // This was causing non-commutative comparisons to produce the wrong result.
1504 CcTest::InitializeVM();
1505 Isolate* isolate = reinterpret_cast<Isolate*>(CcTest::isolate());
1506 HandleScope scope(isolate);
1507 Assembler assm(isolate, nullptr, 0);
1508
1509 uint16_t a = 42;
1510
1511 Label fail;
1512 __ push(ebx);
1513 __ mov(ebx, Immediate(reinterpret_cast<intptr_t>(&a)));
1514 __ mov(eax, Immediate(41));
1515 __ cmpw(eax, Operand(ebx, 0));
1516 __ j(above_equal, &fail);
1517 __ cmpw(Operand(ebx, 0), eax);
1518 __ j(below_equal, &fail);
1519 __ mov(eax, 1);
1520 __ pop(ebx);
1521 __ ret(0);
1522 __ bind(&fail);
1523 __ mov(eax, 0);
1524 __ pop(ebx);
1525 __ ret(0);
1526
1527 CodeDesc desc;
1528 assm.GetCode(&desc);
1529 Handle<Code> code = isolate->factory()->NewCode(
1530 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1531
1532#ifdef OBJECT_PRINT
1533 OFStream os(stdout);
1534 code->Print(os);
1535#endif
1536
1537 F0 f = FUNCTION_CAST<F0>(code->entry());
1538 CHECK_EQ(f(), 1);
1539}
1540
Steve Blocka7e24c12009-10-30 11:49:00 +00001541#undef __