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