blob: 59eeed906c8f69ce5bdc3b059fc6b2c2766e3624 [file] [log] [blame]
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +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
30#include "v8.h"
31
32#include "macro-assembler.h"
33#include "factory.h"
34#include "platform.h"
35#include "serialize.h"
36#include "cctest.h"
37
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +000038using v8::internal::Assembler;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000039using v8::internal::CodeDesc;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +000040using v8::internal::Condition;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000041using v8::internal::FUNCTION_CAST;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +000042using v8::internal::HandleScope;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +000043using v8::internal::Immediate;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000044using v8::internal::Isolate;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +000045using v8::internal::Label;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000046using v8::internal::MacroAssembler;
47using v8::internal::OS;
48using v8::internal::Operand;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +000049using v8::internal::RelocInfo;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000050using v8::internal::Smi;
51using v8::internal::SmiIndex;
52using v8::internal::byte;
53using v8::internal::carry;
54using v8::internal::greater;
55using v8::internal::greater_equal;
56using v8::internal::kIntSize;
57using v8::internal::kPointerSize;
58using v8::internal::kSmiTagMask;
59using v8::internal::kSmiValueSize;
60using v8::internal::less_equal;
61using v8::internal::negative;
62using v8::internal::not_carry;
63using v8::internal::not_equal;
64using v8::internal::not_zero;
65using v8::internal::positive;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +000066using v8::internal::r11;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +000067using v8::internal::r13;
68using v8::internal::r14;
whesse@chromium.orgb08986c2011-03-14 16:13:42 +000069using v8::internal::r15;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +000070using v8::internal::r8;
71using v8::internal::r9;
72using v8::internal::rax;
73using v8::internal::rbp;
74using v8::internal::rbx;
75using v8::internal::rcx;
76using v8::internal::rdi;
77using v8::internal::rdx;
78using v8::internal::rsi;
79using v8::internal::rsp;
kmillikin@chromium.org9155e252010-05-26 13:27:57 +000080using v8::internal::times_pointer_size;
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +000081
82// Test the x64 assembler by compiling some simple functions into
83// a buffer and executing them. These tests do not initialize the
84// V8 library, create a context, or use any V8 objects.
85// The AMD64 calling convention is used, with the first five arguments
86// in RSI, RDI, RDX, RCX, R8, and R9, and floating point arguments in
87// the XMM registers. The return value is in RAX.
88// This calling convention is used on Linux, with GCC, and on Mac OS,
89// with GCC. A different convention is used on 64-bit windows.
90
91typedef int (*F0)();
92
93#define __ masm->
94
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +000095
96static void EntryCode(MacroAssembler* masm) {
97 // Smi constant register is callee save.
98 __ push(v8::internal::kSmiConstantRegister);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +000099 __ push(v8::internal::kRootRegister);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000100 __ InitializeSmiConstantRegister();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000101 __ InitializeRootRegister();
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000102}
103
104
105static void ExitCode(MacroAssembler* masm) {
106 // Return -1 if kSmiConstantRegister was clobbered during the test.
107 __ Move(rdx, Smi::FromInt(1));
108 __ cmpq(rdx, v8::internal::kSmiConstantRegister);
109 __ movq(rdx, Immediate(-1));
110 __ cmovq(not_equal, rax, rdx);
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +0000111 __ pop(v8::internal::kRootRegister);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000112 __ pop(v8::internal::kSmiConstantRegister);
113}
114
115
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000116TEST(Smi) {
117 // Check that C++ Smi operations work as expected.
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000118 int64_t test_numbers[] = {
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000119 0, 1, -1, 127, 128, -128, -129, 255, 256, -256, -257,
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000120 Smi::kMaxValue, static_cast<int64_t>(Smi::kMaxValue) + 1,
121 Smi::kMinValue, static_cast<int64_t>(Smi::kMinValue) - 1
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000122 };
123 int test_number_count = 15;
124 for (int i = 0; i < test_number_count; i++) {
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000125 int64_t number = test_numbers[i];
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000126 bool is_valid = Smi::IsValid(number);
127 bool is_in_range = number >= Smi::kMinValue && number <= Smi::kMaxValue;
128 CHECK_EQ(is_in_range, is_valid);
129 if (is_valid) {
130 Smi* smi_from_intptr = Smi::FromIntptr(number);
131 if (static_cast<int>(number) == number) { // Is a 32-bit int.
132 Smi* smi_from_int = Smi::FromInt(static_cast<int32_t>(number));
133 CHECK_EQ(smi_from_int, smi_from_intptr);
134 }
kmillikin@chromium.org13bd2942009-12-16 15:36:05 +0000135 int64_t smi_value = smi_from_intptr->value();
136 CHECK_EQ(number, smi_value);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000137 }
138 }
139}
140
141
142static void TestMoveSmi(MacroAssembler* masm, Label* exit, int id, Smi* value) {
143 __ movl(rax, Immediate(id));
144 __ Move(rcx, Smi::FromInt(0));
145 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(0)));
146 __ cmpq(rcx, rdx);
147 __ j(not_equal, exit);
148}
149
150
151// Test that we can move a Smi value literally into a register.
152TEST(SmiMove) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000153 v8::internal::V8::Initialize(NULL);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000154 // Allocate an executable page of memory.
155 size_t actual_size;
156 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
157 &actual_size,
158 true));
159 CHECK(buffer);
160 HandleScope handles;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000161 MacroAssembler assembler(Isolate::Current(),
162 buffer,
163 static_cast<int>(actual_size));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000164 MacroAssembler* masm = &assembler; // Create a pointer for the __ macro.
165 masm->set_allow_stub_calls(false);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000166 EntryCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000167 Label exit;
168
169 TestMoveSmi(masm, &exit, 1, Smi::FromInt(0));
170 TestMoveSmi(masm, &exit, 2, Smi::FromInt(127));
171 TestMoveSmi(masm, &exit, 3, Smi::FromInt(128));
172 TestMoveSmi(masm, &exit, 4, Smi::FromInt(255));
173 TestMoveSmi(masm, &exit, 5, Smi::FromInt(256));
174 TestMoveSmi(masm, &exit, 6, Smi::FromInt(Smi::kMaxValue));
175 TestMoveSmi(masm, &exit, 7, Smi::FromInt(-1));
176 TestMoveSmi(masm, &exit, 8, Smi::FromInt(-128));
177 TestMoveSmi(masm, &exit, 9, Smi::FromInt(-129));
178 TestMoveSmi(masm, &exit, 10, Smi::FromInt(-256));
179 TestMoveSmi(masm, &exit, 11, Smi::FromInt(-257));
180 TestMoveSmi(masm, &exit, 12, Smi::FromInt(Smi::kMinValue));
181
182 __ xor_(rax, rax); // Success.
183 __ bind(&exit);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000184 ExitCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000185 __ ret(0);
186
187 CodeDesc desc;
188 masm->GetCode(&desc);
189 // Call the function from C++.
190 int result = FUNCTION_CAST<F0>(buffer)();
191 CHECK_EQ(0, result);
192}
193
194
195void TestSmiCompare(MacroAssembler* masm, Label* exit, int id, int x, int y) {
196 __ Move(rcx, Smi::FromInt(x));
197 __ movq(r8, rcx);
198 __ Move(rdx, Smi::FromInt(y));
199 __ movq(r9, rdx);
200 __ SmiCompare(rcx, rdx);
201 if (x < y) {
202 __ movl(rax, Immediate(id + 1));
203 __ j(greater_equal, exit);
204 } else if (x > y) {
205 __ movl(rax, Immediate(id + 2));
206 __ j(less_equal, exit);
207 } else {
208 ASSERT_EQ(x, y);
209 __ movl(rax, Immediate(id + 3));
210 __ j(not_equal, exit);
211 }
212 __ movl(rax, Immediate(id + 4));
213 __ cmpq(rcx, r8);
214 __ j(not_equal, exit);
215 __ incq(rax);
216 __ cmpq(rdx, r9);
217 __ j(not_equal, exit);
218
219 if (x != y) {
220 __ SmiCompare(rdx, rcx);
221 if (y < x) {
222 __ movl(rax, Immediate(id + 9));
223 __ j(greater_equal, exit);
224 } else {
225 ASSERT(y > x);
226 __ movl(rax, Immediate(id + 10));
227 __ j(less_equal, exit);
228 }
229 } else {
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000230 __ cmpq(rcx, rcx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000231 __ movl(rax, Immediate(id + 11));
232 __ j(not_equal, exit);
233 __ incq(rax);
234 __ cmpq(rcx, r8);
235 __ j(not_equal, exit);
236 }
237}
238
239
240// Test that we can compare smis for equality (and more).
241TEST(SmiCompare) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000242 v8::internal::V8::Initialize(NULL);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000243 // Allocate an executable page of memory.
244 size_t actual_size;
245 byte* buffer =
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000246 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000247 &actual_size,
248 true));
249 CHECK(buffer);
250 HandleScope handles;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000251 MacroAssembler assembler(Isolate::Current(),
252 buffer,
253 static_cast<int>(actual_size));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000254
255 MacroAssembler* masm = &assembler;
256 masm->set_allow_stub_calls(false);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000257 EntryCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000258 Label exit;
259
260 TestSmiCompare(masm, &exit, 0x10, 0, 0);
261 TestSmiCompare(masm, &exit, 0x20, 0, 1);
262 TestSmiCompare(masm, &exit, 0x30, 1, 0);
263 TestSmiCompare(masm, &exit, 0x40, 1, 1);
264 TestSmiCompare(masm, &exit, 0x50, 0, -1);
265 TestSmiCompare(masm, &exit, 0x60, -1, 0);
266 TestSmiCompare(masm, &exit, 0x70, -1, -1);
267 TestSmiCompare(masm, &exit, 0x80, 0, Smi::kMinValue);
268 TestSmiCompare(masm, &exit, 0x90, Smi::kMinValue, 0);
269 TestSmiCompare(masm, &exit, 0xA0, 0, Smi::kMaxValue);
270 TestSmiCompare(masm, &exit, 0xB0, Smi::kMaxValue, 0);
271 TestSmiCompare(masm, &exit, 0xC0, -1, Smi::kMinValue);
272 TestSmiCompare(masm, &exit, 0xD0, Smi::kMinValue, -1);
273 TestSmiCompare(masm, &exit, 0xE0, -1, Smi::kMaxValue);
274 TestSmiCompare(masm, &exit, 0xF0, Smi::kMaxValue, -1);
275 TestSmiCompare(masm, &exit, 0x100, Smi::kMinValue, Smi::kMinValue);
276 TestSmiCompare(masm, &exit, 0x110, Smi::kMinValue, Smi::kMaxValue);
277 TestSmiCompare(masm, &exit, 0x120, Smi::kMaxValue, Smi::kMinValue);
278 TestSmiCompare(masm, &exit, 0x130, Smi::kMaxValue, Smi::kMaxValue);
279
280 __ xor_(rax, rax); // Success.
281 __ bind(&exit);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000282 ExitCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000283 __ ret(0);
284
285 CodeDesc desc;
286 masm->GetCode(&desc);
287 // Call the function from C++.
288 int result = FUNCTION_CAST<F0>(buffer)();
289 CHECK_EQ(0, result);
290}
291
292
293
294TEST(Integer32ToSmi) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000295 v8::internal::V8::Initialize(NULL);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000296 // Allocate an executable page of memory.
297 size_t actual_size;
298 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
299 &actual_size,
300 true));
301 CHECK(buffer);
302 HandleScope handles;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000303 MacroAssembler assembler(Isolate::Current(),
304 buffer,
305 static_cast<int>(actual_size));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000306
307 MacroAssembler* masm = &assembler;
308 masm->set_allow_stub_calls(false);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000309 EntryCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000310 Label exit;
311
312 __ movq(rax, Immediate(1)); // Test number.
313 __ movl(rcx, Immediate(0));
314 __ Integer32ToSmi(rcx, rcx);
315 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(0)));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000316 __ cmpq(rcx, rdx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000317 __ j(not_equal, &exit);
318
319 __ movq(rax, Immediate(2)); // Test number.
320 __ movl(rcx, Immediate(1024));
321 __ Integer32ToSmi(rcx, rcx);
322 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(1024)));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000323 __ cmpq(rcx, rdx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000324 __ j(not_equal, &exit);
325
326 __ movq(rax, Immediate(3)); // Test number.
327 __ movl(rcx, Immediate(-1));
328 __ Integer32ToSmi(rcx, rcx);
329 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(-1)));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000330 __ cmpq(rcx, rdx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000331 __ j(not_equal, &exit);
332
333 __ movq(rax, Immediate(4)); // Test number.
334 __ movl(rcx, Immediate(Smi::kMaxValue));
335 __ Integer32ToSmi(rcx, rcx);
336 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMaxValue)));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000337 __ cmpq(rcx, rdx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000338 __ j(not_equal, &exit);
339
340 __ movq(rax, Immediate(5)); // Test number.
341 __ movl(rcx, Immediate(Smi::kMinValue));
342 __ Integer32ToSmi(rcx, rcx);
343 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMinValue)));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000344 __ cmpq(rcx, rdx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000345 __ j(not_equal, &exit);
346
347 // Different target register.
348
349 __ movq(rax, Immediate(6)); // Test number.
350 __ movl(rcx, Immediate(0));
351 __ Integer32ToSmi(r8, rcx);
352 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(0)));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000353 __ cmpq(r8, rdx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000354 __ j(not_equal, &exit);
355
356 __ movq(rax, Immediate(7)); // Test number.
357 __ movl(rcx, Immediate(1024));
358 __ Integer32ToSmi(r8, rcx);
359 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(1024)));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000360 __ cmpq(r8, rdx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000361 __ j(not_equal, &exit);
362
363 __ movq(rax, Immediate(8)); // Test number.
364 __ movl(rcx, Immediate(-1));
365 __ Integer32ToSmi(r8, rcx);
366 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(-1)));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000367 __ cmpq(r8, rdx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000368 __ j(not_equal, &exit);
369
370 __ movq(rax, Immediate(9)); // Test number.
371 __ movl(rcx, Immediate(Smi::kMaxValue));
372 __ Integer32ToSmi(r8, rcx);
373 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMaxValue)));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000374 __ cmpq(r8, rdx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000375 __ j(not_equal, &exit);
376
377 __ movq(rax, Immediate(10)); // Test number.
378 __ movl(rcx, Immediate(Smi::kMinValue));
379 __ Integer32ToSmi(r8, rcx);
380 __ Set(rdx, reinterpret_cast<intptr_t>(Smi::FromInt(Smi::kMinValue)));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000381 __ cmpq(r8, rdx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000382 __ j(not_equal, &exit);
383
384
385 __ xor_(rax, rax); // Success.
386 __ bind(&exit);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000387 ExitCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000388 __ ret(0);
389
390 CodeDesc desc;
391 masm->GetCode(&desc);
392 // Call the function from C++.
393 int result = FUNCTION_CAST<F0>(buffer)();
394 CHECK_EQ(0, result);
395}
396
397
398void TestI64PlusConstantToSmi(MacroAssembler* masm,
399 Label* exit,
400 int id,
401 int64_t x,
402 int y) {
403 int64_t result = x + y;
404 ASSERT(Smi::IsValid(result));
405 __ movl(rax, Immediate(id));
ager@chromium.orgc4c92722009-11-18 14:12:51 +0000406 __ Move(r8, Smi::FromInt(static_cast<int>(result)));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000407 __ movq(rcx, x, RelocInfo::NONE);
408 __ movq(r11, rcx);
409 __ Integer64PlusConstantToSmi(rdx, rcx, y);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000410 __ cmpq(rdx, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000411 __ j(not_equal, exit);
412
413 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000414 __ cmpq(r11, rcx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000415 __ j(not_equal, exit);
416
417 __ incq(rax);
418 __ Integer64PlusConstantToSmi(rcx, rcx, y);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000419 __ cmpq(rcx, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000420 __ j(not_equal, exit);
421}
422
423
424TEST(Integer64PlusConstantToSmi) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000425 v8::internal::V8::Initialize(NULL);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000426 // Allocate an executable page of memory.
427 size_t actual_size;
428 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
429 &actual_size,
430 true));
431 CHECK(buffer);
432 HandleScope handles;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000433 MacroAssembler assembler(Isolate::Current(),
434 buffer,
435 static_cast<int>(actual_size));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000436
437 MacroAssembler* masm = &assembler;
438 masm->set_allow_stub_calls(false);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000439 EntryCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000440 Label exit;
441
442 int64_t twice_max = static_cast<int64_t>(Smi::kMaxValue) * 2;
443
444 TestI64PlusConstantToSmi(masm, &exit, 0x10, 0, 0);
445 TestI64PlusConstantToSmi(masm, &exit, 0x20, 0, 1);
446 TestI64PlusConstantToSmi(masm, &exit, 0x30, 1, 0);
447 TestI64PlusConstantToSmi(masm, &exit, 0x40, Smi::kMaxValue - 5, 5);
448 TestI64PlusConstantToSmi(masm, &exit, 0x50, Smi::kMinValue + 5, 5);
449 TestI64PlusConstantToSmi(masm, &exit, 0x60, twice_max, -Smi::kMaxValue);
450 TestI64PlusConstantToSmi(masm, &exit, 0x70, -twice_max, Smi::kMaxValue);
451 TestI64PlusConstantToSmi(masm, &exit, 0x80, 0, Smi::kMinValue);
452 TestI64PlusConstantToSmi(masm, &exit, 0x90, 0, Smi::kMaxValue);
453 TestI64PlusConstantToSmi(masm, &exit, 0xA0, Smi::kMinValue, 0);
454 TestI64PlusConstantToSmi(masm, &exit, 0xB0, Smi::kMaxValue, 0);
455 TestI64PlusConstantToSmi(masm, &exit, 0xC0, twice_max, Smi::kMinValue);
456
457 __ xor_(rax, rax); // Success.
458 __ bind(&exit);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000459 ExitCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000460 __ ret(0);
461
462 CodeDesc desc;
463 masm->GetCode(&desc);
464 // Call the function from C++.
465 int result = FUNCTION_CAST<F0>(buffer)();
466 CHECK_EQ(0, result);
467}
468
469
470TEST(SmiCheck) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000471 v8::internal::V8::Initialize(NULL);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000472 // Allocate an executable page of memory.
473 size_t actual_size;
474 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
475 &actual_size,
476 true));
477 CHECK(buffer);
478 HandleScope handles;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000479 MacroAssembler assembler(Isolate::Current(),
480 buffer,
481 static_cast<int>(actual_size));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000482
483 MacroAssembler* masm = &assembler;
484 masm->set_allow_stub_calls(false);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000485 EntryCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000486 Label exit;
487 Condition cond;
488
489 __ movl(rax, Immediate(1)); // Test number.
490
491 // CheckSmi
492
493 __ movl(rcx, Immediate(0));
494 __ Integer32ToSmi(rcx, rcx);
495 cond = masm->CheckSmi(rcx);
496 __ j(NegateCondition(cond), &exit);
497
498 __ incq(rax);
499 __ xor_(rcx, Immediate(kSmiTagMask));
500 cond = masm->CheckSmi(rcx);
501 __ j(cond, &exit);
502
503 __ incq(rax);
504 __ movl(rcx, Immediate(-1));
505 __ Integer32ToSmi(rcx, rcx);
506 cond = masm->CheckSmi(rcx);
507 __ j(NegateCondition(cond), &exit);
508
509 __ incq(rax);
510 __ xor_(rcx, Immediate(kSmiTagMask));
511 cond = masm->CheckSmi(rcx);
512 __ j(cond, &exit);
513
514 __ incq(rax);
515 __ movl(rcx, Immediate(Smi::kMaxValue));
516 __ Integer32ToSmi(rcx, rcx);
517 cond = masm->CheckSmi(rcx);
518 __ j(NegateCondition(cond), &exit);
519
520 __ incq(rax);
521 __ xor_(rcx, Immediate(kSmiTagMask));
522 cond = masm->CheckSmi(rcx);
523 __ j(cond, &exit);
524
525 __ incq(rax);
526 __ movl(rcx, Immediate(Smi::kMinValue));
527 __ Integer32ToSmi(rcx, rcx);
528 cond = masm->CheckSmi(rcx);
529 __ j(NegateCondition(cond), &exit);
530
531 __ incq(rax);
532 __ xor_(rcx, Immediate(kSmiTagMask));
533 cond = masm->CheckSmi(rcx);
534 __ j(cond, &exit);
535
536 // CheckPositiveSmi
537
538 __ incq(rax);
539 __ movl(rcx, Immediate(0));
540 __ Integer32ToSmi(rcx, rcx);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000541 cond = masm->CheckNonNegativeSmi(rcx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000542 __ j(NegateCondition(cond), &exit);
543
544 __ incq(rax);
545 __ xor_(rcx, Immediate(kSmiTagMask));
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000546 cond = masm->CheckNonNegativeSmi(rcx); // "zero" non-smi.
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000547 __ j(cond, &exit);
548
549 __ incq(rax);
550 __ movq(rcx, Immediate(-1));
551 __ Integer32ToSmi(rcx, rcx);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000552 cond = masm->CheckNonNegativeSmi(rcx); // Negative smis are not positive.
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000553 __ j(cond, &exit);
554
555 __ incq(rax);
556 __ movq(rcx, Immediate(Smi::kMinValue));
557 __ Integer32ToSmi(rcx, rcx);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000558 cond = masm->CheckNonNegativeSmi(rcx); // Most negative smi is not positive.
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000559 __ j(cond, &exit);
560
561 __ incq(rax);
562 __ xor_(rcx, Immediate(kSmiTagMask));
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000563 cond = masm->CheckNonNegativeSmi(rcx); // "Negative" non-smi.
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000564 __ j(cond, &exit);
565
566 __ incq(rax);
567 __ movq(rcx, Immediate(Smi::kMaxValue));
568 __ Integer32ToSmi(rcx, rcx);
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000569 cond = masm->CheckNonNegativeSmi(rcx); // Most positive smi is positive.
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000570 __ j(NegateCondition(cond), &exit);
571
572 __ incq(rax);
573 __ xor_(rcx, Immediate(kSmiTagMask));
ricow@chromium.orgeb7c1442010-10-04 08:54:21 +0000574 cond = masm->CheckNonNegativeSmi(rcx); // "Positive" non-smi.
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000575 __ j(cond, &exit);
576
577 // CheckIsMinSmi
578
579 __ incq(rax);
580 __ movq(rcx, Immediate(Smi::kMaxValue));
581 __ Integer32ToSmi(rcx, rcx);
582 cond = masm->CheckIsMinSmi(rcx);
583 __ j(cond, &exit);
584
585 __ incq(rax);
586 __ movq(rcx, Immediate(0));
587 __ Integer32ToSmi(rcx, rcx);
588 cond = masm->CheckIsMinSmi(rcx);
589 __ j(cond, &exit);
590
591 __ incq(rax);
592 __ movq(rcx, Immediate(Smi::kMinValue));
593 __ Integer32ToSmi(rcx, rcx);
594 cond = masm->CheckIsMinSmi(rcx);
595 __ j(NegateCondition(cond), &exit);
596
597 __ incq(rax);
598 __ movq(rcx, Immediate(Smi::kMinValue + 1));
599 __ Integer32ToSmi(rcx, rcx);
600 cond = masm->CheckIsMinSmi(rcx);
601 __ j(cond, &exit);
602
603 // CheckBothSmi
604
605 __ incq(rax);
606 __ movq(rcx, Immediate(Smi::kMaxValue));
607 __ Integer32ToSmi(rcx, rcx);
608 __ movq(rdx, Immediate(Smi::kMinValue));
609 __ Integer32ToSmi(rdx, rdx);
610 cond = masm->CheckBothSmi(rcx, rdx);
611 __ j(NegateCondition(cond), &exit);
612
613 __ incq(rax);
614 __ xor_(rcx, Immediate(kSmiTagMask));
615 cond = masm->CheckBothSmi(rcx, rdx);
616 __ j(cond, &exit);
617
618 __ incq(rax);
619 __ xor_(rdx, Immediate(kSmiTagMask));
620 cond = masm->CheckBothSmi(rcx, rdx);
621 __ j(cond, &exit);
622
623 __ incq(rax);
624 __ xor_(rcx, Immediate(kSmiTagMask));
625 cond = masm->CheckBothSmi(rcx, rdx);
626 __ j(cond, &exit);
627
628 __ incq(rax);
629 cond = masm->CheckBothSmi(rcx, rcx);
630 __ j(NegateCondition(cond), &exit);
631
632 __ incq(rax);
633 cond = masm->CheckBothSmi(rdx, rdx);
634 __ j(cond, &exit);
635
636 // CheckInteger32ValidSmiValue
637 __ incq(rax);
638 __ movq(rcx, Immediate(0));
639 cond = masm->CheckInteger32ValidSmiValue(rax);
640 __ j(NegateCondition(cond), &exit);
641
642 __ incq(rax);
643 __ movq(rcx, Immediate(-1));
644 cond = masm->CheckInteger32ValidSmiValue(rax);
645 __ j(NegateCondition(cond), &exit);
646
647 __ incq(rax);
648 __ movq(rcx, Immediate(Smi::kMaxValue));
649 cond = masm->CheckInteger32ValidSmiValue(rax);
650 __ j(NegateCondition(cond), &exit);
651
652 __ incq(rax);
653 __ movq(rcx, Immediate(Smi::kMinValue));
654 cond = masm->CheckInteger32ValidSmiValue(rax);
655 __ j(NegateCondition(cond), &exit);
656
657 // Success
658 __ xor_(rax, rax);
659
660 __ bind(&exit);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000661 ExitCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000662 __ ret(0);
663
664 CodeDesc desc;
665 masm->GetCode(&desc);
666 // Call the function from C++.
667 int result = FUNCTION_CAST<F0>(buffer)();
668 CHECK_EQ(0, result);
669}
670
671
672
673void TestSmiNeg(MacroAssembler* masm, Label* exit, int id, int x) {
674 __ Move(rcx, Smi::FromInt(x));
675 __ movq(r11, rcx);
676 if (x == Smi::kMinValue || x == 0) {
677 // Negation fails.
678 __ movl(rax, Immediate(id + 8));
679 __ SmiNeg(r9, rcx, exit);
680
681 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000682 __ cmpq(r11, rcx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000683 __ j(not_equal, exit);
684
685 __ incq(rax);
686 __ SmiNeg(rcx, rcx, exit);
687
688 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000689 __ cmpq(r11, rcx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000690 __ j(not_equal, exit);
691 } else {
692 Label smi_ok, smi_ok2;
693 int result = -x;
694 __ movl(rax, Immediate(id));
695 __ Move(r8, Smi::FromInt(result));
696
697 __ SmiNeg(r9, rcx, &smi_ok);
698 __ jmp(exit);
699 __ bind(&smi_ok);
700 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000701 __ cmpq(r9, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000702 __ j(not_equal, exit);
703
704 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000705 __ cmpq(r11, rcx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000706 __ j(not_equal, exit);
707
708 __ incq(rax);
709 __ SmiNeg(rcx, rcx, &smi_ok2);
710 __ jmp(exit);
711 __ bind(&smi_ok2);
712 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000713 __ cmpq(rcx, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000714 __ j(not_equal, exit);
715 }
716}
717
718
719TEST(SmiNeg) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000720 v8::internal::V8::Initialize(NULL);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000721 // Allocate an executable page of memory.
722 size_t actual_size;
723 byte* buffer =
724 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
725 &actual_size,
726 true));
727 CHECK(buffer);
728 HandleScope handles;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000729 MacroAssembler assembler(Isolate::Current(),
730 buffer,
731 static_cast<int>(actual_size));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000732
733 MacroAssembler* masm = &assembler;
734 masm->set_allow_stub_calls(false);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000735 EntryCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000736 Label exit;
737
738 TestSmiNeg(masm, &exit, 0x10, 0);
739 TestSmiNeg(masm, &exit, 0x20, 1);
740 TestSmiNeg(masm, &exit, 0x30, -1);
741 TestSmiNeg(masm, &exit, 0x40, 127);
742 TestSmiNeg(masm, &exit, 0x50, 65535);
743 TestSmiNeg(masm, &exit, 0x60, Smi::kMinValue);
744 TestSmiNeg(masm, &exit, 0x70, Smi::kMaxValue);
745 TestSmiNeg(masm, &exit, 0x80, -Smi::kMaxValue);
746
747 __ xor_(rax, rax); // Success.
748 __ bind(&exit);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000749 ExitCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000750 __ ret(0);
751
752 CodeDesc desc;
753 masm->GetCode(&desc);
754 // Call the function from C++.
755 int result = FUNCTION_CAST<F0>(buffer)();
756 CHECK_EQ(0, result);
757}
758
759
760
761
762static void SmiAddTest(MacroAssembler* masm,
763 Label* exit,
764 int id,
765 int first,
766 int second) {
767 __ movl(rcx, Immediate(first));
768 __ Integer32ToSmi(rcx, rcx);
769 __ movl(rdx, Immediate(second));
770 __ Integer32ToSmi(rdx, rdx);
771 __ movl(r8, Immediate(first + second));
772 __ Integer32ToSmi(r8, r8);
773
774 __ movl(rax, Immediate(id)); // Test number.
775 __ SmiAdd(r9, rcx, rdx, exit);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000776 __ cmpq(r9, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000777 __ j(not_equal, exit);
778
779 __ incq(rax);
780 __ SmiAdd(rcx, rcx, rdx, exit); \
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000781 __ cmpq(rcx, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000782 __ j(not_equal, exit);
783
784 __ movl(rcx, Immediate(first));
785 __ Integer32ToSmi(rcx, rcx);
786
787 __ incq(rax);
788 __ SmiAddConstant(r9, rcx, Smi::FromInt(second));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000789 __ cmpq(r9, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000790 __ j(not_equal, exit);
791
792 __ SmiAddConstant(rcx, rcx, Smi::FromInt(second));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000793 __ cmpq(rcx, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000794 __ j(not_equal, exit);
795
796 __ movl(rcx, Immediate(first));
797 __ Integer32ToSmi(rcx, rcx);
798
799 __ incq(rax);
800 __ SmiAddConstant(r9, rcx, Smi::FromInt(second), exit);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000801 __ cmpq(r9, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000802 __ j(not_equal, exit);
803
804 __ incq(rax);
805 __ SmiAddConstant(rcx, rcx, Smi::FromInt(second), exit);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000806 __ cmpq(rcx, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000807 __ j(not_equal, exit);
808}
809
810TEST(SmiAdd) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000811 v8::internal::V8::Initialize(NULL);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000812 // Allocate an executable page of memory.
813 size_t actual_size;
814 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
815 &actual_size,
816 true));
817 CHECK(buffer);
818 HandleScope handles;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +0000819 MacroAssembler assembler(Isolate::Current(),
820 buffer,
821 static_cast<int>(actual_size));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000822
823 MacroAssembler* masm = &assembler;
824 masm->set_allow_stub_calls(false);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000825 EntryCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000826 Label exit;
827
828 // No-overflow tests.
829 SmiAddTest(masm, &exit, 0x10, 1, 2);
830 SmiAddTest(masm, &exit, 0x20, 1, -2);
831 SmiAddTest(masm, &exit, 0x30, -1, 2);
832 SmiAddTest(masm, &exit, 0x40, -1, -2);
833 SmiAddTest(masm, &exit, 0x50, 0x1000, 0x2000);
834 SmiAddTest(masm, &exit, 0x60, Smi::kMinValue, 5);
835 SmiAddTest(masm, &exit, 0x70, Smi::kMaxValue, -5);
836 SmiAddTest(masm, &exit, 0x80, Smi::kMaxValue, Smi::kMinValue);
837
838 __ xor_(rax, rax); // Success.
839 __ bind(&exit);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +0000840 ExitCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000841 __ ret(0);
842
843 CodeDesc desc;
844 masm->GetCode(&desc);
845 // Call the function from C++.
846 int result = FUNCTION_CAST<F0>(buffer)();
847 CHECK_EQ(0, result);
848}
849
850
851static void SmiSubTest(MacroAssembler* masm,
852 Label* exit,
853 int id,
854 int first,
855 int second) {
856 __ Move(rcx, Smi::FromInt(first));
857 __ Move(rdx, Smi::FromInt(second));
858 __ Move(r8, Smi::FromInt(first - second));
859
860 __ movl(rax, Immediate(id)); // Test 0.
861 __ SmiSub(r9, rcx, rdx, exit);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000862 __ cmpq(r9, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000863 __ j(not_equal, exit);
864
865 __ incq(rax); // Test 1.
866 __ SmiSub(rcx, rcx, rdx, exit);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000867 __ cmpq(rcx, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000868 __ j(not_equal, exit);
869
870 __ Move(rcx, Smi::FromInt(first));
871
872 __ incq(rax); // Test 2.
873 __ SmiSubConstant(r9, rcx, Smi::FromInt(second));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000874 __ cmpq(r9, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000875 __ j(not_equal, exit);
876
877 __ incq(rax); // Test 3.
878 __ SmiSubConstant(rcx, rcx, Smi::FromInt(second));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000879 __ cmpq(rcx, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000880 __ j(not_equal, exit);
881
882 __ Move(rcx, Smi::FromInt(first));
883
884 __ incq(rax); // Test 4.
885 __ SmiSubConstant(r9, rcx, Smi::FromInt(second), exit);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000886 __ cmpq(r9, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000887 __ j(not_equal, exit);
888
889 __ incq(rax); // Test 5.
890 __ SmiSubConstant(rcx, rcx, Smi::FromInt(second), exit);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000891 __ cmpq(rcx, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000892 __ j(not_equal, exit);
893}
894
895static void SmiSubOverflowTest(MacroAssembler* masm,
896 Label* exit,
897 int id,
898 int x) {
899 // Subtracts a Smi from x so that the subtraction overflows.
900 ASSERT(x != -1); // Can't overflow by subtracting a Smi.
901 int y_max = (x < 0) ? (Smi::kMaxValue + 0) : (Smi::kMinValue + 0);
902 int y_min = (x < 0) ? (Smi::kMaxValue + x + 2) : (Smi::kMinValue + x);
903
904 __ movl(rax, Immediate(id));
905 __ Move(rcx, Smi::FromInt(x));
906 __ movq(r11, rcx); // Store original Smi value of x in r11.
907 __ Move(rdx, Smi::FromInt(y_min));
908 {
909 Label overflow_ok;
910 __ SmiSub(r9, rcx, rdx, &overflow_ok);
911 __ jmp(exit);
912 __ bind(&overflow_ok);
913 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000914 __ cmpq(rcx, r11);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000915 __ j(not_equal, exit);
916 }
917
918 {
919 Label overflow_ok;
920 __ incq(rax);
921 __ SmiSub(rcx, rcx, rdx, &overflow_ok);
922 __ jmp(exit);
923 __ bind(&overflow_ok);
924 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000925 __ cmpq(rcx, r11);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000926 __ j(not_equal, exit);
927 }
928
929 __ movq(rcx, r11);
930 {
931 Label overflow_ok;
932 __ incq(rax);
933 __ SmiSubConstant(r9, rcx, Smi::FromInt(y_min), &overflow_ok);
934 __ jmp(exit);
935 __ bind(&overflow_ok);
936 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000937 __ cmpq(rcx, r11);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000938 __ j(not_equal, exit);
939 }
940
941 {
942 Label overflow_ok;
943 __ incq(rax);
944 __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_min), &overflow_ok);
945 __ jmp(exit);
946 __ bind(&overflow_ok);
947 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000948 __ cmpq(rcx, r11);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000949 __ j(not_equal, exit);
950 }
951
952 __ Move(rdx, Smi::FromInt(y_max));
953
954 {
955 Label overflow_ok;
956 __ incq(rax);
957 __ SmiSub(r9, rcx, rdx, &overflow_ok);
958 __ jmp(exit);
959 __ bind(&overflow_ok);
960 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000961 __ cmpq(rcx, r11);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000962 __ j(not_equal, exit);
963 }
964
965 {
966 Label overflow_ok;
967 __ incq(rax);
968 __ SmiSub(rcx, rcx, rdx, &overflow_ok);
969 __ jmp(exit);
970 __ bind(&overflow_ok);
971 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000972 __ cmpq(rcx, r11);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000973 __ j(not_equal, exit);
974 }
975
976 __ movq(rcx, r11);
977 {
978 Label overflow_ok;
979 __ incq(rax);
980 __ SmiSubConstant(r9, rcx, Smi::FromInt(y_max), &overflow_ok);
981 __ jmp(exit);
982 __ bind(&overflow_ok);
983 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000984 __ cmpq(rcx, r11);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000985 __ j(not_equal, exit);
986 }
987
988 {
989 Label overflow_ok;
990 __ incq(rax);
991 __ SmiSubConstant(rcx, rcx, Smi::FromInt(y_max), &overflow_ok);
992 __ jmp(exit);
993 __ bind(&overflow_ok);
994 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +0000995 __ cmpq(rcx, r11);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +0000996 __ j(not_equal, exit);
997 }
998}
999
1000
1001TEST(SmiSub) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001002 v8::internal::V8::Initialize(NULL);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001003 // Allocate an executable page of memory.
1004 size_t actual_size;
1005 byte* buffer =
1006 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
1007 &actual_size,
1008 true));
1009 CHECK(buffer);
1010 HandleScope handles;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001011 MacroAssembler assembler(Isolate::Current(),
1012 buffer,
1013 static_cast<int>(actual_size));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001014
1015 MacroAssembler* masm = &assembler;
1016 masm->set_allow_stub_calls(false);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001017 EntryCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001018 Label exit;
1019
1020 SmiSubTest(masm, &exit, 0x10, 1, 2);
1021 SmiSubTest(masm, &exit, 0x20, 1, -2);
1022 SmiSubTest(masm, &exit, 0x30, -1, 2);
1023 SmiSubTest(masm, &exit, 0x40, -1, -2);
1024 SmiSubTest(masm, &exit, 0x50, 0x1000, 0x2000);
1025 SmiSubTest(masm, &exit, 0x60, Smi::kMinValue, -5);
1026 SmiSubTest(masm, &exit, 0x70, Smi::kMaxValue, 5);
1027 SmiSubTest(masm, &exit, 0x80, -Smi::kMaxValue, Smi::kMinValue);
1028 SmiSubTest(masm, &exit, 0x90, 0, Smi::kMaxValue);
1029
1030 SmiSubOverflowTest(masm, &exit, 0xA0, 1);
1031 SmiSubOverflowTest(masm, &exit, 0xB0, 1024);
1032 SmiSubOverflowTest(masm, &exit, 0xC0, Smi::kMaxValue);
1033 SmiSubOverflowTest(masm, &exit, 0xD0, -2);
1034 SmiSubOverflowTest(masm, &exit, 0xE0, -42000);
1035 SmiSubOverflowTest(masm, &exit, 0xF0, Smi::kMinValue);
1036 SmiSubOverflowTest(masm, &exit, 0x100, 0);
1037
1038 __ xor_(rax, rax); // Success.
1039 __ bind(&exit);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001040 ExitCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001041 __ ret(0);
1042
1043 CodeDesc desc;
1044 masm->GetCode(&desc);
1045 // Call the function from C++.
1046 int result = FUNCTION_CAST<F0>(buffer)();
1047 CHECK_EQ(0, result);
1048}
1049
1050
1051
1052void TestSmiMul(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1053 int64_t result = static_cast<int64_t>(x) * static_cast<int64_t>(y);
1054 bool negative_zero = (result == 0) && (x < 0 || y < 0);
1055 __ Move(rcx, Smi::FromInt(x));
1056 __ movq(r11, rcx);
1057 __ Move(rdx, Smi::FromInt(y));
1058 if (Smi::IsValid(result) && !negative_zero) {
1059 __ movl(rax, Immediate(id));
1060 __ Move(r8, Smi::FromIntptr(result));
1061 __ SmiMul(r9, rcx, rdx, exit);
1062 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001063 __ cmpq(r11, rcx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001064 __ j(not_equal, exit);
1065 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001066 __ cmpq(r9, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001067 __ j(not_equal, exit);
1068
1069 __ incq(rax);
1070 __ SmiMul(rcx, rcx, rdx, exit);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001071 __ cmpq(rcx, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001072 __ j(not_equal, exit);
1073 } else {
1074 __ movl(rax, Immediate(id + 8));
1075 Label overflow_ok, overflow_ok2;
1076 __ SmiMul(r9, rcx, rdx, &overflow_ok);
1077 __ jmp(exit);
1078 __ bind(&overflow_ok);
1079 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001080 __ cmpq(r11, rcx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001081 __ j(not_equal, exit);
1082 __ incq(rax);
1083 __ SmiMul(rcx, rcx, rdx, &overflow_ok2);
1084 __ jmp(exit);
1085 __ bind(&overflow_ok2);
1086 // 31-bit version doesn't preserve rcx on failure.
1087 // __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001088 // __ cmpq(r11, rcx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001089 // __ j(not_equal, exit);
1090 }
1091}
1092
1093
1094TEST(SmiMul) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001095 v8::internal::V8::Initialize(NULL);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001096 // Allocate an executable page of memory.
1097 size_t actual_size;
1098 byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
1099 &actual_size,
1100 true));
1101 CHECK(buffer);
1102 HandleScope handles;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001103 MacroAssembler assembler(Isolate::Current(),
1104 buffer,
1105 static_cast<int>(actual_size));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001106
1107 MacroAssembler* masm = &assembler;
1108 masm->set_allow_stub_calls(false);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001109 EntryCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001110 Label exit;
1111
1112 TestSmiMul(masm, &exit, 0x10, 0, 0);
1113 TestSmiMul(masm, &exit, 0x20, -1, 0);
1114 TestSmiMul(masm, &exit, 0x30, 0, -1);
1115 TestSmiMul(masm, &exit, 0x40, -1, -1);
1116 TestSmiMul(masm, &exit, 0x50, 0x10000, 0x10000);
1117 TestSmiMul(masm, &exit, 0x60, 0x10000, 0xffff);
1118 TestSmiMul(masm, &exit, 0x70, 0x10000, 0xffff);
1119 TestSmiMul(masm, &exit, 0x80, Smi::kMaxValue, -1);
1120 TestSmiMul(masm, &exit, 0x90, Smi::kMaxValue, -2);
1121 TestSmiMul(masm, &exit, 0xa0, Smi::kMaxValue, 2);
1122 TestSmiMul(masm, &exit, 0xb0, (Smi::kMaxValue / 2), 2);
1123 TestSmiMul(masm, &exit, 0xc0, (Smi::kMaxValue / 2) + 1, 2);
1124 TestSmiMul(masm, &exit, 0xd0, (Smi::kMinValue / 2), 2);
1125 TestSmiMul(masm, &exit, 0xe0, (Smi::kMinValue / 2) - 1, 2);
1126
1127 __ xor_(rax, rax); // Success.
1128 __ bind(&exit);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001129 ExitCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001130 __ ret(0);
1131
1132 CodeDesc desc;
1133 masm->GetCode(&desc);
1134 // Call the function from C++.
1135 int result = FUNCTION_CAST<F0>(buffer)();
1136 CHECK_EQ(0, result);
1137}
1138
1139
1140void TestSmiDiv(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1141 bool division_by_zero = (y == 0);
1142 bool negative_zero = (x == 0 && y < 0);
1143#ifdef V8_TARGET_ARCH_X64
1144 bool overflow = (x == Smi::kMinValue && y < 0); // Safe approx. used.
1145#else
1146 bool overflow = (x == Smi::kMinValue && y == -1);
1147#endif
1148 bool fraction = !division_by_zero && !overflow && (x % y != 0);
1149 __ Move(r11, Smi::FromInt(x));
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001150 __ Move(r14, Smi::FromInt(y));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001151 if (!fraction && !overflow && !negative_zero && !division_by_zero) {
1152 // Division succeeds
1153 __ movq(rcx, r11);
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001154 __ movq(r15, Immediate(id));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001155 int result = x / y;
1156 __ Move(r8, Smi::FromInt(result));
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001157 __ SmiDiv(r9, rcx, r14, exit);
1158 // Might have destroyed rcx and r14.
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001159 __ incq(r15);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001160 __ cmpq(r9, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001161 __ j(not_equal, exit);
1162
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001163 __ incq(r15);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001164 __ movq(rcx, r11);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001165 __ Move(r14, Smi::FromInt(y));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001166 __ cmpq(rcx, r11);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001167 __ j(not_equal, exit);
1168
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001169 __ incq(r15);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001170 __ SmiDiv(rcx, rcx, r14, exit);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001171
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001172 __ incq(r15);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001173 __ cmpq(rcx, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001174 __ j(not_equal, exit);
1175 } else {
1176 // Division fails.
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001177 __ movq(r15, Immediate(id + 8));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001178
1179 Label fail_ok, fail_ok2;
1180 __ movq(rcx, r11);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001181 __ SmiDiv(r9, rcx, r14, &fail_ok);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001182 __ jmp(exit);
1183 __ bind(&fail_ok);
1184
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001185 __ incq(r15);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001186 __ cmpq(rcx, r11);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001187 __ j(not_equal, exit);
1188
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001189 __ incq(r15);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001190 __ SmiDiv(rcx, rcx, r14, &fail_ok2);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001191 __ jmp(exit);
1192 __ bind(&fail_ok2);
1193
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001194 __ incq(r15);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001195 __ cmpq(rcx, r11);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001196 __ j(not_equal, exit);
1197 }
1198}
1199
1200
1201TEST(SmiDiv) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001202 v8::internal::V8::Initialize(NULL);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001203 // Allocate an executable page of memory.
1204 size_t actual_size;
1205 byte* buffer =
1206 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
1207 &actual_size,
1208 true));
1209 CHECK(buffer);
1210 HandleScope handles;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001211 MacroAssembler assembler(Isolate::Current(),
1212 buffer,
1213 static_cast<int>(actual_size));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001214
1215 MacroAssembler* masm = &assembler;
1216 masm->set_allow_stub_calls(false);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001217 EntryCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001218 Label exit;
1219
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001220 __ push(r14);
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001221 __ push(r15);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001222 TestSmiDiv(masm, &exit, 0x10, 1, 1);
1223 TestSmiDiv(masm, &exit, 0x20, 1, 0);
1224 TestSmiDiv(masm, &exit, 0x30, -1, 0);
1225 TestSmiDiv(masm, &exit, 0x40, 0, 1);
1226 TestSmiDiv(masm, &exit, 0x50, 0, -1);
1227 TestSmiDiv(masm, &exit, 0x60, 4, 2);
1228 TestSmiDiv(masm, &exit, 0x70, -4, 2);
1229 TestSmiDiv(masm, &exit, 0x80, 4, -2);
1230 TestSmiDiv(masm, &exit, 0x90, -4, -2);
1231 TestSmiDiv(masm, &exit, 0xa0, 3, 2);
1232 TestSmiDiv(masm, &exit, 0xb0, 3, 4);
1233 TestSmiDiv(masm, &exit, 0xc0, 1, Smi::kMaxValue);
1234 TestSmiDiv(masm, &exit, 0xd0, -1, Smi::kMaxValue);
1235 TestSmiDiv(masm, &exit, 0xe0, Smi::kMaxValue, 1);
1236 TestSmiDiv(masm, &exit, 0xf0, Smi::kMaxValue, Smi::kMaxValue);
1237 TestSmiDiv(masm, &exit, 0x100, Smi::kMaxValue, -Smi::kMaxValue);
1238 TestSmiDiv(masm, &exit, 0x110, Smi::kMaxValue, -1);
1239 TestSmiDiv(masm, &exit, 0x120, Smi::kMinValue, 1);
1240 TestSmiDiv(masm, &exit, 0x130, Smi::kMinValue, Smi::kMinValue);
1241 TestSmiDiv(masm, &exit, 0x140, Smi::kMinValue, -1);
1242
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001243 __ xor_(r15, r15); // Success.
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001244 __ bind(&exit);
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001245 __ movq(rax, r15);
1246 __ pop(r15);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001247 __ pop(r14);
1248 ExitCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001249 __ ret(0);
1250
1251 CodeDesc desc;
1252 masm->GetCode(&desc);
1253 // Call the function from C++.
1254 int result = FUNCTION_CAST<F0>(buffer)();
1255 CHECK_EQ(0, result);
1256}
1257
1258
1259void TestSmiMod(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1260 bool division_by_zero = (y == 0);
1261 bool division_overflow = (x == Smi::kMinValue) && (y == -1);
1262 bool fraction = !division_by_zero && !division_overflow && ((x % y) != 0);
1263 bool negative_zero = (!fraction && x < 0);
1264 __ Move(rcx, Smi::FromInt(x));
1265 __ movq(r11, rcx);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001266 __ Move(r14, Smi::FromInt(y));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001267 if (!division_overflow && !negative_zero && !division_by_zero) {
1268 // Modulo succeeds
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001269 __ movq(r15, Immediate(id));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001270 int result = x % y;
1271 __ Move(r8, Smi::FromInt(result));
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001272 __ SmiMod(r9, rcx, r14, exit);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001273
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001274 __ incq(r15);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001275 __ cmpq(r9, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001276 __ j(not_equal, exit);
1277
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001278 __ incq(r15);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001279 __ cmpq(rcx, r11);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001280 __ j(not_equal, exit);
1281
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001282 __ incq(r15);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001283 __ SmiMod(rcx, rcx, r14, exit);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001284
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001285 __ incq(r15);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001286 __ cmpq(rcx, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001287 __ j(not_equal, exit);
1288 } else {
1289 // Modulo fails.
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001290 __ movq(r15, Immediate(id + 8));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001291
1292 Label fail_ok, fail_ok2;
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001293 __ SmiMod(r9, rcx, r14, &fail_ok);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001294 __ jmp(exit);
1295 __ bind(&fail_ok);
1296
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001297 __ incq(r15);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001298 __ cmpq(rcx, r11);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001299 __ j(not_equal, exit);
1300
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001301 __ incq(r15);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001302 __ SmiMod(rcx, rcx, r14, &fail_ok2);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001303 __ jmp(exit);
1304 __ bind(&fail_ok2);
1305
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001306 __ incq(r15);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001307 __ cmpq(rcx, r11);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001308 __ j(not_equal, exit);
1309 }
1310}
1311
1312
1313TEST(SmiMod) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001314 v8::internal::V8::Initialize(NULL);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001315 // Allocate an executable page of memory.
1316 size_t actual_size;
1317 byte* buffer =
1318 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
1319 &actual_size,
1320 true));
1321 CHECK(buffer);
1322 HandleScope handles;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001323 MacroAssembler assembler(Isolate::Current(),
1324 buffer,
1325 static_cast<int>(actual_size));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001326
1327 MacroAssembler* masm = &assembler;
1328 masm->set_allow_stub_calls(false);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001329 EntryCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001330 Label exit;
1331
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001332 __ push(r14);
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001333 __ push(r15);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001334 TestSmiMod(masm, &exit, 0x10, 1, 1);
1335 TestSmiMod(masm, &exit, 0x20, 1, 0);
1336 TestSmiMod(masm, &exit, 0x30, -1, 0);
1337 TestSmiMod(masm, &exit, 0x40, 0, 1);
1338 TestSmiMod(masm, &exit, 0x50, 0, -1);
1339 TestSmiMod(masm, &exit, 0x60, 4, 2);
1340 TestSmiMod(masm, &exit, 0x70, -4, 2);
1341 TestSmiMod(masm, &exit, 0x80, 4, -2);
1342 TestSmiMod(masm, &exit, 0x90, -4, -2);
1343 TestSmiMod(masm, &exit, 0xa0, 3, 2);
1344 TestSmiMod(masm, &exit, 0xb0, 3, 4);
1345 TestSmiMod(masm, &exit, 0xc0, 1, Smi::kMaxValue);
1346 TestSmiMod(masm, &exit, 0xd0, -1, Smi::kMaxValue);
1347 TestSmiMod(masm, &exit, 0xe0, Smi::kMaxValue, 1);
1348 TestSmiMod(masm, &exit, 0xf0, Smi::kMaxValue, Smi::kMaxValue);
1349 TestSmiMod(masm, &exit, 0x100, Smi::kMaxValue, -Smi::kMaxValue);
1350 TestSmiMod(masm, &exit, 0x110, Smi::kMaxValue, -1);
1351 TestSmiMod(masm, &exit, 0x120, Smi::kMinValue, 1);
1352 TestSmiMod(masm, &exit, 0x130, Smi::kMinValue, Smi::kMinValue);
1353 TestSmiMod(masm, &exit, 0x140, Smi::kMinValue, -1);
1354
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001355 __ xor_(r15, r15); // Success.
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001356 __ bind(&exit);
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00001357 __ movq(rax, r15);
1358 __ pop(r15);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001359 __ pop(r14);
1360 ExitCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001361 __ ret(0);
1362
1363 CodeDesc desc;
1364 masm->GetCode(&desc);
1365 // Call the function from C++.
1366 int result = FUNCTION_CAST<F0>(buffer)();
1367 CHECK_EQ(0, result);
1368}
1369
1370
1371void TestSmiIndex(MacroAssembler* masm, Label* exit, int id, int x) {
1372 __ movl(rax, Immediate(id));
1373
1374 for (int i = 0; i < 8; i++) {
1375 __ Move(rcx, Smi::FromInt(x));
1376 SmiIndex index = masm->SmiToIndex(rdx, rcx, i);
1377 ASSERT(index.reg.is(rcx) || index.reg.is(rdx));
1378 __ shl(index.reg, Immediate(index.scale));
1379 __ Set(r8, static_cast<intptr_t>(x) << i);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001380 __ cmpq(index.reg, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001381 __ j(not_equal, exit);
1382 __ incq(rax);
1383 __ Move(rcx, Smi::FromInt(x));
1384 index = masm->SmiToIndex(rcx, rcx, i);
1385 ASSERT(index.reg.is(rcx));
1386 __ shl(rcx, Immediate(index.scale));
1387 __ Set(r8, static_cast<intptr_t>(x) << i);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001388 __ cmpq(rcx, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001389 __ j(not_equal, exit);
1390 __ incq(rax);
1391
1392 __ Move(rcx, Smi::FromInt(x));
1393 index = masm->SmiToNegativeIndex(rdx, rcx, i);
1394 ASSERT(index.reg.is(rcx) || index.reg.is(rdx));
1395 __ shl(index.reg, Immediate(index.scale));
1396 __ Set(r8, static_cast<intptr_t>(-x) << i);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001397 __ cmpq(index.reg, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001398 __ j(not_equal, exit);
1399 __ incq(rax);
1400 __ Move(rcx, Smi::FromInt(x));
1401 index = masm->SmiToNegativeIndex(rcx, rcx, i);
1402 ASSERT(index.reg.is(rcx));
1403 __ shl(rcx, Immediate(index.scale));
1404 __ Set(r8, static_cast<intptr_t>(-x) << i);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001405 __ cmpq(rcx, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001406 __ j(not_equal, exit);
1407 __ incq(rax);
1408 }
1409}
1410
1411TEST(SmiIndex) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001412 v8::internal::V8::Initialize(NULL);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001413 // Allocate an executable page of memory.
1414 size_t actual_size;
1415 byte* buffer =
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001416 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 3,
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001417 &actual_size,
1418 true));
1419 CHECK(buffer);
1420 HandleScope handles;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001421 MacroAssembler assembler(Isolate::Current(),
1422 buffer,
1423 static_cast<int>(actual_size));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001424
1425 MacroAssembler* masm = &assembler;
1426 masm->set_allow_stub_calls(false);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001427 EntryCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001428 Label exit;
1429
1430 TestSmiIndex(masm, &exit, 0x10, 0);
1431 TestSmiIndex(masm, &exit, 0x20, 1);
1432 TestSmiIndex(masm, &exit, 0x30, 100);
1433 TestSmiIndex(masm, &exit, 0x40, 1000);
1434 TestSmiIndex(masm, &exit, 0x50, Smi::kMaxValue);
1435
1436 __ xor_(rax, rax); // Success.
1437 __ bind(&exit);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001438 ExitCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001439 __ ret(0);
1440
1441 CodeDesc desc;
1442 masm->GetCode(&desc);
1443 // Call the function from C++.
1444 int result = FUNCTION_CAST<F0>(buffer)();
1445 CHECK_EQ(0, result);
1446}
1447
1448
1449void TestSelectNonSmi(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1450 __ movl(rax, Immediate(id));
1451 __ Move(rcx, Smi::FromInt(x));
1452 __ Move(rdx, Smi::FromInt(y));
1453 __ xor_(rdx, Immediate(kSmiTagMask));
1454 __ SelectNonSmi(r9, rcx, rdx, exit);
1455
1456 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001457 __ cmpq(r9, rdx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001458 __ j(not_equal, exit);
1459
1460 __ incq(rax);
1461 __ Move(rcx, Smi::FromInt(x));
1462 __ Move(rdx, Smi::FromInt(y));
1463 __ xor_(rcx, Immediate(kSmiTagMask));
1464 __ SelectNonSmi(r9, rcx, rdx, exit);
1465
1466 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001467 __ cmpq(r9, rcx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001468 __ j(not_equal, exit);
1469
1470 __ incq(rax);
1471 Label fail_ok;
1472 __ Move(rcx, Smi::FromInt(x));
1473 __ Move(rdx, Smi::FromInt(y));
1474 __ xor_(rcx, Immediate(kSmiTagMask));
1475 __ xor_(rdx, Immediate(kSmiTagMask));
1476 __ SelectNonSmi(r9, rcx, rdx, &fail_ok);
1477 __ jmp(exit);
1478 __ bind(&fail_ok);
1479}
1480
1481
1482TEST(SmiSelectNonSmi) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001483 v8::internal::V8::Initialize(NULL);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001484 // Allocate an executable page of memory.
1485 size_t actual_size;
1486 byte* buffer =
1487 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
1488 &actual_size,
1489 true));
1490 CHECK(buffer);
1491 HandleScope handles;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001492 MacroAssembler assembler(Isolate::Current(),
1493 buffer,
1494 static_cast<int>(actual_size));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001495
1496 MacroAssembler* masm = &assembler;
1497 masm->set_allow_stub_calls(false); // Avoid inline checks.
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001498 EntryCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001499 Label exit;
1500
1501 TestSelectNonSmi(masm, &exit, 0x10, 0, 0);
1502 TestSelectNonSmi(masm, &exit, 0x20, 0, 1);
1503 TestSelectNonSmi(masm, &exit, 0x30, 1, 0);
1504 TestSelectNonSmi(masm, &exit, 0x40, 0, -1);
1505 TestSelectNonSmi(masm, &exit, 0x50, -1, 0);
1506 TestSelectNonSmi(masm, &exit, 0x60, -1, -1);
1507 TestSelectNonSmi(masm, &exit, 0x70, 1, 1);
1508 TestSelectNonSmi(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
1509 TestSelectNonSmi(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
1510
1511 __ xor_(rax, rax); // Success.
1512 __ bind(&exit);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001513 ExitCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001514 __ ret(0);
1515
1516 CodeDesc desc;
1517 masm->GetCode(&desc);
1518 // Call the function from C++.
1519 int result = FUNCTION_CAST<F0>(buffer)();
1520 CHECK_EQ(0, result);
1521}
1522
1523
1524void TestSmiAnd(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1525 int result = x & y;
1526
1527 __ movl(rax, Immediate(id));
1528
1529 __ Move(rcx, Smi::FromInt(x));
1530 __ movq(r11, rcx);
1531 __ Move(rdx, Smi::FromInt(y));
1532 __ Move(r8, Smi::FromInt(result));
1533 __ SmiAnd(r9, rcx, rdx);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001534 __ cmpq(r8, r9);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001535 __ j(not_equal, exit);
1536
1537 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001538 __ cmpq(r11, rcx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001539 __ j(not_equal, exit);
1540
1541 __ incq(rax);
1542 __ SmiAnd(rcx, rcx, rdx);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001543 __ cmpq(r8, rcx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001544 __ j(not_equal, exit);
1545
1546 __ movq(rcx, r11);
1547 __ incq(rax);
1548 __ SmiAndConstant(r9, rcx, Smi::FromInt(y));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001549 __ cmpq(r8, r9);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001550 __ j(not_equal, exit);
1551
1552 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001553 __ cmpq(r11, rcx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001554 __ j(not_equal, exit);
1555
1556 __ incq(rax);
1557 __ SmiAndConstant(rcx, rcx, Smi::FromInt(y));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001558 __ cmpq(r8, rcx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001559 __ j(not_equal, exit);
1560}
1561
1562
1563TEST(SmiAnd) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001564 v8::internal::V8::Initialize(NULL);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001565 // Allocate an executable page of memory.
1566 size_t actual_size;
1567 byte* buffer =
1568 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
1569 &actual_size,
1570 true));
1571 CHECK(buffer);
1572 HandleScope handles;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001573 MacroAssembler assembler(Isolate::Current(),
1574 buffer,
1575 static_cast<int>(actual_size));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001576
1577 MacroAssembler* masm = &assembler;
1578 masm->set_allow_stub_calls(false);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001579 EntryCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001580 Label exit;
1581
1582 TestSmiAnd(masm, &exit, 0x10, 0, 0);
1583 TestSmiAnd(masm, &exit, 0x20, 0, 1);
1584 TestSmiAnd(masm, &exit, 0x30, 1, 0);
1585 TestSmiAnd(masm, &exit, 0x40, 0, -1);
1586 TestSmiAnd(masm, &exit, 0x50, -1, 0);
1587 TestSmiAnd(masm, &exit, 0x60, -1, -1);
1588 TestSmiAnd(masm, &exit, 0x70, 1, 1);
1589 TestSmiAnd(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
1590 TestSmiAnd(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
1591 TestSmiAnd(masm, &exit, 0xA0, Smi::kMinValue, -1);
1592 TestSmiAnd(masm, &exit, 0xB0, Smi::kMinValue, -1);
1593
1594 __ xor_(rax, rax); // Success.
1595 __ bind(&exit);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001596 ExitCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001597 __ ret(0);
1598
1599 CodeDesc desc;
1600 masm->GetCode(&desc);
1601 // Call the function from C++.
1602 int result = FUNCTION_CAST<F0>(buffer)();
1603 CHECK_EQ(0, result);
1604}
1605
1606
1607void TestSmiOr(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1608 int result = x | y;
1609
1610 __ movl(rax, Immediate(id));
1611
1612 __ Move(rcx, Smi::FromInt(x));
1613 __ movq(r11, rcx);
1614 __ Move(rdx, Smi::FromInt(y));
1615 __ Move(r8, Smi::FromInt(result));
1616 __ SmiOr(r9, rcx, rdx);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001617 __ cmpq(r8, r9);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001618 __ j(not_equal, exit);
1619
1620 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001621 __ cmpq(r11, rcx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001622 __ j(not_equal, exit);
1623
1624 __ incq(rax);
1625 __ SmiOr(rcx, rcx, rdx);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001626 __ cmpq(r8, rcx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001627 __ j(not_equal, exit);
1628
1629 __ movq(rcx, r11);
1630 __ incq(rax);
1631 __ SmiOrConstant(r9, rcx, Smi::FromInt(y));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001632 __ cmpq(r8, r9);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001633 __ j(not_equal, exit);
1634
1635 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001636 __ cmpq(r11, rcx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001637 __ j(not_equal, exit);
1638
1639 __ incq(rax);
1640 __ SmiOrConstant(rcx, rcx, Smi::FromInt(y));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001641 __ cmpq(r8, rcx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001642 __ j(not_equal, exit);
1643}
1644
1645
1646TEST(SmiOr) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001647 v8::internal::V8::Initialize(NULL);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001648 // Allocate an executable page of memory.
1649 size_t actual_size;
1650 byte* buffer =
1651 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
1652 &actual_size,
1653 true));
1654 CHECK(buffer);
1655 HandleScope handles;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001656 MacroAssembler assembler(Isolate::Current(),
1657 buffer,
1658 static_cast<int>(actual_size));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001659
1660 MacroAssembler* masm = &assembler;
1661 masm->set_allow_stub_calls(false);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001662 EntryCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001663 Label exit;
1664
1665 TestSmiOr(masm, &exit, 0x10, 0, 0);
1666 TestSmiOr(masm, &exit, 0x20, 0, 1);
1667 TestSmiOr(masm, &exit, 0x30, 1, 0);
1668 TestSmiOr(masm, &exit, 0x40, 0, -1);
1669 TestSmiOr(masm, &exit, 0x50, -1, 0);
1670 TestSmiOr(masm, &exit, 0x60, -1, -1);
1671 TestSmiOr(masm, &exit, 0x70, 1, 1);
1672 TestSmiOr(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
1673 TestSmiOr(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
1674 TestSmiOr(masm, &exit, 0xA0, Smi::kMinValue, -1);
1675 TestSmiOr(masm, &exit, 0xB0, 0x05555555, 0x01234567);
1676 TestSmiOr(masm, &exit, 0xC0, 0x05555555, 0x0fedcba9);
1677 TestSmiOr(masm, &exit, 0xD0, Smi::kMinValue, -1);
1678
1679 __ xor_(rax, rax); // Success.
1680 __ bind(&exit);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001681 ExitCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001682 __ ret(0);
1683
1684 CodeDesc desc;
1685 masm->GetCode(&desc);
1686 // Call the function from C++.
1687 int result = FUNCTION_CAST<F0>(buffer)();
1688 CHECK_EQ(0, result);
1689}
1690
1691
1692void TestSmiXor(MacroAssembler* masm, Label* exit, int id, int x, int y) {
1693 int result = x ^ y;
1694
1695 __ movl(rax, Immediate(id));
1696
1697 __ Move(rcx, Smi::FromInt(x));
1698 __ movq(r11, rcx);
1699 __ Move(rdx, Smi::FromInt(y));
1700 __ Move(r8, Smi::FromInt(result));
1701 __ SmiXor(r9, rcx, rdx);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001702 __ cmpq(r8, r9);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001703 __ j(not_equal, exit);
1704
1705 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001706 __ cmpq(r11, rcx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001707 __ j(not_equal, exit);
1708
1709 __ incq(rax);
1710 __ SmiXor(rcx, rcx, rdx);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001711 __ cmpq(r8, rcx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001712 __ j(not_equal, exit);
1713
1714 __ movq(rcx, r11);
1715 __ incq(rax);
1716 __ SmiXorConstant(r9, rcx, Smi::FromInt(y));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001717 __ cmpq(r8, r9);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001718 __ j(not_equal, exit);
1719
1720 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001721 __ cmpq(r11, rcx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001722 __ j(not_equal, exit);
1723
1724 __ incq(rax);
1725 __ SmiXorConstant(rcx, rcx, Smi::FromInt(y));
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001726 __ cmpq(r8, rcx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001727 __ j(not_equal, exit);
1728}
1729
1730
1731TEST(SmiXor) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001732 v8::internal::V8::Initialize(NULL);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001733 // Allocate an executable page of memory.
1734 size_t actual_size;
1735 byte* buffer =
1736 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
1737 &actual_size,
1738 true));
1739 CHECK(buffer);
1740 HandleScope handles;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001741 MacroAssembler assembler(Isolate::Current(),
1742 buffer,
1743 static_cast<int>(actual_size));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001744
1745 MacroAssembler* masm = &assembler;
1746 masm->set_allow_stub_calls(false);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001747 EntryCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001748 Label exit;
1749
1750 TestSmiXor(masm, &exit, 0x10, 0, 0);
1751 TestSmiXor(masm, &exit, 0x20, 0, 1);
1752 TestSmiXor(masm, &exit, 0x30, 1, 0);
1753 TestSmiXor(masm, &exit, 0x40, 0, -1);
1754 TestSmiXor(masm, &exit, 0x50, -1, 0);
1755 TestSmiXor(masm, &exit, 0x60, -1, -1);
1756 TestSmiXor(masm, &exit, 0x70, 1, 1);
1757 TestSmiXor(masm, &exit, 0x80, Smi::kMinValue, Smi::kMaxValue);
1758 TestSmiXor(masm, &exit, 0x90, Smi::kMinValue, Smi::kMinValue);
1759 TestSmiXor(masm, &exit, 0xA0, Smi::kMinValue, -1);
1760 TestSmiXor(masm, &exit, 0xB0, 0x5555555, 0x01234567);
1761 TestSmiXor(masm, &exit, 0xC0, 0x5555555, 0x0fedcba9);
1762 TestSmiXor(masm, &exit, 0xD0, Smi::kMinValue, -1);
1763
1764 __ xor_(rax, rax); // Success.
1765 __ bind(&exit);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001766 ExitCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001767 __ ret(0);
1768
1769 CodeDesc desc;
1770 masm->GetCode(&desc);
1771 // Call the function from C++.
1772 int result = FUNCTION_CAST<F0>(buffer)();
1773 CHECK_EQ(0, result);
1774}
1775
1776
1777void TestSmiNot(MacroAssembler* masm, Label* exit, int id, int x) {
1778 int result = ~x;
1779 __ movl(rax, Immediate(id));
1780
1781 __ Move(r8, Smi::FromInt(result));
1782 __ Move(rcx, Smi::FromInt(x));
1783 __ movq(r11, rcx);
1784
1785 __ SmiNot(r9, rcx);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001786 __ cmpq(r9, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001787 __ j(not_equal, exit);
1788
1789 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001790 __ cmpq(r11, rcx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001791 __ j(not_equal, exit);
1792
1793 __ incq(rax);
1794 __ SmiNot(rcx, rcx);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001795 __ cmpq(rcx, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001796 __ j(not_equal, exit);
1797}
1798
1799
1800TEST(SmiNot) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001801 v8::internal::V8::Initialize(NULL);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001802 // Allocate an executable page of memory.
1803 size_t actual_size;
1804 byte* buffer =
1805 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
1806 &actual_size,
1807 true));
1808 CHECK(buffer);
1809 HandleScope handles;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001810 MacroAssembler assembler(Isolate::Current(),
1811 buffer,
1812 static_cast<int>(actual_size));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001813
1814 MacroAssembler* masm = &assembler;
1815 masm->set_allow_stub_calls(false);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001816 EntryCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001817 Label exit;
1818
1819 TestSmiNot(masm, &exit, 0x10, 0);
1820 TestSmiNot(masm, &exit, 0x20, 1);
1821 TestSmiNot(masm, &exit, 0x30, -1);
1822 TestSmiNot(masm, &exit, 0x40, 127);
1823 TestSmiNot(masm, &exit, 0x50, 65535);
1824 TestSmiNot(masm, &exit, 0x60, Smi::kMinValue);
1825 TestSmiNot(masm, &exit, 0x70, Smi::kMaxValue);
1826 TestSmiNot(masm, &exit, 0x80, 0x05555555);
1827
1828 __ xor_(rax, rax); // Success.
1829 __ bind(&exit);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001830 ExitCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001831 __ ret(0);
1832
1833 CodeDesc desc;
1834 masm->GetCode(&desc);
1835 // Call the function from C++.
1836 int result = FUNCTION_CAST<F0>(buffer)();
1837 CHECK_EQ(0, result);
1838}
1839
1840
1841void TestSmiShiftLeft(MacroAssembler* masm, Label* exit, int id, int x) {
1842 const int shifts[] = { 0, 1, 7, 24, kSmiValueSize - 1};
1843 const int kNumShifts = 5;
1844 __ movl(rax, Immediate(id));
1845 for (int i = 0; i < kNumShifts; i++) {
1846 // rax == id + i * 10.
1847 int shift = shifts[i];
1848 int result = x << shift;
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001849 CHECK(Smi::IsValid(result));
1850 __ Move(r8, Smi::FromInt(result));
1851 __ Move(rcx, Smi::FromInt(x));
1852 __ SmiShiftLeftConstant(r9, rcx, shift);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001853
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001854 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001855 __ cmpq(r9, r8);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001856 __ j(not_equal, exit);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001857
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001858 __ incq(rax);
1859 __ Move(rcx, Smi::FromInt(x));
1860 __ SmiShiftLeftConstant(rcx, rcx, shift);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001861
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001862 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001863 __ cmpq(rcx, r8);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001864 __ j(not_equal, exit);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001865
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001866 __ incq(rax);
1867 __ Move(rdx, Smi::FromInt(x));
1868 __ Move(rcx, Smi::FromInt(shift));
1869 __ SmiShiftLeft(r9, rdx, rcx);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001870
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001871 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001872 __ cmpq(r9, r8);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001873 __ j(not_equal, exit);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001874
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001875 __ incq(rax);
1876 __ Move(rdx, Smi::FromInt(x));
1877 __ Move(r11, Smi::FromInt(shift));
1878 __ SmiShiftLeft(r9, rdx, r11);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001879
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001880 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001881 __ cmpq(r9, r8);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001882 __ j(not_equal, exit);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001883
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001884 __ incq(rax);
1885 __ Move(rdx, Smi::FromInt(x));
1886 __ Move(r11, Smi::FromInt(shift));
1887 __ SmiShiftLeft(rdx, rdx, r11);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001888
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001889 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001890 __ cmpq(rdx, r8);
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001891 __ j(not_equal, exit);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001892
sgjesse@chromium.org720dc0b2010-05-10 09:25:39 +00001893 __ incq(rax);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001894 }
1895}
1896
1897
1898TEST(SmiShiftLeft) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001899 v8::internal::V8::Initialize(NULL);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001900 // Allocate an executable page of memory.
1901 size_t actual_size;
1902 byte* buffer =
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001903 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 4,
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001904 &actual_size,
1905 true));
1906 CHECK(buffer);
1907 HandleScope handles;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001908 MacroAssembler assembler(Isolate::Current(),
1909 buffer,
1910 static_cast<int>(actual_size));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001911
1912 MacroAssembler* masm = &assembler;
1913 masm->set_allow_stub_calls(false);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001914 EntryCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001915 Label exit;
1916
1917 TestSmiShiftLeft(masm, &exit, 0x10, 0);
1918 TestSmiShiftLeft(masm, &exit, 0x50, 1);
1919 TestSmiShiftLeft(masm, &exit, 0x90, 127);
1920 TestSmiShiftLeft(masm, &exit, 0xD0, 65535);
1921 TestSmiShiftLeft(masm, &exit, 0x110, Smi::kMaxValue);
1922 TestSmiShiftLeft(masm, &exit, 0x150, Smi::kMinValue);
1923 TestSmiShiftLeft(masm, &exit, 0x190, -1);
1924
1925 __ xor_(rax, rax); // Success.
1926 __ bind(&exit);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001927 ExitCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001928 __ ret(0);
1929
1930 CodeDesc desc;
1931 masm->GetCode(&desc);
1932 // Call the function from C++.
1933 int result = FUNCTION_CAST<F0>(buffer)();
1934 CHECK_EQ(0, result);
1935}
1936
1937
1938void TestSmiShiftLogicalRight(MacroAssembler* masm,
1939 Label* exit,
1940 int id,
1941 int x) {
1942 const int shifts[] = { 0, 1, 7, 24, kSmiValueSize - 1};
1943 const int kNumShifts = 5;
1944 __ movl(rax, Immediate(id));
1945 for (int i = 0; i < kNumShifts; i++) {
1946 int shift = shifts[i];
1947 intptr_t result = static_cast<unsigned int>(x) >> shift;
1948 if (Smi::IsValid(result)) {
ager@chromium.orgc4c92722009-11-18 14:12:51 +00001949 __ Move(r8, Smi::FromInt(static_cast<int>(result)));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001950 __ Move(rcx, Smi::FromInt(x));
1951 __ SmiShiftLogicalRightConstant(r9, rcx, shift, exit);
1952
1953 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001954 __ cmpq(r9, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001955 __ j(not_equal, exit);
1956
1957 __ incq(rax);
1958 __ Move(rdx, Smi::FromInt(x));
1959 __ Move(rcx, Smi::FromInt(shift));
1960 __ SmiShiftLogicalRight(r9, rdx, rcx, exit);
1961
1962 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001963 __ cmpq(r9, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001964 __ j(not_equal, exit);
1965
1966 __ incq(rax);
1967 __ Move(rdx, Smi::FromInt(x));
1968 __ Move(r11, Smi::FromInt(shift));
1969 __ SmiShiftLogicalRight(r9, rdx, r11, exit);
1970
1971 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001972 __ cmpq(r9, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001973 __ j(not_equal, exit);
1974
1975 __ incq(rax);
1976 } else {
1977 // Cannot happen with long smis.
1978 Label fail_ok;
1979 __ Move(rcx, Smi::FromInt(x));
1980 __ movq(r11, rcx);
1981 __ SmiShiftLogicalRightConstant(r9, rcx, shift, &fail_ok);
1982 __ jmp(exit);
1983 __ bind(&fail_ok);
1984
1985 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001986 __ cmpq(rcx, r11);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001987 __ j(not_equal, exit);
1988
1989 __ incq(rax);
1990 __ Move(r8, Smi::FromInt(shift));
1991 Label fail_ok3;
1992 __ SmiShiftLogicalRight(r9, rcx, r8, &fail_ok3);
1993 __ jmp(exit);
1994 __ bind(&fail_ok3);
1995
1996 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00001997 __ cmpq(rcx, r11);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00001998 __ j(not_equal, exit);
1999
2000 __ addq(rax, Immediate(3));
2001 }
2002 }
2003}
2004
2005
2006TEST(SmiShiftLogicalRight) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002007 v8::internal::V8::Initialize(NULL);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002008 // Allocate an executable page of memory.
2009 size_t actual_size;
2010 byte* buffer =
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002011 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 3,
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002012 &actual_size,
2013 true));
2014 CHECK(buffer);
2015 HandleScope handles;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00002016 MacroAssembler assembler(Isolate::Current(),
2017 buffer,
2018 static_cast<int>(actual_size));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002019
2020 MacroAssembler* masm = &assembler;
2021 masm->set_allow_stub_calls(false);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002022 EntryCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002023 Label exit;
2024
2025 TestSmiShiftLogicalRight(masm, &exit, 0x10, 0);
2026 TestSmiShiftLogicalRight(masm, &exit, 0x30, 1);
2027 TestSmiShiftLogicalRight(masm, &exit, 0x50, 127);
2028 TestSmiShiftLogicalRight(masm, &exit, 0x70, 65535);
2029 TestSmiShiftLogicalRight(masm, &exit, 0x90, Smi::kMaxValue);
2030 TestSmiShiftLogicalRight(masm, &exit, 0xB0, Smi::kMinValue);
2031 TestSmiShiftLogicalRight(masm, &exit, 0xD0, -1);
2032
2033 __ xor_(rax, rax); // Success.
2034 __ bind(&exit);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002035 ExitCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002036 __ ret(0);
2037
2038 CodeDesc desc;
2039 masm->GetCode(&desc);
2040 // Call the function from C++.
2041 int result = FUNCTION_CAST<F0>(buffer)();
2042 CHECK_EQ(0, result);
2043}
2044
2045
2046void TestSmiShiftArithmeticRight(MacroAssembler* masm,
2047 Label* exit,
2048 int id,
2049 int x) {
2050 const int shifts[] = { 0, 1, 7, 24, kSmiValueSize - 1};
2051 const int kNumShifts = 5;
2052 __ movl(rax, Immediate(id));
2053 for (int i = 0; i < kNumShifts; i++) {
2054 int shift = shifts[i];
2055 // Guaranteed arithmetic shift.
2056 int result = (x < 0) ? ~((~x) >> shift) : (x >> shift);
2057 __ Move(r8, Smi::FromInt(result));
2058 __ Move(rcx, Smi::FromInt(x));
2059 __ SmiShiftArithmeticRightConstant(rcx, rcx, shift);
2060
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002061 __ cmpq(rcx, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002062 __ j(not_equal, exit);
2063
2064 __ incq(rax);
2065 __ Move(rdx, Smi::FromInt(x));
2066 __ Move(r11, Smi::FromInt(shift));
2067 __ SmiShiftArithmeticRight(rdx, rdx, r11);
2068
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002069 __ cmpq(rdx, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002070 __ j(not_equal, exit);
2071
2072 __ incq(rax);
2073 }
2074}
2075
2076
2077TEST(SmiShiftArithmeticRight) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002078 v8::internal::V8::Initialize(NULL);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002079 // Allocate an executable page of memory.
2080 size_t actual_size;
2081 byte* buffer =
2082 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
2083 &actual_size,
2084 true));
2085 CHECK(buffer);
2086 HandleScope handles;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00002087 MacroAssembler assembler(Isolate::Current(),
2088 buffer,
2089 static_cast<int>(actual_size));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002090
2091 MacroAssembler* masm = &assembler;
2092 masm->set_allow_stub_calls(false);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002093 EntryCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002094 Label exit;
2095
2096 TestSmiShiftArithmeticRight(masm, &exit, 0x10, 0);
2097 TestSmiShiftArithmeticRight(masm, &exit, 0x20, 1);
2098 TestSmiShiftArithmeticRight(masm, &exit, 0x30, 127);
2099 TestSmiShiftArithmeticRight(masm, &exit, 0x40, 65535);
2100 TestSmiShiftArithmeticRight(masm, &exit, 0x50, Smi::kMaxValue);
2101 TestSmiShiftArithmeticRight(masm, &exit, 0x60, Smi::kMinValue);
2102 TestSmiShiftArithmeticRight(masm, &exit, 0x70, -1);
2103
2104 __ xor_(rax, rax); // Success.
2105 __ bind(&exit);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002106 ExitCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002107 __ ret(0);
2108
2109 CodeDesc desc;
2110 masm->GetCode(&desc);
2111 // Call the function from C++.
2112 int result = FUNCTION_CAST<F0>(buffer)();
2113 CHECK_EQ(0, result);
2114}
2115
2116
2117void TestPositiveSmiPowerUp(MacroAssembler* masm, Label* exit, int id, int x) {
2118 ASSERT(x >= 0);
2119 int powers[] = { 0, 1, 2, 3, 8, 16, 24, 31 };
2120 int power_count = 8;
2121 __ movl(rax, Immediate(id));
2122 for (int i = 0; i < power_count; i++) {
2123 int power = powers[i];
2124 intptr_t result = static_cast<intptr_t>(x) << power;
2125 __ Set(r8, result);
2126 __ Move(rcx, Smi::FromInt(x));
2127 __ movq(r11, rcx);
2128 __ PositiveSmiTimesPowerOfTwoToInteger64(rdx, rcx, power);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002129 __ cmpq(rdx, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002130 __ j(not_equal, exit);
2131 __ incq(rax);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002132 __ cmpq(r11, rcx); // rcx unchanged.
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002133 __ j(not_equal, exit);
2134 __ incq(rax);
2135 __ PositiveSmiTimesPowerOfTwoToInteger64(rcx, rcx, power);
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002136 __ cmpq(rdx, r8);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002137 __ j(not_equal, exit);
2138 __ incq(rax);
2139 }
2140}
2141
2142
2143TEST(PositiveSmiTimesPowerOfTwoToInteger64) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002144 v8::internal::V8::Initialize(NULL);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002145 // Allocate an executable page of memory.
2146 size_t actual_size;
2147 byte* buffer =
ricow@chromium.orgbadaffc2011-03-17 12:15:27 +00002148 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 4,
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002149 &actual_size,
2150 true));
2151 CHECK(buffer);
2152 HandleScope handles;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00002153 MacroAssembler assembler(Isolate::Current(),
2154 buffer,
2155 static_cast<int>(actual_size));
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002156
2157 MacroAssembler* masm = &assembler;
2158 masm->set_allow_stub_calls(false);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002159 EntryCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002160 Label exit;
2161
2162 TestPositiveSmiPowerUp(masm, &exit, 0x20, 0);
2163 TestPositiveSmiPowerUp(masm, &exit, 0x40, 1);
2164 TestPositiveSmiPowerUp(masm, &exit, 0x60, 127);
2165 TestPositiveSmiPowerUp(masm, &exit, 0x80, 128);
2166 TestPositiveSmiPowerUp(masm, &exit, 0xA0, 255);
2167 TestPositiveSmiPowerUp(masm, &exit, 0xC0, 256);
2168 TestPositiveSmiPowerUp(masm, &exit, 0x100, 65535);
2169 TestPositiveSmiPowerUp(masm, &exit, 0x120, 65536);
2170 TestPositiveSmiPowerUp(masm, &exit, 0x140, Smi::kMaxValue);
2171
2172 __ xor_(rax, rax); // Success.
2173 __ bind(&exit);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002174 ExitCode(masm);
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002175 __ ret(0);
2176
2177 CodeDesc desc;
2178 masm->GetCode(&desc);
2179 // Call the function from C++.
2180 int result = FUNCTION_CAST<F0>(buffer)();
2181 CHECK_EQ(0, result);
2182}
2183
2184
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00002185TEST(OperandOffset) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00002186 v8::internal::V8::Initialize(NULL);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00002187 int data[256];
2188 for (int i = 0; i < 256; i++) { data[i] = i * 0x01010101; }
2189
2190 // Allocate an executable page of memory.
2191 size_t actual_size;
2192 byte* buffer =
2193 static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize * 2,
2194 &actual_size,
2195 true));
2196 CHECK(buffer);
2197 HandleScope handles;
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00002198 MacroAssembler assembler(Isolate::Current(),
2199 buffer,
2200 static_cast<int>(actual_size));
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00002201
2202 MacroAssembler* masm = &assembler;
2203 masm->set_allow_stub_calls(false);
2204 Label exit;
2205
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002206 EntryCode(masm);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00002207 __ push(r13);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002208 __ push(r14);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00002209 __ push(rbx);
2210 __ push(rbp);
2211 __ push(Immediate(0x100)); // <-- rbp
2212 __ movq(rbp, rsp);
2213 __ push(Immediate(0x101));
2214 __ push(Immediate(0x102));
2215 __ push(Immediate(0x103));
2216 __ push(Immediate(0x104));
2217 __ push(Immediate(0x105)); // <-- rbx
2218 __ push(Immediate(0x106));
2219 __ push(Immediate(0x107));
2220 __ push(Immediate(0x108));
2221 __ push(Immediate(0x109)); // <-- rsp
2222 // rbp = rsp[9]
whesse@chromium.orgb08986c2011-03-14 16:13:42 +00002223 // r15 = rsp[3]
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00002224 // rbx = rsp[5]
2225 // r13 = rsp[7]
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002226 __ lea(r14, Operand(rsp, 3 * kPointerSize));
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00002227 __ lea(r13, Operand(rbp, -3 * kPointerSize));
2228 __ lea(rbx, Operand(rbp, -5 * kPointerSize));
2229 __ movl(rcx, Immediate(2));
2230 __ movq(r8, reinterpret_cast<uintptr_t>(&data[128]), RelocInfo::NONE);
2231 __ movl(rax, Immediate(1));
2232
2233 Operand sp0 = Operand(rsp, 0);
2234
2235 // Test 1.
2236 __ movl(rdx, sp0); // Sanity check.
2237 __ cmpl(rdx, Immediate(0x109));
2238 __ j(not_equal, &exit);
2239 __ incq(rax);
2240
2241 // Test 2.
2242 // Zero to non-zero displacement.
2243 __ movl(rdx, Operand(sp0, 2 * kPointerSize));
2244 __ cmpl(rdx, Immediate(0x107));
2245 __ j(not_equal, &exit);
2246 __ incq(rax);
2247
2248 Operand sp2 = Operand(rsp, 2 * kPointerSize);
2249
2250 // Test 3.
2251 __ movl(rdx, sp2); // Sanity check.
2252 __ cmpl(rdx, Immediate(0x107));
2253 __ j(not_equal, &exit);
2254 __ incq(rax);
2255
2256 __ movl(rdx, Operand(sp2, 2 * kPointerSize));
2257 __ cmpl(rdx, Immediate(0x105));
2258 __ j(not_equal, &exit);
2259 __ incq(rax);
2260
2261 // Non-zero to zero displacement.
2262 __ movl(rdx, Operand(sp2, -2 * kPointerSize));
2263 __ cmpl(rdx, Immediate(0x109));
2264 __ j(not_equal, &exit);
2265 __ incq(rax);
2266
2267 Operand sp2c2 = Operand(rsp, rcx, times_pointer_size, 2 * kPointerSize);
2268
2269 // Test 6.
2270 __ movl(rdx, sp2c2); // Sanity check.
2271 __ cmpl(rdx, Immediate(0x105));
2272 __ j(not_equal, &exit);
2273 __ incq(rax);
2274
2275 __ movl(rdx, Operand(sp2c2, 2 * kPointerSize));
2276 __ cmpl(rdx, Immediate(0x103));
2277 __ j(not_equal, &exit);
2278 __ incq(rax);
2279
2280 // Non-zero to zero displacement.
2281 __ movl(rdx, Operand(sp2c2, -2 * kPointerSize));
2282 __ cmpl(rdx, Immediate(0x107));
2283 __ j(not_equal, &exit);
2284 __ incq(rax);
2285
2286
2287 Operand bp0 = Operand(rbp, 0);
2288
2289 // Test 9.
2290 __ movl(rdx, bp0); // Sanity check.
2291 __ cmpl(rdx, Immediate(0x100));
2292 __ j(not_equal, &exit);
2293 __ incq(rax);
2294
2295 // Zero to non-zero displacement.
2296 __ movl(rdx, Operand(bp0, -2 * kPointerSize));
2297 __ cmpl(rdx, Immediate(0x102));
2298 __ j(not_equal, &exit);
2299 __ incq(rax);
2300
2301 Operand bp2 = Operand(rbp, -2 * kPointerSize);
2302
2303 // Test 11.
2304 __ movl(rdx, bp2); // Sanity check.
2305 __ cmpl(rdx, Immediate(0x102));
2306 __ j(not_equal, &exit);
2307 __ incq(rax);
2308
2309 // Non-zero to zero displacement.
2310 __ movl(rdx, Operand(bp2, 2 * kPointerSize));
2311 __ cmpl(rdx, Immediate(0x100));
2312 __ j(not_equal, &exit);
2313 __ incq(rax);
2314
2315 __ movl(rdx, Operand(bp2, -2 * kPointerSize));
2316 __ cmpl(rdx, Immediate(0x104));
2317 __ j(not_equal, &exit);
2318 __ incq(rax);
2319
2320 Operand bp2c4 = Operand(rbp, rcx, times_pointer_size, -4 * kPointerSize);
2321
2322 // Test 14:
2323 __ movl(rdx, bp2c4); // Sanity check.
2324 __ cmpl(rdx, Immediate(0x102));
2325 __ j(not_equal, &exit);
2326 __ incq(rax);
2327
2328 __ movl(rdx, Operand(bp2c4, 2 * kPointerSize));
2329 __ cmpl(rdx, Immediate(0x100));
2330 __ j(not_equal, &exit);
2331 __ incq(rax);
2332
2333 __ movl(rdx, Operand(bp2c4, -2 * kPointerSize));
2334 __ cmpl(rdx, Immediate(0x104));
2335 __ j(not_equal, &exit);
2336 __ incq(rax);
2337
2338 Operand bx0 = Operand(rbx, 0);
2339
2340 // Test 17.
2341 __ movl(rdx, bx0); // Sanity check.
2342 __ cmpl(rdx, Immediate(0x105));
2343 __ j(not_equal, &exit);
2344 __ incq(rax);
2345
2346 __ movl(rdx, Operand(bx0, 5 * kPointerSize));
2347 __ cmpl(rdx, Immediate(0x100));
2348 __ j(not_equal, &exit);
2349 __ incq(rax);
2350
2351 __ movl(rdx, Operand(bx0, -4 * kPointerSize));
2352 __ cmpl(rdx, Immediate(0x109));
2353 __ j(not_equal, &exit);
2354 __ incq(rax);
2355
2356 Operand bx2 = Operand(rbx, 2 * kPointerSize);
2357
2358 // Test 20.
2359 __ movl(rdx, bx2); // Sanity check.
2360 __ cmpl(rdx, Immediate(0x103));
2361 __ j(not_equal, &exit);
2362 __ incq(rax);
2363
2364 __ movl(rdx, Operand(bx2, 2 * kPointerSize));
2365 __ cmpl(rdx, Immediate(0x101));
2366 __ j(not_equal, &exit);
2367 __ incq(rax);
2368
2369 // Non-zero to zero displacement.
2370 __ movl(rdx, Operand(bx2, -2 * kPointerSize));
2371 __ cmpl(rdx, Immediate(0x105));
2372 __ j(not_equal, &exit);
2373 __ incq(rax);
2374
2375 Operand bx2c2 = Operand(rbx, rcx, times_pointer_size, -2 * kPointerSize);
2376
2377 // Test 23.
2378 __ movl(rdx, bx2c2); // Sanity check.
2379 __ cmpl(rdx, Immediate(0x105));
2380 __ j(not_equal, &exit);
2381 __ incq(rax);
2382
2383 __ movl(rdx, Operand(bx2c2, 2 * kPointerSize));
2384 __ cmpl(rdx, Immediate(0x103));
2385 __ j(not_equal, &exit);
2386 __ incq(rax);
2387
2388 __ movl(rdx, Operand(bx2c2, -2 * kPointerSize));
2389 __ cmpl(rdx, Immediate(0x107));
2390 __ j(not_equal, &exit);
2391 __ incq(rax);
2392
2393 Operand r80 = Operand(r8, 0);
2394
2395 // Test 26.
2396 __ movl(rdx, r80); // Sanity check.
2397 __ cmpl(rdx, Immediate(0x80808080));
2398 __ j(not_equal, &exit);
2399 __ incq(rax);
2400
2401 __ movl(rdx, Operand(r80, -8 * kIntSize));
2402 __ cmpl(rdx, Immediate(0x78787878));
2403 __ j(not_equal, &exit);
2404 __ incq(rax);
2405
2406 __ movl(rdx, Operand(r80, 8 * kIntSize));
2407 __ cmpl(rdx, Immediate(0x88888888));
2408 __ j(not_equal, &exit);
2409 __ incq(rax);
2410
2411 __ movl(rdx, Operand(r80, -64 * kIntSize));
2412 __ cmpl(rdx, Immediate(0x40404040));
2413 __ j(not_equal, &exit);
2414 __ incq(rax);
2415
2416 __ movl(rdx, Operand(r80, 64 * kIntSize));
2417 __ cmpl(rdx, Immediate(0xC0C0C0C0));
2418 __ j(not_equal, &exit);
2419 __ incq(rax);
2420
2421 Operand r88 = Operand(r8, 8 * kIntSize);
2422
2423 // Test 31.
2424 __ movl(rdx, r88); // Sanity check.
2425 __ cmpl(rdx, Immediate(0x88888888));
2426 __ j(not_equal, &exit);
2427 __ incq(rax);
2428
2429 __ movl(rdx, Operand(r88, -8 * kIntSize));
2430 __ cmpl(rdx, Immediate(0x80808080));
2431 __ j(not_equal, &exit);
2432 __ incq(rax);
2433
2434 __ movl(rdx, Operand(r88, 8 * kIntSize));
2435 __ cmpl(rdx, Immediate(0x90909090));
2436 __ j(not_equal, &exit);
2437 __ incq(rax);
2438
2439 __ movl(rdx, Operand(r88, -64 * kIntSize));
2440 __ cmpl(rdx, Immediate(0x48484848));
2441 __ j(not_equal, &exit);
2442 __ incq(rax);
2443
2444 __ movl(rdx, Operand(r88, 64 * kIntSize));
2445 __ cmpl(rdx, Immediate(0xC8C8C8C8));
2446 __ j(not_equal, &exit);
2447 __ incq(rax);
2448
2449
2450 Operand r864 = Operand(r8, 64 * kIntSize);
2451
2452 // Test 36.
2453 __ movl(rdx, r864); // Sanity check.
2454 __ cmpl(rdx, Immediate(0xC0C0C0C0));
2455 __ j(not_equal, &exit);
2456 __ incq(rax);
2457
2458 __ movl(rdx, Operand(r864, -8 * kIntSize));
2459 __ cmpl(rdx, Immediate(0xB8B8B8B8));
2460 __ j(not_equal, &exit);
2461 __ incq(rax);
2462
2463 __ movl(rdx, Operand(r864, 8 * kIntSize));
2464 __ cmpl(rdx, Immediate(0xC8C8C8C8));
2465 __ j(not_equal, &exit);
2466 __ incq(rax);
2467
2468 __ movl(rdx, Operand(r864, -64 * kIntSize));
2469 __ cmpl(rdx, Immediate(0x80808080));
2470 __ j(not_equal, &exit);
2471 __ incq(rax);
2472
2473 __ movl(rdx, Operand(r864, 32 * kIntSize));
2474 __ cmpl(rdx, Immediate(0xE0E0E0E0));
2475 __ j(not_equal, &exit);
2476 __ incq(rax);
2477
2478 // 32-bit offset to 8-bit offset.
2479 __ movl(rdx, Operand(r864, -60 * kIntSize));
2480 __ cmpl(rdx, Immediate(0x84848484));
2481 __ j(not_equal, &exit);
2482 __ incq(rax);
2483
2484 __ movl(rdx, Operand(r864, 60 * kIntSize));
2485 __ cmpl(rdx, Immediate(0xFCFCFCFC));
2486 __ j(not_equal, &exit);
2487 __ incq(rax);
2488
2489 // Test unaligned offsets.
2490
2491 // Test 43.
2492 __ movl(rdx, Operand(r80, 2));
2493 __ cmpl(rdx, Immediate(0x81818080));
2494 __ j(not_equal, &exit);
2495 __ incq(rax);
2496
2497 __ movl(rdx, Operand(r80, -2));
2498 __ cmpl(rdx, Immediate(0x80807F7F));
2499 __ j(not_equal, &exit);
2500 __ incq(rax);
2501
2502 __ movl(rdx, Operand(r80, 126));
2503 __ cmpl(rdx, Immediate(0xA0A09F9F));
2504 __ j(not_equal, &exit);
2505 __ incq(rax);
2506
2507 __ movl(rdx, Operand(r80, -126));
2508 __ cmpl(rdx, Immediate(0x61616060));
2509 __ j(not_equal, &exit);
2510 __ incq(rax);
2511
2512 __ movl(rdx, Operand(r80, 254));
2513 __ cmpl(rdx, Immediate(0xC0C0BFBF));
2514 __ j(not_equal, &exit);
2515 __ incq(rax);
2516
2517 __ movl(rdx, Operand(r80, -254));
2518 __ cmpl(rdx, Immediate(0x41414040));
2519 __ j(not_equal, &exit);
2520 __ incq(rax);
2521
2522 // Success.
2523
2524 __ movl(rax, Immediate(0));
2525 __ bind(&exit);
2526 __ lea(rsp, Operand(rbp, kPointerSize));
2527 __ pop(rbp);
2528 __ pop(rbx);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002529 __ pop(r14);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00002530 __ pop(r13);
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00002531 ExitCode(masm);
kmillikin@chromium.org9155e252010-05-26 13:27:57 +00002532 __ ret(0);
2533
2534
2535 CodeDesc desc;
2536 masm->GetCode(&desc);
2537 // Call the function from C++.
2538 int result = FUNCTION_CAST<F0>(buffer)();
2539 CHECK_EQ(0, result);
2540}
2541
2542
2543
christian.plesner.hansen@gmail.com9d58c2b2009-10-16 11:48:38 +00002544#undef __