blob: cf404b0ebd3550342d4c7c30d17b6d16c9c2e89f [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 Murdochc5610432016-08-08 18:44:38 +0100415 __ usat(r1, 8, Operand(r0)); // Sat 0xFFFF to 0-255 = 0xFF.
416 __ usat(r2, 12, Operand(r0, ASR, 9)); // Sat (0xFFFF>>9) to 0-4095 = 0x7F.
417 __ usat(r3, 1, Operand(r0, LSL, 16)); // Sat (0xFFFF<<16) to 0-1 = 0x0.
418 __ add(r0, r1, Operand(r2));
419 __ add(r0, r0, Operand(r3));
420 __ mov(pc, Operand(lr));
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100421
Ben Murdochc5610432016-08-08 18:44:38 +0100422 CodeDesc desc;
423 assm.GetCode(&desc);
424 Handle<Code> code = isolate->factory()->NewCode(
425 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100426#ifdef DEBUG
Ben Murdochc5610432016-08-08 18:44:38 +0100427 OFStream os(stdout);
428 code->Print(os);
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100429#endif
Ben Murdochc5610432016-08-08 18:44:38 +0100430 F1 f = FUNCTION_CAST<F1>(code->entry());
431 int res = reinterpret_cast<int>(
432 CALL_GENERATED_CODE(isolate, f, 0xFFFF, 0, 0, 0, 0));
433 ::printf("f() = %d\n", res);
434 CHECK_EQ(382, res);
Kristian Monsen50ef84f2010-07-29 15:18:00 +0100435}
436
Russell Brenner90bac252010-11-18 13:33:46 -0800437
Steve Block1e0659c2011-05-24 12:43:12 +0100438enum VCVTTypes {
439 s32_f64,
440 u32_f64
441};
442
443static void TestRoundingMode(VCVTTypes types,
444 VFPRoundingMode mode,
445 double value,
446 int expected,
447 bool expected_exception = false) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000448 Isolate* isolate = CcTest::i_isolate();
449 HandleScope scope(isolate);
Russell Brenner90bac252010-11-18 13:33:46 -0800450
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000451 Assembler assm(isolate, NULL, 0);
Russell Brenner90bac252010-11-18 13:33:46 -0800452
Ben Murdoch8b112d22011-06-08 16:22:53 +0100453 if (CpuFeatures::IsSupported(VFP3)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000454 CpuFeatureScope scope(&assm, VFP3);
Russell Brenner90bac252010-11-18 13:33:46 -0800455
Steve Block1e0659c2011-05-24 12:43:12 +0100456 Label wrong_exception;
Russell Brenner90bac252010-11-18 13:33:46 -0800457
Steve Block1e0659c2011-05-24 12:43:12 +0100458 __ vmrs(r1);
459 // Set custom FPSCR.
460 __ bic(r2, r1, Operand(kVFPRoundingModeMask | kVFPExceptionMask));
461 __ orr(r2, r2, Operand(mode));
462 __ vmsr(r2);
Russell Brenner90bac252010-11-18 13:33:46 -0800463
Steve Block1e0659c2011-05-24 12:43:12 +0100464 // Load value, convert, and move back result to r0 if everything went well.
465 __ vmov(d1, value);
466 switch (types) {
467 case s32_f64:
468 __ vcvt_s32_f64(s0, d1, kFPSCRRounding);
469 break;
470
471 case u32_f64:
472 __ vcvt_u32_f64(s0, d1, kFPSCRRounding);
473 break;
474
475 default:
476 UNREACHABLE();
477 break;
478 }
479 // Check for vfp exceptions
480 __ vmrs(r2);
481 __ tst(r2, Operand(kVFPExceptionMask));
482 // Check that we behaved as expected.
483 __ b(&wrong_exception,
484 expected_exception ? eq : ne);
485 // There was no exception. Retrieve the result and return.
486 __ vmov(r0, s0);
487 __ mov(pc, Operand(lr));
488
489 // The exception behaviour is not what we expected.
490 // Load a special value and return.
491 __ bind(&wrong_exception);
492 __ mov(r0, Operand(11223344));
493 __ mov(pc, Operand(lr));
494
495 CodeDesc desc;
496 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000497 Handle<Code> code = isolate->factory()->NewCode(
498 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Russell Brenner90bac252010-11-18 13:33:46 -0800499#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000500 OFStream os(stdout);
501 code->Print(os);
Russell Brenner90bac252010-11-18 13:33:46 -0800502#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000503 F1 f = FUNCTION_CAST<F1>(code->entry());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000504 int res =
505 reinterpret_cast<int>(CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0));
Steve Block1e0659c2011-05-24 12:43:12 +0100506 ::printf("res = %d\n", res);
507 CHECK_EQ(expected, res);
508 }
Russell Brenner90bac252010-11-18 13:33:46 -0800509}
510
511
512TEST(7) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000513 CcTest::InitializeVM();
Russell Brenner90bac252010-11-18 13:33:46 -0800514 // Test vfp rounding modes.
515
Steve Block1e0659c2011-05-24 12:43:12 +0100516 // s32_f64 (double to integer).
Russell Brenner90bac252010-11-18 13:33:46 -0800517
Steve Block1e0659c2011-05-24 12:43:12 +0100518 TestRoundingMode(s32_f64, RN, 0, 0);
519 TestRoundingMode(s32_f64, RN, 0.5, 0);
520 TestRoundingMode(s32_f64, RN, -0.5, 0);
521 TestRoundingMode(s32_f64, RN, 1.5, 2);
522 TestRoundingMode(s32_f64, RN, -1.5, -2);
523 TestRoundingMode(s32_f64, RN, 123.7, 124);
524 TestRoundingMode(s32_f64, RN, -123.7, -124);
525 TestRoundingMode(s32_f64, RN, 123456.2, 123456);
526 TestRoundingMode(s32_f64, RN, -123456.2, -123456);
527 TestRoundingMode(s32_f64, RN, static_cast<double>(kMaxInt), kMaxInt);
528 TestRoundingMode(s32_f64, RN, (kMaxInt + 0.49), kMaxInt);
529 TestRoundingMode(s32_f64, RN, (kMaxInt + 1.0), kMaxInt, true);
530 TestRoundingMode(s32_f64, RN, (kMaxInt + 0.5), kMaxInt, true);
531 TestRoundingMode(s32_f64, RN, static_cast<double>(kMinInt), kMinInt);
532 TestRoundingMode(s32_f64, RN, (kMinInt - 0.5), kMinInt);
533 TestRoundingMode(s32_f64, RN, (kMinInt - 1.0), kMinInt, true);
534 TestRoundingMode(s32_f64, RN, (kMinInt - 0.51), kMinInt, true);
Russell Brenner90bac252010-11-18 13:33:46 -0800535
Steve Block1e0659c2011-05-24 12:43:12 +0100536 TestRoundingMode(s32_f64, RM, 0, 0);
537 TestRoundingMode(s32_f64, RM, 0.5, 0);
538 TestRoundingMode(s32_f64, RM, -0.5, -1);
539 TestRoundingMode(s32_f64, RM, 123.7, 123);
540 TestRoundingMode(s32_f64, RM, -123.7, -124);
541 TestRoundingMode(s32_f64, RM, 123456.2, 123456);
542 TestRoundingMode(s32_f64, RM, -123456.2, -123457);
543 TestRoundingMode(s32_f64, RM, static_cast<double>(kMaxInt), kMaxInt);
544 TestRoundingMode(s32_f64, RM, (kMaxInt + 0.5), kMaxInt);
545 TestRoundingMode(s32_f64, RM, (kMaxInt + 1.0), kMaxInt, true);
546 TestRoundingMode(s32_f64, RM, static_cast<double>(kMinInt), kMinInt);
547 TestRoundingMode(s32_f64, RM, (kMinInt - 0.5), kMinInt, true);
548 TestRoundingMode(s32_f64, RM, (kMinInt + 0.5), kMinInt);
Russell Brenner90bac252010-11-18 13:33:46 -0800549
Steve Block1e0659c2011-05-24 12:43:12 +0100550 TestRoundingMode(s32_f64, RZ, 0, 0);
551 TestRoundingMode(s32_f64, RZ, 0.5, 0);
552 TestRoundingMode(s32_f64, RZ, -0.5, 0);
553 TestRoundingMode(s32_f64, RZ, 123.7, 123);
554 TestRoundingMode(s32_f64, RZ, -123.7, -123);
555 TestRoundingMode(s32_f64, RZ, 123456.2, 123456);
556 TestRoundingMode(s32_f64, RZ, -123456.2, -123456);
557 TestRoundingMode(s32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt);
558 TestRoundingMode(s32_f64, RZ, (kMaxInt + 0.5), kMaxInt);
559 TestRoundingMode(s32_f64, RZ, (kMaxInt + 1.0), kMaxInt, true);
560 TestRoundingMode(s32_f64, RZ, static_cast<double>(kMinInt), kMinInt);
561 TestRoundingMode(s32_f64, RZ, (kMinInt - 0.5), kMinInt);
562 TestRoundingMode(s32_f64, RZ, (kMinInt - 1.0), kMinInt, true);
563
564
565 // u32_f64 (double to integer).
566
567 // Negative values.
568 TestRoundingMode(u32_f64, RN, -0.5, 0);
569 TestRoundingMode(u32_f64, RN, -123456.7, 0, true);
570 TestRoundingMode(u32_f64, RN, static_cast<double>(kMinInt), 0, true);
571 TestRoundingMode(u32_f64, RN, kMinInt - 1.0, 0, true);
572
573 TestRoundingMode(u32_f64, RM, -0.5, 0, true);
574 TestRoundingMode(u32_f64, RM, -123456.7, 0, true);
575 TestRoundingMode(u32_f64, RM, static_cast<double>(kMinInt), 0, true);
576 TestRoundingMode(u32_f64, RM, kMinInt - 1.0, 0, true);
577
578 TestRoundingMode(u32_f64, RZ, -0.5, 0);
579 TestRoundingMode(u32_f64, RZ, -123456.7, 0, true);
580 TestRoundingMode(u32_f64, RZ, static_cast<double>(kMinInt), 0, true);
581 TestRoundingMode(u32_f64, RZ, kMinInt - 1.0, 0, true);
582
583 // Positive values.
584 // kMaxInt is the maximum *signed* integer: 0x7fffffff.
585 static const uint32_t kMaxUInt = 0xffffffffu;
586 TestRoundingMode(u32_f64, RZ, 0, 0);
587 TestRoundingMode(u32_f64, RZ, 0.5, 0);
588 TestRoundingMode(u32_f64, RZ, 123.7, 123);
589 TestRoundingMode(u32_f64, RZ, 123456.2, 123456);
590 TestRoundingMode(u32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt);
591 TestRoundingMode(u32_f64, RZ, (kMaxInt + 0.5), kMaxInt);
592 TestRoundingMode(u32_f64, RZ, (kMaxInt + 1.0),
593 static_cast<uint32_t>(kMaxInt) + 1);
594 TestRoundingMode(u32_f64, RZ, (kMaxUInt + 0.5), kMaxUInt);
595 TestRoundingMode(u32_f64, RZ, (kMaxUInt + 1.0), kMaxUInt, true);
596
597 TestRoundingMode(u32_f64, RM, 0, 0);
598 TestRoundingMode(u32_f64, RM, 0.5, 0);
599 TestRoundingMode(u32_f64, RM, 123.7, 123);
600 TestRoundingMode(u32_f64, RM, 123456.2, 123456);
601 TestRoundingMode(u32_f64, RM, static_cast<double>(kMaxInt), kMaxInt);
602 TestRoundingMode(u32_f64, RM, (kMaxInt + 0.5), kMaxInt);
603 TestRoundingMode(u32_f64, RM, (kMaxInt + 1.0),
604 static_cast<uint32_t>(kMaxInt) + 1);
605 TestRoundingMode(u32_f64, RM, (kMaxUInt + 0.5), kMaxUInt);
606 TestRoundingMode(u32_f64, RM, (kMaxUInt + 1.0), kMaxUInt, true);
607
608 TestRoundingMode(u32_f64, RN, 0, 0);
609 TestRoundingMode(u32_f64, RN, 0.5, 0);
610 TestRoundingMode(u32_f64, RN, 1.5, 2);
611 TestRoundingMode(u32_f64, RN, 123.7, 124);
612 TestRoundingMode(u32_f64, RN, 123456.2, 123456);
613 TestRoundingMode(u32_f64, RN, static_cast<double>(kMaxInt), kMaxInt);
614 TestRoundingMode(u32_f64, RN, (kMaxInt + 0.49), kMaxInt);
615 TestRoundingMode(u32_f64, RN, (kMaxInt + 0.5),
616 static_cast<uint32_t>(kMaxInt) + 1);
617 TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.49), kMaxUInt);
618 TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.5), kMaxUInt, true);
619 TestRoundingMode(u32_f64, RN, (kMaxUInt + 1.0), kMaxUInt, true);
Russell Brenner90bac252010-11-18 13:33:46 -0800620}
621
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000622
Ben Murdoch8b112d22011-06-08 16:22:53 +0100623TEST(8) {
624 // Test VFP multi load/store with ia_w.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000625 CcTest::InitializeVM();
626 Isolate* isolate = CcTest::i_isolate();
627 HandleScope scope(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100628
629 typedef struct {
630 double a;
631 double b;
632 double c;
633 double d;
634 double e;
635 double f;
636 double g;
637 double h;
638 } D;
639 D d;
640
641 typedef struct {
642 float a;
643 float b;
644 float c;
645 float d;
646 float e;
647 float f;
648 float g;
649 float h;
650 } F;
651 F f;
652
653 // Create a function that uses vldm/vstm to move some double and
654 // single precision values around in memory.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000655 Assembler assm(isolate, NULL, 0);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100656
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000657 __ mov(ip, Operand(sp));
658 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
659 __ sub(fp, ip, Operand(4));
Ben Murdoch8b112d22011-06-08 16:22:53 +0100660
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000661 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, a))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000662 __ vldm(ia_w, r4, d0, d3);
663 __ vldm(ia_w, r4, d4, d7);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100664
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000665 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, a))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000666 __ vstm(ia_w, r4, d6, d7);
667 __ vstm(ia_w, r4, d0, d5);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100668
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000669 __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, a))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000670 __ vldm(ia_w, r4, s0, s3);
671 __ vldm(ia_w, r4, s4, s7);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100672
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000673 __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, a))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000674 __ vstm(ia_w, r4, s6, s7);
675 __ vstm(ia_w, r4, s0, s5);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100676
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000677 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
Ben Murdoch8b112d22011-06-08 16:22:53 +0100678
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000679 CodeDesc desc;
680 assm.GetCode(&desc);
681 Handle<Code> code = isolate->factory()->NewCode(
682 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Ben Murdoch8b112d22011-06-08 16:22:53 +0100683#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000684 OFStream os(stdout);
685 code->Print(os);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100686#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000687 F4 fn = FUNCTION_CAST<F4>(code->entry());
688 d.a = 1.1;
689 d.b = 2.2;
690 d.c = 3.3;
691 d.d = 4.4;
692 d.e = 5.5;
693 d.f = 6.6;
694 d.g = 7.7;
695 d.h = 8.8;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100696
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000697 f.a = 1.0;
698 f.b = 2.0;
699 f.c = 3.0;
700 f.d = 4.0;
701 f.e = 5.0;
702 f.f = 6.0;
703 f.g = 7.0;
704 f.h = 8.0;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100705
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000706 Object* dummy = CALL_GENERATED_CODE(isolate, fn, &d, &f, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000707 USE(dummy);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100708
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000709 CHECK_EQ(7.7, d.a);
710 CHECK_EQ(8.8, d.b);
711 CHECK_EQ(1.1, d.c);
712 CHECK_EQ(2.2, d.d);
713 CHECK_EQ(3.3, d.e);
714 CHECK_EQ(4.4, d.f);
715 CHECK_EQ(5.5, d.g);
716 CHECK_EQ(6.6, d.h);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100717
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000718 CHECK_EQ(7.0f, f.a);
719 CHECK_EQ(8.0f, f.b);
720 CHECK_EQ(1.0f, f.c);
721 CHECK_EQ(2.0f, f.d);
722 CHECK_EQ(3.0f, f.e);
723 CHECK_EQ(4.0f, f.f);
724 CHECK_EQ(5.0f, f.g);
725 CHECK_EQ(6.0f, f.h);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100726}
727
728
729TEST(9) {
730 // Test VFP multi load/store with ia.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000731 CcTest::InitializeVM();
732 Isolate* isolate = CcTest::i_isolate();
733 HandleScope scope(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100734
735 typedef struct {
736 double a;
737 double b;
738 double c;
739 double d;
740 double e;
741 double f;
742 double g;
743 double h;
744 } D;
745 D d;
746
747 typedef struct {
748 float a;
749 float b;
750 float c;
751 float d;
752 float e;
753 float f;
754 float g;
755 float h;
756 } F;
757 F f;
758
759 // Create a function that uses vldm/vstm to move some double and
760 // single precision values around in memory.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000761 Assembler assm(isolate, NULL, 0);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100762
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000763 __ mov(ip, Operand(sp));
764 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
765 __ sub(fp, ip, Operand(4));
Ben Murdoch8b112d22011-06-08 16:22:53 +0100766
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000767 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, a))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000768 __ vldm(ia, r4, d0, d3);
769 __ add(r4, r4, Operand(4 * 8));
770 __ vldm(ia, r4, d4, d7);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100771
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000772 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, a))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000773 __ vstm(ia, r4, d6, d7);
774 __ add(r4, r4, Operand(2 * 8));
775 __ vstm(ia, r4, d0, d5);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100776
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000777 __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, a))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000778 __ vldm(ia, r4, s0, s3);
779 __ add(r4, r4, Operand(4 * 4));
780 __ vldm(ia, r4, s4, s7);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100781
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000782 __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, a))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000783 __ vstm(ia, r4, s6, s7);
784 __ add(r4, r4, Operand(2 * 4));
785 __ vstm(ia, r4, s0, s5);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100786
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000787 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
Ben Murdoch8b112d22011-06-08 16:22:53 +0100788
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000789 CodeDesc desc;
790 assm.GetCode(&desc);
791 Handle<Code> code = isolate->factory()->NewCode(
792 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Ben Murdoch8b112d22011-06-08 16:22:53 +0100793#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000794 OFStream os(stdout);
795 code->Print(os);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100796#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000797 F4 fn = FUNCTION_CAST<F4>(code->entry());
798 d.a = 1.1;
799 d.b = 2.2;
800 d.c = 3.3;
801 d.d = 4.4;
802 d.e = 5.5;
803 d.f = 6.6;
804 d.g = 7.7;
805 d.h = 8.8;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100806
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000807 f.a = 1.0;
808 f.b = 2.0;
809 f.c = 3.0;
810 f.d = 4.0;
811 f.e = 5.0;
812 f.f = 6.0;
813 f.g = 7.0;
814 f.h = 8.0;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100815
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000816 Object* dummy = CALL_GENERATED_CODE(isolate, fn, &d, &f, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000817 USE(dummy);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100818
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000819 CHECK_EQ(7.7, d.a);
820 CHECK_EQ(8.8, d.b);
821 CHECK_EQ(1.1, d.c);
822 CHECK_EQ(2.2, d.d);
823 CHECK_EQ(3.3, d.e);
824 CHECK_EQ(4.4, d.f);
825 CHECK_EQ(5.5, d.g);
826 CHECK_EQ(6.6, d.h);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100827
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000828 CHECK_EQ(7.0f, f.a);
829 CHECK_EQ(8.0f, f.b);
830 CHECK_EQ(1.0f, f.c);
831 CHECK_EQ(2.0f, f.d);
832 CHECK_EQ(3.0f, f.e);
833 CHECK_EQ(4.0f, f.f);
834 CHECK_EQ(5.0f, f.g);
835 CHECK_EQ(6.0f, f.h);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100836}
837
838
839TEST(10) {
840 // Test VFP multi load/store with db_w.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000841 CcTest::InitializeVM();
842 Isolate* isolate = CcTest::i_isolate();
843 HandleScope scope(isolate);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100844
845 typedef struct {
846 double a;
847 double b;
848 double c;
849 double d;
850 double e;
851 double f;
852 double g;
853 double h;
854 } D;
855 D d;
856
857 typedef struct {
858 float a;
859 float b;
860 float c;
861 float d;
862 float e;
863 float f;
864 float g;
865 float h;
866 } F;
867 F f;
868
869 // Create a function that uses vldm/vstm to move some double and
870 // single precision values around in memory.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000871 Assembler assm(isolate, NULL, 0);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100872
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000873 __ mov(ip, Operand(sp));
874 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
875 __ sub(fp, ip, Operand(4));
Ben Murdoch8b112d22011-06-08 16:22:53 +0100876
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000877 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, h)) + 8));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000878 __ vldm(db_w, r4, d4, d7);
879 __ vldm(db_w, r4, d0, d3);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100880
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000881 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, h)) + 8));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000882 __ vstm(db_w, r4, d0, d5);
883 __ vstm(db_w, r4, d6, d7);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100884
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000885 __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, h)) + 4));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000886 __ vldm(db_w, r4, s4, s7);
887 __ vldm(db_w, r4, s0, s3);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100888
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000889 __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, h)) + 4));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000890 __ vstm(db_w, r4, s0, s5);
891 __ vstm(db_w, r4, s6, s7);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100892
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000893 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
Ben Murdoch8b112d22011-06-08 16:22:53 +0100894
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000895 CodeDesc desc;
896 assm.GetCode(&desc);
897 Handle<Code> code = isolate->factory()->NewCode(
898 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Ben Murdoch8b112d22011-06-08 16:22:53 +0100899#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000900 OFStream os(stdout);
901 code->Print(os);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100902#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000903 F4 fn = FUNCTION_CAST<F4>(code->entry());
904 d.a = 1.1;
905 d.b = 2.2;
906 d.c = 3.3;
907 d.d = 4.4;
908 d.e = 5.5;
909 d.f = 6.6;
910 d.g = 7.7;
911 d.h = 8.8;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100912
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000913 f.a = 1.0;
914 f.b = 2.0;
915 f.c = 3.0;
916 f.d = 4.0;
917 f.e = 5.0;
918 f.f = 6.0;
919 f.g = 7.0;
920 f.h = 8.0;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100921
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000922 Object* dummy = CALL_GENERATED_CODE(isolate, fn, &d, &f, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000923 USE(dummy);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100924
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000925 CHECK_EQ(7.7, d.a);
926 CHECK_EQ(8.8, d.b);
927 CHECK_EQ(1.1, d.c);
928 CHECK_EQ(2.2, d.d);
929 CHECK_EQ(3.3, d.e);
930 CHECK_EQ(4.4, d.f);
931 CHECK_EQ(5.5, d.g);
932 CHECK_EQ(6.6, d.h);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100933
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000934 CHECK_EQ(7.0f, f.a);
935 CHECK_EQ(8.0f, f.b);
936 CHECK_EQ(1.0f, f.c);
937 CHECK_EQ(2.0f, f.d);
938 CHECK_EQ(3.0f, f.e);
939 CHECK_EQ(4.0f, f.f);
940 CHECK_EQ(5.0f, f.g);
941 CHECK_EQ(6.0f, f.h);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100942}
943
Ben Murdoch257744e2011-11-30 15:57:28 +0000944
945TEST(11) {
946 // Test instructions using the carry flag.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000947 CcTest::InitializeVM();
948 Isolate* isolate = CcTest::i_isolate();
949 HandleScope scope(isolate);
Ben Murdoch257744e2011-11-30 15:57:28 +0000950
951 typedef struct {
952 int32_t a;
953 int32_t b;
954 int32_t c;
955 int32_t d;
956 } I;
957 I i;
958
959 i.a = 0xabcd0001;
960 i.b = 0xabcd0000;
961
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000962 Assembler assm(isolate, NULL, 0);
Ben Murdoch257744e2011-11-30 15:57:28 +0000963
964 // Test HeapObject untagging.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000965 __ ldr(r1, MemOperand(r0, offsetof(I, a)));
Ben Murdoch257744e2011-11-30 15:57:28 +0000966 __ mov(r1, Operand(r1, ASR, 1), SetCC);
967 __ adc(r1, r1, Operand(r1), LeaveCC, cs);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000968 __ str(r1, MemOperand(r0, offsetof(I, a)));
Ben Murdoch257744e2011-11-30 15:57:28 +0000969
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000970 __ ldr(r2, MemOperand(r0, offsetof(I, b)));
Ben Murdoch257744e2011-11-30 15:57:28 +0000971 __ mov(r2, Operand(r2, ASR, 1), SetCC);
972 __ adc(r2, r2, Operand(r2), LeaveCC, cs);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000973 __ str(r2, MemOperand(r0, offsetof(I, b)));
Ben Murdoch257744e2011-11-30 15:57:28 +0000974
975 // Test corner cases.
976 __ mov(r1, Operand(0xffffffff));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000977 __ mov(r2, Operand::Zero());
Ben Murdoch257744e2011-11-30 15:57:28 +0000978 __ mov(r3, Operand(r1, ASR, 1), SetCC); // Set the carry.
979 __ adc(r3, r1, Operand(r2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000980 __ str(r3, MemOperand(r0, offsetof(I, c)));
Ben Murdoch257744e2011-11-30 15:57:28 +0000981
982 __ mov(r1, Operand(0xffffffff));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000983 __ mov(r2, Operand::Zero());
Ben Murdoch257744e2011-11-30 15:57:28 +0000984 __ mov(r3, Operand(r2, ASR, 1), SetCC); // Unset the carry.
985 __ adc(r3, r1, Operand(r2));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000986 __ str(r3, MemOperand(r0, offsetof(I, d)));
Ben Murdoch257744e2011-11-30 15:57:28 +0000987
988 __ mov(pc, Operand(lr));
989
990 CodeDesc desc;
991 assm.GetCode(&desc);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000992 Handle<Code> code = isolate->factory()->NewCode(
993 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
Ben Murdoch257744e2011-11-30 15:57:28 +0000994#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000995 OFStream os(stdout);
996 code->Print(os);
Ben Murdoch257744e2011-11-30 15:57:28 +0000997#endif
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000998 F3 f = FUNCTION_CAST<F3>(code->entry());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000999 Object* dummy = CALL_GENERATED_CODE(isolate, f, &i, 0, 0, 0, 0);
Ben Murdoch257744e2011-11-30 15:57:28 +00001000 USE(dummy);
1001
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001002 CHECK_EQ(static_cast<int32_t>(0xabcd0001), i.a);
Ben Murdoch257744e2011-11-30 15:57:28 +00001003 CHECK_EQ(static_cast<int32_t>(0xabcd0000) >> 1, i.b);
1004 CHECK_EQ(0x00000000, i.c);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001005 CHECK_EQ(static_cast<int32_t>(0xffffffff), i.d);
Ben Murdoch257744e2011-11-30 15:57:28 +00001006}
1007
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001008
1009TEST(12) {
1010 // Test chaining of label usages within instructions (issue 1644).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001011 CcTest::InitializeVM();
1012 Isolate* isolate = CcTest::i_isolate();
1013 HandleScope scope(isolate);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001014
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001015 Assembler assm(isolate, NULL, 0);
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001016 Label target;
1017 __ b(eq, &target);
1018 __ b(ne, &target);
1019 __ bind(&target);
1020 __ nop();
1021}
1022
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001023
1024TEST(13) {
1025 // Test VFP instructions using registers d16-d31.
1026 CcTest::InitializeVM();
1027 Isolate* isolate = CcTest::i_isolate();
1028 HandleScope scope(isolate);
1029
1030 if (!CpuFeatures::IsSupported(VFP32DREGS)) {
1031 return;
1032 }
1033
1034 typedef struct {
1035 double a;
1036 double b;
1037 double c;
1038 double x;
1039 double y;
1040 double z;
1041 double i;
1042 double j;
1043 double k;
1044 uint32_t low;
1045 uint32_t high;
1046 } T;
1047 T t;
1048
1049 // Create a function that accepts &t, and loads, manipulates, and stores
1050 // the doubles and floats.
1051 Assembler assm(isolate, NULL, 0);
1052 Label L, C;
1053
1054
1055 if (CpuFeatures::IsSupported(VFP3)) {
1056 CpuFeatureScope scope(&assm, VFP3);
1057
1058 __ stm(db_w, sp, r4.bit() | lr.bit());
1059
1060 // Load a, b, c into d16, d17, d18.
1061 __ mov(r4, Operand(r0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001062 __ vldr(d16, r4, offsetof(T, a));
1063 __ vldr(d17, r4, offsetof(T, b));
1064 __ vldr(d18, r4, offsetof(T, c));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001065
1066 __ vneg(d25, d16);
1067 __ vadd(d25, d25, d17);
1068 __ vsub(d25, d25, d18);
1069 __ vmul(d25, d25, d25);
1070 __ vdiv(d25, d25, d18);
1071
1072 __ vmov(d16, d25);
1073 __ vsqrt(d17, d25);
1074 __ vneg(d17, d17);
1075 __ vabs(d17, d17);
1076 __ vmla(d18, d16, d17);
1077
1078 // Store d16, d17, d18 into a, b, c.
1079 __ mov(r4, Operand(r0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001080 __ vstr(d16, r4, offsetof(T, a));
1081 __ vstr(d17, r4, offsetof(T, b));
1082 __ vstr(d18, r4, offsetof(T, c));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001083
1084 // Load x, y, z into d29-d31.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001085 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, x))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001086 __ vldm(ia_w, r4, d29, d31);
1087
1088 // Swap d29 and d30 via r registers.
1089 __ vmov(r1, r2, d29);
1090 __ vmov(d29, d30);
1091 __ vmov(d30, r1, r2);
1092
1093 // Convert to and from integer.
1094 __ vcvt_s32_f64(s1, d31);
1095 __ vcvt_f64_u32(d31, s1);
1096
1097 // Store d29-d31 into x, y, z.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001098 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, x))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001099 __ vstm(ia_w, r4, d29, d31);
1100
1101 // Move constants into d20, d21, d22 and store into i, j, k.
1102 __ vmov(d20, 14.7610017472335499);
1103 __ vmov(d21, 16.0);
1104 __ mov(r1, Operand(372106121));
1105 __ mov(r2, Operand(1079146608));
1106 __ vmov(d22, VmovIndexLo, r1);
1107 __ vmov(d22, VmovIndexHi, r2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001108 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, i))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001109 __ vstm(ia_w, r4, d20, d22);
1110 // Move d22 into low and high.
1111 __ vmov(r4, VmovIndexLo, d22);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001112 __ str(r4, MemOperand(r0, offsetof(T, low)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001113 __ vmov(r4, VmovIndexHi, d22);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001114 __ str(r4, MemOperand(r0, offsetof(T, high)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001115
1116 __ ldm(ia_w, sp, r4.bit() | pc.bit());
1117
1118 CodeDesc desc;
1119 assm.GetCode(&desc);
1120 Handle<Code> code = isolate->factory()->NewCode(
1121 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1122#ifdef DEBUG
1123 OFStream os(stdout);
1124 code->Print(os);
1125#endif
1126 F3 f = FUNCTION_CAST<F3>(code->entry());
1127 t.a = 1.5;
1128 t.b = 2.75;
1129 t.c = 17.17;
1130 t.x = 1.5;
1131 t.y = 2.75;
1132 t.z = 17.17;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001133 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001134 USE(dummy);
1135 CHECK_EQ(14.7610017472335499, t.a);
1136 CHECK_EQ(3.84200491244266251, t.b);
1137 CHECK_EQ(73.8818412254460241, t.c);
1138 CHECK_EQ(2.75, t.x);
1139 CHECK_EQ(1.5, t.y);
1140 CHECK_EQ(17.0, t.z);
1141 CHECK_EQ(14.7610017472335499, t.i);
1142 CHECK_EQ(16.0, t.j);
1143 CHECK_EQ(73.8818412254460241, t.k);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001144 CHECK_EQ(372106121u, t.low);
1145 CHECK_EQ(1079146608u, t.high);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001146 }
1147}
1148
1149
1150TEST(14) {
1151 // Test the VFP Canonicalized Nan mode.
1152 CcTest::InitializeVM();
1153 Isolate* isolate = CcTest::i_isolate();
1154 HandleScope scope(isolate);
1155
1156 typedef struct {
1157 double left;
1158 double right;
1159 double add_result;
1160 double sub_result;
1161 double mul_result;
1162 double div_result;
1163 } T;
1164 T t;
1165
1166 // Create a function that makes the four basic operations.
1167 Assembler assm(isolate, NULL, 0);
1168
1169 // Ensure FPSCR state (as JSEntryStub does).
1170 Label fpscr_done;
1171 __ vmrs(r1);
1172 __ tst(r1, Operand(kVFPDefaultNaNModeControlBit));
1173 __ b(ne, &fpscr_done);
1174 __ orr(r1, r1, Operand(kVFPDefaultNaNModeControlBit));
1175 __ vmsr(r1);
1176 __ bind(&fpscr_done);
1177
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001178 __ vldr(d0, r0, offsetof(T, left));
1179 __ vldr(d1, r0, offsetof(T, right));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001180 __ vadd(d2, d0, d1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001181 __ vstr(d2, r0, offsetof(T, add_result));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001182 __ vsub(d2, d0, d1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001183 __ vstr(d2, r0, offsetof(T, sub_result));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001184 __ vmul(d2, d0, d1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001185 __ vstr(d2, r0, offsetof(T, mul_result));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001186 __ vdiv(d2, d0, d1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001187 __ vstr(d2, r0, offsetof(T, div_result));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001188
1189 __ mov(pc, Operand(lr));
1190
1191 CodeDesc desc;
1192 assm.GetCode(&desc);
1193 Handle<Code> code = isolate->factory()->NewCode(
1194 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1195#ifdef DEBUG
1196 OFStream os(stdout);
1197 code->Print(os);
1198#endif
1199 F3 f = FUNCTION_CAST<F3>(code->entry());
1200 t.left = bit_cast<double>(kHoleNanInt64);
1201 t.right = 1;
1202 t.add_result = 0;
1203 t.sub_result = 0;
1204 t.mul_result = 0;
1205 t.div_result = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001206 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001207 USE(dummy);
1208 const uint32_t kArmNanUpper32 = 0x7ff80000;
1209 const uint32_t kArmNanLower32 = 0x00000000;
1210#ifdef DEBUG
1211 const uint64_t kArmNanInt64 =
1212 (static_cast<uint64_t>(kArmNanUpper32) << 32) | kArmNanLower32;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001213 CHECK(kArmNanInt64 != kHoleNanInt64);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001214#endif
1215 // With VFP2 the sign of the canonicalized Nan is undefined. So
1216 // we remove the sign bit for the upper tests.
1217 CHECK_EQ(kArmNanUpper32,
1218 (bit_cast<int64_t>(t.add_result) >> 32) & 0x7fffffff);
1219 CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.add_result) & 0xffffffffu);
1220 CHECK_EQ(kArmNanUpper32,
1221 (bit_cast<int64_t>(t.sub_result) >> 32) & 0x7fffffff);
1222 CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.sub_result) & 0xffffffffu);
1223 CHECK_EQ(kArmNanUpper32,
1224 (bit_cast<int64_t>(t.mul_result) >> 32) & 0x7fffffff);
1225 CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.mul_result) & 0xffffffffu);
1226 CHECK_EQ(kArmNanUpper32,
1227 (bit_cast<int64_t>(t.div_result) >> 32) & 0x7fffffff);
1228 CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.div_result) & 0xffffffffu);
1229}
1230
1231
1232TEST(15) {
1233 // Test the Neon instructions.
1234 CcTest::InitializeVM();
1235 Isolate* isolate = CcTest::i_isolate();
1236 HandleScope scope(isolate);
1237
1238 typedef struct {
1239 uint32_t src0;
1240 uint32_t src1;
1241 uint32_t src2;
1242 uint32_t src3;
1243 uint32_t src4;
1244 uint32_t src5;
1245 uint32_t src6;
1246 uint32_t src7;
1247 uint32_t dst0;
1248 uint32_t dst1;
1249 uint32_t dst2;
1250 uint32_t dst3;
1251 uint32_t dst4;
1252 uint32_t dst5;
1253 uint32_t dst6;
1254 uint32_t dst7;
1255 uint32_t srcA0;
1256 uint32_t srcA1;
1257 uint32_t dstA0;
1258 uint32_t dstA1;
1259 uint32_t dstA2;
1260 uint32_t dstA3;
1261 uint32_t dstA4;
1262 uint32_t dstA5;
1263 uint32_t dstA6;
1264 uint32_t dstA7;
1265 } T;
1266 T t;
1267
1268 // Create a function that accepts &t, and loads, manipulates, and stores
1269 // the doubles and floats.
1270 Assembler assm(isolate, NULL, 0);
1271
1272
1273 if (CpuFeatures::IsSupported(NEON)) {
1274 CpuFeatureScope scope(&assm, NEON);
1275
1276 __ stm(db_w, sp, r4.bit() | lr.bit());
1277 // Move 32 bytes with neon.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001278 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, src0))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001279 __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001280 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, dst0))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001281 __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4));
1282
1283 // Expand 8 bytes into 8 words(16 bits).
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001284 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, srcA0))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001285 __ vld1(Neon8, NeonListOperand(d0), NeonMemOperand(r4));
1286 __ vmovl(NeonU8, q0, d0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001287 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, dstA0))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001288 __ vst1(Neon8, NeonListOperand(d0, 2), NeonMemOperand(r4));
1289
1290 // The same expansion, but with different source and destination registers.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001291 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, srcA0))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001292 __ vld1(Neon8, NeonListOperand(d1), NeonMemOperand(r4));
1293 __ vmovl(NeonU8, q1, d1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001294 __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, dstA4))));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001295 __ vst1(Neon8, NeonListOperand(d2, 2), NeonMemOperand(r4));
1296
1297 __ ldm(ia_w, sp, r4.bit() | pc.bit());
1298
1299 CodeDesc desc;
1300 assm.GetCode(&desc);
1301 Handle<Code> code = isolate->factory()->NewCode(
1302 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1303#ifdef DEBUG
1304 OFStream os(stdout);
1305 code->Print(os);
1306#endif
1307 F3 f = FUNCTION_CAST<F3>(code->entry());
1308 t.src0 = 0x01020304;
1309 t.src1 = 0x11121314;
1310 t.src2 = 0x21222324;
1311 t.src3 = 0x31323334;
1312 t.src4 = 0x41424344;
1313 t.src5 = 0x51525354;
1314 t.src6 = 0x61626364;
1315 t.src7 = 0x71727374;
1316 t.dst0 = 0;
1317 t.dst1 = 0;
1318 t.dst2 = 0;
1319 t.dst3 = 0;
1320 t.dst4 = 0;
1321 t.dst5 = 0;
1322 t.dst6 = 0;
1323 t.dst7 = 0;
1324 t.srcA0 = 0x41424344;
1325 t.srcA1 = 0x81828384;
1326 t.dstA0 = 0;
1327 t.dstA1 = 0;
1328 t.dstA2 = 0;
1329 t.dstA3 = 0;
1330 t.dstA4 = 0;
1331 t.dstA5 = 0;
1332 t.dstA6 = 0;
1333 t.dstA7 = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001334 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001335 USE(dummy);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001336 CHECK_EQ(0x01020304u, t.dst0);
1337 CHECK_EQ(0x11121314u, t.dst1);
1338 CHECK_EQ(0x21222324u, t.dst2);
1339 CHECK_EQ(0x31323334u, t.dst3);
1340 CHECK_EQ(0x41424344u, t.dst4);
1341 CHECK_EQ(0x51525354u, t.dst5);
1342 CHECK_EQ(0x61626364u, t.dst6);
1343 CHECK_EQ(0x71727374u, t.dst7);
1344 CHECK_EQ(0x00430044u, t.dstA0);
1345 CHECK_EQ(0x00410042u, t.dstA1);
1346 CHECK_EQ(0x00830084u, t.dstA2);
1347 CHECK_EQ(0x00810082u, t.dstA3);
1348 CHECK_EQ(0x00430044u, t.dstA4);
1349 CHECK_EQ(0x00410042u, t.dstA5);
1350 CHECK_EQ(0x00830084u, t.dstA6);
1351 CHECK_EQ(0x00810082u, t.dstA7);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001352 }
1353}
1354
1355
1356TEST(16) {
1357 // Test the pkh, uxtb, uxtab and uxtb16 instructions.
1358 CcTest::InitializeVM();
1359 Isolate* isolate = CcTest::i_isolate();
1360 HandleScope scope(isolate);
1361
1362 typedef struct {
1363 uint32_t src0;
1364 uint32_t src1;
1365 uint32_t src2;
1366 uint32_t dst0;
1367 uint32_t dst1;
1368 uint32_t dst2;
1369 uint32_t dst3;
1370 uint32_t dst4;
1371 } T;
1372 T t;
1373
1374 // Create a function that accepts &t, and loads, manipulates, and stores
1375 // the doubles and floats.
1376 Assembler assm(isolate, NULL, 0);
1377
1378 __ stm(db_w, sp, r4.bit() | lr.bit());
1379
1380 __ mov(r4, Operand(r0));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001381 __ ldr(r0, MemOperand(r4, offsetof(T, src0)));
1382 __ ldr(r1, MemOperand(r4, offsetof(T, src1)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001383
1384 __ pkhbt(r2, r0, Operand(r1, LSL, 8));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001385 __ str(r2, MemOperand(r4, offsetof(T, dst0)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001386
1387 __ pkhtb(r2, r0, Operand(r1, ASR, 8));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001388 __ str(r2, MemOperand(r4, offsetof(T, dst1)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001389
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001390 __ uxtb16(r2, r0, 8);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001391 __ str(r2, MemOperand(r4, offsetof(T, dst2)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001392
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001393 __ uxtb(r2, r0, 8);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001394 __ str(r2, MemOperand(r4, offsetof(T, dst3)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001395
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001396 __ ldr(r0, MemOperand(r4, offsetof(T, src2)));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001397 __ uxtab(r2, r0, r1, 8);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001398 __ str(r2, MemOperand(r4, offsetof(T, dst4)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001399
1400 __ ldm(ia_w, sp, r4.bit() | pc.bit());
1401
1402 CodeDesc desc;
1403 assm.GetCode(&desc);
1404 Handle<Code> code = isolate->factory()->NewCode(
1405 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1406#ifdef DEBUG
1407 OFStream os(stdout);
1408 code->Print(os);
1409#endif
1410 F3 f = FUNCTION_CAST<F3>(code->entry());
1411 t.src0 = 0x01020304;
1412 t.src1 = 0x11121314;
1413 t.src2 = 0x11121300;
1414 t.dst0 = 0;
1415 t.dst1 = 0;
1416 t.dst2 = 0;
1417 t.dst3 = 0;
1418 t.dst4 = 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001419 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001420 USE(dummy);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001421 CHECK_EQ(0x12130304u, t.dst0);
1422 CHECK_EQ(0x01021213u, t.dst1);
1423 CHECK_EQ(0x00010003u, t.dst2);
1424 CHECK_EQ(0x00000003u, t.dst3);
1425 CHECK_EQ(0x11121313u, t.dst4);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001426}
1427
1428
1429TEST(17) {
1430 // Test generating labels at high addresses.
1431 // Should not assert.
1432 CcTest::InitializeVM();
1433 Isolate* isolate = CcTest::i_isolate();
1434 HandleScope scope(isolate);
1435
1436 // Generate a code segment that will be longer than 2^24 bytes.
1437 Assembler assm(isolate, NULL, 0);
1438 for (size_t i = 0; i < 1 << 23 ; ++i) { // 2^23
1439 __ nop();
1440 }
1441
1442 Label target;
1443 __ b(eq, &target);
1444 __ bind(&target);
1445 __ nop();
1446}
1447
1448
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001449#define TEST_SDIV(expected_, dividend_, divisor_) \
1450 t.dividend = dividend_; \
1451 t.divisor = divisor_; \
1452 t.result = 0; \
1453 dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); \
1454 CHECK_EQ(expected_, t.result);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001455
1456
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001457TEST(sdiv) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001458 // Test the sdiv.
1459 CcTest::InitializeVM();
1460 Isolate* isolate = CcTest::i_isolate();
1461 HandleScope scope(isolate);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001462 Assembler assm(isolate, NULL, 0);
1463
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001464 struct T {
1465 int32_t dividend;
1466 int32_t divisor;
1467 int32_t result;
1468 } t;
1469
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001470 if (CpuFeatures::IsSupported(SUDIV)) {
1471 CpuFeatureScope scope(&assm, SUDIV);
1472
1473 __ mov(r3, Operand(r0));
1474
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001475 __ ldr(r0, MemOperand(r3, offsetof(T, dividend)));
1476 __ ldr(r1, MemOperand(r3, offsetof(T, divisor)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001477
1478 __ sdiv(r2, r0, r1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001479 __ str(r2, MemOperand(r3, offsetof(T, result)));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001480
1481 __ bx(lr);
1482
1483 CodeDesc desc;
1484 assm.GetCode(&desc);
1485 Handle<Code> code = isolate->factory()->NewCode(
1486 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1487#ifdef DEBUG
1488 OFStream os(stdout);
1489 code->Print(os);
1490#endif
1491 F3 f = FUNCTION_CAST<F3>(code->entry());
1492 Object* dummy;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001493 TEST_SDIV(0, kMinInt, 0);
1494 TEST_SDIV(0, 1024, 0);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001495 TEST_SDIV(1073741824, kMinInt, -2);
1496 TEST_SDIV(kMinInt, kMinInt, -1);
1497 TEST_SDIV(5, 10, 2);
1498 TEST_SDIV(3, 10, 3);
1499 TEST_SDIV(-5, 10, -2);
1500 TEST_SDIV(-3, 10, -3);
1501 TEST_SDIV(-5, -10, 2);
1502 TEST_SDIV(-3, -10, 3);
1503 TEST_SDIV(5, -10, -2);
1504 TEST_SDIV(3, -10, -3);
1505 USE(dummy);
1506 }
1507}
1508
1509
1510#undef TEST_SDIV
1511
1512
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001513#define TEST_UDIV(expected_, dividend_, divisor_) \
1514 t.dividend = dividend_; \
1515 t.divisor = divisor_; \
1516 t.result = 0; \
1517 dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); \
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001518 CHECK_EQ(expected_, t.result);
1519
1520
1521TEST(udiv) {
1522 // Test the udiv.
1523 CcTest::InitializeVM();
1524 Isolate* isolate = CcTest::i_isolate();
1525 HandleScope scope(isolate);
1526 Assembler assm(isolate, NULL, 0);
1527
1528 struct T {
1529 uint32_t dividend;
1530 uint32_t divisor;
1531 uint32_t result;
1532 } t;
1533
1534 if (CpuFeatures::IsSupported(SUDIV)) {
1535 CpuFeatureScope scope(&assm, SUDIV);
1536
1537 __ mov(r3, Operand(r0));
1538
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001539 __ ldr(r0, MemOperand(r3, offsetof(T, dividend)));
1540 __ ldr(r1, MemOperand(r3, offsetof(T, divisor)));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001541
1542 __ sdiv(r2, r0, r1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001543 __ str(r2, MemOperand(r3, offsetof(T, result)));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001544
1545 __ bx(lr);
1546
1547 CodeDesc desc;
1548 assm.GetCode(&desc);
1549 Handle<Code> code = isolate->factory()->NewCode(
1550 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1551#ifdef DEBUG
1552 OFStream os(stdout);
1553 code->Print(os);
1554#endif
1555 F3 f = FUNCTION_CAST<F3>(code->entry());
1556 Object* dummy;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001557 TEST_UDIV(0u, 0, 0);
1558 TEST_UDIV(0u, 1024, 0);
1559 TEST_UDIV(5u, 10, 2);
1560 TEST_UDIV(3u, 10, 3);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001561 USE(dummy);
1562 }
1563}
1564
1565
1566#undef TEST_UDIV
1567
1568
1569TEST(smmla) {
1570 CcTest::InitializeVM();
1571 Isolate* const isolate = CcTest::i_isolate();
1572 HandleScope scope(isolate);
1573 RandomNumberGenerator* const rng = isolate->random_number_generator();
1574 Assembler assm(isolate, nullptr, 0);
1575 __ smmla(r1, r1, r2, r3);
1576 __ str(r1, MemOperand(r0));
1577 __ bx(lr);
1578 CodeDesc desc;
1579 assm.GetCode(&desc);
1580 Handle<Code> code = isolate->factory()->NewCode(
1581 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1582#ifdef OBJECT_PRINT
1583 code->Print(std::cout);
1584#endif
1585 F3 f = FUNCTION_CAST<F3>(code->entry());
1586 for (size_t i = 0; i < 128; ++i) {
1587 int32_t r, x = rng->NextInt(), y = rng->NextInt(), z = rng->NextInt();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001588 Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, y, z, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001589 CHECK_EQ(bits::SignedMulHighAndAdd32(x, y, z), r);
1590 USE(dummy);
1591 }
1592}
1593
1594
1595TEST(smmul) {
1596 CcTest::InitializeVM();
1597 Isolate* const isolate = CcTest::i_isolate();
1598 HandleScope scope(isolate);
1599 RandomNumberGenerator* const rng = isolate->random_number_generator();
1600 Assembler assm(isolate, nullptr, 0);
1601 __ smmul(r1, r1, r2);
1602 __ str(r1, MemOperand(r0));
1603 __ bx(lr);
1604 CodeDesc desc;
1605 assm.GetCode(&desc);
1606 Handle<Code> code = isolate->factory()->NewCode(
1607 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1608#ifdef OBJECT_PRINT
1609 code->Print(std::cout);
1610#endif
1611 F3 f = FUNCTION_CAST<F3>(code->entry());
1612 for (size_t i = 0; i < 128; ++i) {
1613 int32_t r, x = rng->NextInt(), y = rng->NextInt();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001614 Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, y, 0, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001615 CHECK_EQ(bits::SignedMulHigh32(x, y), r);
1616 USE(dummy);
1617 }
1618}
1619
1620
1621TEST(sxtb) {
1622 CcTest::InitializeVM();
1623 Isolate* const isolate = CcTest::i_isolate();
1624 HandleScope scope(isolate);
1625 RandomNumberGenerator* const rng = isolate->random_number_generator();
1626 Assembler assm(isolate, nullptr, 0);
1627 __ sxtb(r1, r1);
1628 __ str(r1, MemOperand(r0));
1629 __ bx(lr);
1630 CodeDesc desc;
1631 assm.GetCode(&desc);
1632 Handle<Code> code = isolate->factory()->NewCode(
1633 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1634#ifdef OBJECT_PRINT
1635 code->Print(std::cout);
1636#endif
1637 F3 f = FUNCTION_CAST<F3>(code->entry());
1638 for (size_t i = 0; i < 128; ++i) {
1639 int32_t r, x = rng->NextInt();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001640 Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, 0, 0, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001641 CHECK_EQ(static_cast<int32_t>(static_cast<int8_t>(x)), r);
1642 USE(dummy);
1643 }
1644}
1645
1646
1647TEST(sxtab) {
1648 CcTest::InitializeVM();
1649 Isolate* const isolate = CcTest::i_isolate();
1650 HandleScope scope(isolate);
1651 RandomNumberGenerator* const rng = isolate->random_number_generator();
1652 Assembler assm(isolate, nullptr, 0);
1653 __ sxtab(r1, r2, r1);
1654 __ str(r1, MemOperand(r0));
1655 __ bx(lr);
1656 CodeDesc desc;
1657 assm.GetCode(&desc);
1658 Handle<Code> code = isolate->factory()->NewCode(
1659 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1660#ifdef OBJECT_PRINT
1661 code->Print(std::cout);
1662#endif
1663 F3 f = FUNCTION_CAST<F3>(code->entry());
1664 for (size_t i = 0; i < 128; ++i) {
1665 int32_t r, x = rng->NextInt(), y = rng->NextInt();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001666 Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, y, 0, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001667 CHECK_EQ(static_cast<int32_t>(static_cast<int8_t>(x)) + y, r);
1668 USE(dummy);
1669 }
1670}
1671
1672
1673TEST(sxth) {
1674 CcTest::InitializeVM();
1675 Isolate* const isolate = CcTest::i_isolate();
1676 HandleScope scope(isolate);
1677 RandomNumberGenerator* const rng = isolate->random_number_generator();
1678 Assembler assm(isolate, nullptr, 0);
1679 __ sxth(r1, r1);
1680 __ str(r1, MemOperand(r0));
1681 __ bx(lr);
1682 CodeDesc desc;
1683 assm.GetCode(&desc);
1684 Handle<Code> code = isolate->factory()->NewCode(
1685 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1686#ifdef OBJECT_PRINT
1687 code->Print(std::cout);
1688#endif
1689 F3 f = FUNCTION_CAST<F3>(code->entry());
1690 for (size_t i = 0; i < 128; ++i) {
1691 int32_t r, x = rng->NextInt();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001692 Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, 0, 0, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001693 CHECK_EQ(static_cast<int32_t>(static_cast<int16_t>(x)), r);
1694 USE(dummy);
1695 }
1696}
1697
1698
1699TEST(sxtah) {
1700 CcTest::InitializeVM();
1701 Isolate* const isolate = CcTest::i_isolate();
1702 HandleScope scope(isolate);
1703 RandomNumberGenerator* const rng = isolate->random_number_generator();
1704 Assembler assm(isolate, nullptr, 0);
1705 __ sxtah(r1, r2, r1);
1706 __ str(r1, MemOperand(r0));
1707 __ bx(lr);
1708 CodeDesc desc;
1709 assm.GetCode(&desc);
1710 Handle<Code> code = isolate->factory()->NewCode(
1711 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1712#ifdef OBJECT_PRINT
1713 code->Print(std::cout);
1714#endif
1715 F3 f = FUNCTION_CAST<F3>(code->entry());
1716 for (size_t i = 0; i < 128; ++i) {
1717 int32_t r, x = rng->NextInt(), y = rng->NextInt();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001718 Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, y, 0, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001719 CHECK_EQ(static_cast<int32_t>(static_cast<int16_t>(x)) + y, r);
1720 USE(dummy);
1721 }
1722}
1723
1724
1725TEST(uxtb) {
1726 CcTest::InitializeVM();
1727 Isolate* const isolate = CcTest::i_isolate();
1728 HandleScope scope(isolate);
1729 RandomNumberGenerator* const rng = isolate->random_number_generator();
1730 Assembler assm(isolate, nullptr, 0);
1731 __ uxtb(r1, r1);
1732 __ str(r1, MemOperand(r0));
1733 __ bx(lr);
1734 CodeDesc desc;
1735 assm.GetCode(&desc);
1736 Handle<Code> code = isolate->factory()->NewCode(
1737 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1738#ifdef OBJECT_PRINT
1739 code->Print(std::cout);
1740#endif
1741 F3 f = FUNCTION_CAST<F3>(code->entry());
1742 for (size_t i = 0; i < 128; ++i) {
1743 int32_t r, x = rng->NextInt();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001744 Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, 0, 0, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001745 CHECK_EQ(static_cast<int32_t>(static_cast<uint8_t>(x)), r);
1746 USE(dummy);
1747 }
1748}
1749
1750
1751TEST(uxtab) {
1752 CcTest::InitializeVM();
1753 Isolate* const isolate = CcTest::i_isolate();
1754 HandleScope scope(isolate);
1755 RandomNumberGenerator* const rng = isolate->random_number_generator();
1756 Assembler assm(isolate, nullptr, 0);
1757 __ uxtab(r1, r2, r1);
1758 __ str(r1, MemOperand(r0));
1759 __ bx(lr);
1760 CodeDesc desc;
1761 assm.GetCode(&desc);
1762 Handle<Code> code = isolate->factory()->NewCode(
1763 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1764#ifdef OBJECT_PRINT
1765 code->Print(std::cout);
1766#endif
1767 F3 f = FUNCTION_CAST<F3>(code->entry());
1768 for (size_t i = 0; i < 128; ++i) {
1769 int32_t r, x = rng->NextInt(), y = rng->NextInt();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001770 Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, y, 0, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001771 CHECK_EQ(static_cast<int32_t>(static_cast<uint8_t>(x)) + y, r);
1772 USE(dummy);
1773 }
1774}
1775
1776
1777TEST(uxth) {
1778 CcTest::InitializeVM();
1779 Isolate* const isolate = CcTest::i_isolate();
1780 HandleScope scope(isolate);
1781 RandomNumberGenerator* const rng = isolate->random_number_generator();
1782 Assembler assm(isolate, nullptr, 0);
1783 __ uxth(r1, r1);
1784 __ str(r1, MemOperand(r0));
1785 __ bx(lr);
1786 CodeDesc desc;
1787 assm.GetCode(&desc);
1788 Handle<Code> code = isolate->factory()->NewCode(
1789 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1790#ifdef OBJECT_PRINT
1791 code->Print(std::cout);
1792#endif
1793 F3 f = FUNCTION_CAST<F3>(code->entry());
1794 for (size_t i = 0; i < 128; ++i) {
1795 int32_t r, x = rng->NextInt();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001796 Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, 0, 0, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001797 CHECK_EQ(static_cast<int32_t>(static_cast<uint16_t>(x)), r);
1798 USE(dummy);
1799 }
1800}
1801
1802
1803TEST(uxtah) {
1804 CcTest::InitializeVM();
1805 Isolate* const isolate = CcTest::i_isolate();
1806 HandleScope scope(isolate);
1807 RandomNumberGenerator* const rng = isolate->random_number_generator();
1808 Assembler assm(isolate, nullptr, 0);
1809 __ uxtah(r1, r2, r1);
1810 __ str(r1, MemOperand(r0));
1811 __ bx(lr);
1812 CodeDesc desc;
1813 assm.GetCode(&desc);
1814 Handle<Code> code = isolate->factory()->NewCode(
1815 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1816#ifdef OBJECT_PRINT
1817 code->Print(std::cout);
1818#endif
1819 F3 f = FUNCTION_CAST<F3>(code->entry());
1820 for (size_t i = 0; i < 128; ++i) {
1821 int32_t r, x = rng->NextInt(), y = rng->NextInt();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001822 Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, y, 0, 0);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001823 CHECK_EQ(static_cast<int32_t>(static_cast<uint16_t>(x)) + y, r);
1824 USE(dummy);
1825 }
1826}
1827
1828
Ben Murdoch097c5b22016-05-18 11:27:45 +01001829#define TEST_RBIT(expected_, input_) \
1830 t.input = input_; \
1831 t.result = 0; \
1832 dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); \
1833 CHECK_EQ(expected_, t.result);
1834
1835
1836TEST(rbit) {
1837 CcTest::InitializeVM();
1838 Isolate* const isolate = CcTest::i_isolate();
1839 HandleScope scope(isolate);
1840 Assembler assm(isolate, nullptr, 0);
1841
1842 if (CpuFeatures::IsSupported(ARMv7)) {
1843 CpuFeatureScope scope(&assm, ARMv7);
1844
1845 typedef struct {
1846 uint32_t input;
1847 uint32_t result;
1848 } T;
1849 T t;
1850
1851 __ ldr(r1, MemOperand(r0, offsetof(T, input)));
1852 __ rbit(r1, r1);
1853 __ str(r1, MemOperand(r0, offsetof(T, result)));
1854 __ bx(lr);
1855
1856 CodeDesc desc;
1857 assm.GetCode(&desc);
1858 Handle<Code> code = isolate->factory()->NewCode(
1859 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1860
1861#ifdef OBJECT_PRINT
1862 code->Print(std::cout);
1863#endif
1864
1865 F3 f = FUNCTION_CAST<F3>(code->entry());
1866 Object* dummy = NULL;
1867 TEST_RBIT(0xffffffff, 0xffffffff);
1868 TEST_RBIT(0x00000000, 0x00000000);
1869 TEST_RBIT(0xffff0000, 0x0000ffff);
1870 TEST_RBIT(0xff00ff00, 0x00ff00ff);
1871 TEST_RBIT(0xf0f0f0f0, 0x0f0f0f0f);
1872 TEST_RBIT(0x1e6a2c48, 0x12345678);
1873 USE(dummy);
1874 }
1875}
1876
1877
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001878TEST(code_relative_offset) {
1879 // Test extracting the offset of a label from the beginning of the code
1880 // in a register.
1881 CcTest::InitializeVM();
1882 Isolate* isolate = CcTest::i_isolate();
1883 HandleScope scope(isolate);
1884 // Initialize a code object that will contain the code.
1885 Handle<Object> code_object(isolate->heap()->undefined_value(), isolate);
1886
1887 Assembler assm(isolate, NULL, 0);
1888
1889 Label start, target_away, target_faraway;
1890
1891 __ stm(db_w, sp, r4.bit() | r5.bit() | lr.bit());
1892
1893 // r3 is used as the address zero, the test will crash when we load it.
1894 __ mov(r3, Operand::Zero());
1895
1896 // r5 will be a pointer to the start of the code.
1897 __ mov(r5, Operand(code_object));
1898 __ mov_label_offset(r4, &start);
1899
1900 __ mov_label_offset(r1, &target_faraway);
1901 __ str(r1, MemOperand(sp, kPointerSize, NegPreIndex));
1902
1903 __ mov_label_offset(r1, &target_away);
1904
1905 // Jump straight to 'target_away' the first time and use the relative
1906 // position the second time. This covers the case when extracting the
1907 // position of a label which is linked.
1908 __ mov(r2, Operand::Zero());
1909 __ bind(&start);
1910 __ cmp(r2, Operand::Zero());
1911 __ b(eq, &target_away);
1912 __ add(pc, r5, r1);
1913 // Emit invalid instructions to push the label between 2^8 and 2^16
1914 // instructions away. The test will crash if they are reached.
1915 for (int i = 0; i < (1 << 10); i++) {
1916 __ ldr(r3, MemOperand(r3));
1917 }
1918 __ bind(&target_away);
1919 // This will be hit twice: r0 = r0 + 5 + 5.
1920 __ add(r0, r0, Operand(5));
1921
1922 __ ldr(r1, MemOperand(sp, kPointerSize, PostIndex), ne);
1923 __ add(pc, r5, r4, LeaveCC, ne);
1924
1925 __ mov(r2, Operand(1));
1926 __ b(&start);
1927 // Emit invalid instructions to push the label between 2^16 and 2^24
1928 // instructions away. The test will crash if they are reached.
1929 for (int i = 0; i < (1 << 21); i++) {
1930 __ ldr(r3, MemOperand(r3));
1931 }
1932 __ bind(&target_faraway);
1933 // r0 = r0 + 5 + 5 + 11
1934 __ add(r0, r0, Operand(11));
1935
1936 __ ldm(ia_w, sp, r4.bit() | r5.bit() | pc.bit());
1937
1938 CodeDesc desc;
1939 assm.GetCode(&desc);
1940 Handle<Code> code = isolate->factory()->NewCode(
1941 desc, Code::ComputeFlags(Code::STUB), code_object);
1942 F1 f = FUNCTION_CAST<F1>(code->entry());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001943 int res =
1944 reinterpret_cast<int>(CALL_GENERATED_CODE(isolate, f, 21, 0, 0, 0, 0));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001945 ::printf("f() = %d\n", res);
1946 CHECK_EQ(42, res);
1947}
1948
Ben Murdochda12d292016-06-02 14:46:10 +01001949TEST(msr_mrs) {
1950 // Test msr and mrs.
1951 CcTest::InitializeVM();
1952 Isolate* isolate = CcTest::i_isolate();
1953 HandleScope scope(isolate);
1954
1955 Assembler assm(isolate, NULL, 0);
1956
1957 // Create a helper function:
1958 // void TestMsrMrs(uint32_t nzcv,
1959 // uint32_t * result_conditionals,
1960 // uint32_t * result_mrs);
1961 __ msr(CPSR_f, Operand(r0));
1962
1963 // Test that the condition flags have taken effect.
1964 __ mov(r3, Operand(0));
1965 __ orr(r3, r3, Operand(1 << 31), LeaveCC, mi); // N
1966 __ orr(r3, r3, Operand(1 << 30), LeaveCC, eq); // Z
1967 __ orr(r3, r3, Operand(1 << 29), LeaveCC, cs); // C
1968 __ orr(r3, r3, Operand(1 << 28), LeaveCC, vs); // V
1969 __ str(r3, MemOperand(r1));
1970
1971 // Also check mrs, ignoring everything other than the flags.
1972 __ mrs(r3, CPSR);
1973 __ and_(r3, r3, Operand(kSpecialCondition));
1974 __ str(r3, MemOperand(r2));
1975
1976 __ bx(lr);
1977
1978 CodeDesc desc;
1979 assm.GetCode(&desc);
1980 Handle<Code> code = isolate->factory()->NewCode(
1981 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1982#ifdef DEBUG
1983 OFStream os(stdout);
1984 code->Print(os);
1985#endif
1986 F5 f = FUNCTION_CAST<F5>(code->entry());
1987 Object* dummy = nullptr;
1988 USE(dummy);
1989
1990#define CHECK_MSR_MRS(n, z, c, v) \
1991 do { \
1992 uint32_t nzcv = (n << 31) | (z << 30) | (c << 29) | (v << 28); \
1993 uint32_t result_conditionals = -1; \
1994 uint32_t result_mrs = -1; \
1995 dummy = CALL_GENERATED_CODE(isolate, f, nzcv, &result_conditionals, \
1996 &result_mrs, 0, 0); \
1997 CHECK_EQ(nzcv, result_conditionals); \
1998 CHECK_EQ(nzcv, result_mrs); \
1999 } while (0);
2000
2001 // N Z C V
2002 CHECK_MSR_MRS(0, 0, 0, 0);
2003 CHECK_MSR_MRS(0, 0, 0, 1);
2004 CHECK_MSR_MRS(0, 0, 1, 0);
2005 CHECK_MSR_MRS(0, 0, 1, 1);
2006 CHECK_MSR_MRS(0, 1, 0, 0);
2007 CHECK_MSR_MRS(0, 1, 0, 1);
2008 CHECK_MSR_MRS(0, 1, 1, 0);
2009 CHECK_MSR_MRS(0, 1, 1, 1);
2010 CHECK_MSR_MRS(1, 0, 0, 0);
2011 CHECK_MSR_MRS(1, 0, 0, 1);
2012 CHECK_MSR_MRS(1, 0, 1, 0);
2013 CHECK_MSR_MRS(1, 0, 1, 1);
2014 CHECK_MSR_MRS(1, 1, 0, 0);
2015 CHECK_MSR_MRS(1, 1, 0, 1);
2016 CHECK_MSR_MRS(1, 1, 1, 0);
2017 CHECK_MSR_MRS(1, 1, 1, 1);
2018
2019#undef CHECK_MSR_MRS
2020}
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002021
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002022TEST(ARMv8_float32_vrintX) {
2023 // Test the vrintX floating point instructions.
2024 CcTest::InitializeVM();
2025 Isolate* isolate = CcTest::i_isolate();
2026 HandleScope scope(isolate);
2027
2028 typedef struct {
2029 float input;
2030 float ar;
2031 float nr;
2032 float mr;
2033 float pr;
2034 float zr;
2035 } T;
2036 T t;
2037
2038 // Create a function that accepts &t, and loads, manipulates, and stores
2039 // the floats.
2040 Assembler assm(isolate, NULL, 0);
2041 Label L, C;
2042
2043
2044 if (CpuFeatures::IsSupported(ARMv8)) {
2045 CpuFeatureScope scope(&assm, ARMv8);
2046
2047 __ mov(ip, Operand(sp));
2048 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
2049
2050 __ mov(r4, Operand(r0));
2051
2052 // Test vrinta
2053 __ vldr(s6, r4, offsetof(T, input));
2054 __ vrinta(s5, s6);
2055 __ vstr(s5, r4, offsetof(T, ar));
2056
2057 // Test vrintn
2058 __ vldr(s6, r4, offsetof(T, input));
2059 __ vrintn(s5, s6);
2060 __ vstr(s5, r4, offsetof(T, nr));
2061
2062 // Test vrintp
2063 __ vldr(s6, r4, offsetof(T, input));
2064 __ vrintp(s5, s6);
2065 __ vstr(s5, r4, offsetof(T, pr));
2066
2067 // Test vrintm
2068 __ vldr(s6, r4, offsetof(T, input));
2069 __ vrintm(s5, s6);
2070 __ vstr(s5, r4, offsetof(T, mr));
2071
2072 // Test vrintz
2073 __ vldr(s6, r4, offsetof(T, input));
2074 __ vrintz(s5, s6);
2075 __ vstr(s5, r4, offsetof(T, zr));
2076
2077 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
2078
2079 CodeDesc desc;
2080 assm.GetCode(&desc);
2081 Handle<Code> code = isolate->factory()->NewCode(
2082 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2083#ifdef DEBUG
2084 OFStream os(stdout);
2085 code->Print(os);
2086#endif
2087 F3 f = FUNCTION_CAST<F3>(code->entry());
2088
2089 Object* dummy = nullptr;
2090 USE(dummy);
2091
2092#define CHECK_VRINT(input_val, ares, nres, mres, pres, zres) \
2093 t.input = input_val; \
2094 dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); \
2095 CHECK_EQ(ares, t.ar); \
2096 CHECK_EQ(nres, t.nr); \
2097 CHECK_EQ(mres, t.mr); \
2098 CHECK_EQ(pres, t.pr); \
2099 CHECK_EQ(zres, t.zr);
2100
2101 CHECK_VRINT(-0.5, -1.0, -0.0, -1.0, -0.0, -0.0)
2102 CHECK_VRINT(-0.6, -1.0, -1.0, -1.0, -0.0, -0.0)
2103 CHECK_VRINT(-1.1, -1.0, -1.0, -2.0, -1.0, -1.0)
2104 CHECK_VRINT(0.5, 1.0, 0.0, 0.0, 1.0, 0.0)
2105 CHECK_VRINT(0.6, 1.0, 1.0, 0.0, 1.0, 0.0)
2106 CHECK_VRINT(1.1, 1.0, 1.0, 1.0, 2.0, 1.0)
2107 float inf = std::numeric_limits<float>::infinity();
2108 CHECK_VRINT(inf, inf, inf, inf, inf, inf)
2109 CHECK_VRINT(-inf, -inf, -inf, -inf, -inf, -inf)
2110 CHECK_VRINT(-0.0, -0.0, -0.0, -0.0, -0.0, -0.0)
2111
2112 // Check NaN propagation.
2113 float nan = std::numeric_limits<float>::quiet_NaN();
2114 t.input = nan;
2115 dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
2116 CHECK_EQ(bit_cast<int32_t>(nan), bit_cast<int32_t>(t.ar));
2117 CHECK_EQ(bit_cast<int32_t>(nan), bit_cast<int32_t>(t.nr));
2118 CHECK_EQ(bit_cast<int32_t>(nan), bit_cast<int32_t>(t.mr));
2119 CHECK_EQ(bit_cast<int32_t>(nan), bit_cast<int32_t>(t.pr));
2120 CHECK_EQ(bit_cast<int32_t>(nan), bit_cast<int32_t>(t.zr));
2121
2122#undef CHECK_VRINT
2123 }
2124}
2125
2126
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002127TEST(ARMv8_vrintX) {
2128 // Test the vrintX floating point instructions.
2129 CcTest::InitializeVM();
2130 Isolate* isolate = CcTest::i_isolate();
2131 HandleScope scope(isolate);
2132
2133 typedef struct {
2134 double input;
2135 double ar;
2136 double nr;
2137 double mr;
2138 double pr;
2139 double zr;
2140 } T;
2141 T t;
2142
2143 // Create a function that accepts &t, and loads, manipulates, and stores
2144 // the doubles and floats.
2145 Assembler assm(isolate, NULL, 0);
2146 Label L, C;
2147
2148
2149 if (CpuFeatures::IsSupported(ARMv8)) {
2150 CpuFeatureScope scope(&assm, ARMv8);
2151
2152 __ mov(ip, Operand(sp));
2153 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit());
2154
2155 __ mov(r4, Operand(r0));
2156
2157 // Test vrinta
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002158 __ vldr(d6, r4, offsetof(T, input));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002159 __ vrinta(d5, d6);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002160 __ vstr(d5, r4, offsetof(T, ar));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002161
2162 // Test vrintn
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002163 __ vldr(d6, r4, offsetof(T, input));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002164 __ vrintn(d5, d6);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002165 __ vstr(d5, r4, offsetof(T, nr));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002166
2167 // Test vrintp
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002168 __ vldr(d6, r4, offsetof(T, input));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002169 __ vrintp(d5, d6);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002170 __ vstr(d5, r4, offsetof(T, pr));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002171
2172 // Test vrintm
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002173 __ vldr(d6, r4, offsetof(T, input));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002174 __ vrintm(d5, d6);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002175 __ vstr(d5, r4, offsetof(T, mr));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002176
2177 // Test vrintz
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002178 __ vldr(d6, r4, offsetof(T, input));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002179 __ vrintz(d5, d6);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002180 __ vstr(d5, r4, offsetof(T, zr));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002181
2182 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit());
2183
2184 CodeDesc desc;
2185 assm.GetCode(&desc);
2186 Handle<Code> code = isolate->factory()->NewCode(
2187 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2188#ifdef DEBUG
2189 OFStream os(stdout);
2190 code->Print(os);
2191#endif
2192 F3 f = FUNCTION_CAST<F3>(code->entry());
2193
2194 Object* dummy = nullptr;
2195 USE(dummy);
2196
2197#define CHECK_VRINT(input_val, ares, nres, mres, pres, zres) \
2198 t.input = input_val; \
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002199 dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); \
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002200 CHECK_EQ(ares, t.ar); \
2201 CHECK_EQ(nres, t.nr); \
2202 CHECK_EQ(mres, t.mr); \
2203 CHECK_EQ(pres, t.pr); \
2204 CHECK_EQ(zres, t.zr);
2205
2206 CHECK_VRINT(-0.5, -1.0, -0.0, -1.0, -0.0, -0.0)
2207 CHECK_VRINT(-0.6, -1.0, -1.0, -1.0, -0.0, -0.0)
2208 CHECK_VRINT(-1.1, -1.0, -1.0, -2.0, -1.0, -1.0)
2209 CHECK_VRINT(0.5, 1.0, 0.0, 0.0, 1.0, 0.0)
2210 CHECK_VRINT(0.6, 1.0, 1.0, 0.0, 1.0, 0.0)
2211 CHECK_VRINT(1.1, 1.0, 1.0, 1.0, 2.0, 1.0)
2212 double inf = std::numeric_limits<double>::infinity();
2213 CHECK_VRINT(inf, inf, inf, inf, inf, inf)
2214 CHECK_VRINT(-inf, -inf, -inf, -inf, -inf, -inf)
2215 CHECK_VRINT(-0.0, -0.0, -0.0, -0.0, -0.0, -0.0)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002216
2217 // Check NaN propagation.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002218 double nan = std::numeric_limits<double>::quiet_NaN();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002219 t.input = nan;
2220 dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0);
2221 CHECK_EQ(bit_cast<int64_t>(nan), bit_cast<int64_t>(t.ar));
2222 CHECK_EQ(bit_cast<int64_t>(nan), bit_cast<int64_t>(t.nr));
2223 CHECK_EQ(bit_cast<int64_t>(nan), bit_cast<int64_t>(t.mr));
2224 CHECK_EQ(bit_cast<int64_t>(nan), bit_cast<int64_t>(t.pr));
2225 CHECK_EQ(bit_cast<int64_t>(nan), bit_cast<int64_t>(t.zr));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002226
2227#undef CHECK_VRINT
2228 }
2229}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002230
Ben Murdochc5610432016-08-08 18:44:38 +01002231TEST(ARMv8_vsel) {
2232 // Test the vsel floating point instructions.
2233 CcTest::InitializeVM();
2234 Isolate* isolate = CcTest::i_isolate();
2235 HandleScope scope(isolate);
2236
2237 Assembler assm(isolate, NULL, 0);
2238
2239 // Used to indicate whether a condition passed or failed.
2240 static constexpr float kResultPass = 1.0f;
2241 static constexpr float kResultFail = -kResultPass;
2242
2243 struct ResultsF32 {
2244 float vseleq_;
2245 float vselge_;
2246 float vselgt_;
2247 float vselvs_;
2248
2249 // The following conditions aren't architecturally supported, but the
2250 // assembler implements them by swapping the inputs.
2251 float vselne_;
2252 float vsellt_;
2253 float vselle_;
2254 float vselvc_;
2255 };
2256
2257 struct ResultsF64 {
2258 double vseleq_;
2259 double vselge_;
2260 double vselgt_;
2261 double vselvs_;
2262
2263 // The following conditions aren't architecturally supported, but the
2264 // assembler implements them by swapping the inputs.
2265 double vselne_;
2266 double vsellt_;
2267 double vselle_;
2268 double vselvc_;
2269 };
2270
2271 if (CpuFeatures::IsSupported(ARMv8)) {
2272 CpuFeatureScope scope(&assm, ARMv8);
2273
2274 // Create a helper function:
2275 // void TestVsel(uint32_t nzcv,
2276 // ResultsF32* results_f32,
2277 // ResultsF64* results_f64);
2278 __ msr(CPSR_f, Operand(r0));
2279
2280 __ vmov(s1, kResultPass);
2281 __ vmov(s2, kResultFail);
2282
2283 __ vsel(eq, s0, s1, s2);
2284 __ vstr(s0, r1, offsetof(ResultsF32, vseleq_));
2285 __ vsel(ge, s0, s1, s2);
2286 __ vstr(s0, r1, offsetof(ResultsF32, vselge_));
2287 __ vsel(gt, s0, s1, s2);
2288 __ vstr(s0, r1, offsetof(ResultsF32, vselgt_));
2289 __ vsel(vs, s0, s1, s2);
2290 __ vstr(s0, r1, offsetof(ResultsF32, vselvs_));
2291
2292 __ vsel(ne, s0, s1, s2);
2293 __ vstr(s0, r1, offsetof(ResultsF32, vselne_));
2294 __ vsel(lt, s0, s1, s2);
2295 __ vstr(s0, r1, offsetof(ResultsF32, vsellt_));
2296 __ vsel(le, s0, s1, s2);
2297 __ vstr(s0, r1, offsetof(ResultsF32, vselle_));
2298 __ vsel(vc, s0, s1, s2);
2299 __ vstr(s0, r1, offsetof(ResultsF32, vselvc_));
2300
2301 __ vmov(d1, kResultPass);
2302 __ vmov(d2, kResultFail);
2303
2304 __ vsel(eq, d0, d1, d2);
2305 __ vstr(d0, r2, offsetof(ResultsF64, vseleq_));
2306 __ vsel(ge, d0, d1, d2);
2307 __ vstr(d0, r2, offsetof(ResultsF64, vselge_));
2308 __ vsel(gt, d0, d1, d2);
2309 __ vstr(d0, r2, offsetof(ResultsF64, vselgt_));
2310 __ vsel(vs, d0, d1, d2);
2311 __ vstr(d0, r2, offsetof(ResultsF64, vselvs_));
2312
2313 __ vsel(ne, d0, d1, d2);
2314 __ vstr(d0, r2, offsetof(ResultsF64, vselne_));
2315 __ vsel(lt, d0, d1, d2);
2316 __ vstr(d0, r2, offsetof(ResultsF64, vsellt_));
2317 __ vsel(le, d0, d1, d2);
2318 __ vstr(d0, r2, offsetof(ResultsF64, vselle_));
2319 __ vsel(vc, d0, d1, d2);
2320 __ vstr(d0, r2, offsetof(ResultsF64, vselvc_));
2321
2322 __ bx(lr);
2323
2324 CodeDesc desc;
2325 assm.GetCode(&desc);
2326 Handle<Code> code = isolate->factory()->NewCode(
2327 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
2328#ifdef DEBUG
2329 OFStream os(stdout);
2330 code->Print(os);
2331#endif
2332 F5 f = FUNCTION_CAST<F5>(code->entry());
2333 Object* dummy = nullptr;
2334 USE(dummy);
2335
2336 STATIC_ASSERT(kResultPass == -kResultFail);
2337#define CHECK_VSEL(n, z, c, v, vseleq, vselge, vselgt, vselvs) \
2338 do { \
2339 ResultsF32 results_f32; \
2340 ResultsF64 results_f64; \
2341 uint32_t nzcv = (n << 31) | (z << 30) | (c << 29) | (v << 28); \
2342 dummy = CALL_GENERATED_CODE(isolate, f, nzcv, &results_f32, &results_f64, \
2343 0, 0); \
2344 CHECK_EQ(vseleq, results_f32.vseleq_); \
2345 CHECK_EQ(vselge, results_f32.vselge_); \
2346 CHECK_EQ(vselgt, results_f32.vselgt_); \
2347 CHECK_EQ(vselvs, results_f32.vselvs_); \
2348 CHECK_EQ(-vseleq, results_f32.vselne_); \
2349 CHECK_EQ(-vselge, results_f32.vsellt_); \
2350 CHECK_EQ(-vselgt, results_f32.vselle_); \
2351 CHECK_EQ(-vselvs, results_f32.vselvc_); \
2352 CHECK_EQ(vseleq, results_f64.vseleq_); \
2353 CHECK_EQ(vselge, results_f64.vselge_); \
2354 CHECK_EQ(vselgt, results_f64.vselgt_); \
2355 CHECK_EQ(vselvs, results_f64.vselvs_); \
2356 CHECK_EQ(-vseleq, results_f64.vselne_); \
2357 CHECK_EQ(-vselge, results_f64.vsellt_); \
2358 CHECK_EQ(-vselgt, results_f64.vselle_); \
2359 CHECK_EQ(-vselvs, results_f64.vselvc_); \
2360 } while (0);
2361
2362 // N Z C V vseleq vselge vselgt vselvs
2363 CHECK_VSEL(0, 0, 0, 0, kResultFail, kResultPass, kResultPass, kResultFail);
2364 CHECK_VSEL(0, 0, 0, 1, kResultFail, kResultFail, kResultFail, kResultPass);
2365 CHECK_VSEL(0, 0, 1, 0, kResultFail, kResultPass, kResultPass, kResultFail);
2366 CHECK_VSEL(0, 0, 1, 1, kResultFail, kResultFail, kResultFail, kResultPass);
2367 CHECK_VSEL(0, 1, 0, 0, kResultPass, kResultPass, kResultFail, kResultFail);
2368 CHECK_VSEL(0, 1, 0, 1, kResultPass, kResultFail, kResultFail, kResultPass);
2369 CHECK_VSEL(0, 1, 1, 0, kResultPass, kResultPass, kResultFail, kResultFail);
2370 CHECK_VSEL(0, 1, 1, 1, kResultPass, kResultFail, kResultFail, kResultPass);
2371 CHECK_VSEL(1, 0, 0, 0, kResultFail, kResultFail, kResultFail, kResultFail);
2372 CHECK_VSEL(1, 0, 0, 1, kResultFail, kResultPass, kResultPass, kResultPass);
2373 CHECK_VSEL(1, 0, 1, 0, kResultFail, kResultFail, kResultFail, kResultFail);
2374 CHECK_VSEL(1, 0, 1, 1, kResultFail, kResultPass, kResultPass, kResultPass);
2375 CHECK_VSEL(1, 1, 0, 0, kResultPass, kResultFail, kResultFail, kResultFail);
2376 CHECK_VSEL(1, 1, 0, 1, kResultPass, kResultPass, kResultFail, kResultPass);
2377 CHECK_VSEL(1, 1, 1, 0, kResultPass, kResultFail, kResultFail, kResultFail);
2378 CHECK_VSEL(1, 1, 1, 1, kResultPass, kResultPass, kResultFail, kResultPass);
2379
2380#undef CHECK_VSEL
2381 }
2382}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002383
2384TEST(regress4292_b) {
2385 CcTest::InitializeVM();
2386 Isolate* isolate = CcTest::i_isolate();
2387 HandleScope scope(isolate);
2388
2389 Assembler assm(isolate, NULL, 0);
2390 Label end;
2391 __ mov(r0, Operand(isolate->factory()->infinity_value()));
2392 for (int i = 0; i < 1020; ++i) {
2393 __ b(hi, &end);
2394 }
2395 __ bind(&end);
2396}
2397
2398
2399TEST(regress4292_bl) {
2400 CcTest::InitializeVM();
2401 Isolate* isolate = CcTest::i_isolate();
2402 HandleScope scope(isolate);
2403
2404 Assembler assm(isolate, NULL, 0);
2405 Label end;
2406 __ mov(r0, Operand(isolate->factory()->infinity_value()));
2407 for (int i = 0; i < 1020; ++i) {
2408 __ bl(hi, &end);
2409 }
2410 __ bind(&end);
2411}
2412
2413
2414TEST(regress4292_blx) {
2415 CcTest::InitializeVM();
2416 Isolate* isolate = CcTest::i_isolate();
2417 HandleScope scope(isolate);
2418
2419 Assembler assm(isolate, NULL, 0);
2420 Label end;
2421 __ mov(r0, Operand(isolate->factory()->infinity_value()));
2422 for (int i = 0; i < 1020; ++i) {
2423 __ blx(&end);
2424 }
2425 __ bind(&end);
2426}
2427
2428
2429TEST(regress4292_CheckConstPool) {
2430 CcTest::InitializeVM();
2431 Isolate* isolate = CcTest::i_isolate();
2432 HandleScope scope(isolate);
2433
2434 Assembler assm(isolate, NULL, 0);
2435 __ mov(r0, Operand(isolate->factory()->infinity_value()));
2436 __ BlockConstPoolFor(1019);
2437 for (int i = 0; i < 1019; ++i) __ nop();
2438 __ vldr(d0, MemOperand(r0, 0));
2439}
2440
Steve Blocka7e24c12009-10-30 11:49:00 +00002441#undef __