blob: 612f9e88a3d96e5808064a037707f1f0b88c3eb9 [file] [log] [blame]
Steve Block3ce2e202009-11-05 08:53:23 +00001// Copyright 2009 the V8 project authors. All rights reserved.
2// 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 Block3ce2e202009-11-05 08:53:23 +000031
Ben Murdochb8a8cc12014-11-26 15:28:44 +000032#include "src/base/platform/platform.h"
33#include "src/factory.h"
34#include "src/macro-assembler.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000035#include "test/cctest/cctest.h"
Steve Block3ce2e202009-11-05 08:53:23 +000036
Ben Murdochb8a8cc12014-11-26 15:28:44 +000037namespace i = v8::internal;
38using i::Address;
39using i::Assembler;
40using i::CodeDesc;
41using i::Condition;
42using i::FUNCTION_CAST;
43using i::HandleScope;
44using i::Immediate;
45using i::Isolate;
46using i::Label;
47using i::MacroAssembler;
48using i::Operand;
49using i::RelocInfo;
50using i::Representation;
51using i::Smi;
52using i::SmiIndex;
53using i::byte;
54using i::carry;
55using i::greater;
56using i::greater_equal;
57using i::kIntSize;
58using i::kPointerSize;
59using i::kSmiTagMask;
60using i::kSmiValueSize;
61using i::less_equal;
62using i::negative;
63using i::not_carry;
64using i::not_equal;
65using i::equal;
66using i::not_zero;
67using i::positive;
68using i::r11;
69using i::r13;
70using i::r14;
71using i::r15;
72using i::r8;
73using i::r9;
74using i::rax;
75using i::rbp;
76using i::rbx;
77using i::rcx;
78using i::rdi;
79using i::rdx;
80using i::rsi;
81using i::rsp;
82using i::times_pointer_size;
Steve Block3ce2e202009-11-05 08:53:23 +000083
84// Test the x64 assembler by compiling some simple functions into
85// a buffer and executing them. These tests do not initialize the
86// V8 library, create a context, or use any V8 objects.
87// The AMD64 calling convention is used, with the first five arguments
88// in RSI, RDI, RDX, RCX, R8, and R9, and floating point arguments in
89// the XMM registers. The return value is in RAX.
90// This calling convention is used on Linux, with GCC, and on Mac OS,
91// with GCC. A different convention is used on 64-bit windows.
92
93typedef int (*F0)();
94
95#define __ masm->
96
Steve Block8defd9f2010-07-08 12:39:36 +010097
98static void EntryCode(MacroAssembler* masm) {
99 // Smi constant register is callee save.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000100 __ pushq(i::kRootRegister);
Steve Block44f0eee2011-05-26 01:26:41 +0100101 __ InitializeRootRegister();
Steve Block8defd9f2010-07-08 12:39:36 +0100102}
103
104
105static void ExitCode(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000106 __ popq(i::kRootRegister);
Steve Block8defd9f2010-07-08 12:39:36 +0100107}
108
109
Steve Block3ce2e202009-11-05 08:53:23 +0000110TEST(Smi) {
111 // Check that C++ Smi operations work as expected.
Leon Clarkee46be812010-01-19 14:06:41 +0000112 int64_t test_numbers[] = {
Steve Block3ce2e202009-11-05 08:53:23 +0000113 0, 1, -1, 127, 128, -128, -129, 255, 256, -256, -257,
Leon Clarkee46be812010-01-19 14:06:41 +0000114 Smi::kMaxValue, static_cast<int64_t>(Smi::kMaxValue) + 1,
115 Smi::kMinValue, static_cast<int64_t>(Smi::kMinValue) - 1
Steve Block3ce2e202009-11-05 08:53:23 +0000116 };
117 int test_number_count = 15;
118 for (int i = 0; i < test_number_count; i++) {
Leon Clarkee46be812010-01-19 14:06:41 +0000119 int64_t number = test_numbers[i];
Steve Block3ce2e202009-11-05 08:53:23 +0000120 bool is_valid = Smi::IsValid(number);
121 bool is_in_range = number >= Smi::kMinValue && number <= Smi::kMaxValue;
122 CHECK_EQ(is_in_range, is_valid);
123 if (is_valid) {
124 Smi* smi_from_intptr = Smi::FromIntptr(number);
125 if (static_cast<int>(number) == number) { // Is a 32-bit int.
126 Smi* smi_from_int = Smi::FromInt(static_cast<int32_t>(number));
127 CHECK_EQ(smi_from_int, smi_from_intptr);
128 }
Leon Clarkee46be812010-01-19 14:06:41 +0000129 int64_t smi_value = smi_from_intptr->value();
130 CHECK_EQ(number, smi_value);
Steve Block3ce2e202009-11-05 08:53:23 +0000131 }
132 }
133}
134
135
136static void TestMoveSmi(MacroAssembler* masm, Label* exit, int id, Smi* value) {
137 __ movl(rax, Immediate(id));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000138 __ Move(rcx, value);
139 __ Set(rdx, reinterpret_cast<intptr_t>(value));
Steve Block3ce2e202009-11-05 08:53:23 +0000140 __ cmpq(rcx, rdx);
141 __ j(not_equal, exit);
142}
143
144
145// Test that we can move a Smi value literally into a register.
146TEST(SmiMove) {
147 // Allocate an executable page of memory.
148 size_t actual_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000149 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
150 Assembler::kMinimalBufferSize, &actual_size, true));
Steve Block3ce2e202009-11-05 08:53:23 +0000151 CHECK(buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000152 Isolate* isolate = CcTest::i_isolate();
153 HandleScope handles(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000154 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
155 v8::internal::CodeObjectRequired::kYes);
Steve Block3ce2e202009-11-05 08:53:23 +0000156 MacroAssembler* masm = &assembler; // Create a pointer for the __ macro.
Steve Block8defd9f2010-07-08 12:39:36 +0100157 EntryCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +0000158 Label exit;
159
160 TestMoveSmi(masm, &exit, 1, Smi::FromInt(0));
161 TestMoveSmi(masm, &exit, 2, Smi::FromInt(127));
162 TestMoveSmi(masm, &exit, 3, Smi::FromInt(128));
163 TestMoveSmi(masm, &exit, 4, Smi::FromInt(255));
164 TestMoveSmi(masm, &exit, 5, Smi::FromInt(256));
165 TestMoveSmi(masm, &exit, 6, Smi::FromInt(Smi::kMaxValue));
166 TestMoveSmi(masm, &exit, 7, Smi::FromInt(-1));
167 TestMoveSmi(masm, &exit, 8, Smi::FromInt(-128));
168 TestMoveSmi(masm, &exit, 9, Smi::FromInt(-129));
169 TestMoveSmi(masm, &exit, 10, Smi::FromInt(-256));
170 TestMoveSmi(masm, &exit, 11, Smi::FromInt(-257));
171 TestMoveSmi(masm, &exit, 12, Smi::FromInt(Smi::kMinValue));
172
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000173 __ xorq(rax, rax); // Success.
Steve Block3ce2e202009-11-05 08:53:23 +0000174 __ bind(&exit);
Steve Block8defd9f2010-07-08 12:39:36 +0100175 ExitCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +0000176 __ ret(0);
177
178 CodeDesc desc;
179 masm->GetCode(&desc);
180 // Call the function from C++.
181 int result = FUNCTION_CAST<F0>(buffer)();
182 CHECK_EQ(0, result);
183}
184
185
186void TestSmiCompare(MacroAssembler* masm, Label* exit, int id, int x, int y) {
187 __ Move(rcx, Smi::FromInt(x));
188 __ movq(r8, rcx);
189 __ Move(rdx, Smi::FromInt(y));
190 __ movq(r9, rdx);
191 __ SmiCompare(rcx, rdx);
192 if (x < y) {
193 __ movl(rax, Immediate(id + 1));
194 __ j(greater_equal, exit);
195 } else if (x > y) {
196 __ movl(rax, Immediate(id + 2));
197 __ j(less_equal, exit);
198 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000199 CHECK_EQ(x, y);
Steve Block3ce2e202009-11-05 08:53:23 +0000200 __ movl(rax, Immediate(id + 3));
201 __ j(not_equal, exit);
202 }
203 __ movl(rax, Immediate(id + 4));
204 __ cmpq(rcx, r8);
205 __ j(not_equal, exit);
206 __ incq(rax);
207 __ cmpq(rdx, r9);
208 __ j(not_equal, exit);
209
210 if (x != y) {
211 __ SmiCompare(rdx, rcx);
212 if (y < x) {
213 __ movl(rax, Immediate(id + 9));
214 __ j(greater_equal, exit);
215 } else {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000216 CHECK(y > x);
Steve Block3ce2e202009-11-05 08:53:23 +0000217 __ movl(rax, Immediate(id + 10));
218 __ j(less_equal, exit);
219 }
220 } else {
Steve Block44f0eee2011-05-26 01:26:41 +0100221 __ cmpq(rcx, rcx);
Steve Block3ce2e202009-11-05 08:53:23 +0000222 __ movl(rax, Immediate(id + 11));
223 __ j(not_equal, exit);
224 __ incq(rax);
225 __ cmpq(rcx, r8);
226 __ j(not_equal, exit);
227 }
228}
229
230
231// Test that we can compare smis for equality (and more).
232TEST(SmiCompare) {
233 // Allocate an executable page of memory.
234 size_t actual_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000235 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
236 Assembler::kMinimalBufferSize * 2, &actual_size, true));
Steve Block3ce2e202009-11-05 08:53:23 +0000237 CHECK(buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000238 Isolate* isolate = CcTest::i_isolate();
239 HandleScope handles(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000240 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
241 v8::internal::CodeObjectRequired::kYes);
Steve Block3ce2e202009-11-05 08:53:23 +0000242
243 MacroAssembler* masm = &assembler;
Steve Block8defd9f2010-07-08 12:39:36 +0100244 EntryCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +0000245 Label exit;
246
247 TestSmiCompare(masm, &exit, 0x10, 0, 0);
248 TestSmiCompare(masm, &exit, 0x20, 0, 1);
249 TestSmiCompare(masm, &exit, 0x30, 1, 0);
250 TestSmiCompare(masm, &exit, 0x40, 1, 1);
251 TestSmiCompare(masm, &exit, 0x50, 0, -1);
252 TestSmiCompare(masm, &exit, 0x60, -1, 0);
253 TestSmiCompare(masm, &exit, 0x70, -1, -1);
254 TestSmiCompare(masm, &exit, 0x80, 0, Smi::kMinValue);
255 TestSmiCompare(masm, &exit, 0x90, Smi::kMinValue, 0);
256 TestSmiCompare(masm, &exit, 0xA0, 0, Smi::kMaxValue);
257 TestSmiCompare(masm, &exit, 0xB0, Smi::kMaxValue, 0);
258 TestSmiCompare(masm, &exit, 0xC0, -1, Smi::kMinValue);
259 TestSmiCompare(masm, &exit, 0xD0, Smi::kMinValue, -1);
260 TestSmiCompare(masm, &exit, 0xE0, -1, Smi::kMaxValue);
261 TestSmiCompare(masm, &exit, 0xF0, Smi::kMaxValue, -1);
262 TestSmiCompare(masm, &exit, 0x100, Smi::kMinValue, Smi::kMinValue);
263 TestSmiCompare(masm, &exit, 0x110, Smi::kMinValue, Smi::kMaxValue);
264 TestSmiCompare(masm, &exit, 0x120, Smi::kMaxValue, Smi::kMinValue);
265 TestSmiCompare(masm, &exit, 0x130, Smi::kMaxValue, Smi::kMaxValue);
266
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000267 __ xorq(rax, rax); // Success.
Steve Block3ce2e202009-11-05 08:53:23 +0000268 __ bind(&exit);
Steve Block8defd9f2010-07-08 12:39:36 +0100269 ExitCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +0000270 __ ret(0);
271
272 CodeDesc desc;
273 masm->GetCode(&desc);
274 // Call the function from C++.
275 int result = FUNCTION_CAST<F0>(buffer)();
276 CHECK_EQ(0, result);
277}
278
279
280
281TEST(Integer32ToSmi) {
282 // Allocate an executable page of memory.
283 size_t actual_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000284 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
285 Assembler::kMinimalBufferSize, &actual_size, true));
Steve Block3ce2e202009-11-05 08:53:23 +0000286 CHECK(buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000287 Isolate* isolate = CcTest::i_isolate();
288 HandleScope handles(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000289 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
290 v8::internal::CodeObjectRequired::kYes);
Steve Block3ce2e202009-11-05 08:53:23 +0000291
292 MacroAssembler* masm = &assembler;
Steve Block8defd9f2010-07-08 12:39:36 +0100293 EntryCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +0000294 Label exit;
295
296 __ movq(rax, Immediate(1)); // Test number.
297 __ movl(rcx, Immediate(0));
298 __ Integer32ToSmi(rcx, rcx);
299 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(0)));
Steve Block44f0eee2011-05-26 01:26:41 +0100300 __ cmpq(rcx, rdx);
Steve Block3ce2e202009-11-05 08:53:23 +0000301 __ j(not_equal, &exit);
302
303 __ movq(rax, Immediate(2)); // Test number.
304 __ movl(rcx, Immediate(1024));
305 __ Integer32ToSmi(rcx, rcx);
306 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(1024)));
Steve Block44f0eee2011-05-26 01:26:41 +0100307 __ cmpq(rcx, rdx);
Steve Block3ce2e202009-11-05 08:53:23 +0000308 __ j(not_equal, &exit);
309
310 __ movq(rax, Immediate(3)); // Test number.
311 __ movl(rcx, Immediate(-1));
312 __ Integer32ToSmi(rcx, rcx);
313 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(-1)));
Steve Block44f0eee2011-05-26 01:26:41 +0100314 __ cmpq(rcx, rdx);
Steve Block3ce2e202009-11-05 08:53:23 +0000315 __ j(not_equal, &exit);
316
317 __ movq(rax, Immediate(4)); // Test number.
318 __ movl(rcx, Immediate(Smi::kMaxValue));
319 __ Integer32ToSmi(rcx, rcx);
320 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMaxValue)));
Steve Block44f0eee2011-05-26 01:26:41 +0100321 __ cmpq(rcx, rdx);
Steve Block3ce2e202009-11-05 08:53:23 +0000322 __ j(not_equal, &exit);
323
324 __ movq(rax, Immediate(5)); // Test number.
325 __ movl(rcx, Immediate(Smi::kMinValue));
326 __ Integer32ToSmi(rcx, rcx);
327 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMinValue)));
Steve Block44f0eee2011-05-26 01:26:41 +0100328 __ cmpq(rcx, rdx);
Steve Block3ce2e202009-11-05 08:53:23 +0000329 __ j(not_equal, &exit);
330
331 // Different target register.
332
333 __ movq(rax, Immediate(6)); // Test number.
334 __ movl(rcx, Immediate(0));
335 __ Integer32ToSmi(r8, rcx);
336 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(0)));
Steve Block44f0eee2011-05-26 01:26:41 +0100337 __ cmpq(r8, rdx);
Steve Block3ce2e202009-11-05 08:53:23 +0000338 __ j(not_equal, &exit);
339
340 __ movq(rax, Immediate(7)); // Test number.
341 __ movl(rcx, Immediate(1024));
342 __ Integer32ToSmi(r8, rcx);
343 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(1024)));
Steve Block44f0eee2011-05-26 01:26:41 +0100344 __ cmpq(r8, rdx);
Steve Block3ce2e202009-11-05 08:53:23 +0000345 __ j(not_equal, &exit);
346
347 __ movq(rax, Immediate(8)); // Test number.
348 __ movl(rcx, Immediate(-1));
349 __ Integer32ToSmi(r8, rcx);
350 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(-1)));
Steve Block44f0eee2011-05-26 01:26:41 +0100351 __ cmpq(r8, rdx);
Steve Block3ce2e202009-11-05 08:53:23 +0000352 __ j(not_equal, &exit);
353
354 __ movq(rax, Immediate(9)); // Test number.
355 __ movl(rcx, Immediate(Smi::kMaxValue));
356 __ Integer32ToSmi(r8, rcx);
357 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMaxValue)));
Steve Block44f0eee2011-05-26 01:26:41 +0100358 __ cmpq(r8, rdx);
Steve Block3ce2e202009-11-05 08:53:23 +0000359 __ j(not_equal, &exit);
360
361 __ movq(rax, Immediate(10)); // Test number.
362 __ movl(rcx, Immediate(Smi::kMinValue));
363 __ Integer32ToSmi(r8, rcx);
364 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMinValue)));
Steve Block44f0eee2011-05-26 01:26:41 +0100365 __ cmpq(r8, rdx);
Steve Block3ce2e202009-11-05 08:53:23 +0000366 __ j(not_equal, &exit);
367
368
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000369 __ xorq(rax, rax); // Success.
Steve Block3ce2e202009-11-05 08:53:23 +0000370 __ bind(&exit);
Steve Block8defd9f2010-07-08 12:39:36 +0100371 ExitCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +0000372 __ ret(0);
373
374 CodeDesc desc;
375 masm->GetCode(&desc);
376 // Call the function from C++.
377 int result = FUNCTION_CAST<F0>(buffer)();
378 CHECK_EQ(0, result);
379}
380
381
382void TestI64PlusConstantToSmi(MacroAssembler* masm,
383 Label* exit,
384 int id,
385 int64_t x,
386 int y) {
387 int64_t result = x + y;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000388 CHECK(Smi::IsValid(result));
Steve Block3ce2e202009-11-05 08:53:23 +0000389 __ movl(rax, Immediate(id));
Steve Blockd0582a62009-12-15 09:54:21 +0000390 __ Move(r8, Smi::FromInt(static_cast<int>(result)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000391 __ movq(rcx, x);
Steve Block3ce2e202009-11-05 08:53:23 +0000392 __ movq(r11, rcx);
393 __ Integer64PlusConstantToSmi(rdx, rcx, y);
Steve Block44f0eee2011-05-26 01:26:41 +0100394 __ cmpq(rdx, r8);
Steve Block3ce2e202009-11-05 08:53:23 +0000395 __ j(not_equal, exit);
396
397 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +0100398 __ cmpq(r11, rcx);
Steve Block3ce2e202009-11-05 08:53:23 +0000399 __ j(not_equal, exit);
400
401 __ incq(rax);
402 __ Integer64PlusConstantToSmi(rcx, rcx, y);
Steve Block44f0eee2011-05-26 01:26:41 +0100403 __ cmpq(rcx, r8);
Steve Block3ce2e202009-11-05 08:53:23 +0000404 __ j(not_equal, exit);
405}
406
407
408TEST(Integer64PlusConstantToSmi) {
409 // Allocate an executable page of memory.
410 size_t actual_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000411 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
412 Assembler::kMinimalBufferSize, &actual_size, true));
Steve Block3ce2e202009-11-05 08:53:23 +0000413 CHECK(buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000414 Isolate* isolate = CcTest::i_isolate();
415 HandleScope handles(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000416 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
417 v8::internal::CodeObjectRequired::kYes);
Steve Block3ce2e202009-11-05 08:53:23 +0000418
419 MacroAssembler* masm = &assembler;
Steve Block8defd9f2010-07-08 12:39:36 +0100420 EntryCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +0000421 Label exit;
422
423 int64_t twice_max = static_cast<int64_t>(Smi::kMaxValue) * 2;
424
425 TestI64PlusConstantToSmi(masm, &exit, 0x10, 0, 0);
426 TestI64PlusConstantToSmi(masm, &exit, 0x20, 0, 1);
427 TestI64PlusConstantToSmi(masm, &exit, 0x30, 1, 0);
428 TestI64PlusConstantToSmi(masm, &exit, 0x40, Smi::kMaxValue - 5, 5);
429 TestI64PlusConstantToSmi(masm, &exit, 0x50, Smi::kMinValue + 5, 5);
430 TestI64PlusConstantToSmi(masm, &exit, 0x60, twice_max, -Smi::kMaxValue);
431 TestI64PlusConstantToSmi(masm, &exit, 0x70, -twice_max, Smi::kMaxValue);
432 TestI64PlusConstantToSmi(masm, &exit, 0x80, 0, Smi::kMinValue);
433 TestI64PlusConstantToSmi(masm, &exit, 0x90, 0, Smi::kMaxValue);
434 TestI64PlusConstantToSmi(masm, &exit, 0xA0, Smi::kMinValue, 0);
435 TestI64PlusConstantToSmi(masm, &exit, 0xB0, Smi::kMaxValue, 0);
436 TestI64PlusConstantToSmi(masm, &exit, 0xC0, twice_max, Smi::kMinValue);
437
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000438 __ xorq(rax, rax); // Success.
Steve Block3ce2e202009-11-05 08:53:23 +0000439 __ bind(&exit);
Steve Block8defd9f2010-07-08 12:39:36 +0100440 ExitCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +0000441 __ ret(0);
442
443 CodeDesc desc;
444 masm->GetCode(&desc);
445 // Call the function from C++.
446 int result = FUNCTION_CAST<F0>(buffer)();
447 CHECK_EQ(0, result);
448}
449
450
451TEST(SmiCheck) {
452 // Allocate an executable page of memory.
453 size_t actual_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000454 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
455 Assembler::kMinimalBufferSize, &actual_size, true));
Steve Block3ce2e202009-11-05 08:53:23 +0000456 CHECK(buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000457 Isolate* isolate = CcTest::i_isolate();
458 HandleScope handles(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000459 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
460 v8::internal::CodeObjectRequired::kYes);
Steve Block3ce2e202009-11-05 08:53:23 +0000461
462 MacroAssembler* masm = &assembler;
Steve Block8defd9f2010-07-08 12:39:36 +0100463 EntryCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +0000464 Label exit;
465 Condition cond;
466
467 __ movl(rax, Immediate(1)); // Test number.
468
469 // CheckSmi
470
471 __ movl(rcx, Immediate(0));
472 __ Integer32ToSmi(rcx, rcx);
473 cond = masm->CheckSmi(rcx);
474 __ j(NegateCondition(cond), &exit);
475
476 __ incq(rax);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000477 __ xorq(rcx, Immediate(kSmiTagMask));
Steve Block3ce2e202009-11-05 08:53:23 +0000478 cond = masm->CheckSmi(rcx);
479 __ j(cond, &exit);
480
481 __ incq(rax);
482 __ movl(rcx, Immediate(-1));
483 __ Integer32ToSmi(rcx, rcx);
484 cond = masm->CheckSmi(rcx);
485 __ j(NegateCondition(cond), &exit);
486
487 __ incq(rax);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000488 __ xorq(rcx, Immediate(kSmiTagMask));
Steve Block3ce2e202009-11-05 08:53:23 +0000489 cond = masm->CheckSmi(rcx);
490 __ j(cond, &exit);
491
492 __ incq(rax);
493 __ movl(rcx, Immediate(Smi::kMaxValue));
494 __ Integer32ToSmi(rcx, rcx);
495 cond = masm->CheckSmi(rcx);
496 __ j(NegateCondition(cond), &exit);
497
498 __ incq(rax);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000499 __ xorq(rcx, Immediate(kSmiTagMask));
Steve Block3ce2e202009-11-05 08:53:23 +0000500 cond = masm->CheckSmi(rcx);
501 __ j(cond, &exit);
502
503 __ incq(rax);
504 __ movl(rcx, Immediate(Smi::kMinValue));
505 __ Integer32ToSmi(rcx, rcx);
506 cond = masm->CheckSmi(rcx);
507 __ j(NegateCondition(cond), &exit);
508
509 __ incq(rax);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000510 __ xorq(rcx, Immediate(kSmiTagMask));
Steve Block3ce2e202009-11-05 08:53:23 +0000511 cond = masm->CheckSmi(rcx);
512 __ j(cond, &exit);
513
514 // CheckPositiveSmi
515
516 __ incq(rax);
517 __ movl(rcx, Immediate(0));
518 __ Integer32ToSmi(rcx, rcx);
Ben Murdochf87a2032010-10-22 12:50:53 +0100519 cond = masm->CheckNonNegativeSmi(rcx);
Steve Block3ce2e202009-11-05 08:53:23 +0000520 __ j(NegateCondition(cond), &exit);
521
522 __ incq(rax);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000523 __ xorq(rcx, Immediate(kSmiTagMask));
Ben Murdochf87a2032010-10-22 12:50:53 +0100524 cond = masm->CheckNonNegativeSmi(rcx); // "zero" non-smi.
Steve Block3ce2e202009-11-05 08:53:23 +0000525 __ j(cond, &exit);
526
527 __ incq(rax);
528 __ movq(rcx, Immediate(-1));
529 __ Integer32ToSmi(rcx, rcx);
Ben Murdochf87a2032010-10-22 12:50:53 +0100530 cond = masm->CheckNonNegativeSmi(rcx); // Negative smis are not positive.
Steve Block3ce2e202009-11-05 08:53:23 +0000531 __ j(cond, &exit);
532
533 __ incq(rax);
534 __ movq(rcx, Immediate(Smi::kMinValue));
535 __ Integer32ToSmi(rcx, rcx);
Ben Murdochf87a2032010-10-22 12:50:53 +0100536 cond = masm->CheckNonNegativeSmi(rcx); // Most negative smi is not positive.
Steve Block3ce2e202009-11-05 08:53:23 +0000537 __ j(cond, &exit);
538
539 __ incq(rax);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000540 __ xorq(rcx, Immediate(kSmiTagMask));
Ben Murdochf87a2032010-10-22 12:50:53 +0100541 cond = masm->CheckNonNegativeSmi(rcx); // "Negative" non-smi.
Steve Block3ce2e202009-11-05 08:53:23 +0000542 __ j(cond, &exit);
543
544 __ incq(rax);
545 __ movq(rcx, Immediate(Smi::kMaxValue));
546 __ Integer32ToSmi(rcx, rcx);
Ben Murdochf87a2032010-10-22 12:50:53 +0100547 cond = masm->CheckNonNegativeSmi(rcx); // Most positive smi is positive.
Steve Block3ce2e202009-11-05 08:53:23 +0000548 __ j(NegateCondition(cond), &exit);
549
550 __ incq(rax);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000551 __ xorq(rcx, Immediate(kSmiTagMask));
Ben Murdochf87a2032010-10-22 12:50:53 +0100552 cond = masm->CheckNonNegativeSmi(rcx); // "Positive" non-smi.
Steve Block3ce2e202009-11-05 08:53:23 +0000553 __ j(cond, &exit);
554
Steve Block3ce2e202009-11-05 08:53:23 +0000555 // CheckBothSmi
556
557 __ incq(rax);
558 __ movq(rcx, Immediate(Smi::kMaxValue));
559 __ Integer32ToSmi(rcx, rcx);
560 __ movq(rdx, Immediate(Smi::kMinValue));
561 __ Integer32ToSmi(rdx, rdx);
562 cond = masm->CheckBothSmi(rcx, rdx);
563 __ j(NegateCondition(cond), &exit);
564
565 __ incq(rax);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000566 __ xorq(rcx, Immediate(kSmiTagMask));
Steve Block3ce2e202009-11-05 08:53:23 +0000567 cond = masm->CheckBothSmi(rcx, rdx);
568 __ j(cond, &exit);
569
570 __ incq(rax);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000571 __ xorq(rdx, Immediate(kSmiTagMask));
Steve Block3ce2e202009-11-05 08:53:23 +0000572 cond = masm->CheckBothSmi(rcx, rdx);
573 __ j(cond, &exit);
574
575 __ incq(rax);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000576 __ xorq(rcx, Immediate(kSmiTagMask));
Steve Block3ce2e202009-11-05 08:53:23 +0000577 cond = masm->CheckBothSmi(rcx, rdx);
578 __ j(cond, &exit);
579
580 __ incq(rax);
581 cond = masm->CheckBothSmi(rcx, rcx);
582 __ j(NegateCondition(cond), &exit);
583
584 __ incq(rax);
585 cond = masm->CheckBothSmi(rdx, rdx);
586 __ j(cond, &exit);
587
588 // CheckInteger32ValidSmiValue
589 __ incq(rax);
590 __ movq(rcx, Immediate(0));
591 cond = masm->CheckInteger32ValidSmiValue(rax);
592 __ j(NegateCondition(cond), &exit);
593
594 __ incq(rax);
595 __ movq(rcx, Immediate(-1));
596 cond = masm->CheckInteger32ValidSmiValue(rax);
597 __ j(NegateCondition(cond), &exit);
598
599 __ incq(rax);
600 __ movq(rcx, Immediate(Smi::kMaxValue));
601 cond = masm->CheckInteger32ValidSmiValue(rax);
602 __ j(NegateCondition(cond), &exit);
603
604 __ incq(rax);
605 __ movq(rcx, Immediate(Smi::kMinValue));
606 cond = masm->CheckInteger32ValidSmiValue(rax);
607 __ j(NegateCondition(cond), &exit);
608
609 // Success
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000610 __ xorq(rax, rax);
Steve Block3ce2e202009-11-05 08:53:23 +0000611
612 __ bind(&exit);
Steve Block8defd9f2010-07-08 12:39:36 +0100613 ExitCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +0000614 __ ret(0);
615
616 CodeDesc desc;
617 masm->GetCode(&desc);
618 // Call the function from C++.
619 int result = FUNCTION_CAST<F0>(buffer)();
620 CHECK_EQ(0, result);
621}
622
623
624
625void TestSmiNeg(MacroAssembler* masm, Label* exit, int id, int x) {
626 __ Move(rcx, Smi::FromInt(x));
627 __ movq(r11, rcx);
628 if (x == Smi::kMinValue || x == 0) {
629 // Negation fails.
630 __ movl(rax, Immediate(id + 8));
631 __ SmiNeg(r9, rcx, exit);
632
633 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +0100634 __ cmpq(r11, rcx);
Steve Block3ce2e202009-11-05 08:53:23 +0000635 __ j(not_equal, exit);
636
637 __ incq(rax);
638 __ SmiNeg(rcx, rcx, exit);
639
640 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +0100641 __ cmpq(r11, rcx);
Steve Block3ce2e202009-11-05 08:53:23 +0000642 __ j(not_equal, exit);
643 } else {
644 Label smi_ok, smi_ok2;
645 int result = -x;
646 __ movl(rax, Immediate(id));
647 __ Move(r8, Smi::FromInt(result));
648
649 __ SmiNeg(r9, rcx, &smi_ok);
650 __ jmp(exit);
651 __ bind(&smi_ok);
652 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +0100653 __ cmpq(r9, r8);
Steve Block3ce2e202009-11-05 08:53:23 +0000654 __ j(not_equal, exit);
655
656 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +0100657 __ cmpq(r11, rcx);
Steve Block3ce2e202009-11-05 08:53:23 +0000658 __ j(not_equal, exit);
659
660 __ incq(rax);
661 __ SmiNeg(rcx, rcx, &smi_ok2);
662 __ jmp(exit);
663 __ bind(&smi_ok2);
664 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +0100665 __ cmpq(rcx, r8);
Steve Block3ce2e202009-11-05 08:53:23 +0000666 __ j(not_equal, exit);
667 }
668}
669
670
671TEST(SmiNeg) {
672 // Allocate an executable page of memory.
673 size_t actual_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000674 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
675 Assembler::kMinimalBufferSize, &actual_size, true));
Steve Block3ce2e202009-11-05 08:53:23 +0000676 CHECK(buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000677 Isolate* isolate = CcTest::i_isolate();
678 HandleScope handles(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000679 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
680 v8::internal::CodeObjectRequired::kYes);
Steve Block3ce2e202009-11-05 08:53:23 +0000681
682 MacroAssembler* masm = &assembler;
Steve Block8defd9f2010-07-08 12:39:36 +0100683 EntryCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +0000684 Label exit;
685
686 TestSmiNeg(masm, &exit, 0x10, 0);
687 TestSmiNeg(masm, &exit, 0x20, 1);
688 TestSmiNeg(masm, &exit, 0x30, -1);
689 TestSmiNeg(masm, &exit, 0x40, 127);
690 TestSmiNeg(masm, &exit, 0x50, 65535);
691 TestSmiNeg(masm, &exit, 0x60, Smi::kMinValue);
692 TestSmiNeg(masm, &exit, 0x70, Smi::kMaxValue);
693 TestSmiNeg(masm, &exit, 0x80, -Smi::kMaxValue);
694
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000695 __ xorq(rax, rax); // Success.
Steve Block3ce2e202009-11-05 08:53:23 +0000696 __ bind(&exit);
Steve Block8defd9f2010-07-08 12:39:36 +0100697 ExitCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +0000698 __ ret(0);
699
700 CodeDesc desc;
701 masm->GetCode(&desc);
702 // Call the function from C++.
703 int result = FUNCTION_CAST<F0>(buffer)();
704 CHECK_EQ(0, result);
705}
706
707
Steve Block3ce2e202009-11-05 08:53:23 +0000708static void SmiAddTest(MacroAssembler* masm,
709 Label* exit,
710 int id,
711 int first,
712 int second) {
713 __ movl(rcx, Immediate(first));
714 __ Integer32ToSmi(rcx, rcx);
715 __ movl(rdx, Immediate(second));
716 __ Integer32ToSmi(rdx, rdx);
717 __ movl(r8, Immediate(first + second));
718 __ Integer32ToSmi(r8, r8);
719
720 __ movl(rax, Immediate(id)); // Test number.
721 __ SmiAdd(r9, rcx, rdx, exit);
Steve Block44f0eee2011-05-26 01:26:41 +0100722 __ cmpq(r9, r8);
Steve Block3ce2e202009-11-05 08:53:23 +0000723 __ j(not_equal, exit);
724
725 __ incq(rax);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000726 __ SmiAdd(rcx, rcx, rdx, exit);
Steve Block44f0eee2011-05-26 01:26:41 +0100727 __ cmpq(rcx, r8);
Steve Block3ce2e202009-11-05 08:53:23 +0000728 __ j(not_equal, exit);
729
730 __ movl(rcx, Immediate(first));
731 __ Integer32ToSmi(rcx, rcx);
732
733 __ incq(rax);
734 __ SmiAddConstant(r9, rcx, Smi::FromInt(second));
Steve Block44f0eee2011-05-26 01:26:41 +0100735 __ cmpq(r9, r8);
Steve Block3ce2e202009-11-05 08:53:23 +0000736 __ j(not_equal, exit);
737
738 __ SmiAddConstant(rcx, rcx, Smi::FromInt(second));
Steve Block44f0eee2011-05-26 01:26:41 +0100739 __ cmpq(rcx, r8);
Steve Block3ce2e202009-11-05 08:53:23 +0000740 __ j(not_equal, exit);
741
742 __ movl(rcx, Immediate(first));
743 __ Integer32ToSmi(rcx, rcx);
744
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000745 i::SmiOperationConstraints constraints =
746 i::SmiOperationConstraint::kPreserveSourceRegister |
747 i::SmiOperationConstraint::kBailoutOnOverflow;
Steve Block3ce2e202009-11-05 08:53:23 +0000748 __ incq(rax);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000749 __ SmiAddConstant(r9, rcx, Smi::FromInt(second), constraints, exit);
Steve Block44f0eee2011-05-26 01:26:41 +0100750 __ cmpq(r9, r8);
Steve Block3ce2e202009-11-05 08:53:23 +0000751 __ j(not_equal, exit);
752
753 __ incq(rax);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000754 __ SmiAddConstant(rcx, rcx, Smi::FromInt(second), constraints, exit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000755 __ cmpq(rcx, r8);
756 __ j(not_equal, exit);
757
758 __ movl(rcx, Immediate(first));
759 __ Integer32ToSmi(rcx, rcx);
760
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000761 constraints = i::SmiOperationConstraint::kPreserveSourceRegister |
762 i::SmiOperationConstraint::kBailoutOnNoOverflow;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000763 Label done;
764 __ incq(rax);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000765 __ SmiAddConstant(rcx, rcx, Smi::FromInt(second), constraints, &done);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000766 __ jmp(exit);
767 __ bind(&done);
Steve Block44f0eee2011-05-26 01:26:41 +0100768 __ cmpq(rcx, r8);
Steve Block3ce2e202009-11-05 08:53:23 +0000769 __ j(not_equal, exit);
770}
771
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000772
773static void SmiAddOverflowTest(MacroAssembler* masm,
774 Label* exit,
775 int id,
776 int x) {
777 // Adds a Smi to x so that the addition overflows.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000778 CHECK(x != 0); // Can't overflow by adding a Smi.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000779 int y_max = (x > 0) ? (Smi::kMaxValue + 0) : (Smi::kMinValue - x - 1);
780 int y_min = (x > 0) ? (Smi::kMaxValue - x + 1) : (Smi::kMinValue + 0);
781
782 __ movl(rax, Immediate(id));
783 __ Move(rcx, Smi::FromInt(x));
784 __ movq(r11, rcx); // Store original Smi value of x in r11.
785 __ Move(rdx, Smi::FromInt(y_min));
786 {
787 Label overflow_ok;
788 __ SmiAdd(r9, rcx, rdx, &overflow_ok);
789 __ jmp(exit);
790 __ bind(&overflow_ok);
791 __ incq(rax);
792 __ cmpq(rcx, r11);
793 __ j(not_equal, exit);
794 }
795
796 {
797 Label overflow_ok;
798 __ incq(rax);
799 __ SmiAdd(rcx, rcx, rdx, &overflow_ok);
800 __ jmp(exit);
801 __ bind(&overflow_ok);
802 __ incq(rax);
803 __ cmpq(rcx, r11);
804 __ j(not_equal, exit);
805 }
806
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000807 i::SmiOperationConstraints constraints =
808 i::SmiOperationConstraint::kPreserveSourceRegister |
809 i::SmiOperationConstraint::kBailoutOnOverflow;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000810 __ movq(rcx, r11);
811 {
812 Label overflow_ok;
813 __ incq(rax);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000814 __ SmiAddConstant(r9, rcx, Smi::FromInt(y_min), constraints, &overflow_ok);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000815 __ jmp(exit);
816 __ bind(&overflow_ok);
817 __ incq(rax);
818 __ cmpq(rcx, r11);
819 __ j(not_equal, exit);
820 }
821
822 {
823 Label overflow_ok;
824 __ incq(rax);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000825 __ SmiAddConstant(rcx, rcx, Smi::FromInt(y_min), constraints, &overflow_ok);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000826 __ jmp(exit);
827 __ bind(&overflow_ok);
828 __ incq(rax);
829 __ cmpq(rcx, r11);
830 __ j(not_equal, exit);
831 }
832
833 __ Move(rdx, Smi::FromInt(y_max));
834
835 {
836 Label overflow_ok;
837 __ incq(rax);
838 __ SmiAdd(r9, rcx, rdx, &overflow_ok);
839 __ jmp(exit);
840 __ bind(&overflow_ok);
841 __ incq(rax);
842 __ cmpq(rcx, r11);
843 __ j(not_equal, exit);
844 }
845
846 {
847 Label overflow_ok;
848 __ incq(rax);
849 __ SmiAdd(rcx, rcx, rdx, &overflow_ok);
850 __ jmp(exit);
851 __ bind(&overflow_ok);
852 __ incq(rax);
853 __ cmpq(rcx, r11);
854 __ j(not_equal, exit);
855 }
856
857 __ movq(rcx, r11);
858 {
859 Label overflow_ok;
860 __ incq(rax);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000861 __ SmiAddConstant(r9, rcx, Smi::FromInt(y_max), constraints, &overflow_ok);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000862 __ jmp(exit);
863 __ bind(&overflow_ok);
864 __ incq(rax);
865 __ cmpq(rcx, r11);
866 __ j(not_equal, exit);
867 }
868
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000869 constraints = i::SmiOperationConstraint::kBailoutOnOverflow;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000870 {
871 Label overflow_ok;
872 __ incq(rax);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000873 __ SmiAddConstant(rcx, rcx, Smi::FromInt(y_max), constraints, &overflow_ok);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000874 __ jmp(exit);
875 __ bind(&overflow_ok);
876 __ incq(rax);
877 __ cmpq(rcx, r11);
878 __ j(equal, exit);
879 }
880}
881
882
Steve Block3ce2e202009-11-05 08:53:23 +0000883TEST(SmiAdd) {
884 // Allocate an executable page of memory.
885 size_t actual_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000886 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
887 Assembler::kMinimalBufferSize * 3, &actual_size, true));
Steve Block3ce2e202009-11-05 08:53:23 +0000888 CHECK(buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000889 Isolate* isolate = CcTest::i_isolate();
890 HandleScope handles(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000891 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
892 v8::internal::CodeObjectRequired::kYes);
Steve Block3ce2e202009-11-05 08:53:23 +0000893
894 MacroAssembler* masm = &assembler;
Steve Block8defd9f2010-07-08 12:39:36 +0100895 EntryCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +0000896 Label exit;
897
898 // No-overflow tests.
899 SmiAddTest(masm, &exit, 0x10, 1, 2);
900 SmiAddTest(masm, &exit, 0x20, 1, -2);
901 SmiAddTest(masm, &exit, 0x30, -1, 2);
902 SmiAddTest(masm, &exit, 0x40, -1, -2);
903 SmiAddTest(masm, &exit, 0x50, 0x1000, 0x2000);
904 SmiAddTest(masm, &exit, 0x60, Smi::kMinValue, 5);
905 SmiAddTest(masm, &exit, 0x70, Smi::kMaxValue, -5);
906 SmiAddTest(masm, &exit, 0x80, Smi::kMaxValue, Smi::kMinValue);
907
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000908 SmiAddOverflowTest(masm, &exit, 0x90, -1);
909 SmiAddOverflowTest(masm, &exit, 0xA0, 1);
910 SmiAddOverflowTest(masm, &exit, 0xB0, 1024);
911 SmiAddOverflowTest(masm, &exit, 0xC0, Smi::kMaxValue);
912 SmiAddOverflowTest(masm, &exit, 0xD0, -2);
913 SmiAddOverflowTest(masm, &exit, 0xE0, -42000);
914 SmiAddOverflowTest(masm, &exit, 0xF0, Smi::kMinValue);
915
916 __ xorq(rax, rax); // Success.
Steve Block3ce2e202009-11-05 08:53:23 +0000917 __ bind(&exit);
Steve Block8defd9f2010-07-08 12:39:36 +0100918 ExitCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +0000919 __ ret(0);
920
921 CodeDesc desc;
922 masm->GetCode(&desc);
923 // Call the function from C++.
924 int result = FUNCTION_CAST<F0>(buffer)();
925 CHECK_EQ(0, result);
926}
927
928
929static void SmiSubTest(MacroAssembler* masm,
930 Label* exit,
931 int id,
932 int first,
933 int second) {
934 __ Move(rcx, Smi::FromInt(first));
935 __ Move(rdx, Smi::FromInt(second));
936 __ Move(r8, Smi::FromInt(first - second));
937
938 __ movl(rax, Immediate(id)); // Test 0.
939 __ SmiSub(r9, rcx, rdx, exit);
Steve Block44f0eee2011-05-26 01:26:41 +0100940 __ cmpq(r9, r8);
Steve Block3ce2e202009-11-05 08:53:23 +0000941 __ j(not_equal, exit);
942
943 __ incq(rax); // Test 1.
944 __ SmiSub(rcx, rcx, rdx, exit);
Steve Block44f0eee2011-05-26 01:26:41 +0100945 __ cmpq(rcx, r8);
Steve Block3ce2e202009-11-05 08:53:23 +0000946 __ j(not_equal, exit);
947
948 __ Move(rcx, Smi::FromInt(first));
949
950 __ incq(rax); // Test 2.
951 __ SmiSubConstant(r9, rcx, Smi::FromInt(second));
Steve Block44f0eee2011-05-26 01:26:41 +0100952 __ cmpq(r9, r8);
Steve Block3ce2e202009-11-05 08:53:23 +0000953 __ j(not_equal, exit);
954
955 __ incq(rax); // Test 3.
956 __ SmiSubConstant(rcx, rcx, Smi::FromInt(second));
Steve Block44f0eee2011-05-26 01:26:41 +0100957 __ cmpq(rcx, r8);
Steve Block3ce2e202009-11-05 08:53:23 +0000958 __ j(not_equal, exit);
959
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000960 i::SmiOperationConstraints constraints =
961 i::SmiOperationConstraint::kPreserveSourceRegister |
962 i::SmiOperationConstraint::kBailoutOnOverflow;
Steve Block3ce2e202009-11-05 08:53:23 +0000963 __ Move(rcx, Smi::FromInt(first));
Steve Block3ce2e202009-11-05 08:53:23 +0000964 __ incq(rax); // Test 4.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000965 __ SmiSubConstant(rcx, rcx, Smi::FromInt(second), constraints, exit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000966 __ cmpq(rcx, r8);
967 __ j(not_equal, exit);
968
969 __ Move(rcx, Smi::FromInt(first));
970 __ incq(rax); // Test 5.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000971 __ SmiSubConstant(r9, rcx, Smi::FromInt(second), constraints, exit);
Steve Block44f0eee2011-05-26 01:26:41 +0100972 __ cmpq(r9, r8);
Steve Block3ce2e202009-11-05 08:53:23 +0000973 __ j(not_equal, exit);
974
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000975 constraints = i::SmiOperationConstraint::kPreserveSourceRegister |
976 i::SmiOperationConstraint::kBailoutOnNoOverflow;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000977 __ Move(rcx, Smi::FromInt(first));
978 Label done;
979 __ incq(rax); // Test 6.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000980 __ SmiSubConstant(rcx, rcx, Smi::FromInt(second), constraints, &done);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000981 __ jmp(exit);
982 __ bind(&done);
Steve Block44f0eee2011-05-26 01:26:41 +0100983 __ cmpq(rcx, r8);
Steve Block3ce2e202009-11-05 08:53:23 +0000984 __ j(not_equal, exit);
985}
986
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000987
Steve Block3ce2e202009-11-05 08:53:23 +0000988static void SmiSubOverflowTest(MacroAssembler* masm,
989 Label* exit,
990 int id,
991 int x) {
992 // Subtracts a Smi from x so that the subtraction overflows.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000993 CHECK(x != -1); // Can't overflow by subtracting a Smi.
Steve Block3ce2e202009-11-05 08:53:23 +0000994 int y_max = (x < 0) ? (Smi::kMaxValue + 0) : (Smi::kMinValue + 0);
995 int y_min = (x < 0) ? (Smi::kMaxValue + x + 2) : (Smi::kMinValue + x);
996
997 __ movl(rax, Immediate(id));
998 __ Move(rcx, Smi::FromInt(x));
999 __ movq(r11, rcx); // Store original Smi value of x in r11.
1000 __ Move(rdx, Smi::FromInt(y_min));
1001 {
1002 Label overflow_ok;
1003 __ SmiSub(r9, rcx, rdx, &overflow_ok);
1004 __ jmp(exit);
1005 __ bind(&overflow_ok);
1006 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001007 __ cmpq(rcx, r11);
Steve Block3ce2e202009-11-05 08:53:23 +00001008 __ j(not_equal, exit);
1009 }
1010
1011 {
1012 Label overflow_ok;
1013 __ incq(rax);
1014 __ SmiSub(rcx, rcx, rdx, &overflow_ok);
1015 __ jmp(exit);
1016 __ bind(&overflow_ok);
1017 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001018 __ cmpq(rcx, r11);
Steve Block3ce2e202009-11-05 08:53:23 +00001019 __ j(not_equal, exit);
1020 }
1021
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001022 i::SmiOperationConstraints constraints =
1023 i::SmiOperationConstraint::kPreserveSourceRegister |
1024 i::SmiOperationConstraint::kBailoutOnOverflow;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001025
Steve Block3ce2e202009-11-05 08:53:23 +00001026 __ movq(rcx, r11);
1027 {
1028 Label overflow_ok;
1029 __ incq(rax);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001030 __ SmiSubConstant(r9, rcx, Smi::FromInt(y_min), constraints, &overflow_ok);
Steve Block3ce2e202009-11-05 08:53:23 +00001031 __ jmp(exit);
1032 __ bind(&overflow_ok);
1033 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001034 __ cmpq(rcx, r11);
Steve Block3ce2e202009-11-05 08:53:23 +00001035 __ j(not_equal, exit);
1036 }
1037
1038 {
1039 Label overflow_ok;
1040 __ incq(rax);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001041 __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_min), constraints, &overflow_ok);
Steve Block3ce2e202009-11-05 08:53:23 +00001042 __ jmp(exit);
1043 __ bind(&overflow_ok);
1044 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001045 __ cmpq(rcx, r11);
Steve Block3ce2e202009-11-05 08:53:23 +00001046 __ j(not_equal, exit);
1047 }
1048
1049 __ Move(rdx, Smi::FromInt(y_max));
1050
1051 {
1052 Label overflow_ok;
1053 __ incq(rax);
1054 __ SmiSub(r9, rcx, rdx, &overflow_ok);
1055 __ jmp(exit);
1056 __ bind(&overflow_ok);
1057 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001058 __ cmpq(rcx, r11);
Steve Block3ce2e202009-11-05 08:53:23 +00001059 __ j(not_equal, exit);
1060 }
1061
1062 {
1063 Label overflow_ok;
1064 __ incq(rax);
1065 __ SmiSub(rcx, rcx, rdx, &overflow_ok);
1066 __ jmp(exit);
1067 __ bind(&overflow_ok);
1068 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001069 __ cmpq(rcx, r11);
Steve Block3ce2e202009-11-05 08:53:23 +00001070 __ j(not_equal, exit);
1071 }
1072
1073 __ movq(rcx, r11);
1074 {
1075 Label overflow_ok;
1076 __ incq(rax);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001077 __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_max), constraints, &overflow_ok);
Steve Block3ce2e202009-11-05 08:53:23 +00001078 __ jmp(exit);
1079 __ bind(&overflow_ok);
1080 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001081 __ cmpq(rcx, r11);
Steve Block3ce2e202009-11-05 08:53:23 +00001082 __ j(not_equal, exit);
1083 }
1084
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001085 constraints = i::SmiOperationConstraint::kBailoutOnOverflow;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001086 __ movq(rcx, r11);
Steve Block3ce2e202009-11-05 08:53:23 +00001087 {
1088 Label overflow_ok;
1089 __ incq(rax);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001090 __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_max), constraints, &overflow_ok);
Steve Block3ce2e202009-11-05 08:53:23 +00001091 __ jmp(exit);
1092 __ bind(&overflow_ok);
1093 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001094 __ cmpq(rcx, r11);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001095 __ j(equal, exit);
Steve Block3ce2e202009-11-05 08:53:23 +00001096 }
1097}
1098
1099
1100TEST(SmiSub) {
1101 // Allocate an executable page of memory.
1102 size_t actual_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001103 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1104 Assembler::kMinimalBufferSize * 4, &actual_size, true));
Steve Block3ce2e202009-11-05 08:53:23 +00001105 CHECK(buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001106 Isolate* isolate = CcTest::i_isolate();
1107 HandleScope handles(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001108 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
1109 v8::internal::CodeObjectRequired::kYes);
Steve Block3ce2e202009-11-05 08:53:23 +00001110
1111 MacroAssembler* masm = &assembler;
Steve Block8defd9f2010-07-08 12:39:36 +01001112 EntryCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00001113 Label exit;
1114
1115 SmiSubTest(masm, &exit, 0x10, 1, 2);
1116 SmiSubTest(masm, &exit, 0x20, 1, -2);
1117 SmiSubTest(masm, &exit, 0x30, -1, 2);
1118 SmiSubTest(masm, &exit, 0x40, -1, -2);
1119 SmiSubTest(masm, &exit, 0x50, 0x1000, 0x2000);
1120 SmiSubTest(masm, &exit, 0x60, Smi::kMinValue, -5);
1121 SmiSubTest(masm, &exit, 0x70, Smi::kMaxValue, 5);
1122 SmiSubTest(masm, &exit, 0x80, -Smi::kMaxValue, Smi::kMinValue);
1123 SmiSubTest(masm, &exit, 0x90, 0, Smi::kMaxValue);
1124
1125 SmiSubOverflowTest(masm, &exit, 0xA0, 1);
1126 SmiSubOverflowTest(masm, &exit, 0xB0, 1024);
1127 SmiSubOverflowTest(masm, &exit, 0xC0, Smi::kMaxValue);
1128 SmiSubOverflowTest(masm, &exit, 0xD0, -2);
1129 SmiSubOverflowTest(masm, &exit, 0xE0, -42000);
1130 SmiSubOverflowTest(masm, &exit, 0xF0, Smi::kMinValue);
1131 SmiSubOverflowTest(masm, &exit, 0x100, 0);
1132
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001133 __ xorq(rax, rax); // Success.
Steve Block3ce2e202009-11-05 08:53:23 +00001134 __ bind(&exit);
Steve Block8defd9f2010-07-08 12:39:36 +01001135 ExitCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00001136 __ ret(0);
1137
1138 CodeDesc desc;
1139 masm->GetCode(&desc);
1140 // Call the function from C++.
1141 int result = FUNCTION_CAST<F0>(buffer)();
1142 CHECK_EQ(0, result);
1143}
1144
1145
1146
1147void TestSmiMul(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1148 int64_t result = static_cast<int64_t>(x) * static_cast<int64_t>(y);
1149 bool negative_zero = (result == 0) && (x < 0 || y < 0);
1150 __ Move(rcx, Smi::FromInt(x));
1151 __ movq(r11, rcx);
1152 __ Move(rdx, Smi::FromInt(y));
1153 if (Smi::IsValid(result) && !negative_zero) {
1154 __ movl(rax, Immediate(id));
1155 __ Move(r8, Smi::FromIntptr(result));
1156 __ SmiMul(r9, rcx, rdx, exit);
1157 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001158 __ cmpq(r11, rcx);
Steve Block3ce2e202009-11-05 08:53:23 +00001159 __ j(not_equal, exit);
1160 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001161 __ cmpq(r9, r8);
Steve Block3ce2e202009-11-05 08:53:23 +00001162 __ j(not_equal, exit);
1163
1164 __ incq(rax);
1165 __ SmiMul(rcx, rcx, rdx, exit);
Steve Block44f0eee2011-05-26 01:26:41 +01001166 __ cmpq(rcx, r8);
Steve Block3ce2e202009-11-05 08:53:23 +00001167 __ j(not_equal, exit);
1168 } else {
1169 __ movl(rax, Immediate(id + 8));
1170 Label overflow_ok, overflow_ok2;
1171 __ SmiMul(r9, rcx, rdx, &overflow_ok);
1172 __ jmp(exit);
1173 __ bind(&overflow_ok);
1174 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001175 __ cmpq(r11, rcx);
Steve Block3ce2e202009-11-05 08:53:23 +00001176 __ j(not_equal, exit);
1177 __ incq(rax);
1178 __ SmiMul(rcx, rcx, rdx, &overflow_ok2);
1179 __ jmp(exit);
1180 __ bind(&overflow_ok2);
1181 // 31-bit version doesn't preserve rcx on failure.
1182 // __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001183 // __ cmpq(r11, rcx);
Steve Block3ce2e202009-11-05 08:53:23 +00001184 // __ j(not_equal, exit);
1185 }
1186}
1187
1188
1189TEST(SmiMul) {
1190 // Allocate an executable page of memory.
1191 size_t actual_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001192 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1193 Assembler::kMinimalBufferSize, &actual_size, true));
Steve Block3ce2e202009-11-05 08:53:23 +00001194 CHECK(buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001195 Isolate* isolate = CcTest::i_isolate();
1196 HandleScope handles(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001197 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
1198 v8::internal::CodeObjectRequired::kYes);
Steve Block3ce2e202009-11-05 08:53:23 +00001199
1200 MacroAssembler* masm = &assembler;
Steve Block8defd9f2010-07-08 12:39:36 +01001201 EntryCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00001202 Label exit;
1203
1204 TestSmiMul(masm, &exit, 0x10, 0, 0);
1205 TestSmiMul(masm, &exit, 0x20, -1, 0);
1206 TestSmiMul(masm, &exit, 0x30, 0, -1);
1207 TestSmiMul(masm, &exit, 0x40, -1, -1);
1208 TestSmiMul(masm, &exit, 0x50, 0x10000, 0x10000);
1209 TestSmiMul(masm, &exit, 0x60, 0x10000, 0xffff);
1210 TestSmiMul(masm, &exit, 0x70, 0x10000, 0xffff);
1211 TestSmiMul(masm, &exit, 0x80, Smi::kMaxValue, -1);
1212 TestSmiMul(masm, &exit, 0x90, Smi::kMaxValue, -2);
1213 TestSmiMul(masm, &exit, 0xa0, Smi::kMaxValue, 2);
1214 TestSmiMul(masm, &exit, 0xb0, (Smi::kMaxValue / 2), 2);
1215 TestSmiMul(masm, &exit, 0xc0, (Smi::kMaxValue / 2) + 1, 2);
1216 TestSmiMul(masm, &exit, 0xd0, (Smi::kMinValue / 2), 2);
1217 TestSmiMul(masm, &exit, 0xe0, (Smi::kMinValue / 2) - 1, 2);
1218
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001219 __ xorq(rax, rax); // Success.
Steve Block3ce2e202009-11-05 08:53:23 +00001220 __ bind(&exit);
Steve Block8defd9f2010-07-08 12:39:36 +01001221 ExitCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00001222 __ ret(0);
1223
1224 CodeDesc desc;
1225 masm->GetCode(&desc);
1226 // Call the function from C++.
1227 int result = FUNCTION_CAST<F0>(buffer)();
1228 CHECK_EQ(0, result);
1229}
1230
1231
1232void TestSmiDiv(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1233 bool division_by_zero = (y == 0);
1234 bool negative_zero = (x == 0 && y < 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001235#if V8_TARGET_ARCH_X64
Steve Block3ce2e202009-11-05 08:53:23 +00001236 bool overflow = (x == Smi::kMinValue && y < 0); // Safe approx. used.
1237#else
1238 bool overflow = (x == Smi::kMinValue && y == -1);
1239#endif
1240 bool fraction = !division_by_zero && !overflow && (x % y != 0);
1241 __ Move(r11, Smi::FromInt(x));
Steve Block8defd9f2010-07-08 12:39:36 +01001242 __ Move(r14, Smi::FromInt(y));
Steve Block3ce2e202009-11-05 08:53:23 +00001243 if (!fraction && !overflow && !negative_zero && !division_by_zero) {
1244 // Division succeeds
1245 __ movq(rcx, r11);
Steve Block44f0eee2011-05-26 01:26:41 +01001246 __ movq(r15, Immediate(id));
Steve Block3ce2e202009-11-05 08:53:23 +00001247 int result = x / y;
1248 __ Move(r8, Smi::FromInt(result));
Steve Block8defd9f2010-07-08 12:39:36 +01001249 __ SmiDiv(r9, rcx, r14, exit);
1250 // Might have destroyed rcx and r14.
Steve Block44f0eee2011-05-26 01:26:41 +01001251 __ incq(r15);
1252 __ cmpq(r9, r8);
Steve Block3ce2e202009-11-05 08:53:23 +00001253 __ j(not_equal, exit);
1254
Steve Block44f0eee2011-05-26 01:26:41 +01001255 __ incq(r15);
Steve Block3ce2e202009-11-05 08:53:23 +00001256 __ movq(rcx, r11);
Steve Block8defd9f2010-07-08 12:39:36 +01001257 __ Move(r14, Smi::FromInt(y));
Steve Block44f0eee2011-05-26 01:26:41 +01001258 __ cmpq(rcx, r11);
Steve Block3ce2e202009-11-05 08:53:23 +00001259 __ j(not_equal, exit);
1260
Steve Block44f0eee2011-05-26 01:26:41 +01001261 __ incq(r15);
Steve Block8defd9f2010-07-08 12:39:36 +01001262 __ SmiDiv(rcx, rcx, r14, exit);
Steve Block3ce2e202009-11-05 08:53:23 +00001263
Steve Block44f0eee2011-05-26 01:26:41 +01001264 __ incq(r15);
1265 __ cmpq(rcx, r8);
Steve Block3ce2e202009-11-05 08:53:23 +00001266 __ j(not_equal, exit);
1267 } else {
1268 // Division fails.
Steve Block44f0eee2011-05-26 01:26:41 +01001269 __ movq(r15, Immediate(id + 8));
Steve Block3ce2e202009-11-05 08:53:23 +00001270
1271 Label fail_ok, fail_ok2;
1272 __ movq(rcx, r11);
Steve Block8defd9f2010-07-08 12:39:36 +01001273 __ SmiDiv(r9, rcx, r14, &fail_ok);
Steve Block3ce2e202009-11-05 08:53:23 +00001274 __ jmp(exit);
1275 __ bind(&fail_ok);
1276
Steve Block44f0eee2011-05-26 01:26:41 +01001277 __ incq(r15);
1278 __ cmpq(rcx, r11);
Steve Block3ce2e202009-11-05 08:53:23 +00001279 __ j(not_equal, exit);
1280
Steve Block44f0eee2011-05-26 01:26:41 +01001281 __ incq(r15);
Steve Block8defd9f2010-07-08 12:39:36 +01001282 __ SmiDiv(rcx, rcx, r14, &fail_ok2);
Steve Block3ce2e202009-11-05 08:53:23 +00001283 __ jmp(exit);
1284 __ bind(&fail_ok2);
1285
Steve Block44f0eee2011-05-26 01:26:41 +01001286 __ incq(r15);
1287 __ cmpq(rcx, r11);
Steve Block3ce2e202009-11-05 08:53:23 +00001288 __ j(not_equal, exit);
1289 }
1290}
1291
1292
1293TEST(SmiDiv) {
1294 // Allocate an executable page of memory.
1295 size_t actual_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001296 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1297 Assembler::kMinimalBufferSize * 2, &actual_size, true));
Steve Block3ce2e202009-11-05 08:53:23 +00001298 CHECK(buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001299 Isolate* isolate = CcTest::i_isolate();
1300 HandleScope handles(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001301 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
1302 v8::internal::CodeObjectRequired::kYes);
Steve Block3ce2e202009-11-05 08:53:23 +00001303
1304 MacroAssembler* masm = &assembler;
Steve Block8defd9f2010-07-08 12:39:36 +01001305 EntryCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00001306 Label exit;
1307
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001308 __ pushq(r14);
1309 __ pushq(r15);
Steve Block3ce2e202009-11-05 08:53:23 +00001310 TestSmiDiv(masm, &exit, 0x10, 1, 1);
1311 TestSmiDiv(masm, &exit, 0x20, 1, 0);
1312 TestSmiDiv(masm, &exit, 0x30, -1, 0);
1313 TestSmiDiv(masm, &exit, 0x40, 0, 1);
1314 TestSmiDiv(masm, &exit, 0x50, 0, -1);
1315 TestSmiDiv(masm, &exit, 0x60, 4, 2);
1316 TestSmiDiv(masm, &exit, 0x70, -4, 2);
1317 TestSmiDiv(masm, &exit, 0x80, 4, -2);
1318 TestSmiDiv(masm, &exit, 0x90, -4, -2);
1319 TestSmiDiv(masm, &exit, 0xa0, 3, 2);
1320 TestSmiDiv(masm, &exit, 0xb0, 3, 4);
1321 TestSmiDiv(masm, &exit, 0xc0, 1, Smi::kMaxValue);
1322 TestSmiDiv(masm, &exit, 0xd0, -1, Smi::kMaxValue);
1323 TestSmiDiv(masm, &exit, 0xe0, Smi::kMaxValue, 1);
1324 TestSmiDiv(masm, &exit, 0xf0, Smi::kMaxValue, Smi::kMaxValue);
1325 TestSmiDiv(masm, &exit, 0x100, Smi::kMaxValue, -Smi::kMaxValue);
1326 TestSmiDiv(masm, &exit, 0x110, Smi::kMaxValue, -1);
1327 TestSmiDiv(masm, &exit, 0x120, Smi::kMinValue, 1);
1328 TestSmiDiv(masm, &exit, 0x130, Smi::kMinValue, Smi::kMinValue);
1329 TestSmiDiv(masm, &exit, 0x140, Smi::kMinValue, -1);
1330
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001331 __ xorq(r15, r15); // Success.
Steve Block3ce2e202009-11-05 08:53:23 +00001332 __ bind(&exit);
Steve Block44f0eee2011-05-26 01:26:41 +01001333 __ movq(rax, r15);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001334 __ popq(r15);
1335 __ popq(r14);
Steve Block8defd9f2010-07-08 12:39:36 +01001336 ExitCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00001337 __ ret(0);
1338
1339 CodeDesc desc;
1340 masm->GetCode(&desc);
1341 // Call the function from C++.
1342 int result = FUNCTION_CAST<F0>(buffer)();
1343 CHECK_EQ(0, result);
1344}
1345
1346
1347void TestSmiMod(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1348 bool division_by_zero = (y == 0);
1349 bool division_overflow = (x == Smi::kMinValue) && (y == -1);
1350 bool fraction = !division_by_zero && !division_overflow && ((x % y) != 0);
1351 bool negative_zero = (!fraction && x < 0);
1352 __ Move(rcx, Smi::FromInt(x));
1353 __ movq(r11, rcx);
Steve Block8defd9f2010-07-08 12:39:36 +01001354 __ Move(r14, Smi::FromInt(y));
Steve Block3ce2e202009-11-05 08:53:23 +00001355 if (!division_overflow && !negative_zero && !division_by_zero) {
1356 // Modulo succeeds
Steve Block44f0eee2011-05-26 01:26:41 +01001357 __ movq(r15, Immediate(id));
Steve Block3ce2e202009-11-05 08:53:23 +00001358 int result = x % y;
1359 __ Move(r8, Smi::FromInt(result));
Steve Block8defd9f2010-07-08 12:39:36 +01001360 __ SmiMod(r9, rcx, r14, exit);
Steve Block3ce2e202009-11-05 08:53:23 +00001361
Steve Block44f0eee2011-05-26 01:26:41 +01001362 __ incq(r15);
1363 __ cmpq(r9, r8);
Steve Block3ce2e202009-11-05 08:53:23 +00001364 __ j(not_equal, exit);
1365
Steve Block44f0eee2011-05-26 01:26:41 +01001366 __ incq(r15);
1367 __ cmpq(rcx, r11);
Steve Block3ce2e202009-11-05 08:53:23 +00001368 __ j(not_equal, exit);
1369
Steve Block44f0eee2011-05-26 01:26:41 +01001370 __ incq(r15);
Steve Block8defd9f2010-07-08 12:39:36 +01001371 __ SmiMod(rcx, rcx, r14, exit);
Steve Block3ce2e202009-11-05 08:53:23 +00001372
Steve Block44f0eee2011-05-26 01:26:41 +01001373 __ incq(r15);
1374 __ cmpq(rcx, r8);
Steve Block3ce2e202009-11-05 08:53:23 +00001375 __ j(not_equal, exit);
1376 } else {
1377 // Modulo fails.
Steve Block44f0eee2011-05-26 01:26:41 +01001378 __ movq(r15, Immediate(id + 8));
Steve Block3ce2e202009-11-05 08:53:23 +00001379
1380 Label fail_ok, fail_ok2;
Steve Block8defd9f2010-07-08 12:39:36 +01001381 __ SmiMod(r9, rcx, r14, &fail_ok);
Steve Block3ce2e202009-11-05 08:53:23 +00001382 __ jmp(exit);
1383 __ bind(&fail_ok);
1384
Steve Block44f0eee2011-05-26 01:26:41 +01001385 __ incq(r15);
1386 __ cmpq(rcx, r11);
Steve Block3ce2e202009-11-05 08:53:23 +00001387 __ j(not_equal, exit);
1388
Steve Block44f0eee2011-05-26 01:26:41 +01001389 __ incq(r15);
Steve Block8defd9f2010-07-08 12:39:36 +01001390 __ SmiMod(rcx, rcx, r14, &fail_ok2);
Steve Block3ce2e202009-11-05 08:53:23 +00001391 __ jmp(exit);
1392 __ bind(&fail_ok2);
1393
Steve Block44f0eee2011-05-26 01:26:41 +01001394 __ incq(r15);
1395 __ cmpq(rcx, r11);
Steve Block3ce2e202009-11-05 08:53:23 +00001396 __ j(not_equal, exit);
1397 }
1398}
1399
1400
1401TEST(SmiMod) {
1402 // Allocate an executable page of memory.
1403 size_t actual_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001404 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1405 Assembler::kMinimalBufferSize * 2, &actual_size, true));
Steve Block3ce2e202009-11-05 08:53:23 +00001406 CHECK(buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001407 Isolate* isolate = CcTest::i_isolate();
1408 HandleScope handles(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001409 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
1410 v8::internal::CodeObjectRequired::kYes);
Steve Block3ce2e202009-11-05 08:53:23 +00001411
1412 MacroAssembler* masm = &assembler;
Steve Block8defd9f2010-07-08 12:39:36 +01001413 EntryCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00001414 Label exit;
1415
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001416 __ pushq(r14);
1417 __ pushq(r15);
Steve Block3ce2e202009-11-05 08:53:23 +00001418 TestSmiMod(masm, &exit, 0x10, 1, 1);
1419 TestSmiMod(masm, &exit, 0x20, 1, 0);
1420 TestSmiMod(masm, &exit, 0x30, -1, 0);
1421 TestSmiMod(masm, &exit, 0x40, 0, 1);
1422 TestSmiMod(masm, &exit, 0x50, 0, -1);
1423 TestSmiMod(masm, &exit, 0x60, 4, 2);
1424 TestSmiMod(masm, &exit, 0x70, -4, 2);
1425 TestSmiMod(masm, &exit, 0x80, 4, -2);
1426 TestSmiMod(masm, &exit, 0x90, -4, -2);
1427 TestSmiMod(masm, &exit, 0xa0, 3, 2);
1428 TestSmiMod(masm, &exit, 0xb0, 3, 4);
1429 TestSmiMod(masm, &exit, 0xc0, 1, Smi::kMaxValue);
1430 TestSmiMod(masm, &exit, 0xd0, -1, Smi::kMaxValue);
1431 TestSmiMod(masm, &exit, 0xe0, Smi::kMaxValue, 1);
1432 TestSmiMod(masm, &exit, 0xf0, Smi::kMaxValue, Smi::kMaxValue);
1433 TestSmiMod(masm, &exit, 0x100, Smi::kMaxValue, -Smi::kMaxValue);
1434 TestSmiMod(masm, &exit, 0x110, Smi::kMaxValue, -1);
1435 TestSmiMod(masm, &exit, 0x120, Smi::kMinValue, 1);
1436 TestSmiMod(masm, &exit, 0x130, Smi::kMinValue, Smi::kMinValue);
1437 TestSmiMod(masm, &exit, 0x140, Smi::kMinValue, -1);
1438
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001439 __ xorq(r15, r15); // Success.
Steve Block3ce2e202009-11-05 08:53:23 +00001440 __ bind(&exit);
Steve Block44f0eee2011-05-26 01:26:41 +01001441 __ movq(rax, r15);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001442 __ popq(r15);
1443 __ popq(r14);
Steve Block8defd9f2010-07-08 12:39:36 +01001444 ExitCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00001445 __ ret(0);
1446
1447 CodeDesc desc;
1448 masm->GetCode(&desc);
1449 // Call the function from C++.
1450 int result = FUNCTION_CAST<F0>(buffer)();
1451 CHECK_EQ(0, result);
1452}
1453
1454
1455void TestSmiIndex(MacroAssembler* masm, Label* exit, int id, int x) {
1456 __ movl(rax, Immediate(id));
1457
1458 for (int i = 0; i < 8; i++) {
1459 __ Move(rcx, Smi::FromInt(x));
1460 SmiIndex index = masm->SmiToIndex(rdx, rcx, i);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001461 CHECK(index.reg.is(rcx) || index.reg.is(rdx));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001462 __ shlq(index.reg, Immediate(index.scale));
Steve Block3ce2e202009-11-05 08:53:23 +00001463 __ Set(r8, static_cast<intptr_t>(x) << i);
Steve Block44f0eee2011-05-26 01:26:41 +01001464 __ cmpq(index.reg, r8);
Steve Block3ce2e202009-11-05 08:53:23 +00001465 __ j(not_equal, exit);
1466 __ incq(rax);
1467 __ Move(rcx, Smi::FromInt(x));
1468 index = masm->SmiToIndex(rcx, rcx, i);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001469 CHECK(index.reg.is(rcx));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001470 __ shlq(rcx, Immediate(index.scale));
Steve Block3ce2e202009-11-05 08:53:23 +00001471 __ Set(r8, static_cast<intptr_t>(x) << i);
Steve Block44f0eee2011-05-26 01:26:41 +01001472 __ cmpq(rcx, r8);
Steve Block3ce2e202009-11-05 08:53:23 +00001473 __ j(not_equal, exit);
1474 __ incq(rax);
1475
1476 __ Move(rcx, Smi::FromInt(x));
1477 index = masm->SmiToNegativeIndex(rdx, rcx, i);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001478 CHECK(index.reg.is(rcx) || index.reg.is(rdx));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001479 __ shlq(index.reg, Immediate(index.scale));
Steve Block3ce2e202009-11-05 08:53:23 +00001480 __ Set(r8, static_cast<intptr_t>(-x) << i);
Steve Block44f0eee2011-05-26 01:26:41 +01001481 __ cmpq(index.reg, r8);
Steve Block3ce2e202009-11-05 08:53:23 +00001482 __ j(not_equal, exit);
1483 __ incq(rax);
1484 __ Move(rcx, Smi::FromInt(x));
1485 index = masm->SmiToNegativeIndex(rcx, rcx, i);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001486 CHECK(index.reg.is(rcx));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001487 __ shlq(rcx, Immediate(index.scale));
Steve Block3ce2e202009-11-05 08:53:23 +00001488 __ Set(r8, static_cast<intptr_t>(-x) << i);
Steve Block44f0eee2011-05-26 01:26:41 +01001489 __ cmpq(rcx, r8);
Steve Block3ce2e202009-11-05 08:53:23 +00001490 __ j(not_equal, exit);
1491 __ incq(rax);
1492 }
1493}
1494
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001495
Steve Block3ce2e202009-11-05 08:53:23 +00001496TEST(SmiIndex) {
1497 // Allocate an executable page of memory.
1498 size_t actual_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001499 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1500 Assembler::kMinimalBufferSize * 5, &actual_size, true));
Steve Block3ce2e202009-11-05 08:53:23 +00001501 CHECK(buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001502 Isolate* isolate = CcTest::i_isolate();
1503 HandleScope handles(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001504 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
1505 v8::internal::CodeObjectRequired::kYes);
Steve Block3ce2e202009-11-05 08:53:23 +00001506
1507 MacroAssembler* masm = &assembler;
Steve Block8defd9f2010-07-08 12:39:36 +01001508 EntryCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00001509 Label exit;
1510
1511 TestSmiIndex(masm, &exit, 0x10, 0);
1512 TestSmiIndex(masm, &exit, 0x20, 1);
1513 TestSmiIndex(masm, &exit, 0x30, 100);
1514 TestSmiIndex(masm, &exit, 0x40, 1000);
1515 TestSmiIndex(masm, &exit, 0x50, Smi::kMaxValue);
1516
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001517 __ xorq(rax, rax); // Success.
Steve Block3ce2e202009-11-05 08:53:23 +00001518 __ bind(&exit);
Steve Block8defd9f2010-07-08 12:39:36 +01001519 ExitCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00001520 __ ret(0);
1521
1522 CodeDesc desc;
1523 masm->GetCode(&desc);
1524 // Call the function from C++.
1525 int result = FUNCTION_CAST<F0>(buffer)();
1526 CHECK_EQ(0, result);
1527}
1528
1529
1530void TestSelectNonSmi(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1531 __ movl(rax, Immediate(id));
1532 __ Move(rcx, Smi::FromInt(x));
1533 __ Move(rdx, Smi::FromInt(y));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001534 __ xorq(rdx, Immediate(kSmiTagMask));
Steve Block3ce2e202009-11-05 08:53:23 +00001535 __ SelectNonSmi(r9, rcx, rdx, exit);
1536
1537 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001538 __ cmpq(r9, rdx);
Steve Block3ce2e202009-11-05 08:53:23 +00001539 __ j(not_equal, exit);
1540
1541 __ incq(rax);
1542 __ Move(rcx, Smi::FromInt(x));
1543 __ Move(rdx, Smi::FromInt(y));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001544 __ xorq(rcx, Immediate(kSmiTagMask));
Steve Block3ce2e202009-11-05 08:53:23 +00001545 __ SelectNonSmi(r9, rcx, rdx, exit);
1546
1547 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001548 __ cmpq(r9, rcx);
Steve Block3ce2e202009-11-05 08:53:23 +00001549 __ j(not_equal, exit);
1550
1551 __ incq(rax);
1552 Label fail_ok;
1553 __ Move(rcx, Smi::FromInt(x));
1554 __ Move(rdx, Smi::FromInt(y));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001555 __ xorq(rcx, Immediate(kSmiTagMask));
1556 __ xorq(rdx, Immediate(kSmiTagMask));
Steve Block3ce2e202009-11-05 08:53:23 +00001557 __ SelectNonSmi(r9, rcx, rdx, &fail_ok);
1558 __ jmp(exit);
1559 __ bind(&fail_ok);
1560}
1561
1562
1563TEST(SmiSelectNonSmi) {
1564 // Allocate an executable page of memory.
1565 size_t actual_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001566 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1567 Assembler::kMinimalBufferSize * 2, &actual_size, true));
Steve Block3ce2e202009-11-05 08:53:23 +00001568 CHECK(buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001569 Isolate* isolate = CcTest::i_isolate();
1570 HandleScope handles(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001571 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
1572 v8::internal::CodeObjectRequired::kYes);
Steve Block3ce2e202009-11-05 08:53:23 +00001573
1574 MacroAssembler* masm = &assembler;
Steve Block8defd9f2010-07-08 12:39:36 +01001575 EntryCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00001576 Label exit;
1577
1578 TestSelectNonSmi(masm, &exit, 0x10, 0, 0);
1579 TestSelectNonSmi(masm, &exit, 0x20, 0, 1);
1580 TestSelectNonSmi(masm, &exit, 0x30, 1, 0);
1581 TestSelectNonSmi(masm, &exit, 0x40, 0, -1);
1582 TestSelectNonSmi(masm, &exit, 0x50, -1, 0);
1583 TestSelectNonSmi(masm, &exit, 0x60, -1, -1);
1584 TestSelectNonSmi(masm, &exit, 0x70, 1, 1);
1585 TestSelectNonSmi(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
1586 TestSelectNonSmi(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
1587
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001588 __ xorq(rax, rax); // Success.
Steve Block3ce2e202009-11-05 08:53:23 +00001589 __ bind(&exit);
Steve Block8defd9f2010-07-08 12:39:36 +01001590 ExitCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00001591 __ ret(0);
1592
1593 CodeDesc desc;
1594 masm->GetCode(&desc);
1595 // Call the function from C++.
1596 int result = FUNCTION_CAST<F0>(buffer)();
1597 CHECK_EQ(0, result);
1598}
1599
1600
1601void TestSmiAnd(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1602 int result = x & y;
1603
1604 __ movl(rax, Immediate(id));
1605
1606 __ Move(rcx, Smi::FromInt(x));
1607 __ movq(r11, rcx);
1608 __ Move(rdx, Smi::FromInt(y));
1609 __ Move(r8, Smi::FromInt(result));
1610 __ SmiAnd(r9, rcx, rdx);
Steve Block44f0eee2011-05-26 01:26:41 +01001611 __ cmpq(r8, r9);
Steve Block3ce2e202009-11-05 08:53:23 +00001612 __ j(not_equal, exit);
1613
1614 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001615 __ cmpq(r11, rcx);
Steve Block3ce2e202009-11-05 08:53:23 +00001616 __ j(not_equal, exit);
1617
1618 __ incq(rax);
1619 __ SmiAnd(rcx, rcx, rdx);
Steve Block44f0eee2011-05-26 01:26:41 +01001620 __ cmpq(r8, rcx);
Steve Block3ce2e202009-11-05 08:53:23 +00001621 __ j(not_equal, exit);
1622
1623 __ movq(rcx, r11);
1624 __ incq(rax);
1625 __ SmiAndConstant(r9, rcx, Smi::FromInt(y));
Steve Block44f0eee2011-05-26 01:26:41 +01001626 __ cmpq(r8, r9);
Steve Block3ce2e202009-11-05 08:53:23 +00001627 __ j(not_equal, exit);
1628
1629 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001630 __ cmpq(r11, rcx);
Steve Block3ce2e202009-11-05 08:53:23 +00001631 __ j(not_equal, exit);
1632
1633 __ incq(rax);
1634 __ SmiAndConstant(rcx, rcx, Smi::FromInt(y));
Steve Block44f0eee2011-05-26 01:26:41 +01001635 __ cmpq(r8, rcx);
Steve Block3ce2e202009-11-05 08:53:23 +00001636 __ j(not_equal, exit);
1637}
1638
1639
1640TEST(SmiAnd) {
1641 // Allocate an executable page of memory.
1642 size_t actual_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001643 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1644 Assembler::kMinimalBufferSize * 2, &actual_size, true));
Steve Block3ce2e202009-11-05 08:53:23 +00001645 CHECK(buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001646 Isolate* isolate = CcTest::i_isolate();
1647 HandleScope handles(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001648 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
1649 v8::internal::CodeObjectRequired::kYes);
Steve Block3ce2e202009-11-05 08:53:23 +00001650
1651 MacroAssembler* masm = &assembler;
Steve Block8defd9f2010-07-08 12:39:36 +01001652 EntryCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00001653 Label exit;
1654
1655 TestSmiAnd(masm, &exit, 0x10, 0, 0);
1656 TestSmiAnd(masm, &exit, 0x20, 0, 1);
1657 TestSmiAnd(masm, &exit, 0x30, 1, 0);
1658 TestSmiAnd(masm, &exit, 0x40, 0, -1);
1659 TestSmiAnd(masm, &exit, 0x50, -1, 0);
1660 TestSmiAnd(masm, &exit, 0x60, -1, -1);
1661 TestSmiAnd(masm, &exit, 0x70, 1, 1);
1662 TestSmiAnd(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
1663 TestSmiAnd(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
1664 TestSmiAnd(masm, &exit, 0xA0, Smi::kMinValue, -1);
1665 TestSmiAnd(masm, &exit, 0xB0, Smi::kMinValue, -1);
1666
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001667 __ xorq(rax, rax); // Success.
Steve Block3ce2e202009-11-05 08:53:23 +00001668 __ bind(&exit);
Steve Block8defd9f2010-07-08 12:39:36 +01001669 ExitCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00001670 __ ret(0);
1671
1672 CodeDesc desc;
1673 masm->GetCode(&desc);
1674 // Call the function from C++.
1675 int result = FUNCTION_CAST<F0>(buffer)();
1676 CHECK_EQ(0, result);
1677}
1678
1679
1680void TestSmiOr(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1681 int result = x | y;
1682
1683 __ movl(rax, Immediate(id));
1684
1685 __ Move(rcx, Smi::FromInt(x));
1686 __ movq(r11, rcx);
1687 __ Move(rdx, Smi::FromInt(y));
1688 __ Move(r8, Smi::FromInt(result));
1689 __ SmiOr(r9, rcx, rdx);
Steve Block44f0eee2011-05-26 01:26:41 +01001690 __ cmpq(r8, r9);
Steve Block3ce2e202009-11-05 08:53:23 +00001691 __ j(not_equal, exit);
1692
1693 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001694 __ cmpq(r11, rcx);
Steve Block3ce2e202009-11-05 08:53:23 +00001695 __ j(not_equal, exit);
1696
1697 __ incq(rax);
1698 __ SmiOr(rcx, rcx, rdx);
Steve Block44f0eee2011-05-26 01:26:41 +01001699 __ cmpq(r8, rcx);
Steve Block3ce2e202009-11-05 08:53:23 +00001700 __ j(not_equal, exit);
1701
1702 __ movq(rcx, r11);
1703 __ incq(rax);
1704 __ SmiOrConstant(r9, rcx, Smi::FromInt(y));
Steve Block44f0eee2011-05-26 01:26:41 +01001705 __ cmpq(r8, r9);
Steve Block3ce2e202009-11-05 08:53:23 +00001706 __ j(not_equal, exit);
1707
1708 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001709 __ cmpq(r11, rcx);
Steve Block3ce2e202009-11-05 08:53:23 +00001710 __ j(not_equal, exit);
1711
1712 __ incq(rax);
1713 __ SmiOrConstant(rcx, rcx, Smi::FromInt(y));
Steve Block44f0eee2011-05-26 01:26:41 +01001714 __ cmpq(r8, rcx);
Steve Block3ce2e202009-11-05 08:53:23 +00001715 __ j(not_equal, exit);
1716}
1717
1718
1719TEST(SmiOr) {
1720 // Allocate an executable page of memory.
1721 size_t actual_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001722 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1723 Assembler::kMinimalBufferSize * 2, &actual_size, true));
Steve Block3ce2e202009-11-05 08:53:23 +00001724 CHECK(buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001725 Isolate* isolate = CcTest::i_isolate();
1726 HandleScope handles(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001727 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
1728 v8::internal::CodeObjectRequired::kYes);
Steve Block3ce2e202009-11-05 08:53:23 +00001729
1730 MacroAssembler* masm = &assembler;
Steve Block8defd9f2010-07-08 12:39:36 +01001731 EntryCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00001732 Label exit;
1733
1734 TestSmiOr(masm, &exit, 0x10, 0, 0);
1735 TestSmiOr(masm, &exit, 0x20, 0, 1);
1736 TestSmiOr(masm, &exit, 0x30, 1, 0);
1737 TestSmiOr(masm, &exit, 0x40, 0, -1);
1738 TestSmiOr(masm, &exit, 0x50, -1, 0);
1739 TestSmiOr(masm, &exit, 0x60, -1, -1);
1740 TestSmiOr(masm, &exit, 0x70, 1, 1);
1741 TestSmiOr(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
1742 TestSmiOr(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
1743 TestSmiOr(masm, &exit, 0xA0, Smi::kMinValue, -1);
1744 TestSmiOr(masm, &exit, 0xB0, 0x05555555, 0x01234567);
1745 TestSmiOr(masm, &exit, 0xC0, 0x05555555, 0x0fedcba9);
1746 TestSmiOr(masm, &exit, 0xD0, Smi::kMinValue, -1);
1747
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001748 __ xorq(rax, rax); // Success.
Steve Block3ce2e202009-11-05 08:53:23 +00001749 __ bind(&exit);
Steve Block8defd9f2010-07-08 12:39:36 +01001750 ExitCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00001751 __ ret(0);
1752
1753 CodeDesc desc;
1754 masm->GetCode(&desc);
1755 // Call the function from C++.
1756 int result = FUNCTION_CAST<F0>(buffer)();
1757 CHECK_EQ(0, result);
1758}
1759
1760
1761void TestSmiXor(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1762 int result = x ^ y;
1763
1764 __ movl(rax, Immediate(id));
1765
1766 __ Move(rcx, Smi::FromInt(x));
1767 __ movq(r11, rcx);
1768 __ Move(rdx, Smi::FromInt(y));
1769 __ Move(r8, Smi::FromInt(result));
1770 __ SmiXor(r9, rcx, rdx);
Steve Block44f0eee2011-05-26 01:26:41 +01001771 __ cmpq(r8, r9);
Steve Block3ce2e202009-11-05 08:53:23 +00001772 __ j(not_equal, exit);
1773
1774 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001775 __ cmpq(r11, rcx);
Steve Block3ce2e202009-11-05 08:53:23 +00001776 __ j(not_equal, exit);
1777
1778 __ incq(rax);
1779 __ SmiXor(rcx, rcx, rdx);
Steve Block44f0eee2011-05-26 01:26:41 +01001780 __ cmpq(r8, rcx);
Steve Block3ce2e202009-11-05 08:53:23 +00001781 __ j(not_equal, exit);
1782
1783 __ movq(rcx, r11);
1784 __ incq(rax);
1785 __ SmiXorConstant(r9, rcx, Smi::FromInt(y));
Steve Block44f0eee2011-05-26 01:26:41 +01001786 __ cmpq(r8, r9);
Steve Block3ce2e202009-11-05 08:53:23 +00001787 __ j(not_equal, exit);
1788
1789 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001790 __ cmpq(r11, rcx);
Steve Block3ce2e202009-11-05 08:53:23 +00001791 __ j(not_equal, exit);
1792
1793 __ incq(rax);
1794 __ SmiXorConstant(rcx, rcx, Smi::FromInt(y));
Steve Block44f0eee2011-05-26 01:26:41 +01001795 __ cmpq(r8, rcx);
Steve Block3ce2e202009-11-05 08:53:23 +00001796 __ j(not_equal, exit);
1797}
1798
1799
1800TEST(SmiXor) {
1801 // Allocate an executable page of memory.
1802 size_t actual_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001803 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1804 Assembler::kMinimalBufferSize * 2, &actual_size, true));
Steve Block3ce2e202009-11-05 08:53:23 +00001805 CHECK(buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001806 Isolate* isolate = CcTest::i_isolate();
1807 HandleScope handles(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001808 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
1809 v8::internal::CodeObjectRequired::kYes);
Steve Block3ce2e202009-11-05 08:53:23 +00001810
1811 MacroAssembler* masm = &assembler;
Steve Block8defd9f2010-07-08 12:39:36 +01001812 EntryCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00001813 Label exit;
1814
1815 TestSmiXor(masm, &exit, 0x10, 0, 0);
1816 TestSmiXor(masm, &exit, 0x20, 0, 1);
1817 TestSmiXor(masm, &exit, 0x30, 1, 0);
1818 TestSmiXor(masm, &exit, 0x40, 0, -1);
1819 TestSmiXor(masm, &exit, 0x50, -1, 0);
1820 TestSmiXor(masm, &exit, 0x60, -1, -1);
1821 TestSmiXor(masm, &exit, 0x70, 1, 1);
1822 TestSmiXor(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
1823 TestSmiXor(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
1824 TestSmiXor(masm, &exit, 0xA0, Smi::kMinValue, -1);
1825 TestSmiXor(masm, &exit, 0xB0, 0x5555555, 0x01234567);
1826 TestSmiXor(masm, &exit, 0xC0, 0x5555555, 0x0fedcba9);
1827 TestSmiXor(masm, &exit, 0xD0, Smi::kMinValue, -1);
1828
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001829 __ xorq(rax, rax); // Success.
Steve Block3ce2e202009-11-05 08:53:23 +00001830 __ bind(&exit);
Steve Block8defd9f2010-07-08 12:39:36 +01001831 ExitCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00001832 __ ret(0);
1833
1834 CodeDesc desc;
1835 masm->GetCode(&desc);
1836 // Call the function from C++.
1837 int result = FUNCTION_CAST<F0>(buffer)();
1838 CHECK_EQ(0, result);
1839}
1840
1841
1842void TestSmiNot(MacroAssembler* masm, Label* exit, int id, int x) {
1843 int result = ~x;
1844 __ movl(rax, Immediate(id));
1845
1846 __ Move(r8, Smi::FromInt(result));
1847 __ Move(rcx, Smi::FromInt(x));
1848 __ movq(r11, rcx);
1849
1850 __ SmiNot(r9, rcx);
Steve Block44f0eee2011-05-26 01:26:41 +01001851 __ cmpq(r9, r8);
Steve Block3ce2e202009-11-05 08:53:23 +00001852 __ j(not_equal, exit);
1853
1854 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001855 __ cmpq(r11, rcx);
Steve Block3ce2e202009-11-05 08:53:23 +00001856 __ j(not_equal, exit);
1857
1858 __ incq(rax);
1859 __ SmiNot(rcx, rcx);
Steve Block44f0eee2011-05-26 01:26:41 +01001860 __ cmpq(rcx, r8);
Steve Block3ce2e202009-11-05 08:53:23 +00001861 __ j(not_equal, exit);
1862}
1863
1864
1865TEST(SmiNot) {
1866 // Allocate an executable page of memory.
1867 size_t actual_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001868 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1869 Assembler::kMinimalBufferSize, &actual_size, true));
Steve Block3ce2e202009-11-05 08:53:23 +00001870 CHECK(buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001871 Isolate* isolate = CcTest::i_isolate();
1872 HandleScope handles(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001873 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
1874 v8::internal::CodeObjectRequired::kYes);
Steve Block3ce2e202009-11-05 08:53:23 +00001875
1876 MacroAssembler* masm = &assembler;
Steve Block8defd9f2010-07-08 12:39:36 +01001877 EntryCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00001878 Label exit;
1879
1880 TestSmiNot(masm, &exit, 0x10, 0);
1881 TestSmiNot(masm, &exit, 0x20, 1);
1882 TestSmiNot(masm, &exit, 0x30, -1);
1883 TestSmiNot(masm, &exit, 0x40, 127);
1884 TestSmiNot(masm, &exit, 0x50, 65535);
1885 TestSmiNot(masm, &exit, 0x60, Smi::kMinValue);
1886 TestSmiNot(masm, &exit, 0x70, Smi::kMaxValue);
1887 TestSmiNot(masm, &exit, 0x80, 0x05555555);
1888
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001889 __ xorq(rax, rax); // Success.
Steve Block3ce2e202009-11-05 08:53:23 +00001890 __ bind(&exit);
Steve Block8defd9f2010-07-08 12:39:36 +01001891 ExitCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00001892 __ ret(0);
1893
1894 CodeDesc desc;
1895 masm->GetCode(&desc);
1896 // Call the function from C++.
1897 int result = FUNCTION_CAST<F0>(buffer)();
1898 CHECK_EQ(0, result);
1899}
1900
1901
1902void TestSmiShiftLeft(MacroAssembler* masm, Label* exit, int id, int x) {
1903 const int shifts[] = { 0, 1, 7, 24, kSmiValueSize - 1};
1904 const int kNumShifts = 5;
1905 __ movl(rax, Immediate(id));
1906 for (int i = 0; i < kNumShifts; i++) {
1907 // rax == id + i * 10.
1908 int shift = shifts[i];
1909 int result = x << shift;
Kristian Monsen25f61362010-05-21 11:50:48 +01001910 CHECK(Smi::IsValid(result));
1911 __ Move(r8, Smi::FromInt(result));
1912 __ Move(rcx, Smi::FromInt(x));
1913 __ SmiShiftLeftConstant(r9, rcx, shift);
Steve Block3ce2e202009-11-05 08:53:23 +00001914
Kristian Monsen25f61362010-05-21 11:50:48 +01001915 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001916 __ cmpq(r9, r8);
Kristian Monsen25f61362010-05-21 11:50:48 +01001917 __ j(not_equal, exit);
Steve Block3ce2e202009-11-05 08:53:23 +00001918
Kristian Monsen25f61362010-05-21 11:50:48 +01001919 __ incq(rax);
1920 __ Move(rcx, Smi::FromInt(x));
1921 __ SmiShiftLeftConstant(rcx, rcx, shift);
Steve Block3ce2e202009-11-05 08:53:23 +00001922
Kristian Monsen25f61362010-05-21 11:50:48 +01001923 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001924 __ cmpq(rcx, r8);
Kristian Monsen25f61362010-05-21 11:50:48 +01001925 __ j(not_equal, exit);
Steve Block3ce2e202009-11-05 08:53:23 +00001926
Kristian Monsen25f61362010-05-21 11:50:48 +01001927 __ incq(rax);
1928 __ Move(rdx, Smi::FromInt(x));
1929 __ Move(rcx, Smi::FromInt(shift));
1930 __ SmiShiftLeft(r9, rdx, rcx);
Steve Block3ce2e202009-11-05 08:53:23 +00001931
Kristian Monsen25f61362010-05-21 11:50:48 +01001932 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001933 __ cmpq(r9, r8);
Kristian Monsen25f61362010-05-21 11:50:48 +01001934 __ j(not_equal, exit);
Steve Block3ce2e202009-11-05 08:53:23 +00001935
Kristian Monsen25f61362010-05-21 11:50:48 +01001936 __ incq(rax);
1937 __ Move(rdx, Smi::FromInt(x));
1938 __ Move(r11, Smi::FromInt(shift));
1939 __ SmiShiftLeft(r9, rdx, r11);
Steve Block3ce2e202009-11-05 08:53:23 +00001940
Kristian Monsen25f61362010-05-21 11:50:48 +01001941 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001942 __ cmpq(r9, r8);
Kristian Monsen25f61362010-05-21 11:50:48 +01001943 __ j(not_equal, exit);
Steve Block3ce2e202009-11-05 08:53:23 +00001944
Kristian Monsen25f61362010-05-21 11:50:48 +01001945 __ incq(rax);
1946 __ Move(rdx, Smi::FromInt(x));
1947 __ Move(r11, Smi::FromInt(shift));
1948 __ SmiShiftLeft(rdx, rdx, r11);
Steve Block3ce2e202009-11-05 08:53:23 +00001949
Kristian Monsen25f61362010-05-21 11:50:48 +01001950 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01001951 __ cmpq(rdx, r8);
Kristian Monsen25f61362010-05-21 11:50:48 +01001952 __ j(not_equal, exit);
Steve Block3ce2e202009-11-05 08:53:23 +00001953
Kristian Monsen25f61362010-05-21 11:50:48 +01001954 __ incq(rax);
Steve Block3ce2e202009-11-05 08:53:23 +00001955 }
1956}
1957
1958
1959TEST(SmiShiftLeft) {
1960 // Allocate an executable page of memory.
1961 size_t actual_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001962 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
1963 Assembler::kMinimalBufferSize * 7, &actual_size, true));
Steve Block3ce2e202009-11-05 08:53:23 +00001964 CHECK(buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001965 Isolate* isolate = CcTest::i_isolate();
1966 HandleScope handles(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001967 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
1968 v8::internal::CodeObjectRequired::kYes);
Steve Block3ce2e202009-11-05 08:53:23 +00001969
1970 MacroAssembler* masm = &assembler;
Steve Block8defd9f2010-07-08 12:39:36 +01001971 EntryCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00001972 Label exit;
1973
1974 TestSmiShiftLeft(masm, &exit, 0x10, 0);
1975 TestSmiShiftLeft(masm, &exit, 0x50, 1);
1976 TestSmiShiftLeft(masm, &exit, 0x90, 127);
1977 TestSmiShiftLeft(masm, &exit, 0xD0, 65535);
1978 TestSmiShiftLeft(masm, &exit, 0x110, Smi::kMaxValue);
1979 TestSmiShiftLeft(masm, &exit, 0x150, Smi::kMinValue);
1980 TestSmiShiftLeft(masm, &exit, 0x190, -1);
1981
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001982 __ xorq(rax, rax); // Success.
Steve Block3ce2e202009-11-05 08:53:23 +00001983 __ bind(&exit);
Steve Block8defd9f2010-07-08 12:39:36 +01001984 ExitCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00001985 __ ret(0);
1986
1987 CodeDesc desc;
1988 masm->GetCode(&desc);
1989 // Call the function from C++.
1990 int result = FUNCTION_CAST<F0>(buffer)();
1991 CHECK_EQ(0, result);
1992}
1993
1994
1995void TestSmiShiftLogicalRight(MacroAssembler* masm,
1996 Label* exit,
1997 int id,
1998 int x) {
1999 const int shifts[] = { 0, 1, 7, 24, kSmiValueSize - 1};
2000 const int kNumShifts = 5;
2001 __ movl(rax, Immediate(id));
2002 for (int i = 0; i < kNumShifts; i++) {
2003 int shift = shifts[i];
2004 intptr_t result = static_cast<unsigned int>(x) >> shift;
2005 if (Smi::IsValid(result)) {
Steve Blockd0582a62009-12-15 09:54:21 +00002006 __ Move(r8, Smi::FromInt(static_cast<int>(result)));
Steve Block3ce2e202009-11-05 08:53:23 +00002007 __ Move(rcx, Smi::FromInt(x));
2008 __ SmiShiftLogicalRightConstant(r9, rcx, shift, exit);
2009
2010 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01002011 __ cmpq(r9, r8);
Steve Block3ce2e202009-11-05 08:53:23 +00002012 __ j(not_equal, exit);
2013
2014 __ incq(rax);
2015 __ Move(rdx, Smi::FromInt(x));
2016 __ Move(rcx, Smi::FromInt(shift));
2017 __ SmiShiftLogicalRight(r9, rdx, rcx, exit);
2018
2019 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01002020 __ cmpq(r9, r8);
Steve Block3ce2e202009-11-05 08:53:23 +00002021 __ j(not_equal, exit);
2022
2023 __ incq(rax);
2024 __ Move(rdx, Smi::FromInt(x));
2025 __ Move(r11, Smi::FromInt(shift));
2026 __ SmiShiftLogicalRight(r9, rdx, r11, exit);
2027
2028 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01002029 __ cmpq(r9, r8);
Steve Block3ce2e202009-11-05 08:53:23 +00002030 __ j(not_equal, exit);
2031
2032 __ incq(rax);
2033 } else {
2034 // Cannot happen with long smis.
2035 Label fail_ok;
2036 __ Move(rcx, Smi::FromInt(x));
2037 __ movq(r11, rcx);
2038 __ SmiShiftLogicalRightConstant(r9, rcx, shift, &fail_ok);
2039 __ jmp(exit);
2040 __ bind(&fail_ok);
2041
2042 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01002043 __ cmpq(rcx, r11);
Steve Block3ce2e202009-11-05 08:53:23 +00002044 __ j(not_equal, exit);
2045
2046 __ incq(rax);
2047 __ Move(r8, Smi::FromInt(shift));
2048 Label fail_ok3;
2049 __ SmiShiftLogicalRight(r9, rcx, r8, &fail_ok3);
2050 __ jmp(exit);
2051 __ bind(&fail_ok3);
2052
2053 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01002054 __ cmpq(rcx, r11);
Steve Block3ce2e202009-11-05 08:53:23 +00002055 __ j(not_equal, exit);
2056
2057 __ addq(rax, Immediate(3));
2058 }
2059 }
2060}
2061
2062
2063TEST(SmiShiftLogicalRight) {
2064 // Allocate an executable page of memory.
2065 size_t actual_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002066 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
2067 Assembler::kMinimalBufferSize * 5, &actual_size, true));
Steve Block3ce2e202009-11-05 08:53:23 +00002068 CHECK(buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002069 Isolate* isolate = CcTest::i_isolate();
2070 HandleScope handles(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002071 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
2072 v8::internal::CodeObjectRequired::kYes);
Steve Block3ce2e202009-11-05 08:53:23 +00002073
2074 MacroAssembler* masm = &assembler;
Steve Block8defd9f2010-07-08 12:39:36 +01002075 EntryCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00002076 Label exit;
2077
2078 TestSmiShiftLogicalRight(masm, &exit, 0x10, 0);
2079 TestSmiShiftLogicalRight(masm, &exit, 0x30, 1);
2080 TestSmiShiftLogicalRight(masm, &exit, 0x50, 127);
2081 TestSmiShiftLogicalRight(masm, &exit, 0x70, 65535);
2082 TestSmiShiftLogicalRight(masm, &exit, 0x90, Smi::kMaxValue);
2083 TestSmiShiftLogicalRight(masm, &exit, 0xB0, Smi::kMinValue);
2084 TestSmiShiftLogicalRight(masm, &exit, 0xD0, -1);
2085
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002086 __ xorq(rax, rax); // Success.
Steve Block3ce2e202009-11-05 08:53:23 +00002087 __ bind(&exit);
Steve Block8defd9f2010-07-08 12:39:36 +01002088 ExitCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00002089 __ ret(0);
2090
2091 CodeDesc desc;
2092 masm->GetCode(&desc);
2093 // Call the function from C++.
2094 int result = FUNCTION_CAST<F0>(buffer)();
2095 CHECK_EQ(0, result);
2096}
2097
2098
2099void TestSmiShiftArithmeticRight(MacroAssembler* masm,
2100 Label* exit,
2101 int id,
2102 int x) {
2103 const int shifts[] = { 0, 1, 7, 24, kSmiValueSize - 1};
2104 const int kNumShifts = 5;
2105 __ movl(rax, Immediate(id));
2106 for (int i = 0; i < kNumShifts; i++) {
2107 int shift = shifts[i];
2108 // Guaranteed arithmetic shift.
2109 int result = (x < 0) ? ~((~x) >> shift) : (x >> shift);
2110 __ Move(r8, Smi::FromInt(result));
2111 __ Move(rcx, Smi::FromInt(x));
2112 __ SmiShiftArithmeticRightConstant(rcx, rcx, shift);
2113
Steve Block44f0eee2011-05-26 01:26:41 +01002114 __ cmpq(rcx, r8);
Steve Block3ce2e202009-11-05 08:53:23 +00002115 __ j(not_equal, exit);
2116
2117 __ incq(rax);
2118 __ Move(rdx, Smi::FromInt(x));
2119 __ Move(r11, Smi::FromInt(shift));
2120 __ SmiShiftArithmeticRight(rdx, rdx, r11);
2121
Steve Block44f0eee2011-05-26 01:26:41 +01002122 __ cmpq(rdx, r8);
Steve Block3ce2e202009-11-05 08:53:23 +00002123 __ j(not_equal, exit);
2124
2125 __ incq(rax);
2126 }
2127}
2128
2129
2130TEST(SmiShiftArithmeticRight) {
2131 // Allocate an executable page of memory.
2132 size_t actual_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002133 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
2134 Assembler::kMinimalBufferSize * 3, &actual_size, true));
Steve Block3ce2e202009-11-05 08:53:23 +00002135 CHECK(buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002136 Isolate* isolate = CcTest::i_isolate();
2137 HandleScope handles(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002138 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
2139 v8::internal::CodeObjectRequired::kYes);
Steve Block3ce2e202009-11-05 08:53:23 +00002140
2141 MacroAssembler* masm = &assembler;
Steve Block8defd9f2010-07-08 12:39:36 +01002142 EntryCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00002143 Label exit;
2144
2145 TestSmiShiftArithmeticRight(masm, &exit, 0x10, 0);
2146 TestSmiShiftArithmeticRight(masm, &exit, 0x20, 1);
2147 TestSmiShiftArithmeticRight(masm, &exit, 0x30, 127);
2148 TestSmiShiftArithmeticRight(masm, &exit, 0x40, 65535);
2149 TestSmiShiftArithmeticRight(masm, &exit, 0x50, Smi::kMaxValue);
2150 TestSmiShiftArithmeticRight(masm, &exit, 0x60, Smi::kMinValue);
2151 TestSmiShiftArithmeticRight(masm, &exit, 0x70, -1);
2152
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002153 __ xorq(rax, rax); // Success.
Steve Block3ce2e202009-11-05 08:53:23 +00002154 __ bind(&exit);
Steve Block8defd9f2010-07-08 12:39:36 +01002155 ExitCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00002156 __ ret(0);
2157
2158 CodeDesc desc;
2159 masm->GetCode(&desc);
2160 // Call the function from C++.
2161 int result = FUNCTION_CAST<F0>(buffer)();
2162 CHECK_EQ(0, result);
2163}
2164
2165
2166void TestPositiveSmiPowerUp(MacroAssembler* masm, Label* exit, int id, int x) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002167 CHECK(x >= 0);
Steve Block3ce2e202009-11-05 08:53:23 +00002168 int powers[] = { 0, 1, 2, 3, 8, 16, 24, 31 };
2169 int power_count = 8;
2170 __ movl(rax, Immediate(id));
2171 for (int i = 0; i < power_count; i++) {
2172 int power = powers[i];
2173 intptr_t result = static_cast<intptr_t>(x) << power;
2174 __ Set(r8, result);
2175 __ Move(rcx, Smi::FromInt(x));
2176 __ movq(r11, rcx);
2177 __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rcx, power);
Steve Block44f0eee2011-05-26 01:26:41 +01002178 __ cmpq(rdx, r8);
Steve Block3ce2e202009-11-05 08:53:23 +00002179 __ j(not_equal, exit);
2180 __ incq(rax);
Steve Block44f0eee2011-05-26 01:26:41 +01002181 __ cmpq(r11, rcx); // rcx unchanged.
Steve Block3ce2e202009-11-05 08:53:23 +00002182 __ j(not_equal, exit);
2183 __ incq(rax);
2184 __ PositiveSmiTimesPowerOfTwoToInteger64(rcx, rcx, power);
Steve Block44f0eee2011-05-26 01:26:41 +01002185 __ cmpq(rdx, r8);
Steve Block3ce2e202009-11-05 08:53:23 +00002186 __ j(not_equal, exit);
2187 __ incq(rax);
2188 }
2189}
2190
2191
2192TEST(PositiveSmiTimesPowerOfTwoToInteger64) {
2193 // Allocate an executable page of memory.
2194 size_t actual_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002195 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
2196 Assembler::kMinimalBufferSize * 4, &actual_size, true));
Steve Block3ce2e202009-11-05 08:53:23 +00002197 CHECK(buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002198 Isolate* isolate = CcTest::i_isolate();
2199 HandleScope handles(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002200 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
2201 v8::internal::CodeObjectRequired::kYes);
Steve Block3ce2e202009-11-05 08:53:23 +00002202
2203 MacroAssembler* masm = &assembler;
Steve Block8defd9f2010-07-08 12:39:36 +01002204 EntryCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00002205 Label exit;
2206
2207 TestPositiveSmiPowerUp(masm, &exit, 0x20, 0);
2208 TestPositiveSmiPowerUp(masm, &exit, 0x40, 1);
2209 TestPositiveSmiPowerUp(masm, &exit, 0x60, 127);
2210 TestPositiveSmiPowerUp(masm, &exit, 0x80, 128);
2211 TestPositiveSmiPowerUp(masm, &exit, 0xA0, 255);
2212 TestPositiveSmiPowerUp(masm, &exit, 0xC0, 256);
2213 TestPositiveSmiPowerUp(masm, &exit, 0x100, 65535);
2214 TestPositiveSmiPowerUp(masm, &exit, 0x120, 65536);
2215 TestPositiveSmiPowerUp(masm, &exit, 0x140, Smi::kMaxValue);
2216
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002217 __ xorq(rax, rax); // Success.
Steve Block3ce2e202009-11-05 08:53:23 +00002218 __ bind(&exit);
Steve Block8defd9f2010-07-08 12:39:36 +01002219 ExitCode(masm);
Steve Block3ce2e202009-11-05 08:53:23 +00002220 __ ret(0);
2221
2222 CodeDesc desc;
2223 masm->GetCode(&desc);
2224 // Call the function from C++.
2225 int result = FUNCTION_CAST<F0>(buffer)();
2226 CHECK_EQ(0, result);
2227}
2228
2229
Leon Clarkef7060e22010-06-03 12:02:55 +01002230TEST(OperandOffset) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002231 uint32_t data[256];
2232 for (uint32_t i = 0; i < 256; i++) { data[i] = i * 0x01010101; }
Leon Clarkef7060e22010-06-03 12:02:55 +01002233
2234 // Allocate an executable page of memory.
2235 size_t actual_size;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002236 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
2237 Assembler::kMinimalBufferSize * 2, &actual_size, true));
Leon Clarkef7060e22010-06-03 12:02:55 +01002238 CHECK(buffer);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002239 Isolate* isolate = CcTest::i_isolate();
2240 HandleScope handles(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002241 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
2242 v8::internal::CodeObjectRequired::kYes);
Leon Clarkef7060e22010-06-03 12:02:55 +01002243
2244 MacroAssembler* masm = &assembler;
Leon Clarkef7060e22010-06-03 12:02:55 +01002245 Label exit;
2246
Steve Block8defd9f2010-07-08 12:39:36 +01002247 EntryCode(masm);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002248 __ pushq(r13);
2249 __ pushq(r14);
2250 __ pushq(rbx);
2251 __ pushq(rbp);
2252 __ pushq(Immediate(0x100)); // <-- rbp
Leon Clarkef7060e22010-06-03 12:02:55 +01002253 __ movq(rbp, rsp);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002254 __ pushq(Immediate(0x101));
2255 __ pushq(Immediate(0x102));
2256 __ pushq(Immediate(0x103));
2257 __ pushq(Immediate(0x104));
2258 __ pushq(Immediate(0x105)); // <-- rbx
2259 __ pushq(Immediate(0x106));
2260 __ pushq(Immediate(0x107));
2261 __ pushq(Immediate(0x108));
2262 __ pushq(Immediate(0x109)); // <-- rsp
Leon Clarkef7060e22010-06-03 12:02:55 +01002263 // rbp = rsp[9]
Steve Block44f0eee2011-05-26 01:26:41 +01002264 // r15 = rsp[3]
Leon Clarkef7060e22010-06-03 12:02:55 +01002265 // rbx = rsp[5]
2266 // r13 = rsp[7]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002267 __ leaq(r14, Operand(rsp, 3 * kPointerSize));
2268 __ leaq(r13, Operand(rbp, -3 * kPointerSize));
2269 __ leaq(rbx, Operand(rbp, -5 * kPointerSize));
Leon Clarkef7060e22010-06-03 12:02:55 +01002270 __ movl(rcx, Immediate(2));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002271 __ Move(r8, reinterpret_cast<Address>(&data[128]), RelocInfo::NONE64);
Leon Clarkef7060e22010-06-03 12:02:55 +01002272 __ movl(rax, Immediate(1));
2273
2274 Operand sp0 = Operand(rsp, 0);
2275
2276 // Test 1.
2277 __ movl(rdx, sp0); // Sanity check.
2278 __ cmpl(rdx, Immediate(0x109));
2279 __ j(not_equal, &exit);
2280 __ incq(rax);
2281
2282 // Test 2.
2283 // Zero to non-zero displacement.
2284 __ movl(rdx, Operand(sp0, 2 * kPointerSize));
2285 __ cmpl(rdx, Immediate(0x107));
2286 __ j(not_equal, &exit);
2287 __ incq(rax);
2288
2289 Operand sp2 = Operand(rsp, 2 * kPointerSize);
2290
2291 // Test 3.
2292 __ movl(rdx, sp2); // Sanity check.
2293 __ cmpl(rdx, Immediate(0x107));
2294 __ j(not_equal, &exit);
2295 __ incq(rax);
2296
2297 __ movl(rdx, Operand(sp2, 2 * kPointerSize));
2298 __ cmpl(rdx, Immediate(0x105));
2299 __ j(not_equal, &exit);
2300 __ incq(rax);
2301
2302 // Non-zero to zero displacement.
2303 __ movl(rdx, Operand(sp2, -2 * kPointerSize));
2304 __ cmpl(rdx, Immediate(0x109));
2305 __ j(not_equal, &exit);
2306 __ incq(rax);
2307
2308 Operand sp2c2 = Operand(rsp, rcx, times_pointer_size, 2 * kPointerSize);
2309
2310 // Test 6.
2311 __ movl(rdx, sp2c2); // Sanity check.
2312 __ cmpl(rdx, Immediate(0x105));
2313 __ j(not_equal, &exit);
2314 __ incq(rax);
2315
2316 __ movl(rdx, Operand(sp2c2, 2 * kPointerSize));
2317 __ cmpl(rdx, Immediate(0x103));
2318 __ j(not_equal, &exit);
2319 __ incq(rax);
2320
2321 // Non-zero to zero displacement.
2322 __ movl(rdx, Operand(sp2c2, -2 * kPointerSize));
2323 __ cmpl(rdx, Immediate(0x107));
2324 __ j(not_equal, &exit);
2325 __ incq(rax);
2326
2327
2328 Operand bp0 = Operand(rbp, 0);
2329
2330 // Test 9.
2331 __ movl(rdx, bp0); // Sanity check.
2332 __ cmpl(rdx, Immediate(0x100));
2333 __ j(not_equal, &exit);
2334 __ incq(rax);
2335
2336 // Zero to non-zero displacement.
2337 __ movl(rdx, Operand(bp0, -2 * kPointerSize));
2338 __ cmpl(rdx, Immediate(0x102));
2339 __ j(not_equal, &exit);
2340 __ incq(rax);
2341
2342 Operand bp2 = Operand(rbp, -2 * kPointerSize);
2343
2344 // Test 11.
2345 __ movl(rdx, bp2); // Sanity check.
2346 __ cmpl(rdx, Immediate(0x102));
2347 __ j(not_equal, &exit);
2348 __ incq(rax);
2349
2350 // Non-zero to zero displacement.
2351 __ movl(rdx, Operand(bp2, 2 * kPointerSize));
2352 __ cmpl(rdx, Immediate(0x100));
2353 __ j(not_equal, &exit);
2354 __ incq(rax);
2355
2356 __ movl(rdx, Operand(bp2, -2 * kPointerSize));
2357 __ cmpl(rdx, Immediate(0x104));
2358 __ j(not_equal, &exit);
2359 __ incq(rax);
2360
2361 Operand bp2c4 = Operand(rbp, rcx, times_pointer_size, -4 * kPointerSize);
2362
2363 // Test 14:
2364 __ movl(rdx, bp2c4); // Sanity check.
2365 __ cmpl(rdx, Immediate(0x102));
2366 __ j(not_equal, &exit);
2367 __ incq(rax);
2368
2369 __ movl(rdx, Operand(bp2c4, 2 * kPointerSize));
2370 __ cmpl(rdx, Immediate(0x100));
2371 __ j(not_equal, &exit);
2372 __ incq(rax);
2373
2374 __ movl(rdx, Operand(bp2c4, -2 * kPointerSize));
2375 __ cmpl(rdx, Immediate(0x104));
2376 __ j(not_equal, &exit);
2377 __ incq(rax);
2378
2379 Operand bx0 = Operand(rbx, 0);
2380
2381 // Test 17.
2382 __ movl(rdx, bx0); // Sanity check.
2383 __ cmpl(rdx, Immediate(0x105));
2384 __ j(not_equal, &exit);
2385 __ incq(rax);
2386
2387 __ movl(rdx, Operand(bx0, 5 * kPointerSize));
2388 __ cmpl(rdx, Immediate(0x100));
2389 __ j(not_equal, &exit);
2390 __ incq(rax);
2391
2392 __ movl(rdx, Operand(bx0, -4 * kPointerSize));
2393 __ cmpl(rdx, Immediate(0x109));
2394 __ j(not_equal, &exit);
2395 __ incq(rax);
2396
2397 Operand bx2 = Operand(rbx, 2 * kPointerSize);
2398
2399 // Test 20.
2400 __ movl(rdx, bx2); // Sanity check.
2401 __ cmpl(rdx, Immediate(0x103));
2402 __ j(not_equal, &exit);
2403 __ incq(rax);
2404
2405 __ movl(rdx, Operand(bx2, 2 * kPointerSize));
2406 __ cmpl(rdx, Immediate(0x101));
2407 __ j(not_equal, &exit);
2408 __ incq(rax);
2409
2410 // Non-zero to zero displacement.
2411 __ movl(rdx, Operand(bx2, -2 * kPointerSize));
2412 __ cmpl(rdx, Immediate(0x105));
2413 __ j(not_equal, &exit);
2414 __ incq(rax);
2415
2416 Operand bx2c2 = Operand(rbx, rcx, times_pointer_size, -2 * kPointerSize);
2417
2418 // Test 23.
2419 __ movl(rdx, bx2c2); // Sanity check.
2420 __ cmpl(rdx, Immediate(0x105));
2421 __ j(not_equal, &exit);
2422 __ incq(rax);
2423
2424 __ movl(rdx, Operand(bx2c2, 2 * kPointerSize));
2425 __ cmpl(rdx, Immediate(0x103));
2426 __ j(not_equal, &exit);
2427 __ incq(rax);
2428
2429 __ movl(rdx, Operand(bx2c2, -2 * kPointerSize));
2430 __ cmpl(rdx, Immediate(0x107));
2431 __ j(not_equal, &exit);
2432 __ incq(rax);
2433
2434 Operand r80 = Operand(r8, 0);
2435
2436 // Test 26.
2437 __ movl(rdx, r80); // Sanity check.
2438 __ cmpl(rdx, Immediate(0x80808080));
2439 __ j(not_equal, &exit);
2440 __ incq(rax);
2441
2442 __ movl(rdx, Operand(r80, -8 * kIntSize));
2443 __ cmpl(rdx, Immediate(0x78787878));
2444 __ j(not_equal, &exit);
2445 __ incq(rax);
2446
2447 __ movl(rdx, Operand(r80, 8 * kIntSize));
2448 __ cmpl(rdx, Immediate(0x88888888));
2449 __ j(not_equal, &exit);
2450 __ incq(rax);
2451
2452 __ movl(rdx, Operand(r80, -64 * kIntSize));
2453 __ cmpl(rdx, Immediate(0x40404040));
2454 __ j(not_equal, &exit);
2455 __ incq(rax);
2456
2457 __ movl(rdx, Operand(r80, 64 * kIntSize));
2458 __ cmpl(rdx, Immediate(0xC0C0C0C0));
2459 __ j(not_equal, &exit);
2460 __ incq(rax);
2461
2462 Operand r88 = Operand(r8, 8 * kIntSize);
2463
2464 // Test 31.
2465 __ movl(rdx, r88); // Sanity check.
2466 __ cmpl(rdx, Immediate(0x88888888));
2467 __ j(not_equal, &exit);
2468 __ incq(rax);
2469
2470 __ movl(rdx, Operand(r88, -8 * kIntSize));
2471 __ cmpl(rdx, Immediate(0x80808080));
2472 __ j(not_equal, &exit);
2473 __ incq(rax);
2474
2475 __ movl(rdx, Operand(r88, 8 * kIntSize));
2476 __ cmpl(rdx, Immediate(0x90909090));
2477 __ j(not_equal, &exit);
2478 __ incq(rax);
2479
2480 __ movl(rdx, Operand(r88, -64 * kIntSize));
2481 __ cmpl(rdx, Immediate(0x48484848));
2482 __ j(not_equal, &exit);
2483 __ incq(rax);
2484
2485 __ movl(rdx, Operand(r88, 64 * kIntSize));
2486 __ cmpl(rdx, Immediate(0xC8C8C8C8));
2487 __ j(not_equal, &exit);
2488 __ incq(rax);
2489
2490
2491 Operand r864 = Operand(r8, 64 * kIntSize);
2492
2493 // Test 36.
2494 __ movl(rdx, r864); // Sanity check.
2495 __ cmpl(rdx, Immediate(0xC0C0C0C0));
2496 __ j(not_equal, &exit);
2497 __ incq(rax);
2498
2499 __ movl(rdx, Operand(r864, -8 * kIntSize));
2500 __ cmpl(rdx, Immediate(0xB8B8B8B8));
2501 __ j(not_equal, &exit);
2502 __ incq(rax);
2503
2504 __ movl(rdx, Operand(r864, 8 * kIntSize));
2505 __ cmpl(rdx, Immediate(0xC8C8C8C8));
2506 __ j(not_equal, &exit);
2507 __ incq(rax);
2508
2509 __ movl(rdx, Operand(r864, -64 * kIntSize));
2510 __ cmpl(rdx, Immediate(0x80808080));
2511 __ j(not_equal, &exit);
2512 __ incq(rax);
2513
2514 __ movl(rdx, Operand(r864, 32 * kIntSize));
2515 __ cmpl(rdx, Immediate(0xE0E0E0E0));
2516 __ j(not_equal, &exit);
2517 __ incq(rax);
2518
2519 // 32-bit offset to 8-bit offset.
2520 __ movl(rdx, Operand(r864, -60 * kIntSize));
2521 __ cmpl(rdx, Immediate(0x84848484));
2522 __ j(not_equal, &exit);
2523 __ incq(rax);
2524
2525 __ movl(rdx, Operand(r864, 60 * kIntSize));
2526 __ cmpl(rdx, Immediate(0xFCFCFCFC));
2527 __ j(not_equal, &exit);
2528 __ incq(rax);
2529
2530 // Test unaligned offsets.
2531
2532 // Test 43.
2533 __ movl(rdx, Operand(r80, 2));
2534 __ cmpl(rdx, Immediate(0x81818080));
2535 __ j(not_equal, &exit);
2536 __ incq(rax);
2537
2538 __ movl(rdx, Operand(r80, -2));
2539 __ cmpl(rdx, Immediate(0x80807F7F));
2540 __ j(not_equal, &exit);
2541 __ incq(rax);
2542
2543 __ movl(rdx, Operand(r80, 126));
2544 __ cmpl(rdx, Immediate(0xA0A09F9F));
2545 __ j(not_equal, &exit);
2546 __ incq(rax);
2547
2548 __ movl(rdx, Operand(r80, -126));
2549 __ cmpl(rdx, Immediate(0x61616060));
2550 __ j(not_equal, &exit);
2551 __ incq(rax);
2552
2553 __ movl(rdx, Operand(r80, 254));
2554 __ cmpl(rdx, Immediate(0xC0C0BFBF));
2555 __ j(not_equal, &exit);
2556 __ incq(rax);
2557
2558 __ movl(rdx, Operand(r80, -254));
2559 __ cmpl(rdx, Immediate(0x41414040));
2560 __ j(not_equal, &exit);
2561 __ incq(rax);
2562
2563 // Success.
2564
2565 __ movl(rax, Immediate(0));
2566 __ bind(&exit);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002567 __ leaq(rsp, Operand(rbp, kPointerSize));
2568 __ popq(rbp);
2569 __ popq(rbx);
2570 __ popq(r14);
2571 __ popq(r13);
Steve Block8defd9f2010-07-08 12:39:36 +01002572 ExitCode(masm);
Leon Clarkef7060e22010-06-03 12:02:55 +01002573 __ ret(0);
2574
2575
2576 CodeDesc desc;
2577 masm->GetCode(&desc);
2578 // Call the function from C++.
2579 int result = FUNCTION_CAST<F0>(buffer)();
2580 CHECK_EQ(0, result);
2581}
2582
2583
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002584TEST(LoadAndStoreWithRepresentation) {
2585 // Allocate an executable page of memory.
2586 size_t actual_size;
2587 byte* buffer = static_cast<byte*>(v8::base::OS::Allocate(
2588 Assembler::kMinimalBufferSize, &actual_size, true));
2589 CHECK(buffer);
2590 Isolate* isolate = CcTest::i_isolate();
2591 HandleScope handles(isolate);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002592 MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size),
2593 v8::internal::CodeObjectRequired::kYes);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002594 MacroAssembler* masm = &assembler; // Create a pointer for the __ macro.
2595 EntryCode(masm);
2596 __ subq(rsp, Immediate(1 * kPointerSize));
2597 Label exit;
2598
2599 // Test 1.
2600 __ movq(rax, Immediate(1)); // Test number.
2601 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2602 __ movq(rcx, Immediate(-1));
2603 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::UInteger8());
2604 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2605 __ movl(rdx, Immediate(255));
2606 __ cmpq(rcx, rdx);
2607 __ j(not_equal, &exit);
2608 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::UInteger8());
2609 __ cmpq(rcx, rdx);
2610 __ j(not_equal, &exit);
2611
2612 // Test 2.
2613 __ movq(rax, Immediate(2)); // Test number.
2614 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2615 __ Set(rcx, V8_2PART_UINT64_C(0xdeadbeaf, 12345678));
2616 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::Smi());
2617 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2618 __ Set(rdx, V8_2PART_UINT64_C(0xdeadbeaf, 12345678));
2619 __ cmpq(rcx, rdx);
2620 __ j(not_equal, &exit);
2621 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::Smi());
2622 __ cmpq(rcx, rdx);
2623 __ j(not_equal, &exit);
2624
2625 // Test 3.
2626 __ movq(rax, Immediate(3)); // Test number.
2627 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2628 __ movq(rcx, Immediate(-1));
2629 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::Integer32());
2630 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2631 __ movl(rdx, Immediate(-1));
2632 __ cmpq(rcx, rdx);
2633 __ j(not_equal, &exit);
2634 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::Integer32());
2635 __ cmpq(rcx, rdx);
2636 __ j(not_equal, &exit);
2637
2638 // Test 4.
2639 __ movq(rax, Immediate(4)); // Test number.
2640 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2641 __ movl(rcx, Immediate(0x44332211));
2642 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::HeapObject());
2643 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2644 __ movl(rdx, Immediate(0x44332211));
2645 __ cmpq(rcx, rdx);
2646 __ j(not_equal, &exit);
2647 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::HeapObject());
2648 __ cmpq(rcx, rdx);
2649 __ j(not_equal, &exit);
2650
2651 // Test 5.
2652 __ movq(rax, Immediate(5)); // Test number.
2653 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2654 __ Set(rcx, V8_2PART_UINT64_C(0x12345678, deadbeaf));
2655 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::Tagged());
2656 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2657 __ Set(rdx, V8_2PART_UINT64_C(0x12345678, deadbeaf));
2658 __ cmpq(rcx, rdx);
2659 __ j(not_equal, &exit);
2660 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::Tagged());
2661 __ cmpq(rcx, rdx);
2662 __ j(not_equal, &exit);
2663
2664 // Test 6.
2665 __ movq(rax, Immediate(6)); // Test number.
2666 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2667 __ Set(rcx, V8_2PART_UINT64_C(0x11223344, 55667788));
2668 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::External());
2669 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2670 __ Set(rdx, V8_2PART_UINT64_C(0x11223344, 55667788));
2671 __ cmpq(rcx, rdx);
2672 __ j(not_equal, &exit);
2673 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::External());
2674 __ cmpq(rcx, rdx);
2675 __ j(not_equal, &exit);
2676
2677 // Test 7.
2678 __ movq(rax, Immediate(7)); // Test number.
2679 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2680 __ movq(rcx, Immediate(-1));
2681 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::Integer8());
2682 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2683 __ movl(rdx, Immediate(255));
2684 __ cmpq(rcx, rdx);
2685 __ j(not_equal, &exit);
2686 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::Integer8());
2687 __ movq(rcx, Immediate(-1));
2688 __ cmpq(rcx, rdx);
2689 __ j(not_equal, &exit);
2690
2691 // Test 8.
2692 __ movq(rax, Immediate(8)); // Test number.
2693 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2694 __ movq(rcx, Immediate(-1));
2695 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::Integer16());
2696 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2697 __ movl(rdx, Immediate(65535));
2698 __ cmpq(rcx, rdx);
2699 __ j(not_equal, &exit);
2700 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::Integer16());
2701 __ movq(rcx, Immediate(-1));
2702 __ cmpq(rcx, rdx);
2703 __ j(not_equal, &exit);
2704
2705 // Test 9.
2706 __ movq(rax, Immediate(9)); // Test number.
2707 __ movq(Operand(rsp, 0 * kPointerSize), Immediate(0));
2708 __ movq(rcx, Immediate(-1));
2709 __ Store(Operand(rsp, 0 * kPointerSize), rcx, Representation::UInteger16());
2710 __ movq(rcx, Operand(rsp, 0 * kPointerSize));
2711 __ movl(rdx, Immediate(65535));
2712 __ cmpq(rcx, rdx);
2713 __ j(not_equal, &exit);
2714 __ Load(rdx, Operand(rsp, 0 * kPointerSize), Representation::UInteger16());
2715 __ cmpq(rcx, rdx);
2716 __ j(not_equal, &exit);
2717
2718 __ xorq(rax, rax); // Success.
2719 __ bind(&exit);
2720 __ addq(rsp, Immediate(1 * kPointerSize));
2721 ExitCode(masm);
2722 __ ret(0);
2723
2724 CodeDesc desc;
2725 masm->GetCode(&desc);
2726 // Call the function from C++.
2727 int result = FUNCTION_CAST<F0>(buffer)();
2728 CHECK_EQ(0, result);
2729}
2730
Leon Clarkef7060e22010-06-03 12:02:55 +01002731
Steve Block3ce2e202009-11-05 08:53:23 +00002732#undef __