blob: 3763f064930e353497b7541d7778a090842098fb [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// Copyright 2012 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
Emily Bernierd0a1eb72015-03-24 16:35:39 -040028#include <iostream> // NOLINT(readability/streams)
29
Ben Murdochb8a8cc12014-11-26 15:28:44 +000030#include "src/v8.h"
31#include "test/cctest/cctest.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000032
Ben Murdochb8a8cc12014-11-26 15:28:44 +000033#include "src/arm/assembler-arm-inl.h"
34#include "src/arm/simulator-arm.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000035#include "src/base/utils/random-number-generator.h"
Ben Murdochb8a8cc12014-11-26 15:28:44 +000036#include "src/disassembler.h"
37#include "src/factory.h"
38#include "src/ostreams.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000039
Emily Bernierd0a1eb72015-03-24 16:35:39 -040040using namespace v8::base;
Steve Blocka7e24c12009-10-30 11:49:00 +000041using namespace v8::internal;
42
43
44// Define these function prototypes to match JSEntryFunction in execution.cc.
45typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
46typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
Ben Murdoch8b112d22011-06-08 16:22:53 +010047typedef Object* (*F3)(void* p0, int p1, int p2, int p3, int p4);
48typedef Object* (*F4)(void* p0, void* p1, int p2, int p3, int p4);
Ben Murdochda12d292016-06-02 14:46:10 +010049typedef Object* (*F5)(uint32_t p0, void* p1, void* p2, int p3, int p4);
Steve Blocka7e24c12009-10-30 11:49:00 +000050
Steve Blocka7e24c12009-10-30 11:49:00 +000051#define __ assm.
52
53TEST(0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000054 CcTest::InitializeVM();
55 Isolate* isolate = CcTest::i_isolate();
56 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000057
Ben Murdochb8a8cc12014-11-26 15:28:44 +000058 Assembler assm(isolate, NULL, 0);
Steve Blocka7e24c12009-10-30 11:49:00 +000059
60 __ add(r0, r0, Operand(r1));
61 __ mov(pc, Operand(lr));
62
63 CodeDesc desc;
64 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000065 Handle<Code> code = isolate->factory()->NewCode(
66 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Steve Blocka7e24c12009-10-30 11:49:00 +000067#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +000068 OFStream os(stdout);
69 code->Print(os);
Steve Blocka7e24c12009-10-30 11:49:00 +000070#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +000071 F2 f = FUNCTION_CAST<F2>(code->entry());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000072 int res =
73 reinterpret_cast<int>(CALL_GENERATED_CODE(isolate, f, 3, 4, 0, 0, 0));
Steve Blocka7e24c12009-10-30 11:49:00 +000074 ::printf("f() = %d\n", res);
75 CHECK_EQ(7, res);
76}
77
78
79TEST(1) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000080 CcTest::InitializeVM();
81 Isolate* isolate = CcTest::i_isolate();
82 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +000083
Ben Murdochb8a8cc12014-11-26 15:28:44 +000084 Assembler assm(isolate, NULL, 0);
Steve Blocka7e24c12009-10-30 11:49:00 +000085 Label L, C;
86
87 __ mov(r1, Operand(r0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +000088 __ mov(r0, Operand::Zero());
Steve Blocka7e24c12009-10-30 11:49:00 +000089 __ b(&C);
90
91 __ bind(&L);
92 __ add(r0, r0, Operand(r1));
93 __ sub(r1, r1, Operand(1));
94
95 __ bind(&C);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000096 __ teq(r1, Operand::Zero());
Steve Blocka7e24c12009-10-30 11:49:00 +000097 __ b(ne, &L);
98 __ mov(pc, Operand(lr));
99
100 CodeDesc desc;
101 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000102 Handle<Code> code = isolate->factory()->NewCode(
103 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Steve Blocka7e24c12009-10-30 11:49:00 +0000104#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000105 OFStream os(stdout);
106 code->Print(os);
Steve Blocka7e24c12009-10-30 11:49:00 +0000107#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000108 F1 f = FUNCTION_CAST<F1>(code->entry());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000109 int res =
110 reinterpret_cast<int>(CALL_GENERATED_CODE(isolate, f, 100, 0, 0, 0, 0));
Steve Blocka7e24c12009-10-30 11:49:00 +0000111 ::printf("f() = %d\n", res);
112 CHECK_EQ(5050, res);
113}
114
115
116TEST(2) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000117 CcTest::InitializeVM();
118 Isolate* isolate = CcTest::i_isolate();
119 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000120
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000121 Assembler assm(isolate, NULL, 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000122 Label L, C;
123
124 __ mov(r1, Operand(r0));
125 __ mov(r0, Operand(1));
126 __ b(&C);
127
128 __ bind(&L);
129 __ mul(r0, r1, r0);
130 __ sub(r1, r1, Operand(1));
131
132 __ bind(&C);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000133 __ teq(r1, Operand::Zero());
Steve Blocka7e24c12009-10-30 11:49:00 +0000134 __ b(ne, &L);
135 __ mov(pc, Operand(lr));
136
137 // some relocated stuff here, not executed
138 __ RecordComment("dead code, just testing relocations");
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000139 __ mov(r0, Operand(isolate->factory()->true_value()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000140 __ RecordComment("dead code, just testing immediate operands");
141 __ mov(r0, Operand(-1));
142 __ mov(r0, Operand(0xFF000000));
143 __ mov(r0, Operand(0xF0F0F0F0));
144 __ mov(r0, Operand(0xFFF0FFFF));
145
146 CodeDesc desc;
147 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000148 Handle<Code> code = isolate->factory()->NewCode(
149 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Steve Blocka7e24c12009-10-30 11:49:00 +0000150#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000151 OFStream os(stdout);
152 code->Print(os);
Steve Blocka7e24c12009-10-30 11:49:00 +0000153#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000154 F1 f = FUNCTION_CAST<F1>(code->entry());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000155 int res =
156 reinterpret_cast<int>(CALL_GENERATED_CODE(isolate, f, 10, 0, 0, 0, 0));
Steve Blocka7e24c12009-10-30 11:49:00 +0000157 ::printf("f() = %d\n", res);
158 CHECK_EQ(3628800, res);
159}
160
161
162TEST(3) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000163 CcTest::InitializeVM();
164 Isolate* isolate = CcTest::i_isolate();
165 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000166
167 typedef struct {
168 int i;
169 char c;
170 int16_t s;
171 } T;
172 T t;
173
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000174 Assembler assm(isolate, NULL, 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000175 Label L, C;
176
177 __ mov(ip, Operand(sp));
178 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
179 __ sub(fp, ip, Operand(4));
180 __ mov(r4, Operand(r0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000181 __ ldr(r0, MemOperand(r4, offsetof(T, i)));
Steve Blocka7e24c12009-10-30 11:49:00 +0000182 __ mov(r2, Operand(r0, ASR, 1));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000183 __ str(r2, MemOperand(r4, offsetof(T, i)));
184 __ ldrsb(r2, MemOperand(r4, offsetof(T, c)));
Steve Blocka7e24c12009-10-30 11:49:00 +0000185 __ add(r0, r2, Operand(r0));
186 __ mov(r2, Operand(r2, LSL, 2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000187 __ strb(r2, MemOperand(r4, offsetof(T, c)));
188 __ ldrsh(r2, MemOperand(r4, offsetof(T, s)));
Steve Blocka7e24c12009-10-30 11:49:00 +0000189 __ add(r0, r2, Operand(r0));
190 __ mov(r2, Operand(r2, ASR, 3));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000191 __ strh(r2, MemOperand(r4, offsetof(T, s)));
Steve Blocka7e24c12009-10-30 11:49:00 +0000192 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
193
194 CodeDesc desc;
195 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000196 Handle<Code> code = isolate->factory()->NewCode(
197 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Steve Blocka7e24c12009-10-30 11:49:00 +0000198#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000199 OFStream os(stdout);
200 code->Print(os);
Steve Blocka7e24c12009-10-30 11:49:00 +0000201#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000202 F3 f = FUNCTION_CAST<F3>(code->entry());
Steve Blocka7e24c12009-10-30 11:49:00 +0000203 t.i = 100000;
204 t.c = 10;
205 t.s = 1000;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000206 int res =
207 reinterpret_cast<int>(CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0));
Steve Blocka7e24c12009-10-30 11:49:00 +0000208 ::printf("f() = %d\n", res);
209 CHECK_EQ(101010, res);
210 CHECK_EQ(100000/2, t.i);
211 CHECK_EQ(10*4, t.c);
212 CHECK_EQ(1000/8, t.s);
213}
214
215
Leon Clarked91b9f72010-01-27 17:25:45 +0000216TEST(4) {
217 // Test the VFP floating point instructions.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000218 CcTest::InitializeVM();
219 Isolate* isolate = CcTest::i_isolate();
220 HandleScope scope(isolate);
Leon Clarked91b9f72010-01-27 17:25:45 +0000221
222 typedef struct {
223 double a;
224 double b;
225 double c;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100226 double d;
227 double e;
228 double f;
Steve Block1e0659c2011-05-24 12:43:12 +0100229 double g;
230 double h;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100231 int i;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000232 double j;
Steve Block44f0eee2011-05-26 01:26:41 +0100233 double m;
234 double n;
Ben Murdochda12d292016-06-02 14:46:10 +0100235 float o;
236 float p;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100237 float x;
238 float y;
Leon Clarked91b9f72010-01-27 17:25:45 +0000239 } T;
240 T t;
241
242 // Create a function that accepts &t, and loads, manipulates, and stores
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100243 // the doubles and floats.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000244 Assembler assm(isolate, NULL, 0);
Leon Clarked91b9f72010-01-27 17:25:45 +0000245 Label L, C;
246
247
Ben Murdoch8b112d22011-06-08 16:22:53 +0100248 if (CpuFeatures::IsSupported(VFP3)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000249 CpuFeatureScope scope(&assm, VFP3);
Leon Clarked91b9f72010-01-27 17:25:45 +0000250
251 __ mov(ip, Operand(sp));
252 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
253 __ sub(fp, ip, Operand(4));
254
255 __ mov(r4, Operand(r0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000256 __ vldr(d6, r4, offsetof(T, a));
257 __ vldr(d7, r4, offsetof(T, b));
Leon Clarked91b9f72010-01-27 17:25:45 +0000258 __ vadd(d5, d6, d7);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000259 __ vstr(d5, r4, offsetof(T, c));
Leon Clarked91b9f72010-01-27 17:25:45 +0000260
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000261 __ vmla(d5, d6, d7);
262 __ vmls(d5, d5, d6);
263
Leon Clarked91b9f72010-01-27 17:25:45 +0000264 __ vmov(r2, r3, d5);
265 __ vmov(d4, r2, r3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000266 __ vstr(d4, r4, offsetof(T, b));
Leon Clarked91b9f72010-01-27 17:25:45 +0000267
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100268 // Load t.x and t.y, switch values, and store back to the struct.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000269 __ vldr(s0, r4, offsetof(T, x));
270 __ vldr(s31, r4, offsetof(T, y));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100271 __ vmov(s16, s0);
272 __ vmov(s0, s31);
273 __ vmov(s31, s16);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000274 __ vstr(s0, r4, offsetof(T, x));
275 __ vstr(s31, r4, offsetof(T, y));
Iain Merrick75681382010-08-19 15:07:18 +0100276
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100277 // Move a literal into a register that can be encoded in the instruction.
278 __ vmov(d4, 1.0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000279 __ vstr(d4, r4, offsetof(T, e));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100280
281 // Move a literal into a register that requires 64 bits to encode.
282 // 0x3ff0000010000000 = 1.000000059604644775390625
283 __ vmov(d4, 1.000000059604644775390625);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000284 __ vstr(d4, r4, offsetof(T, d));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100285
286 // Convert from floating point to integer.
287 __ vmov(d4, 2.0);
288 __ vcvt_s32_f64(s31, d4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000289 __ vstr(s31, r4, offsetof(T, i));
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100290
291 // Convert from integer to floating point.
292 __ mov(lr, Operand(42));
293 __ vmov(s31, lr);
294 __ vcvt_f64_s32(d4, s31);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000295 __ vstr(d4, r4, offsetof(T, f));
Steve Block1e0659c2011-05-24 12:43:12 +0100296
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000297 // Convert from fixed point to floating point.
298 __ mov(lr, Operand(2468));
299 __ vmov(s8, lr);
300 __ vcvt_f64_s32(d4, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301 __ vstr(d4, r4, offsetof(T, j));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000302
Steve Block1e0659c2011-05-24 12:43:12 +0100303 // Test vabs.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000304 __ vldr(d1, r4, offsetof(T, g));
Steve Block1e0659c2011-05-24 12:43:12 +0100305 __ vabs(d0, d1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000306 __ vstr(d0, r4, offsetof(T, g));
307 __ vldr(d2, r4, offsetof(T, h));
Steve Block1e0659c2011-05-24 12:43:12 +0100308 __ vabs(d0, d2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000309 __ vstr(d0, r4, offsetof(T, h));
Steve Block1e0659c2011-05-24 12:43:12 +0100310
Steve Block44f0eee2011-05-26 01:26:41 +0100311 // Test vneg.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000312 __ vldr(d1, r4, offsetof(T, m));
Steve Block44f0eee2011-05-26 01:26:41 +0100313 __ vneg(d0, d1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000314 __ vstr(d0, r4, offsetof(T, m));
315 __ vldr(d1, r4, offsetof(T, n));
Steve Block44f0eee2011-05-26 01:26:41 +0100316 __ vneg(d0, d1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000317 __ vstr(d0, r4, offsetof(T, n));
Steve Block44f0eee2011-05-26 01:26:41 +0100318
Ben Murdochda12d292016-06-02 14:46:10 +0100319 // Test vmov for single-precision immediates.
320 __ vmov(s0, 0.25f);
321 __ vstr(s0, r4, offsetof(T, o));
322 __ vmov(s0, -16.0f);
323 __ vstr(s0, r4, offsetof(T, p));
324
Leon Clarked91b9f72010-01-27 17:25:45 +0000325 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
326
327 CodeDesc desc;
328 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000329 Handle<Code> code = isolate->factory()->NewCode(
330 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Leon Clarked91b9f72010-01-27 17:25:45 +0000331#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000332 OFStream os(stdout);
333 code->Print(os);
Leon Clarked91b9f72010-01-27 17:25:45 +0000334#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000335 F3 f = FUNCTION_CAST<F3>(code->entry());
Leon Clarked91b9f72010-01-27 17:25:45 +0000336 t.a = 1.5;
337 t.b = 2.75;
338 t.c = 17.17;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100339 t.d = 0.0;
340 t.e = 0.0;
341 t.f = 0.0;
Steve Block1e0659c2011-05-24 12:43:12 +0100342 t.g = -2718.2818;
343 t.h = 31415926.5;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100344 t.i = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000345 t.j = 0;
Steve Block44f0eee2011-05-26 01:26:41 +0100346 t.m = -2718.2818;
347 t.n = 123.456;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100348 t.x = 4.5;
349 t.y = 9.0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000350 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Leon Clarked91b9f72010-01-27 17:25:45 +0000351 USE(dummy);
Ben Murdochda12d292016-06-02 14:46:10 +0100352 CHECK_EQ(-16.0f, t.p);
353 CHECK_EQ(0.25f, t.o);
Steve Block44f0eee2011-05-26 01:26:41 +0100354 CHECK_EQ(-123.456, t.n);
355 CHECK_EQ(2718.2818, t.m);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100356 CHECK_EQ(2, t.i);
Steve Block1e0659c2011-05-24 12:43:12 +0100357 CHECK_EQ(2718.2818, t.g);
358 CHECK_EQ(31415926.5, t.h);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000359 CHECK_EQ(617.0, t.j);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100360 CHECK_EQ(42.0, t.f);
361 CHECK_EQ(1.0, t.e);
362 CHECK_EQ(1.000000059604644775390625, t.d);
Leon Clarked91b9f72010-01-27 17:25:45 +0000363 CHECK_EQ(4.25, t.c);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000364 CHECK_EQ(-4.1875, t.b);
Leon Clarked91b9f72010-01-27 17:25:45 +0000365 CHECK_EQ(1.5, t.a);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000366 CHECK_EQ(4.5f, t.y);
367 CHECK_EQ(9.0f, t.x);
Leon Clarked91b9f72010-01-27 17:25:45 +0000368 }
369}
370
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100371
372TEST(5) {
373 // Test the ARMv7 bitfield instructions.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000374 CcTest::InitializeVM();
375 Isolate* isolate = CcTest::i_isolate();
376 HandleScope scope(isolate);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100377
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000378 Assembler assm(isolate, NULL, 0);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100379
Ben Murdoch8b112d22011-06-08 16:22:53 +0100380 if (CpuFeatures::IsSupported(ARMv7)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000381 CpuFeatureScope scope(&assm, ARMv7);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100382 // On entry, r0 = 0xAAAAAAAA = 0b10..10101010.
383 __ ubfx(r0, r0, 1, 12); // 0b00..010101010101 = 0x555
384 __ sbfx(r0, r0, 0, 5); // 0b11..111111110101 = -11
385 __ bfc(r0, 1, 3); // 0b11..111111110001 = -15
386 __ mov(r1, Operand(7));
387 __ bfi(r0, r1, 3, 3); // 0b11..111111111001 = -7
388 __ mov(pc, Operand(lr));
389
390 CodeDesc desc;
391 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000392 Handle<Code> code = isolate->factory()->NewCode(
393 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100394#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000395 OFStream os(stdout);
396 code->Print(os);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100397#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000398 F1 f = FUNCTION_CAST<F1>(code->entry());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100399 int res = reinterpret_cast<int>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000400 CALL_GENERATED_CODE(isolate, f, 0xAAAAAAAA, 0, 0, 0, 0));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100401 ::printf("f() = %d\n", res);
402 CHECK_EQ(-7, res);
403 }
404}
405
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100406
407TEST(6) {
408 // Test saturating instructions.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000409 CcTest::InitializeVM();
410 Isolate* isolate = CcTest::i_isolate();
411 HandleScope scope(isolate);
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100412
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000413 Assembler assm(isolate, NULL, 0);
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100414
Ben Murdoch8b112d22011-06-08 16:22:53 +0100415 if (CpuFeatures::IsSupported(ARMv7)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000416 CpuFeatureScope scope(&assm, ARMv7);
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100417 __ usat(r1, 8, Operand(r0)); // Sat 0xFFFF to 0-255 = 0xFF.
418 __ usat(r2, 12, Operand(r0, ASR, 9)); // Sat (0xFFFF>>9) to 0-4095 = 0x7F.
419 __ usat(r3, 1, Operand(r0, LSL, 16)); // Sat (0xFFFF<<16) to 0-1 = 0x0.
420 __ add(r0, r1, Operand(r2));
421 __ add(r0, r0, Operand(r3));
422 __ mov(pc, Operand(lr));
423
424 CodeDesc desc;
425 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000426 Handle<Code> code = isolate->factory()->NewCode(
427 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100428#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000429 OFStream os(stdout);
430 code->Print(os);
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100431#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000432 F1 f = FUNCTION_CAST<F1>(code->entry());
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100433 int res = reinterpret_cast<int>(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000434 CALL_GENERATED_CODE(isolate, f, 0xFFFF, 0, 0, 0, 0));
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100435 ::printf("f() = %d\n", res);
436 CHECK_EQ(382, res);
437 }
438}
439
Russell Brenner90bac252010-11-18 13:33:46 -0800440
Steve Block1e0659c2011-05-24 12:43:12 +0100441enum VCVTTypes {
442 s32_f64,
443 u32_f64
444};
445
446static void TestRoundingMode(VCVTTypes types,
447 VFPRoundingMode mode,
448 double value,
449 int expected,
450 bool expected_exception = false) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000451 Isolate* isolate = CcTest::i_isolate();
452 HandleScope scope(isolate);
Russell Brenner90bac252010-11-18 13:33:46 -0800453
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000454 Assembler assm(isolate, NULL, 0);
Russell Brenner90bac252010-11-18 13:33:46 -0800455
Ben Murdoch8b112d22011-06-08 16:22:53 +0100456 if (CpuFeatures::IsSupported(VFP3)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000457 CpuFeatureScope scope(&assm, VFP3);
Russell Brenner90bac252010-11-18 13:33:46 -0800458
Steve Block1e0659c2011-05-24 12:43:12 +0100459 Label wrong_exception;
Russell Brenner90bac252010-11-18 13:33:46 -0800460
Steve Block1e0659c2011-05-24 12:43:12 +0100461 __ vmrs(r1);
462 // Set custom FPSCR.
463 __ bic(r2, r1, Operand(kVFPRoundingModeMask | kVFPExceptionMask));
464 __ orr(r2, r2, Operand(mode));
465 __ vmsr(r2);
Russell Brenner90bac252010-11-18 13:33:46 -0800466
Steve Block1e0659c2011-05-24 12:43:12 +0100467 // Load value, convert, and move back result to r0 if everything went well.
468 __ vmov(d1, value);
469 switch (types) {
470 case s32_f64:
471 __ vcvt_s32_f64(s0, d1, kFPSCRRounding);
472 break;
473
474 case u32_f64:
475 __ vcvt_u32_f64(s0, d1, kFPSCRRounding);
476 break;
477
478 default:
479 UNREACHABLE();
480 break;
481 }
482 // Check for vfp exceptions
483 __ vmrs(r2);
484 __ tst(r2, Operand(kVFPExceptionMask));
485 // Check that we behaved as expected.
486 __ b(&wrong_exception,
487 expected_exception ? eq : ne);
488 // There was no exception. Retrieve the result and return.
489 __ vmov(r0, s0);
490 __ mov(pc, Operand(lr));
491
492 // The exception behaviour is not what we expected.
493 // Load a special value and return.
494 __ bind(&wrong_exception);
495 __ mov(r0, Operand(11223344));
496 __ mov(pc, Operand(lr));
497
498 CodeDesc desc;
499 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000500 Handle<Code> code = isolate->factory()->NewCode(
501 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Russell Brenner90bac252010-11-18 13:33:46 -0800502#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000503 OFStream os(stdout);
504 code->Print(os);
Russell Brenner90bac252010-11-18 13:33:46 -0800505#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000506 F1 f = FUNCTION_CAST<F1>(code->entry());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000507 int res =
508 reinterpret_cast<int>(CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
Steve Block1e0659c2011-05-24 12:43:12 +0100509 ::printf("res = %d\n", res);
510 CHECK_EQ(expected, res);
511 }
Russell Brenner90bac252010-11-18 13:33:46 -0800512}
513
514
515TEST(7) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000516 CcTest::InitializeVM();
Russell Brenner90bac252010-11-18 13:33:46 -0800517 // Test vfp rounding modes.
518
Steve Block1e0659c2011-05-24 12:43:12 +0100519 // s32_f64 (double to integer).
Russell Brenner90bac252010-11-18 13:33:46 -0800520
Steve Block1e0659c2011-05-24 12:43:12 +0100521 TestRoundingMode(s32_f64, RN, 0, 0);
522 TestRoundingMode(s32_f64, RN, 0.5, 0);
523 TestRoundingMode(s32_f64, RN, -0.5, 0);
524 TestRoundingMode(s32_f64, RN, 1.5, 2);
525 TestRoundingMode(s32_f64, RN, -1.5, -2);
526 TestRoundingMode(s32_f64, RN, 123.7, 124);
527 TestRoundingMode(s32_f64, RN, -123.7, -124);
528 TestRoundingMode(s32_f64, RN, 123456.2, 123456);
529 TestRoundingMode(s32_f64, RN, -123456.2, -123456);
530 TestRoundingMode(s32_f64, RN, static_cast<double>(kMaxInt), kMaxInt);
531 TestRoundingMode(s32_f64, RN, (kMaxInt + 0.49), kMaxInt);
532 TestRoundingMode(s32_f64, RN, (kMaxInt + 1.0), kMaxInt, true);
533 TestRoundingMode(s32_f64, RN, (kMaxInt + 0.5), kMaxInt, true);
534 TestRoundingMode(s32_f64, RN, static_cast<double>(kMinInt), kMinInt);
535 TestRoundingMode(s32_f64, RN, (kMinInt - 0.5), kMinInt);
536 TestRoundingMode(s32_f64, RN, (kMinInt - 1.0), kMinInt, true);
537 TestRoundingMode(s32_f64, RN, (kMinInt - 0.51), kMinInt, true);
Russell Brenner90bac252010-11-18 13:33:46 -0800538
Steve Block1e0659c2011-05-24 12:43:12 +0100539 TestRoundingMode(s32_f64, RM, 0, 0);
540 TestRoundingMode(s32_f64, RM, 0.5, 0);
541 TestRoundingMode(s32_f64, RM, -0.5, -1);
542 TestRoundingMode(s32_f64, RM, 123.7, 123);
543 TestRoundingMode(s32_f64, RM, -123.7, -124);
544 TestRoundingMode(s32_f64, RM, 123456.2, 123456);
545 TestRoundingMode(s32_f64, RM, -123456.2, -123457);
546 TestRoundingMode(s32_f64, RM, static_cast<double>(kMaxInt), kMaxInt);
547 TestRoundingMode(s32_f64, RM, (kMaxInt + 0.5), kMaxInt);
548 TestRoundingMode(s32_f64, RM, (kMaxInt + 1.0), kMaxInt, true);
549 TestRoundingMode(s32_f64, RM, static_cast<double>(kMinInt), kMinInt);
550 TestRoundingMode(s32_f64, RM, (kMinInt - 0.5), kMinInt, true);
551 TestRoundingMode(s32_f64, RM, (kMinInt + 0.5), kMinInt);
Russell Brenner90bac252010-11-18 13:33:46 -0800552
Steve Block1e0659c2011-05-24 12:43:12 +0100553 TestRoundingMode(s32_f64, RZ, 0, 0);
554 TestRoundingMode(s32_f64, RZ, 0.5, 0);
555 TestRoundingMode(s32_f64, RZ, -0.5, 0);
556 TestRoundingMode(s32_f64, RZ, 123.7, 123);
557 TestRoundingMode(s32_f64, RZ, -123.7, -123);
558 TestRoundingMode(s32_f64, RZ, 123456.2, 123456);
559 TestRoundingMode(s32_f64, RZ, -123456.2, -123456);
560 TestRoundingMode(s32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt);
561 TestRoundingMode(s32_f64, RZ, (kMaxInt + 0.5), kMaxInt);
562 TestRoundingMode(s32_f64, RZ, (kMaxInt + 1.0), kMaxInt, true);
563 TestRoundingMode(s32_f64, RZ, static_cast<double>(kMinInt), kMinInt);
564 TestRoundingMode(s32_f64, RZ, (kMinInt - 0.5), kMinInt);
565 TestRoundingMode(s32_f64, RZ, (kMinInt - 1.0), kMinInt, true);
566
567
568 // u32_f64 (double to integer).
569
570 // Negative values.
571 TestRoundingMode(u32_f64, RN, -0.5, 0);
572 TestRoundingMode(u32_f64, RN, -123456.7, 0, true);
573 TestRoundingMode(u32_f64, RN, static_cast<double>(kMinInt), 0, true);
574 TestRoundingMode(u32_f64, RN, kMinInt - 1.0, 0, true);
575
576 TestRoundingMode(u32_f64, RM, -0.5, 0, true);
577 TestRoundingMode(u32_f64, RM, -123456.7, 0, true);
578 TestRoundingMode(u32_f64, RM, static_cast<double>(kMinInt), 0, true);
579 TestRoundingMode(u32_f64, RM, kMinInt - 1.0, 0, true);
580
581 TestRoundingMode(u32_f64, RZ, -0.5, 0);
582 TestRoundingMode(u32_f64, RZ, -123456.7, 0, true);
583 TestRoundingMode(u32_f64, RZ, static_cast<double>(kMinInt), 0, true);
584 TestRoundingMode(u32_f64, RZ, kMinInt - 1.0, 0, true);
585
586 // Positive values.
587 // kMaxInt is the maximum *signed* integer: 0x7fffffff.
588 static const uint32_t kMaxUInt = 0xffffffffu;
589 TestRoundingMode(u32_f64, RZ, 0, 0);
590 TestRoundingMode(u32_f64, RZ, 0.5, 0);
591 TestRoundingMode(u32_f64, RZ, 123.7, 123);
592 TestRoundingMode(u32_f64, RZ, 123456.2, 123456);
593 TestRoundingMode(u32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt);
594 TestRoundingMode(u32_f64, RZ, (kMaxInt + 0.5), kMaxInt);
595 TestRoundingMode(u32_f64, RZ, (kMaxInt + 1.0),
596 static_cast<uint32_t>(kMaxInt) + 1);
597 TestRoundingMode(u32_f64, RZ, (kMaxUInt + 0.5), kMaxUInt);
598 TestRoundingMode(u32_f64, RZ, (kMaxUInt + 1.0), kMaxUInt, true);
599
600 TestRoundingMode(u32_f64, RM, 0, 0);
601 TestRoundingMode(u32_f64, RM, 0.5, 0);
602 TestRoundingMode(u32_f64, RM, 123.7, 123);
603 TestRoundingMode(u32_f64, RM, 123456.2, 123456);
604 TestRoundingMode(u32_f64, RM, static_cast<double>(kMaxInt), kMaxInt);
605 TestRoundingMode(u32_f64, RM, (kMaxInt + 0.5), kMaxInt);
606 TestRoundingMode(u32_f64, RM, (kMaxInt + 1.0),
607 static_cast<uint32_t>(kMaxInt) + 1);
608 TestRoundingMode(u32_f64, RM, (kMaxUInt + 0.5), kMaxUInt);
609 TestRoundingMode(u32_f64, RM, (kMaxUInt + 1.0), kMaxUInt, true);
610
611 TestRoundingMode(u32_f64, RN, 0, 0);
612 TestRoundingMode(u32_f64, RN, 0.5, 0);
613 TestRoundingMode(u32_f64, RN, 1.5, 2);
614 TestRoundingMode(u32_f64, RN, 123.7, 124);
615 TestRoundingMode(u32_f64, RN, 123456.2, 123456);
616 TestRoundingMode(u32_f64, RN, static_cast<double>(kMaxInt), kMaxInt);
617 TestRoundingMode(u32_f64, RN, (kMaxInt + 0.49), kMaxInt);
618 TestRoundingMode(u32_f64, RN, (kMaxInt + 0.5),
619 static_cast<uint32_t>(kMaxInt) + 1);
620 TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.49), kMaxUInt);
621 TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.5), kMaxUInt, true);
622 TestRoundingMode(u32_f64, RN, (kMaxUInt + 1.0), kMaxUInt, true);
Russell Brenner90bac252010-11-18 13:33:46 -0800623}
624
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000625
Ben Murdoch8b112d22011-06-08 16:22:53 +0100626TEST(8) {
627 // Test VFP multi load/store with ia_w.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000628 CcTest::InitializeVM();
629 Isolate* isolate = CcTest::i_isolate();
630 HandleScope scope(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100631
632 typedef struct {
633 double a;
634 double b;
635 double c;
636 double d;
637 double e;
638 double f;
639 double g;
640 double h;
641 } D;
642 D d;
643
644 typedef struct {
645 float a;
646 float b;
647 float c;
648 float d;
649 float e;
650 float f;
651 float g;
652 float h;
653 } F;
654 F f;
655
656 // Create a function that uses vldm/vstm to move some double and
657 // single precision values around in memory.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000658 Assembler assm(isolate, NULL, 0);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100659
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000660 __ mov(ip, Operand(sp));
661 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
662 __ sub(fp, ip, Operand(4));
Ben Murdoch8b112d22011-06-08 16:22:53 +0100663
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000664 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, a))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000665 __ vldm(ia_w, r4, d0, d3);
666 __ vldm(ia_w, r4, d4, d7);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100667
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000668 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, a))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000669 __ vstm(ia_w, r4, d6, d7);
670 __ vstm(ia_w, r4, d0, d5);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100671
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000672 __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, a))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000673 __ vldm(ia_w, r4, s0, s3);
674 __ vldm(ia_w, r4, s4, s7);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100675
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000676 __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, a))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000677 __ vstm(ia_w, r4, s6, s7);
678 __ vstm(ia_w, r4, s0, s5);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100679
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000680 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
Ben Murdoch8b112d22011-06-08 16:22:53 +0100681
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000682 CodeDesc desc;
683 assm.GetCode(&desc);
684 Handle<Code> code = isolate->factory()->NewCode(
685 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Ben Murdoch8b112d22011-06-08 16:22:53 +0100686#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000687 OFStream os(stdout);
688 code->Print(os);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100689#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000690 F4 fn = FUNCTION_CAST<F4>(code->entry());
691 d.a = 1.1;
692 d.b = 2.2;
693 d.c = 3.3;
694 d.d = 4.4;
695 d.e = 5.5;
696 d.f = 6.6;
697 d.g = 7.7;
698 d.h = 8.8;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100699
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000700 f.a = 1.0;
701 f.b = 2.0;
702 f.c = 3.0;
703 f.d = 4.0;
704 f.e = 5.0;
705 f.f = 6.0;
706 f.g = 7.0;
707 f.h = 8.0;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100708
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000709 Object* dummy = CALL_GENERATED_CODE(isolate, fn, &d, &f, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000710 USE(dummy);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100711
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000712 CHECK_EQ(7.7, d.a);
713 CHECK_EQ(8.8, d.b);
714 CHECK_EQ(1.1, d.c);
715 CHECK_EQ(2.2, d.d);
716 CHECK_EQ(3.3, d.e);
717 CHECK_EQ(4.4, d.f);
718 CHECK_EQ(5.5, d.g);
719 CHECK_EQ(6.6, d.h);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100720
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000721 CHECK_EQ(7.0f, f.a);
722 CHECK_EQ(8.0f, f.b);
723 CHECK_EQ(1.0f, f.c);
724 CHECK_EQ(2.0f, f.d);
725 CHECK_EQ(3.0f, f.e);
726 CHECK_EQ(4.0f, f.f);
727 CHECK_EQ(5.0f, f.g);
728 CHECK_EQ(6.0f, f.h);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100729}
730
731
732TEST(9) {
733 // Test VFP multi load/store with ia.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000734 CcTest::InitializeVM();
735 Isolate* isolate = CcTest::i_isolate();
736 HandleScope scope(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100737
738 typedef struct {
739 double a;
740 double b;
741 double c;
742 double d;
743 double e;
744 double f;
745 double g;
746 double h;
747 } D;
748 D d;
749
750 typedef struct {
751 float a;
752 float b;
753 float c;
754 float d;
755 float e;
756 float f;
757 float g;
758 float h;
759 } F;
760 F f;
761
762 // Create a function that uses vldm/vstm to move some double and
763 // single precision values around in memory.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000764 Assembler assm(isolate, NULL, 0);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100765
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000766 __ mov(ip, Operand(sp));
767 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
768 __ sub(fp, ip, Operand(4));
Ben Murdoch8b112d22011-06-08 16:22:53 +0100769
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000770 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, a))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000771 __ vldm(ia, r4, d0, d3);
772 __ add(r4, r4, Operand(4 * 8));
773 __ vldm(ia, r4, d4, d7);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100774
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000775 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, a))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000776 __ vstm(ia, r4, d6, d7);
777 __ add(r4, r4, Operand(2 * 8));
778 __ vstm(ia, r4, d0, d5);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100779
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000780 __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, a))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000781 __ vldm(ia, r4, s0, s3);
782 __ add(r4, r4, Operand(4 * 4));
783 __ vldm(ia, r4, s4, s7);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100784
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000785 __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, a))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000786 __ vstm(ia, r4, s6, s7);
787 __ add(r4, r4, Operand(2 * 4));
788 __ vstm(ia, r4, s0, s5);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100789
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000790 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
Ben Murdoch8b112d22011-06-08 16:22:53 +0100791
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000792 CodeDesc desc;
793 assm.GetCode(&desc);
794 Handle<Code> code = isolate->factory()->NewCode(
795 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Ben Murdoch8b112d22011-06-08 16:22:53 +0100796#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000797 OFStream os(stdout);
798 code->Print(os);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100799#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000800 F4 fn = FUNCTION_CAST<F4>(code->entry());
801 d.a = 1.1;
802 d.b = 2.2;
803 d.c = 3.3;
804 d.d = 4.4;
805 d.e = 5.5;
806 d.f = 6.6;
807 d.g = 7.7;
808 d.h = 8.8;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100809
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000810 f.a = 1.0;
811 f.b = 2.0;
812 f.c = 3.0;
813 f.d = 4.0;
814 f.e = 5.0;
815 f.f = 6.0;
816 f.g = 7.0;
817 f.h = 8.0;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100818
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000819 Object* dummy = CALL_GENERATED_CODE(isolate, fn, &d, &f, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000820 USE(dummy);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100821
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000822 CHECK_EQ(7.7, d.a);
823 CHECK_EQ(8.8, d.b);
824 CHECK_EQ(1.1, d.c);
825 CHECK_EQ(2.2, d.d);
826 CHECK_EQ(3.3, d.e);
827 CHECK_EQ(4.4, d.f);
828 CHECK_EQ(5.5, d.g);
829 CHECK_EQ(6.6, d.h);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100830
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000831 CHECK_EQ(7.0f, f.a);
832 CHECK_EQ(8.0f, f.b);
833 CHECK_EQ(1.0f, f.c);
834 CHECK_EQ(2.0f, f.d);
835 CHECK_EQ(3.0f, f.e);
836 CHECK_EQ(4.0f, f.f);
837 CHECK_EQ(5.0f, f.g);
838 CHECK_EQ(6.0f, f.h);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100839}
840
841
842TEST(10) {
843 // Test VFP multi load/store with db_w.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000844 CcTest::InitializeVM();
845 Isolate* isolate = CcTest::i_isolate();
846 HandleScope scope(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100847
848 typedef struct {
849 double a;
850 double b;
851 double c;
852 double d;
853 double e;
854 double f;
855 double g;
856 double h;
857 } D;
858 D d;
859
860 typedef struct {
861 float a;
862 float b;
863 float c;
864 float d;
865 float e;
866 float f;
867 float g;
868 float h;
869 } F;
870 F f;
871
872 // Create a function that uses vldm/vstm to move some double and
873 // single precision values around in memory.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000874 Assembler assm(isolate, NULL, 0);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100875
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000876 __ mov(ip, Operand(sp));
877 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
878 __ sub(fp, ip, Operand(4));
Ben Murdoch8b112d22011-06-08 16:22:53 +0100879
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000880 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, h)) + 8));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000881 __ vldm(db_w, r4, d4, d7);
882 __ vldm(db_w, r4, d0, d3);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100883
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000884 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, h)) + 8));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000885 __ vstm(db_w, r4, d0, d5);
886 __ vstm(db_w, r4, d6, d7);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100887
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000888 __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, h)) + 4));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000889 __ vldm(db_w, r4, s4, s7);
890 __ vldm(db_w, r4, s0, s3);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100891
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000892 __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, h)) + 4));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000893 __ vstm(db_w, r4, s0, s5);
894 __ vstm(db_w, r4, s6, s7);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100895
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000896 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
Ben Murdoch8b112d22011-06-08 16:22:53 +0100897
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000898 CodeDesc desc;
899 assm.GetCode(&desc);
900 Handle<Code> code = isolate->factory()->NewCode(
901 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Ben Murdoch8b112d22011-06-08 16:22:53 +0100902#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000903 OFStream os(stdout);
904 code->Print(os);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100905#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000906 F4 fn = FUNCTION_CAST<F4>(code->entry());
907 d.a = 1.1;
908 d.b = 2.2;
909 d.c = 3.3;
910 d.d = 4.4;
911 d.e = 5.5;
912 d.f = 6.6;
913 d.g = 7.7;
914 d.h = 8.8;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100915
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000916 f.a = 1.0;
917 f.b = 2.0;
918 f.c = 3.0;
919 f.d = 4.0;
920 f.e = 5.0;
921 f.f = 6.0;
922 f.g = 7.0;
923 f.h = 8.0;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100924
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000925 Object* dummy = CALL_GENERATED_CODE(isolate, fn, &d, &f, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000926 USE(dummy);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100927
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000928 CHECK_EQ(7.7, d.a);
929 CHECK_EQ(8.8, d.b);
930 CHECK_EQ(1.1, d.c);
931 CHECK_EQ(2.2, d.d);
932 CHECK_EQ(3.3, d.e);
933 CHECK_EQ(4.4, d.f);
934 CHECK_EQ(5.5, d.g);
935 CHECK_EQ(6.6, d.h);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100936
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000937 CHECK_EQ(7.0f, f.a);
938 CHECK_EQ(8.0f, f.b);
939 CHECK_EQ(1.0f, f.c);
940 CHECK_EQ(2.0f, f.d);
941 CHECK_EQ(3.0f, f.e);
942 CHECK_EQ(4.0f, f.f);
943 CHECK_EQ(5.0f, f.g);
944 CHECK_EQ(6.0f, f.h);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100945}
946
Ben Murdoch257744e2011-11-30 15:57:28 +0000947
948TEST(11) {
949 // Test instructions using the carry flag.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000950 CcTest::InitializeVM();
951 Isolate* isolate = CcTest::i_isolate();
952 HandleScope scope(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +0000953
954 typedef struct {
955 int32_t a;
956 int32_t b;
957 int32_t c;
958 int32_t d;
959 } I;
960 I i;
961
962 i.a = 0xabcd0001;
963 i.b = 0xabcd0000;
964
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000965 Assembler assm(isolate, NULL, 0);
Ben Murdoch257744e2011-11-30 15:57:28 +0000966
967 // Test HeapObject untagging.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000968 __ ldr(r1, MemOperand(r0, offsetof(I, a)));
Ben Murdoch257744e2011-11-30 15:57:28 +0000969 __ mov(r1, Operand(r1, ASR, 1), SetCC);
970 __ adc(r1, r1, Operand(r1), LeaveCC, cs);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000971 __ str(r1, MemOperand(r0, offsetof(I, a)));
Ben Murdoch257744e2011-11-30 15:57:28 +0000972
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000973 __ ldr(r2, MemOperand(r0, offsetof(I, b)));
Ben Murdoch257744e2011-11-30 15:57:28 +0000974 __ mov(r2, Operand(r2, ASR, 1), SetCC);
975 __ adc(r2, r2, Operand(r2), LeaveCC, cs);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000976 __ str(r2, MemOperand(r0, offsetof(I, b)));
Ben Murdoch257744e2011-11-30 15:57:28 +0000977
978 // Test corner cases.
979 __ mov(r1, Operand(0xffffffff));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000980 __ mov(r2, Operand::Zero());
Ben Murdoch257744e2011-11-30 15:57:28 +0000981 __ mov(r3, Operand(r1, ASR, 1), SetCC); // Set the carry.
982 __ adc(r3, r1, Operand(r2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000983 __ str(r3, MemOperand(r0, offsetof(I, c)));
Ben Murdoch257744e2011-11-30 15:57:28 +0000984
985 __ mov(r1, Operand(0xffffffff));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000986 __ mov(r2, Operand::Zero());
Ben Murdoch257744e2011-11-30 15:57:28 +0000987 __ mov(r3, Operand(r2, ASR, 1), SetCC); // Unset the carry.
988 __ adc(r3, r1, Operand(r2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000989 __ str(r3, MemOperand(r0, offsetof(I, d)));
Ben Murdoch257744e2011-11-30 15:57:28 +0000990
991 __ mov(pc, Operand(lr));
992
993 CodeDesc desc;
994 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000995 Handle<Code> code = isolate->factory()->NewCode(
996 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Ben Murdoch257744e2011-11-30 15:57:28 +0000997#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000998 OFStream os(stdout);
999 code->Print(os);
Ben Murdoch257744e2011-11-30 15:57:28 +00001000#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001001 F3 f = FUNCTION_CAST<F3>(code->entry());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001002 Object* dummy = CALL_GENERATED_CODE(isolate, f, &i, 0, 0, 0, 0);
Ben Murdoch257744e2011-11-30 15:57:28 +00001003 USE(dummy);
1004
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001005 CHECK_EQ(static_cast<int32_t>(0xabcd0001), i.a);
Ben Murdoch257744e2011-11-30 15:57:28 +00001006 CHECK_EQ(static_cast<int32_t>(0xabcd0000) >> 1, i.b);
1007 CHECK_EQ(0x00000000, i.c);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001008 CHECK_EQ(static_cast<int32_t>(0xffffffff), i.d);
Ben Murdoch257744e2011-11-30 15:57:28 +00001009}
1010
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001011
1012TEST(12) {
1013 // Test chaining of label usages within instructions (issue 1644).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001014 CcTest::InitializeVM();
1015 Isolate* isolate = CcTest::i_isolate();
1016 HandleScope scope(isolate);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001017
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001018 Assembler assm(isolate, NULL, 0);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001019 Label target;
1020 __ b(eq, &target);
1021 __ b(ne, &target);
1022 __ bind(&target);
1023 __ nop();
1024}
1025
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001026
1027TEST(13) {
1028 // Test VFP instructions using registers d16-d31.
1029 CcTest::InitializeVM();
1030 Isolate* isolate = CcTest::i_isolate();
1031 HandleScope scope(isolate);
1032
1033 if (!CpuFeatures::IsSupported(VFP32DREGS)) {
1034 return;
1035 }
1036
1037 typedef struct {
1038 double a;
1039 double b;
1040 double c;
1041 double x;
1042 double y;
1043 double z;
1044 double i;
1045 double j;
1046 double k;
1047 uint32_t low;
1048 uint32_t high;
1049 } T;
1050 T t;
1051
1052 // Create a function that accepts &t, and loads, manipulates, and stores
1053 // the doubles and floats.
1054 Assembler assm(isolate, NULL, 0);
1055 Label L, C;
1056
1057
1058 if (CpuFeatures::IsSupported(VFP3)) {
1059 CpuFeatureScope scope(&assm, VFP3);
1060
1061 __ stm(db_w, sp, r4.bit() | lr.bit());
1062
1063 // Load a, b, c into d16, d17, d18.
1064 __ mov(r4, Operand(r0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001065 __ vldr(d16, r4, offsetof(T, a));
1066 __ vldr(d17, r4, offsetof(T, b));
1067 __ vldr(d18, r4, offsetof(T, c));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001068
1069 __ vneg(d25, d16);
1070 __ vadd(d25, d25, d17);
1071 __ vsub(d25, d25, d18);
1072 __ vmul(d25, d25, d25);
1073 __ vdiv(d25, d25, d18);
1074
1075 __ vmov(d16, d25);
1076 __ vsqrt(d17, d25);
1077 __ vneg(d17, d17);
1078 __ vabs(d17, d17);
1079 __ vmla(d18, d16, d17);
1080
1081 // Store d16, d17, d18 into a, b, c.
1082 __ mov(r4, Operand(r0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001083 __ vstr(d16, r4, offsetof(T, a));
1084 __ vstr(d17, r4, offsetof(T, b));
1085 __ vstr(d18, r4, offsetof(T, c));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001086
1087 // Load x, y, z into d29-d31.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001088 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, x))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001089 __ vldm(ia_w, r4, d29, d31);
1090
1091 // Swap d29 and d30 via r registers.
1092 __ vmov(r1, r2, d29);
1093 __ vmov(d29, d30);
1094 __ vmov(d30, r1, r2);
1095
1096 // Convert to and from integer.
1097 __ vcvt_s32_f64(s1, d31);
1098 __ vcvt_f64_u32(d31, s1);
1099
1100 // Store d29-d31 into x, y, z.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001101 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, x))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001102 __ vstm(ia_w, r4, d29, d31);
1103
1104 // Move constants into d20, d21, d22 and store into i, j, k.
1105 __ vmov(d20, 14.7610017472335499);
1106 __ vmov(d21, 16.0);
1107 __ mov(r1, Operand(372106121));
1108 __ mov(r2, Operand(1079146608));
1109 __ vmov(d22, VmovIndexLo, r1);
1110 __ vmov(d22, VmovIndexHi, r2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001111 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, i))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001112 __ vstm(ia_w, r4, d20, d22);
1113 // Move d22 into low and high.
1114 __ vmov(r4, VmovIndexLo, d22);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001115 __ str(r4, MemOperand(r0, offsetof(T, low)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001116 __ vmov(r4, VmovIndexHi, d22);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001117 __ str(r4, MemOperand(r0, offsetof(T, high)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001118
1119 __ ldm(ia_w, sp, r4.bit() | pc.bit());
1120
1121 CodeDesc desc;
1122 assm.GetCode(&desc);
1123 Handle<Code> code = isolate->factory()->NewCode(
1124 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1125#ifdef DEBUG
1126 OFStream os(stdout);
1127 code->Print(os);
1128#endif
1129 F3 f = FUNCTION_CAST<F3>(code->entry());
1130 t.a = 1.5;
1131 t.b = 2.75;
1132 t.c = 17.17;
1133 t.x = 1.5;
1134 t.y = 2.75;
1135 t.z = 17.17;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001136 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001137 USE(dummy);
1138 CHECK_EQ(14.7610017472335499, t.a);
1139 CHECK_EQ(3.84200491244266251, t.b);
1140 CHECK_EQ(73.8818412254460241, t.c);
1141 CHECK_EQ(2.75, t.x);
1142 CHECK_EQ(1.5, t.y);
1143 CHECK_EQ(17.0, t.z);
1144 CHECK_EQ(14.7610017472335499, t.i);
1145 CHECK_EQ(16.0, t.j);
1146 CHECK_EQ(73.8818412254460241, t.k);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001147 CHECK_EQ(372106121u, t.low);
1148 CHECK_EQ(1079146608u, t.high);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001149 }
1150}
1151
1152
1153TEST(14) {
1154 // Test the VFP Canonicalized Nan mode.
1155 CcTest::InitializeVM();
1156 Isolate* isolate = CcTest::i_isolate();
1157 HandleScope scope(isolate);
1158
1159 typedef struct {
1160 double left;
1161 double right;
1162 double add_result;
1163 double sub_result;
1164 double mul_result;
1165 double div_result;
1166 } T;
1167 T t;
1168
1169 // Create a function that makes the four basic operations.
1170 Assembler assm(isolate, NULL, 0);
1171
1172 // Ensure FPSCR state (as JSEntryStub does).
1173 Label fpscr_done;
1174 __ vmrs(r1);
1175 __ tst(r1, Operand(kVFPDefaultNaNModeControlBit));
1176 __ b(ne, &fpscr_done);
1177 __ orr(r1, r1, Operand(kVFPDefaultNaNModeControlBit));
1178 __ vmsr(r1);
1179 __ bind(&fpscr_done);
1180
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001181 __ vldr(d0, r0, offsetof(T, left));
1182 __ vldr(d1, r0, offsetof(T, right));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001183 __ vadd(d2, d0, d1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001184 __ vstr(d2, r0, offsetof(T, add_result));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001185 __ vsub(d2, d0, d1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001186 __ vstr(d2, r0, offsetof(T, sub_result));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001187 __ vmul(d2, d0, d1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001188 __ vstr(d2, r0, offsetof(T, mul_result));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001189 __ vdiv(d2, d0, d1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001190 __ vstr(d2, r0, offsetof(T, div_result));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001191
1192 __ mov(pc, Operand(lr));
1193
1194 CodeDesc desc;
1195 assm.GetCode(&desc);
1196 Handle<Code> code = isolate->factory()->NewCode(
1197 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1198#ifdef DEBUG
1199 OFStream os(stdout);
1200 code->Print(os);
1201#endif
1202 F3 f = FUNCTION_CAST<F3>(code->entry());
1203 t.left = bit_cast<double>(kHoleNanInt64);
1204 t.right = 1;
1205 t.add_result = 0;
1206 t.sub_result = 0;
1207 t.mul_result = 0;
1208 t.div_result = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001209 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001210 USE(dummy);
1211 const uint32_t kArmNanUpper32 = 0x7ff80000;
1212 const uint32_t kArmNanLower32 = 0x00000000;
1213#ifdef DEBUG
1214 const uint64_t kArmNanInt64 =
1215 (static_cast<uint64_t>(kArmNanUpper32) << 32) | kArmNanLower32;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001216 CHECK(kArmNanInt64 != kHoleNanInt64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001217#endif
1218 // With VFP2 the sign of the canonicalized Nan is undefined. So
1219 // we remove the sign bit for the upper tests.
1220 CHECK_EQ(kArmNanUpper32,
1221 (bit_cast<int64_t>(t.add_result) >> 32) & 0x7fffffff);
1222 CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.add_result) & 0xffffffffu);
1223 CHECK_EQ(kArmNanUpper32,
1224 (bit_cast<int64_t>(t.sub_result) >> 32) & 0x7fffffff);
1225 CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.sub_result) & 0xffffffffu);
1226 CHECK_EQ(kArmNanUpper32,
1227 (bit_cast<int64_t>(t.mul_result) >> 32) & 0x7fffffff);
1228 CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.mul_result) & 0xffffffffu);
1229 CHECK_EQ(kArmNanUpper32,
1230 (bit_cast<int64_t>(t.div_result) >> 32) & 0x7fffffff);
1231 CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.div_result) & 0xffffffffu);
1232}
1233
1234
1235TEST(15) {
1236 // Test the Neon instructions.
1237 CcTest::InitializeVM();
1238 Isolate* isolate = CcTest::i_isolate();
1239 HandleScope scope(isolate);
1240
1241 typedef struct {
1242 uint32_t src0;
1243 uint32_t src1;
1244 uint32_t src2;
1245 uint32_t src3;
1246 uint32_t src4;
1247 uint32_t src5;
1248 uint32_t src6;
1249 uint32_t src7;
1250 uint32_t dst0;
1251 uint32_t dst1;
1252 uint32_t dst2;
1253 uint32_t dst3;
1254 uint32_t dst4;
1255 uint32_t dst5;
1256 uint32_t dst6;
1257 uint32_t dst7;
1258 uint32_t srcA0;
1259 uint32_t srcA1;
1260 uint32_t dstA0;
1261 uint32_t dstA1;
1262 uint32_t dstA2;
1263 uint32_t dstA3;
1264 uint32_t dstA4;
1265 uint32_t dstA5;
1266 uint32_t dstA6;
1267 uint32_t dstA7;
1268 } T;
1269 T t;
1270
1271 // Create a function that accepts &t, and loads, manipulates, and stores
1272 // the doubles and floats.
1273 Assembler assm(isolate, NULL, 0);
1274
1275
1276 if (CpuFeatures::IsSupported(NEON)) {
1277 CpuFeatureScope scope(&assm, NEON);
1278
1279 __ stm(db_w, sp, r4.bit() | lr.bit());
1280 // Move 32 bytes with neon.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001281 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, src0))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001282 __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001283 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, dst0))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001284 __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4));
1285
1286 // Expand 8 bytes into 8 words(16 bits).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001287 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, srcA0))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001288 __ vld1(Neon8, NeonListOperand(d0), NeonMemOperand(r4));
1289 __ vmovl(NeonU8, q0, d0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001290 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, dstA0))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001291 __ vst1(Neon8, NeonListOperand(d0, 2), NeonMemOperand(r4));
1292
1293 // The same expansion, but with different source and destination registers.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001294 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, srcA0))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001295 __ vld1(Neon8, NeonListOperand(d1), NeonMemOperand(r4));
1296 __ vmovl(NeonU8, q1, d1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001297 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, dstA4))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001298 __ vst1(Neon8, NeonListOperand(d2, 2), NeonMemOperand(r4));
1299
1300 __ ldm(ia_w, sp, r4.bit() | pc.bit());
1301
1302 CodeDesc desc;
1303 assm.GetCode(&desc);
1304 Handle<Code> code = isolate->factory()->NewCode(
1305 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1306#ifdef DEBUG
1307 OFStream os(stdout);
1308 code->Print(os);
1309#endif
1310 F3 f = FUNCTION_CAST<F3>(code->entry());
1311 t.src0 = 0x01020304;
1312 t.src1 = 0x11121314;
1313 t.src2 = 0x21222324;
1314 t.src3 = 0x31323334;
1315 t.src4 = 0x41424344;
1316 t.src5 = 0x51525354;
1317 t.src6 = 0x61626364;
1318 t.src7 = 0x71727374;
1319 t.dst0 = 0;
1320 t.dst1 = 0;
1321 t.dst2 = 0;
1322 t.dst3 = 0;
1323 t.dst4 = 0;
1324 t.dst5 = 0;
1325 t.dst6 = 0;
1326 t.dst7 = 0;
1327 t.srcA0 = 0x41424344;
1328 t.srcA1 = 0x81828384;
1329 t.dstA0 = 0;
1330 t.dstA1 = 0;
1331 t.dstA2 = 0;
1332 t.dstA3 = 0;
1333 t.dstA4 = 0;
1334 t.dstA5 = 0;
1335 t.dstA6 = 0;
1336 t.dstA7 = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001337 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001338 USE(dummy);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001339 CHECK_EQ(0x01020304u, t.dst0);
1340 CHECK_EQ(0x11121314u, t.dst1);
1341 CHECK_EQ(0x21222324u, t.dst2);
1342 CHECK_EQ(0x31323334u, t.dst3);
1343 CHECK_EQ(0x41424344u, t.dst4);
1344 CHECK_EQ(0x51525354u, t.dst5);
1345 CHECK_EQ(0x61626364u, t.dst6);
1346 CHECK_EQ(0x71727374u, t.dst7);
1347 CHECK_EQ(0x00430044u, t.dstA0);
1348 CHECK_EQ(0x00410042u, t.dstA1);
1349 CHECK_EQ(0x00830084u, t.dstA2);
1350 CHECK_EQ(0x00810082u, t.dstA3);
1351 CHECK_EQ(0x00430044u, t.dstA4);
1352 CHECK_EQ(0x00410042u, t.dstA5);
1353 CHECK_EQ(0x00830084u, t.dstA6);
1354 CHECK_EQ(0x00810082u, t.dstA7);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001355 }
1356}
1357
1358
1359TEST(16) {
1360 // Test the pkh, uxtb, uxtab and uxtb16 instructions.
1361 CcTest::InitializeVM();
1362 Isolate* isolate = CcTest::i_isolate();
1363 HandleScope scope(isolate);
1364
1365 typedef struct {
1366 uint32_t src0;
1367 uint32_t src1;
1368 uint32_t src2;
1369 uint32_t dst0;
1370 uint32_t dst1;
1371 uint32_t dst2;
1372 uint32_t dst3;
1373 uint32_t dst4;
1374 } T;
1375 T t;
1376
1377 // Create a function that accepts &t, and loads, manipulates, and stores
1378 // the doubles and floats.
1379 Assembler assm(isolate, NULL, 0);
1380
1381 __ stm(db_w, sp, r4.bit() | lr.bit());
1382
1383 __ mov(r4, Operand(r0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001384 __ ldr(r0, MemOperand(r4, offsetof(T, src0)));
1385 __ ldr(r1, MemOperand(r4, offsetof(T, src1)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001386
1387 __ pkhbt(r2, r0, Operand(r1, LSL, 8));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001388 __ str(r2, MemOperand(r4, offsetof(T, dst0)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001389
1390 __ pkhtb(r2, r0, Operand(r1, ASR, 8));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001391 __ str(r2, MemOperand(r4, offsetof(T, dst1)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001392
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001393 __ uxtb16(r2, r0, 8);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001394 __ str(r2, MemOperand(r4, offsetof(T, dst2)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001395
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001396 __ uxtb(r2, r0, 8);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001397 __ str(r2, MemOperand(r4, offsetof(T, dst3)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001398
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001399 __ ldr(r0, MemOperand(r4, offsetof(T, src2)));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001400 __ uxtab(r2, r0, r1, 8);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001401 __ str(r2, MemOperand(r4, offsetof(T, dst4)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001402
1403 __ ldm(ia_w, sp, r4.bit() | pc.bit());
1404
1405 CodeDesc desc;
1406 assm.GetCode(&desc);
1407 Handle<Code> code = isolate->factory()->NewCode(
1408 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1409#ifdef DEBUG
1410 OFStream os(stdout);
1411 code->Print(os);
1412#endif
1413 F3 f = FUNCTION_CAST<F3>(code->entry());
1414 t.src0 = 0x01020304;
1415 t.src1 = 0x11121314;
1416 t.src2 = 0x11121300;
1417 t.dst0 = 0;
1418 t.dst1 = 0;
1419 t.dst2 = 0;
1420 t.dst3 = 0;
1421 t.dst4 = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001422 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001423 USE(dummy);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001424 CHECK_EQ(0x12130304u, t.dst0);
1425 CHECK_EQ(0x01021213u, t.dst1);
1426 CHECK_EQ(0x00010003u, t.dst2);
1427 CHECK_EQ(0x00000003u, t.dst3);
1428 CHECK_EQ(0x11121313u, t.dst4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001429}
1430
1431
1432TEST(17) {
1433 // Test generating labels at high addresses.
1434 // Should not assert.
1435 CcTest::InitializeVM();
1436 Isolate* isolate = CcTest::i_isolate();
1437 HandleScope scope(isolate);
1438
1439 // Generate a code segment that will be longer than 2^24 bytes.
1440 Assembler assm(isolate, NULL, 0);
1441 for (size_t i = 0; i < 1 << 23 ; ++i) { // 2^23
1442 __ nop();
1443 }
1444
1445 Label target;
1446 __ b(eq, &target);
1447 __ bind(&target);
1448 __ nop();
1449}
1450
1451
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001452#define TEST_SDIV(expected_, dividend_, divisor_) \
1453 t.dividend = dividend_; \
1454 t.divisor = divisor_; \
1455 t.result = 0; \
1456 dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); \
1457 CHECK_EQ(expected_, t.result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001458
1459
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001460TEST(sdiv) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001461 // Test the sdiv.
1462 CcTest::InitializeVM();
1463 Isolate* isolate = CcTest::i_isolate();
1464 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001465 Assembler assm(isolate, NULL, 0);
1466
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001467 struct T {
1468 int32_t dividend;
1469 int32_t divisor;
1470 int32_t result;
1471 } t;
1472
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001473 if (CpuFeatures::IsSupported(SUDIV)) {
1474 CpuFeatureScope scope(&assm, SUDIV);
1475
1476 __ mov(r3, Operand(r0));
1477
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001478 __ ldr(r0, MemOperand(r3, offsetof(T, dividend)));
1479 __ ldr(r1, MemOperand(r3, offsetof(T, divisor)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001480
1481 __ sdiv(r2, r0, r1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001482 __ str(r2, MemOperand(r3, offsetof(T, result)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001483
1484 __ bx(lr);
1485
1486 CodeDesc desc;
1487 assm.GetCode(&desc);
1488 Handle<Code> code = isolate->factory()->NewCode(
1489 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1490#ifdef DEBUG
1491 OFStream os(stdout);
1492 code->Print(os);
1493#endif
1494 F3 f = FUNCTION_CAST<F3>(code->entry());
1495 Object* dummy;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001496 TEST_SDIV(0, kMinInt, 0);
1497 TEST_SDIV(0, 1024, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001498 TEST_SDIV(1073741824, kMinInt, -2);
1499 TEST_SDIV(kMinInt, kMinInt, -1);
1500 TEST_SDIV(5, 10, 2);
1501 TEST_SDIV(3, 10, 3);
1502 TEST_SDIV(-5, 10, -2);
1503 TEST_SDIV(-3, 10, -3);
1504 TEST_SDIV(-5, -10, 2);
1505 TEST_SDIV(-3, -10, 3);
1506 TEST_SDIV(5, -10, -2);
1507 TEST_SDIV(3, -10, -3);
1508 USE(dummy);
1509 }
1510}
1511
1512
1513#undef TEST_SDIV
1514
1515
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001516#define TEST_UDIV(expected_, dividend_, divisor_) \
1517 t.dividend = dividend_; \
1518 t.divisor = divisor_; \
1519 t.result = 0; \
1520 dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); \
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001521 CHECK_EQ(expected_, t.result);
1522
1523
1524TEST(udiv) {
1525 // Test the udiv.
1526 CcTest::InitializeVM();
1527 Isolate* isolate = CcTest::i_isolate();
1528 HandleScope scope(isolate);
1529 Assembler assm(isolate, NULL, 0);
1530
1531 struct T {
1532 uint32_t dividend;
1533 uint32_t divisor;
1534 uint32_t result;
1535 } t;
1536
1537 if (CpuFeatures::IsSupported(SUDIV)) {
1538 CpuFeatureScope scope(&assm, SUDIV);
1539
1540 __ mov(r3, Operand(r0));
1541
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001542 __ ldr(r0, MemOperand(r3, offsetof(T, dividend)));
1543 __ ldr(r1, MemOperand(r3, offsetof(T, divisor)));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001544
1545 __ sdiv(r2, r0, r1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001546 __ str(r2, MemOperand(r3, offsetof(T, result)));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001547
1548 __ bx(lr);
1549
1550 CodeDesc desc;
1551 assm.GetCode(&desc);
1552 Handle<Code> code = isolate->factory()->NewCode(
1553 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1554#ifdef DEBUG
1555 OFStream os(stdout);
1556 code->Print(os);
1557#endif
1558 F3 f = FUNCTION_CAST<F3>(code->entry());
1559 Object* dummy;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001560 TEST_UDIV(0u, 0, 0);
1561 TEST_UDIV(0u, 1024, 0);
1562 TEST_UDIV(5u, 10, 2);
1563 TEST_UDIV(3u, 10, 3);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001564 USE(dummy);
1565 }
1566}
1567
1568
1569#undef TEST_UDIV
1570
1571
1572TEST(smmla) {
1573 CcTest::InitializeVM();
1574 Isolate* const isolate = CcTest::i_isolate();
1575 HandleScope scope(isolate);
1576 RandomNumberGenerator* const rng = isolate->random_number_generator();
1577 Assembler assm(isolate, nullptr, 0);
1578 __ smmla(r1, r1, r2, r3);
1579 __ str(r1, MemOperand(r0));
1580 __ bx(lr);
1581 CodeDesc desc;
1582 assm.GetCode(&desc);
1583 Handle<Code> code = isolate->factory()->NewCode(
1584 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1585#ifdef OBJECT_PRINT
1586 code->Print(std::cout);
1587#endif
1588 F3 f = FUNCTION_CAST<F3>(code->entry());
1589 for (size_t i = 0; i < 128; ++i) {
1590 int32_t r, x = rng->NextInt(), y = rng->NextInt(), z = rng->NextInt();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001591 Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, y, z, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001592 CHECK_EQ(bits::SignedMulHighAndAdd32(x, y, z), r);
1593 USE(dummy);
1594 }
1595}
1596
1597
1598TEST(smmul) {
1599 CcTest::InitializeVM();
1600 Isolate* const isolate = CcTest::i_isolate();
1601 HandleScope scope(isolate);
1602 RandomNumberGenerator* const rng = isolate->random_number_generator();
1603 Assembler assm(isolate, nullptr, 0);
1604 __ smmul(r1, r1, r2);
1605 __ str(r1, MemOperand(r0));
1606 __ bx(lr);
1607 CodeDesc desc;
1608 assm.GetCode(&desc);
1609 Handle<Code> code = isolate->factory()->NewCode(
1610 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1611#ifdef OBJECT_PRINT
1612 code->Print(std::cout);
1613#endif
1614 F3 f = FUNCTION_CAST<F3>(code->entry());
1615 for (size_t i = 0; i < 128; ++i) {
1616 int32_t r, x = rng->NextInt(), y = rng->NextInt();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001617 Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, y, 0, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001618 CHECK_EQ(bits::SignedMulHigh32(x, y), r);
1619 USE(dummy);
1620 }
1621}
1622
1623
1624TEST(sxtb) {
1625 CcTest::InitializeVM();
1626 Isolate* const isolate = CcTest::i_isolate();
1627 HandleScope scope(isolate);
1628 RandomNumberGenerator* const rng = isolate->random_number_generator();
1629 Assembler assm(isolate, nullptr, 0);
1630 __ sxtb(r1, r1);
1631 __ str(r1, MemOperand(r0));
1632 __ bx(lr);
1633 CodeDesc desc;
1634 assm.GetCode(&desc);
1635 Handle<Code> code = isolate->factory()->NewCode(
1636 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1637#ifdef OBJECT_PRINT
1638 code->Print(std::cout);
1639#endif
1640 F3 f = FUNCTION_CAST<F3>(code->entry());
1641 for (size_t i = 0; i < 128; ++i) {
1642 int32_t r, x = rng->NextInt();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001643 Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, 0, 0, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001644 CHECK_EQ(static_cast<int32_t>(static_cast<int8_t>(x)), r);
1645 USE(dummy);
1646 }
1647}
1648
1649
1650TEST(sxtab) {
1651 CcTest::InitializeVM();
1652 Isolate* const isolate = CcTest::i_isolate();
1653 HandleScope scope(isolate);
1654 RandomNumberGenerator* const rng = isolate->random_number_generator();
1655 Assembler assm(isolate, nullptr, 0);
1656 __ sxtab(r1, r2, r1);
1657 __ str(r1, MemOperand(r0));
1658 __ bx(lr);
1659 CodeDesc desc;
1660 assm.GetCode(&desc);
1661 Handle<Code> code = isolate->factory()->NewCode(
1662 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1663#ifdef OBJECT_PRINT
1664 code->Print(std::cout);
1665#endif
1666 F3 f = FUNCTION_CAST<F3>(code->entry());
1667 for (size_t i = 0; i < 128; ++i) {
1668 int32_t r, x = rng->NextInt(), y = rng->NextInt();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001669 Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, y, 0, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001670 CHECK_EQ(static_cast<int32_t>(static_cast<int8_t>(x)) + y, r);
1671 USE(dummy);
1672 }
1673}
1674
1675
1676TEST(sxth) {
1677 CcTest::InitializeVM();
1678 Isolate* const isolate = CcTest::i_isolate();
1679 HandleScope scope(isolate);
1680 RandomNumberGenerator* const rng = isolate->random_number_generator();
1681 Assembler assm(isolate, nullptr, 0);
1682 __ sxth(r1, r1);
1683 __ str(r1, MemOperand(r0));
1684 __ bx(lr);
1685 CodeDesc desc;
1686 assm.GetCode(&desc);
1687 Handle<Code> code = isolate->factory()->NewCode(
1688 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1689#ifdef OBJECT_PRINT
1690 code->Print(std::cout);
1691#endif
1692 F3 f = FUNCTION_CAST<F3>(code->entry());
1693 for (size_t i = 0; i < 128; ++i) {
1694 int32_t r, x = rng->NextInt();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001695 Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, 0, 0, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001696 CHECK_EQ(static_cast<int32_t>(static_cast<int16_t>(x)), r);
1697 USE(dummy);
1698 }
1699}
1700
1701
1702TEST(sxtah) {
1703 CcTest::InitializeVM();
1704 Isolate* const isolate = CcTest::i_isolate();
1705 HandleScope scope(isolate);
1706 RandomNumberGenerator* const rng = isolate->random_number_generator();
1707 Assembler assm(isolate, nullptr, 0);
1708 __ sxtah(r1, r2, r1);
1709 __ str(r1, MemOperand(r0));
1710 __ bx(lr);
1711 CodeDesc desc;
1712 assm.GetCode(&desc);
1713 Handle<Code> code = isolate->factory()->NewCode(
1714 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1715#ifdef OBJECT_PRINT
1716 code->Print(std::cout);
1717#endif
1718 F3 f = FUNCTION_CAST<F3>(code->entry());
1719 for (size_t i = 0; i < 128; ++i) {
1720 int32_t r, x = rng->NextInt(), y = rng->NextInt();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001721 Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, y, 0, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001722 CHECK_EQ(static_cast<int32_t>(static_cast<int16_t>(x)) + y, r);
1723 USE(dummy);
1724 }
1725}
1726
1727
1728TEST(uxtb) {
1729 CcTest::InitializeVM();
1730 Isolate* const isolate = CcTest::i_isolate();
1731 HandleScope scope(isolate);
1732 RandomNumberGenerator* const rng = isolate->random_number_generator();
1733 Assembler assm(isolate, nullptr, 0);
1734 __ uxtb(r1, r1);
1735 __ str(r1, MemOperand(r0));
1736 __ bx(lr);
1737 CodeDesc desc;
1738 assm.GetCode(&desc);
1739 Handle<Code> code = isolate->factory()->NewCode(
1740 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1741#ifdef OBJECT_PRINT
1742 code->Print(std::cout);
1743#endif
1744 F3 f = FUNCTION_CAST<F3>(code->entry());
1745 for (size_t i = 0; i < 128; ++i) {
1746 int32_t r, x = rng->NextInt();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001747 Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, 0, 0, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001748 CHECK_EQ(static_cast<int32_t>(static_cast<uint8_t>(x)), r);
1749 USE(dummy);
1750 }
1751}
1752
1753
1754TEST(uxtab) {
1755 CcTest::InitializeVM();
1756 Isolate* const isolate = CcTest::i_isolate();
1757 HandleScope scope(isolate);
1758 RandomNumberGenerator* const rng = isolate->random_number_generator();
1759 Assembler assm(isolate, nullptr, 0);
1760 __ uxtab(r1, r2, r1);
1761 __ str(r1, MemOperand(r0));
1762 __ bx(lr);
1763 CodeDesc desc;
1764 assm.GetCode(&desc);
1765 Handle<Code> code = isolate->factory()->NewCode(
1766 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1767#ifdef OBJECT_PRINT
1768 code->Print(std::cout);
1769#endif
1770 F3 f = FUNCTION_CAST<F3>(code->entry());
1771 for (size_t i = 0; i < 128; ++i) {
1772 int32_t r, x = rng->NextInt(), y = rng->NextInt();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001773 Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, y, 0, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001774 CHECK_EQ(static_cast<int32_t>(static_cast<uint8_t>(x)) + y, r);
1775 USE(dummy);
1776 }
1777}
1778
1779
1780TEST(uxth) {
1781 CcTest::InitializeVM();
1782 Isolate* const isolate = CcTest::i_isolate();
1783 HandleScope scope(isolate);
1784 RandomNumberGenerator* const rng = isolate->random_number_generator();
1785 Assembler assm(isolate, nullptr, 0);
1786 __ uxth(r1, r1);
1787 __ str(r1, MemOperand(r0));
1788 __ bx(lr);
1789 CodeDesc desc;
1790 assm.GetCode(&desc);
1791 Handle<Code> code = isolate->factory()->NewCode(
1792 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1793#ifdef OBJECT_PRINT
1794 code->Print(std::cout);
1795#endif
1796 F3 f = FUNCTION_CAST<F3>(code->entry());
1797 for (size_t i = 0; i < 128; ++i) {
1798 int32_t r, x = rng->NextInt();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001799 Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, 0, 0, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001800 CHECK_EQ(static_cast<int32_t>(static_cast<uint16_t>(x)), r);
1801 USE(dummy);
1802 }
1803}
1804
1805
1806TEST(uxtah) {
1807 CcTest::InitializeVM();
1808 Isolate* const isolate = CcTest::i_isolate();
1809 HandleScope scope(isolate);
1810 RandomNumberGenerator* const rng = isolate->random_number_generator();
1811 Assembler assm(isolate, nullptr, 0);
1812 __ uxtah(r1, r2, r1);
1813 __ str(r1, MemOperand(r0));
1814 __ bx(lr);
1815 CodeDesc desc;
1816 assm.GetCode(&desc);
1817 Handle<Code> code = isolate->factory()->NewCode(
1818 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1819#ifdef OBJECT_PRINT
1820 code->Print(std::cout);
1821#endif
1822 F3 f = FUNCTION_CAST<F3>(code->entry());
1823 for (size_t i = 0; i < 128; ++i) {
1824 int32_t r, x = rng->NextInt(), y = rng->NextInt();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001825 Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, y, 0, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001826 CHECK_EQ(static_cast<int32_t>(static_cast<uint16_t>(x)) + y, r);
1827 USE(dummy);
1828 }
1829}
1830
1831
Ben Murdoch097c5b22016-05-18 11:27:45 +01001832#define TEST_RBIT(expected_, input_) \
1833 t.input = input_; \
1834 t.result = 0; \
1835 dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); \
1836 CHECK_EQ(expected_, t.result);
1837
1838
1839TEST(rbit) {
1840 CcTest::InitializeVM();
1841 Isolate* const isolate = CcTest::i_isolate();
1842 HandleScope scope(isolate);
1843 Assembler assm(isolate, nullptr, 0);
1844
1845 if (CpuFeatures::IsSupported(ARMv7)) {
1846 CpuFeatureScope scope(&assm, ARMv7);
1847
1848 typedef struct {
1849 uint32_t input;
1850 uint32_t result;
1851 } T;
1852 T t;
1853
1854 __ ldr(r1, MemOperand(r0, offsetof(T, input)));
1855 __ rbit(r1, r1);
1856 __ str(r1, MemOperand(r0, offsetof(T, result)));
1857 __ bx(lr);
1858
1859 CodeDesc desc;
1860 assm.GetCode(&desc);
1861 Handle<Code> code = isolate->factory()->NewCode(
1862 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1863
1864#ifdef OBJECT_PRINT
1865 code->Print(std::cout);
1866#endif
1867
1868 F3 f = FUNCTION_CAST<F3>(code->entry());
1869 Object* dummy = NULL;
1870 TEST_RBIT(0xffffffff, 0xffffffff);
1871 TEST_RBIT(0x00000000, 0x00000000);
1872 TEST_RBIT(0xffff0000, 0x0000ffff);
1873 TEST_RBIT(0xff00ff00, 0x00ff00ff);
1874 TEST_RBIT(0xf0f0f0f0, 0x0f0f0f0f);
1875 TEST_RBIT(0x1e6a2c48, 0x12345678);
1876 USE(dummy);
1877 }
1878}
1879
1880
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001881TEST(code_relative_offset) {
1882 // Test extracting the offset of a label from the beginning of the code
1883 // in a register.
1884 CcTest::InitializeVM();
1885 Isolate* isolate = CcTest::i_isolate();
1886 HandleScope scope(isolate);
1887 // Initialize a code object that will contain the code.
1888 Handle<Object> code_object(isolate->heap()->undefined_value(), isolate);
1889
1890 Assembler assm(isolate, NULL, 0);
1891
1892 Label start, target_away, target_faraway;
1893
1894 __ stm(db_w, sp, r4.bit() | r5.bit() | lr.bit());
1895
1896 // r3 is used as the address zero, the test will crash when we load it.
1897 __ mov(r3, Operand::Zero());
1898
1899 // r5 will be a pointer to the start of the code.
1900 __ mov(r5, Operand(code_object));
1901 __ mov_label_offset(r4, &start);
1902
1903 __ mov_label_offset(r1, &target_faraway);
1904 __ str(r1, MemOperand(sp, kPointerSize, NegPreIndex));
1905
1906 __ mov_label_offset(r1, &target_away);
1907
1908 // Jump straight to 'target_away' the first time and use the relative
1909 // position the second time. This covers the case when extracting the
1910 // position of a label which is linked.
1911 __ mov(r2, Operand::Zero());
1912 __ bind(&start);
1913 __ cmp(r2, Operand::Zero());
1914 __ b(eq, &target_away);
1915 __ add(pc, r5, r1);
1916 // Emit invalid instructions to push the label between 2^8 and 2^16
1917 // instructions away. The test will crash if they are reached.
1918 for (int i = 0; i < (1 << 10); i++) {
1919 __ ldr(r3, MemOperand(r3));
1920 }
1921 __ bind(&target_away);
1922 // This will be hit twice: r0 = r0 + 5 + 5.
1923 __ add(r0, r0, Operand(5));
1924
1925 __ ldr(r1, MemOperand(sp, kPointerSize, PostIndex), ne);
1926 __ add(pc, r5, r4, LeaveCC, ne);
1927
1928 __ mov(r2, Operand(1));
1929 __ b(&start);
1930 // Emit invalid instructions to push the label between 2^16 and 2^24
1931 // instructions away. The test will crash if they are reached.
1932 for (int i = 0; i < (1 << 21); i++) {
1933 __ ldr(r3, MemOperand(r3));
1934 }
1935 __ bind(&target_faraway);
1936 // r0 = r0 + 5 + 5 + 11
1937 __ add(r0, r0, Operand(11));
1938
1939 __ ldm(ia_w, sp, r4.bit() | r5.bit() | pc.bit());
1940
1941 CodeDesc desc;
1942 assm.GetCode(&desc);
1943 Handle<Code> code = isolate->factory()->NewCode(
1944 desc, Code::ComputeFlags(Code::STUB), code_object);
1945 F1 f = FUNCTION_CAST<F1>(code->entry());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001946 int res =
1947 reinterpret_cast<int>(CALL_GENERATED_CODE(isolate, f, 21, 0, 0, 0, 0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001948 ::printf("f() = %d\n", res);
1949 CHECK_EQ(42, res);
1950}
1951
Ben Murdochda12d292016-06-02 14:46:10 +01001952TEST(msr_mrs) {
1953 // Test msr and mrs.
1954 CcTest::InitializeVM();
1955 Isolate* isolate = CcTest::i_isolate();
1956 HandleScope scope(isolate);
1957
1958 Assembler assm(isolate, NULL, 0);
1959
1960 // Create a helper function:
1961 // void TestMsrMrs(uint32_t nzcv,
1962 // uint32_t * result_conditionals,
1963 // uint32_t * result_mrs);
1964 __ msr(CPSR_f, Operand(r0));
1965
1966 // Test that the condition flags have taken effect.
1967 __ mov(r3, Operand(0));
1968 __ orr(r3, r3, Operand(1 << 31), LeaveCC, mi); // N
1969 __ orr(r3, r3, Operand(1 << 30), LeaveCC, eq); // Z
1970 __ orr(r3, r3, Operand(1 << 29), LeaveCC, cs); // C
1971 __ orr(r3, r3, Operand(1 << 28), LeaveCC, vs); // V
1972 __ str(r3, MemOperand(r1));
1973
1974 // Also check mrs, ignoring everything other than the flags.
1975 __ mrs(r3, CPSR);
1976 __ and_(r3, r3, Operand(kSpecialCondition));
1977 __ str(r3, MemOperand(r2));
1978
1979 __ bx(lr);
1980
1981 CodeDesc desc;
1982 assm.GetCode(&desc);
1983 Handle<Code> code = isolate->factory()->NewCode(
1984 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1985#ifdef DEBUG
1986 OFStream os(stdout);
1987 code->Print(os);
1988#endif
1989 F5 f = FUNCTION_CAST<F5>(code->entry());
1990 Object* dummy = nullptr;
1991 USE(dummy);
1992
1993#define CHECK_MSR_MRS(n, z, c, v) \
1994 do { \
1995 uint32_t nzcv = (n << 31) | (z << 30) | (c << 29) | (v << 28); \
1996 uint32_t result_conditionals = -1; \
1997 uint32_t result_mrs = -1; \
1998 dummy = CALL_GENERATED_CODE(isolate, f, nzcv, &result_conditionals, \
1999 &result_mrs, 0, 0); \
2000 CHECK_EQ(nzcv, result_conditionals); \
2001 CHECK_EQ(nzcv, result_mrs); \
2002 } while (0);
2003
2004 // N Z C V
2005 CHECK_MSR_MRS(0, 0, 0, 0);
2006 CHECK_MSR_MRS(0, 0, 0, 1);
2007 CHECK_MSR_MRS(0, 0, 1, 0);
2008 CHECK_MSR_MRS(0, 0, 1, 1);
2009 CHECK_MSR_MRS(0, 1, 0, 0);
2010 CHECK_MSR_MRS(0, 1, 0, 1);
2011 CHECK_MSR_MRS(0, 1, 1, 0);
2012 CHECK_MSR_MRS(0, 1, 1, 1);
2013 CHECK_MSR_MRS(1, 0, 0, 0);
2014 CHECK_MSR_MRS(1, 0, 0, 1);
2015 CHECK_MSR_MRS(1, 0, 1, 0);
2016 CHECK_MSR_MRS(1, 0, 1, 1);
2017 CHECK_MSR_MRS(1, 1, 0, 0);
2018 CHECK_MSR_MRS(1, 1, 0, 1);
2019 CHECK_MSR_MRS(1, 1, 1, 0);
2020 CHECK_MSR_MRS(1, 1, 1, 1);
2021
2022#undef CHECK_MSR_MRS
2023}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002024
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002025TEST(ARMv8_float32_vrintX) {
2026 // Test the vrintX floating point instructions.
2027 CcTest::InitializeVM();
2028 Isolate* isolate = CcTest::i_isolate();
2029 HandleScope scope(isolate);
2030
2031 typedef struct {
2032 float input;
2033 float ar;
2034 float nr;
2035 float mr;
2036 float pr;
2037 float zr;
2038 } T;
2039 T t;
2040
2041 // Create a function that accepts &t, and loads, manipulates, and stores
2042 // the floats.
2043 Assembler assm(isolate, NULL, 0);
2044 Label L, C;
2045
2046
2047 if (CpuFeatures::IsSupported(ARMv8)) {
2048 CpuFeatureScope scope(&assm, ARMv8);
2049
2050 __ mov(ip, Operand(sp));
2051 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
2052
2053 __ mov(r4, Operand(r0));
2054
2055 // Test vrinta
2056 __ vldr(s6, r4, offsetof(T, input));
2057 __ vrinta(s5, s6);
2058 __ vstr(s5, r4, offsetof(T, ar));
2059
2060 // Test vrintn
2061 __ vldr(s6, r4, offsetof(T, input));
2062 __ vrintn(s5, s6);
2063 __ vstr(s5, r4, offsetof(T, nr));
2064
2065 // Test vrintp
2066 __ vldr(s6, r4, offsetof(T, input));
2067 __ vrintp(s5, s6);
2068 __ vstr(s5, r4, offsetof(T, pr));
2069
2070 // Test vrintm
2071 __ vldr(s6, r4, offsetof(T, input));
2072 __ vrintm(s5, s6);
2073 __ vstr(s5, r4, offsetof(T, mr));
2074
2075 // Test vrintz
2076 __ vldr(s6, r4, offsetof(T, input));
2077 __ vrintz(s5, s6);
2078 __ vstr(s5, r4, offsetof(T, zr));
2079
2080 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
2081
2082 CodeDesc desc;
2083 assm.GetCode(&desc);
2084 Handle<Code> code = isolate->factory()->NewCode(
2085 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2086#ifdef DEBUG
2087 OFStream os(stdout);
2088 code->Print(os);
2089#endif
2090 F3 f = FUNCTION_CAST<F3>(code->entry());
2091
2092 Object* dummy = nullptr;
2093 USE(dummy);
2094
2095#define CHECK_VRINT(input_val, ares, nres, mres, pres, zres) \
2096 t.input = input_val; \
2097 dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); \
2098 CHECK_EQ(ares, t.ar); \
2099 CHECK_EQ(nres, t.nr); \
2100 CHECK_EQ(mres, t.mr); \
2101 CHECK_EQ(pres, t.pr); \
2102 CHECK_EQ(zres, t.zr);
2103
2104 CHECK_VRINT(-0.5, -1.0, -0.0, -1.0, -0.0, -0.0)
2105 CHECK_VRINT(-0.6, -1.0, -1.0, -1.0, -0.0, -0.0)
2106 CHECK_VRINT(-1.1, -1.0, -1.0, -2.0, -1.0, -1.0)
2107 CHECK_VRINT(0.5, 1.0, 0.0, 0.0, 1.0, 0.0)
2108 CHECK_VRINT(0.6, 1.0, 1.0, 0.0, 1.0, 0.0)
2109 CHECK_VRINT(1.1, 1.0, 1.0, 1.0, 2.0, 1.0)
2110 float inf = std::numeric_limits<float>::infinity();
2111 CHECK_VRINT(inf, inf, inf, inf, inf, inf)
2112 CHECK_VRINT(-inf, -inf, -inf, -inf, -inf, -inf)
2113 CHECK_VRINT(-0.0, -0.0, -0.0, -0.0, -0.0, -0.0)
2114
2115 // Check NaN propagation.
2116 float nan = std::numeric_limits<float>::quiet_NaN();
2117 t.input = nan;
2118 dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
2119 CHECK_EQ(bit_cast<int32_t>(nan), bit_cast<int32_t>(t.ar));
2120 CHECK_EQ(bit_cast<int32_t>(nan), bit_cast<int32_t>(t.nr));
2121 CHECK_EQ(bit_cast<int32_t>(nan), bit_cast<int32_t>(t.mr));
2122 CHECK_EQ(bit_cast<int32_t>(nan), bit_cast<int32_t>(t.pr));
2123 CHECK_EQ(bit_cast<int32_t>(nan), bit_cast<int32_t>(t.zr));
2124
2125#undef CHECK_VRINT
2126 }
2127}
2128
2129
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002130TEST(ARMv8_vrintX) {
2131 // Test the vrintX floating point instructions.
2132 CcTest::InitializeVM();
2133 Isolate* isolate = CcTest::i_isolate();
2134 HandleScope scope(isolate);
2135
2136 typedef struct {
2137 double input;
2138 double ar;
2139 double nr;
2140 double mr;
2141 double pr;
2142 double zr;
2143 } T;
2144 T t;
2145
2146 // Create a function that accepts &t, and loads, manipulates, and stores
2147 // the doubles and floats.
2148 Assembler assm(isolate, NULL, 0);
2149 Label L, C;
2150
2151
2152 if (CpuFeatures::IsSupported(ARMv8)) {
2153 CpuFeatureScope scope(&assm, ARMv8);
2154
2155 __ mov(ip, Operand(sp));
2156 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
2157
2158 __ mov(r4, Operand(r0));
2159
2160 // Test vrinta
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002161 __ vldr(d6, r4, offsetof(T, input));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002162 __ vrinta(d5, d6);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002163 __ vstr(d5, r4, offsetof(T, ar));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002164
2165 // Test vrintn
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002166 __ vldr(d6, r4, offsetof(T, input));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002167 __ vrintn(d5, d6);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002168 __ vstr(d5, r4, offsetof(T, nr));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002169
2170 // Test vrintp
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002171 __ vldr(d6, r4, offsetof(T, input));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002172 __ vrintp(d5, d6);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002173 __ vstr(d5, r4, offsetof(T, pr));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002174
2175 // Test vrintm
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002176 __ vldr(d6, r4, offsetof(T, input));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002177 __ vrintm(d5, d6);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002178 __ vstr(d5, r4, offsetof(T, mr));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002179
2180 // Test vrintz
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002181 __ vldr(d6, r4, offsetof(T, input));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002182 __ vrintz(d5, d6);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002183 __ vstr(d5, r4, offsetof(T, zr));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002184
2185 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
2186
2187 CodeDesc desc;
2188 assm.GetCode(&desc);
2189 Handle<Code> code = isolate->factory()->NewCode(
2190 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2191#ifdef DEBUG
2192 OFStream os(stdout);
2193 code->Print(os);
2194#endif
2195 F3 f = FUNCTION_CAST<F3>(code->entry());
2196
2197 Object* dummy = nullptr;
2198 USE(dummy);
2199
2200#define CHECK_VRINT(input_val, ares, nres, mres, pres, zres) \
2201 t.input = input_val; \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002202 dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); \
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002203 CHECK_EQ(ares, t.ar); \
2204 CHECK_EQ(nres, t.nr); \
2205 CHECK_EQ(mres, t.mr); \
2206 CHECK_EQ(pres, t.pr); \
2207 CHECK_EQ(zres, t.zr);
2208
2209 CHECK_VRINT(-0.5, -1.0, -0.0, -1.0, -0.0, -0.0)
2210 CHECK_VRINT(-0.6, -1.0, -1.0, -1.0, -0.0, -0.0)
2211 CHECK_VRINT(-1.1, -1.0, -1.0, -2.0, -1.0, -1.0)
2212 CHECK_VRINT(0.5, 1.0, 0.0, 0.0, 1.0, 0.0)
2213 CHECK_VRINT(0.6, 1.0, 1.0, 0.0, 1.0, 0.0)
2214 CHECK_VRINT(1.1, 1.0, 1.0, 1.0, 2.0, 1.0)
2215 double inf = std::numeric_limits<double>::infinity();
2216 CHECK_VRINT(inf, inf, inf, inf, inf, inf)
2217 CHECK_VRINT(-inf, -inf, -inf, -inf, -inf, -inf)
2218 CHECK_VRINT(-0.0, -0.0, -0.0, -0.0, -0.0, -0.0)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002219
2220 // Check NaN propagation.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002221 double nan = std::numeric_limits<double>::quiet_NaN();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002222 t.input = nan;
2223 dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
2224 CHECK_EQ(bit_cast<int64_t>(nan), bit_cast<int64_t>(t.ar));
2225 CHECK_EQ(bit_cast<int64_t>(nan), bit_cast<int64_t>(t.nr));
2226 CHECK_EQ(bit_cast<int64_t>(nan), bit_cast<int64_t>(t.mr));
2227 CHECK_EQ(bit_cast<int64_t>(nan), bit_cast<int64_t>(t.pr));
2228 CHECK_EQ(bit_cast<int64_t>(nan), bit_cast<int64_t>(t.zr));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002229
2230#undef CHECK_VRINT
2231 }
2232}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002233
2234
2235TEST(regress4292_b) {
2236 CcTest::InitializeVM();
2237 Isolate* isolate = CcTest::i_isolate();
2238 HandleScope scope(isolate);
2239
2240 Assembler assm(isolate, NULL, 0);
2241 Label end;
2242 __ mov(r0, Operand(isolate->factory()->infinity_value()));
2243 for (int i = 0; i < 1020; ++i) {
2244 __ b(hi, &end);
2245 }
2246 __ bind(&end);
2247}
2248
2249
2250TEST(regress4292_bl) {
2251 CcTest::InitializeVM();
2252 Isolate* isolate = CcTest::i_isolate();
2253 HandleScope scope(isolate);
2254
2255 Assembler assm(isolate, NULL, 0);
2256 Label end;
2257 __ mov(r0, Operand(isolate->factory()->infinity_value()));
2258 for (int i = 0; i < 1020; ++i) {
2259 __ bl(hi, &end);
2260 }
2261 __ bind(&end);
2262}
2263
2264
2265TEST(regress4292_blx) {
2266 CcTest::InitializeVM();
2267 Isolate* isolate = CcTest::i_isolate();
2268 HandleScope scope(isolate);
2269
2270 Assembler assm(isolate, NULL, 0);
2271 Label end;
2272 __ mov(r0, Operand(isolate->factory()->infinity_value()));
2273 for (int i = 0; i < 1020; ++i) {
2274 __ blx(&end);
2275 }
2276 __ bind(&end);
2277}
2278
2279
2280TEST(regress4292_CheckConstPool) {
2281 CcTest::InitializeVM();
2282 Isolate* isolate = CcTest::i_isolate();
2283 HandleScope scope(isolate);
2284
2285 Assembler assm(isolate, NULL, 0);
2286 __ mov(r0, Operand(isolate->factory()->infinity_value()));
2287 __ BlockConstPoolFor(1019);
2288 for (int i = 0; i < 1019; ++i) __ nop();
2289 __ vldr(d0, MemOperand(r0, 0));
2290}
2291
Steve Blocka7e24c12009-10-30 11:49:00 +00002292#undef __