v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
test-assembler-arm.cc
Go to the documentation of this file.
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 "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 
47 
48 
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 
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 
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 
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 {
430 };
431 
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 
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 
646  CpuFeatures::Scope scope(VFP2);
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 
757  CpuFeatures::Scope scope(VFP2);
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 
872  CpuFeatures::Scope scope(VFP2);
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 __
Object *(* F3)(void *p0, int p1, int p2, int p3, int p4)
const int kMinInt
Definition: globals.h:211
#define CHECK_EQ(expected, value)
Definition: checks.h:219
const Register r3
const SwVfpRegister s7
const DwVfpRegister d5
const DwVfpRegister d0
const SwVfpRegister s16
#define __
int int32_t
Definition: unicode.cc:47
static bool IsSupported(CpuFeature f)
const int kMaxInt
Definition: globals.h:210
Object *(* F2)(int x, int y, int p2, int p3, int p4)
const DwVfpRegister d6
#define CHECK(condition)
Definition: checks.h:56
const Register r2
static Code * cast(Object *obj)
const SwVfpRegister s6
const SwVfpRegister s31
const Register sp
const SwVfpRegister s3
#define UNREACHABLE()
Definition: checks.h:50
#define OFFSET_OF(type, field)
Definition: globals.h:273
const Register ip
void GetCode(CodeDesc *desc)
const DwVfpRegister d7
Object *(* F1)(int x, int p1, int p2, int p3, int p4)
const Register pc
static Flags ComputeFlags(Kind kind, InlineCacheState ic_state=UNINITIALIZED, ExtraICState extra_ic_state=kNoExtraICState, StubType type=NORMAL, int argc=-1, InlineCacheHolderFlag holder=OWN_MAP)
Definition: objects-inl.h:3491
#define CALL_GENERATED_CODE(entry, p0, p1, p2, p3, p4)
Definition: simulator-arm.h:48
const uint32_t kVFPExceptionMask
const SwVfpRegister s0
const DwVfpRegister d3
const Register r0
const SwVfpRegister s5
#define T(name, string, precedence)
Definition: token.cc:48
const Register lr
const Register r1
#define HEAP
Definition: isolate.h:1433
void USE(T)
Definition: globals.h:289
const SwVfpRegister s4
const DwVfpRegister d2
Object *(* F4)(void *p0, void *p1, int p2, int p3, int p4)
bool IsEmpty() const
Definition: v8.h:209
#define FACTORY
Definition: isolate.h:1434
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
Definition: flags.cc:301
static Persistent< Context > New(ExtensionConfiguration *extensions=NULL, Handle< ObjectTemplate > global_template=Handle< ObjectTemplate >(), Handle< Value > global_object=Handle< Value >())
Definition: api.cc:4411
const uint32_t kVFPRoundingModeMask
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
const DwVfpRegister d1
const Register fp
signed short int16_t
Definition: unicode.cc:45
const DwVfpRegister d4
const Register r4