• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 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 "src/v8.h"
29 
30 #include "src/disassembler.h"
31 #include "src/factory.h"
32 #include "src/ppc/assembler-ppc-inl.h"
33 #include "src/ppc/simulator-ppc.h"
34 #include "test/cctest/cctest.h"
35 
36 using namespace v8::internal;
37 
38 
39 // Define these function prototypes to match JSEntryFunction in execution.cc.
40 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
41 typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
42 typedef Object* (*F3)(void* p0, int p1, int p2, int p3, int p4);
43 typedef Object* (*F4)(void* p0, void* p1, int p2, int p3, int p4);
44 
45 
46 #define __ assm.
47 
48 // Simple add parameter 1 to parameter 2 and return
49 TEST(0) {
50   CcTest::InitializeVM();
51   Isolate* isolate = CcTest::i_isolate();
52   HandleScope scope(isolate);
53 
54   Assembler assm(isolate, NULL, 0);
55 
56   __ function_descriptor();
57 
58   __ add(r3, r3, r4);
59   __ blr();
60 
61   CodeDesc desc;
62   assm.GetCode(&desc);
63   Handle<Code> code = isolate->factory()->NewCode(
64       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
65 #ifdef DEBUG
66   code->Print();
67 #endif
68   F2 f = FUNCTION_CAST<F2>(code->entry());
69   intptr_t res = reinterpret_cast<intptr_t>(
70       CALL_GENERATED_CODE(isolate, f, 3, 4, 0, 0, 0));
71   ::printf("f() = %" V8PRIdPTR "\n", res);
72   CHECK_EQ(7, static_cast<int>(res));
73 }
74 
75 
76 // Loop 100 times, adding loop counter to result
77 TEST(1) {
78   CcTest::InitializeVM();
79   Isolate* isolate = CcTest::i_isolate();
80   HandleScope scope(isolate);
81 
82   Assembler assm(isolate, NULL, 0);
83   Label L, C;
84 
85   __ function_descriptor();
86 
87   __ mr(r4, r3);
88   __ li(r3, Operand::Zero());
89   __ b(&C);
90 
91   __ bind(&L);
92   __ add(r3, r3, r4);
93   __ subi(r4, r4, Operand(1));
94 
95   __ bind(&C);
96   __ cmpi(r4, Operand::Zero());
97   __ bne(&L);
98   __ blr();
99 
100   CodeDesc desc;
101   assm.GetCode(&desc);
102   Handle<Code> code = isolate->factory()->NewCode(
103       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
104 #ifdef DEBUG
105   code->Print();
106 #endif
107   F1 f = FUNCTION_CAST<F1>(code->entry());
108   intptr_t res = reinterpret_cast<intptr_t>(
109       CALL_GENERATED_CODE(isolate, f, 100, 0, 0, 0, 0));
110   ::printf("f() = %" V8PRIdPTR "\n", res);
111   CHECK_EQ(5050, static_cast<int>(res));
112 }
113 
114 
115 TEST(2) {
116   CcTest::InitializeVM();
117   Isolate* isolate = CcTest::i_isolate();
118   HandleScope scope(isolate);
119 
120   Assembler assm(isolate, NULL, 0);
121   Label L, C;
122 
123   __ function_descriptor();
124 
125   __ mr(r4, r3);
126   __ li(r3, Operand(1));
127   __ b(&C);
128 
129   __ bind(&L);
130 #if defined(V8_TARGET_ARCH_PPC64)
131   __ mulld(r3, r4, r3);
132 #else
133   __ mullw(r3, r4, r3);
134 #endif
135   __ subi(r4, r4, Operand(1));
136 
137   __ bind(&C);
138   __ cmpi(r4, Operand::Zero());
139   __ bne(&L);
140   __ blr();
141 
142   // some relocated stuff here, not executed
143   __ RecordComment("dead code, just testing relocations");
144   __ mov(r0, Operand(isolate->factory()->true_value()));
145   __ RecordComment("dead code, just testing immediate operands");
146   __ mov(r0, Operand(-1));
147   __ mov(r0, Operand(0xFF000000));
148   __ mov(r0, Operand(0xF0F0F0F0));
149   __ mov(r0, Operand(0xFFF0FFFF));
150 
151   CodeDesc desc;
152   assm.GetCode(&desc);
153   Handle<Code> code = isolate->factory()->NewCode(
154       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
155 #ifdef DEBUG
156   code->Print();
157 #endif
158   F1 f = FUNCTION_CAST<F1>(code->entry());
159   intptr_t res = reinterpret_cast<intptr_t>(
160       CALL_GENERATED_CODE(isolate, f, 10, 0, 0, 0, 0));
161   ::printf("f() = %" V8PRIdPTR "\n", res);
162   CHECK_EQ(3628800, static_cast<int>(res));
163 }
164 
165 
166 TEST(3) {
167   CcTest::InitializeVM();
168   Isolate* isolate = CcTest::i_isolate();
169   HandleScope scope(isolate);
170 
171   typedef struct {
172     int i;
173     char c;
174     int16_t s;
175   } T;
176   T t;
177 
178   Assembler assm(CcTest::i_isolate(), NULL, 0);
179   Label L, C;
180 
181   __ function_descriptor();
182 
183 // build a frame
184 #if V8_TARGET_ARCH_PPC64
185   __ stdu(sp, MemOperand(sp, -32));
186   __ std(fp, MemOperand(sp, 24));
187 #else
188   __ stwu(sp, MemOperand(sp, -16));
189   __ stw(fp, MemOperand(sp, 12));
190 #endif
191   __ mr(fp, sp);
192 
193   // r4 points to our struct
194   __ mr(r4, r3);
195 
196   // modify field int i of struct
197   __ lwz(r3, MemOperand(r4, offsetof(T, i)));
198   __ srwi(r5, r3, Operand(1));
199   __ stw(r5, MemOperand(r4, offsetof(T, i)));
200 
201   // modify field char c of struct
202   __ lbz(r5, MemOperand(r4, offsetof(T, c)));
203   __ add(r3, r5, r3);
204   __ slwi(r5, r5, Operand(2));
205   __ stb(r5, MemOperand(r4, offsetof(T, c)));
206 
207   // modify field int16_t s of struct
208   __ lhz(r5, MemOperand(r4, offsetof(T, s)));
209   __ add(r3, r5, r3);
210   __ srwi(r5, r5, Operand(3));
211   __ sth(r5, MemOperand(r4, offsetof(T, s)));
212 
213 // restore frame
214 #if V8_TARGET_ARCH_PPC64
215   __ addi(r11, fp, Operand(32));
216   __ ld(fp, MemOperand(r11, -8));
217 #else
218   __ addi(r11, fp, Operand(16));
219   __ lwz(fp, MemOperand(r11, -4));
220 #endif
221   __ mr(sp, r11);
222   __ blr();
223 
224   CodeDesc desc;
225   assm.GetCode(&desc);
226   Handle<Code> code = isolate->factory()->NewCode(
227       desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
228 #ifdef DEBUG
229   code->Print();
230 #endif
231   F3 f = FUNCTION_CAST<F3>(code->entry());
232   t.i = 100000;
233   t.c = 10;
234   t.s = 1000;
235   intptr_t res = reinterpret_cast<intptr_t>(
236       CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0));
237   ::printf("f() = %" V8PRIdPTR "\n", res);
238   CHECK_EQ(101010, static_cast<int>(res));
239   CHECK_EQ(100000 / 2, t.i);
240   CHECK_EQ(10 * 4, t.c);
241   CHECK_EQ(1000 / 8, t.s);
242 }
243 
244 #if 0
245 TEST(4) {
246   // Test the VFP floating point instructions.
247   CcTest::InitializeVM();
248   Isolate* isolate = CcTest::i_isolate();
249   HandleScope scope(isolate);
250 
251   typedef struct {
252     double a;
253     double b;
254     double c;
255     double d;
256     double e;
257     double f;
258     double g;
259     double h;
260     int i;
261     double m;
262     double n;
263     float x;
264     float y;
265   } T;
266   T t;
267 
268   // Create a function that accepts &t, and loads, manipulates, and stores
269   // the doubles and floats.
270   Assembler assm(CcTest::i_isolate(), NULL, 0);
271   Label L, C;
272 
273   if (CpuFeatures::IsSupported(VFP3)) {
274     CpuFeatures::Scope scope(VFP3);
275 
276     __ mov(ip, Operand(sp));
277     __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
278     __ sub(fp, ip, Operand(4));
279 
280     __ mov(r4, Operand(r0));
281     __ vldr(d6, r4, offsetof(T, a));
282     __ vldr(d7, r4, offsetof(T, b));
283     __ vadd(d5, d6, d7);
284     __ vstr(d5, r4, offsetof(T, c));
285 
286     __ vmov(r2, r3, d5);
287     __ vmov(d4, r2, r3);
288     __ vstr(d4, r4, offsetof(T, b));
289 
290     // Load t.x and t.y, switch values, and store back to the struct.
291     __ vldr(s0, r4, offsetof(T, x));
292     __ vldr(s31, r4, offsetof(T, y));
293     __ vmov(s16, s0);
294     __ vmov(s0, s31);
295     __ vmov(s31, s16);
296     __ vstr(s0, r4, offsetof(T, x));
297     __ vstr(s31, r4, offsetof(T, y));
298 
299     // Move a literal into a register that can be encoded in the instruction.
300     __ vmov(d4, 1.0);
301     __ vstr(d4, r4, offsetof(T, e));
302 
303     // Move a literal into a register that requires 64 bits to encode.
304     // 0x3ff0000010000000 = 1.000000059604644775390625
305     __ vmov(d4, 1.000000059604644775390625);
306     __ vstr(d4, r4, offsetof(T, d));
307 
308     // Convert from floating point to integer.
309     __ vmov(d4, 2.0);
310     __ vcvt_s32_f64(s31, d4);
311     __ vstr(s31, r4, offsetof(T, i));
312 
313     // Convert from integer to floating point.
314     __ mov(lr, Operand(42));
315     __ vmov(s31, lr);
316     __ vcvt_f64_s32(d4, s31);
317     __ vstr(d4, r4, offsetof(T, f));
318 
319     // Test vabs.
320     __ vldr(d1, r4, offsetof(T, g));
321     __ vabs(d0, d1);
322     __ vstr(d0, r4, offsetof(T, g));
323     __ vldr(d2, r4, offsetof(T, h));
324     __ vabs(d0, d2);
325     __ vstr(d0, r4, offsetof(T, h));
326 
327     // Test vneg.
328     __ vldr(d1, r4, offsetof(T, m));
329     __ vneg(d0, d1);
330     __ vstr(d0, r4, offsetof(T, m));
331     __ vldr(d1, r4, offsetof(T, n));
332     __ vneg(d0, d1);
333     __ vstr(d0, r4, offsetof(T, n));
334 
335     __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
336 
337     CodeDesc desc;
338     assm.GetCode(&desc);
339     Object* code = isolate->heap()->CreateCode(
340         desc,
341         Code::ComputeFlags(Code::STUB),
342         Handle<Code>())->ToObjectChecked();
343     CHECK(code->IsCode());
344 #ifdef DEBUG
345     Code::cast(code)->Print();
346 #endif
347     F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
348     t.a = 1.5;
349     t.b = 2.75;
350     t.c = 17.17;
351     t.d = 0.0;
352     t.e = 0.0;
353     t.f = 0.0;
354     t.g = -2718.2818;
355     t.h = 31415926.5;
356     t.i = 0;
357     t.m = -2718.2818;
358     t.n = 123.456;
359     t.x = 4.5;
360     t.y = 9.0;
361     Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
362     USE(dummy);
363     CHECK_EQ(4.5, t.y);
364     CHECK_EQ(9.0, t.x);
365     CHECK_EQ(-123.456, t.n);
366     CHECK_EQ(2718.2818, t.m);
367     CHECK_EQ(2, t.i);
368     CHECK_EQ(2718.2818, t.g);
369     CHECK_EQ(31415926.5, t.h);
370     CHECK_EQ(42.0, t.f);
371     CHECK_EQ(1.0, t.e);
372     CHECK_EQ(1.000000059604644775390625, t.d);
373     CHECK_EQ(4.25, t.c);
374     CHECK_EQ(4.25, t.b);
375     CHECK_EQ(1.5, t.a);
376   }
377 }
378 
379 
380 TEST(5) {
381   // Test the ARMv7 bitfield instructions.
382   CcTest::InitializeVM();
383   Isolate* isolate = CcTest::i_isolate();
384   HandleScope scope(isolate);
385 
386   Assembler assm(isolate, NULL, 0);
387 
388   if (CpuFeatures::IsSupported(ARMv7)) {
389     CpuFeatures::Scope scope(ARMv7);
390     // On entry, r0 = 0xAAAAAAAA = 0b10..10101010.
391     __ ubfx(r0, r0, 1, 12);  // 0b00..010101010101 = 0x555
392     __ sbfx(r0, r0, 0, 5);   // 0b11..111111110101 = -11
393     __ bfc(r0, 1, 3);        // 0b11..111111110001 = -15
394     __ mov(r1, Operand(7));
395     __ bfi(r0, r1, 3, 3);    // 0b11..111111111001 = -7
396     __ mov(pc, Operand(lr));
397 
398     CodeDesc desc;
399     assm.GetCode(&desc);
400     Object* code = isolate->heap()->CreateCode(
401         desc,
402         Code::ComputeFlags(Code::STUB),
403         Handle<Code>())->ToObjectChecked();
404     CHECK(code->IsCode());
405 #ifdef DEBUG
406     Code::cast(code)->Print();
407 #endif
408     F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
409     int res = reinterpret_cast<int>(
410                 CALL_GENERATED_CODE(isolate, f, 0xAAAAAAAA, 0, 0, 0, 0));
411     ::printf("f() = %d\n", res);
412     CHECK_EQ(-7, res);
413   }
414 }
415 
416 
417 TEST(6) {
418   // Test saturating instructions.
419   CcTest::InitializeVM();
420   Isolate* isolate = CcTest::i_isolate();
421   HandleScope scope(isolate);
422 
423   Assembler assm(isolate, NULL, 0);
424 
425   if (CpuFeatures::IsSupported(ARMv7)) {
426     CpuFeatures::Scope scope(ARMv7);
427     __ usat(r1, 8, Operand(r0));           // Sat 0xFFFF to 0-255 = 0xFF.
428     __ usat(r2, 12, Operand(r0, ASR, 9));  // Sat (0xFFFF>>9) to 0-4095 = 0x7F.
429     __ usat(r3, 1, Operand(r0, LSL, 16));  // Sat (0xFFFF<<16) to 0-1 = 0x0.
430     __ addi(r0, r1, Operand(r2));
431     __ addi(r0, r0, Operand(r3));
432     __ mov(pc, Operand(lr));
433 
434     CodeDesc desc;
435     assm.GetCode(&desc);
436     Object* code = isolate->heap()->CreateCode(
437         desc,
438         Code::ComputeFlags(Code::STUB),
439         Handle<Code>())->ToObjectChecked();
440     CHECK(code->IsCode());
441 #ifdef DEBUG
442     Code::cast(code)->Print();
443 #endif
444     F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
445     int res = reinterpret_cast<int>(
446                 CALL_GENERATED_CODE(isolate, f, 0xFFFF, 0, 0, 0, 0));
447     ::printf("f() = %d\n", res);
448     CHECK_EQ(382, res);
449   }
450 }
451 
452 enum VCVTTypes {
453   s32_f64,
454   u32_f64
455 };
456 
457 static void TestRoundingMode(VCVTTypes types,
458                              VFPRoundingMode mode,
459                              double value,
460                              int expected,
461                              bool expected_exception = false) {
462   CcTest::InitializeVM();
463   Isolate* isolate = CcTest::i_isolate();
464   HandleScope scope(isolate);
465 
466   Assembler assm(isolate, NULL, 0);
467 
468   if (CpuFeatures::IsSupported(VFP3)) {
469     CpuFeatures::Scope scope(VFP3);
470 
471     Label wrong_exception;
472 
473     __ vmrs(r1);
474     // Set custom FPSCR.
475     __ bic(r2, r1, Operand(kVFPRoundingModeMask | kVFPExceptionMask));
476     __ orr(r2, r2, Operand(mode));
477     __ vmsr(r2);
478 
479     // Load value, convert, and move back result to r0 if everything went well.
480     __ vmov(d1, value);
481     switch (types) {
482       case s32_f64:
483         __ vcvt_s32_f64(s0, d1, kFPSCRRounding);
484         break;
485 
486       case u32_f64:
487         __ vcvt_u32_f64(s0, d1, kFPSCRRounding);
488         break;
489 
490       default:
491         UNREACHABLE();
492         break;
493     }
494     // Check for vfp exceptions
495     __ vmrs(r2);
496     __ tst(r2, Operand(kVFPExceptionMask));
497     // Check that we behaved as expected.
498     __ b(&wrong_exception,
499          expected_exception ? eq : ne);
500     // There was no exception. Retrieve the result and return.
501     __ vmov(r0, s0);
502     __ mov(pc, Operand(lr));
503 
504     // The exception behaviour is not what we expected.
505     // Load a special value and return.
506     __ bind(&wrong_exception);
507     __ mov(r0, Operand(11223344));
508     __ mov(pc, Operand(lr));
509 
510     CodeDesc desc;
511     assm.GetCode(&desc);
512     Object* code = isolate->heap()->CreateCode(
513         desc,
514         Code::ComputeFlags(Code::STUB),
515         Handle<Code>())->ToObjectChecked();
516     CHECK(code->IsCode());
517 #ifdef DEBUG
518     Code::cast(code)->Print();
519 #endif
520     F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry());
521     int res = reinterpret_cast<int>(
522                 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
523     ::printf("res = %d\n", res);
524     CHECK_EQ(expected, res);
525   }
526 }
527 
528 
529 TEST(7) {
530   // Test vfp rounding modes.
531 
532   // s32_f64 (double to integer).
533 
534   TestRoundingMode(s32_f64, RN,  0, 0);
535   TestRoundingMode(s32_f64, RN,  0.5, 0);
536   TestRoundingMode(s32_f64, RN, -0.5, 0);
537   TestRoundingMode(s32_f64, RN,  1.5, 2);
538   TestRoundingMode(s32_f64, RN, -1.5, -2);
539   TestRoundingMode(s32_f64, RN,  123.7, 124);
540   TestRoundingMode(s32_f64, RN, -123.7, -124);
541   TestRoundingMode(s32_f64, RN,  123456.2,  123456);
542   TestRoundingMode(s32_f64, RN, -123456.2, -123456);
543   TestRoundingMode(s32_f64, RN, static_cast<double>(kMaxInt), kMaxInt);
544   TestRoundingMode(s32_f64, RN, (kMaxInt + 0.49), kMaxInt);
545   TestRoundingMode(s32_f64, RN, (kMaxInt + 1.0), kMaxInt, true);
546   TestRoundingMode(s32_f64, RN, (kMaxInt + 0.5), kMaxInt, true);
547   TestRoundingMode(s32_f64, RN, static_cast<double>(kMinInt), kMinInt);
548   TestRoundingMode(s32_f64, RN, (kMinInt - 0.5), kMinInt);
549   TestRoundingMode(s32_f64, RN, (kMinInt - 1.0), kMinInt, true);
550   TestRoundingMode(s32_f64, RN, (kMinInt - 0.51), kMinInt, true);
551 
552   TestRoundingMode(s32_f64, RM,  0, 0);
553   TestRoundingMode(s32_f64, RM,  0.5, 0);
554   TestRoundingMode(s32_f64, RM, -0.5, -1);
555   TestRoundingMode(s32_f64, RM,  123.7, 123);
556   TestRoundingMode(s32_f64, RM, -123.7, -124);
557   TestRoundingMode(s32_f64, RM,  123456.2,  123456);
558   TestRoundingMode(s32_f64, RM, -123456.2, -123457);
559   TestRoundingMode(s32_f64, RM, static_cast<double>(kMaxInt), kMaxInt);
560   TestRoundingMode(s32_f64, RM, (kMaxInt + 0.5), kMaxInt);
561   TestRoundingMode(s32_f64, RM, (kMaxInt + 1.0), kMaxInt, true);
562   TestRoundingMode(s32_f64, RM, static_cast<double>(kMinInt), kMinInt);
563   TestRoundingMode(s32_f64, RM, (kMinInt - 0.5), kMinInt, true);
564   TestRoundingMode(s32_f64, RM, (kMinInt + 0.5), kMinInt);
565 
566   TestRoundingMode(s32_f64, RZ,  0, 0);
567   TestRoundingMode(s32_f64, RZ,  0.5, 0);
568   TestRoundingMode(s32_f64, RZ, -0.5, 0);
569   TestRoundingMode(s32_f64, RZ,  123.7,  123);
570   TestRoundingMode(s32_f64, RZ, -123.7, -123);
571   TestRoundingMode(s32_f64, RZ,  123456.2,  123456);
572   TestRoundingMode(s32_f64, RZ, -123456.2, -123456);
573   TestRoundingMode(s32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt);
574   TestRoundingMode(s32_f64, RZ, (kMaxInt + 0.5), kMaxInt);
575   TestRoundingMode(s32_f64, RZ, (kMaxInt + 1.0), kMaxInt, true);
576   TestRoundingMode(s32_f64, RZ, static_cast<double>(kMinInt), kMinInt);
577   TestRoundingMode(s32_f64, RZ, (kMinInt - 0.5), kMinInt);
578   TestRoundingMode(s32_f64, RZ, (kMinInt - 1.0), kMinInt, true);
579 
580 
581   // u32_f64 (double to integer).
582 
583   // Negative values.
584   TestRoundingMode(u32_f64, RN, -0.5, 0);
585   TestRoundingMode(u32_f64, RN, -123456.7, 0, true);
586   TestRoundingMode(u32_f64, RN, static_cast<double>(kMinInt), 0, true);
587   TestRoundingMode(u32_f64, RN, kMinInt - 1.0, 0, true);
588 
589   TestRoundingMode(u32_f64, RM, -0.5, 0, true);
590   TestRoundingMode(u32_f64, RM, -123456.7, 0, true);
591   TestRoundingMode(u32_f64, RM, static_cast<double>(kMinInt), 0, true);
592   TestRoundingMode(u32_f64, RM, kMinInt - 1.0, 0, true);
593 
594   TestRoundingMode(u32_f64, RZ, -0.5, 0);
595   TestRoundingMode(u32_f64, RZ, -123456.7, 0, true);
596   TestRoundingMode(u32_f64, RZ, static_cast<double>(kMinInt), 0, true);
597   TestRoundingMode(u32_f64, RZ, kMinInt - 1.0, 0, true);
598 
599   // Positive values.
600   // kMaxInt is the maximum *signed* integer: 0x7fffffff.
601   static const uint32_t kMaxUInt = 0xffffffffu;
602   TestRoundingMode(u32_f64, RZ,  0, 0);
603   TestRoundingMode(u32_f64, RZ,  0.5, 0);
604   TestRoundingMode(u32_f64, RZ,  123.7,  123);
605   TestRoundingMode(u32_f64, RZ,  123456.2,  123456);
606   TestRoundingMode(u32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt);
607   TestRoundingMode(u32_f64, RZ, (kMaxInt + 0.5), kMaxInt);
608   TestRoundingMode(u32_f64, RZ, (kMaxInt + 1.0),
609                                 static_cast<uint32_t>(kMaxInt) + 1);
610   TestRoundingMode(u32_f64, RZ, (kMaxUInt + 0.5), kMaxUInt);
611   TestRoundingMode(u32_f64, RZ, (kMaxUInt + 1.0), kMaxUInt, true);
612 
613   TestRoundingMode(u32_f64, RM,  0, 0);
614   TestRoundingMode(u32_f64, RM,  0.5, 0);
615   TestRoundingMode(u32_f64, RM,  123.7, 123);
616   TestRoundingMode(u32_f64, RM,  123456.2,  123456);
617   TestRoundingMode(u32_f64, RM, static_cast<double>(kMaxInt), kMaxInt);
618   TestRoundingMode(u32_f64, RM, (kMaxInt + 0.5), kMaxInt);
619   TestRoundingMode(u32_f64, RM, (kMaxInt + 1.0),
620                                 static_cast<uint32_t>(kMaxInt) + 1);
621   TestRoundingMode(u32_f64, RM, (kMaxUInt + 0.5), kMaxUInt);
622   TestRoundingMode(u32_f64, RM, (kMaxUInt + 1.0), kMaxUInt, true);
623 
624   TestRoundingMode(u32_f64, RN,  0, 0);
625   TestRoundingMode(u32_f64, RN,  0.5, 0);
626   TestRoundingMode(u32_f64, RN,  1.5, 2);
627   TestRoundingMode(u32_f64, RN,  123.7, 124);
628   TestRoundingMode(u32_f64, RN,  123456.2,  123456);
629   TestRoundingMode(u32_f64, RN, static_cast<double>(kMaxInt), kMaxInt);
630   TestRoundingMode(u32_f64, RN, (kMaxInt + 0.49), kMaxInt);
631   TestRoundingMode(u32_f64, RN, (kMaxInt + 0.5),
632                                 static_cast<uint32_t>(kMaxInt) + 1);
633   TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.49), kMaxUInt);
634   TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.5), kMaxUInt, true);
635   TestRoundingMode(u32_f64, RN, (kMaxUInt + 1.0), kMaxUInt, true);
636 }
637 
638 
639 TEST(8) {
640   // Test VFP multi load/store with ia_w.
641   CcTest::InitializeVM();
642   Isolate* isolate = CcTest::i_isolate();
643   HandleScope scope(isolate);
644 
645   typedef struct {
646     double a;
647     double b;
648     double c;
649     double d;
650     double e;
651     double f;
652     double g;
653     double h;
654   } D;
655   D d;
656 
657   typedef struct {
658     float a;
659     float b;
660     float c;
661     float d;
662     float e;
663     float f;
664     float g;
665     float h;
666   } F;
667   F f;
668 
669   // Create a function that uses vldm/vstm to move some double and
670   // single precision values around in memory.
671   Assembler assm(isolate, NULL, 0);
672 
673   if (CpuFeatures::IsSupported(VFP2)) {
674     CpuFeatures::Scope scope(VFP2);
675 
676     __ mov(ip, Operand(sp));
677     __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
678     __ sub(fp, ip, Operand(4));
679 
680     __ addi(r4, r0, Operand(offsetof(D, a)));
681     __ vldm(ia_w, r4, d0, d3);
682     __ vldm(ia_w, r4, d4, d7);
683 
684     __ addi(r4, r0, Operand(offsetof(D, a)));
685     __ vstm(ia_w, r4, d6, d7);
686     __ vstm(ia_w, r4, d0, d5);
687 
688     __ addi(r4, r1, Operand(offsetof(F, a)));
689     __ vldm(ia_w, r4, s0, s3);
690     __ vldm(ia_w, r4, s4, s7);
691 
692     __ addi(r4, r1, Operand(offsetof(F, a)));
693     __ vstm(ia_w, r4, s6, s7);
694     __ vstm(ia_w, r4, s0, s5);
695 
696     __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
697 
698     CodeDesc desc;
699     assm.GetCode(&desc);
700     Object* code = isolate->heap()->CreateCode(
701         desc,
702         Code::ComputeFlags(Code::STUB),
703         Handle<Code>())->ToObjectChecked();
704     CHECK(code->IsCode());
705 #ifdef DEBUG
706     Code::cast(code)->Print();
707 #endif
708     F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry());
709     d.a = 1.1;
710     d.b = 2.2;
711     d.c = 3.3;
712     d.d = 4.4;
713     d.e = 5.5;
714     d.f = 6.6;
715     d.g = 7.7;
716     d.h = 8.8;
717 
718     f.a = 1.0;
719     f.b = 2.0;
720     f.c = 3.0;
721     f.d = 4.0;
722     f.e = 5.0;
723     f.f = 6.0;
724     f.g = 7.0;
725     f.h = 8.0;
726 
727     Object* dummy = CALL_GENERATED_CODE(isolate, fn, &d, &f, 0, 0, 0);
728     USE(dummy);
729 
730     CHECK_EQ(7.7, d.a);
731     CHECK_EQ(8.8, d.b);
732     CHECK_EQ(1.1, d.c);
733     CHECK_EQ(2.2, d.d);
734     CHECK_EQ(3.3, d.e);
735     CHECK_EQ(4.4, d.f);
736     CHECK_EQ(5.5, d.g);
737     CHECK_EQ(6.6, d.h);
738 
739     CHECK_EQ(7.0, f.a);
740     CHECK_EQ(8.0, f.b);
741     CHECK_EQ(1.0, f.c);
742     CHECK_EQ(2.0, f.d);
743     CHECK_EQ(3.0, f.e);
744     CHECK_EQ(4.0, f.f);
745     CHECK_EQ(5.0, f.g);
746     CHECK_EQ(6.0, f.h);
747   }
748 }
749 
750 
751 TEST(9) {
752   // Test VFP multi load/store with ia.
753   CcTest::InitializeVM();
754   Isolate* isolate = CcTest::i_isolate();
755   HandleScope scope(isolate);
756 
757   typedef struct {
758     double a;
759     double b;
760     double c;
761     double d;
762     double e;
763     double f;
764     double g;
765     double h;
766   } D;
767   D d;
768 
769   typedef struct {
770     float a;
771     float b;
772     float c;
773     float d;
774     float e;
775     float f;
776     float g;
777     float h;
778   } F;
779   F f;
780 
781   // Create a function that uses vldm/vstm to move some double and
782   // single precision values around in memory.
783   Assembler assm(isolate, NULL, 0);
784 
785   if (CpuFeatures::IsSupported(VFP2)) {
786     CpuFeatures::Scope scope(VFP2);
787 
788     __ mov(ip, Operand(sp));
789     __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
790     __ sub(fp, ip, Operand(4));
791 
792     __ addi(r4, r0, Operand(offsetof(D, a)));
793     __ vldm(ia, r4, d0, d3);
794     __ addi(r4, r4, Operand(4 * 8));
795     __ vldm(ia, r4, d4, d7);
796 
797     __ addi(r4, r0, Operand(offsetof(D, a)));
798     __ vstm(ia, r4, d6, d7);
799     __ addi(r4, r4, Operand(2 * 8));
800     __ vstm(ia, r4, d0, d5);
801 
802     __ addi(r4, r1, Operand(offsetof(F, a)));
803     __ vldm(ia, r4, s0, s3);
804     __ addi(r4, r4, Operand(4 * 4));
805     __ vldm(ia, r4, s4, s7);
806 
807     __ addi(r4, r1, Operand(offsetof(F, a)));
808     __ vstm(ia, r4, s6, s7);
809     __ addi(r4, r4, Operand(2 * 4));
810     __ vstm(ia, r4, s0, s5);
811 
812     __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
813 
814     CodeDesc desc;
815     assm.GetCode(&desc);
816     Object* code = isolate->heap()->CreateCode(
817         desc,
818         Code::ComputeFlags(Code::STUB),
819         Handle<Code>())->ToObjectChecked();
820     CHECK(code->IsCode());
821 #ifdef DEBUG
822     Code::cast(code)->Print();
823 #endif
824     F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry());
825     d.a = 1.1;
826     d.b = 2.2;
827     d.c = 3.3;
828     d.d = 4.4;
829     d.e = 5.5;
830     d.f = 6.6;
831     d.g = 7.7;
832     d.h = 8.8;
833 
834     f.a = 1.0;
835     f.b = 2.0;
836     f.c = 3.0;
837     f.d = 4.0;
838     f.e = 5.0;
839     f.f = 6.0;
840     f.g = 7.0;
841     f.h = 8.0;
842 
843     Object* dummy = CALL_GENERATED_CODE(isolate, fn, &d, &f, 0, 0, 0);
844     USE(dummy);
845 
846     CHECK_EQ(7.7, d.a);
847     CHECK_EQ(8.8, d.b);
848     CHECK_EQ(1.1, d.c);
849     CHECK_EQ(2.2, d.d);
850     CHECK_EQ(3.3, d.e);
851     CHECK_EQ(4.4, d.f);
852     CHECK_EQ(5.5, d.g);
853     CHECK_EQ(6.6, d.h);
854 
855     CHECK_EQ(7.0, f.a);
856     CHECK_EQ(8.0, f.b);
857     CHECK_EQ(1.0, f.c);
858     CHECK_EQ(2.0, f.d);
859     CHECK_EQ(3.0, f.e);
860     CHECK_EQ(4.0, f.f);
861     CHECK_EQ(5.0, f.g);
862     CHECK_EQ(6.0, f.h);
863   }
864 }
865 
866 
867 TEST(10) {
868   // Test VFP multi load/store with db_w.
869   CcTest::InitializeVM();
870   Isolate* isolate = CcTest::i_isolate();
871   HandleScope scope(isolate);
872 
873   typedef struct {
874     double a;
875     double b;
876     double c;
877     double d;
878     double e;
879     double f;
880     double g;
881     double h;
882   } D;
883   D d;
884 
885   typedef struct {
886     float a;
887     float b;
888     float c;
889     float d;
890     float e;
891     float f;
892     float g;
893     float h;
894   } F;
895   F f;
896 
897   // Create a function that uses vldm/vstm to move some double and
898   // single precision values around in memory.
899   Assembler assm(isolate, NULL, 0);
900 
901   if (CpuFeatures::IsSupported(VFP2)) {
902     CpuFeatures::Scope scope(VFP2);
903 
904     __ mov(ip, Operand(sp));
905     __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
906     __ sub(fp, ip, Operand(4));
907 
908     __ addi(r4, r0, Operand(offsetof(D, h) + 8));
909     __ vldm(db_w, r4, d4, d7);
910     __ vldm(db_w, r4, d0, d3);
911 
912     __ addi(r4, r0, Operand(offsetof(D, h) + 8));
913     __ vstm(db_w, r4, d0, d5);
914     __ vstm(db_w, r4, d6, d7);
915 
916     __ addi(r4, r1, Operand(offsetof(F, h) + 4));
917     __ vldm(db_w, r4, s4, s7);
918     __ vldm(db_w, r4, s0, s3);
919 
920     __ addi(r4, r1, Operand(offsetof(F, h) + 4));
921     __ vstm(db_w, r4, s0, s5);
922     __ vstm(db_w, r4, s6, s7);
923 
924     __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
925 
926     CodeDesc desc;
927     assm.GetCode(&desc);
928     Object* code = isolate->heap()->CreateCode(
929         desc,
930         Code::ComputeFlags(Code::STUB),
931         Handle<Code>())->ToObjectChecked();
932     CHECK(code->IsCode());
933 #ifdef DEBUG
934     Code::cast(code)->Print();
935 #endif
936     F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry());
937     d.a = 1.1;
938     d.b = 2.2;
939     d.c = 3.3;
940     d.d = 4.4;
941     d.e = 5.5;
942     d.f = 6.6;
943     d.g = 7.7;
944     d.h = 8.8;
945 
946     f.a = 1.0;
947     f.b = 2.0;
948     f.c = 3.0;
949     f.d = 4.0;
950     f.e = 5.0;
951     f.f = 6.0;
952     f.g = 7.0;
953     f.h = 8.0;
954 
955     Object* dummy = CALL_GENERATED_CODE(isolate, fn, &d, &f, 0, 0, 0);
956     USE(dummy);
957 
958     CHECK_EQ(7.7, d.a);
959     CHECK_EQ(8.8, d.b);
960     CHECK_EQ(1.1, d.c);
961     CHECK_EQ(2.2, d.d);
962     CHECK_EQ(3.3, d.e);
963     CHECK_EQ(4.4, d.f);
964     CHECK_EQ(5.5, d.g);
965     CHECK_EQ(6.6, d.h);
966 
967     CHECK_EQ(7.0, f.a);
968     CHECK_EQ(8.0, f.b);
969     CHECK_EQ(1.0, f.c);
970     CHECK_EQ(2.0, f.d);
971     CHECK_EQ(3.0, f.e);
972     CHECK_EQ(4.0, f.f);
973     CHECK_EQ(5.0, f.g);
974     CHECK_EQ(6.0, f.h);
975   }
976 }
977 
978 
979 TEST(11) {
980   // Test instructions using the carry flag.
981   CcTest::InitializeVM();
982   Isolate* isolate = CcTest::i_isolate();
983   HandleScope scope(isolate);
984 
985   typedef struct {
986     int32_t a;
987     int32_t b;
988     int32_t c;
989     int32_t d;
990   } I;
991   I i;
992 
993   i.a = 0xabcd0001;
994   i.b = 0xabcd0000;
995 
996   Assembler assm(isolate, NULL, 0);
997 
998   // Test HeapObject untagging.
999   __ ldr(r1, MemOperand(r0, offsetof(I, a)));
1000   __ mov(r1, Operand(r1, ASR, 1), SetCC);
1001   __ adc(r1, r1, Operand(r1), LeaveCC, cs);
1002   __ str(r1, MemOperand(r0, offsetof(I, a)));
1003 
1004   __ ldr(r2, MemOperand(r0, offsetof(I, b)));
1005   __ mov(r2, Operand(r2, ASR, 1), SetCC);
1006   __ adc(r2, r2, Operand(r2), LeaveCC, cs);
1007   __ str(r2, MemOperand(r0, offsetof(I, b)));
1008 
1009   // Test corner cases.
1010   __ mov(r1, Operand(0xffffffff));
1011   __ mov(r2, Operand::Zero());
1012   __ mov(r3, Operand(r1, ASR, 1), SetCC);  // Set the carry.
1013   __ adc(r3, r1, Operand(r2));
1014   __ str(r3, MemOperand(r0, offsetof(I, c)));
1015 
1016   __ mov(r1, Operand(0xffffffff));
1017   __ mov(r2, Operand::Zero());
1018   __ mov(r3, Operand(r2, ASR, 1), SetCC);  // Unset the carry.
1019   __ adc(r3, r1, Operand(r2));
1020   __ str(r3, MemOperand(r0, offsetof(I, d)));
1021 
1022   __ mov(pc, Operand(lr));
1023 
1024   CodeDesc desc;
1025   assm.GetCode(&desc);
1026   Object* code = isolate->heap()->CreateCode(
1027       desc,
1028       Code::ComputeFlags(Code::STUB),
1029       Handle<Code>())->ToObjectChecked();
1030   CHECK(code->IsCode());
1031 #ifdef DEBUG
1032   Code::cast(code)->Print();
1033 #endif
1034   F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry());
1035   Object* dummy = CALL_GENERATED_CODE(isolate, f, &i, 0, 0, 0, 0);
1036   USE(dummy);
1037 
1038   CHECK_EQ(0xabcd0001, i.a);
1039   CHECK_EQ(static_cast<int32_t>(0xabcd0000) >> 1, i.b);
1040   CHECK_EQ(0x00000000, i.c);
1041   CHECK_EQ(0xffffffff, i.d);
1042 }
1043 
1044 
1045 TEST(12) {
1046   // Test chaining of label usages within instructions (issue 1644).
1047   CcTest::InitializeVM();
1048   Isolate* isolate = CcTest::i_isolate();
1049   HandleScope scope(isolate);
1050 
1051   Assembler assm(isolate, NULL, 0);
1052   Label target;
1053   __ b(eq, &target);
1054   __ b(ne, &target);
1055   __ bind(&target);
1056   __ nop();
1057 }
1058 #endif
1059 
1060 #undef __
1061