1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h"
29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "test/cctest/cctest.h"
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm/assembler-arm-inl.h"
32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/arm/simulator-arm.h"
33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/disassembler.h"
34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/factory.h"
35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ostreams.h"
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing namespace v8::internal;
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Define these function prototypes to match JSEntryFunction in execution.cc.
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktypedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktypedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochtypedef Object* (*F3)(void* p0, int p1, int p2, int p3, int p4);
448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochtypedef Object* (*F4)(void* p0, void* p1, int p2, int p3, int p4);
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ assm.
48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(0) {
50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::InitializeVM();
51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler assm(isolate, NULL, 0);
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r0, r0, Operand(r1));
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(pc, Operand(lr));
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CodeDesc desc;
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  assm.GetCode(&desc);
61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> code = isolate->factory()->NewCode(
62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  OFStream os(stdout);
65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  code->Print(os);
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  F2 f = FUNCTION_CAST<F2>(code->entry());
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 3, 4, 0, 0, 0));
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ::printf("f() = %d\n", res);
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(7, res);
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(1) {
75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::InitializeVM();
76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler assm(isolate, NULL, 0);
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label L, C;
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r1, Operand(r0));
83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(r0, Operand::Zero());
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(&C);
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&L);
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r0, r0, Operand(r1));
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ sub(r1, r1, Operand(1));
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&C);
91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ teq(r1, Operand::Zero());
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &L);
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(pc, Operand(lr));
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CodeDesc desc;
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  assm.GetCode(&desc);
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> code = isolate->factory()->NewCode(
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  OFStream os(stdout);
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  code->Print(os);
102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  F1 f = FUNCTION_CAST<F1>(code->entry());
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 100, 0, 0, 0, 0));
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ::printf("f() = %d\n", res);
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(5050, res);
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(2) {
111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::InitializeVM();
112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler assm(isolate, NULL, 0);
116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label L, C;
117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r1, Operand(r0));
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(1));
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(&C);
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&L);
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mul(r0, r1, r0);
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ sub(r1, r1, Operand(1));
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ bind(&C);
127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ teq(r1, Operand::Zero());
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ b(ne, &L);
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(pc, Operand(lr));
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // some relocated stuff here, not executed
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ RecordComment("dead code, just testing relocations");
133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(r0, Operand(isolate->factory()->true_value()));
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ RecordComment("dead code, just testing immediate operands");
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(-1));
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(0xFF000000));
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(0xF0F0F0F0));
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r0, Operand(0xFFF0FFFF));
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CodeDesc desc;
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  assm.GetCode(&desc);
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> code = isolate->factory()->NewCode(
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  OFStream os(stdout);
146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  code->Print(os);
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  F1 f = FUNCTION_CAST<F1>(code->entry());
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 10, 0, 0, 0, 0));
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ::printf("f() = %d\n", res);
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3628800, res);
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(3) {
156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::InitializeVM();
157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  typedef struct {
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int i;
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    char c;
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int16_t s;
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } T;
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  T t;
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler assm(isolate, NULL, 0);
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label L, C;
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(ip, Operand(sp));
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ sub(fp, ip, Operand(4));
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r4, Operand(r0));
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldr(r0, MemOperand(r4, OFFSET_OF(T, i)));
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r2, Operand(r0, ASR, 1));
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ str(r2, MemOperand(r4, OFFSET_OF(T, i)));
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldrsb(r2, MemOperand(r4, OFFSET_OF(T, c)));
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r0, r2, Operand(r0));
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r2, Operand(r2, LSL, 2));
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ strb(r2, MemOperand(r4, OFFSET_OF(T, c)));
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldrsh(r2, MemOperand(r4, OFFSET_OF(T, s)));
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ add(r0, r2, Operand(r0));
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ mov(r2, Operand(r2, ASR, 3));
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ strh(r2, MemOperand(r4, OFFSET_OF(T, s)));
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CodeDesc desc;
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  assm.GetCode(&desc);
189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> code = isolate->factory()->NewCode(
190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  OFStream os(stdout);
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  code->Print(os);
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  F3 f = FUNCTION_CAST<F3>(code->entry());
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  t.i = 100000;
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  t.c = 10;
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  t.s = 1000;
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0));
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ::printf("f() = %d\n", res);
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(101010, res);
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(100000/2, t.i);
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(10*4, t.c);
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1000/8, t.s);
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
208d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeTEST(4) {
209d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Test the VFP floating point instructions.
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::InitializeVM();
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
213d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
214d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  typedef struct {
215d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    double a;
216d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    double b;
217d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    double c;
21880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    double d;
21980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    double e;
22080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    double f;
2211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    double g;
2221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    double h;
22380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    int i;
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    double j;
22544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    double m;
22644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    double n;
22780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    float x;
22880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    float y;
229d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  } T;
230d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  T t;
231d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
232d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Create a function that accepts &t, and loads, manipulates, and stores
23380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // the doubles and floats.
234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler assm(isolate, NULL, 0);
235d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  Label L, C;
236d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
237d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
2388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (CpuFeatures::IsSupported(VFP3)) {
239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CpuFeatureScope scope(&assm, VFP3);
240d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
241d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ mov(ip, Operand(sp));
242d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
243d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ sub(fp, ip, Operand(4));
244d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
245d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ mov(r4, Operand(r0));
246d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ vldr(d6, r4, OFFSET_OF(T, a));
247d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ vldr(d7, r4, OFFSET_OF(T, b));
248d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ vadd(d5, d6, d7);
249d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ vstr(d5, r4, OFFSET_OF(T, c));
250d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vmla(d5, d6, d7);
252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vmls(d5, d5, d6);
253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
254d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ vmov(r2, r3, d5);
255d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ vmov(d4, r2, r3);
256d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ vstr(d4, r4, OFFSET_OF(T, b));
257d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
25880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Load t.x and t.y, switch values, and store back to the struct.
25980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ vldr(s0, r4, OFFSET_OF(T, x));
26080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ vldr(s31, r4, OFFSET_OF(T, y));
26180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ vmov(s16, s0);
26280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ vmov(s0, s31);
26380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ vmov(s31, s16);
26480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ vstr(s0, r4, OFFSET_OF(T, x));
26580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ vstr(s31, r4, OFFSET_OF(T, y));
26680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
26780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Move a literal into a register that can be encoded in the instruction.
26880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ vmov(d4, 1.0);
26980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ vstr(d4, r4, OFFSET_OF(T, e));
27080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
27180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Move a literal into a register that requires 64 bits to encode.
27280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // 0x3ff0000010000000 = 1.000000059604644775390625
27380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ vmov(d4, 1.000000059604644775390625);
27480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ vstr(d4, r4, OFFSET_OF(T, d));
27580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
27680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Convert from floating point to integer.
27780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ vmov(d4, 2.0);
27880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ vcvt_s32_f64(s31, d4);
27980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ vstr(s31, r4, OFFSET_OF(T, i));
28080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
28180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Convert from integer to floating point.
28280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ mov(lr, Operand(42));
28380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ vmov(s31, lr);
28480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ vcvt_f64_s32(d4, s31);
28580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    __ vstr(d4, r4, OFFSET_OF(T, f));
2861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Convert from fixed point to floating point.
288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(lr, Operand(2468));
289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vmov(s8, lr);
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vcvt_f64_s32(d4, 2);
291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vstr(d4, r4, OFFSET_OF(T, j));
292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Test vabs.
2941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ vldr(d1, r4, OFFSET_OF(T, g));
2951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ vabs(d0, d1);
2961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ vstr(d0, r4, OFFSET_OF(T, g));
2971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ vldr(d2, r4, OFFSET_OF(T, h));
2981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ vabs(d0, d2);
2991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ vstr(d0, r4, OFFSET_OF(T, h));
3001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
30144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Test vneg.
30244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ vldr(d1, r4, OFFSET_OF(T, m));
30344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ vneg(d0, d1);
30444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ vstr(d0, r4, OFFSET_OF(T, m));
30544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ vldr(d1, r4, OFFSET_OF(T, n));
30644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ vneg(d0, d1);
30744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    __ vstr(d0, r4, OFFSET_OF(T, n));
30844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
309d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
310d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
311d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    CodeDesc desc;
312d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    assm.GetCode(&desc);
313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Code> code = isolate->factory()->NewCode(
314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
315d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#ifdef DEBUG
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    OFStream os(stdout);
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    code->Print(os);
318d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke#endif
319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    F3 f = FUNCTION_CAST<F3>(code->entry());
320d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    t.a = 1.5;
321d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    t.b = 2.75;
322d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    t.c = 17.17;
32380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    t.d = 0.0;
32480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    t.e = 0.0;
32580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    t.f = 0.0;
3261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    t.g = -2718.2818;
3271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    t.h = 31415926.5;
32880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    t.i = 0;
329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.j = 0;
33044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    t.m = -2718.2818;
33144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    t.n = 123.456;
33280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    t.x = 4.5;
33380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    t.y = 9.0;
334d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
335d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    USE(dummy);
33680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    CHECK_EQ(4.5, t.y);
33780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    CHECK_EQ(9.0, t.x);
33844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    CHECK_EQ(-123.456, t.n);
33944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    CHECK_EQ(2718.2818, t.m);
34080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    CHECK_EQ(2, t.i);
3411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    CHECK_EQ(2718.2818, t.g);
3421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    CHECK_EQ(31415926.5, t.h);
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(617.0, t.j);
34480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    CHECK_EQ(42.0, t.f);
34580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    CHECK_EQ(1.0, t.e);
34680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    CHECK_EQ(1.000000059604644775390625, t.d);
347d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    CHECK_EQ(4.25, t.c);
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(-4.1875, t.b);
349d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    CHECK_EQ(1.5, t.a);
350d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
351d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
352d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
3537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3547f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen MurdochTEST(5) {
3557f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  // Test the ARMv7 bitfield instructions.
356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::InitializeVM();
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
3597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler assm(isolate, NULL, 0);
3617f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (CpuFeatures::IsSupported(ARMv7)) {
363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CpuFeatureScope scope(&assm, ARMv7);
3647f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    // On entry, r0 = 0xAAAAAAAA = 0b10..10101010.
3657f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ ubfx(r0, r0, 1, 12);  // 0b00..010101010101 = 0x555
3667f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ sbfx(r0, r0, 0, 5);   // 0b11..111111110101 = -11
3677f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ bfc(r0, 1, 3);        // 0b11..111111110001 = -15
3687f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ mov(r1, Operand(7));
3697f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ bfi(r0, r1, 3, 3);    // 0b11..111111111001 = -7
3707f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    __ mov(pc, Operand(lr));
3717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
3727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    CodeDesc desc;
3737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    assm.GetCode(&desc);
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Code> code = isolate->factory()->NewCode(
375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
3767f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch#ifdef DEBUG
377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    OFStream os(stdout);
378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    code->Print(os);
3797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch#endif
380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    F1 f = FUNCTION_CAST<F1>(code->entry());
3817f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    int res = reinterpret_cast<int>(
3827f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch                CALL_GENERATED_CODE(f, 0xAAAAAAAA, 0, 0, 0, 0));
3837f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    ::printf("f() = %d\n", res);
3847f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch    CHECK_EQ(-7, res);
3857f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch  }
3867f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch}
3877f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch
38850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
38950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian MonsenTEST(6) {
39050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  // Test saturating instructions.
391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::InitializeVM();
392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
39450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler assm(isolate, NULL, 0);
39650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
3978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (CpuFeatures::IsSupported(ARMv7)) {
398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CpuFeatureScope scope(&assm, ARMv7);
39950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    __ usat(r1, 8, Operand(r0));           // Sat 0xFFFF to 0-255 = 0xFF.
40050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    __ usat(r2, 12, Operand(r0, ASR, 9));  // Sat (0xFFFF>>9) to 0-4095 = 0x7F.
40150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    __ usat(r3, 1, Operand(r0, LSL, 16));  // Sat (0xFFFF<<16) to 0-1 = 0x0.
40250ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    __ add(r0, r1, Operand(r2));
40350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    __ add(r0, r0, Operand(r3));
40450ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    __ mov(pc, Operand(lr));
40550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
40650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    CodeDesc desc;
40750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    assm.GetCode(&desc);
408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Code> code = isolate->factory()->NewCode(
409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
41050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen#ifdef DEBUG
411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    OFStream os(stdout);
412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    code->Print(os);
41350ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen#endif
414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    F1 f = FUNCTION_CAST<F1>(code->entry());
41550ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    int res = reinterpret_cast<int>(
41650ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen                CALL_GENERATED_CODE(f, 0xFFFF, 0, 0, 0, 0));
41750ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    ::printf("f() = %d\n", res);
41850ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen    CHECK_EQ(382, res);
41950ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen  }
42050ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen}
42150ef84f5fad2def87d3fbc737bec4a32711fdef4Kristian Monsen
42290bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner
4231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockenum VCVTTypes {
4241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  s32_f64,
4251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  u32_f64
4261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block};
4271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockstatic void TestRoundingMode(VCVTTypes types,
4291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             VFPRoundingMode mode,
4301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             double value,
4311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             int expected,
4321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                             bool expected_exception = false) {
433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
43590bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner
436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler assm(isolate, NULL, 0);
43790bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner
4388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (CpuFeatures::IsSupported(VFP3)) {
439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CpuFeatureScope scope(&assm, VFP3);
44090bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner
4411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Label wrong_exception;
4421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ vmrs(r1);
4441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Set custom FPSCR.
4451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bic(r2, r1, Operand(kVFPRoundingModeMask | kVFPExceptionMask));
4461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ orr(r2, r2, Operand(mode));
4471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ vmsr(r2);
4481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Load value, convert, and move back result to r0 if everything went well.
4501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ vmov(d1, value);
4511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    switch (types) {
4521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      case s32_f64:
4531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ vcvt_s32_f64(s0, d1, kFPSCRRounding);
4541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        break;
4551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      case u32_f64:
4571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        __ vcvt_u32_f64(s0, d1, kFPSCRRounding);
4581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        break;
4591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
4601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      default:
4611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        UNREACHABLE();
4621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        break;
4631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
4641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Check for vfp exceptions
4651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ vmrs(r2);
4661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ tst(r2, Operand(kVFPExceptionMask));
4671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Check that we behaved as expected.
4681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ b(&wrong_exception,
4691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block         expected_exception ? eq : ne);
4701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // There was no exception. Retrieve the result and return.
4711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ vmov(r0, s0);
4721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(pc, Operand(lr));
47390bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner
4741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // The exception behaviour is not what we expected.
4751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Load a special value and return.
4761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ bind(&wrong_exception);
4771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(r0, Operand(11223344));
4781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ mov(pc, Operand(lr));
47990bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner
4801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    CodeDesc desc;
4811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    assm.GetCode(&desc);
482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Code> code = isolate->factory()->NewCode(
483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
48490bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner#ifdef DEBUG
485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    OFStream os(stdout);
486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    code->Print(os);
48790bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner#endif
488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    F1 f = FUNCTION_CAST<F1>(code->entry());
4891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int res = reinterpret_cast<int>(
4901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0));
4911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ::printf("res = %d\n", res);
4921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    CHECK_EQ(expected, res);
4931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
49490bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner}
49590bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner
49690bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner
49790bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell BrennerTEST(7) {
498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::InitializeVM();
49990bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner  // Test vfp rounding modes.
50090bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner
5011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // s32_f64 (double to integer).
5021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RN,  0, 0);
5041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RN,  0.5, 0);
5051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RN, -0.5, 0);
5061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RN,  1.5, 2);
5071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RN, -1.5, -2);
5081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RN,  123.7, 124);
5091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RN, -123.7, -124);
5101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RN,  123456.2,  123456);
5111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RN, -123456.2, -123456);
5121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RN, static_cast<double>(kMaxInt), kMaxInt);
5131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RN, (kMaxInt + 0.49), kMaxInt);
5141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RN, (kMaxInt + 1.0), kMaxInt, true);
5151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RN, (kMaxInt + 0.5), kMaxInt, true);
5161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RN, static_cast<double>(kMinInt), kMinInt);
5171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RN, (kMinInt - 0.5), kMinInt);
5181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RN, (kMinInt - 1.0), kMinInt, true);
5191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RN, (kMinInt - 0.51), kMinInt, true);
5201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RM,  0, 0);
5221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RM,  0.5, 0);
5231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RM, -0.5, -1);
5241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RM,  123.7, 123);
5251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RM, -123.7, -124);
5261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RM,  123456.2,  123456);
5271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RM, -123456.2, -123457);
5281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RM, static_cast<double>(kMaxInt), kMaxInt);
5291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RM, (kMaxInt + 0.5), kMaxInt);
5301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RM, (kMaxInt + 1.0), kMaxInt, true);
5311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RM, static_cast<double>(kMinInt), kMinInt);
5321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RM, (kMinInt - 0.5), kMinInt, true);
5331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RM, (kMinInt + 0.5), kMinInt);
5341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RZ,  0, 0);
5361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RZ,  0.5, 0);
5371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RZ, -0.5, 0);
5381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RZ,  123.7,  123);
5391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RZ, -123.7, -123);
5401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RZ,  123456.2,  123456);
5411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RZ, -123456.2, -123456);
5421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt);
5431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RZ, (kMaxInt + 0.5), kMaxInt);
5441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RZ, (kMaxInt + 1.0), kMaxInt, true);
5451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RZ, static_cast<double>(kMinInt), kMinInt);
5461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RZ, (kMinInt - 0.5), kMinInt);
5471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(s32_f64, RZ, (kMinInt - 1.0), kMinInt, true);
5481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // u32_f64 (double to integer).
5511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Negative values.
5531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RN, -0.5, 0);
5541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RN, -123456.7, 0, true);
5551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RN, static_cast<double>(kMinInt), 0, true);
5561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RN, kMinInt - 1.0, 0, true);
5571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RM, -0.5, 0, true);
5591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RM, -123456.7, 0, true);
5601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RM, static_cast<double>(kMinInt), 0, true);
5611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RM, kMinInt - 1.0, 0, true);
5621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RZ, -0.5, 0);
5641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RZ, -123456.7, 0, true);
5651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RZ, static_cast<double>(kMinInt), 0, true);
5661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RZ, kMinInt - 1.0, 0, true);
5671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Positive values.
5691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // kMaxInt is the maximum *signed* integer: 0x7fffffff.
5701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  static const uint32_t kMaxUInt = 0xffffffffu;
5711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RZ,  0, 0);
5721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RZ,  0.5, 0);
5731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RZ,  123.7,  123);
5741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RZ,  123456.2,  123456);
5751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt);
5761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RZ, (kMaxInt + 0.5), kMaxInt);
5771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RZ, (kMaxInt + 1.0),
5781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                static_cast<uint32_t>(kMaxInt) + 1);
5791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RZ, (kMaxUInt + 0.5), kMaxUInt);
5801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RZ, (kMaxUInt + 1.0), kMaxUInt, true);
5811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RM,  0, 0);
5831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RM,  0.5, 0);
5841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RM,  123.7, 123);
5851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RM,  123456.2,  123456);
5861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RM, static_cast<double>(kMaxInt), kMaxInt);
5871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RM, (kMaxInt + 0.5), kMaxInt);
5881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RM, (kMaxInt + 1.0),
5891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                static_cast<uint32_t>(kMaxInt) + 1);
5901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RM, (kMaxUInt + 0.5), kMaxUInt);
5911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RM, (kMaxUInt + 1.0), kMaxUInt, true);
5921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RN,  0, 0);
5941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RN,  0.5, 0);
5951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RN,  1.5, 2);
5961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RN,  123.7, 124);
5971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RN,  123456.2,  123456);
5981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RN, static_cast<double>(kMaxInt), kMaxInt);
5991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RN, (kMaxInt + 0.49), kMaxInt);
6001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RN, (kMaxInt + 0.5),
6011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                static_cast<uint32_t>(kMaxInt) + 1);
6021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.49), kMaxUInt);
6031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.5), kMaxUInt, true);
6041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  TestRoundingMode(u32_f64, RN, (kMaxUInt + 1.0), kMaxUInt, true);
60590bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner}
60690bac256d9f48d4ee52d0e08bf0e5cad57b3c51cRussell Brenner
607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
6088b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochTEST(8) {
6098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Test VFP multi load/store with ia_w.
610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::InitializeVM();
611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
6138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
6148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  typedef struct {
6158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    double a;
6168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    double b;
6178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    double c;
6188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    double d;
6198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    double e;
6208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    double f;
6218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    double g;
6228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    double h;
6238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } D;
6248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  D d;
6258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
6268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  typedef struct {
6278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    float a;
6288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    float b;
6298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    float c;
6308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    float d;
6318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    float e;
6328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    float f;
6338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    float g;
6348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    float h;
6358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } F;
6368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  F f;
6378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
6388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Create a function that uses vldm/vstm to move some double and
6398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // single precision values around in memory.
640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler assm(isolate, NULL, 0);
6418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(ip, Operand(sp));
643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sub(fp, ip, Operand(4));
6458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(r4, r0, Operand(OFFSET_OF(D, a)));
647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vldm(ia_w, r4, d0, d3);
648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vldm(ia_w, r4, d4, d7);
6498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(r4, r0, Operand(OFFSET_OF(D, a)));
651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vstm(ia_w, r4, d6, d7);
652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vstm(ia_w, r4, d0, d5);
6538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(r4, r1, Operand(OFFSET_OF(F, a)));
655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vldm(ia_w, r4, s0, s3);
656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vldm(ia_w, r4, s4, s7);
6578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(r4, r1, Operand(OFFSET_OF(F, a)));
659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vstm(ia_w, r4, s6, s7);
660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vstm(ia_w, r4, s0, s5);
6618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
6638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeDesc desc;
665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assm.GetCode(&desc);
666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> code = isolate->factory()->NewCode(
667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
6688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#ifdef DEBUG
669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  OFStream os(stdout);
670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  code->Print(os);
6718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif
672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  F4 fn = FUNCTION_CAST<F4>(code->entry());
673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  d.a = 1.1;
674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  d.b = 2.2;
675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  d.c = 3.3;
676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  d.d = 4.4;
677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  d.e = 5.5;
678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  d.f = 6.6;
679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  d.g = 7.7;
680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  d.h = 8.8;
681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f.a = 1.0;
683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f.b = 2.0;
684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f.c = 3.0;
685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f.d = 4.0;
686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f.e = 5.0;
687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f.f = 6.0;
688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f.g = 7.0;
689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f.h = 8.0;
690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  USE(dummy);
6938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(7.7, d.a);
695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(8.8, d.b);
696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1.1, d.c);
697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2.2, d.d);
698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(3.3, d.e);
699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(4.4, d.f);
700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(5.5, d.g);
701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(6.6, d.h);
702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(7.0, f.a);
704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(8.0, f.b);
705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1.0, f.c);
706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2.0, f.d);
707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(3.0, f.e);
708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(4.0, f.f);
709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(5.0, f.g);
710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(6.0, f.h);
7118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
7128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
7138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
7148b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochTEST(9) {
7158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Test VFP multi load/store with ia.
716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::InitializeVM();
717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
7198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
7208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  typedef struct {
7218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    double a;
7228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    double b;
7238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    double c;
7248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    double d;
7258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    double e;
7268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    double f;
7278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    double g;
7288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    double h;
7298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } D;
7308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  D d;
7318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
7328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  typedef struct {
7338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    float a;
7348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    float b;
7358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    float c;
7368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    float d;
7378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    float e;
7388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    float f;
7398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    float g;
7408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    float h;
7418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } F;
7428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  F f;
7438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
7448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Create a function that uses vldm/vstm to move some double and
7458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // single precision values around in memory.
746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler assm(isolate, NULL, 0);
7478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(ip, Operand(sp));
749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sub(fp, ip, Operand(4));
7518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(r4, r0, Operand(OFFSET_OF(D, a)));
753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vldm(ia, r4, d0, d3);
754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(r4, r4, Operand(4 * 8));
755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vldm(ia, r4, d4, d7);
7568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(r4, r0, Operand(OFFSET_OF(D, a)));
758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vstm(ia, r4, d6, d7);
759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(r4, r4, Operand(2 * 8));
760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vstm(ia, r4, d0, d5);
7618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(r4, r1, Operand(OFFSET_OF(F, a)));
763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vldm(ia, r4, s0, s3);
764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(r4, r4, Operand(4 * 4));
765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vldm(ia, r4, s4, s7);
7668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(r4, r1, Operand(OFFSET_OF(F, a)));
768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vstm(ia, r4, s6, s7);
769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(r4, r4, Operand(2 * 4));
770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vstm(ia, r4, s0, s5);
7718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
7738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeDesc desc;
775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assm.GetCode(&desc);
776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> code = isolate->factory()->NewCode(
777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
7788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#ifdef DEBUG
779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  OFStream os(stdout);
780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  code->Print(os);
7818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif
782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  F4 fn = FUNCTION_CAST<F4>(code->entry());
783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  d.a = 1.1;
784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  d.b = 2.2;
785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  d.c = 3.3;
786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  d.d = 4.4;
787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  d.e = 5.5;
788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  d.f = 6.6;
789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  d.g = 7.7;
790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  d.h = 8.8;
791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f.a = 1.0;
793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f.b = 2.0;
794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f.c = 3.0;
795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f.d = 4.0;
796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f.e = 5.0;
797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f.f = 6.0;
798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f.g = 7.0;
799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f.h = 8.0;
800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  USE(dummy);
8038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(7.7, d.a);
805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(8.8, d.b);
806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1.1, d.c);
807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2.2, d.d);
808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(3.3, d.e);
809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(4.4, d.f);
810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(5.5, d.g);
811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(6.6, d.h);
812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(7.0, f.a);
814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(8.0, f.b);
815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1.0, f.c);
816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2.0, f.d);
817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(3.0, f.e);
818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(4.0, f.f);
819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(5.0, f.g);
820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(6.0, f.h);
8218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
8228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
8238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
8248b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochTEST(10) {
8258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Test VFP multi load/store with db_w.
826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::InitializeVM();
827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
8298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
8308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  typedef struct {
8318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    double a;
8328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    double b;
8338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    double c;
8348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    double d;
8358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    double e;
8368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    double f;
8378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    double g;
8388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    double h;
8398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } D;
8408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  D d;
8418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
8428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  typedef struct {
8438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    float a;
8448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    float b;
8458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    float c;
8468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    float d;
8478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    float e;
8488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    float f;
8498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    float g;
8508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    float h;
8518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  } F;
8528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  F f;
8538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
8548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Create a function that uses vldm/vstm to move some double and
8558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // single precision values around in memory.
856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler assm(isolate, NULL, 0);
8578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(ip, Operand(sp));
859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ sub(fp, ip, Operand(4));
8618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(r4, r0, Operand(OFFSET_OF(D, h) + 8));
863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vldm(db_w, r4, d4, d7);
864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vldm(db_w, r4, d0, d3);
8658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(r4, r0, Operand(OFFSET_OF(D, h) + 8));
867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vstm(db_w, r4, d0, d5);
868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vstm(db_w, r4, d6, d7);
8698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(r4, r1, Operand(OFFSET_OF(F, h) + 4));
871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vldm(db_w, r4, s4, s7);
872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vldm(db_w, r4, s0, s3);
8738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(r4, r1, Operand(OFFSET_OF(F, h) + 4));
875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vstm(db_w, r4, s0, s5);
876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vstm(db_w, r4, s6, s7);
8778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
8798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeDesc desc;
881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assm.GetCode(&desc);
882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> code = isolate->factory()->NewCode(
883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
8848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#ifdef DEBUG
885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  OFStream os(stdout);
886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  code->Print(os);
8878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#endif
888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  F4 fn = FUNCTION_CAST<F4>(code->entry());
889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  d.a = 1.1;
890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  d.b = 2.2;
891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  d.c = 3.3;
892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  d.d = 4.4;
893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  d.e = 5.5;
894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  d.f = 6.6;
895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  d.g = 7.7;
896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  d.h = 8.8;
897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f.a = 1.0;
899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f.b = 2.0;
900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f.c = 3.0;
901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f.d = 4.0;
902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f.e = 5.0;
903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f.f = 6.0;
904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f.g = 7.0;
905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  f.h = 8.0;
906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0);
908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  USE(dummy);
9098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(7.7, d.a);
911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(8.8, d.b);
912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1.1, d.c);
913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2.2, d.d);
914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(3.3, d.e);
915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(4.4, d.f);
916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(5.5, d.g);
917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(6.6, d.h);
918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(7.0, f.a);
920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(8.0, f.b);
921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(1.0, f.c);
922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(2.0, f.d);
923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(3.0, f.e);
924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(4.0, f.f);
925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(5.0, f.g);
926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(6.0, f.h);
9278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
9288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochTEST(11) {
931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Test instructions using the carry flag.
932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::InitializeVM();
933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
935257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  typedef struct {
937257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    int32_t a;
938257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    int32_t b;
939257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    int32_t c;
940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    int32_t d;
941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  } I;
942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  I i;
943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  i.a = 0xabcd0001;
945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  i.b = 0xabcd0000;
946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler assm(isolate, NULL, 0);
948257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Test HeapObject untagging.
950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ldr(r1, MemOperand(r0, OFFSET_OF(I, a)));
951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(r1, Operand(r1, ASR, 1), SetCC);
952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ adc(r1, r1, Operand(r1), LeaveCC, cs);
953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ str(r1, MemOperand(r0, OFFSET_OF(I, a)));
954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ ldr(r2, MemOperand(r0, OFFSET_OF(I, b)));
956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(r2, Operand(r2, ASR, 1), SetCC);
957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ adc(r2, r2, Operand(r2), LeaveCC, cs);
958257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ str(r2, MemOperand(r0, OFFSET_OF(I, b)));
959257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
960257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  // Test corner cases.
961257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(r1, Operand(0xffffffff));
962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(r2, Operand::Zero());
963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(r3, Operand(r1, ASR, 1), SetCC);  // Set the carry.
964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ adc(r3, r1, Operand(r2));
965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ str(r3, MemOperand(r0, OFFSET_OF(I, c)));
966257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(r1, Operand(0xffffffff));
968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(r2, Operand::Zero());
969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(r3, Operand(r2, ASR, 1), SetCC);  // Unset the carry.
970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ adc(r3, r1, Operand(r2));
971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ str(r3, MemOperand(r0, OFFSET_OF(I, d)));
972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
973257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  __ mov(pc, Operand(lr));
974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CodeDesc desc;
976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  assm.GetCode(&desc);
977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> code = isolate->factory()->NewCode(
978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef DEBUG
980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  OFStream os(stdout);
981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  code->Print(os);
982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif
983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  F3 f = FUNCTION_CAST<F3>(code->entry());
984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  Object* dummy = CALL_GENERATED_CODE(f, &i, 0, 0, 0, 0);
985257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  USE(dummy);
986257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_EQ(0xabcd0001, i.a);
988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_EQ(static_cast<int32_t>(0xabcd0000) >> 1, i.b);
989257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_EQ(0x00000000, i.c);
990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  CHECK_EQ(0xffffffff, i.d);
991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}
992257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch
99369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
99469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen MurdochTEST(12) {
99569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  // Test chaining of label usages within instructions (issue 1644).
996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::InitializeVM();
997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
99969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler assm(isolate, NULL, 0);
100169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  Label target;
100269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ b(eq, &target);
100369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ b(ne, &target);
100469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ bind(&target);
100569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch  __ nop();
100669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch}
100769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch
1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(13) {
1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test VFP instructions using registers d16-d31.
1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::InitializeVM();
1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (!CpuFeatures::IsSupported(VFP32DREGS)) {
1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    return;
1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  typedef struct {
1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    double a;
1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    double b;
1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    double c;
1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    double x;
1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    double y;
1025b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    double z;
1026b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    double i;
1027b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    double j;
1028b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    double k;
1029b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t low;
1030b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t high;
1031b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } T;
1032b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  T t;
1033b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1034b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Create a function that accepts &t, and loads, manipulates, and stores
1035b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the doubles and floats.
1036b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler assm(isolate, NULL, 0);
1037b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label L, C;
1038b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1039b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1040b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (CpuFeatures::IsSupported(VFP3)) {
1041b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CpuFeatureScope scope(&assm, VFP3);
1042b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1043b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ stm(db_w, sp, r4.bit() | lr.bit());
1044b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1045b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Load a, b, c into d16, d17, d18.
1046b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(r4, Operand(r0));
1047b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vldr(d16, r4, OFFSET_OF(T, a));
1048b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vldr(d17, r4, OFFSET_OF(T, b));
1049b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vldr(d18, r4, OFFSET_OF(T, c));
1050b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1051b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vneg(d25, d16);
1052b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vadd(d25, d25, d17);
1053b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vsub(d25, d25, d18);
1054b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vmul(d25, d25, d25);
1055b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vdiv(d25, d25, d18);
1056b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1057b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vmov(d16, d25);
1058b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vsqrt(d17, d25);
1059b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vneg(d17, d17);
1060b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vabs(d17, d17);
1061b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vmla(d18, d16, d17);
1062b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1063b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Store d16, d17, d18 into a, b, c.
1064b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(r4, Operand(r0));
1065b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vstr(d16, r4, OFFSET_OF(T, a));
1066b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vstr(d17, r4, OFFSET_OF(T, b));
1067b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vstr(d18, r4, OFFSET_OF(T, c));
1068b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1069b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Load x, y, z into d29-d31.
1070b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ add(r4, r0, Operand(OFFSET_OF(T, x)));
1071b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vldm(ia_w, r4, d29, d31);
1072b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1073b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Swap d29 and d30 via r registers.
1074b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vmov(r1, r2, d29);
1075b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vmov(d29, d30);
1076b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vmov(d30, r1, r2);
1077b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1078b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Convert to and from integer.
1079b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vcvt_s32_f64(s1, d31);
1080b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vcvt_f64_u32(d31, s1);
1081b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1082b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Store d29-d31 into x, y, z.
1083b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ add(r4, r0, Operand(OFFSET_OF(T, x)));
1084b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vstm(ia_w, r4, d29, d31);
1085b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1086b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Move constants into d20, d21, d22 and store into i, j, k.
1087b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vmov(d20, 14.7610017472335499);
1088b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vmov(d21, 16.0);
1089b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(r1, Operand(372106121));
1090b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(r2, Operand(1079146608));
1091b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vmov(d22, VmovIndexLo, r1);
1092b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vmov(d22, VmovIndexHi, r2);
1093b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ add(r4, r0, Operand(OFFSET_OF(T, i)));
1094b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vstm(ia_w, r4, d20, d22);
1095b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Move d22 into low and high.
1096b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vmov(r4, VmovIndexLo, d22);
1097b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ str(r4, MemOperand(r0, OFFSET_OF(T, low)));
1098b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vmov(r4, VmovIndexHi, d22);
1099b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ str(r4, MemOperand(r0, OFFSET_OF(T, high)));
1100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldm(ia_w, sp, r4.bit() | pc.bit());
1102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CodeDesc desc;
1104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    assm.GetCode(&desc);
1105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Code> code = isolate->factory()->NewCode(
1106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
1108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    OFStream os(stdout);
1109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    code->Print(os);
1110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
1111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    F3 f = FUNCTION_CAST<F3>(code->entry());
1112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.a = 1.5;
1113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.b = 2.75;
1114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.c = 17.17;
1115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.x = 1.5;
1116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.y = 2.75;
1117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.z = 17.17;
1118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    USE(dummy);
1120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(14.7610017472335499, t.a);
1121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(3.84200491244266251, t.b);
1122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(73.8818412254460241, t.c);
1123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(2.75, t.x);
1124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(1.5, t.y);
1125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(17.0, t.z);
1126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(14.7610017472335499, t.i);
1127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(16.0, t.j);
1128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(73.8818412254460241, t.k);
1129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(372106121, t.low);
1130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(1079146608, t.high);
1131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(14) {
1136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test the VFP Canonicalized Nan mode.
1137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::InitializeVM();
1138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
1139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
1140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  typedef struct {
1142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    double left;
1143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    double right;
1144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    double add_result;
1145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    double sub_result;
1146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    double mul_result;
1147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    double div_result;
1148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } T;
1149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  T t;
1150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Create a function that makes the four basic operations.
1152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler assm(isolate, NULL, 0);
1153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Ensure FPSCR state (as JSEntryStub does).
1155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label fpscr_done;
1156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vmrs(r1);
1157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ tst(r1, Operand(kVFPDefaultNaNModeControlBit));
1158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ b(ne, &fpscr_done);
1159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ orr(r1, r1, Operand(kVFPDefaultNaNModeControlBit));
1160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vmsr(r1);
1161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&fpscr_done);
1162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vldr(d0, r0, OFFSET_OF(T, left));
1164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vldr(d1, r0, OFFSET_OF(T, right));
1165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vadd(d2, d0, d1);
1166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vstr(d2, r0, OFFSET_OF(T, add_result));
1167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vsub(d2, d0, d1);
1168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vstr(d2, r0, OFFSET_OF(T, sub_result));
1169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vmul(d2, d0, d1);
1170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vstr(d2, r0, OFFSET_OF(T, mul_result));
1171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vdiv(d2, d0, d1);
1172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ vstr(d2, r0, OFFSET_OF(T, div_result));
1173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(pc, Operand(lr));
1175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeDesc desc;
1177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assm.GetCode(&desc);
1178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> code = isolate->factory()->NewCode(
1179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
1181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  OFStream os(stdout);
1182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  code->Print(os);
1183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
1184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  F3 f = FUNCTION_CAST<F3>(code->entry());
1185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t.left = bit_cast<double>(kHoleNanInt64);
1186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t.right = 1;
1187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t.add_result = 0;
1188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t.sub_result = 0;
1189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t.mul_result = 0;
1190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t.div_result = 0;
1191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  USE(dummy);
1193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const uint32_t kArmNanUpper32 = 0x7ff80000;
1194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const uint32_t kArmNanLower32 = 0x00000000;
1195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
1196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  const uint64_t kArmNanInt64 =
1197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      (static_cast<uint64_t>(kArmNanUpper32) << 32) | kArmNanLower32;
1198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(kArmNanInt64 != kHoleNanInt64);
1199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
1200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // With VFP2 the sign of the canonicalized Nan is undefined. So
1201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // we remove the sign bit for the upper tests.
1202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(kArmNanUpper32,
1203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           (bit_cast<int64_t>(t.add_result) >> 32) & 0x7fffffff);
1204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.add_result) & 0xffffffffu);
1205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(kArmNanUpper32,
1206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           (bit_cast<int64_t>(t.sub_result) >> 32) & 0x7fffffff);
1207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.sub_result) & 0xffffffffu);
1208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(kArmNanUpper32,
1209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           (bit_cast<int64_t>(t.mul_result) >> 32) & 0x7fffffff);
1210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.mul_result) & 0xffffffffu);
1211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(kArmNanUpper32,
1212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch           (bit_cast<int64_t>(t.div_result) >> 32) & 0x7fffffff);
1213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.div_result) & 0xffffffffu);
1214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(15) {
1218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test the Neon instructions.
1219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::InitializeVM();
1220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
1221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
1222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  typedef struct {
1224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t src0;
1225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t src1;
1226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t src2;
1227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t src3;
1228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t src4;
1229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t src5;
1230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t src6;
1231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t src7;
1232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t dst0;
1233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t dst1;
1234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t dst2;
1235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t dst3;
1236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t dst4;
1237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t dst5;
1238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t dst6;
1239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t dst7;
1240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t srcA0;
1241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t srcA1;
1242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t dstA0;
1243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t dstA1;
1244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t dstA2;
1245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t dstA3;
1246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t dstA4;
1247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t dstA5;
1248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t dstA6;
1249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t dstA7;
1250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } T;
1251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  T t;
1252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Create a function that accepts &t, and loads, manipulates, and stores
1254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the doubles and floats.
1255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler assm(isolate, NULL, 0);
1256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (CpuFeatures::IsSupported(NEON)) {
1259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CpuFeatureScope scope(&assm, NEON);
1260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ stm(db_w, sp, r4.bit() | lr.bit());
1262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Move 32 bytes with neon.
1263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ add(r4, r0, Operand(OFFSET_OF(T, src0)));
1264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4));
1265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ add(r4, r0, Operand(OFFSET_OF(T, dst0)));
1266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4));
1267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Expand 8 bytes into 8 words(16 bits).
1269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ add(r4, r0, Operand(OFFSET_OF(T, srcA0)));
1270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vld1(Neon8, NeonListOperand(d0), NeonMemOperand(r4));
1271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vmovl(NeonU8, q0, d0);
1272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ add(r4, r0, Operand(OFFSET_OF(T, dstA0)));
1273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vst1(Neon8, NeonListOperand(d0, 2), NeonMemOperand(r4));
1274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // The same expansion, but with different source and destination registers.
1276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ add(r4, r0, Operand(OFFSET_OF(T, srcA0)));
1277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vld1(Neon8, NeonListOperand(d1), NeonMemOperand(r4));
1278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vmovl(NeonU8, q1, d1);
1279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ add(r4, r0, Operand(OFFSET_OF(T, dstA4)));
1280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ vst1(Neon8, NeonListOperand(d2, 2), NeonMemOperand(r4));
1281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldm(ia_w, sp, r4.bit() | pc.bit());
1283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CodeDesc desc;
1285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    assm.GetCode(&desc);
1286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Code> code = isolate->factory()->NewCode(
1287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
1289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    OFStream os(stdout);
1290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    code->Print(os);
1291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
1292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    F3 f = FUNCTION_CAST<F3>(code->entry());
1293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.src0 = 0x01020304;
1294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.src1 = 0x11121314;
1295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.src2 = 0x21222324;
1296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.src3 = 0x31323334;
1297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.src4 = 0x41424344;
1298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.src5 = 0x51525354;
1299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.src6 = 0x61626364;
1300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.src7 = 0x71727374;
1301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.dst0 = 0;
1302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.dst1 = 0;
1303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.dst2 = 0;
1304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.dst3 = 0;
1305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.dst4 = 0;
1306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.dst5 = 0;
1307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.dst6 = 0;
1308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.dst7 = 0;
1309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.srcA0 = 0x41424344;
1310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.srcA1 = 0x81828384;
1311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.dstA0 = 0;
1312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.dstA1 = 0;
1313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.dstA2 = 0;
1314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.dstA3 = 0;
1315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.dstA4 = 0;
1316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.dstA5 = 0;
1317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.dstA6 = 0;
1318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.dstA7 = 0;
1319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    USE(dummy);
1321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0x01020304, t.dst0);
1322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0x11121314, t.dst1);
1323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0x21222324, t.dst2);
1324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0x31323334, t.dst3);
1325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0x41424344, t.dst4);
1326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0x51525354, t.dst5);
1327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0x61626364, t.dst6);
1328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0x71727374, t.dst7);
1329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0x00430044, t.dstA0);
1330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0x00410042, t.dstA1);
1331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0x00830084, t.dstA2);
1332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0x00810082, t.dstA3);
1333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0x00430044, t.dstA4);
1334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0x00410042, t.dstA5);
1335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0x00830084, t.dstA6);
1336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(0x00810082, t.dstA7);
1337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(16) {
1342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test the pkh, uxtb, uxtab and uxtb16 instructions.
1343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::InitializeVM();
1344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
1345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
1346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  typedef struct {
1348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t src0;
1349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t src1;
1350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t src2;
1351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t dst0;
1352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t dst1;
1353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t dst2;
1354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t dst3;
1355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t dst4;
1356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } T;
1357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  T t;
1358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Create a function that accepts &t, and loads, manipulates, and stores
1360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // the doubles and floats.
1361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler assm(isolate, NULL, 0);
1362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ stm(db_w, sp, r4.bit() | lr.bit());
1364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(r4, Operand(r0));
1366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r0, MemOperand(r4, OFFSET_OF(T, src0)));
1367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r1, MemOperand(r4, OFFSET_OF(T, src1)));
1368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ pkhbt(r2, r0, Operand(r1, LSL, 8));
1370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r2, MemOperand(r4, OFFSET_OF(T, dst0)));
1371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ pkhtb(r2, r0, Operand(r1, ASR, 8));
1373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r2, MemOperand(r4, OFFSET_OF(T, dst1)));
1374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ uxtb16(r2, Operand(r0, ROR, 8));
1376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r2, MemOperand(r4, OFFSET_OF(T, dst2)));
1377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ uxtb(r2, Operand(r0, ROR, 8));
1379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r2, MemOperand(r4, OFFSET_OF(T, dst3)));
1380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r0, MemOperand(r4, OFFSET_OF(T, src2)));
1382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ uxtab(r2, r0, Operand(r1, ROR, 8));
1383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r2, MemOperand(r4, OFFSET_OF(T, dst4)));
1384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldm(ia_w, sp, r4.bit() | pc.bit());
1386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeDesc desc;
1388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assm.GetCode(&desc);
1389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> code = isolate->factory()->NewCode(
1390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
1392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  OFStream os(stdout);
1393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  code->Print(os);
1394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
1395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  F3 f = FUNCTION_CAST<F3>(code->entry());
1396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t.src0 = 0x01020304;
1397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t.src1 = 0x11121314;
1398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t.src2 = 0x11121300;
1399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t.dst0 = 0;
1400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t.dst1 = 0;
1401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t.dst2 = 0;
1402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t.dst3 = 0;
1403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  t.dst4 = 0;
1404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  USE(dummy);
1406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0x12130304, t.dst0);
1407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0x01021213, t.dst1);
1408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0x00010003, t.dst2);
1409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0x00000003, t.dst3);
1410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(0x11121313, t.dst4);
1411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(17) {
1415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test generating labels at high addresses.
1416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Should not assert.
1417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::InitializeVM();
1418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
1419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
1420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Generate a code segment that will be longer than 2^24 bytes.
1422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler assm(isolate, NULL, 0);
1423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (size_t i = 0; i < 1 << 23 ; ++i) {  // 2^23
1424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ nop();
1425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label target;
1428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ b(eq, &target);
1429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&target);
1430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ nop();
1431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define TEST_SDIV(expected_, dividend_, divisor_) \
1435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.dividend = dividend_; \
1436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.divisor = divisor_; \
1437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    t.result = 0; \
1438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); \
1439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CHECK_EQ(expected_, t.result);
1440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(18) {
1443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test the sdiv.
1444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::InitializeVM();
1445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
1446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
1447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  typedef struct {
1449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t dividend;
1450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t divisor;
1451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    uint32_t result;
1452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  } T;
1453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  T t;
1454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler assm(isolate, NULL, 0);
1456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (CpuFeatures::IsSupported(SUDIV)) {
1458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CpuFeatureScope scope(&assm, SUDIV);
1459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ mov(r3, Operand(r0));
1461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(r0, MemOperand(r3, OFFSET_OF(T, dividend)));
1463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(r1, MemOperand(r3, OFFSET_OF(T, divisor)));
1464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ sdiv(r2, r0, r1);
1466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ str(r2, MemOperand(r3, OFFSET_OF(T, result)));
1467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bx(lr);
1469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    CodeDesc desc;
1471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    assm.GetCode(&desc);
1472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Handle<Code> code = isolate->factory()->NewCode(
1473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG
1475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    OFStream os(stdout);
1476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    code->Print(os);
1477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif
1478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    F3 f = FUNCTION_CAST<F3>(code->entry());
1479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Object* dummy;
1480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TEST_SDIV(1073741824, kMinInt, -2);
1481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TEST_SDIV(kMinInt, kMinInt, -1);
1482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TEST_SDIV(5, 10, 2);
1483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TEST_SDIV(3, 10, 3);
1484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TEST_SDIV(-5, 10, -2);
1485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TEST_SDIV(-3, 10, -3);
1486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TEST_SDIV(-5, -10, 2);
1487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TEST_SDIV(-3, -10, 3);
1488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TEST_SDIV(5, -10, -2);
1489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    TEST_SDIV(3, -10, -3);
1490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    USE(dummy);
1491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef TEST_SDIV
1496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(code_relative_offset) {
1499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Test extracting the offset of a label from the beginning of the code
1500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // in a register.
1501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CcTest::InitializeVM();
1502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Isolate* isolate = CcTest::i_isolate();
1503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  HandleScope scope(isolate);
1504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Initialize a code object that will contain the code.
1505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Object> code_object(isolate->heap()->undefined_value(), isolate);
1506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Assembler assm(isolate, NULL, 0);
1508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label start, target_away, target_faraway;
1510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ stm(db_w, sp, r4.bit() | r5.bit() | lr.bit());
1512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // r3 is used as the address zero, the test will crash when we load it.
1514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(r3, Operand::Zero());
1515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // r5 will be a pointer to the start of the code.
1517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(r5, Operand(code_object));
1518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov_label_offset(r4, &start);
1519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov_label_offset(r1, &target_faraway);
1521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ str(r1, MemOperand(sp, kPointerSize, NegPreIndex));
1522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov_label_offset(r1, &target_away);
1524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Jump straight to 'target_away' the first time and use the relative
1526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // position the second time. This covers the case when extracting the
1527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // position of a label which is linked.
1528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(r2, Operand::Zero());
1529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&start);
1530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(r2, Operand::Zero());
1531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ b(eq, &target_away);
1532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(pc, r5, r1);
1533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Emit invalid instructions to push the label between 2^8 and 2^16
1534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // instructions away. The test will crash if they are reached.
1535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < (1 << 10); i++) {
1536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(r3, MemOperand(r3));
1537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&target_away);
1539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // This will be hit twice: r0 = r0 + 5 + 5.
1540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(r0, r0, Operand(5));
1541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldr(r1, MemOperand(sp, kPointerSize, PostIndex), ne);
1543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(pc, r5, r4, LeaveCC, ne);
1544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(r2, Operand(1));
1546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ b(&start);
1547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Emit invalid instructions to push the label between 2^16 and 2^24
1548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // instructions away. The test will crash if they are reached.
1549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  for (int i = 0; i < (1 << 21); i++) {
1550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ ldr(r3, MemOperand(r3));
1551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
1552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&target_faraway);
1553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // r0 = r0 + 5 + 5 + 11
1554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(r0, r0, Operand(11));
1555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ ldm(ia_w, sp, r4.bit() | r5.bit() | pc.bit());
1557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CodeDesc desc;
1559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  assm.GetCode(&desc);
1560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Handle<Code> code = isolate->factory()->NewCode(
1561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      desc, Code::ComputeFlags(Code::STUB), code_object);
1562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  F1 f = FUNCTION_CAST<F1>(code->entry());
1563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 21, 0, 0, 0, 0));
1564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  ::printf("f() = %d\n", res);
1565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  CHECK_EQ(42, res);
1566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
1567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __
1569