blob: e5f73cb96aec58a937899a2f9ca9ea5f94b35f5f [file] [log] [blame]
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001// Copyright 2010 the V8 project authors. All rights reserved.
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "disassembler.h"
31#include "factory.h"
ager@chromium.org3a37e9b2009-04-27 09:26:21 +000032#include "arm/simulator-arm.h"
33#include "arm/assembler-arm-inl.h"
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000034#include "cctest.h"
35
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000036using namespace v8::internal;
37
38
39// Define these function prototypes to match JSEntryFunction in execution.cc.
ager@chromium.orga1645e22009-09-09 19:27:10 +000040typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
41typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
42typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4);
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000043
44
45static v8::Persistent<v8::Context> env;
46
47
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000048static void InitializeVM() {
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000049 if (env.IsEmpty()) {
50 env = v8::Context::New();
51 }
52}
53
54
55#define __ assm.
56
57TEST(0) {
58 InitializeVM();
59 v8::HandleScope scope;
60
61 Assembler assm(NULL, 0);
62
63 __ add(r0, r0, Operand(r1));
64 __ mov(pc, Operand(lr));
65
66 CodeDesc desc;
67 assm.GetCode(&desc);
lrn@chromium.org303ada72010-10-27 09:33:13 +000068 Object* code = Heap::CreateCode(
69 desc,
70 Code::ComputeFlags(Code::STUB),
71 Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000072 CHECK(code->IsCode());
73#ifdef DEBUG
74 Code::cast(code)->Print();
75#endif
76 F2 f = FUNCTION_CAST<F2>(Code::cast(code)->entry());
77 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 3, 4, 0, 0, 0));
78 ::printf("f() = %d\n", res);
79 CHECK_EQ(7, res);
80}
81
82
83TEST(1) {
84 InitializeVM();
85 v8::HandleScope scope;
86
87 Assembler assm(NULL, 0);
88 Label L, C;
89
90 __ mov(r1, Operand(r0));
ager@chromium.org5b2fbee2010-09-08 06:38:15 +000091 __ mov(r0, Operand(0, RelocInfo::NONE));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +000092 __ b(&C);
93
94 __ bind(&L);
95 __ add(r0, r0, Operand(r1));
96 __ sub(r1, r1, Operand(1));
97
98 __ bind(&C);
ager@chromium.org5b2fbee2010-09-08 06:38:15 +000099 __ teq(r1, Operand(0, RelocInfo::NONE));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000100 __ b(ne, &L);
101 __ mov(pc, Operand(lr));
102
103 CodeDesc desc;
104 assm.GetCode(&desc);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000105 Object* code = Heap::CreateCode(
106 desc,
107 Code::ComputeFlags(Code::STUB),
108 Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000109 CHECK(code->IsCode());
110#ifdef DEBUG
111 Code::cast(code)->Print();
112#endif
113 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
114 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 100, 0, 0, 0, 0));
115 ::printf("f() = %d\n", res);
116 CHECK_EQ(5050, res);
117}
118
119
120TEST(2) {
121 InitializeVM();
122 v8::HandleScope scope;
123
124 Assembler assm(NULL, 0);
125 Label L, C;
126
127 __ mov(r1, Operand(r0));
128 __ mov(r0, Operand(1));
129 __ b(&C);
130
131 __ bind(&L);
132 __ mul(r0, r1, r0);
133 __ sub(r1, r1, Operand(1));
134
135 __ bind(&C);
ager@chromium.org5b2fbee2010-09-08 06:38:15 +0000136 __ teq(r1, Operand(0, RelocInfo::NONE));
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000137 __ b(ne, &L);
138 __ mov(pc, Operand(lr));
139
140 // some relocated stuff here, not executed
141 __ RecordComment("dead code, just testing relocations");
142 __ mov(r0, Operand(Factory::true_value()));
143 __ RecordComment("dead code, just testing immediate operands");
144 __ mov(r0, Operand(-1));
145 __ mov(r0, Operand(0xFF000000));
146 __ mov(r0, Operand(0xF0F0F0F0));
147 __ mov(r0, Operand(0xFFF0FFFF));
148
149 CodeDesc desc;
150 assm.GetCode(&desc);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000151 Object* code = Heap::CreateCode(
152 desc,
153 Code::ComputeFlags(Code::STUB),
154 Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000155 CHECK(code->IsCode());
156#ifdef DEBUG
157 Code::cast(code)->Print();
158#endif
159 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
160 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 10, 0, 0, 0, 0));
161 ::printf("f() = %d\n", res);
162 CHECK_EQ(3628800, res);
163}
164
165
166TEST(3) {
167 InitializeVM();
168 v8::HandleScope scope;
169
170 typedef struct {
171 int i;
172 char c;
173 int16_t s;
174 } T;
175 T t;
176
177 Assembler assm(NULL, 0);
178 Label L, C;
179
180 __ mov(ip, Operand(sp));
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000181 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000182 __ sub(fp, ip, Operand(4));
183 __ mov(r4, Operand(r0));
184 __ ldr(r0, MemOperand(r4, OFFSET_OF(T, i)));
185 __ mov(r2, Operand(r0, ASR, 1));
186 __ str(r2, MemOperand(r4, OFFSET_OF(T, i)));
187 __ ldrsb(r2, MemOperand(r4, OFFSET_OF(T, c)));
188 __ add(r0, r2, Operand(r0));
189 __ mov(r2, Operand(r2, LSL, 2));
190 __ strb(r2, MemOperand(r4, OFFSET_OF(T, c)));
191 __ ldrsh(r2, MemOperand(r4, OFFSET_OF(T, s)));
192 __ add(r0, r2, Operand(r0));
193 __ mov(r2, Operand(r2, ASR, 3));
194 __ strh(r2, MemOperand(r4, OFFSET_OF(T, s)));
ager@chromium.org18ad94b2009-09-02 08:22:29 +0000195 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000196
197 CodeDesc desc;
198 assm.GetCode(&desc);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000199 Object* code = Heap::CreateCode(
200 desc,
201 Code::ComputeFlags(Code::STUB),
202 Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000203 CHECK(code->IsCode());
204#ifdef DEBUG
205 Code::cast(code)->Print();
206#endif
207 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
208 t.i = 100000;
209 t.c = 10;
210 t.s = 1000;
211 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0));
212 ::printf("f() = %d\n", res);
213 CHECK_EQ(101010, res);
214 CHECK_EQ(100000/2, t.i);
215 CHECK_EQ(10*4, t.c);
216 CHECK_EQ(1000/8, t.s);
217}
218
219
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000220TEST(4) {
221 // Test the VFP floating point instructions.
222 InitializeVM();
223 v8::HandleScope scope;
224
225 typedef struct {
226 double a;
227 double b;
228 double c;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000229 double d;
230 double e;
231 double f;
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000232 double g;
233 double h;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000234 int i;
235 float x;
236 float y;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000237 } T;
238 T t;
239
240 // Create a function that accepts &t, and loads, manipulates, and stores
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000241 // the doubles and floats.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000242 Assembler assm(NULL, 0);
243 Label L, C;
244
245
246 if (CpuFeatures::IsSupported(VFP3)) {
247 CpuFeatures::Scope scope(VFP3);
248
249 __ mov(ip, Operand(sp));
250 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
251 __ sub(fp, ip, Operand(4));
252
253 __ mov(r4, Operand(r0));
254 __ vldr(d6, r4, OFFSET_OF(T, a));
255 __ vldr(d7, r4, OFFSET_OF(T, b));
256 __ vadd(d5, d6, d7);
257 __ vstr(d5, r4, OFFSET_OF(T, c));
258
259 __ vmov(r2, r3, d5);
260 __ vmov(d4, r2, r3);
261 __ vstr(d4, r4, OFFSET_OF(T, b));
262
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000263 // Load t.x and t.y, switch values, and store back to the struct.
264 __ vldr(s0, r4, OFFSET_OF(T, x));
265 __ vldr(s31, r4, OFFSET_OF(T, y));
266 __ vmov(s16, s0);
267 __ vmov(s0, s31);
268 __ vmov(s31, s16);
269 __ vstr(s0, r4, OFFSET_OF(T, x));
270 __ vstr(s31, r4, OFFSET_OF(T, y));
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000271
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000272 // Move a literal into a register that can be encoded in the instruction.
273 __ vmov(d4, 1.0);
274 __ vstr(d4, r4, OFFSET_OF(T, e));
275
276 // Move a literal into a register that requires 64 bits to encode.
277 // 0x3ff0000010000000 = 1.000000059604644775390625
278 __ vmov(d4, 1.000000059604644775390625);
279 __ vstr(d4, r4, OFFSET_OF(T, d));
280
281 // Convert from floating point to integer.
282 __ vmov(d4, 2.0);
283 __ vcvt_s32_f64(s31, d4);
284 __ vstr(s31, r4, OFFSET_OF(T, i));
285
286 // Convert from integer to floating point.
287 __ mov(lr, Operand(42));
288 __ vmov(s31, lr);
289 __ vcvt_f64_s32(d4, s31);
290 __ vstr(d4, r4, OFFSET_OF(T, f));
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000291
292 // Test vabs.
293 __ vldr(d1, r4, OFFSET_OF(T, g));
294 __ vabs(d0, d1);
295 __ vstr(d0, r4, OFFSET_OF(T, g));
296 __ vldr(d2, r4, OFFSET_OF(T, h));
297 __ vabs(d0, d2);
298 __ vstr(d0, r4, OFFSET_OF(T, h));
299
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000300 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
301
302 CodeDesc desc;
303 assm.GetCode(&desc);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000304 Object* code = Heap::CreateCode(
305 desc,
306 Code::ComputeFlags(Code::STUB),
307 Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000308 CHECK(code->IsCode());
309#ifdef DEBUG
310 Code::cast(code)->Print();
311#endif
312 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
313 t.a = 1.5;
314 t.b = 2.75;
315 t.c = 17.17;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000316 t.d = 0.0;
317 t.e = 0.0;
318 t.f = 0.0;
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000319 t.g = -2718.2818;
320 t.h = 31415926.5;
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000321 t.i = 0;
322 t.x = 4.5;
323 t.y = 9.0;
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000324 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
325 USE(dummy);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000326 CHECK_EQ(4.5, t.y);
327 CHECK_EQ(9.0, t.x);
328 CHECK_EQ(2, t.i);
whesse@chromium.org7a392b32011-01-31 11:30:36 +0000329 CHECK_EQ(2718.2818, t.g);
330 CHECK_EQ(31415926.5, t.h);
ricow@chromium.orgd236f4d2010-09-01 06:52:08 +0000331 CHECK_EQ(42.0, t.f);
332 CHECK_EQ(1.0, t.e);
333 CHECK_EQ(1.000000059604644775390625, t.d);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000334 CHECK_EQ(4.25, t.c);
335 CHECK_EQ(4.25, t.b);
336 CHECK_EQ(1.5, t.a);
337 }
338}
339
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000340
341TEST(5) {
342 // Test the ARMv7 bitfield instructions.
343 InitializeVM();
344 v8::HandleScope scope;
345
346 Assembler assm(NULL, 0);
347
348 if (CpuFeatures::IsSupported(ARMv7)) {
349 CpuFeatures::Scope scope(ARMv7);
350 // On entry, r0 = 0xAAAAAAAA = 0b10..10101010.
351 __ ubfx(r0, r0, 1, 12); // 0b00..010101010101 = 0x555
352 __ sbfx(r0, r0, 0, 5); // 0b11..111111110101 = -11
353 __ bfc(r0, 1, 3); // 0b11..111111110001 = -15
354 __ mov(r1, Operand(7));
355 __ bfi(r0, r1, 3, 3); // 0b11..111111111001 = -7
356 __ mov(pc, Operand(lr));
357
358 CodeDesc desc;
359 assm.GetCode(&desc);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000360 Object* code = Heap::CreateCode(
361 desc,
362 Code::ComputeFlags(Code::STUB),
363 Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
ricow@chromium.org30ce4112010-05-31 10:38:25 +0000364 CHECK(code->IsCode());
365#ifdef DEBUG
366 Code::cast(code)->Print();
367#endif
368 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
369 int res = reinterpret_cast<int>(
370 CALL_GENERATED_CODE(f, 0xAAAAAAAA, 0, 0, 0, 0));
371 ::printf("f() = %d\n", res);
372 CHECK_EQ(-7, res);
373 }
374}
375
fschneider@chromium.orged78ffd2010-07-21 11:05:19 +0000376
377TEST(6) {
378 // Test saturating instructions.
379 InitializeVM();
380 v8::HandleScope scope;
381
382 Assembler assm(NULL, 0);
383
384 if (CpuFeatures::IsSupported(ARMv7)) {
385 CpuFeatures::Scope scope(ARMv7);
386 __ usat(r1, 8, Operand(r0)); // Sat 0xFFFF to 0-255 = 0xFF.
387 __ usat(r2, 12, Operand(r0, ASR, 9)); // Sat (0xFFFF>>9) to 0-4095 = 0x7F.
388 __ usat(r3, 1, Operand(r0, LSL, 16)); // Sat (0xFFFF<<16) to 0-1 = 0x0.
389 __ add(r0, r1, Operand(r2));
390 __ add(r0, r0, Operand(r3));
391 __ mov(pc, Operand(lr));
392
393 CodeDesc desc;
394 assm.GetCode(&desc);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000395 Object* code = Heap::CreateCode(
396 desc,
397 Code::ComputeFlags(Code::STUB),
398 Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
fschneider@chromium.orged78ffd2010-07-21 11:05:19 +0000399 CHECK(code->IsCode());
400#ifdef DEBUG
401 Code::cast(code)->Print();
402#endif
403 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
404 int res = reinterpret_cast<int>(
405 CALL_GENERATED_CODE(f, 0xFFFF, 0, 0, 0, 0));
406 ::printf("f() = %d\n", res);
407 CHECK_EQ(382, res);
408 }
409}
410
ager@chromium.org01fe7df2010-11-10 11:59:11 +0000411
412static void TestRoundingMode(int32_t mode, double value, int expected) {
413 InitializeVM();
414 v8::HandleScope scope;
415
416 Assembler assm(NULL, 0);
417
418 __ vmrs(r1);
419 // Set custom FPSCR.
420 __ bic(r2, r1, Operand(((mode ^ 3) << 22) | 0xf));
421 __ orr(r2, r2, Operand(mode << 22));
422 __ vmsr(r2);
423
424 // Load value, convert, and move back result to r0.
425 __ vmov(d1, value);
426 __ vcvt_s32_f64(s0, d1, Assembler::FPSCRRounding, al);
427 __ vmov(r0, s0);
428
429 __ mov(pc, Operand(lr));
430
431 CodeDesc desc;
432 assm.GetCode(&desc);
433 Object* code = Heap::CreateCode(
434 desc,
435 Code::ComputeFlags(Code::STUB),
436 Handle<Object>(Heap::undefined_value()))->ToObjectChecked();
437 CHECK(code->IsCode());
438#ifdef DEBUG
439 Code::cast(code)->Print();
440#endif
441 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
442 int res = reinterpret_cast<int>(
443 CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
444 ::printf("res = %d\n", res);
445 CHECK_EQ(expected, res);
446}
447
448
449TEST(7) {
450 // Test vfp rounding modes.
451
452 // See ARM DDI 0406B Page A2-29.
453 enum FPSCRRoungingMode {
454 RN, // Round to Nearest.
455 RP, // Round towards Plus Infinity.
456 RM, // Round towards Minus Infinity.
457 RZ // Round towards zero.
458 };
459
460 if (CpuFeatures::IsSupported(VFP3)) {
461 CpuFeatures::Scope scope(VFP3);
462
463 TestRoundingMode(RZ, 0.5, 0);
464 TestRoundingMode(RZ, -0.5, 0);
465 TestRoundingMode(RZ, 123.7, 123);
466 TestRoundingMode(RZ, -123.7, -123);
467 TestRoundingMode(RZ, 123456.2, 123456);
468 TestRoundingMode(RZ, -123456.2, -123456);
469
470 TestRoundingMode(RM, 0.5, 0);
471 TestRoundingMode(RM, -0.5, -1);
472 TestRoundingMode(RM, 123.7, 123);
473 TestRoundingMode(RM, -123.7, -124);
474 TestRoundingMode(RM, 123456.2, 123456);
475 TestRoundingMode(RM, -123456.2, -123457);
476 }
477}
478
mads.s.ager@gmail.com9a4089a2008-09-01 08:55:01 +0000479#undef __