blob: 156e1cb0874023ee24d157bc8ec52d066c40cd45 [file] [log] [blame]
armvixlad96eda2013-06-14 11:42:37 +01001// Copyright 2013, ARM Limited
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6//
7// * Redistributions of source code must retain the above copyright notice,
8// this list of conditions and the following disclaimer.
9// * Redistributions in binary form must reproduce the above copyright notice,
10// this list of conditions and the following disclaimer in the documentation
11// and/or other materials provided with the distribution.
12// * Neither the name of ARM Limited nor the names of its contributors may be
13// used to endorse or promote products derived from this software without
14// specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27#include <stdio.h>
armvixlf37fdc02014-02-05 13:22:16 +000028#include <stdlib.h>
armvixlad96eda2013-06-14 11:42:37 +010029#include <string.h>
armvixl578645f2013-08-15 17:21:42 +010030#include <math.h>
31#include <float.h>
armvixlad96eda2013-06-14 11:42:37 +010032
armvixl330dc712014-11-25 10:38:32 +000033#include "test-runner.h"
armvixlad96eda2013-06-14 11:42:37 +010034#include "test-utils-a64.h"
35#include "a64/macro-assembler-a64.h"
36#include "a64/simulator-a64.h"
37#include "a64/debugger-a64.h"
38#include "a64/disasm-a64.h"
39#include "a64/cpu-a64.h"
40
41namespace vixl {
42
43// Test infrastructure.
44//
45// Tests are functions which accept no parameters and have no return values.
46// The testing code should not perform an explicit return once completed. For
47// example to test the mov immediate instruction a very simple test would be:
48//
49// TEST(mov_x0_one) {
50// SETUP();
51//
52// START();
53// __ mov(x0, Operand(1));
54// END();
55//
56// RUN();
57//
58// ASSERT_EQUAL_64(1, x0);
59//
60// TEARDOWN();
61// }
62//
63// Within a START ... END block all registers but sp can be modified. sp has to
64// be explicitly saved/restored. The END() macro replaces the function return
65// so it may appear multiple times in a test if the test has multiple exit
66// points.
67//
68// Once the test has been run all integer and floating point registers as well
69// as flags are accessible through a RegisterDump instance, see
70// utils-a64.cc for more info on RegisterDump.
71//
72// We provide some helper assert to handle common cases:
73//
74// ASSERT_EQUAL_32(int32_t, int_32t)
75// ASSERT_EQUAL_FP32(float, float)
76// ASSERT_EQUAL_32(int32_t, W register)
77// ASSERT_EQUAL_FP32(float, S register)
78// ASSERT_EQUAL_64(int64_t, int_64t)
79// ASSERT_EQUAL_FP64(double, double)
80// ASSERT_EQUAL_64(int64_t, X register)
81// ASSERT_EQUAL_64(X register, X register)
82// ASSERT_EQUAL_FP64(double, D register)
83//
84// e.g. ASSERT_EQUAL_64(0.5, d30);
85//
armvixl578645f2013-08-15 17:21:42 +010086// If more advanced computation is required before the assert then access the
armvixlad96eda2013-06-14 11:42:37 +010087// RegisterDump named core directly:
88//
89// ASSERT_EQUAL_64(0x1234, core->reg_x0() & 0xffff);
90
91
92#define __ masm.
93#define TEST(name) TEST_(ASM_##name)
94
95#define BUF_SIZE (4096)
96
armvixlad96eda2013-06-14 11:42:37 +010097#ifdef USE_SIMULATOR
armvixlad96eda2013-06-14 11:42:37 +010098// Run tests with the simulator.
armvixlc68cb642014-09-25 18:49:30 +010099
100#define SETUP() \
101 MacroAssembler masm(BUF_SIZE); \
102 SETUP_COMMON()
103
104#define SETUP_CUSTOM(size, pic) \
105 byte* buf = new byte[size + BUF_SIZE]; \
106 MacroAssembler masm(buf, size + BUF_SIZE, pic); \
107 SETUP_COMMON()
108
109#define SETUP_COMMON() \
armvixlad96eda2013-06-14 11:42:37 +0100110 Decoder decoder; \
armvixl330dc712014-11-25 10:38:32 +0000111 Simulator* simulator = Test::run_debugger() ? new Debugger(&decoder) \
112 : new Simulator(&decoder); \
113 simulator->set_coloured_trace(Test::coloured_trace()); \
114 simulator->set_instruction_stats(Test::instruction_stats()); \
armvixlad96eda2013-06-14 11:42:37 +0100115 RegisterDump core
116
armvixlc68cb642014-09-25 18:49:30 +0100117// This is a convenience macro to avoid creating a scope for every assembler
118// function called. It will still assert the buffer hasn't been exceeded.
119#define ALLOW_ASM() \
120 CodeBufferCheckScope guard(&masm, masm.BufferCapacity())
121
armvixlad96eda2013-06-14 11:42:37 +0100122#define START() \
123 masm.Reset(); \
124 simulator->ResetState(); \
125 __ PushCalleeSavedRegisters(); \
armvixl330dc712014-11-25 10:38:32 +0000126 if (Test::trace_reg()) { \
127 __ Trace(LOG_STATE, TRACE_ENABLE); \
armvixl578645f2013-08-15 17:21:42 +0100128 } \
armvixl330dc712014-11-25 10:38:32 +0000129 if (Test::trace_write()) { \
130 __ Trace(LOG_WRITE, TRACE_ENABLE); \
131 } \
132 if (Test::trace_sim()) { \
133 __ Trace(LOG_DISASM, TRACE_ENABLE); \
134 } \
135 if (Test::instruction_stats()) { \
armvixl578645f2013-08-15 17:21:42 +0100136 __ EnableInstrumentation(); \
armvixlad96eda2013-06-14 11:42:37 +0100137 }
138
139#define END() \
armvixl330dc712014-11-25 10:38:32 +0000140 if (Test::instruction_stats()) { \
armvixl578645f2013-08-15 17:21:42 +0100141 __ DisableInstrumentation(); \
142 } \
armvixl330dc712014-11-25 10:38:32 +0000143 __ Trace(LOG_ALL, TRACE_DISABLE); \
armvixlad96eda2013-06-14 11:42:37 +0100144 core.Dump(&masm); \
145 __ PopCalleeSavedRegisters(); \
146 __ Ret(); \
147 masm.FinalizeCode()
148
149#define RUN() \
armvixlc68cb642014-09-25 18:49:30 +0100150 simulator->RunFrom(masm.GetStartAddress<Instruction*>())
armvixlad96eda2013-06-14 11:42:37 +0100151
armvixlc68cb642014-09-25 18:49:30 +0100152#define TEARDOWN() TEARDOWN_COMMON()
153
154#define TEARDOWN_CUSTOM() \
155 delete[] buf; \
156 TEARDOWN_COMMON()
157
158#define TEARDOWN_COMMON() \
159 delete simulator;
armvixlad96eda2013-06-14 11:42:37 +0100160
161#else // ifdef USE_SIMULATOR.
162// Run the test on real hardware or models.
armvixlc68cb642014-09-25 18:49:30 +0100163#define SETUP() \
164 MacroAssembler masm(BUF_SIZE); \
165 SETUP_COMMON()
166
167#define SETUP_CUSTOM(size, pic) \
168 byte* buf = new byte[size + BUF_SIZE]; \
169 MacroAssembler masm(buf, size + BUF_SIZE, pic); \
170 SETUP_COMMON()
171
172#define SETUP_COMMON() \
armvixlad96eda2013-06-14 11:42:37 +0100173 RegisterDump core; \
174 CPU::SetUp()
175
armvixlc68cb642014-09-25 18:49:30 +0100176// This is a convenience macro to avoid creating a scope for every assembler
177// function called. It will still assert the buffer hasn't been exceeded.
178#define ALLOW_ASM() \
179 CodeBufferCheckScope guard(&masm, masm.BufferCapacity())
180
armvixlad96eda2013-06-14 11:42:37 +0100181#define START() \
182 masm.Reset(); \
183 __ PushCalleeSavedRegisters()
184
185#define END() \
186 core.Dump(&masm); \
187 __ PopCalleeSavedRegisters(); \
188 __ Ret(); \
189 masm.FinalizeCode()
190
191#define RUN() \
armvixlad96eda2013-06-14 11:42:37 +0100192 { \
armvixlc68cb642014-09-25 18:49:30 +0100193 byte* buffer_start = masm.GetStartAddress<byte*>(); \
194 size_t buffer_length = masm.CursorOffset(); \
armvixlad96eda2013-06-14 11:42:37 +0100195 void (*test_function)(void); \
armvixlc68cb642014-09-25 18:49:30 +0100196 \
197 CPU::EnsureIAndDCacheCoherency(buffer_start, buffer_length); \
198 VIXL_STATIC_ASSERT(sizeof(buffer_start) == sizeof(test_function)); \
199 memcpy(&test_function, &buffer_start, sizeof(buffer_start)); \
armvixlad96eda2013-06-14 11:42:37 +0100200 test_function(); \
201 }
202
armvixlc68cb642014-09-25 18:49:30 +0100203#define TEARDOWN()
204
205#define TEARDOWN_CUSTOM() \
206 delete[] buf; \
armvixlad96eda2013-06-14 11:42:37 +0100207
208#endif // ifdef USE_SIMULATOR.
209
210#define ASSERT_EQUAL_NZCV(expected) \
211 assert(EqualNzcv(expected, core.flags_nzcv()))
212
213#define ASSERT_EQUAL_REGISTERS(expected) \
214 assert(EqualRegisters(&expected, &core))
215
216#define ASSERT_EQUAL_32(expected, result) \
217 assert(Equal32(static_cast<uint32_t>(expected), &core, result))
218
219#define ASSERT_EQUAL_FP32(expected, result) \
220 assert(EqualFP32(expected, &core, result))
221
222#define ASSERT_EQUAL_64(expected, result) \
223 assert(Equal64(expected, &core, result))
224
225#define ASSERT_EQUAL_FP64(expected, result) \
226 assert(EqualFP64(expected, &core, result))
227
228#define ASSERT_LITERAL_POOL_SIZE(expected) \
229 assert((expected) == (__ LiteralPoolSize()))
230
231
232TEST(stack_ops) {
233 SETUP();
234
235 START();
236 // save sp.
237 __ Mov(x29, sp);
238
239 // Set the sp to a known value.
240 __ Mov(sp, 0x1004);
241 __ Mov(x0, sp);
242
243 // Add immediate to the sp, and move the result to a normal register.
armvixlb0c8ae22014-03-21 14:03:59 +0000244 __ Add(sp, sp, 0x50);
armvixlad96eda2013-06-14 11:42:37 +0100245 __ Mov(x1, sp);
246
247 // Add extended to the sp, and move the result to a normal register.
248 __ Mov(x17, 0xfff);
249 __ Add(sp, sp, Operand(x17, SXTB));
250 __ Mov(x2, sp);
251
252 // Create an sp using a logical instruction, and move to normal register.
armvixlb0c8ae22014-03-21 14:03:59 +0000253 __ Orr(sp, xzr, 0x1fff);
armvixlad96eda2013-06-14 11:42:37 +0100254 __ Mov(x3, sp);
255
256 // Write wsp using a logical instruction.
armvixlb0c8ae22014-03-21 14:03:59 +0000257 __ Orr(wsp, wzr, 0xfffffff8);
armvixlad96eda2013-06-14 11:42:37 +0100258 __ Mov(x4, sp);
259
260 // Write sp, and read back wsp.
armvixlb0c8ae22014-03-21 14:03:59 +0000261 __ Orr(sp, xzr, 0xfffffff8);
armvixlad96eda2013-06-14 11:42:37 +0100262 __ Mov(w5, wsp);
263
264 // restore sp.
265 __ Mov(sp, x29);
266 END();
267
268 RUN();
269
270 ASSERT_EQUAL_64(0x1004, x0);
271 ASSERT_EQUAL_64(0x1054, x1);
272 ASSERT_EQUAL_64(0x1053, x2);
273 ASSERT_EQUAL_64(0x1fff, x3);
274 ASSERT_EQUAL_64(0xfffffff8, x4);
275 ASSERT_EQUAL_64(0xfffffff8, x5);
276
277 TEARDOWN();
278}
279
280
281TEST(mvn) {
282 SETUP();
283
284 START();
285 __ Mvn(w0, 0xfff);
286 __ Mvn(x1, 0xfff);
287 __ Mvn(w2, Operand(w0, LSL, 1));
288 __ Mvn(x3, Operand(x1, LSL, 2));
289 __ Mvn(w4, Operand(w0, LSR, 3));
290 __ Mvn(x5, Operand(x1, LSR, 4));
291 __ Mvn(w6, Operand(w0, ASR, 11));
292 __ Mvn(x7, Operand(x1, ASR, 12));
293 __ Mvn(w8, Operand(w0, ROR, 13));
294 __ Mvn(x9, Operand(x1, ROR, 14));
295 __ Mvn(w10, Operand(w2, UXTB));
296 __ Mvn(x11, Operand(x2, SXTB, 1));
297 __ Mvn(w12, Operand(w2, UXTH, 2));
298 __ Mvn(x13, Operand(x2, SXTH, 3));
299 __ Mvn(x14, Operand(w2, UXTW, 4));
300 __ Mvn(x15, Operand(w2, SXTW, 4));
301 END();
302
303 RUN();
304
305 ASSERT_EQUAL_64(0xfffff000, x0);
armvixlb0c8ae22014-03-21 14:03:59 +0000306 ASSERT_EQUAL_64(0xfffffffffffff000, x1);
armvixlad96eda2013-06-14 11:42:37 +0100307 ASSERT_EQUAL_64(0x00001fff, x2);
armvixlb0c8ae22014-03-21 14:03:59 +0000308 ASSERT_EQUAL_64(0x0000000000003fff, x3);
armvixlad96eda2013-06-14 11:42:37 +0100309 ASSERT_EQUAL_64(0xe00001ff, x4);
armvixlb0c8ae22014-03-21 14:03:59 +0000310 ASSERT_EQUAL_64(0xf0000000000000ff, x5);
armvixlad96eda2013-06-14 11:42:37 +0100311 ASSERT_EQUAL_64(0x00000001, x6);
armvixlb0c8ae22014-03-21 14:03:59 +0000312 ASSERT_EQUAL_64(0x0000000000000000, x7);
armvixlad96eda2013-06-14 11:42:37 +0100313 ASSERT_EQUAL_64(0x7ff80000, x8);
armvixlb0c8ae22014-03-21 14:03:59 +0000314 ASSERT_EQUAL_64(0x3ffc000000000000, x9);
armvixlad96eda2013-06-14 11:42:37 +0100315 ASSERT_EQUAL_64(0xffffff00, x10);
armvixlb0c8ae22014-03-21 14:03:59 +0000316 ASSERT_EQUAL_64(0x0000000000000001, x11);
armvixlad96eda2013-06-14 11:42:37 +0100317 ASSERT_EQUAL_64(0xffff8003, x12);
armvixlb0c8ae22014-03-21 14:03:59 +0000318 ASSERT_EQUAL_64(0xffffffffffff0007, x13);
319 ASSERT_EQUAL_64(0xfffffffffffe000f, x14);
320 ASSERT_EQUAL_64(0xfffffffffffe000f, x15);
armvixlad96eda2013-06-14 11:42:37 +0100321
322 TEARDOWN();
323}
324
325
armvixlf37fdc02014-02-05 13:22:16 +0000326TEST(mov_imm_w) {
327 SETUP();
328
329 START();
armvixlb0c8ae22014-03-21 14:03:59 +0000330 __ Mov(w0, 0xffffffff);
331 __ Mov(w1, 0xffff1234);
332 __ Mov(w2, 0x1234ffff);
333 __ Mov(w3, 0x00000000);
334 __ Mov(w4, 0x00001234);
335 __ Mov(w5, 0x12340000);
336 __ Mov(w6, 0x12345678);
armvixl4a102ba2014-07-14 09:02:40 +0100337 __ Mov(w7, (int32_t)0x80000000);
338 __ Mov(w8, (int32_t)0xffff0000);
339 __ Mov(w9, kWMinInt);
armvixlf37fdc02014-02-05 13:22:16 +0000340 END();
341
342 RUN();
343
armvixlb0c8ae22014-03-21 14:03:59 +0000344 ASSERT_EQUAL_64(0xffffffff, x0);
345 ASSERT_EQUAL_64(0xffff1234, x1);
346 ASSERT_EQUAL_64(0x1234ffff, x2);
347 ASSERT_EQUAL_64(0x00000000, x3);
348 ASSERT_EQUAL_64(0x00001234, x4);
349 ASSERT_EQUAL_64(0x12340000, x5);
350 ASSERT_EQUAL_64(0x12345678, x6);
armvixl4a102ba2014-07-14 09:02:40 +0100351 ASSERT_EQUAL_64(0x80000000, x7);
352 ASSERT_EQUAL_64(0xffff0000, x8);
353 ASSERT_EQUAL_32(kWMinInt, w9);
armvixlf37fdc02014-02-05 13:22:16 +0000354
355 TEARDOWN();
356}
357
358
359TEST(mov_imm_x) {
360 SETUP();
361
362 START();
armvixlb0c8ae22014-03-21 14:03:59 +0000363 __ Mov(x0, 0xffffffffffffffff);
364 __ Mov(x1, 0xffffffffffff1234);
365 __ Mov(x2, 0xffffffff12345678);
366 __ Mov(x3, 0xffff1234ffff5678);
367 __ Mov(x4, 0x1234ffffffff5678);
368 __ Mov(x5, 0x1234ffff5678ffff);
369 __ Mov(x6, 0x12345678ffffffff);
370 __ Mov(x7, 0x1234ffffffffffff);
371 __ Mov(x8, 0x123456789abcffff);
372 __ Mov(x9, 0x12345678ffff9abc);
373 __ Mov(x10, 0x1234ffff56789abc);
374 __ Mov(x11, 0xffff123456789abc);
375 __ Mov(x12, 0x0000000000000000);
376 __ Mov(x13, 0x0000000000001234);
377 __ Mov(x14, 0x0000000012345678);
378 __ Mov(x15, 0x0000123400005678);
379 __ Mov(x18, 0x1234000000005678);
380 __ Mov(x19, 0x1234000056780000);
381 __ Mov(x20, 0x1234567800000000);
382 __ Mov(x21, 0x1234000000000000);
383 __ Mov(x22, 0x123456789abc0000);
384 __ Mov(x23, 0x1234567800009abc);
385 __ Mov(x24, 0x1234000056789abc);
386 __ Mov(x25, 0x0000123456789abc);
387 __ Mov(x26, 0x123456789abcdef0);
388 __ Mov(x27, 0xffff000000000001);
389 __ Mov(x28, 0x8000ffff00000000);
armvixlf37fdc02014-02-05 13:22:16 +0000390 END();
391
392 RUN();
393
armvixlb0c8ae22014-03-21 14:03:59 +0000394 ASSERT_EQUAL_64(0xffffffffffff1234, x1);
395 ASSERT_EQUAL_64(0xffffffff12345678, x2);
396 ASSERT_EQUAL_64(0xffff1234ffff5678, x3);
397 ASSERT_EQUAL_64(0x1234ffffffff5678, x4);
398 ASSERT_EQUAL_64(0x1234ffff5678ffff, x5);
399 ASSERT_EQUAL_64(0x12345678ffffffff, x6);
400 ASSERT_EQUAL_64(0x1234ffffffffffff, x7);
401 ASSERT_EQUAL_64(0x123456789abcffff, x8);
402 ASSERT_EQUAL_64(0x12345678ffff9abc, x9);
403 ASSERT_EQUAL_64(0x1234ffff56789abc, x10);
404 ASSERT_EQUAL_64(0xffff123456789abc, x11);
405 ASSERT_EQUAL_64(0x0000000000000000, x12);
406 ASSERT_EQUAL_64(0x0000000000001234, x13);
407 ASSERT_EQUAL_64(0x0000000012345678, x14);
408 ASSERT_EQUAL_64(0x0000123400005678, x15);
409 ASSERT_EQUAL_64(0x1234000000005678, x18);
410 ASSERT_EQUAL_64(0x1234000056780000, x19);
411 ASSERT_EQUAL_64(0x1234567800000000, x20);
412 ASSERT_EQUAL_64(0x1234000000000000, x21);
413 ASSERT_EQUAL_64(0x123456789abc0000, x22);
414 ASSERT_EQUAL_64(0x1234567800009abc, x23);
415 ASSERT_EQUAL_64(0x1234000056789abc, x24);
416 ASSERT_EQUAL_64(0x0000123456789abc, x25);
417 ASSERT_EQUAL_64(0x123456789abcdef0, x26);
418 ASSERT_EQUAL_64(0xffff000000000001, x27);
419 ASSERT_EQUAL_64(0x8000ffff00000000, x28);
armvixlf37fdc02014-02-05 13:22:16 +0000420
421
422 TEARDOWN();
423}
424
425
armvixlad96eda2013-06-14 11:42:37 +0100426TEST(mov) {
427 SETUP();
armvixlc68cb642014-09-25 18:49:30 +0100428 ALLOW_ASM();
armvixlad96eda2013-06-14 11:42:37 +0100429
430 START();
armvixlb0c8ae22014-03-21 14:03:59 +0000431 __ Mov(x0, 0xffffffffffffffff);
432 __ Mov(x1, 0xffffffffffffffff);
433 __ Mov(x2, 0xffffffffffffffff);
434 __ Mov(x3, 0xffffffffffffffff);
armvixlad96eda2013-06-14 11:42:37 +0100435
armvixlb0c8ae22014-03-21 14:03:59 +0000436 __ Mov(x0, 0x0123456789abcdef);
armvixlad96eda2013-06-14 11:42:37 +0100437
armvixlb0c8ae22014-03-21 14:03:59 +0000438 __ movz(x1, UINT64_C(0xabcd) << 16);
439 __ movk(x2, UINT64_C(0xabcd) << 32);
440 __ movn(x3, UINT64_C(0xabcd) << 48);
armvixlad96eda2013-06-14 11:42:37 +0100441
armvixlb0c8ae22014-03-21 14:03:59 +0000442 __ Mov(x4, 0x0123456789abcdef);
armvixlad96eda2013-06-14 11:42:37 +0100443 __ Mov(x5, x4);
444
445 __ Mov(w6, -1);
446
447 // Test that moves back to the same register have the desired effect. This
448 // is a no-op for X registers, and a truncation for W registers.
armvixlb0c8ae22014-03-21 14:03:59 +0000449 __ Mov(x7, 0x0123456789abcdef);
armvixlad96eda2013-06-14 11:42:37 +0100450 __ Mov(x7, x7);
armvixlb0c8ae22014-03-21 14:03:59 +0000451 __ Mov(x8, 0x0123456789abcdef);
armvixlad96eda2013-06-14 11:42:37 +0100452 __ Mov(w8, w8);
armvixlb0c8ae22014-03-21 14:03:59 +0000453 __ Mov(x9, 0x0123456789abcdef);
armvixlad96eda2013-06-14 11:42:37 +0100454 __ Mov(x9, Operand(x9));
armvixlb0c8ae22014-03-21 14:03:59 +0000455 __ Mov(x10, 0x0123456789abcdef);
armvixlad96eda2013-06-14 11:42:37 +0100456 __ Mov(w10, Operand(w10));
457
458 __ Mov(w11, 0xfff);
459 __ Mov(x12, 0xfff);
460 __ Mov(w13, Operand(w11, LSL, 1));
461 __ Mov(x14, Operand(x12, LSL, 2));
462 __ Mov(w15, Operand(w11, LSR, 3));
463 __ Mov(x18, Operand(x12, LSR, 4));
464 __ Mov(w19, Operand(w11, ASR, 11));
465 __ Mov(x20, Operand(x12, ASR, 12));
466 __ Mov(w21, Operand(w11, ROR, 13));
467 __ Mov(x22, Operand(x12, ROR, 14));
468 __ Mov(w23, Operand(w13, UXTB));
469 __ Mov(x24, Operand(x13, SXTB, 1));
470 __ Mov(w25, Operand(w13, UXTH, 2));
471 __ Mov(x26, Operand(x13, SXTH, 3));
472 __ Mov(x27, Operand(w13, UXTW, 4));
armvixlf37fdc02014-02-05 13:22:16 +0000473
armvixlb0c8ae22014-03-21 14:03:59 +0000474 __ Mov(x28, 0x0123456789abcdef);
armvixlf37fdc02014-02-05 13:22:16 +0000475 __ Mov(w28, w28, kDiscardForSameWReg);
armvixlad96eda2013-06-14 11:42:37 +0100476 END();
477
478 RUN();
479
armvixlb0c8ae22014-03-21 14:03:59 +0000480 ASSERT_EQUAL_64(0x0123456789abcdef, x0);
481 ASSERT_EQUAL_64(0x00000000abcd0000, x1);
482 ASSERT_EQUAL_64(0xffffabcdffffffff, x2);
483 ASSERT_EQUAL_64(0x5432ffffffffffff, x3);
armvixlad96eda2013-06-14 11:42:37 +0100484 ASSERT_EQUAL_64(x4, x5);
485 ASSERT_EQUAL_32(-1, w6);
armvixlb0c8ae22014-03-21 14:03:59 +0000486 ASSERT_EQUAL_64(0x0123456789abcdef, x7);
487 ASSERT_EQUAL_32(0x89abcdef, w8);
488 ASSERT_EQUAL_64(0x0123456789abcdef, x9);
489 ASSERT_EQUAL_32(0x89abcdef, w10);
armvixlad96eda2013-06-14 11:42:37 +0100490 ASSERT_EQUAL_64(0x00000fff, x11);
armvixlb0c8ae22014-03-21 14:03:59 +0000491 ASSERT_EQUAL_64(0x0000000000000fff, x12);
armvixlad96eda2013-06-14 11:42:37 +0100492 ASSERT_EQUAL_64(0x00001ffe, x13);
armvixlb0c8ae22014-03-21 14:03:59 +0000493 ASSERT_EQUAL_64(0x0000000000003ffc, x14);
armvixlad96eda2013-06-14 11:42:37 +0100494 ASSERT_EQUAL_64(0x000001ff, x15);
armvixlb0c8ae22014-03-21 14:03:59 +0000495 ASSERT_EQUAL_64(0x00000000000000ff, x18);
armvixlad96eda2013-06-14 11:42:37 +0100496 ASSERT_EQUAL_64(0x00000001, x19);
armvixlb0c8ae22014-03-21 14:03:59 +0000497 ASSERT_EQUAL_64(0x0000000000000000, x20);
armvixlad96eda2013-06-14 11:42:37 +0100498 ASSERT_EQUAL_64(0x7ff80000, x21);
armvixlb0c8ae22014-03-21 14:03:59 +0000499 ASSERT_EQUAL_64(0x3ffc000000000000, x22);
armvixlad96eda2013-06-14 11:42:37 +0100500 ASSERT_EQUAL_64(0x000000fe, x23);
armvixlb0c8ae22014-03-21 14:03:59 +0000501 ASSERT_EQUAL_64(0xfffffffffffffffc, x24);
armvixlad96eda2013-06-14 11:42:37 +0100502 ASSERT_EQUAL_64(0x00007ff8, x25);
armvixlb0c8ae22014-03-21 14:03:59 +0000503 ASSERT_EQUAL_64(0x000000000000fff0, x26);
504 ASSERT_EQUAL_64(0x000000000001ffe0, x27);
505 ASSERT_EQUAL_64(0x0123456789abcdef, x28);
armvixlad96eda2013-06-14 11:42:37 +0100506
507 TEARDOWN();
508}
509
510
511TEST(orr) {
512 SETUP();
513
514 START();
515 __ Mov(x0, 0xf0f0);
516 __ Mov(x1, 0xf00000ff);
517
518 __ Orr(x2, x0, Operand(x1));
519 __ Orr(w3, w0, Operand(w1, LSL, 28));
520 __ Orr(x4, x0, Operand(x1, LSL, 32));
521 __ Orr(x5, x0, Operand(x1, LSR, 4));
522 __ Orr(w6, w0, Operand(w1, ASR, 4));
523 __ Orr(x7, x0, Operand(x1, ASR, 4));
524 __ Orr(w8, w0, Operand(w1, ROR, 12));
525 __ Orr(x9, x0, Operand(x1, ROR, 12));
armvixlb0c8ae22014-03-21 14:03:59 +0000526 __ Orr(w10, w0, 0xf);
527 __ Orr(x11, x0, 0xf0000000f0000000);
armvixlad96eda2013-06-14 11:42:37 +0100528 END();
529
530 RUN();
531
armvixlb0c8ae22014-03-21 14:03:59 +0000532 ASSERT_EQUAL_64(0x00000000f000f0ff, x2);
armvixlad96eda2013-06-14 11:42:37 +0100533 ASSERT_EQUAL_64(0xf000f0f0, x3);
armvixlb0c8ae22014-03-21 14:03:59 +0000534 ASSERT_EQUAL_64(0xf00000ff0000f0f0, x4);
535 ASSERT_EQUAL_64(0x000000000f00f0ff, x5);
armvixlad96eda2013-06-14 11:42:37 +0100536 ASSERT_EQUAL_64(0xff00f0ff, x6);
armvixlb0c8ae22014-03-21 14:03:59 +0000537 ASSERT_EQUAL_64(0x000000000f00f0ff, x7);
armvixlad96eda2013-06-14 11:42:37 +0100538 ASSERT_EQUAL_64(0x0ffff0f0, x8);
armvixlb0c8ae22014-03-21 14:03:59 +0000539 ASSERT_EQUAL_64(0x0ff00000000ff0f0, x9);
540 ASSERT_EQUAL_64(0x0000f0ff, x10);
541 ASSERT_EQUAL_64(0xf0000000f000f0f0, x11);
armvixlad96eda2013-06-14 11:42:37 +0100542
543 TEARDOWN();
544}
545
546
547TEST(orr_extend) {
548 SETUP();
549
550 START();
551 __ Mov(x0, 1);
armvixlb0c8ae22014-03-21 14:03:59 +0000552 __ Mov(x1, 0x8000000080008080);
armvixlad96eda2013-06-14 11:42:37 +0100553 __ Orr(w6, w0, Operand(w1, UXTB));
554 __ Orr(x7, x0, Operand(x1, UXTH, 1));
555 __ Orr(w8, w0, Operand(w1, UXTW, 2));
556 __ Orr(x9, x0, Operand(x1, UXTX, 3));
557 __ Orr(w10, w0, Operand(w1, SXTB));
558 __ Orr(x11, x0, Operand(x1, SXTH, 1));
559 __ Orr(x12, x0, Operand(x1, SXTW, 2));
560 __ Orr(x13, x0, Operand(x1, SXTX, 3));
561 END();
562
563 RUN();
564
565 ASSERT_EQUAL_64(0x00000081, x6);
armvixlb0c8ae22014-03-21 14:03:59 +0000566 ASSERT_EQUAL_64(0x0000000000010101, x7);
armvixlad96eda2013-06-14 11:42:37 +0100567 ASSERT_EQUAL_64(0x00020201, x8);
armvixlb0c8ae22014-03-21 14:03:59 +0000568 ASSERT_EQUAL_64(0x0000000400040401, x9);
569 ASSERT_EQUAL_64(0xffffff81, x10);
570 ASSERT_EQUAL_64(0xffffffffffff0101, x11);
571 ASSERT_EQUAL_64(0xfffffffe00020201, x12);
572 ASSERT_EQUAL_64(0x0000000400040401, x13);
armvixlad96eda2013-06-14 11:42:37 +0100573
574 TEARDOWN();
575}
576
577
578TEST(bitwise_wide_imm) {
579 SETUP();
580
581 START();
582 __ Mov(x0, 0);
armvixlb0c8ae22014-03-21 14:03:59 +0000583 __ Mov(x1, 0xf0f0f0f0f0f0f0f0);
armvixlad96eda2013-06-14 11:42:37 +0100584
armvixlb0c8ae22014-03-21 14:03:59 +0000585 __ Orr(x10, x0, 0x1234567890abcdef);
586 __ Orr(w11, w1, 0x90abcdef);
armvixl4a102ba2014-07-14 09:02:40 +0100587
588 __ Orr(w12, w0, kWMinInt);
589 __ Eor(w13, w0, kWMinInt);
armvixlad96eda2013-06-14 11:42:37 +0100590 END();
591
592 RUN();
593
594 ASSERT_EQUAL_64(0, x0);
armvixlb0c8ae22014-03-21 14:03:59 +0000595 ASSERT_EQUAL_64(0xf0f0f0f0f0f0f0f0, x1);
596 ASSERT_EQUAL_64(0x1234567890abcdef, x10);
597 ASSERT_EQUAL_64(0x00000000f0fbfdff, x11);
armvixl4a102ba2014-07-14 09:02:40 +0100598 ASSERT_EQUAL_32(kWMinInt, w12);
599 ASSERT_EQUAL_32(kWMinInt, w13);
armvixlad96eda2013-06-14 11:42:37 +0100600
601 TEARDOWN();
602}
603
604
605TEST(orn) {
606 SETUP();
607
608 START();
609 __ Mov(x0, 0xf0f0);
610 __ Mov(x1, 0xf00000ff);
611
612 __ Orn(x2, x0, Operand(x1));
613 __ Orn(w3, w0, Operand(w1, LSL, 4));
614 __ Orn(x4, x0, Operand(x1, LSL, 4));
615 __ Orn(x5, x0, Operand(x1, LSR, 1));
616 __ Orn(w6, w0, Operand(w1, ASR, 1));
617 __ Orn(x7, x0, Operand(x1, ASR, 1));
618 __ Orn(w8, w0, Operand(w1, ROR, 16));
619 __ Orn(x9, x0, Operand(x1, ROR, 16));
armvixlb0c8ae22014-03-21 14:03:59 +0000620 __ Orn(w10, w0, 0x0000ffff);
621 __ Orn(x11, x0, 0x0000ffff0000ffff);
armvixlad96eda2013-06-14 11:42:37 +0100622 END();
623
624 RUN();
625
armvixlb0c8ae22014-03-21 14:03:59 +0000626 ASSERT_EQUAL_64(0xffffffff0ffffff0, x2);
armvixlad96eda2013-06-14 11:42:37 +0100627 ASSERT_EQUAL_64(0xfffff0ff, x3);
armvixlb0c8ae22014-03-21 14:03:59 +0000628 ASSERT_EQUAL_64(0xfffffff0fffff0ff, x4);
629 ASSERT_EQUAL_64(0xffffffff87fffff0, x5);
armvixlad96eda2013-06-14 11:42:37 +0100630 ASSERT_EQUAL_64(0x07fffff0, x6);
armvixlb0c8ae22014-03-21 14:03:59 +0000631 ASSERT_EQUAL_64(0xffffffff87fffff0, x7);
armvixlad96eda2013-06-14 11:42:37 +0100632 ASSERT_EQUAL_64(0xff00ffff, x8);
armvixlb0c8ae22014-03-21 14:03:59 +0000633 ASSERT_EQUAL_64(0xff00ffffffffffff, x9);
armvixlad96eda2013-06-14 11:42:37 +0100634 ASSERT_EQUAL_64(0xfffff0f0, x10);
armvixlb0c8ae22014-03-21 14:03:59 +0000635 ASSERT_EQUAL_64(0xffff0000fffff0f0, x11);
armvixlad96eda2013-06-14 11:42:37 +0100636
637 TEARDOWN();
638}
639
640
641TEST(orn_extend) {
642 SETUP();
643
644 START();
645 __ Mov(x0, 1);
armvixlb0c8ae22014-03-21 14:03:59 +0000646 __ Mov(x1, 0x8000000080008081);
armvixlad96eda2013-06-14 11:42:37 +0100647 __ Orn(w6, w0, Operand(w1, UXTB));
648 __ Orn(x7, x0, Operand(x1, UXTH, 1));
649 __ Orn(w8, w0, Operand(w1, UXTW, 2));
650 __ Orn(x9, x0, Operand(x1, UXTX, 3));
651 __ Orn(w10, w0, Operand(w1, SXTB));
652 __ Orn(x11, x0, Operand(x1, SXTH, 1));
653 __ Orn(x12, x0, Operand(x1, SXTW, 2));
654 __ Orn(x13, x0, Operand(x1, SXTX, 3));
655 END();
656
657 RUN();
658
659 ASSERT_EQUAL_64(0xffffff7f, x6);
armvixlb0c8ae22014-03-21 14:03:59 +0000660 ASSERT_EQUAL_64(0xfffffffffffefefd, x7);
armvixlad96eda2013-06-14 11:42:37 +0100661 ASSERT_EQUAL_64(0xfffdfdfb, x8);
armvixlb0c8ae22014-03-21 14:03:59 +0000662 ASSERT_EQUAL_64(0xfffffffbfffbfbf7, x9);
armvixlad96eda2013-06-14 11:42:37 +0100663 ASSERT_EQUAL_64(0x0000007f, x10);
armvixlb0c8ae22014-03-21 14:03:59 +0000664 ASSERT_EQUAL_64(0x000000000000fefd, x11);
665 ASSERT_EQUAL_64(0x00000001fffdfdfb, x12);
666 ASSERT_EQUAL_64(0xfffffffbfffbfbf7, x13);
armvixlad96eda2013-06-14 11:42:37 +0100667
668 TEARDOWN();
669}
670
671
672TEST(and_) {
673 SETUP();
674
675 START();
676 __ Mov(x0, 0xfff0);
677 __ Mov(x1, 0xf00000ff);
678
679 __ And(x2, x0, Operand(x1));
680 __ And(w3, w0, Operand(w1, LSL, 4));
681 __ And(x4, x0, Operand(x1, LSL, 4));
682 __ And(x5, x0, Operand(x1, LSR, 1));
683 __ And(w6, w0, Operand(w1, ASR, 20));
684 __ And(x7, x0, Operand(x1, ASR, 20));
685 __ And(w8, w0, Operand(w1, ROR, 28));
686 __ And(x9, x0, Operand(x1, ROR, 28));
687 __ And(w10, w0, Operand(0xff00));
688 __ And(x11, x0, Operand(0xff));
689 END();
690
691 RUN();
692
693 ASSERT_EQUAL_64(0x000000f0, x2);
694 ASSERT_EQUAL_64(0x00000ff0, x3);
695 ASSERT_EQUAL_64(0x00000ff0, x4);
696 ASSERT_EQUAL_64(0x00000070, x5);
697 ASSERT_EQUAL_64(0x0000ff00, x6);
698 ASSERT_EQUAL_64(0x00000f00, x7);
699 ASSERT_EQUAL_64(0x00000ff0, x8);
700 ASSERT_EQUAL_64(0x00000000, x9);
701 ASSERT_EQUAL_64(0x0000ff00, x10);
702 ASSERT_EQUAL_64(0x000000f0, x11);
703
704 TEARDOWN();
705}
706
707
708TEST(and_extend) {
709 SETUP();
710
711 START();
armvixlb0c8ae22014-03-21 14:03:59 +0000712 __ Mov(x0, 0xffffffffffffffff);
713 __ Mov(x1, 0x8000000080008081);
armvixlad96eda2013-06-14 11:42:37 +0100714 __ And(w6, w0, Operand(w1, UXTB));
715 __ And(x7, x0, Operand(x1, UXTH, 1));
716 __ And(w8, w0, Operand(w1, UXTW, 2));
717 __ And(x9, x0, Operand(x1, UXTX, 3));
718 __ And(w10, w0, Operand(w1, SXTB));
719 __ And(x11, x0, Operand(x1, SXTH, 1));
720 __ And(x12, x0, Operand(x1, SXTW, 2));
721 __ And(x13, x0, Operand(x1, SXTX, 3));
722 END();
723
724 RUN();
725
726 ASSERT_EQUAL_64(0x00000081, x6);
armvixlb0c8ae22014-03-21 14:03:59 +0000727 ASSERT_EQUAL_64(0x0000000000010102, x7);
armvixlad96eda2013-06-14 11:42:37 +0100728 ASSERT_EQUAL_64(0x00020204, x8);
armvixlb0c8ae22014-03-21 14:03:59 +0000729 ASSERT_EQUAL_64(0x0000000400040408, x9);
armvixlad96eda2013-06-14 11:42:37 +0100730 ASSERT_EQUAL_64(0xffffff81, x10);
armvixlb0c8ae22014-03-21 14:03:59 +0000731 ASSERT_EQUAL_64(0xffffffffffff0102, x11);
732 ASSERT_EQUAL_64(0xfffffffe00020204, x12);
733 ASSERT_EQUAL_64(0x0000000400040408, x13);
armvixlad96eda2013-06-14 11:42:37 +0100734
735 TEARDOWN();
736}
737
738
739TEST(ands) {
740 SETUP();
741
742 START();
743 __ Mov(x1, 0xf00000ff);
armvixlf37fdc02014-02-05 13:22:16 +0000744 __ Ands(w0, w1, Operand(w1));
armvixlad96eda2013-06-14 11:42:37 +0100745 END();
746
747 RUN();
748
749 ASSERT_EQUAL_NZCV(NFlag);
750 ASSERT_EQUAL_64(0xf00000ff, x0);
751
752 START();
753 __ Mov(x0, 0xfff0);
754 __ Mov(x1, 0xf00000ff);
armvixlf37fdc02014-02-05 13:22:16 +0000755 __ Ands(w0, w0, Operand(w1, LSR, 4));
armvixlad96eda2013-06-14 11:42:37 +0100756 END();
757
758 RUN();
759
760 ASSERT_EQUAL_NZCV(ZFlag);
761 ASSERT_EQUAL_64(0x00000000, x0);
762
763 START();
armvixlb0c8ae22014-03-21 14:03:59 +0000764 __ Mov(x0, 0x8000000000000000);
armvixlad96eda2013-06-14 11:42:37 +0100765 __ Mov(x1, 0x00000001);
armvixlf37fdc02014-02-05 13:22:16 +0000766 __ Ands(x0, x0, Operand(x1, ROR, 1));
armvixlad96eda2013-06-14 11:42:37 +0100767 END();
768
769 RUN();
770
771 ASSERT_EQUAL_NZCV(NFlag);
armvixlb0c8ae22014-03-21 14:03:59 +0000772 ASSERT_EQUAL_64(0x8000000000000000, x0);
armvixlad96eda2013-06-14 11:42:37 +0100773
774 START();
775 __ Mov(x0, 0xfff0);
armvixlf37fdc02014-02-05 13:22:16 +0000776 __ Ands(w0, w0, Operand(0xf));
armvixlad96eda2013-06-14 11:42:37 +0100777 END();
778
779 RUN();
780
781 ASSERT_EQUAL_NZCV(ZFlag);
782 ASSERT_EQUAL_64(0x00000000, x0);
783
784 START();
785 __ Mov(x0, 0xff000000);
armvixlf37fdc02014-02-05 13:22:16 +0000786 __ Ands(w0, w0, Operand(0x80000000));
armvixlad96eda2013-06-14 11:42:37 +0100787 END();
788
789 RUN();
790
791 ASSERT_EQUAL_NZCV(NFlag);
792 ASSERT_EQUAL_64(0x80000000, x0);
793
794 TEARDOWN();
795}
796
797
798TEST(bic) {
799 SETUP();
800
801 START();
802 __ Mov(x0, 0xfff0);
803 __ Mov(x1, 0xf00000ff);
804
805 __ Bic(x2, x0, Operand(x1));
806 __ Bic(w3, w0, Operand(w1, LSL, 4));
807 __ Bic(x4, x0, Operand(x1, LSL, 4));
808 __ Bic(x5, x0, Operand(x1, LSR, 1));
809 __ Bic(w6, w0, Operand(w1, ASR, 20));
810 __ Bic(x7, x0, Operand(x1, ASR, 20));
811 __ Bic(w8, w0, Operand(w1, ROR, 28));
812 __ Bic(x9, x0, Operand(x1, ROR, 24));
813 __ Bic(x10, x0, Operand(0x1f));
814 __ Bic(x11, x0, Operand(0x100));
815
816 // Test bic into sp when the constant cannot be encoded in the immediate
817 // field.
818 // Use x20 to preserve sp. We check for the result via x21 because the
819 // test infrastructure requires that sp be restored to its original value.
820 __ Mov(x20, sp);
821 __ Mov(x0, 0xffffff);
822 __ Bic(sp, x0, Operand(0xabcdef));
823 __ Mov(x21, sp);
824 __ Mov(sp, x20);
825 END();
826
827 RUN();
828
829 ASSERT_EQUAL_64(0x0000ff00, x2);
830 ASSERT_EQUAL_64(0x0000f000, x3);
831 ASSERT_EQUAL_64(0x0000f000, x4);
832 ASSERT_EQUAL_64(0x0000ff80, x5);
833 ASSERT_EQUAL_64(0x000000f0, x6);
834 ASSERT_EQUAL_64(0x0000f0f0, x7);
835 ASSERT_EQUAL_64(0x0000f000, x8);
836 ASSERT_EQUAL_64(0x0000ff00, x9);
837 ASSERT_EQUAL_64(0x0000ffe0, x10);
838 ASSERT_EQUAL_64(0x0000fef0, x11);
839
840 ASSERT_EQUAL_64(0x543210, x21);
841
842 TEARDOWN();
843}
844
845
846TEST(bic_extend) {
847 SETUP();
848
849 START();
armvixlb0c8ae22014-03-21 14:03:59 +0000850 __ Mov(x0, 0xffffffffffffffff);
851 __ Mov(x1, 0x8000000080008081);
armvixlad96eda2013-06-14 11:42:37 +0100852 __ Bic(w6, w0, Operand(w1, UXTB));
853 __ Bic(x7, x0, Operand(x1, UXTH, 1));
854 __ Bic(w8, w0, Operand(w1, UXTW, 2));
855 __ Bic(x9, x0, Operand(x1, UXTX, 3));
856 __ Bic(w10, w0, Operand(w1, SXTB));
857 __ Bic(x11, x0, Operand(x1, SXTH, 1));
858 __ Bic(x12, x0, Operand(x1, SXTW, 2));
859 __ Bic(x13, x0, Operand(x1, SXTX, 3));
860 END();
861
862 RUN();
863
864 ASSERT_EQUAL_64(0xffffff7e, x6);
armvixlb0c8ae22014-03-21 14:03:59 +0000865 ASSERT_EQUAL_64(0xfffffffffffefefd, x7);
armvixlad96eda2013-06-14 11:42:37 +0100866 ASSERT_EQUAL_64(0xfffdfdfb, x8);
armvixlb0c8ae22014-03-21 14:03:59 +0000867 ASSERT_EQUAL_64(0xfffffffbfffbfbf7, x9);
armvixlad96eda2013-06-14 11:42:37 +0100868 ASSERT_EQUAL_64(0x0000007e, x10);
armvixlb0c8ae22014-03-21 14:03:59 +0000869 ASSERT_EQUAL_64(0x000000000000fefd, x11);
870 ASSERT_EQUAL_64(0x00000001fffdfdfb, x12);
871 ASSERT_EQUAL_64(0xfffffffbfffbfbf7, x13);
armvixlad96eda2013-06-14 11:42:37 +0100872
873 TEARDOWN();
874}
875
876
877TEST(bics) {
878 SETUP();
879
880 START();
881 __ Mov(x1, 0xffff);
armvixlf37fdc02014-02-05 13:22:16 +0000882 __ Bics(w0, w1, Operand(w1));
armvixlad96eda2013-06-14 11:42:37 +0100883 END();
884
885 RUN();
886
887 ASSERT_EQUAL_NZCV(ZFlag);
888 ASSERT_EQUAL_64(0x00000000, x0);
889
890 START();
891 __ Mov(x0, 0xffffffff);
armvixlf37fdc02014-02-05 13:22:16 +0000892 __ Bics(w0, w0, Operand(w0, LSR, 1));
armvixlad96eda2013-06-14 11:42:37 +0100893 END();
894
895 RUN();
896
897 ASSERT_EQUAL_NZCV(NFlag);
898 ASSERT_EQUAL_64(0x80000000, x0);
899
900 START();
armvixlb0c8ae22014-03-21 14:03:59 +0000901 __ Mov(x0, 0x8000000000000000);
armvixlad96eda2013-06-14 11:42:37 +0100902 __ Mov(x1, 0x00000001);
armvixlf37fdc02014-02-05 13:22:16 +0000903 __ Bics(x0, x0, Operand(x1, ROR, 1));
armvixlad96eda2013-06-14 11:42:37 +0100904 END();
905
906 RUN();
907
908 ASSERT_EQUAL_NZCV(ZFlag);
909 ASSERT_EQUAL_64(0x00000000, x0);
910
911 START();
armvixlb0c8ae22014-03-21 14:03:59 +0000912 __ Mov(x0, 0xffffffffffffffff);
913 __ Bics(x0, x0, 0x7fffffffffffffff);
armvixlad96eda2013-06-14 11:42:37 +0100914 END();
915
916 RUN();
917
918 ASSERT_EQUAL_NZCV(NFlag);
armvixlb0c8ae22014-03-21 14:03:59 +0000919 ASSERT_EQUAL_64(0x8000000000000000, x0);
armvixlad96eda2013-06-14 11:42:37 +0100920
921 START();
922 __ Mov(w0, 0xffff0000);
armvixlb0c8ae22014-03-21 14:03:59 +0000923 __ Bics(w0, w0, 0xfffffff0);
armvixlad96eda2013-06-14 11:42:37 +0100924 END();
925
926 RUN();
927
928 ASSERT_EQUAL_NZCV(ZFlag);
929 ASSERT_EQUAL_64(0x00000000, x0);
930
931 TEARDOWN();
932}
933
934
935TEST(eor) {
936 SETUP();
937
938 START();
939 __ Mov(x0, 0xfff0);
940 __ Mov(x1, 0xf00000ff);
941
942 __ Eor(x2, x0, Operand(x1));
943 __ Eor(w3, w0, Operand(w1, LSL, 4));
944 __ Eor(x4, x0, Operand(x1, LSL, 4));
945 __ Eor(x5, x0, Operand(x1, LSR, 1));
946 __ Eor(w6, w0, Operand(w1, ASR, 20));
947 __ Eor(x7, x0, Operand(x1, ASR, 20));
948 __ Eor(w8, w0, Operand(w1, ROR, 28));
949 __ Eor(x9, x0, Operand(x1, ROR, 28));
armvixlb0c8ae22014-03-21 14:03:59 +0000950 __ Eor(w10, w0, 0xff00ff00);
951 __ Eor(x11, x0, 0xff00ff00ff00ff00);
armvixlad96eda2013-06-14 11:42:37 +0100952 END();
953
954 RUN();
955
armvixlb0c8ae22014-03-21 14:03:59 +0000956 ASSERT_EQUAL_64(0x00000000f000ff0f, x2);
armvixlad96eda2013-06-14 11:42:37 +0100957 ASSERT_EQUAL_64(0x0000f000, x3);
armvixlb0c8ae22014-03-21 14:03:59 +0000958 ASSERT_EQUAL_64(0x0000000f0000f000, x4);
959 ASSERT_EQUAL_64(0x000000007800ff8f, x5);
armvixlad96eda2013-06-14 11:42:37 +0100960 ASSERT_EQUAL_64(0xffff00f0, x6);
armvixlb0c8ae22014-03-21 14:03:59 +0000961 ASSERT_EQUAL_64(0x000000000000f0f0, x7);
armvixlad96eda2013-06-14 11:42:37 +0100962 ASSERT_EQUAL_64(0x0000f00f, x8);
armvixlb0c8ae22014-03-21 14:03:59 +0000963 ASSERT_EQUAL_64(0x00000ff00000ffff, x9);
armvixlad96eda2013-06-14 11:42:37 +0100964 ASSERT_EQUAL_64(0xff0000f0, x10);
armvixlb0c8ae22014-03-21 14:03:59 +0000965 ASSERT_EQUAL_64(0xff00ff00ff0000f0, x11);
armvixlad96eda2013-06-14 11:42:37 +0100966
967 TEARDOWN();
968}
969
970TEST(eor_extend) {
971 SETUP();
972
973 START();
armvixlb0c8ae22014-03-21 14:03:59 +0000974 __ Mov(x0, 0x1111111111111111);
975 __ Mov(x1, 0x8000000080008081);
armvixlad96eda2013-06-14 11:42:37 +0100976 __ Eor(w6, w0, Operand(w1, UXTB));
977 __ Eor(x7, x0, Operand(x1, UXTH, 1));
978 __ Eor(w8, w0, Operand(w1, UXTW, 2));
979 __ Eor(x9, x0, Operand(x1, UXTX, 3));
980 __ Eor(w10, w0, Operand(w1, SXTB));
981 __ Eor(x11, x0, Operand(x1, SXTH, 1));
982 __ Eor(x12, x0, Operand(x1, SXTW, 2));
983 __ Eor(x13, x0, Operand(x1, SXTX, 3));
984 END();
985
986 RUN();
987
988 ASSERT_EQUAL_64(0x11111190, x6);
armvixlb0c8ae22014-03-21 14:03:59 +0000989 ASSERT_EQUAL_64(0x1111111111101013, x7);
armvixlad96eda2013-06-14 11:42:37 +0100990 ASSERT_EQUAL_64(0x11131315, x8);
armvixlb0c8ae22014-03-21 14:03:59 +0000991 ASSERT_EQUAL_64(0x1111111511151519, x9);
armvixlad96eda2013-06-14 11:42:37 +0100992 ASSERT_EQUAL_64(0xeeeeee90, x10);
armvixlb0c8ae22014-03-21 14:03:59 +0000993 ASSERT_EQUAL_64(0xeeeeeeeeeeee1013, x11);
994 ASSERT_EQUAL_64(0xeeeeeeef11131315, x12);
995 ASSERT_EQUAL_64(0x1111111511151519, x13);
armvixlad96eda2013-06-14 11:42:37 +0100996
997 TEARDOWN();
998}
999
1000
1001TEST(eon) {
1002 SETUP();
1003
1004 START();
1005 __ Mov(x0, 0xfff0);
1006 __ Mov(x1, 0xf00000ff);
1007
1008 __ Eon(x2, x0, Operand(x1));
1009 __ Eon(w3, w0, Operand(w1, LSL, 4));
1010 __ Eon(x4, x0, Operand(x1, LSL, 4));
1011 __ Eon(x5, x0, Operand(x1, LSR, 1));
1012 __ Eon(w6, w0, Operand(w1, ASR, 20));
1013 __ Eon(x7, x0, Operand(x1, ASR, 20));
1014 __ Eon(w8, w0, Operand(w1, ROR, 28));
1015 __ Eon(x9, x0, Operand(x1, ROR, 28));
armvixlb0c8ae22014-03-21 14:03:59 +00001016 __ Eon(w10, w0, 0x03c003c0);
1017 __ Eon(x11, x0, 0x0000100000001000);
armvixlad96eda2013-06-14 11:42:37 +01001018 END();
1019
1020 RUN();
1021
armvixlb0c8ae22014-03-21 14:03:59 +00001022 ASSERT_EQUAL_64(0xffffffff0fff00f0, x2);
armvixlad96eda2013-06-14 11:42:37 +01001023 ASSERT_EQUAL_64(0xffff0fff, x3);
armvixlb0c8ae22014-03-21 14:03:59 +00001024 ASSERT_EQUAL_64(0xfffffff0ffff0fff, x4);
1025 ASSERT_EQUAL_64(0xffffffff87ff0070, x5);
armvixlad96eda2013-06-14 11:42:37 +01001026 ASSERT_EQUAL_64(0x0000ff0f, x6);
armvixlb0c8ae22014-03-21 14:03:59 +00001027 ASSERT_EQUAL_64(0xffffffffffff0f0f, x7);
armvixlad96eda2013-06-14 11:42:37 +01001028 ASSERT_EQUAL_64(0xffff0ff0, x8);
armvixlb0c8ae22014-03-21 14:03:59 +00001029 ASSERT_EQUAL_64(0xfffff00fffff0000, x9);
armvixlad96eda2013-06-14 11:42:37 +01001030 ASSERT_EQUAL_64(0xfc3f03cf, x10);
armvixlb0c8ae22014-03-21 14:03:59 +00001031 ASSERT_EQUAL_64(0xffffefffffff100f, x11);
armvixlad96eda2013-06-14 11:42:37 +01001032
1033 TEARDOWN();
1034}
1035
1036
1037TEST(eon_extend) {
1038 SETUP();
1039
1040 START();
armvixlb0c8ae22014-03-21 14:03:59 +00001041 __ Mov(x0, 0x1111111111111111);
1042 __ Mov(x1, 0x8000000080008081);
armvixlad96eda2013-06-14 11:42:37 +01001043 __ Eon(w6, w0, Operand(w1, UXTB));
1044 __ Eon(x7, x0, Operand(x1, UXTH, 1));
1045 __ Eon(w8, w0, Operand(w1, UXTW, 2));
1046 __ Eon(x9, x0, Operand(x1, UXTX, 3));
1047 __ Eon(w10, w0, Operand(w1, SXTB));
1048 __ Eon(x11, x0, Operand(x1, SXTH, 1));
1049 __ Eon(x12, x0, Operand(x1, SXTW, 2));
1050 __ Eon(x13, x0, Operand(x1, SXTX, 3));
1051 END();
1052
1053 RUN();
1054
1055 ASSERT_EQUAL_64(0xeeeeee6f, x6);
armvixlb0c8ae22014-03-21 14:03:59 +00001056 ASSERT_EQUAL_64(0xeeeeeeeeeeefefec, x7);
armvixlad96eda2013-06-14 11:42:37 +01001057 ASSERT_EQUAL_64(0xeeececea, x8);
armvixlb0c8ae22014-03-21 14:03:59 +00001058 ASSERT_EQUAL_64(0xeeeeeeeaeeeaeae6, x9);
armvixlad96eda2013-06-14 11:42:37 +01001059 ASSERT_EQUAL_64(0x1111116f, x10);
armvixlb0c8ae22014-03-21 14:03:59 +00001060 ASSERT_EQUAL_64(0x111111111111efec, x11);
1061 ASSERT_EQUAL_64(0x11111110eeececea, x12);
1062 ASSERT_EQUAL_64(0xeeeeeeeaeeeaeae6, x13);
armvixlad96eda2013-06-14 11:42:37 +01001063
1064 TEARDOWN();
1065}
1066
1067
1068TEST(mul) {
1069 SETUP();
1070
1071 START();
1072 __ Mov(x16, 0);
1073 __ Mov(x17, 1);
1074 __ Mov(x18, 0xffffffff);
armvixlb0c8ae22014-03-21 14:03:59 +00001075 __ Mov(x19, 0xffffffffffffffff);
armvixlad96eda2013-06-14 11:42:37 +01001076
1077 __ Mul(w0, w16, w16);
1078 __ Mul(w1, w16, w17);
1079 __ Mul(w2, w17, w18);
1080 __ Mul(w3, w18, w19);
1081 __ Mul(x4, x16, x16);
1082 __ Mul(x5, x17, x18);
1083 __ Mul(x6, x18, x19);
1084 __ Mul(x7, x19, x19);
1085 __ Smull(x8, w17, w18);
1086 __ Smull(x9, w18, w18);
1087 __ Smull(x10, w19, w19);
1088 __ Mneg(w11, w16, w16);
1089 __ Mneg(w12, w16, w17);
1090 __ Mneg(w13, w17, w18);
1091 __ Mneg(w14, w18, w19);
1092 __ Mneg(x20, x16, x16);
1093 __ Mneg(x21, x17, x18);
1094 __ Mneg(x22, x18, x19);
1095 __ Mneg(x23, x19, x19);
1096 END();
1097
1098 RUN();
1099
1100 ASSERT_EQUAL_64(0, x0);
1101 ASSERT_EQUAL_64(0, x1);
1102 ASSERT_EQUAL_64(0xffffffff, x2);
1103 ASSERT_EQUAL_64(1, x3);
1104 ASSERT_EQUAL_64(0, x4);
1105 ASSERT_EQUAL_64(0xffffffff, x5);
armvixlb0c8ae22014-03-21 14:03:59 +00001106 ASSERT_EQUAL_64(0xffffffff00000001, x6);
armvixlad96eda2013-06-14 11:42:37 +01001107 ASSERT_EQUAL_64(1, x7);
armvixlb0c8ae22014-03-21 14:03:59 +00001108 ASSERT_EQUAL_64(0xffffffffffffffff, x8);
armvixlad96eda2013-06-14 11:42:37 +01001109 ASSERT_EQUAL_64(1, x9);
1110 ASSERT_EQUAL_64(1, x10);
1111 ASSERT_EQUAL_64(0, x11);
1112 ASSERT_EQUAL_64(0, x12);
1113 ASSERT_EQUAL_64(1, x13);
1114 ASSERT_EQUAL_64(0xffffffff, x14);
1115 ASSERT_EQUAL_64(0, x20);
armvixlb0c8ae22014-03-21 14:03:59 +00001116 ASSERT_EQUAL_64(0xffffffff00000001, x21);
armvixlad96eda2013-06-14 11:42:37 +01001117 ASSERT_EQUAL_64(0xffffffff, x22);
armvixlb0c8ae22014-03-21 14:03:59 +00001118 ASSERT_EQUAL_64(0xffffffffffffffff, x23);
armvixlad96eda2013-06-14 11:42:37 +01001119
1120 TEARDOWN();
1121}
1122
1123
armvixlf37fdc02014-02-05 13:22:16 +00001124static void SmullHelper(int64_t expected, int64_t a, int64_t b) {
1125 SETUP();
1126 START();
1127 __ Mov(w0, a);
1128 __ Mov(w1, b);
1129 __ Smull(x2, w0, w1);
1130 END();
1131 RUN();
1132 ASSERT_EQUAL_64(expected, x2);
1133 TEARDOWN();
1134}
1135
1136
1137TEST(smull) {
1138 SmullHelper(0, 0, 0);
1139 SmullHelper(1, 1, 1);
1140 SmullHelper(-1, -1, 1);
1141 SmullHelper(1, -1, -1);
1142 SmullHelper(0xffffffff80000000, 0x80000000, 1);
1143 SmullHelper(0x0000000080000000, 0x00010000, 0x00008000);
1144}
1145
1146
armvixlad96eda2013-06-14 11:42:37 +01001147TEST(madd) {
1148 SETUP();
1149
1150 START();
1151 __ Mov(x16, 0);
1152 __ Mov(x17, 1);
1153 __ Mov(x18, 0xffffffff);
armvixlb0c8ae22014-03-21 14:03:59 +00001154 __ Mov(x19, 0xffffffffffffffff);
armvixlad96eda2013-06-14 11:42:37 +01001155
1156 __ Madd(w0, w16, w16, w16);
1157 __ Madd(w1, w16, w16, w17);
1158 __ Madd(w2, w16, w16, w18);
1159 __ Madd(w3, w16, w16, w19);
1160 __ Madd(w4, w16, w17, w17);
1161 __ Madd(w5, w17, w17, w18);
1162 __ Madd(w6, w17, w17, w19);
1163 __ Madd(w7, w17, w18, w16);
1164 __ Madd(w8, w17, w18, w18);
1165 __ Madd(w9, w18, w18, w17);
1166 __ Madd(w10, w18, w19, w18);
1167 __ Madd(w11, w19, w19, w19);
1168
1169 __ Madd(x12, x16, x16, x16);
1170 __ Madd(x13, x16, x16, x17);
1171 __ Madd(x14, x16, x16, x18);
1172 __ Madd(x15, x16, x16, x19);
1173 __ Madd(x20, x16, x17, x17);
1174 __ Madd(x21, x17, x17, x18);
1175 __ Madd(x22, x17, x17, x19);
1176 __ Madd(x23, x17, x18, x16);
1177 __ Madd(x24, x17, x18, x18);
1178 __ Madd(x25, x18, x18, x17);
1179 __ Madd(x26, x18, x19, x18);
1180 __ Madd(x27, x19, x19, x19);
1181
1182 END();
1183
1184 RUN();
1185
1186 ASSERT_EQUAL_64(0, x0);
1187 ASSERT_EQUAL_64(1, x1);
1188 ASSERT_EQUAL_64(0xffffffff, x2);
1189 ASSERT_EQUAL_64(0xffffffff, x3);
1190 ASSERT_EQUAL_64(1, x4);
1191 ASSERT_EQUAL_64(0, x5);
1192 ASSERT_EQUAL_64(0, x6);
1193 ASSERT_EQUAL_64(0xffffffff, x7);
1194 ASSERT_EQUAL_64(0xfffffffe, x8);
1195 ASSERT_EQUAL_64(2, x9);
1196 ASSERT_EQUAL_64(0, x10);
1197 ASSERT_EQUAL_64(0, x11);
1198
1199 ASSERT_EQUAL_64(0, x12);
1200 ASSERT_EQUAL_64(1, x13);
armvixlb0c8ae22014-03-21 14:03:59 +00001201 ASSERT_EQUAL_64(0x00000000ffffffff, x14);
armvixlad96eda2013-06-14 11:42:37 +01001202 ASSERT_EQUAL_64(0xffffffffffffffff, x15);
1203 ASSERT_EQUAL_64(1, x20);
armvixlb0c8ae22014-03-21 14:03:59 +00001204 ASSERT_EQUAL_64(0x0000000100000000, x21);
armvixlad96eda2013-06-14 11:42:37 +01001205 ASSERT_EQUAL_64(0, x22);
armvixlb0c8ae22014-03-21 14:03:59 +00001206 ASSERT_EQUAL_64(0x00000000ffffffff, x23);
1207 ASSERT_EQUAL_64(0x00000001fffffffe, x24);
1208 ASSERT_EQUAL_64(0xfffffffe00000002, x25);
armvixlad96eda2013-06-14 11:42:37 +01001209 ASSERT_EQUAL_64(0, x26);
1210 ASSERT_EQUAL_64(0, x27);
1211
1212 TEARDOWN();
1213}
1214
1215
1216TEST(msub) {
1217 SETUP();
1218
1219 START();
1220 __ Mov(x16, 0);
1221 __ Mov(x17, 1);
1222 __ Mov(x18, 0xffffffff);
armvixlb0c8ae22014-03-21 14:03:59 +00001223 __ Mov(x19, 0xffffffffffffffff);
armvixlad96eda2013-06-14 11:42:37 +01001224
1225 __ Msub(w0, w16, w16, w16);
1226 __ Msub(w1, w16, w16, w17);
1227 __ Msub(w2, w16, w16, w18);
1228 __ Msub(w3, w16, w16, w19);
1229 __ Msub(w4, w16, w17, w17);
1230 __ Msub(w5, w17, w17, w18);
1231 __ Msub(w6, w17, w17, w19);
1232 __ Msub(w7, w17, w18, w16);
1233 __ Msub(w8, w17, w18, w18);
1234 __ Msub(w9, w18, w18, w17);
1235 __ Msub(w10, w18, w19, w18);
1236 __ Msub(w11, w19, w19, w19);
1237
1238 __ Msub(x12, x16, x16, x16);
1239 __ Msub(x13, x16, x16, x17);
1240 __ Msub(x14, x16, x16, x18);
1241 __ Msub(x15, x16, x16, x19);
1242 __ Msub(x20, x16, x17, x17);
1243 __ Msub(x21, x17, x17, x18);
1244 __ Msub(x22, x17, x17, x19);
1245 __ Msub(x23, x17, x18, x16);
1246 __ Msub(x24, x17, x18, x18);
1247 __ Msub(x25, x18, x18, x17);
1248 __ Msub(x26, x18, x19, x18);
1249 __ Msub(x27, x19, x19, x19);
1250
1251 END();
1252
1253 RUN();
1254
1255 ASSERT_EQUAL_64(0, x0);
1256 ASSERT_EQUAL_64(1, x1);
1257 ASSERT_EQUAL_64(0xffffffff, x2);
1258 ASSERT_EQUAL_64(0xffffffff, x3);
1259 ASSERT_EQUAL_64(1, x4);
1260 ASSERT_EQUAL_64(0xfffffffe, x5);
1261 ASSERT_EQUAL_64(0xfffffffe, x6);
1262 ASSERT_EQUAL_64(1, x7);
1263 ASSERT_EQUAL_64(0, x8);
1264 ASSERT_EQUAL_64(0, x9);
1265 ASSERT_EQUAL_64(0xfffffffe, x10);
1266 ASSERT_EQUAL_64(0xfffffffe, x11);
1267
1268 ASSERT_EQUAL_64(0, x12);
1269 ASSERT_EQUAL_64(1, x13);
armvixlb0c8ae22014-03-21 14:03:59 +00001270 ASSERT_EQUAL_64(0x00000000ffffffff, x14);
1271 ASSERT_EQUAL_64(0xffffffffffffffff, x15);
armvixlad96eda2013-06-14 11:42:37 +01001272 ASSERT_EQUAL_64(1, x20);
armvixlb0c8ae22014-03-21 14:03:59 +00001273 ASSERT_EQUAL_64(0x00000000fffffffe, x21);
1274 ASSERT_EQUAL_64(0xfffffffffffffffe, x22);
1275 ASSERT_EQUAL_64(0xffffffff00000001, x23);
armvixlad96eda2013-06-14 11:42:37 +01001276 ASSERT_EQUAL_64(0, x24);
armvixlb0c8ae22014-03-21 14:03:59 +00001277 ASSERT_EQUAL_64(0x0000000200000000, x25);
1278 ASSERT_EQUAL_64(0x00000001fffffffe, x26);
1279 ASSERT_EQUAL_64(0xfffffffffffffffe, x27);
armvixlad96eda2013-06-14 11:42:37 +01001280
1281 TEARDOWN();
1282}
1283
1284
1285TEST(smulh) {
1286 SETUP();
1287
1288 START();
1289 __ Mov(x20, 0);
1290 __ Mov(x21, 1);
armvixlb0c8ae22014-03-21 14:03:59 +00001291 __ Mov(x22, 0x0000000100000000);
1292 __ Mov(x23, 0x0000000012345678);
1293 __ Mov(x24, 0x0123456789abcdef);
1294 __ Mov(x25, 0x0000000200000000);
1295 __ Mov(x26, 0x8000000000000000);
1296 __ Mov(x27, 0xffffffffffffffff);
1297 __ Mov(x28, 0x5555555555555555);
1298 __ Mov(x29, 0xaaaaaaaaaaaaaaaa);
armvixlad96eda2013-06-14 11:42:37 +01001299
1300 __ Smulh(x0, x20, x24);
1301 __ Smulh(x1, x21, x24);
1302 __ Smulh(x2, x22, x23);
1303 __ Smulh(x3, x22, x24);
1304 __ Smulh(x4, x24, x25);
1305 __ Smulh(x5, x23, x27);
1306 __ Smulh(x6, x26, x26);
1307 __ Smulh(x7, x26, x27);
1308 __ Smulh(x8, x27, x27);
1309 __ Smulh(x9, x28, x28);
1310 __ Smulh(x10, x28, x29);
1311 __ Smulh(x11, x29, x29);
1312 END();
1313
1314 RUN();
1315
1316 ASSERT_EQUAL_64(0, x0);
1317 ASSERT_EQUAL_64(0, x1);
1318 ASSERT_EQUAL_64(0, x2);
armvixlb0c8ae22014-03-21 14:03:59 +00001319 ASSERT_EQUAL_64(0x0000000001234567, x3);
1320 ASSERT_EQUAL_64(0x0000000002468acf, x4);
1321 ASSERT_EQUAL_64(0xffffffffffffffff, x5);
1322 ASSERT_EQUAL_64(0x4000000000000000, x6);
armvixlad96eda2013-06-14 11:42:37 +01001323 ASSERT_EQUAL_64(0, x7);
1324 ASSERT_EQUAL_64(0, x8);
armvixlb0c8ae22014-03-21 14:03:59 +00001325 ASSERT_EQUAL_64(0x1c71c71c71c71c71, x9);
1326 ASSERT_EQUAL_64(0xe38e38e38e38e38e, x10);
1327 ASSERT_EQUAL_64(0x1c71c71c71c71c72, x11);
armvixlad96eda2013-06-14 11:42:37 +01001328
1329 TEARDOWN();
1330}
1331
1332
1333TEST(smaddl_umaddl) {
1334 SETUP();
1335
1336 START();
1337 __ Mov(x17, 1);
armvixlb0c8ae22014-03-21 14:03:59 +00001338 __ Mov(x18, 0x00000000ffffffff);
1339 __ Mov(x19, 0xffffffffffffffff);
armvixlad96eda2013-06-14 11:42:37 +01001340 __ Mov(x20, 4);
armvixlb0c8ae22014-03-21 14:03:59 +00001341 __ Mov(x21, 0x0000000200000000);
armvixlad96eda2013-06-14 11:42:37 +01001342
1343 __ Smaddl(x9, w17, w18, x20);
1344 __ Smaddl(x10, w18, w18, x20);
1345 __ Smaddl(x11, w19, w19, x20);
1346 __ Smaddl(x12, w19, w19, x21);
1347 __ Umaddl(x13, w17, w18, x20);
1348 __ Umaddl(x14, w18, w18, x20);
1349 __ Umaddl(x15, w19, w19, x20);
1350 __ Umaddl(x22, w19, w19, x21);
1351 END();
1352
1353 RUN();
1354
1355 ASSERT_EQUAL_64(3, x9);
1356 ASSERT_EQUAL_64(5, x10);
1357 ASSERT_EQUAL_64(5, x11);
armvixlb0c8ae22014-03-21 14:03:59 +00001358 ASSERT_EQUAL_64(0x0000000200000001, x12);
1359 ASSERT_EQUAL_64(0x0000000100000003, x13);
1360 ASSERT_EQUAL_64(0xfffffffe00000005, x14);
1361 ASSERT_EQUAL_64(0xfffffffe00000005, x15);
1362 ASSERT_EQUAL_64(1, x22);
armvixlad96eda2013-06-14 11:42:37 +01001363
1364 TEARDOWN();
1365}
1366
1367
1368TEST(smsubl_umsubl) {
1369 SETUP();
1370
1371 START();
1372 __ Mov(x17, 1);
armvixlb0c8ae22014-03-21 14:03:59 +00001373 __ Mov(x18, 0x00000000ffffffff);
1374 __ Mov(x19, 0xffffffffffffffff);
armvixlad96eda2013-06-14 11:42:37 +01001375 __ Mov(x20, 4);
armvixlb0c8ae22014-03-21 14:03:59 +00001376 __ Mov(x21, 0x0000000200000000);
armvixlad96eda2013-06-14 11:42:37 +01001377
1378 __ Smsubl(x9, w17, w18, x20);
1379 __ Smsubl(x10, w18, w18, x20);
1380 __ Smsubl(x11, w19, w19, x20);
1381 __ Smsubl(x12, w19, w19, x21);
1382 __ Umsubl(x13, w17, w18, x20);
1383 __ Umsubl(x14, w18, w18, x20);
1384 __ Umsubl(x15, w19, w19, x20);
1385 __ Umsubl(x22, w19, w19, x21);
1386 END();
1387
1388 RUN();
1389
1390 ASSERT_EQUAL_64(5, x9);
1391 ASSERT_EQUAL_64(3, x10);
1392 ASSERT_EQUAL_64(3, x11);
armvixlb0c8ae22014-03-21 14:03:59 +00001393 ASSERT_EQUAL_64(0x00000001ffffffff, x12);
1394 ASSERT_EQUAL_64(0xffffffff00000005, x13);
1395 ASSERT_EQUAL_64(0x0000000200000003, x14);
1396 ASSERT_EQUAL_64(0x0000000200000003, x15);
1397 ASSERT_EQUAL_64(0x00000003ffffffff, x22);
armvixlad96eda2013-06-14 11:42:37 +01001398
1399 TEARDOWN();
1400}
1401
1402
1403TEST(div) {
1404 SETUP();
1405
1406 START();
1407 __ Mov(x16, 1);
1408 __ Mov(x17, 0xffffffff);
armvixlb0c8ae22014-03-21 14:03:59 +00001409 __ Mov(x18, 0xffffffffffffffff);
armvixlad96eda2013-06-14 11:42:37 +01001410 __ Mov(x19, 0x80000000);
armvixlb0c8ae22014-03-21 14:03:59 +00001411 __ Mov(x20, 0x8000000000000000);
armvixlad96eda2013-06-14 11:42:37 +01001412 __ Mov(x21, 2);
1413
1414 __ Udiv(w0, w16, w16);
1415 __ Udiv(w1, w17, w16);
1416 __ Sdiv(w2, w16, w16);
1417 __ Sdiv(w3, w16, w17);
1418 __ Sdiv(w4, w17, w18);
1419
1420 __ Udiv(x5, x16, x16);
1421 __ Udiv(x6, x17, x18);
1422 __ Sdiv(x7, x16, x16);
1423 __ Sdiv(x8, x16, x17);
1424 __ Sdiv(x9, x17, x18);
1425
1426 __ Udiv(w10, w19, w21);
1427 __ Sdiv(w11, w19, w21);
1428 __ Udiv(x12, x19, x21);
1429 __ Sdiv(x13, x19, x21);
1430 __ Udiv(x14, x20, x21);
1431 __ Sdiv(x15, x20, x21);
armvixlf37fdc02014-02-05 13:22:16 +00001432
1433 __ Udiv(w22, w19, w17);
1434 __ Sdiv(w23, w19, w17);
1435 __ Udiv(x24, x20, x18);
1436 __ Sdiv(x25, x20, x18);
1437
1438 __ Udiv(x26, x16, x21);
1439 __ Sdiv(x27, x16, x21);
1440 __ Udiv(x28, x18, x21);
1441 __ Sdiv(x29, x18, x21);
1442
1443 __ Mov(x17, 0);
1444 __ Udiv(w18, w16, w17);
1445 __ Sdiv(w19, w16, w17);
1446 __ Udiv(x20, x16, x17);
1447 __ Sdiv(x21, x16, x17);
armvixlad96eda2013-06-14 11:42:37 +01001448 END();
1449
1450 RUN();
1451
1452 ASSERT_EQUAL_64(1, x0);
1453 ASSERT_EQUAL_64(0xffffffff, x1);
1454 ASSERT_EQUAL_64(1, x2);
1455 ASSERT_EQUAL_64(0xffffffff, x3);
1456 ASSERT_EQUAL_64(1, x4);
1457 ASSERT_EQUAL_64(1, x5);
1458 ASSERT_EQUAL_64(0, x6);
1459 ASSERT_EQUAL_64(1, x7);
1460 ASSERT_EQUAL_64(0, x8);
armvixlb0c8ae22014-03-21 14:03:59 +00001461 ASSERT_EQUAL_64(0xffffffff00000001, x9);
armvixlad96eda2013-06-14 11:42:37 +01001462 ASSERT_EQUAL_64(0x40000000, x10);
1463 ASSERT_EQUAL_64(0xC0000000, x11);
armvixlb0c8ae22014-03-21 14:03:59 +00001464 ASSERT_EQUAL_64(0x0000000040000000, x12);
1465 ASSERT_EQUAL_64(0x0000000040000000, x13);
1466 ASSERT_EQUAL_64(0x4000000000000000, x14);
1467 ASSERT_EQUAL_64(0xC000000000000000, x15);
armvixlf37fdc02014-02-05 13:22:16 +00001468 ASSERT_EQUAL_64(0, x22);
1469 ASSERT_EQUAL_64(0x80000000, x23);
1470 ASSERT_EQUAL_64(0, x24);
armvixlb0c8ae22014-03-21 14:03:59 +00001471 ASSERT_EQUAL_64(0x8000000000000000, x25);
armvixlf37fdc02014-02-05 13:22:16 +00001472 ASSERT_EQUAL_64(0, x26);
1473 ASSERT_EQUAL_64(0, x27);
armvixlb0c8ae22014-03-21 14:03:59 +00001474 ASSERT_EQUAL_64(0x7fffffffffffffff, x28);
armvixlf37fdc02014-02-05 13:22:16 +00001475 ASSERT_EQUAL_64(0, x29);
1476 ASSERT_EQUAL_64(0, x18);
1477 ASSERT_EQUAL_64(0, x19);
1478 ASSERT_EQUAL_64(0, x20);
1479 ASSERT_EQUAL_64(0, x21);
armvixlad96eda2013-06-14 11:42:37 +01001480
1481 TEARDOWN();
1482}
1483
1484
1485TEST(rbit_rev) {
1486 SETUP();
1487
1488 START();
armvixlb0c8ae22014-03-21 14:03:59 +00001489 __ Mov(x24, 0xfedcba9876543210);
armvixlad96eda2013-06-14 11:42:37 +01001490 __ Rbit(w0, w24);
1491 __ Rbit(x1, x24);
1492 __ Rev16(w2, w24);
1493 __ Rev16(x3, x24);
1494 __ Rev(w4, w24);
1495 __ Rev32(x5, x24);
1496 __ Rev(x6, x24);
1497 END();
1498
1499 RUN();
1500
1501 ASSERT_EQUAL_64(0x084c2a6e, x0);
armvixlb0c8ae22014-03-21 14:03:59 +00001502 ASSERT_EQUAL_64(0x084c2a6e195d3b7f, x1);
armvixlad96eda2013-06-14 11:42:37 +01001503 ASSERT_EQUAL_64(0x54761032, x2);
armvixlb0c8ae22014-03-21 14:03:59 +00001504 ASSERT_EQUAL_64(0xdcfe98ba54761032, x3);
armvixlad96eda2013-06-14 11:42:37 +01001505 ASSERT_EQUAL_64(0x10325476, x4);
armvixlb0c8ae22014-03-21 14:03:59 +00001506 ASSERT_EQUAL_64(0x98badcfe10325476, x5);
1507 ASSERT_EQUAL_64(0x1032547698badcfe, x6);
armvixlad96eda2013-06-14 11:42:37 +01001508
1509 TEARDOWN();
1510}
1511
1512
1513TEST(clz_cls) {
1514 SETUP();
1515
1516 START();
armvixlb0c8ae22014-03-21 14:03:59 +00001517 __ Mov(x24, 0x0008000000800000);
1518 __ Mov(x25, 0xff800000fff80000);
armvixlad96eda2013-06-14 11:42:37 +01001519 __ Mov(x26, 0);
1520 __ Clz(w0, w24);
1521 __ Clz(x1, x24);
1522 __ Clz(w2, w25);
1523 __ Clz(x3, x25);
1524 __ Clz(w4, w26);
1525 __ Clz(x5, x26);
1526 __ Cls(w6, w24);
1527 __ Cls(x7, x24);
1528 __ Cls(w8, w25);
1529 __ Cls(x9, x25);
1530 __ Cls(w10, w26);
1531 __ Cls(x11, x26);
1532 END();
1533
1534 RUN();
1535
1536 ASSERT_EQUAL_64(8, x0);
1537 ASSERT_EQUAL_64(12, x1);
1538 ASSERT_EQUAL_64(0, x2);
1539 ASSERT_EQUAL_64(0, x3);
1540 ASSERT_EQUAL_64(32, x4);
1541 ASSERT_EQUAL_64(64, x5);
1542 ASSERT_EQUAL_64(7, x6);
1543 ASSERT_EQUAL_64(11, x7);
1544 ASSERT_EQUAL_64(12, x8);
1545 ASSERT_EQUAL_64(8, x9);
1546 ASSERT_EQUAL_64(31, x10);
1547 ASSERT_EQUAL_64(63, x11);
1548
1549 TEARDOWN();
1550}
1551
1552
1553TEST(label) {
1554 SETUP();
1555
1556 Label label_1, label_2, label_3, label_4;
1557
1558 START();
1559 __ Mov(x0, 0x1);
1560 __ Mov(x1, 0x0);
1561 __ Mov(x22, lr); // Save lr.
1562
1563 __ B(&label_1);
1564 __ B(&label_1);
1565 __ B(&label_1); // Multiple branches to the same label.
1566 __ Mov(x0, 0x0);
1567 __ Bind(&label_2);
1568 __ B(&label_3); // Forward branch.
1569 __ Mov(x0, 0x0);
1570 __ Bind(&label_1);
1571 __ B(&label_2); // Backward branch.
1572 __ Mov(x0, 0x0);
1573 __ Bind(&label_3);
1574 __ Bl(&label_4);
1575 END();
1576
1577 __ Bind(&label_4);
1578 __ Mov(x1, 0x1);
1579 __ Mov(lr, x22);
1580 END();
1581
1582 RUN();
1583
1584 ASSERT_EQUAL_64(0x1, x0);
1585 ASSERT_EQUAL_64(0x1, x1);
1586
1587 TEARDOWN();
1588}
1589
1590
armvixlc68cb642014-09-25 18:49:30 +01001591TEST(label_2) {
1592 SETUP();
1593
1594 Label label_1, label_2, label_3;
1595 Label first_jump_to_3;
1596
1597 START();
1598 __ Mov(x0, 0x0);
1599
1600 __ B(&label_1);
1601 ptrdiff_t offset_2 = masm.CursorOffset();
1602 __ Orr(x0, x0, 1 << 1);
1603 __ B(&label_3);
1604 ptrdiff_t offset_1 = masm.CursorOffset();
1605 __ Orr(x0, x0, 1 << 0);
1606 __ B(&label_2);
1607 ptrdiff_t offset_3 = masm.CursorOffset();
1608 __ Tbz(x0, 2, &first_jump_to_3);
1609 __ Orr(x0, x0, 1 << 3);
1610 __ Bind(&first_jump_to_3);
1611 __ Orr(x0, x0, 1 << 2);
1612 __ Tbz(x0, 3, &label_3);
1613
1614 // Labels 1, 2, and 3 are bound before the current buffer offset. Branches to
1615 // label_1 and label_2 branch respectively forward and backward. Branches to
1616 // label 3 include both forward and backward branches.
1617 masm.BindToOffset(&label_1, offset_1);
1618 masm.BindToOffset(&label_2, offset_2);
1619 masm.BindToOffset(&label_3, offset_3);
1620
1621 END();
1622
1623 RUN();
1624
1625 ASSERT_EQUAL_64(0xf, x0);
1626
1627 TEARDOWN();
1628}
1629
1630
armvixlad96eda2013-06-14 11:42:37 +01001631TEST(adr) {
1632 SETUP();
1633
1634 Label label_1, label_2, label_3, label_4;
1635
1636 START();
1637 __ Mov(x0, 0x0); // Set to non-zero to indicate failure.
1638 __ Adr(x1, &label_3); // Set to zero to indicate success.
1639
1640 __ Adr(x2, &label_1); // Multiple forward references to the same label.
1641 __ Adr(x3, &label_1);
1642 __ Adr(x4, &label_1);
1643
1644 __ Bind(&label_2);
1645 __ Eor(x5, x2, Operand(x3)); // Ensure that x2,x3 and x4 are identical.
1646 __ Eor(x6, x2, Operand(x4));
1647 __ Orr(x0, x0, Operand(x5));
1648 __ Orr(x0, x0, Operand(x6));
1649 __ Br(x2); // label_1, label_3
1650
1651 __ Bind(&label_3);
1652 __ Adr(x2, &label_3); // Self-reference (offset 0).
1653 __ Eor(x1, x1, Operand(x2));
1654 __ Adr(x2, &label_4); // Simple forward reference.
1655 __ Br(x2); // label_4
1656
1657 __ Bind(&label_1);
1658 __ Adr(x2, &label_3); // Multiple reverse references to the same label.
1659 __ Adr(x3, &label_3);
1660 __ Adr(x4, &label_3);
1661 __ Adr(x5, &label_2); // Simple reverse reference.
1662 __ Br(x5); // label_2
1663
1664 __ Bind(&label_4);
1665 END();
1666
1667 RUN();
1668
1669 ASSERT_EQUAL_64(0x0, x0);
1670 ASSERT_EQUAL_64(0x0, x1);
1671
1672 TEARDOWN();
1673}
1674
1675
armvixl4a102ba2014-07-14 09:02:40 +01001676// Simple adrp tests: check that labels are linked and handled properly.
1677// This is similar to the adr test, but all the adrp instructions are put on the
1678// same page so that they return the same value.
1679TEST(adrp) {
1680 Label start;
1681 Label label_1, label_2, label_3;
1682
1683 SETUP_CUSTOM(2 * kPageSize, PageOffsetDependentCode);
1684 START();
1685
1686 // Waste space until the start of a page.
armvixlc68cb642014-09-25 18:49:30 +01001687 {
1688 InstructionAccurateScope scope(&masm,
1689 kPageSize / kInstructionSize,
1690 InstructionAccurateScope::kMaximumSize);
armvixl4a102ba2014-07-14 09:02:40 +01001691 const uintptr_t kPageOffsetMask = kPageSize - 1;
armvixlc68cb642014-09-25 18:49:30 +01001692 while ((masm.GetCursorAddress<uintptr_t>() & kPageOffsetMask) != 0) {
armvixl4a102ba2014-07-14 09:02:40 +01001693 __ b(&start);
1694 }
1695 __ bind(&start);
1696 }
1697
1698 // Simple forward reference.
1699 __ Adrp(x0, &label_2);
1700
1701 __ Bind(&label_1);
1702
1703 // Multiple forward references to the same label.
1704 __ Adrp(x1, &label_3);
1705 __ Adrp(x2, &label_3);
1706 __ Adrp(x3, &label_3);
1707
1708 __ Bind(&label_2);
1709
1710 // Self-reference (offset 0).
1711 __ Adrp(x4, &label_2);
1712
1713 __ Bind(&label_3);
1714
1715 // Simple reverse reference.
1716 __ Adrp(x5, &label_1);
1717
1718 // Multiple reverse references to the same label.
1719 __ Adrp(x6, &label_2);
1720 __ Adrp(x7, &label_2);
1721 __ Adrp(x8, &label_2);
1722
1723 VIXL_ASSERT(masm.SizeOfCodeGeneratedSince(&start) < kPageSize);
1724 END();
1725 RUN();
1726
1727 uint64_t expected = reinterpret_cast<uint64_t>(
1728 AlignDown(masm.GetLabelAddress<uint64_t*>(&start), kPageSize));
1729 ASSERT_EQUAL_64(expected, x0);
1730 ASSERT_EQUAL_64(expected, x1);
1731 ASSERT_EQUAL_64(expected, x2);
1732 ASSERT_EQUAL_64(expected, x3);
1733 ASSERT_EQUAL_64(expected, x4);
1734 ASSERT_EQUAL_64(expected, x5);
1735 ASSERT_EQUAL_64(expected, x6);
1736 ASSERT_EQUAL_64(expected, x7);
1737 ASSERT_EQUAL_64(expected, x8);
1738
armvixlc68cb642014-09-25 18:49:30 +01001739 TEARDOWN_CUSTOM();
armvixl4a102ba2014-07-14 09:02:40 +01001740}
1741
1742
1743static void AdrpPageBoundaryHelper(unsigned offset_into_page) {
1744 VIXL_ASSERT(offset_into_page < kPageSize);
1745 VIXL_ASSERT((offset_into_page % kInstructionSize) == 0);
1746
1747 const uintptr_t kPageOffsetMask = kPageSize - 1;
1748
1749 // The test label is always bound on page 0. Adrp instructions are generated
1750 // on pages from kStartPage to kEndPage (inclusive).
1751 const int kStartPage = -16;
1752 const int kEndPage = 16;
armvixlc68cb642014-09-25 18:49:30 +01001753 const int kMaxCodeSize = (kEndPage - kStartPage + 2) * kPageSize;
armvixl4a102ba2014-07-14 09:02:40 +01001754
armvixlc68cb642014-09-25 18:49:30 +01001755 SETUP_CUSTOM(kMaxCodeSize, PageOffsetDependentCode);
armvixl4a102ba2014-07-14 09:02:40 +01001756 START();
1757
armvixl4a102ba2014-07-14 09:02:40 +01001758 Label test;
armvixlc68cb642014-09-25 18:49:30 +01001759 Label start;
armvixl4a102ba2014-07-14 09:02:40 +01001760
armvixlc68cb642014-09-25 18:49:30 +01001761 {
1762 InstructionAccurateScope scope(&masm,
1763 kMaxCodeSize / kInstructionSize,
1764 InstructionAccurateScope::kMaximumSize);
1765 // Initialize NZCV with `eq` flags.
1766 __ cmp(wzr, wzr);
armvixl4a102ba2014-07-14 09:02:40 +01001767 // Waste space until the start of a page.
armvixlc68cb642014-09-25 18:49:30 +01001768 while ((masm.GetCursorAddress<uintptr_t>() & kPageOffsetMask) != 0) {
armvixl4a102ba2014-07-14 09:02:40 +01001769 __ b(&start);
1770 }
1771
1772 // The first page.
1773 VIXL_STATIC_ASSERT(kStartPage < 0);
armvixlc68cb642014-09-25 18:49:30 +01001774 {
1775 InstructionAccurateScope scope_page(&masm, kPageSize / kInstructionSize);
armvixl4a102ba2014-07-14 09:02:40 +01001776 __ bind(&start);
1777 __ adrp(x0, &test);
1778 __ adrp(x1, &test);
1779 for (size_t i = 2; i < (kPageSize / kInstructionSize); i += 2) {
1780 __ ccmp(x0, x1, NoFlag, eq);
1781 __ adrp(x1, &test);
1782 }
1783 }
1784
1785 // Subsequent pages.
1786 VIXL_STATIC_ASSERT(kEndPage >= 0);
1787 for (int page = (kStartPage + 1); page <= kEndPage; page++) {
1788 InstructionAccurateScope scope_page(&masm, kPageSize / kInstructionSize);
1789 if (page == 0) {
1790 for (size_t i = 0; i < (kPageSize / kInstructionSize);) {
1791 if (i++ == (offset_into_page / kInstructionSize)) __ bind(&test);
1792 __ ccmp(x0, x1, NoFlag, eq);
1793 if (i++ == (offset_into_page / kInstructionSize)) __ bind(&test);
1794 __ adrp(x1, &test);
1795 }
1796 } else {
1797 for (size_t i = 0; i < (kPageSize / kInstructionSize); i += 2) {
1798 __ ccmp(x0, x1, NoFlag, eq);
1799 __ adrp(x1, &test);
1800 }
1801 }
1802 }
armvixl4a102ba2014-07-14 09:02:40 +01001803 }
1804
armvixlc68cb642014-09-25 18:49:30 +01001805 // Every adrp instruction pointed to the same label (`test`), so they should
1806 // all have produced the same result.
1807
armvixl4a102ba2014-07-14 09:02:40 +01001808 END();
1809 RUN();
1810
1811 uintptr_t expected =
1812 AlignDown(masm.GetLabelAddress<uintptr_t>(&test), kPageSize);
1813 ASSERT_EQUAL_64(expected, x0);
1814 ASSERT_EQUAL_64(expected, x1);
1815 ASSERT_EQUAL_NZCV(ZCFlag);
1816
armvixlc68cb642014-09-25 18:49:30 +01001817 TEARDOWN_CUSTOM();
armvixl4a102ba2014-07-14 09:02:40 +01001818}
1819
1820
1821// Test that labels are correctly referenced by adrp across page boundaries.
1822TEST(adrp_page_boundaries) {
1823 VIXL_STATIC_ASSERT(kPageSize == 4096);
1824 AdrpPageBoundaryHelper(kInstructionSize * 0);
1825 AdrpPageBoundaryHelper(kInstructionSize * 1);
1826 AdrpPageBoundaryHelper(kInstructionSize * 512);
1827 AdrpPageBoundaryHelper(kInstructionSize * 1022);
1828 AdrpPageBoundaryHelper(kInstructionSize * 1023);
1829}
1830
1831
1832static void AdrpOffsetHelper(int64_t imm21) {
1833 const size_t kPageOffsetMask = kPageSize - 1;
armvixlc68cb642014-09-25 18:49:30 +01001834 const int kMaxCodeSize = 2 * kPageSize;
armvixl4a102ba2014-07-14 09:02:40 +01001835
armvixlc68cb642014-09-25 18:49:30 +01001836 SETUP_CUSTOM(kMaxCodeSize, PageOffsetDependentCode);
armvixl4a102ba2014-07-14 09:02:40 +01001837 START();
1838
armvixl4a102ba2014-07-14 09:02:40 +01001839 Label page;
armvixlc68cb642014-09-25 18:49:30 +01001840
1841 {
1842 InstructionAccurateScope scope(&masm,
1843 kMaxCodeSize / kInstructionSize,
1844 InstructionAccurateScope::kMaximumSize);
1845 // Initialize NZCV with `eq` flags.
1846 __ cmp(wzr, wzr);
armvixl4a102ba2014-07-14 09:02:40 +01001847 // Waste space until the start of a page.
armvixlc68cb642014-09-25 18:49:30 +01001848 while ((masm.GetCursorAddress<uintptr_t>() & kPageOffsetMask) != 0) {
armvixl4a102ba2014-07-14 09:02:40 +01001849 __ b(&page);
1850 }
1851 __ bind(&page);
1852
armvixlc68cb642014-09-25 18:49:30 +01001853 {
1854 InstructionAccurateScope scope_page(&masm, kPageSize / kInstructionSize);
armvixl4a102ba2014-07-14 09:02:40 +01001855 // Every adrp instruction on this page should return the same value.
1856 __ adrp(x0, imm21);
1857 __ adrp(x1, imm21);
1858 for (size_t i = 2; i < kPageSize / kInstructionSize; i += 2) {
1859 __ ccmp(x0, x1, NoFlag, eq);
1860 __ adrp(x1, imm21);
1861 }
1862 }
1863 }
1864
1865 END();
1866 RUN();
1867
1868 uintptr_t expected =
1869 masm.GetLabelAddress<uintptr_t>(&page) + (kPageSize * imm21);
1870 ASSERT_EQUAL_64(expected, x0);
1871 ASSERT_EQUAL_64(expected, x1);
1872 ASSERT_EQUAL_NZCV(ZCFlag);
1873
armvixlc68cb642014-09-25 18:49:30 +01001874 TEARDOWN_CUSTOM();
armvixl4a102ba2014-07-14 09:02:40 +01001875}
1876
1877
1878// Check that adrp produces the correct result for a specific offset.
1879TEST(adrp_offset) {
1880 AdrpOffsetHelper(0);
1881 AdrpOffsetHelper(1);
1882 AdrpOffsetHelper(-1);
1883 AdrpOffsetHelper(4);
1884 AdrpOffsetHelper(-4);
1885 AdrpOffsetHelper(0x000fffff);
1886 AdrpOffsetHelper(-0x000fffff);
1887 AdrpOffsetHelper(-0x00100000);
1888}
1889
1890
armvixlad96eda2013-06-14 11:42:37 +01001891TEST(branch_cond) {
1892 SETUP();
armvixlc68cb642014-09-25 18:49:30 +01001893 ALLOW_ASM();
armvixlad96eda2013-06-14 11:42:37 +01001894
1895 Label wrong;
1896
1897 START();
1898 __ Mov(x0, 0x1);
1899 __ Mov(x1, 0x1);
armvixlb0c8ae22014-03-21 14:03:59 +00001900 __ Mov(x2, 0x8000000000000000);
armvixlad96eda2013-06-14 11:42:37 +01001901
1902 // For each 'cmp' instruction below, condition codes other than the ones
1903 // following it would branch.
1904
armvixl578645f2013-08-15 17:21:42 +01001905 __ Cmp(x1, 0);
armvixlad96eda2013-06-14 11:42:37 +01001906 __ B(&wrong, eq);
1907 __ B(&wrong, lo);
1908 __ B(&wrong, mi);
1909 __ B(&wrong, vs);
1910 __ B(&wrong, ls);
1911 __ B(&wrong, lt);
1912 __ B(&wrong, le);
1913 Label ok_1;
1914 __ B(&ok_1, ne);
1915 __ Mov(x0, 0x0);
1916 __ Bind(&ok_1);
1917
armvixl578645f2013-08-15 17:21:42 +01001918 __ Cmp(x1, 1);
armvixlad96eda2013-06-14 11:42:37 +01001919 __ B(&wrong, ne);
1920 __ B(&wrong, lo);
1921 __ B(&wrong, mi);
1922 __ B(&wrong, vs);
1923 __ B(&wrong, hi);
1924 __ B(&wrong, lt);
1925 __ B(&wrong, gt);
1926 Label ok_2;
1927 __ B(&ok_2, pl);
1928 __ Mov(x0, 0x0);
1929 __ Bind(&ok_2);
1930
armvixl578645f2013-08-15 17:21:42 +01001931 __ Cmp(x1, 2);
armvixlad96eda2013-06-14 11:42:37 +01001932 __ B(&wrong, eq);
1933 __ B(&wrong, hs);
1934 __ B(&wrong, pl);
1935 __ B(&wrong, vs);
1936 __ B(&wrong, hi);
1937 __ B(&wrong, ge);
1938 __ B(&wrong, gt);
1939 Label ok_3;
1940 __ B(&ok_3, vc);
1941 __ Mov(x0, 0x0);
1942 __ Bind(&ok_3);
1943
armvixl578645f2013-08-15 17:21:42 +01001944 __ Cmp(x2, 1);
armvixlad96eda2013-06-14 11:42:37 +01001945 __ B(&wrong, eq);
1946 __ B(&wrong, lo);
1947 __ B(&wrong, mi);
1948 __ B(&wrong, vc);
1949 __ B(&wrong, ls);
1950 __ B(&wrong, ge);
1951 __ B(&wrong, gt);
1952 Label ok_4;
1953 __ B(&ok_4, le);
1954 __ Mov(x0, 0x0);
1955 __ Bind(&ok_4);
armvixl578645f2013-08-15 17:21:42 +01001956
armvixlc68cb642014-09-25 18:49:30 +01001957 // The MacroAssembler does not allow al as a branch condition.
armvixl578645f2013-08-15 17:21:42 +01001958 Label ok_5;
1959 __ b(&ok_5, al);
1960 __ Mov(x0, 0x0);
1961 __ Bind(&ok_5);
1962
armvixlc68cb642014-09-25 18:49:30 +01001963 // The MacroAssembler does not allow nv as a branch condition.
armvixl578645f2013-08-15 17:21:42 +01001964 Label ok_6;
1965 __ b(&ok_6, nv);
1966 __ Mov(x0, 0x0);
1967 __ Bind(&ok_6);
1968
armvixlad96eda2013-06-14 11:42:37 +01001969 END();
1970
1971 __ Bind(&wrong);
1972 __ Mov(x0, 0x0);
1973 END();
1974
1975 RUN();
1976
1977 ASSERT_EQUAL_64(0x1, x0);
1978
1979 TEARDOWN();
1980}
1981
1982
1983TEST(branch_to_reg) {
1984 SETUP();
1985
1986 // Test br.
1987 Label fn1, after_fn1;
1988
1989 START();
1990 __ Mov(x29, lr);
1991
1992 __ Mov(x1, 0);
1993 __ B(&after_fn1);
1994
1995 __ Bind(&fn1);
1996 __ Mov(x0, lr);
1997 __ Mov(x1, 42);
1998 __ Br(x0);
1999
2000 __ Bind(&after_fn1);
2001 __ Bl(&fn1);
2002
2003 // Test blr.
2004 Label fn2, after_fn2;
2005
2006 __ Mov(x2, 0);
2007 __ B(&after_fn2);
2008
2009 __ Bind(&fn2);
2010 __ Mov(x0, lr);
2011 __ Mov(x2, 84);
2012 __ Blr(x0);
2013
2014 __ Bind(&after_fn2);
2015 __ Bl(&fn2);
2016 __ Mov(x3, lr);
2017
2018 __ Mov(lr, x29);
2019 END();
2020
2021 RUN();
2022
2023 ASSERT_EQUAL_64(core.xreg(3) + kInstructionSize, x0);
2024 ASSERT_EQUAL_64(42, x1);
2025 ASSERT_EQUAL_64(84, x2);
2026
2027 TEARDOWN();
2028}
2029
2030
2031TEST(compare_branch) {
2032 SETUP();
2033
2034 START();
2035 __ Mov(x0, 0);
2036 __ Mov(x1, 0);
2037 __ Mov(x2, 0);
2038 __ Mov(x3, 0);
2039 __ Mov(x4, 0);
2040 __ Mov(x5, 0);
2041 __ Mov(x16, 0);
2042 __ Mov(x17, 42);
2043
2044 Label zt, zt_end;
2045 __ Cbz(w16, &zt);
2046 __ B(&zt_end);
2047 __ Bind(&zt);
2048 __ Mov(x0, 1);
2049 __ Bind(&zt_end);
2050
2051 Label zf, zf_end;
2052 __ Cbz(x17, &zf);
2053 __ B(&zf_end);
2054 __ Bind(&zf);
2055 __ Mov(x1, 1);
2056 __ Bind(&zf_end);
2057
2058 Label nzt, nzt_end;
2059 __ Cbnz(w17, &nzt);
2060 __ B(&nzt_end);
2061 __ Bind(&nzt);
2062 __ Mov(x2, 1);
2063 __ Bind(&nzt_end);
2064
2065 Label nzf, nzf_end;
2066 __ Cbnz(x16, &nzf);
2067 __ B(&nzf_end);
2068 __ Bind(&nzf);
2069 __ Mov(x3, 1);
2070 __ Bind(&nzf_end);
2071
armvixlb0c8ae22014-03-21 14:03:59 +00002072 __ Mov(x18, 0xffffffff00000000);
armvixlad96eda2013-06-14 11:42:37 +01002073
2074 Label a, a_end;
2075 __ Cbz(w18, &a);
2076 __ B(&a_end);
2077 __ Bind(&a);
2078 __ Mov(x4, 1);
2079 __ Bind(&a_end);
2080
2081 Label b, b_end;
2082 __ Cbnz(w18, &b);
2083 __ B(&b_end);
2084 __ Bind(&b);
2085 __ Mov(x5, 1);
2086 __ Bind(&b_end);
2087
2088 END();
2089
2090 RUN();
2091
2092 ASSERT_EQUAL_64(1, x0);
2093 ASSERT_EQUAL_64(0, x1);
2094 ASSERT_EQUAL_64(1, x2);
2095 ASSERT_EQUAL_64(0, x3);
2096 ASSERT_EQUAL_64(1, x4);
2097 ASSERT_EQUAL_64(0, x5);
2098
2099 TEARDOWN();
2100}
2101
2102
2103TEST(test_branch) {
2104 SETUP();
2105
2106 START();
2107 __ Mov(x0, 0);
2108 __ Mov(x1, 0);
2109 __ Mov(x2, 0);
2110 __ Mov(x3, 0);
armvixlb0c8ae22014-03-21 14:03:59 +00002111 __ Mov(x16, 0xaaaaaaaaaaaaaaaa);
armvixlad96eda2013-06-14 11:42:37 +01002112
2113 Label bz, bz_end;
armvixlf37fdc02014-02-05 13:22:16 +00002114 __ Tbz(w16, 0, &bz);
armvixlad96eda2013-06-14 11:42:37 +01002115 __ B(&bz_end);
2116 __ Bind(&bz);
2117 __ Mov(x0, 1);
2118 __ Bind(&bz_end);
2119
2120 Label bo, bo_end;
2121 __ Tbz(x16, 63, &bo);
2122 __ B(&bo_end);
2123 __ Bind(&bo);
2124 __ Mov(x1, 1);
2125 __ Bind(&bo_end);
2126
2127 Label nbz, nbz_end;
2128 __ Tbnz(x16, 61, &nbz);
2129 __ B(&nbz_end);
2130 __ Bind(&nbz);
2131 __ Mov(x2, 1);
2132 __ Bind(&nbz_end);
2133
2134 Label nbo, nbo_end;
armvixlf37fdc02014-02-05 13:22:16 +00002135 __ Tbnz(w16, 2, &nbo);
armvixlad96eda2013-06-14 11:42:37 +01002136 __ B(&nbo_end);
2137 __ Bind(&nbo);
2138 __ Mov(x3, 1);
2139 __ Bind(&nbo_end);
2140 END();
2141
2142 RUN();
2143
2144 ASSERT_EQUAL_64(1, x0);
2145 ASSERT_EQUAL_64(0, x1);
2146 ASSERT_EQUAL_64(1, x2);
2147 ASSERT_EQUAL_64(0, x3);
2148
2149 TEARDOWN();
2150}
2151
2152
armvixlb0c8ae22014-03-21 14:03:59 +00002153TEST(branch_type) {
2154 SETUP();
2155
2156 Label fail, done;
2157
2158 START();
2159 __ Mov(x0, 0x0);
2160 __ Mov(x10, 0x7);
2161 __ Mov(x11, 0x0);
2162
2163 // Test non taken branches.
2164 __ Cmp(x10, 0x7);
2165 __ B(&fail, ne);
2166 __ B(&fail, never);
2167 __ B(&fail, reg_zero, x10);
2168 __ B(&fail, reg_not_zero, x11);
2169 __ B(&fail, reg_bit_clear, x10, 0);
2170 __ B(&fail, reg_bit_set, x10, 3);
2171
2172 // Test taken branches.
2173 Label l1, l2, l3, l4, l5;
2174 __ Cmp(x10, 0x7);
2175 __ B(&l1, eq);
2176 __ B(&fail);
2177 __ Bind(&l1);
2178 __ B(&l2, always);
2179 __ B(&fail);
2180 __ Bind(&l2);
2181 __ B(&l3, reg_not_zero, x10);
2182 __ B(&fail);
2183 __ Bind(&l3);
2184 __ B(&l4, reg_bit_clear, x10, 15);
2185 __ B(&fail);
2186 __ Bind(&l4);
2187 __ B(&l5, reg_bit_set, x10, 1);
2188 __ B(&fail);
2189 __ Bind(&l5);
2190
2191 __ B(&done);
2192
2193 __ Bind(&fail);
2194 __ Mov(x0, 0x1);
2195
2196 __ Bind(&done);
2197
2198 END();
2199
2200 RUN();
2201
2202 ASSERT_EQUAL_64(0x0, x0);
2203
2204 TEARDOWN();
2205}
2206
2207
armvixlad96eda2013-06-14 11:42:37 +01002208TEST(ldr_str_offset) {
2209 SETUP();
2210
armvixlb0c8ae22014-03-21 14:03:59 +00002211 uint64_t src[2] = {0xfedcba9876543210, 0x0123456789abcdef};
armvixlad96eda2013-06-14 11:42:37 +01002212 uint64_t dst[5] = {0, 0, 0, 0, 0};
2213 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
2214 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
2215
2216 START();
2217 __ Mov(x17, src_base);
2218 __ Mov(x18, dst_base);
2219 __ Ldr(w0, MemOperand(x17));
2220 __ Str(w0, MemOperand(x18));
2221 __ Ldr(w1, MemOperand(x17, 4));
2222 __ Str(w1, MemOperand(x18, 12));
2223 __ Ldr(x2, MemOperand(x17, 8));
2224 __ Str(x2, MemOperand(x18, 16));
2225 __ Ldrb(w3, MemOperand(x17, 1));
2226 __ Strb(w3, MemOperand(x18, 25));
2227 __ Ldrh(w4, MemOperand(x17, 2));
2228 __ Strh(w4, MemOperand(x18, 33));
2229 END();
2230
2231 RUN();
2232
2233 ASSERT_EQUAL_64(0x76543210, x0);
2234 ASSERT_EQUAL_64(0x76543210, dst[0]);
2235 ASSERT_EQUAL_64(0xfedcba98, x1);
armvixlb0c8ae22014-03-21 14:03:59 +00002236 ASSERT_EQUAL_64(0xfedcba9800000000, dst[1]);
2237 ASSERT_EQUAL_64(0x0123456789abcdef, x2);
2238 ASSERT_EQUAL_64(0x0123456789abcdef, dst[2]);
armvixlad96eda2013-06-14 11:42:37 +01002239 ASSERT_EQUAL_64(0x32, x3);
2240 ASSERT_EQUAL_64(0x3200, dst[3]);
2241 ASSERT_EQUAL_64(0x7654, x4);
2242 ASSERT_EQUAL_64(0x765400, dst[4]);
2243 ASSERT_EQUAL_64(src_base, x17);
2244 ASSERT_EQUAL_64(dst_base, x18);
2245
2246 TEARDOWN();
2247}
2248
2249
2250TEST(ldr_str_wide) {
2251 SETUP();
2252
2253 uint32_t src[8192];
2254 uint32_t dst[8192];
2255 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
2256 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
2257 memset(src, 0xaa, 8192 * sizeof(src[0]));
2258 memset(dst, 0xaa, 8192 * sizeof(dst[0]));
2259 src[0] = 0;
2260 src[6144] = 6144;
2261 src[8191] = 8191;
2262
2263 START();
2264 __ Mov(x22, src_base);
2265 __ Mov(x23, dst_base);
2266 __ Mov(x24, src_base);
2267 __ Mov(x25, dst_base);
2268 __ Mov(x26, src_base);
2269 __ Mov(x27, dst_base);
2270
2271 __ Ldr(w0, MemOperand(x22, 8191 * sizeof(src[0])));
2272 __ Str(w0, MemOperand(x23, 8191 * sizeof(dst[0])));
2273 __ Ldr(w1, MemOperand(x24, 4096 * sizeof(src[0]), PostIndex));
2274 __ Str(w1, MemOperand(x25, 4096 * sizeof(dst[0]), PostIndex));
2275 __ Ldr(w2, MemOperand(x26, 6144 * sizeof(src[0]), PreIndex));
2276 __ Str(w2, MemOperand(x27, 6144 * sizeof(dst[0]), PreIndex));
2277 END();
2278
2279 RUN();
2280
2281 ASSERT_EQUAL_32(8191, w0);
2282 ASSERT_EQUAL_32(8191, dst[8191]);
2283 ASSERT_EQUAL_64(src_base, x22);
2284 ASSERT_EQUAL_64(dst_base, x23);
2285 ASSERT_EQUAL_32(0, w1);
2286 ASSERT_EQUAL_32(0, dst[0]);
2287 ASSERT_EQUAL_64(src_base + 4096 * sizeof(src[0]), x24);
2288 ASSERT_EQUAL_64(dst_base + 4096 * sizeof(dst[0]), x25);
2289 ASSERT_EQUAL_32(6144, w2);
2290 ASSERT_EQUAL_32(6144, dst[6144]);
2291 ASSERT_EQUAL_64(src_base + 6144 * sizeof(src[0]), x26);
2292 ASSERT_EQUAL_64(dst_base + 6144 * sizeof(dst[0]), x27);
2293
2294 TEARDOWN();
2295}
2296
2297
2298TEST(ldr_str_preindex) {
2299 SETUP();
2300
armvixlb0c8ae22014-03-21 14:03:59 +00002301 uint64_t src[2] = {0xfedcba9876543210, 0x0123456789abcdef};
armvixlad96eda2013-06-14 11:42:37 +01002302 uint64_t dst[6] = {0, 0, 0, 0, 0, 0};
2303 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
2304 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
2305
2306 START();
2307 __ Mov(x17, src_base);
2308 __ Mov(x18, dst_base);
2309 __ Mov(x19, src_base);
2310 __ Mov(x20, dst_base);
2311 __ Mov(x21, src_base + 16);
2312 __ Mov(x22, dst_base + 40);
2313 __ Mov(x23, src_base);
2314 __ Mov(x24, dst_base);
2315 __ Mov(x25, src_base);
2316 __ Mov(x26, dst_base);
2317 __ Ldr(w0, MemOperand(x17, 4, PreIndex));
2318 __ Str(w0, MemOperand(x18, 12, PreIndex));
2319 __ Ldr(x1, MemOperand(x19, 8, PreIndex));
2320 __ Str(x1, MemOperand(x20, 16, PreIndex));
2321 __ Ldr(w2, MemOperand(x21, -4, PreIndex));
2322 __ Str(w2, MemOperand(x22, -4, PreIndex));
2323 __ Ldrb(w3, MemOperand(x23, 1, PreIndex));
2324 __ Strb(w3, MemOperand(x24, 25, PreIndex));
2325 __ Ldrh(w4, MemOperand(x25, 3, PreIndex));
2326 __ Strh(w4, MemOperand(x26, 41, PreIndex));
2327 END();
2328
2329 RUN();
2330
2331 ASSERT_EQUAL_64(0xfedcba98, x0);
armvixlb0c8ae22014-03-21 14:03:59 +00002332 ASSERT_EQUAL_64(0xfedcba9800000000, dst[1]);
2333 ASSERT_EQUAL_64(0x0123456789abcdef, x1);
2334 ASSERT_EQUAL_64(0x0123456789abcdef, dst[2]);
armvixlad96eda2013-06-14 11:42:37 +01002335 ASSERT_EQUAL_64(0x01234567, x2);
armvixlb0c8ae22014-03-21 14:03:59 +00002336 ASSERT_EQUAL_64(0x0123456700000000, dst[4]);
armvixlad96eda2013-06-14 11:42:37 +01002337 ASSERT_EQUAL_64(0x32, x3);
2338 ASSERT_EQUAL_64(0x3200, dst[3]);
2339 ASSERT_EQUAL_64(0x9876, x4);
2340 ASSERT_EQUAL_64(0x987600, dst[5]);
2341 ASSERT_EQUAL_64(src_base + 4, x17);
2342 ASSERT_EQUAL_64(dst_base + 12, x18);
2343 ASSERT_EQUAL_64(src_base + 8, x19);
2344 ASSERT_EQUAL_64(dst_base + 16, x20);
2345 ASSERT_EQUAL_64(src_base + 12, x21);
2346 ASSERT_EQUAL_64(dst_base + 36, x22);
2347 ASSERT_EQUAL_64(src_base + 1, x23);
2348 ASSERT_EQUAL_64(dst_base + 25, x24);
2349 ASSERT_EQUAL_64(src_base + 3, x25);
2350 ASSERT_EQUAL_64(dst_base + 41, x26);
2351
2352 TEARDOWN();
2353}
2354
2355
2356TEST(ldr_str_postindex) {
2357 SETUP();
2358
armvixlb0c8ae22014-03-21 14:03:59 +00002359 uint64_t src[2] = {0xfedcba9876543210, 0x0123456789abcdef};
armvixlad96eda2013-06-14 11:42:37 +01002360 uint64_t dst[6] = {0, 0, 0, 0, 0, 0};
2361 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
2362 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
2363
2364 START();
2365 __ Mov(x17, src_base + 4);
2366 __ Mov(x18, dst_base + 12);
2367 __ Mov(x19, src_base + 8);
2368 __ Mov(x20, dst_base + 16);
2369 __ Mov(x21, src_base + 8);
2370 __ Mov(x22, dst_base + 32);
2371 __ Mov(x23, src_base + 1);
2372 __ Mov(x24, dst_base + 25);
2373 __ Mov(x25, src_base + 3);
2374 __ Mov(x26, dst_base + 41);
2375 __ Ldr(w0, MemOperand(x17, 4, PostIndex));
2376 __ Str(w0, MemOperand(x18, 12, PostIndex));
2377 __ Ldr(x1, MemOperand(x19, 8, PostIndex));
2378 __ Str(x1, MemOperand(x20, 16, PostIndex));
2379 __ Ldr(x2, MemOperand(x21, -8, PostIndex));
2380 __ Str(x2, MemOperand(x22, -32, PostIndex));
2381 __ Ldrb(w3, MemOperand(x23, 1, PostIndex));
2382 __ Strb(w3, MemOperand(x24, 5, PostIndex));
2383 __ Ldrh(w4, MemOperand(x25, -3, PostIndex));
2384 __ Strh(w4, MemOperand(x26, -41, PostIndex));
2385 END();
2386
2387 RUN();
2388
2389 ASSERT_EQUAL_64(0xfedcba98, x0);
armvixlb0c8ae22014-03-21 14:03:59 +00002390 ASSERT_EQUAL_64(0xfedcba9800000000, dst[1]);
2391 ASSERT_EQUAL_64(0x0123456789abcdef, x1);
2392 ASSERT_EQUAL_64(0x0123456789abcdef, dst[2]);
2393 ASSERT_EQUAL_64(0x0123456789abcdef, x2);
2394 ASSERT_EQUAL_64(0x0123456789abcdef, dst[4]);
armvixlad96eda2013-06-14 11:42:37 +01002395 ASSERT_EQUAL_64(0x32, x3);
2396 ASSERT_EQUAL_64(0x3200, dst[3]);
2397 ASSERT_EQUAL_64(0x9876, x4);
2398 ASSERT_EQUAL_64(0x987600, dst[5]);
2399 ASSERT_EQUAL_64(src_base + 8, x17);
2400 ASSERT_EQUAL_64(dst_base + 24, x18);
2401 ASSERT_EQUAL_64(src_base + 16, x19);
2402 ASSERT_EQUAL_64(dst_base + 32, x20);
2403 ASSERT_EQUAL_64(src_base, x21);
2404 ASSERT_EQUAL_64(dst_base, x22);
2405 ASSERT_EQUAL_64(src_base + 2, x23);
2406 ASSERT_EQUAL_64(dst_base + 30, x24);
2407 ASSERT_EQUAL_64(src_base, x25);
2408 ASSERT_EQUAL_64(dst_base, x26);
2409
2410 TEARDOWN();
2411}
2412
2413
2414TEST(ldr_str_largeindex) {
2415 SETUP();
2416
2417 // This value won't fit in the immediate offset field of ldr/str instructions.
2418 int largeoffset = 0xabcdef;
2419
2420 int64_t data[3] = { 0x1122334455667788, 0, 0 };
armvixlb0c8ae22014-03-21 14:03:59 +00002421 uint64_t base_addr = reinterpret_cast<uintptr_t>(data);
2422 uint64_t drifted_addr = base_addr - largeoffset;
armvixlad96eda2013-06-14 11:42:37 +01002423
2424 // This test checks that we we can use large immediate offsets when
2425 // using PreIndex or PostIndex addressing mode of the MacroAssembler
2426 // Ldr/Str instructions.
2427
2428 START();
armvixlad96eda2013-06-14 11:42:37 +01002429 __ Mov(x19, drifted_addr);
armvixlb0c8ae22014-03-21 14:03:59 +00002430 __ Ldr(x0, MemOperand(x19, largeoffset, PreIndex));
armvixlad96eda2013-06-14 11:42:37 +01002431
armvixlb0c8ae22014-03-21 14:03:59 +00002432 __ Mov(x20, base_addr);
2433 __ Ldr(x1, MemOperand(x20, largeoffset, PostIndex));
2434
2435 __ Mov(x21, drifted_addr);
2436 __ Str(x0, MemOperand(x21, largeoffset + 8, PreIndex));
2437
2438 __ Mov(x22, base_addr + 16);
2439 __ Str(x0, MemOperand(x22, largeoffset, PostIndex));
armvixlad96eda2013-06-14 11:42:37 +01002440 END();
2441
2442 RUN();
2443
2444 ASSERT_EQUAL_64(0x1122334455667788, data[0]);
2445 ASSERT_EQUAL_64(0x1122334455667788, data[1]);
2446 ASSERT_EQUAL_64(0x1122334455667788, data[2]);
2447 ASSERT_EQUAL_64(0x1122334455667788, x0);
2448 ASSERT_EQUAL_64(0x1122334455667788, x1);
2449
armvixlb0c8ae22014-03-21 14:03:59 +00002450 ASSERT_EQUAL_64(base_addr, x19);
2451 ASSERT_EQUAL_64(base_addr + largeoffset, x20);
2452 ASSERT_EQUAL_64(base_addr + 8, x21);
2453 ASSERT_EQUAL_64(base_addr + 16 + largeoffset, x22);
armvixlad96eda2013-06-14 11:42:37 +01002454
2455 TEARDOWN();
2456}
2457
2458
2459TEST(load_signed) {
2460 SETUP();
2461
2462 uint32_t src[2] = {0x80008080, 0x7fff7f7f};
2463 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
2464
2465 START();
2466 __ Mov(x24, src_base);
2467 __ Ldrsb(w0, MemOperand(x24));
2468 __ Ldrsb(w1, MemOperand(x24, 4));
2469 __ Ldrsh(w2, MemOperand(x24));
2470 __ Ldrsh(w3, MemOperand(x24, 4));
2471 __ Ldrsb(x4, MemOperand(x24));
2472 __ Ldrsb(x5, MemOperand(x24, 4));
2473 __ Ldrsh(x6, MemOperand(x24));
2474 __ Ldrsh(x7, MemOperand(x24, 4));
2475 __ Ldrsw(x8, MemOperand(x24));
2476 __ Ldrsw(x9, MemOperand(x24, 4));
2477 END();
2478
2479 RUN();
2480
2481 ASSERT_EQUAL_64(0xffffff80, x0);
2482 ASSERT_EQUAL_64(0x0000007f, x1);
2483 ASSERT_EQUAL_64(0xffff8080, x2);
2484 ASSERT_EQUAL_64(0x00007f7f, x3);
armvixlb0c8ae22014-03-21 14:03:59 +00002485 ASSERT_EQUAL_64(0xffffffffffffff80, x4);
2486 ASSERT_EQUAL_64(0x000000000000007f, x5);
2487 ASSERT_EQUAL_64(0xffffffffffff8080, x6);
2488 ASSERT_EQUAL_64(0x0000000000007f7f, x7);
2489 ASSERT_EQUAL_64(0xffffffff80008080, x8);
2490 ASSERT_EQUAL_64(0x000000007fff7f7f, x9);
armvixlad96eda2013-06-14 11:42:37 +01002491
2492 TEARDOWN();
2493}
2494
2495
2496TEST(load_store_regoffset) {
2497 SETUP();
2498
2499 uint32_t src[3] = {1, 2, 3};
2500 uint32_t dst[4] = {0, 0, 0, 0};
2501 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
2502 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
2503
2504 START();
2505 __ Mov(x16, src_base);
2506 __ Mov(x17, dst_base);
2507 __ Mov(x18, src_base + 3 * sizeof(src[0]));
2508 __ Mov(x19, dst_base + 3 * sizeof(dst[0]));
2509 __ Mov(x20, dst_base + 4 * sizeof(dst[0]));
2510 __ Mov(x24, 0);
2511 __ Mov(x25, 4);
2512 __ Mov(x26, -4);
2513 __ Mov(x27, 0xfffffffc); // 32-bit -4.
2514 __ Mov(x28, 0xfffffffe); // 32-bit -2.
2515 __ Mov(x29, 0xffffffff); // 32-bit -1.
2516
2517 __ Ldr(w0, MemOperand(x16, x24));
2518 __ Ldr(x1, MemOperand(x16, x25));
2519 __ Ldr(w2, MemOperand(x18, x26));
2520 __ Ldr(w3, MemOperand(x18, x27, SXTW));
2521 __ Ldr(w4, MemOperand(x18, x28, SXTW, 2));
2522 __ Str(w0, MemOperand(x17, x24));
2523 __ Str(x1, MemOperand(x17, x25));
2524 __ Str(w2, MemOperand(x20, x29, SXTW, 2));
2525 END();
2526
2527 RUN();
2528
2529 ASSERT_EQUAL_64(1, x0);
armvixlb0c8ae22014-03-21 14:03:59 +00002530 ASSERT_EQUAL_64(0x0000000300000002, x1);
armvixlad96eda2013-06-14 11:42:37 +01002531 ASSERT_EQUAL_64(3, x2);
2532 ASSERT_EQUAL_64(3, x3);
2533 ASSERT_EQUAL_64(2, x4);
2534 ASSERT_EQUAL_32(1, dst[0]);
2535 ASSERT_EQUAL_32(2, dst[1]);
2536 ASSERT_EQUAL_32(3, dst[2]);
2537 ASSERT_EQUAL_32(3, dst[3]);
2538
2539 TEARDOWN();
2540}
2541
2542
2543TEST(load_store_float) {
2544 SETUP();
2545
2546 float src[3] = {1.0, 2.0, 3.0};
2547 float dst[3] = {0.0, 0.0, 0.0};
2548 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
2549 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
2550
2551 START();
2552 __ Mov(x17, src_base);
2553 __ Mov(x18, dst_base);
2554 __ Mov(x19, src_base);
2555 __ Mov(x20, dst_base);
2556 __ Mov(x21, src_base);
2557 __ Mov(x22, dst_base);
2558 __ Ldr(s0, MemOperand(x17, sizeof(src[0])));
2559 __ Str(s0, MemOperand(x18, sizeof(dst[0]), PostIndex));
2560 __ Ldr(s1, MemOperand(x19, sizeof(src[0]), PostIndex));
2561 __ Str(s1, MemOperand(x20, 2 * sizeof(dst[0]), PreIndex));
2562 __ Ldr(s2, MemOperand(x21, 2 * sizeof(src[0]), PreIndex));
2563 __ Str(s2, MemOperand(x22, sizeof(dst[0])));
2564 END();
2565
2566 RUN();
2567
2568 ASSERT_EQUAL_FP32(2.0, s0);
2569 ASSERT_EQUAL_FP32(2.0, dst[0]);
2570 ASSERT_EQUAL_FP32(1.0, s1);
2571 ASSERT_EQUAL_FP32(1.0, dst[2]);
2572 ASSERT_EQUAL_FP32(3.0, s2);
2573 ASSERT_EQUAL_FP32(3.0, dst[1]);
2574 ASSERT_EQUAL_64(src_base, x17);
2575 ASSERT_EQUAL_64(dst_base + sizeof(dst[0]), x18);
2576 ASSERT_EQUAL_64(src_base + sizeof(src[0]), x19);
2577 ASSERT_EQUAL_64(dst_base + 2 * sizeof(dst[0]), x20);
2578 ASSERT_EQUAL_64(src_base + 2 * sizeof(src[0]), x21);
2579 ASSERT_EQUAL_64(dst_base, x22);
2580
2581 TEARDOWN();
2582}
2583
2584
2585TEST(load_store_double) {
2586 SETUP();
2587
2588 double src[3] = {1.0, 2.0, 3.0};
2589 double dst[3] = {0.0, 0.0, 0.0};
2590 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
2591 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
2592
2593 START();
2594 __ Mov(x17, src_base);
2595 __ Mov(x18, dst_base);
2596 __ Mov(x19, src_base);
2597 __ Mov(x20, dst_base);
2598 __ Mov(x21, src_base);
2599 __ Mov(x22, dst_base);
2600 __ Ldr(d0, MemOperand(x17, sizeof(src[0])));
2601 __ Str(d0, MemOperand(x18, sizeof(dst[0]), PostIndex));
2602 __ Ldr(d1, MemOperand(x19, sizeof(src[0]), PostIndex));
2603 __ Str(d1, MemOperand(x20, 2 * sizeof(dst[0]), PreIndex));
2604 __ Ldr(d2, MemOperand(x21, 2 * sizeof(src[0]), PreIndex));
2605 __ Str(d2, MemOperand(x22, sizeof(dst[0])));
2606 END();
2607
2608 RUN();
2609
2610 ASSERT_EQUAL_FP64(2.0, d0);
2611 ASSERT_EQUAL_FP64(2.0, dst[0]);
2612 ASSERT_EQUAL_FP64(1.0, d1);
2613 ASSERT_EQUAL_FP64(1.0, dst[2]);
2614 ASSERT_EQUAL_FP64(3.0, d2);
2615 ASSERT_EQUAL_FP64(3.0, dst[1]);
2616 ASSERT_EQUAL_64(src_base, x17);
2617 ASSERT_EQUAL_64(dst_base + sizeof(dst[0]), x18);
2618 ASSERT_EQUAL_64(src_base + sizeof(src[0]), x19);
2619 ASSERT_EQUAL_64(dst_base + 2 * sizeof(dst[0]), x20);
2620 ASSERT_EQUAL_64(src_base + 2 * sizeof(src[0]), x21);
2621 ASSERT_EQUAL_64(dst_base, x22);
2622
2623 TEARDOWN();
2624}
2625
2626
2627TEST(ldp_stp_float) {
2628 SETUP();
2629
2630 float src[2] = {1.0, 2.0};
2631 float dst[3] = {0.0, 0.0, 0.0};
2632 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
2633 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
2634
2635 START();
2636 __ Mov(x16, src_base);
2637 __ Mov(x17, dst_base);
2638 __ Ldp(s31, s0, MemOperand(x16, 2 * sizeof(src[0]), PostIndex));
2639 __ Stp(s0, s31, MemOperand(x17, sizeof(dst[1]), PreIndex));
2640 END();
2641
2642 RUN();
2643
2644 ASSERT_EQUAL_FP32(1.0, s31);
2645 ASSERT_EQUAL_FP32(2.0, s0);
2646 ASSERT_EQUAL_FP32(0.0, dst[0]);
2647 ASSERT_EQUAL_FP32(2.0, dst[1]);
2648 ASSERT_EQUAL_FP32(1.0, dst[2]);
2649 ASSERT_EQUAL_64(src_base + 2 * sizeof(src[0]), x16);
2650 ASSERT_EQUAL_64(dst_base + sizeof(dst[1]), x17);
2651
2652 TEARDOWN();
2653}
2654
2655
2656TEST(ldp_stp_double) {
2657 SETUP();
2658
2659 double src[2] = {1.0, 2.0};
2660 double dst[3] = {0.0, 0.0, 0.0};
2661 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
2662 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
2663
2664 START();
2665 __ Mov(x16, src_base);
2666 __ Mov(x17, dst_base);
2667 __ Ldp(d31, d0, MemOperand(x16, 2 * sizeof(src[0]), PostIndex));
2668 __ Stp(d0, d31, MemOperand(x17, sizeof(dst[1]), PreIndex));
2669 END();
2670
2671 RUN();
2672
2673 ASSERT_EQUAL_FP64(1.0, d31);
2674 ASSERT_EQUAL_FP64(2.0, d0);
2675 ASSERT_EQUAL_FP64(0.0, dst[0]);
2676 ASSERT_EQUAL_FP64(2.0, dst[1]);
2677 ASSERT_EQUAL_FP64(1.0, dst[2]);
2678 ASSERT_EQUAL_64(src_base + 2 * sizeof(src[0]), x16);
2679 ASSERT_EQUAL_64(dst_base + sizeof(dst[1]), x17);
2680
2681 TEARDOWN();
2682}
2683
2684
2685TEST(ldp_stp_offset) {
2686 SETUP();
2687
armvixlb0c8ae22014-03-21 14:03:59 +00002688 uint64_t src[3] = {0x0011223344556677, 0x8899aabbccddeeff,
2689 0xffeeddccbbaa9988};
armvixlad96eda2013-06-14 11:42:37 +01002690 uint64_t dst[7] = {0, 0, 0, 0, 0, 0, 0};
2691 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
2692 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
2693
2694 START();
2695 __ Mov(x16, src_base);
2696 __ Mov(x17, dst_base);
2697 __ Mov(x18, src_base + 24);
2698 __ Mov(x19, dst_base + 56);
2699 __ Ldp(w0, w1, MemOperand(x16));
2700 __ Ldp(w2, w3, MemOperand(x16, 4));
2701 __ Ldp(x4, x5, MemOperand(x16, 8));
2702 __ Ldp(w6, w7, MemOperand(x18, -12));
2703 __ Ldp(x8, x9, MemOperand(x18, -16));
2704 __ Stp(w0, w1, MemOperand(x17));
2705 __ Stp(w2, w3, MemOperand(x17, 8));
2706 __ Stp(x4, x5, MemOperand(x17, 16));
2707 __ Stp(w6, w7, MemOperand(x19, -24));
2708 __ Stp(x8, x9, MemOperand(x19, -16));
2709 END();
2710
2711 RUN();
2712
2713 ASSERT_EQUAL_64(0x44556677, x0);
2714 ASSERT_EQUAL_64(0x00112233, x1);
armvixlb0c8ae22014-03-21 14:03:59 +00002715 ASSERT_EQUAL_64(0x0011223344556677, dst[0]);
armvixlad96eda2013-06-14 11:42:37 +01002716 ASSERT_EQUAL_64(0x00112233, x2);
2717 ASSERT_EQUAL_64(0xccddeeff, x3);
armvixlb0c8ae22014-03-21 14:03:59 +00002718 ASSERT_EQUAL_64(0xccddeeff00112233, dst[1]);
2719 ASSERT_EQUAL_64(0x8899aabbccddeeff, x4);
2720 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[2]);
2721 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5);
2722 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[3]);
armvixlad96eda2013-06-14 11:42:37 +01002723 ASSERT_EQUAL_64(0x8899aabb, x6);
2724 ASSERT_EQUAL_64(0xbbaa9988, x7);
armvixlb0c8ae22014-03-21 14:03:59 +00002725 ASSERT_EQUAL_64(0xbbaa99888899aabb, dst[4]);
2726 ASSERT_EQUAL_64(0x8899aabbccddeeff, x8);
2727 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[5]);
2728 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x9);
2729 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[6]);
armvixlad96eda2013-06-14 11:42:37 +01002730 ASSERT_EQUAL_64(src_base, x16);
2731 ASSERT_EQUAL_64(dst_base, x17);
2732 ASSERT_EQUAL_64(src_base + 24, x18);
2733 ASSERT_EQUAL_64(dst_base + 56, x19);
2734
2735 TEARDOWN();
2736}
2737
2738
armvixlc68cb642014-09-25 18:49:30 +01002739TEST(ldp_stp_offset_wide) {
2740 SETUP();
2741
2742 uint64_t src[3] = {0x0011223344556677, 0x8899aabbccddeeff,
2743 0xffeeddccbbaa9988};
2744 uint64_t dst[7] = {0, 0, 0, 0, 0, 0, 0};
2745 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
2746 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
2747 // Move base too far from the array to force multiple instructions
2748 // to be emitted.
2749 const int64_t base_offset = 1024;
2750
2751 START();
2752 __ Mov(x20, src_base - base_offset);
2753 __ Mov(x21, dst_base - base_offset);
2754 __ Mov(x18, src_base + base_offset + 24);
2755 __ Mov(x19, dst_base + base_offset + 56);
2756 __ Ldp(w0, w1, MemOperand(x20, base_offset));
2757 __ Ldp(w2, w3, MemOperand(x20, base_offset + 4));
2758 __ Ldp(x4, x5, MemOperand(x20, base_offset + 8));
2759 __ Ldp(w6, w7, MemOperand(x18, -12 - base_offset));
2760 __ Ldp(x8, x9, MemOperand(x18, -16 - base_offset));
2761 __ Stp(w0, w1, MemOperand(x21, base_offset));
2762 __ Stp(w2, w3, MemOperand(x21, base_offset + 8));
2763 __ Stp(x4, x5, MemOperand(x21, base_offset + 16));
2764 __ Stp(w6, w7, MemOperand(x19, -24 - base_offset));
2765 __ Stp(x8, x9, MemOperand(x19, -16 - base_offset));
2766 END();
2767
2768 RUN();
2769
2770 ASSERT_EQUAL_64(0x44556677, x0);
2771 ASSERT_EQUAL_64(0x00112233, x1);
2772 ASSERT_EQUAL_64(0x0011223344556677, dst[0]);
2773 ASSERT_EQUAL_64(0x00112233, x2);
2774 ASSERT_EQUAL_64(0xccddeeff, x3);
2775 ASSERT_EQUAL_64(0xccddeeff00112233, dst[1]);
2776 ASSERT_EQUAL_64(0x8899aabbccddeeff, x4);
2777 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[2]);
2778 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5);
2779 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[3]);
2780 ASSERT_EQUAL_64(0x8899aabb, x6);
2781 ASSERT_EQUAL_64(0xbbaa9988, x7);
2782 ASSERT_EQUAL_64(0xbbaa99888899aabb, dst[4]);
2783 ASSERT_EQUAL_64(0x8899aabbccddeeff, x8);
2784 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[5]);
2785 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x9);
2786 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[6]);
2787 ASSERT_EQUAL_64(src_base - base_offset, x20);
2788 ASSERT_EQUAL_64(dst_base - base_offset, x21);
2789 ASSERT_EQUAL_64(src_base + base_offset + 24, x18);
2790 ASSERT_EQUAL_64(dst_base + base_offset + 56, x19);
2791
2792 TEARDOWN();
2793}
2794
2795
armvixlad96eda2013-06-14 11:42:37 +01002796TEST(ldnp_stnp_offset) {
2797 SETUP();
2798
armvixlb0c8ae22014-03-21 14:03:59 +00002799 uint64_t src[3] = {0x0011223344556677, 0x8899aabbccddeeff,
2800 0xffeeddccbbaa9988};
armvixlad96eda2013-06-14 11:42:37 +01002801 uint64_t dst[7] = {0, 0, 0, 0, 0, 0, 0};
2802 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
2803 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
2804
2805 START();
2806 __ Mov(x16, src_base);
2807 __ Mov(x17, dst_base);
2808 __ Mov(x18, src_base + 24);
2809 __ Mov(x19, dst_base + 56);
2810 __ Ldnp(w0, w1, MemOperand(x16));
2811 __ Ldnp(w2, w3, MemOperand(x16, 4));
2812 __ Ldnp(x4, x5, MemOperand(x16, 8));
2813 __ Ldnp(w6, w7, MemOperand(x18, -12));
2814 __ Ldnp(x8, x9, MemOperand(x18, -16));
2815 __ Stnp(w0, w1, MemOperand(x17));
2816 __ Stnp(w2, w3, MemOperand(x17, 8));
2817 __ Stnp(x4, x5, MemOperand(x17, 16));
2818 __ Stnp(w6, w7, MemOperand(x19, -24));
2819 __ Stnp(x8, x9, MemOperand(x19, -16));
2820 END();
2821
2822 RUN();
2823
2824 ASSERT_EQUAL_64(0x44556677, x0);
2825 ASSERT_EQUAL_64(0x00112233, x1);
armvixlb0c8ae22014-03-21 14:03:59 +00002826 ASSERT_EQUAL_64(0x0011223344556677, dst[0]);
armvixlad96eda2013-06-14 11:42:37 +01002827 ASSERT_EQUAL_64(0x00112233, x2);
2828 ASSERT_EQUAL_64(0xccddeeff, x3);
armvixlb0c8ae22014-03-21 14:03:59 +00002829 ASSERT_EQUAL_64(0xccddeeff00112233, dst[1]);
2830 ASSERT_EQUAL_64(0x8899aabbccddeeff, x4);
2831 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[2]);
2832 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5);
2833 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[3]);
armvixlad96eda2013-06-14 11:42:37 +01002834 ASSERT_EQUAL_64(0x8899aabb, x6);
2835 ASSERT_EQUAL_64(0xbbaa9988, x7);
armvixlb0c8ae22014-03-21 14:03:59 +00002836 ASSERT_EQUAL_64(0xbbaa99888899aabb, dst[4]);
2837 ASSERT_EQUAL_64(0x8899aabbccddeeff, x8);
2838 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[5]);
2839 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x9);
2840 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[6]);
armvixlad96eda2013-06-14 11:42:37 +01002841 ASSERT_EQUAL_64(src_base, x16);
2842 ASSERT_EQUAL_64(dst_base, x17);
2843 ASSERT_EQUAL_64(src_base + 24, x18);
2844 ASSERT_EQUAL_64(dst_base + 56, x19);
2845
2846 TEARDOWN();
2847}
2848
2849
2850TEST(ldp_stp_preindex) {
2851 SETUP();
2852
armvixlb0c8ae22014-03-21 14:03:59 +00002853 uint64_t src[3] = {0x0011223344556677, 0x8899aabbccddeeff,
2854 0xffeeddccbbaa9988};
armvixlad96eda2013-06-14 11:42:37 +01002855 uint64_t dst[5] = {0, 0, 0, 0, 0};
2856 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
2857 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
2858
2859 START();
2860 __ Mov(x16, src_base);
2861 __ Mov(x17, dst_base);
2862 __ Mov(x18, dst_base + 16);
2863 __ Ldp(w0, w1, MemOperand(x16, 4, PreIndex));
2864 __ Mov(x19, x16);
2865 __ Ldp(w2, w3, MemOperand(x16, -4, PreIndex));
2866 __ Stp(w2, w3, MemOperand(x17, 4, PreIndex));
2867 __ Mov(x20, x17);
2868 __ Stp(w0, w1, MemOperand(x17, -4, PreIndex));
2869 __ Ldp(x4, x5, MemOperand(x16, 8, PreIndex));
2870 __ Mov(x21, x16);
2871 __ Ldp(x6, x7, MemOperand(x16, -8, PreIndex));
2872 __ Stp(x7, x6, MemOperand(x18, 8, PreIndex));
2873 __ Mov(x22, x18);
2874 __ Stp(x5, x4, MemOperand(x18, -8, PreIndex));
2875 END();
2876
2877 RUN();
2878
2879 ASSERT_EQUAL_64(0x00112233, x0);
2880 ASSERT_EQUAL_64(0xccddeeff, x1);
2881 ASSERT_EQUAL_64(0x44556677, x2);
2882 ASSERT_EQUAL_64(0x00112233, x3);
armvixlb0c8ae22014-03-21 14:03:59 +00002883 ASSERT_EQUAL_64(0xccddeeff00112233, dst[0]);
2884 ASSERT_EQUAL_64(0x0000000000112233, dst[1]);
2885 ASSERT_EQUAL_64(0x8899aabbccddeeff, x4);
2886 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5);
2887 ASSERT_EQUAL_64(0x0011223344556677, x6);
2888 ASSERT_EQUAL_64(0x8899aabbccddeeff, x7);
2889 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[2]);
2890 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[3]);
2891 ASSERT_EQUAL_64(0x0011223344556677, dst[4]);
armvixlad96eda2013-06-14 11:42:37 +01002892 ASSERT_EQUAL_64(src_base, x16);
2893 ASSERT_EQUAL_64(dst_base, x17);
2894 ASSERT_EQUAL_64(dst_base + 16, x18);
2895 ASSERT_EQUAL_64(src_base + 4, x19);
2896 ASSERT_EQUAL_64(dst_base + 4, x20);
2897 ASSERT_EQUAL_64(src_base + 8, x21);
2898 ASSERT_EQUAL_64(dst_base + 24, x22);
2899
2900 TEARDOWN();
2901}
2902
2903
armvixlc68cb642014-09-25 18:49:30 +01002904TEST(ldp_stp_preindex_wide) {
2905 SETUP();
2906
2907 uint64_t src[3] = {0x0011223344556677, 0x8899aabbccddeeff,
2908 0xffeeddccbbaa9988};
2909 uint64_t dst[5] = {0, 0, 0, 0, 0};
2910 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
2911 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
2912 // Move base too far from the array to force multiple instructions
2913 // to be emitted.
2914 const int64_t base_offset = 1024;
2915
2916 START();
2917 __ Mov(x24, src_base - base_offset);
2918 __ Mov(x25, dst_base + base_offset);
2919 __ Mov(x18, dst_base + base_offset + 16);
2920 __ Ldp(w0, w1, MemOperand(x24, base_offset + 4, PreIndex));
2921 __ Mov(x19, x24);
2922 __ Mov(x24, src_base - base_offset + 4);
2923 __ Ldp(w2, w3, MemOperand(x24, base_offset - 4, PreIndex));
2924 __ Stp(w2, w3, MemOperand(x25, 4 - base_offset , PreIndex));
2925 __ Mov(x20, x25);
2926 __ Mov(x25, dst_base + base_offset + 4);
2927 __ Mov(x24, src_base - base_offset);
2928 __ Stp(w0, w1, MemOperand(x25, -4 - base_offset, PreIndex));
2929 __ Ldp(x4, x5, MemOperand(x24, base_offset + 8, PreIndex));
2930 __ Mov(x21, x24);
2931 __ Mov(x24, src_base - base_offset + 8);
2932 __ Ldp(x6, x7, MemOperand(x24, base_offset - 8, PreIndex));
2933 __ Stp(x7, x6, MemOperand(x18, 8 - base_offset, PreIndex));
2934 __ Mov(x22, x18);
2935 __ Mov(x18, dst_base + base_offset + 16 + 8);
2936 __ Stp(x5, x4, MemOperand(x18, -8 - base_offset, PreIndex));
2937 END();
2938
2939 RUN();
2940
2941 ASSERT_EQUAL_64(0x00112233, x0);
2942 ASSERT_EQUAL_64(0xccddeeff, x1);
2943 ASSERT_EQUAL_64(0x44556677, x2);
2944 ASSERT_EQUAL_64(0x00112233, x3);
2945 ASSERT_EQUAL_64(0xccddeeff00112233, dst[0]);
2946 ASSERT_EQUAL_64(0x0000000000112233, dst[1]);
2947 ASSERT_EQUAL_64(0x8899aabbccddeeff, x4);
2948 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x5);
2949 ASSERT_EQUAL_64(0x0011223344556677, x6);
2950 ASSERT_EQUAL_64(0x8899aabbccddeeff, x7);
2951 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[2]);
2952 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[3]);
2953 ASSERT_EQUAL_64(0x0011223344556677, dst[4]);
2954 ASSERT_EQUAL_64(src_base, x24);
2955 ASSERT_EQUAL_64(dst_base, x25);
2956 ASSERT_EQUAL_64(dst_base + 16, x18);
2957 ASSERT_EQUAL_64(src_base + 4, x19);
2958 ASSERT_EQUAL_64(dst_base + 4, x20);
2959 ASSERT_EQUAL_64(src_base + 8, x21);
2960 ASSERT_EQUAL_64(dst_base + 24, x22);
2961
2962 TEARDOWN();
2963}
2964
2965
armvixlad96eda2013-06-14 11:42:37 +01002966TEST(ldp_stp_postindex) {
2967 SETUP();
2968
armvixlb0c8ae22014-03-21 14:03:59 +00002969 uint64_t src[4] = {0x0011223344556677, 0x8899aabbccddeeff,
2970 0xffeeddccbbaa9988, 0x7766554433221100};
armvixlad96eda2013-06-14 11:42:37 +01002971 uint64_t dst[5] = {0, 0, 0, 0, 0};
2972 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
2973 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
2974
2975 START();
2976 __ Mov(x16, src_base);
2977 __ Mov(x17, dst_base);
2978 __ Mov(x18, dst_base + 16);
2979 __ Ldp(w0, w1, MemOperand(x16, 4, PostIndex));
2980 __ Mov(x19, x16);
2981 __ Ldp(w2, w3, MemOperand(x16, -4, PostIndex));
2982 __ Stp(w2, w3, MemOperand(x17, 4, PostIndex));
2983 __ Mov(x20, x17);
2984 __ Stp(w0, w1, MemOperand(x17, -4, PostIndex));
2985 __ Ldp(x4, x5, MemOperand(x16, 8, PostIndex));
2986 __ Mov(x21, x16);
2987 __ Ldp(x6, x7, MemOperand(x16, -8, PostIndex));
2988 __ Stp(x7, x6, MemOperand(x18, 8, PostIndex));
2989 __ Mov(x22, x18);
2990 __ Stp(x5, x4, MemOperand(x18, -8, PostIndex));
2991 END();
2992
2993 RUN();
2994
2995 ASSERT_EQUAL_64(0x44556677, x0);
2996 ASSERT_EQUAL_64(0x00112233, x1);
2997 ASSERT_EQUAL_64(0x00112233, x2);
2998 ASSERT_EQUAL_64(0xccddeeff, x3);
armvixlb0c8ae22014-03-21 14:03:59 +00002999 ASSERT_EQUAL_64(0x4455667700112233, dst[0]);
3000 ASSERT_EQUAL_64(0x0000000000112233, dst[1]);
3001 ASSERT_EQUAL_64(0x0011223344556677, x4);
3002 ASSERT_EQUAL_64(0x8899aabbccddeeff, x5);
3003 ASSERT_EQUAL_64(0x8899aabbccddeeff, x6);
3004 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x7);
3005 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[2]);
3006 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[3]);
3007 ASSERT_EQUAL_64(0x0011223344556677, dst[4]);
armvixlad96eda2013-06-14 11:42:37 +01003008 ASSERT_EQUAL_64(src_base, x16);
3009 ASSERT_EQUAL_64(dst_base, x17);
3010 ASSERT_EQUAL_64(dst_base + 16, x18);
3011 ASSERT_EQUAL_64(src_base + 4, x19);
3012 ASSERT_EQUAL_64(dst_base + 4, x20);
3013 ASSERT_EQUAL_64(src_base + 8, x21);
3014 ASSERT_EQUAL_64(dst_base + 24, x22);
3015
3016 TEARDOWN();
3017}
3018
3019
armvixlc68cb642014-09-25 18:49:30 +01003020TEST(ldp_stp_postindex_wide) {
3021 SETUP();
3022
3023 uint64_t src[4] = {0x0011223344556677, 0x8899aabbccddeeff,
3024 0xffeeddccbbaa9988, 0x7766554433221100};
3025 uint64_t dst[5] = {0, 0, 0, 0, 0};
3026 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3027 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3028 // Move base too far from the array to force multiple instructions
3029 // to be emitted.
3030 const int64_t base_offset = 1024;
3031
3032 START();
3033 __ Mov(x24, src_base);
3034 __ Mov(x25, dst_base);
3035 __ Mov(x18, dst_base + 16);
3036 __ Ldp(w0, w1, MemOperand(x24, base_offset + 4, PostIndex));
3037 __ Mov(x19, x24);
3038 __ Sub(x24, x24, base_offset);
3039 __ Ldp(w2, w3, MemOperand(x24, base_offset - 4, PostIndex));
3040 __ Stp(w2, w3, MemOperand(x25, 4 - base_offset, PostIndex));
3041 __ Mov(x20, x25);
3042 __ Sub(x24, x24, base_offset);
3043 __ Add(x25, x25, base_offset);
3044 __ Stp(w0, w1, MemOperand(x25, -4 - base_offset, PostIndex));
3045 __ Ldp(x4, x5, MemOperand(x24, base_offset + 8, PostIndex));
3046 __ Mov(x21, x24);
3047 __ Sub(x24, x24, base_offset);
3048 __ Ldp(x6, x7, MemOperand(x24, base_offset - 8, PostIndex));
3049 __ Stp(x7, x6, MemOperand(x18, 8 - base_offset, PostIndex));
3050 __ Mov(x22, x18);
3051 __ Add(x18, x18, base_offset);
3052 __ Stp(x5, x4, MemOperand(x18, -8 - base_offset, PostIndex));
3053 END();
3054
3055 RUN();
3056
3057 ASSERT_EQUAL_64(0x44556677, x0);
3058 ASSERT_EQUAL_64(0x00112233, x1);
3059 ASSERT_EQUAL_64(0x00112233, x2);
3060 ASSERT_EQUAL_64(0xccddeeff, x3);
3061 ASSERT_EQUAL_64(0x4455667700112233, dst[0]);
3062 ASSERT_EQUAL_64(0x0000000000112233, dst[1]);
3063 ASSERT_EQUAL_64(0x0011223344556677, x4);
3064 ASSERT_EQUAL_64(0x8899aabbccddeeff, x5);
3065 ASSERT_EQUAL_64(0x8899aabbccddeeff, x6);
3066 ASSERT_EQUAL_64(0xffeeddccbbaa9988, x7);
3067 ASSERT_EQUAL_64(0xffeeddccbbaa9988, dst[2]);
3068 ASSERT_EQUAL_64(0x8899aabbccddeeff, dst[3]);
3069 ASSERT_EQUAL_64(0x0011223344556677, dst[4]);
3070 ASSERT_EQUAL_64(src_base + base_offset, x24);
3071 ASSERT_EQUAL_64(dst_base - base_offset, x25);
3072 ASSERT_EQUAL_64(dst_base - base_offset + 16, x18);
3073 ASSERT_EQUAL_64(src_base + base_offset + 4, x19);
3074 ASSERT_EQUAL_64(dst_base - base_offset + 4, x20);
3075 ASSERT_EQUAL_64(src_base + base_offset + 8, x21);
3076 ASSERT_EQUAL_64(dst_base - base_offset + 24, x22);
3077
3078 TEARDOWN();
3079}
3080
3081
armvixlad96eda2013-06-14 11:42:37 +01003082TEST(ldp_sign_extend) {
3083 SETUP();
3084
3085 uint32_t src[2] = {0x80000000, 0x7fffffff};
3086 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3087
3088 START();
3089 __ Mov(x24, src_base);
3090 __ Ldpsw(x0, x1, MemOperand(x24));
3091 END();
3092
3093 RUN();
3094
armvixlb0c8ae22014-03-21 14:03:59 +00003095 ASSERT_EQUAL_64(0xffffffff80000000, x0);
3096 ASSERT_EQUAL_64(0x000000007fffffff, x1);
armvixlad96eda2013-06-14 11:42:37 +01003097
3098 TEARDOWN();
3099}
3100
3101
3102TEST(ldur_stur) {
3103 SETUP();
3104
armvixlb0c8ae22014-03-21 14:03:59 +00003105 int64_t src[2] = {0x0123456789abcdef, 0x0123456789abcdef};
armvixlad96eda2013-06-14 11:42:37 +01003106 int64_t dst[5] = {0, 0, 0, 0, 0};
3107 uintptr_t src_base = reinterpret_cast<uintptr_t>(src);
3108 uintptr_t dst_base = reinterpret_cast<uintptr_t>(dst);
3109
3110 START();
3111 __ Mov(x17, src_base);
3112 __ Mov(x18, dst_base);
3113 __ Mov(x19, src_base + 16);
3114 __ Mov(x20, dst_base + 32);
3115 __ Mov(x21, dst_base + 40);
3116 __ Ldr(w0, MemOperand(x17, 1));
3117 __ Str(w0, MemOperand(x18, 2));
3118 __ Ldr(x1, MemOperand(x17, 3));
3119 __ Str(x1, MemOperand(x18, 9));
3120 __ Ldr(w2, MemOperand(x19, -9));
3121 __ Str(w2, MemOperand(x20, -5));
3122 __ Ldrb(w3, MemOperand(x19, -1));
3123 __ Strb(w3, MemOperand(x21, -1));
3124 END();
3125
3126 RUN();
3127
3128 ASSERT_EQUAL_64(0x6789abcd, x0);
armvixlb0c8ae22014-03-21 14:03:59 +00003129 ASSERT_EQUAL_64(0x00006789abcd0000, dst[0]);
3130 ASSERT_EQUAL_64(0xabcdef0123456789, x1);
3131 ASSERT_EQUAL_64(0xcdef012345678900, dst[1]);
armvixlad96eda2013-06-14 11:42:37 +01003132 ASSERT_EQUAL_64(0x000000ab, dst[2]);
3133 ASSERT_EQUAL_64(0xabcdef01, x2);
armvixlb0c8ae22014-03-21 14:03:59 +00003134 ASSERT_EQUAL_64(0x00abcdef01000000, dst[3]);
armvixlad96eda2013-06-14 11:42:37 +01003135 ASSERT_EQUAL_64(0x00000001, x3);
armvixlb0c8ae22014-03-21 14:03:59 +00003136 ASSERT_EQUAL_64(0x0100000000000000, dst[4]);
armvixlad96eda2013-06-14 11:42:37 +01003137 ASSERT_EQUAL_64(src_base, x17);
3138 ASSERT_EQUAL_64(dst_base, x18);
3139 ASSERT_EQUAL_64(src_base + 16, x19);
3140 ASSERT_EQUAL_64(dst_base + 32, x20);
3141
3142 TEARDOWN();
3143}
3144
3145
3146TEST(ldr_literal) {
3147 SETUP();
3148
3149 START();
armvixlb0c8ae22014-03-21 14:03:59 +00003150 __ Ldr(x2, 0x1234567890abcdef);
armvixlad96eda2013-06-14 11:42:37 +01003151 __ Ldr(w3, 0xfedcba09);
armvixlc68cb642014-09-25 18:49:30 +01003152 __ Ldrsw(x4, 0x7fffffff);
3153 __ Ldrsw(x5, 0x80000000);
armvixlad96eda2013-06-14 11:42:37 +01003154 __ Ldr(d13, 1.234);
3155 __ Ldr(s25, 2.5);
3156 END();
3157
3158 RUN();
3159
armvixlb0c8ae22014-03-21 14:03:59 +00003160 ASSERT_EQUAL_64(0x1234567890abcdef, x2);
armvixlad96eda2013-06-14 11:42:37 +01003161 ASSERT_EQUAL_64(0xfedcba09, x3);
armvixlc68cb642014-09-25 18:49:30 +01003162 ASSERT_EQUAL_64(0x7fffffff, x4);
3163 ASSERT_EQUAL_64(0xffffffff80000000, x5);
armvixlad96eda2013-06-14 11:42:37 +01003164 ASSERT_EQUAL_FP64(1.234, d13);
3165 ASSERT_EQUAL_FP32(2.5, s25);
3166
3167 TEARDOWN();
3168}
3169
3170
armvixlc68cb642014-09-25 18:49:30 +01003171TEST(ldr_literal_range) {
3172 SETUP();
armvixlad96eda2013-06-14 11:42:37 +01003173
3174 START();
armvixlc68cb642014-09-25 18:49:30 +01003175 // Make sure the pool is empty;
3176 masm.EmitLiteralPool(LiteralPool::kBranchRequired);
armvixlad96eda2013-06-14 11:42:37 +01003177 ASSERT_LITERAL_POOL_SIZE(0);
3178
armvixlc68cb642014-09-25 18:49:30 +01003179 // Create some literal pool entries.
armvixlb0c8ae22014-03-21 14:03:59 +00003180 __ Ldr(x0, 0x1234567890abcdef);
armvixlad96eda2013-06-14 11:42:37 +01003181 __ Ldr(w1, 0xfedcba09);
armvixlc68cb642014-09-25 18:49:30 +01003182 __ Ldrsw(x2, 0x7fffffff);
3183 __ Ldrsw(x3, 0x80000000);
armvixlad96eda2013-06-14 11:42:37 +01003184 __ Ldr(d0, 1.234);
3185 __ Ldr(s1, 2.5);
armvixlc68cb642014-09-25 18:49:30 +01003186 ASSERT_LITERAL_POOL_SIZE(32);
armvixlad96eda2013-06-14 11:42:37 +01003187
armvixlc68cb642014-09-25 18:49:30 +01003188 // Emit more code than the maximum literal load range to ensure the pool
3189 // should be emitted.
armvixl330dc712014-11-25 10:38:32 +00003190 const ptrdiff_t end = masm.CursorOffset() + 2 * kMaxLoadLiteralRange;
3191 while (masm.CursorOffset() < end) {
armvixlad96eda2013-06-14 11:42:37 +01003192 __ Nop();
armvixlad96eda2013-06-14 11:42:37 +01003193 }
3194
armvixlc68cb642014-09-25 18:49:30 +01003195 // The pool should have been emitted.
armvixlad96eda2013-06-14 11:42:37 +01003196 ASSERT_LITERAL_POOL_SIZE(0);
3197
3198 // These loads should be after the pool (and will require a new one).
armvixlb0c8ae22014-03-21 14:03:59 +00003199 __ Ldr(x4, 0x34567890abcdef12);
armvixlad96eda2013-06-14 11:42:37 +01003200 __ Ldr(w5, 0xdcba09fe);
armvixlc68cb642014-09-25 18:49:30 +01003201 __ Ldrsw(x6, 0x7fffffff);
3202 __ Ldrsw(x7, 0x80000000);
armvixlad96eda2013-06-14 11:42:37 +01003203 __ Ldr(d4, 123.4);
3204 __ Ldr(s5, 250.0);
armvixlc68cb642014-09-25 18:49:30 +01003205 ASSERT_LITERAL_POOL_SIZE(32);
armvixlad96eda2013-06-14 11:42:37 +01003206 END();
3207
3208 RUN();
3209
3210 // Check that the literals loaded correctly.
armvixlb0c8ae22014-03-21 14:03:59 +00003211 ASSERT_EQUAL_64(0x1234567890abcdef, x0);
armvixlad96eda2013-06-14 11:42:37 +01003212 ASSERT_EQUAL_64(0xfedcba09, x1);
armvixlc68cb642014-09-25 18:49:30 +01003213 ASSERT_EQUAL_64(0x7fffffff, x2);
3214 ASSERT_EQUAL_64(0xffffffff80000000, x3);
armvixlad96eda2013-06-14 11:42:37 +01003215 ASSERT_EQUAL_FP64(1.234, d0);
3216 ASSERT_EQUAL_FP32(2.5, s1);
armvixlb0c8ae22014-03-21 14:03:59 +00003217 ASSERT_EQUAL_64(0x34567890abcdef12, x4);
armvixlad96eda2013-06-14 11:42:37 +01003218 ASSERT_EQUAL_64(0xdcba09fe, x5);
armvixlc68cb642014-09-25 18:49:30 +01003219 ASSERT_EQUAL_64(0x7fffffff, x6);
3220 ASSERT_EQUAL_64(0xffffffff80000000, x7);
armvixlad96eda2013-06-14 11:42:37 +01003221 ASSERT_EQUAL_FP64(123.4, d4);
3222 ASSERT_EQUAL_FP32(250.0, s5);
3223
3224 TEARDOWN();
3225}
3226
3227
armvixlc68cb642014-09-25 18:49:30 +01003228template <typename T>
3229void LoadIntValueHelper(T values[], int card) {
3230 SETUP();
3231
3232 const bool is_32bits = (sizeof(T) == 4);
3233 const Register& tgt1 = is_32bits ? w1 : x1;
3234 const Register& tgt2 = is_32bits ? w2 : x2;
3235
3236 START();
3237 __ Mov(x0, 0);
3238
3239 // If one of the values differ then x0 will be one.
3240 for (int i = 0; i < card; ++i) {
3241 __ Mov(tgt1, values[i]);
3242 __ Ldr(tgt2, values[i]);
3243 __ Cmp(tgt1, tgt2);
3244 __ Cset(x0, ne);
3245 }
3246 END();
3247
3248 RUN();
3249
3250 // If one of the values differs, the trace can be used to identify which one.
3251 ASSERT_EQUAL_64(0, x0);
3252
3253 TEARDOWN();
armvixlad96eda2013-06-14 11:42:37 +01003254}
3255
3256
armvixlc68cb642014-09-25 18:49:30 +01003257TEST(ldr_literal_values_x) {
3258 static const uint64_t kValues[] = {
3259 0x8000000000000000, 0x7fffffffffffffff, 0x0000000000000000,
3260 0xffffffffffffffff, 0x00ff00ff00ff00ff, 0x1234567890abcdef
3261 };
3262
3263 LoadIntValueHelper(kValues, sizeof(kValues) / sizeof(kValues[0]));
armvixlad96eda2013-06-14 11:42:37 +01003264}
3265
3266
armvixlc68cb642014-09-25 18:49:30 +01003267TEST(ldr_literal_values_w) {
3268 static const uint32_t kValues[] = {
3269 0x80000000, 0x7fffffff, 0x00000000, 0xffffffff, 0x00ff00ff, 0x12345678,
3270 0x90abcdef
3271 };
3272
3273 LoadIntValueHelper(kValues, sizeof(kValues) / sizeof(kValues[0]));
armvixlad96eda2013-06-14 11:42:37 +01003274}
3275
3276
armvixlc68cb642014-09-25 18:49:30 +01003277template <typename T>
3278void LoadFPValueHelper(T values[], int card) {
3279 SETUP();
3280
3281 const bool is_32bits = (sizeof(T) == 4);
3282 const FPRegister& fp_tgt = is_32bits ? s2 : d2;
3283 const Register& tgt1 = is_32bits ? w1 : x1;
3284 const Register& tgt2 = is_32bits ? w2 : x2;
3285
3286 START();
3287 __ Mov(x0, 0);
3288
3289 // If one of the values differ then x0 will be one.
3290 for (int i = 0; i < card; ++i) {
3291 __ Mov(tgt1, is_32bits ? float_to_rawbits(values[i])
3292 : double_to_rawbits(values[i]));
3293 __ Ldr(fp_tgt, values[i]);
3294 __ Fmov(tgt2, fp_tgt);
3295 __ Cmp(tgt1, tgt2);
3296 __ Cset(x0, ne);
3297 }
3298 END();
3299
3300 RUN();
3301
3302 // If one of the values differs, the trace can be used to identify which one.
3303 ASSERT_EQUAL_64(0, x0);
3304
3305 TEARDOWN();
3306}
3307
3308TEST(ldr_literal_values_d) {
3309 static const double kValues[] = {
3310 -0.0, 0.0, -1.0, 1.0, -1e10, 1e10
3311 };
3312
3313 LoadFPValueHelper(kValues, sizeof(kValues) / sizeof(kValues[0]));
armvixlad96eda2013-06-14 11:42:37 +01003314}
3315
3316
armvixlc68cb642014-09-25 18:49:30 +01003317TEST(ldr_literal_values_s) {
3318 static const float kValues[] = {
3319 -0.0, 0.0, -1.0, 1.0, -1e10, 1e10
3320 };
3321
3322 LoadFPValueHelper(kValues, sizeof(kValues) / sizeof(kValues[0]));
armvixlad96eda2013-06-14 11:42:37 +01003323}
3324
3325
armvixlc68cb642014-09-25 18:49:30 +01003326TEST(ldr_literal_custom) {
armvixlc68cb642014-09-25 18:49:30 +01003327 SETUP();
3328 ALLOW_ASM();
3329
armvixl330dc712014-11-25 10:38:32 +00003330 Label end_of_pool_before;
3331 Label end_of_pool_after;
3332 Literal<uint64_t> before_x(0x1234567890abcdef);
3333 Literal<uint32_t> before_w(0xfedcba09);
3334 Literal<uint32_t> before_sx(0x80000000);
3335 Literal<double> before_d(1.234);
3336 Literal<float> before_s(2.5);
3337 Literal<uint64_t> after_x(0x1234567890abcdef);
3338 Literal<uint32_t> after_w(0xfedcba09);
3339 Literal<uint32_t> after_sx(0x80000000);
3340 Literal<double> after_d(1.234);
3341 Literal<float> after_s(2.5);
armvixlc68cb642014-09-25 18:49:30 +01003342
3343 START();
armvixlc68cb642014-09-25 18:49:30 +01003344
armvixl330dc712014-11-25 10:38:32 +00003345 // Manually generate a pool.
3346 __ B(&end_of_pool_before);
3347 __ place(&before_x);
3348 __ place(&before_w);
3349 __ place(&before_sx);
3350 __ place(&before_d);
3351 __ place(&before_s);
3352 __ Bind(&end_of_pool_before);
3353
3354 __ ldr(x2, &before_x);
3355 __ ldr(w3, &before_w);
3356 __ ldrsw(x5, &before_sx);
3357 __ ldr(d13, &before_d);
3358 __ ldr(s25, &before_s);
3359
3360 __ ldr(x6, &after_x);
3361 __ ldr(w7, &after_w);
3362 __ ldrsw(x8, &after_sx);
3363 __ ldr(d14, &after_d);
3364 __ ldr(s26, &after_s);
3365
3366 // Manually generate a pool.
3367 __ B(&end_of_pool_after);
3368 __ place(&after_x);
3369 __ place(&after_w);
3370 __ place(&after_sx);
3371 __ place(&after_d);
3372 __ place(&after_s);
3373 __ Bind(&end_of_pool_after);
3374
armvixlc68cb642014-09-25 18:49:30 +01003375 END();
3376
3377 RUN();
3378
3379 ASSERT_EQUAL_64(0x1234567890abcdef, x2);
3380 ASSERT_EQUAL_64(0xfedcba09, x3);
3381 ASSERT_EQUAL_64(0xffffffff80000000, x5);
3382 ASSERT_EQUAL_FP64(1.234, d13);
3383 ASSERT_EQUAL_FP32(2.5, s25);
3384
armvixl330dc712014-11-25 10:38:32 +00003385 ASSERT_EQUAL_64(0x1234567890abcdef, x6);
3386 ASSERT_EQUAL_64(0xfedcba09, x7);
3387 ASSERT_EQUAL_64(0xffffffff80000000, x8);
3388 ASSERT_EQUAL_FP64(1.234, d14);
3389 ASSERT_EQUAL_FP32(2.5, s26);
3390
3391 TEARDOWN();
3392}
3393
3394
3395TEST(ldr_literal_custom_shared) {
3396 SETUP();
3397 ALLOW_ASM();
3398
3399 Label end_of_pool_before;
3400 Label end_of_pool_after;
3401 Literal<uint64_t> before_x(0x1234567890abcdef);
3402 Literal<uint32_t> before_w(0xfedcba09);
3403 Literal<double> before_d(1.234);
3404 Literal<float> before_s(2.5);
3405 Literal<uint64_t> after_x(0x1234567890abcdef);
3406 Literal<uint32_t> after_w(0xfedcba09);
3407 Literal<double> after_d(1.234);
3408 Literal<float> after_s(2.5);
3409
3410 START();
3411
3412 // Manually generate a pool.
3413 __ B(&end_of_pool_before);
3414 __ place(&before_x);
3415 __ place(&before_w);
3416 __ place(&before_d);
3417 __ place(&before_s);
3418 __ Bind(&end_of_pool_before);
3419
3420 // Load the entries several times to test that literals can be shared.
3421 for (int i = 0; i < 50; i++) {
3422 __ ldr(x2, &before_x);
3423 __ ldr(w3, &before_w);
3424 __ ldrsw(x5, &before_w); // Re-use before_w.
3425 __ ldr(d13, &before_d);
3426 __ ldr(s25, &before_s);
3427
3428 __ ldr(x6, &after_x);
3429 __ ldr(w7, &after_w);
3430 __ ldrsw(x8, &after_w); // Re-use after_w.
3431 __ ldr(d14, &after_d);
3432 __ ldr(s26, &after_s);
3433 }
3434
3435 // Manually generate a pool.
3436 __ B(&end_of_pool_after);
3437 __ place(&after_x);
3438 __ place(&after_w);
3439 __ place(&after_d);
3440 __ place(&after_s);
3441 __ Bind(&end_of_pool_after);
3442
3443 END();
3444
3445 RUN();
3446
3447 ASSERT_EQUAL_64(0x1234567890abcdef, x2);
3448 ASSERT_EQUAL_64(0xfedcba09, x3);
3449 ASSERT_EQUAL_64(0xfffffffffedcba09, x5);
3450 ASSERT_EQUAL_FP64(1.234, d13);
3451 ASSERT_EQUAL_FP32(2.5, s25);
3452
3453 ASSERT_EQUAL_64(0x1234567890abcdef, x6);
3454 ASSERT_EQUAL_64(0xfedcba09, x7);
3455 ASSERT_EQUAL_64(0xfffffffffedcba09, x8);
3456 ASSERT_EQUAL_FP64(1.234, d14);
3457 ASSERT_EQUAL_FP32(2.5, s26);
3458
3459 TEARDOWN();
3460}
3461
3462
3463TEST(prfm_offset) {
3464 SETUP();
3465
3466 START();
3467 // The address used in prfm doesn't have to be valid.
3468 __ Mov(x0, 0x0123456789abcdef);
3469
3470 for (int i = 0; i < (1 << ImmPrefetchOperation_width); i++) {
3471 // Unallocated prefetch operations are ignored, so test all of them.
3472 PrefetchOperation op = static_cast<PrefetchOperation>(i);
3473
3474 __ Prfm(op, MemOperand(x0));
3475 __ Prfm(op, MemOperand(x0, 8));
3476 __ Prfm(op, MemOperand(x0, 32760));
3477 __ Prfm(op, MemOperand(x0, 32768));
3478
3479 __ Prfm(op, MemOperand(x0, 1));
3480 __ Prfm(op, MemOperand(x0, 9));
3481 __ Prfm(op, MemOperand(x0, 255));
3482 __ Prfm(op, MemOperand(x0, 257));
3483 __ Prfm(op, MemOperand(x0, -1));
3484 __ Prfm(op, MemOperand(x0, -9));
3485 __ Prfm(op, MemOperand(x0, -255));
3486 __ Prfm(op, MemOperand(x0, -257));
3487
3488 __ Prfm(op, MemOperand(x0, 0xfedcba9876543210));
3489 }
3490
3491 END();
3492 RUN();
3493 TEARDOWN();
3494}
3495
3496
3497TEST(prfm_regoffset) {
3498 SETUP();
3499
3500 START();
3501 // The address used in prfm doesn't have to be valid.
3502 __ Mov(x0, 0x0123456789abcdef);
3503
3504 CPURegList inputs(CPURegister::kRegister, kXRegSize, 10, 18);
3505 __ Mov(x10, 0);
3506 __ Mov(x11, 1);
3507 __ Mov(x12, 8);
3508 __ Mov(x13, 255);
3509 __ Mov(x14, -0);
3510 __ Mov(x15, -1);
3511 __ Mov(x16, -8);
3512 __ Mov(x17, -255);
3513 __ Mov(x18, 0xfedcba9876543210);
3514
3515 for (int i = 0; i < (1 << ImmPrefetchOperation_width); i++) {
3516 // Unallocated prefetch operations are ignored, so test all of them.
3517 PrefetchOperation op = static_cast<PrefetchOperation>(i);
3518
3519 CPURegList loop = inputs;
3520 while (!loop.IsEmpty()) {
3521 Register input(loop.PopLowestIndex());
3522 __ Prfm(op, MemOperand(x0, input));
3523 __ Prfm(op, MemOperand(x0, input, UXTW));
3524 __ Prfm(op, MemOperand(x0, input, UXTW, 3));
3525 __ Prfm(op, MemOperand(x0, input, LSL));
3526 __ Prfm(op, MemOperand(x0, input, LSL, 3));
3527 __ Prfm(op, MemOperand(x0, input, SXTW));
3528 __ Prfm(op, MemOperand(x0, input, SXTW, 3));
3529 __ Prfm(op, MemOperand(x0, input, SXTX));
3530 __ Prfm(op, MemOperand(x0, input, SXTX, 3));
3531 }
3532 }
3533
3534 END();
3535 RUN();
3536 TEARDOWN();
3537}
3538
3539
3540TEST(prfm_literal_imm19) {
3541 SETUP();
3542 ALLOW_ASM();
3543 START();
3544
3545 for (int i = 0; i < (1 << ImmPrefetchOperation_width); i++) {
3546 // Unallocated prefetch operations are ignored, so test all of them.
3547 PrefetchOperation op = static_cast<PrefetchOperation>(i);
3548
3549 // The address used in prfm doesn't have to be valid.
3550 __ prfm(op, 0);
3551 __ prfm(op, 1);
3552 __ prfm(op, -1);
3553 __ prfm(op, 1000);
3554 __ prfm(op, -1000);
3555 __ prfm(op, 0x3ffff);
3556 __ prfm(op, -0x40000);
3557 }
3558
3559 END();
3560 RUN();
3561 TEARDOWN();
3562}
3563
3564
3565TEST(prfm_literal) {
3566 SETUP();
3567 ALLOW_ASM();
3568
3569 Label end_of_pool_before;
3570 Label end_of_pool_after;
3571 Literal<uint64_t> before(0);
3572 Literal<uint64_t> after(0);
3573
3574 START();
3575
3576 // Manually generate a pool.
3577 __ B(&end_of_pool_before);
3578 __ place(&before);
3579 __ Bind(&end_of_pool_before);
3580
3581 for (int i = 0; i < (1 << ImmPrefetchOperation_width); i++) {
3582 // Unallocated prefetch operations are ignored, so test all of them.
3583 PrefetchOperation op = static_cast<PrefetchOperation>(i);
3584
3585 CodeBufferCheckScope guard(&masm, 2 * kInstructionSize);
3586 __ prfm(op, &before);
3587 __ prfm(op, &after);
3588 }
3589
3590 // Manually generate a pool.
3591 __ B(&end_of_pool_after);
3592 __ place(&after);
3593 __ Bind(&end_of_pool_after);
3594
3595 END();
3596 RUN();
3597 TEARDOWN();
3598}
3599
3600
3601TEST(prfm_wide) {
3602 SETUP();
3603
3604 START();
3605 // The address used in prfm doesn't have to be valid.
3606 __ Mov(x0, 0x0123456789abcdef);
3607
3608 for (int i = 0; i < (1 << ImmPrefetchOperation_width); i++) {
3609 // Unallocated prefetch operations are ignored, so test all of them.
3610 PrefetchOperation op = static_cast<PrefetchOperation>(i);
3611
3612 __ Prfm(op, MemOperand(x0, 0x40000));
3613 __ Prfm(op, MemOperand(x0, -0x40001));
3614 __ Prfm(op, MemOperand(x0, UINT64_C(0x5555555555555555)));
3615 __ Prfm(op, MemOperand(x0, UINT64_C(0xfedcba9876543210)));
3616 }
3617
3618 END();
3619 RUN();
3620 TEARDOWN();
3621}
3622
3623
3624TEST(load_prfm_literal) {
3625 // Test literals shared between both prfm and ldr.
3626 SETUP();
3627 ALLOW_ASM();
3628
3629 Label end_of_pool_before;
3630 Label end_of_pool_after;
3631 Literal<uint64_t> before_x(0x1234567890abcdef);
3632 Literal<uint32_t> before_w(0xfedcba09);
3633 Literal<uint32_t> before_sx(0x80000000);
3634 Literal<double> before_d(1.234);
3635 Literal<float> before_s(2.5);
3636 Literal<uint64_t> after_x(0x1234567890abcdef);
3637 Literal<uint32_t> after_w(0xfedcba09);
3638 Literal<uint32_t> after_sx(0x80000000);
3639 Literal<double> after_d(1.234);
3640 Literal<float> after_s(2.5);
3641
3642 START();
3643
3644 // Manually generate a pool.
3645 __ B(&end_of_pool_before);
3646 __ place(&before_x);
3647 __ place(&before_w);
3648 __ place(&before_sx);
3649 __ place(&before_d);
3650 __ place(&before_s);
3651 __ Bind(&end_of_pool_before);
3652
3653 for (int i = 0; i < (1 << ImmPrefetchOperation_width); i++) {
3654 // Unallocated prefetch operations are ignored, so test all of them.
3655 PrefetchOperation op = static_cast<PrefetchOperation>(i);
3656
3657 __ prfm(op, &before_x);
3658 __ prfm(op, &before_w);
3659 __ prfm(op, &before_sx);
3660 __ prfm(op, &before_d);
3661 __ prfm(op, &before_s);
3662
3663 __ prfm(op, &after_x);
3664 __ prfm(op, &after_w);
3665 __ prfm(op, &after_sx);
3666 __ prfm(op, &after_d);
3667 __ prfm(op, &after_s);
3668 }
3669
3670 __ ldr(x2, &before_x);
3671 __ ldr(w3, &before_w);
3672 __ ldrsw(x5, &before_sx);
3673 __ ldr(d13, &before_d);
3674 __ ldr(s25, &before_s);
3675
3676 __ ldr(x6, &after_x);
3677 __ ldr(w7, &after_w);
3678 __ ldrsw(x8, &after_sx);
3679 __ ldr(d14, &after_d);
3680 __ ldr(s26, &after_s);
3681
3682 // Manually generate a pool.
3683 __ B(&end_of_pool_after);
3684 __ place(&after_x);
3685 __ place(&after_w);
3686 __ place(&after_sx);
3687 __ place(&after_d);
3688 __ place(&after_s);
3689 __ Bind(&end_of_pool_after);
3690
3691 END();
3692
3693 RUN();
3694
3695 ASSERT_EQUAL_64(0x1234567890abcdef, x2);
3696 ASSERT_EQUAL_64(0xfedcba09, x3);
3697 ASSERT_EQUAL_64(0xffffffff80000000, x5);
3698 ASSERT_EQUAL_FP64(1.234, d13);
3699 ASSERT_EQUAL_FP32(2.5, s25);
3700
3701 ASSERT_EQUAL_64(0x1234567890abcdef, x6);
3702 ASSERT_EQUAL_64(0xfedcba09, x7);
3703 ASSERT_EQUAL_64(0xffffffff80000000, x8);
3704 ASSERT_EQUAL_FP64(1.234, d14);
3705 ASSERT_EQUAL_FP32(2.5, s26);
3706
armvixlc68cb642014-09-25 18:49:30 +01003707 TEARDOWN();
armvixlad96eda2013-06-14 11:42:37 +01003708}
3709
3710
3711TEST(add_sub_imm) {
3712 SETUP();
3713
3714 START();
3715 __ Mov(x0, 0x0);
3716 __ Mov(x1, 0x1111);
armvixlb0c8ae22014-03-21 14:03:59 +00003717 __ Mov(x2, 0xffffffffffffffff);
3718 __ Mov(x3, 0x8000000000000000);
armvixlad96eda2013-06-14 11:42:37 +01003719
3720 __ Add(x10, x0, Operand(0x123));
3721 __ Add(x11, x1, Operand(0x122000));
3722 __ Add(x12, x0, Operand(0xabc << 12));
3723 __ Add(x13, x2, Operand(1));
3724
3725 __ Add(w14, w0, Operand(0x123));
3726 __ Add(w15, w1, Operand(0x122000));
3727 __ Add(w16, w0, Operand(0xabc << 12));
3728 __ Add(w17, w2, Operand(1));
3729
3730 __ Sub(x20, x0, Operand(0x1));
3731 __ Sub(x21, x1, Operand(0x111));
3732 __ Sub(x22, x1, Operand(0x1 << 12));
3733 __ Sub(x23, x3, Operand(1));
3734
3735 __ Sub(w24, w0, Operand(0x1));
3736 __ Sub(w25, w1, Operand(0x111));
3737 __ Sub(w26, w1, Operand(0x1 << 12));
3738 __ Sub(w27, w3, Operand(1));
3739 END();
3740
3741 RUN();
3742
3743 ASSERT_EQUAL_64(0x123, x10);
3744 ASSERT_EQUAL_64(0x123111, x11);
3745 ASSERT_EQUAL_64(0xabc000, x12);
3746 ASSERT_EQUAL_64(0x0, x13);
3747
3748 ASSERT_EQUAL_32(0x123, w14);
3749 ASSERT_EQUAL_32(0x123111, w15);
3750 ASSERT_EQUAL_32(0xabc000, w16);
3751 ASSERT_EQUAL_32(0x0, w17);
3752
armvixlb0c8ae22014-03-21 14:03:59 +00003753 ASSERT_EQUAL_64(0xffffffffffffffff, x20);
armvixlad96eda2013-06-14 11:42:37 +01003754 ASSERT_EQUAL_64(0x1000, x21);
3755 ASSERT_EQUAL_64(0x111, x22);
armvixlb0c8ae22014-03-21 14:03:59 +00003756 ASSERT_EQUAL_64(0x7fffffffffffffff, x23);
armvixlad96eda2013-06-14 11:42:37 +01003757
3758 ASSERT_EQUAL_32(0xffffffff, w24);
3759 ASSERT_EQUAL_32(0x1000, w25);
3760 ASSERT_EQUAL_32(0x111, w26);
3761 ASSERT_EQUAL_32(0xffffffff, w27);
3762
3763 TEARDOWN();
3764}
3765
3766
3767TEST(add_sub_wide_imm) {
3768 SETUP();
3769
3770 START();
3771 __ Mov(x0, 0x0);
3772 __ Mov(x1, 0x1);
3773
armvixlb0c8ae22014-03-21 14:03:59 +00003774 __ Add(x10, x0, Operand(0x1234567890abcdef));
armvixlad96eda2013-06-14 11:42:37 +01003775 __ Add(x11, x1, Operand(0xffffffff));
3776
3777 __ Add(w12, w0, Operand(0x12345678));
3778 __ Add(w13, w1, Operand(0xffffffff));
3779
armvixl4a102ba2014-07-14 09:02:40 +01003780 __ Add(w18, w0, Operand(kWMinInt));
3781 __ Sub(w19, w0, Operand(kWMinInt));
armvixlad96eda2013-06-14 11:42:37 +01003782
armvixl4a102ba2014-07-14 09:02:40 +01003783 __ Sub(x20, x0, Operand(0x1234567890abcdef));
armvixlad96eda2013-06-14 11:42:37 +01003784 __ Sub(w21, w0, Operand(0x12345678));
armvixl4a102ba2014-07-14 09:02:40 +01003785
armvixlad96eda2013-06-14 11:42:37 +01003786 END();
3787
3788 RUN();
3789
armvixlb0c8ae22014-03-21 14:03:59 +00003790 ASSERT_EQUAL_64(0x1234567890abcdef, x10);
3791 ASSERT_EQUAL_64(0x100000000, x11);
armvixlad96eda2013-06-14 11:42:37 +01003792
3793 ASSERT_EQUAL_32(0x12345678, w12);
3794 ASSERT_EQUAL_64(0x0, x13);
3795
armvixl4a102ba2014-07-14 09:02:40 +01003796 ASSERT_EQUAL_32(kWMinInt, w18);
3797 ASSERT_EQUAL_32(kWMinInt, w19);
armvixlad96eda2013-06-14 11:42:37 +01003798
armvixl4a102ba2014-07-14 09:02:40 +01003799 ASSERT_EQUAL_64(-0x1234567890abcdef, x20);
armvixlad96eda2013-06-14 11:42:37 +01003800 ASSERT_EQUAL_32(-0x12345678, w21);
3801
3802 TEARDOWN();
3803}
3804
3805
3806TEST(add_sub_shifted) {
3807 SETUP();
3808
3809 START();
3810 __ Mov(x0, 0);
armvixlb0c8ae22014-03-21 14:03:59 +00003811 __ Mov(x1, 0x0123456789abcdef);
3812 __ Mov(x2, 0xfedcba9876543210);
3813 __ Mov(x3, 0xffffffffffffffff);
armvixlad96eda2013-06-14 11:42:37 +01003814
3815 __ Add(x10, x1, Operand(x2));
3816 __ Add(x11, x0, Operand(x1, LSL, 8));
3817 __ Add(x12, x0, Operand(x1, LSR, 8));
3818 __ Add(x13, x0, Operand(x1, ASR, 8));
3819 __ Add(x14, x0, Operand(x2, ASR, 8));
3820 __ Add(w15, w0, Operand(w1, ASR, 8));
3821 __ Add(w18, w3, Operand(w1, ROR, 8));
3822 __ Add(x19, x3, Operand(x1, ROR, 8));
3823
3824 __ Sub(x20, x3, Operand(x2));
3825 __ Sub(x21, x3, Operand(x1, LSL, 8));
3826 __ Sub(x22, x3, Operand(x1, LSR, 8));
3827 __ Sub(x23, x3, Operand(x1, ASR, 8));
3828 __ Sub(x24, x3, Operand(x2, ASR, 8));
3829 __ Sub(w25, w3, Operand(w1, ASR, 8));
3830 __ Sub(w26, w3, Operand(w1, ROR, 8));
3831 __ Sub(x27, x3, Operand(x1, ROR, 8));
3832 END();
3833
3834 RUN();
3835
armvixlb0c8ae22014-03-21 14:03:59 +00003836 ASSERT_EQUAL_64(0xffffffffffffffff, x10);
3837 ASSERT_EQUAL_64(0x23456789abcdef00, x11);
3838 ASSERT_EQUAL_64(0x000123456789abcd, x12);
3839 ASSERT_EQUAL_64(0x000123456789abcd, x13);
3840 ASSERT_EQUAL_64(0xfffedcba98765432, x14);
armvixlad96eda2013-06-14 11:42:37 +01003841 ASSERT_EQUAL_64(0xff89abcd, x15);
3842 ASSERT_EQUAL_64(0xef89abcc, x18);
armvixlb0c8ae22014-03-21 14:03:59 +00003843 ASSERT_EQUAL_64(0xef0123456789abcc, x19);
armvixlad96eda2013-06-14 11:42:37 +01003844
armvixlb0c8ae22014-03-21 14:03:59 +00003845 ASSERT_EQUAL_64(0x0123456789abcdef, x20);
3846 ASSERT_EQUAL_64(0xdcba9876543210ff, x21);
3847 ASSERT_EQUAL_64(0xfffedcba98765432, x22);
3848 ASSERT_EQUAL_64(0xfffedcba98765432, x23);
3849 ASSERT_EQUAL_64(0x000123456789abcd, x24);
armvixlad96eda2013-06-14 11:42:37 +01003850 ASSERT_EQUAL_64(0x00765432, x25);
3851 ASSERT_EQUAL_64(0x10765432, x26);
armvixlb0c8ae22014-03-21 14:03:59 +00003852 ASSERT_EQUAL_64(0x10fedcba98765432, x27);
armvixlad96eda2013-06-14 11:42:37 +01003853
3854 TEARDOWN();
3855}
3856
3857
3858TEST(add_sub_extended) {
3859 SETUP();
3860
3861 START();
3862 __ Mov(x0, 0);
armvixlb0c8ae22014-03-21 14:03:59 +00003863 __ Mov(x1, 0x0123456789abcdef);
3864 __ Mov(x2, 0xfedcba9876543210);
armvixlad96eda2013-06-14 11:42:37 +01003865 __ Mov(w3, 0x80);
3866
3867 __ Add(x10, x0, Operand(x1, UXTB, 0));
3868 __ Add(x11, x0, Operand(x1, UXTB, 1));
3869 __ Add(x12, x0, Operand(x1, UXTH, 2));
3870 __ Add(x13, x0, Operand(x1, UXTW, 4));
3871
3872 __ Add(x14, x0, Operand(x1, SXTB, 0));
3873 __ Add(x15, x0, Operand(x1, SXTB, 1));
3874 __ Add(x16, x0, Operand(x1, SXTH, 2));
3875 __ Add(x17, x0, Operand(x1, SXTW, 3));
3876 __ Add(x18, x0, Operand(x2, SXTB, 0));
3877 __ Add(x19, x0, Operand(x2, SXTB, 1));
3878 __ Add(x20, x0, Operand(x2, SXTH, 2));
3879 __ Add(x21, x0, Operand(x2, SXTW, 3));
3880
3881 __ Add(x22, x1, Operand(x2, SXTB, 1));
3882 __ Sub(x23, x1, Operand(x2, SXTB, 1));
3883
3884 __ Add(w24, w1, Operand(w2, UXTB, 2));
3885 __ Add(w25, w0, Operand(w1, SXTB, 0));
3886 __ Add(w26, w0, Operand(w1, SXTB, 1));
3887 __ Add(w27, w2, Operand(w1, SXTW, 3));
3888
3889 __ Add(w28, w0, Operand(w1, SXTW, 3));
3890 __ Add(x29, x0, Operand(w1, SXTW, 3));
3891
3892 __ Sub(x30, x0, Operand(w3, SXTB, 1));
3893 END();
3894
3895 RUN();
3896
armvixlb0c8ae22014-03-21 14:03:59 +00003897 ASSERT_EQUAL_64(0xef, x10);
3898 ASSERT_EQUAL_64(0x1de, x11);
3899 ASSERT_EQUAL_64(0x337bc, x12);
3900 ASSERT_EQUAL_64(0x89abcdef0, x13);
armvixlad96eda2013-06-14 11:42:37 +01003901
armvixlb0c8ae22014-03-21 14:03:59 +00003902 ASSERT_EQUAL_64(0xffffffffffffffef, x14);
3903 ASSERT_EQUAL_64(0xffffffffffffffde, x15);
3904 ASSERT_EQUAL_64(0xffffffffffff37bc, x16);
3905 ASSERT_EQUAL_64(0xfffffffc4d5e6f78, x17);
3906 ASSERT_EQUAL_64(0x10, x18);
3907 ASSERT_EQUAL_64(0x20, x19);
3908 ASSERT_EQUAL_64(0xc840, x20);
3909 ASSERT_EQUAL_64(0x3b2a19080, x21);
armvixlad96eda2013-06-14 11:42:37 +01003910
armvixlb0c8ae22014-03-21 14:03:59 +00003911 ASSERT_EQUAL_64(0x0123456789abce0f, x22);
3912 ASSERT_EQUAL_64(0x0123456789abcdcf, x23);
armvixlad96eda2013-06-14 11:42:37 +01003913
3914 ASSERT_EQUAL_32(0x89abce2f, w24);
3915 ASSERT_EQUAL_32(0xffffffef, w25);
3916 ASSERT_EQUAL_32(0xffffffde, w26);
3917 ASSERT_EQUAL_32(0xc3b2a188, w27);
3918
3919 ASSERT_EQUAL_32(0x4d5e6f78, w28);
armvixlb0c8ae22014-03-21 14:03:59 +00003920 ASSERT_EQUAL_64(0xfffffffc4d5e6f78, x29);
armvixlad96eda2013-06-14 11:42:37 +01003921
3922 ASSERT_EQUAL_64(256, x30);
3923
3924 TEARDOWN();
3925}
3926
3927
3928TEST(add_sub_negative) {
3929 SETUP();
3930
3931 START();
3932 __ Mov(x0, 0);
3933 __ Mov(x1, 4687);
3934 __ Mov(x2, 0x1122334455667788);
3935 __ Mov(w3, 0x11223344);
3936 __ Mov(w4, 400000);
3937
3938 __ Add(x10, x0, -42);
3939 __ Add(x11, x1, -687);
3940 __ Add(x12, x2, -0x88);
3941
3942 __ Sub(x13, x0, -600);
3943 __ Sub(x14, x1, -313);
3944 __ Sub(x15, x2, -0x555);
3945
3946 __ Add(w19, w3, -0x344);
3947 __ Add(w20, w4, -2000);
3948
3949 __ Sub(w21, w3, -0xbc);
3950 __ Sub(w22, w4, -2000);
3951 END();
3952
3953 RUN();
3954
3955 ASSERT_EQUAL_64(-42, x10);
3956 ASSERT_EQUAL_64(4000, x11);
3957 ASSERT_EQUAL_64(0x1122334455667700, x12);
3958
3959 ASSERT_EQUAL_64(600, x13);
3960 ASSERT_EQUAL_64(5000, x14);
3961 ASSERT_EQUAL_64(0x1122334455667cdd, x15);
3962
3963 ASSERT_EQUAL_32(0x11223000, w19);
3964 ASSERT_EQUAL_32(398000, w20);
3965
3966 ASSERT_EQUAL_32(0x11223400, w21);
3967 ASSERT_EQUAL_32(402000, w22);
3968
3969 TEARDOWN();
3970}
3971
3972
armvixlf37fdc02014-02-05 13:22:16 +00003973TEST(add_sub_zero) {
3974 SETUP();
3975
3976 START();
3977 __ Mov(x0, 0);
3978 __ Mov(x1, 0);
3979 __ Mov(x2, 0);
3980
3981 Label blob1;
3982 __ Bind(&blob1);
3983 __ Add(x0, x0, 0);
3984 __ Sub(x1, x1, 0);
3985 __ Sub(x2, x2, xzr);
armvixlb0c8ae22014-03-21 14:03:59 +00003986 VIXL_CHECK(__ SizeOfCodeGeneratedSince(&blob1) == 0);
armvixlf37fdc02014-02-05 13:22:16 +00003987
3988 Label blob2;
3989 __ Bind(&blob2);
3990 __ Add(w3, w3, 0);
armvixlb0c8ae22014-03-21 14:03:59 +00003991 VIXL_CHECK(__ SizeOfCodeGeneratedSince(&blob2) != 0);
armvixlf37fdc02014-02-05 13:22:16 +00003992
3993 Label blob3;
3994 __ Bind(&blob3);
3995 __ Sub(w3, w3, wzr);
armvixlb0c8ae22014-03-21 14:03:59 +00003996 VIXL_CHECK(__ SizeOfCodeGeneratedSince(&blob3) != 0);
armvixlf37fdc02014-02-05 13:22:16 +00003997
3998 END();
3999
4000 RUN();
4001
4002 ASSERT_EQUAL_64(0, x0);
4003 ASSERT_EQUAL_64(0, x1);
4004 ASSERT_EQUAL_64(0, x2);
4005
4006 TEARDOWN();
4007}
4008
4009
4010TEST(claim_drop_zero) {
4011 SETUP();
4012
4013 START();
4014
4015 Label start;
4016 __ Bind(&start);
4017 __ Claim(Operand(0));
4018 __ Drop(Operand(0));
4019 __ Claim(Operand(xzr));
4020 __ Drop(Operand(xzr));
armvixlb0c8ae22014-03-21 14:03:59 +00004021 VIXL_CHECK(__ SizeOfCodeGeneratedSince(&start) == 0);
armvixlf37fdc02014-02-05 13:22:16 +00004022
4023 END();
4024
4025 RUN();
4026
4027 TEARDOWN();
4028}
4029
4030
armvixlad96eda2013-06-14 11:42:37 +01004031TEST(neg) {
4032 SETUP();
4033
4034 START();
armvixlb0c8ae22014-03-21 14:03:59 +00004035 __ Mov(x0, 0xf123456789abcdef);
armvixlad96eda2013-06-14 11:42:37 +01004036
4037 // Immediate.
4038 __ Neg(x1, 0x123);
4039 __ Neg(w2, 0x123);
4040
4041 // Shifted.
4042 __ Neg(x3, Operand(x0, LSL, 1));
4043 __ Neg(w4, Operand(w0, LSL, 2));
4044 __ Neg(x5, Operand(x0, LSR, 3));
4045 __ Neg(w6, Operand(w0, LSR, 4));
4046 __ Neg(x7, Operand(x0, ASR, 5));
4047 __ Neg(w8, Operand(w0, ASR, 6));
4048
4049 // Extended.
4050 __ Neg(w9, Operand(w0, UXTB));
4051 __ Neg(x10, Operand(x0, SXTB, 1));
4052 __ Neg(w11, Operand(w0, UXTH, 2));
4053 __ Neg(x12, Operand(x0, SXTH, 3));
4054 __ Neg(w13, Operand(w0, UXTW, 4));
4055 __ Neg(x14, Operand(x0, SXTW, 4));
4056 END();
4057
4058 RUN();
4059
armvixlb0c8ae22014-03-21 14:03:59 +00004060 ASSERT_EQUAL_64(0xfffffffffffffedd, x1);
armvixlad96eda2013-06-14 11:42:37 +01004061 ASSERT_EQUAL_64(0xfffffedd, x2);
armvixlb0c8ae22014-03-21 14:03:59 +00004062 ASSERT_EQUAL_64(0x1db97530eca86422, x3);
armvixlad96eda2013-06-14 11:42:37 +01004063 ASSERT_EQUAL_64(0xd950c844, x4);
armvixlb0c8ae22014-03-21 14:03:59 +00004064 ASSERT_EQUAL_64(0xe1db97530eca8643, x5);
armvixlad96eda2013-06-14 11:42:37 +01004065 ASSERT_EQUAL_64(0xf7654322, x6);
armvixlb0c8ae22014-03-21 14:03:59 +00004066 ASSERT_EQUAL_64(0x0076e5d4c3b2a191, x7);
armvixlad96eda2013-06-14 11:42:37 +01004067 ASSERT_EQUAL_64(0x01d950c9, x8);
4068 ASSERT_EQUAL_64(0xffffff11, x9);
armvixlb0c8ae22014-03-21 14:03:59 +00004069 ASSERT_EQUAL_64(0x0000000000000022, x10);
armvixlad96eda2013-06-14 11:42:37 +01004070 ASSERT_EQUAL_64(0xfffcc844, x11);
armvixlb0c8ae22014-03-21 14:03:59 +00004071 ASSERT_EQUAL_64(0x0000000000019088, x12);
armvixlad96eda2013-06-14 11:42:37 +01004072 ASSERT_EQUAL_64(0x65432110, x13);
armvixlb0c8ae22014-03-21 14:03:59 +00004073 ASSERT_EQUAL_64(0x0000000765432110, x14);
armvixlad96eda2013-06-14 11:42:37 +01004074
4075 TEARDOWN();
4076}
4077
4078
4079TEST(adc_sbc_shift) {
4080 SETUP();
4081
4082 START();
4083 __ Mov(x0, 0);
4084 __ Mov(x1, 1);
armvixlb0c8ae22014-03-21 14:03:59 +00004085 __ Mov(x2, 0x0123456789abcdef);
4086 __ Mov(x3, 0xfedcba9876543210);
4087 __ Mov(x4, 0xffffffffffffffff);
armvixlad96eda2013-06-14 11:42:37 +01004088
4089 // Clear the C flag.
armvixlf37fdc02014-02-05 13:22:16 +00004090 __ Adds(x0, x0, Operand(0));
armvixlad96eda2013-06-14 11:42:37 +01004091
4092 __ Adc(x5, x2, Operand(x3));
4093 __ Adc(x6, x0, Operand(x1, LSL, 60));
4094 __ Sbc(x7, x4, Operand(x3, LSR, 4));
4095 __ Adc(x8, x2, Operand(x3, ASR, 4));
4096 __ Adc(x9, x2, Operand(x3, ROR, 8));
4097
4098 __ Adc(w10, w2, Operand(w3));
4099 __ Adc(w11, w0, Operand(w1, LSL, 30));
4100 __ Sbc(w12, w4, Operand(w3, LSR, 4));
4101 __ Adc(w13, w2, Operand(w3, ASR, 4));
4102 __ Adc(w14, w2, Operand(w3, ROR, 8));
4103
4104 // Set the C flag.
4105 __ Cmp(w0, Operand(w0));
4106
4107 __ Adc(x18, x2, Operand(x3));
4108 __ Adc(x19, x0, Operand(x1, LSL, 60));
4109 __ Sbc(x20, x4, Operand(x3, LSR, 4));
4110 __ Adc(x21, x2, Operand(x3, ASR, 4));
4111 __ Adc(x22, x2, Operand(x3, ROR, 8));
4112
4113 __ Adc(w23, w2, Operand(w3));
4114 __ Adc(w24, w0, Operand(w1, LSL, 30));
4115 __ Sbc(w25, w4, Operand(w3, LSR, 4));
4116 __ Adc(w26, w2, Operand(w3, ASR, 4));
4117 __ Adc(w27, w2, Operand(w3, ROR, 8));
4118 END();
4119
4120 RUN();
4121
armvixlb0c8ae22014-03-21 14:03:59 +00004122 ASSERT_EQUAL_64(0xffffffffffffffff, x5);
4123 ASSERT_EQUAL_64(INT64_C(1) << 60, x6);
4124 ASSERT_EQUAL_64(0xf0123456789abcdd, x7);
4125 ASSERT_EQUAL_64(0x0111111111111110, x8);
4126 ASSERT_EQUAL_64(0x1222222222222221, x9);
armvixlad96eda2013-06-14 11:42:37 +01004127
4128 ASSERT_EQUAL_32(0xffffffff, w10);
armvixlb0c8ae22014-03-21 14:03:59 +00004129 ASSERT_EQUAL_32(INT32_C(1) << 30, w11);
armvixlad96eda2013-06-14 11:42:37 +01004130 ASSERT_EQUAL_32(0xf89abcdd, w12);
4131 ASSERT_EQUAL_32(0x91111110, w13);
4132 ASSERT_EQUAL_32(0x9a222221, w14);
4133
armvixlb0c8ae22014-03-21 14:03:59 +00004134 ASSERT_EQUAL_64(0xffffffffffffffff + 1, x18);
4135 ASSERT_EQUAL_64((INT64_C(1) << 60) + 1, x19);
4136 ASSERT_EQUAL_64(0xf0123456789abcdd + 1, x20);
4137 ASSERT_EQUAL_64(0x0111111111111110 + 1, x21);
4138 ASSERT_EQUAL_64(0x1222222222222221 + 1, x22);
armvixlad96eda2013-06-14 11:42:37 +01004139
4140 ASSERT_EQUAL_32(0xffffffff + 1, w23);
armvixlb0c8ae22014-03-21 14:03:59 +00004141 ASSERT_EQUAL_32((INT32_C(1) << 30) + 1, w24);
armvixlad96eda2013-06-14 11:42:37 +01004142 ASSERT_EQUAL_32(0xf89abcdd + 1, w25);
4143 ASSERT_EQUAL_32(0x91111110 + 1, w26);
4144 ASSERT_EQUAL_32(0x9a222221 + 1, w27);
4145
4146 // Check that adc correctly sets the condition flags.
4147 START();
4148 __ Mov(x0, 1);
armvixlb0c8ae22014-03-21 14:03:59 +00004149 __ Mov(x1, 0xffffffffffffffff);
armvixlad96eda2013-06-14 11:42:37 +01004150 // Clear the C flag.
armvixlf37fdc02014-02-05 13:22:16 +00004151 __ Adds(x0, x0, Operand(0));
4152 __ Adcs(x10, x0, Operand(x1));
armvixlad96eda2013-06-14 11:42:37 +01004153 END();
4154
4155 RUN();
4156
4157 ASSERT_EQUAL_NZCV(ZCFlag);
armvixlf37fdc02014-02-05 13:22:16 +00004158 ASSERT_EQUAL_64(0, x10);
armvixlad96eda2013-06-14 11:42:37 +01004159
4160 START();
4161 __ Mov(x0, 1);
armvixlb0c8ae22014-03-21 14:03:59 +00004162 __ Mov(x1, 0x8000000000000000);
armvixlad96eda2013-06-14 11:42:37 +01004163 // Clear the C flag.
armvixlf37fdc02014-02-05 13:22:16 +00004164 __ Adds(x0, x0, Operand(0));
4165 __ Adcs(x10, x0, Operand(x1, ASR, 63));
armvixlad96eda2013-06-14 11:42:37 +01004166 END();
4167
4168 RUN();
4169
4170 ASSERT_EQUAL_NZCV(ZCFlag);
armvixlf37fdc02014-02-05 13:22:16 +00004171 ASSERT_EQUAL_64(0, x10);
armvixlad96eda2013-06-14 11:42:37 +01004172
4173 START();
4174 __ Mov(x0, 0x10);
armvixlb0c8ae22014-03-21 14:03:59 +00004175 __ Mov(x1, 0x07ffffffffffffff);
armvixlad96eda2013-06-14 11:42:37 +01004176 // Clear the C flag.
armvixlf37fdc02014-02-05 13:22:16 +00004177 __ Adds(x0, x0, Operand(0));
4178 __ Adcs(x10, x0, Operand(x1, LSL, 4));
armvixlad96eda2013-06-14 11:42:37 +01004179 END();
4180
4181 RUN();
4182
4183 ASSERT_EQUAL_NZCV(NVFlag);
armvixlb0c8ae22014-03-21 14:03:59 +00004184 ASSERT_EQUAL_64(0x8000000000000000, x10);
armvixlf37fdc02014-02-05 13:22:16 +00004185
4186 // Check that sbc correctly sets the condition flags.
4187 START();
4188 __ Mov(x0, 0);
armvixlb0c8ae22014-03-21 14:03:59 +00004189 __ Mov(x1, 0xffffffffffffffff);
armvixlf37fdc02014-02-05 13:22:16 +00004190 // Clear the C flag.
4191 __ Adds(x0, x0, Operand(0));
4192 __ Sbcs(x10, x0, Operand(x1));
4193 END();
4194
4195 RUN();
4196
4197 ASSERT_EQUAL_NZCV(ZFlag);
4198 ASSERT_EQUAL_64(0, x10);
4199
4200 START();
4201 __ Mov(x0, 1);
armvixlb0c8ae22014-03-21 14:03:59 +00004202 __ Mov(x1, 0xffffffffffffffff);
armvixlf37fdc02014-02-05 13:22:16 +00004203 // Clear the C flag.
4204 __ Adds(x0, x0, Operand(0));
4205 __ Sbcs(x10, x0, Operand(x1, LSR, 1));
4206 END();
4207
4208 RUN();
4209
4210 ASSERT_EQUAL_NZCV(NFlag);
armvixlb0c8ae22014-03-21 14:03:59 +00004211 ASSERT_EQUAL_64(0x8000000000000001, x10);
armvixlf37fdc02014-02-05 13:22:16 +00004212
4213 START();
4214 __ Mov(x0, 0);
4215 // Clear the C flag.
4216 __ Adds(x0, x0, Operand(0));
armvixlb0c8ae22014-03-21 14:03:59 +00004217 __ Sbcs(x10, x0, Operand(0xffffffffffffffff));
armvixlf37fdc02014-02-05 13:22:16 +00004218 END();
4219
4220 RUN();
4221
4222 ASSERT_EQUAL_NZCV(ZFlag);
4223 ASSERT_EQUAL_64(0, x10);
4224
armvixlb0c8ae22014-03-21 14:03:59 +00004225 START();
armvixlf37fdc02014-02-05 13:22:16 +00004226 __ Mov(w0, 0x7fffffff);
4227 // Clear the C flag.
4228 __ Adds(x0, x0, Operand(0));
4229 __ Ngcs(w10, w0);
4230 END();
4231
4232 RUN();
4233
4234 ASSERT_EQUAL_NZCV(NFlag);
4235 ASSERT_EQUAL_64(0x80000000, x10);
4236
4237 START();
4238 // Clear the C flag.
4239 __ Adds(x0, x0, Operand(0));
armvixlb0c8ae22014-03-21 14:03:59 +00004240 __ Ngcs(x10, 0x7fffffffffffffff);
armvixlf37fdc02014-02-05 13:22:16 +00004241 END();
4242
4243 RUN();
4244
4245 ASSERT_EQUAL_NZCV(NFlag);
armvixlb0c8ae22014-03-21 14:03:59 +00004246 ASSERT_EQUAL_64(0x8000000000000000, x10);
armvixlf37fdc02014-02-05 13:22:16 +00004247
armvixlb0c8ae22014-03-21 14:03:59 +00004248 START();
armvixlf37fdc02014-02-05 13:22:16 +00004249 __ Mov(x0, 0);
4250 // Set the C flag.
4251 __ Cmp(x0, Operand(x0));
4252 __ Sbcs(x10, x0, Operand(1));
4253 END();
4254
4255 RUN();
4256
4257 ASSERT_EQUAL_NZCV(NFlag);
armvixlb0c8ae22014-03-21 14:03:59 +00004258 ASSERT_EQUAL_64(0xffffffffffffffff, x10);
armvixlf37fdc02014-02-05 13:22:16 +00004259
armvixlb0c8ae22014-03-21 14:03:59 +00004260 START();
armvixlf37fdc02014-02-05 13:22:16 +00004261 __ Mov(x0, 0);
4262 // Set the C flag.
4263 __ Cmp(x0, Operand(x0));
armvixlb0c8ae22014-03-21 14:03:59 +00004264 __ Ngcs(x10, 0x7fffffffffffffff);
armvixlf37fdc02014-02-05 13:22:16 +00004265 END();
4266
4267 RUN();
4268
4269 ASSERT_EQUAL_NZCV(NFlag);
armvixlb0c8ae22014-03-21 14:03:59 +00004270 ASSERT_EQUAL_64(0x8000000000000001, x10);
armvixlad96eda2013-06-14 11:42:37 +01004271
4272 TEARDOWN();
4273}
4274
4275
4276TEST(adc_sbc_extend) {
4277 SETUP();
4278
4279 START();
4280 // Clear the C flag.
armvixlf37fdc02014-02-05 13:22:16 +00004281 __ Adds(x0, x0, Operand(0));
armvixlad96eda2013-06-14 11:42:37 +01004282
4283 __ Mov(x0, 0);
4284 __ Mov(x1, 1);
armvixlb0c8ae22014-03-21 14:03:59 +00004285 __ Mov(x2, 0x0123456789abcdef);
armvixlad96eda2013-06-14 11:42:37 +01004286
4287 __ Adc(x10, x1, Operand(w2, UXTB, 1));
4288 __ Adc(x11, x1, Operand(x2, SXTH, 2));
4289 __ Sbc(x12, x1, Operand(w2, UXTW, 4));
4290 __ Adc(x13, x1, Operand(x2, UXTX, 4));
4291
4292 __ Adc(w14, w1, Operand(w2, UXTB, 1));
4293 __ Adc(w15, w1, Operand(w2, SXTH, 2));
4294 __ Adc(w9, w1, Operand(w2, UXTW, 4));
4295
4296 // Set the C flag.
4297 __ Cmp(w0, Operand(w0));
4298
4299 __ Adc(x20, x1, Operand(w2, UXTB, 1));
4300 __ Adc(x21, x1, Operand(x2, SXTH, 2));
4301 __ Sbc(x22, x1, Operand(w2, UXTW, 4));
4302 __ Adc(x23, x1, Operand(x2, UXTX, 4));
4303
4304 __ Adc(w24, w1, Operand(w2, UXTB, 1));
4305 __ Adc(w25, w1, Operand(w2, SXTH, 2));
4306 __ Adc(w26, w1, Operand(w2, UXTW, 4));
4307 END();
4308
4309 RUN();
4310
4311 ASSERT_EQUAL_64(0x1df, x10);
armvixlb0c8ae22014-03-21 14:03:59 +00004312 ASSERT_EQUAL_64(0xffffffffffff37bd, x11);
4313 ASSERT_EQUAL_64(0xfffffff765432110, x12);
4314 ASSERT_EQUAL_64(0x123456789abcdef1, x13);
armvixlad96eda2013-06-14 11:42:37 +01004315
4316 ASSERT_EQUAL_32(0x1df, w14);
4317 ASSERT_EQUAL_32(0xffff37bd, w15);
4318 ASSERT_EQUAL_32(0x9abcdef1, w9);
4319
4320 ASSERT_EQUAL_64(0x1df + 1, x20);
armvixlb0c8ae22014-03-21 14:03:59 +00004321 ASSERT_EQUAL_64(0xffffffffffff37bd + 1, x21);
4322 ASSERT_EQUAL_64(0xfffffff765432110 + 1, x22);
4323 ASSERT_EQUAL_64(0x123456789abcdef1 + 1, x23);
armvixlad96eda2013-06-14 11:42:37 +01004324
4325 ASSERT_EQUAL_32(0x1df + 1, w24);
4326 ASSERT_EQUAL_32(0xffff37bd + 1, w25);
4327 ASSERT_EQUAL_32(0x9abcdef1 + 1, w26);
4328
4329 // Check that adc correctly sets the condition flags.
4330 START();
4331 __ Mov(x0, 0xff);
armvixlb0c8ae22014-03-21 14:03:59 +00004332 __ Mov(x1, 0xffffffffffffffff);
armvixlad96eda2013-06-14 11:42:37 +01004333 // Clear the C flag.
armvixlf37fdc02014-02-05 13:22:16 +00004334 __ Adds(x0, x0, Operand(0));
4335 __ Adcs(x10, x0, Operand(x1, SXTX, 1));
armvixlad96eda2013-06-14 11:42:37 +01004336 END();
4337
4338 RUN();
4339
4340 ASSERT_EQUAL_NZCV(CFlag);
4341
4342 START();
armvixlb0c8ae22014-03-21 14:03:59 +00004343 __ Mov(x0, 0x7fffffffffffffff);
armvixlad96eda2013-06-14 11:42:37 +01004344 __ Mov(x1, 1);
4345 // Clear the C flag.
armvixlf37fdc02014-02-05 13:22:16 +00004346 __ Adds(x0, x0, Operand(0));
4347 __ Adcs(x10, x0, Operand(x1, UXTB, 2));
armvixlad96eda2013-06-14 11:42:37 +01004348 END();
4349
4350 RUN();
4351
4352 ASSERT_EQUAL_NZCV(NVFlag);
4353
4354 START();
armvixlb0c8ae22014-03-21 14:03:59 +00004355 __ Mov(x0, 0x7fffffffffffffff);
armvixlad96eda2013-06-14 11:42:37 +01004356 // Clear the C flag.
armvixlf37fdc02014-02-05 13:22:16 +00004357 __ Adds(x0, x0, Operand(0));
4358 __ Adcs(x10, x0, Operand(1));
armvixlad96eda2013-06-14 11:42:37 +01004359 END();
4360
4361 RUN();
4362
4363 ASSERT_EQUAL_NZCV(NVFlag);
4364
4365 TEARDOWN();
4366}
4367
4368
4369TEST(adc_sbc_wide_imm) {
4370 SETUP();
4371
4372 START();
4373 __ Mov(x0, 0);
4374
4375 // Clear the C flag.
armvixlf37fdc02014-02-05 13:22:16 +00004376 __ Adds(x0, x0, Operand(0));
armvixlad96eda2013-06-14 11:42:37 +01004377
armvixlb0c8ae22014-03-21 14:03:59 +00004378 __ Adc(x7, x0, Operand(0x1234567890abcdef));
armvixlad96eda2013-06-14 11:42:37 +01004379 __ Adc(w8, w0, Operand(0xffffffff));
armvixlb0c8ae22014-03-21 14:03:59 +00004380 __ Sbc(x9, x0, Operand(0x1234567890abcdef));
armvixlf37fdc02014-02-05 13:22:16 +00004381 __ Sbc(w10, w0, Operand(0xffffffff));
armvixlb0c8ae22014-03-21 14:03:59 +00004382 __ Ngc(x11, Operand(0xffffffff00000000));
armvixlf37fdc02014-02-05 13:22:16 +00004383 __ Ngc(w12, Operand(0xffff0000));
armvixlad96eda2013-06-14 11:42:37 +01004384
4385 // Set the C flag.
4386 __ Cmp(w0, Operand(w0));
4387
armvixlb0c8ae22014-03-21 14:03:59 +00004388 __ Adc(x18, x0, Operand(0x1234567890abcdef));
armvixlf37fdc02014-02-05 13:22:16 +00004389 __ Adc(w19, w0, Operand(0xffffffff));
armvixlb0c8ae22014-03-21 14:03:59 +00004390 __ Sbc(x20, x0, Operand(0x1234567890abcdef));
armvixlf37fdc02014-02-05 13:22:16 +00004391 __ Sbc(w21, w0, Operand(0xffffffff));
armvixlb0c8ae22014-03-21 14:03:59 +00004392 __ Ngc(x22, Operand(0xffffffff00000000));
armvixlf37fdc02014-02-05 13:22:16 +00004393 __ Ngc(w23, Operand(0xffff0000));
armvixlad96eda2013-06-14 11:42:37 +01004394 END();
4395
4396 RUN();
4397
armvixlb0c8ae22014-03-21 14:03:59 +00004398 ASSERT_EQUAL_64(0x1234567890abcdef, x7);
armvixlad96eda2013-06-14 11:42:37 +01004399 ASSERT_EQUAL_64(0xffffffff, x8);
armvixlb0c8ae22014-03-21 14:03:59 +00004400 ASSERT_EQUAL_64(0xedcba9876f543210, x9);
armvixlf37fdc02014-02-05 13:22:16 +00004401 ASSERT_EQUAL_64(0, x10);
4402 ASSERT_EQUAL_64(0xffffffff, x11);
4403 ASSERT_EQUAL_64(0xffff, x12);
4404
armvixlb0c8ae22014-03-21 14:03:59 +00004405 ASSERT_EQUAL_64(0x1234567890abcdef + 1, x18);
armvixlf37fdc02014-02-05 13:22:16 +00004406 ASSERT_EQUAL_64(0, x19);
armvixlb0c8ae22014-03-21 14:03:59 +00004407 ASSERT_EQUAL_64(0xedcba9876f543211, x20);
armvixlf37fdc02014-02-05 13:22:16 +00004408 ASSERT_EQUAL_64(1, x21);
armvixlb0c8ae22014-03-21 14:03:59 +00004409 ASSERT_EQUAL_64(0x0000000100000000, x22);
4410 ASSERT_EQUAL_64(0x0000000000010000, x23);
armvixlad96eda2013-06-14 11:42:37 +01004411
4412 TEARDOWN();
4413}
4414
4415TEST(flags) {
4416 SETUP();
4417
4418 START();
4419 __ Mov(x0, 0);
armvixlb0c8ae22014-03-21 14:03:59 +00004420 __ Mov(x1, 0x1111111111111111);
armvixlad96eda2013-06-14 11:42:37 +01004421 __ Neg(x10, Operand(x0));
4422 __ Neg(x11, Operand(x1));
4423 __ Neg(w12, Operand(w1));
4424 // Clear the C flag.
armvixlf37fdc02014-02-05 13:22:16 +00004425 __ Adds(x0, x0, Operand(0));
armvixlad96eda2013-06-14 11:42:37 +01004426 __ Ngc(x13, Operand(x0));
4427 // Set the C flag.
4428 __ Cmp(x0, Operand(x0));
4429 __ Ngc(w14, Operand(w0));
4430 END();
4431
4432 RUN();
4433
4434 ASSERT_EQUAL_64(0, x10);
armvixlb0c8ae22014-03-21 14:03:59 +00004435 ASSERT_EQUAL_64(-0x1111111111111111, x11);
armvixlad96eda2013-06-14 11:42:37 +01004436 ASSERT_EQUAL_32(-0x11111111, w12);
armvixlb0c8ae22014-03-21 14:03:59 +00004437 ASSERT_EQUAL_64(-1, x13);
armvixlad96eda2013-06-14 11:42:37 +01004438 ASSERT_EQUAL_32(0, w14);
4439
4440 START();
4441 __ Mov(x0, 0);
4442 __ Cmp(x0, Operand(x0));
4443 END();
4444
4445 RUN();
4446
4447 ASSERT_EQUAL_NZCV(ZCFlag);
4448
4449 START();
4450 __ Mov(w0, 0);
4451 __ Cmp(w0, Operand(w0));
4452 END();
4453
4454 RUN();
4455
4456 ASSERT_EQUAL_NZCV(ZCFlag);
4457
4458 START();
4459 __ Mov(x0, 0);
armvixlb0c8ae22014-03-21 14:03:59 +00004460 __ Mov(x1, 0x1111111111111111);
armvixlad96eda2013-06-14 11:42:37 +01004461 __ Cmp(x0, Operand(x1));
4462 END();
4463
4464 RUN();
4465
4466 ASSERT_EQUAL_NZCV(NFlag);
4467
4468 START();
4469 __ Mov(w0, 0);
4470 __ Mov(w1, 0x11111111);
4471 __ Cmp(w0, Operand(w1));
4472 END();
4473
4474 RUN();
4475
4476 ASSERT_EQUAL_NZCV(NFlag);
4477
4478 START();
armvixlb0c8ae22014-03-21 14:03:59 +00004479 __ Mov(x1, 0x1111111111111111);
armvixlad96eda2013-06-14 11:42:37 +01004480 __ Cmp(x1, Operand(0));
4481 END();
4482
4483 RUN();
4484
4485 ASSERT_EQUAL_NZCV(CFlag);
4486
4487 START();
4488 __ Mov(w1, 0x11111111);
4489 __ Cmp(w1, Operand(0));
4490 END();
4491
4492 RUN();
4493
4494 ASSERT_EQUAL_NZCV(CFlag);
4495
4496 START();
4497 __ Mov(x0, 1);
armvixlb0c8ae22014-03-21 14:03:59 +00004498 __ Mov(x1, 0x7fffffffffffffff);
armvixlad96eda2013-06-14 11:42:37 +01004499 __ Cmn(x1, Operand(x0));
4500 END();
4501
4502 RUN();
4503
4504 ASSERT_EQUAL_NZCV(NVFlag);
4505
4506 START();
4507 __ Mov(w0, 1);
4508 __ Mov(w1, 0x7fffffff);
4509 __ Cmn(w1, Operand(w0));
4510 END();
4511
4512 RUN();
4513
4514 ASSERT_EQUAL_NZCV(NVFlag);
4515
4516 START();
4517 __ Mov(x0, 1);
armvixlb0c8ae22014-03-21 14:03:59 +00004518 __ Mov(x1, 0xffffffffffffffff);
armvixlad96eda2013-06-14 11:42:37 +01004519 __ Cmn(x1, Operand(x0));
4520 END();
4521
4522 RUN();
4523
4524 ASSERT_EQUAL_NZCV(ZCFlag);
4525
4526 START();
4527 __ Mov(w0, 1);
4528 __ Mov(w1, 0xffffffff);
4529 __ Cmn(w1, Operand(w0));
4530 END();
4531
4532 RUN();
4533
4534 ASSERT_EQUAL_NZCV(ZCFlag);
4535
4536 START();
4537 __ Mov(w0, 0);
4538 __ Mov(w1, 1);
4539 // Clear the C flag.
armvixlf37fdc02014-02-05 13:22:16 +00004540 __ Adds(w0, w0, Operand(0));
4541 __ Ngcs(w0, Operand(w1));
armvixlad96eda2013-06-14 11:42:37 +01004542 END();
4543
4544 RUN();
4545
4546 ASSERT_EQUAL_NZCV(NFlag);
4547
4548 START();
4549 __ Mov(w0, 0);
4550 __ Mov(w1, 0);
4551 // Set the C flag.
4552 __ Cmp(w0, Operand(w0));
armvixlf37fdc02014-02-05 13:22:16 +00004553 __ Ngcs(w0, Operand(w1));
armvixlad96eda2013-06-14 11:42:37 +01004554 END();
4555
4556 RUN();
4557
4558 ASSERT_EQUAL_NZCV(ZCFlag);
4559
4560 TEARDOWN();
4561}
4562
4563
4564TEST(cmp_shift) {
4565 SETUP();
4566
4567 START();
4568 __ Mov(x18, 0xf0000000);
armvixlb0c8ae22014-03-21 14:03:59 +00004569 __ Mov(x19, 0xf000000010000000);
4570 __ Mov(x20, 0xf0000000f0000000);
4571 __ Mov(x21, 0x7800000078000000);
4572 __ Mov(x22, 0x3c0000003c000000);
4573 __ Mov(x23, 0x8000000780000000);
4574 __ Mov(x24, 0x0000000f00000000);
4575 __ Mov(x25, 0x00000003c0000000);
4576 __ Mov(x26, 0x8000000780000000);
armvixlad96eda2013-06-14 11:42:37 +01004577 __ Mov(x27, 0xc0000003);
4578
4579 __ Cmp(w20, Operand(w21, LSL, 1));
4580 __ Mrs(x0, NZCV);
4581
4582 __ Cmp(x20, Operand(x22, LSL, 2));
4583 __ Mrs(x1, NZCV);
4584
4585 __ Cmp(w19, Operand(w23, LSR, 3));
4586 __ Mrs(x2, NZCV);
4587
4588 __ Cmp(x18, Operand(x24, LSR, 4));
4589 __ Mrs(x3, NZCV);
4590
4591 __ Cmp(w20, Operand(w25, ASR, 2));
4592 __ Mrs(x4, NZCV);
4593
4594 __ Cmp(x20, Operand(x26, ASR, 3));
4595 __ Mrs(x5, NZCV);
4596
4597 __ Cmp(w27, Operand(w22, ROR, 28));
4598 __ Mrs(x6, NZCV);
4599
4600 __ Cmp(x20, Operand(x21, ROR, 31));
4601 __ Mrs(x7, NZCV);
4602 END();
4603
4604 RUN();
4605
4606 ASSERT_EQUAL_32(ZCFlag, w0);
4607 ASSERT_EQUAL_32(ZCFlag, w1);
4608 ASSERT_EQUAL_32(ZCFlag, w2);
4609 ASSERT_EQUAL_32(ZCFlag, w3);
4610 ASSERT_EQUAL_32(ZCFlag, w4);
4611 ASSERT_EQUAL_32(ZCFlag, w5);
4612 ASSERT_EQUAL_32(ZCFlag, w6);
4613 ASSERT_EQUAL_32(ZCFlag, w7);
4614
4615 TEARDOWN();
4616}
4617
4618
4619TEST(cmp_extend) {
4620 SETUP();
4621
4622 START();
4623 __ Mov(w20, 0x2);
4624 __ Mov(w21, 0x1);
armvixlb0c8ae22014-03-21 14:03:59 +00004625 __ Mov(x22, 0xffffffffffffffff);
armvixlad96eda2013-06-14 11:42:37 +01004626 __ Mov(x23, 0xff);
armvixlb0c8ae22014-03-21 14:03:59 +00004627 __ Mov(x24, 0xfffffffffffffffe);
armvixlad96eda2013-06-14 11:42:37 +01004628 __ Mov(x25, 0xffff);
4629 __ Mov(x26, 0xffffffff);
4630
4631 __ Cmp(w20, Operand(w21, LSL, 1));
4632 __ Mrs(x0, NZCV);
4633
4634 __ Cmp(x22, Operand(x23, SXTB, 0));
4635 __ Mrs(x1, NZCV);
4636
4637 __ Cmp(x24, Operand(x23, SXTB, 1));
4638 __ Mrs(x2, NZCV);
4639
4640 __ Cmp(x24, Operand(x23, UXTB, 1));
4641 __ Mrs(x3, NZCV);
4642
4643 __ Cmp(w22, Operand(w25, UXTH));
4644 __ Mrs(x4, NZCV);
4645
4646 __ Cmp(x22, Operand(x25, SXTH));
4647 __ Mrs(x5, NZCV);
4648
4649 __ Cmp(x22, Operand(x26, UXTW));
4650 __ Mrs(x6, NZCV);
4651
4652 __ Cmp(x24, Operand(x26, SXTW, 1));
4653 __ Mrs(x7, NZCV);
4654 END();
4655
4656 RUN();
4657
4658 ASSERT_EQUAL_32(ZCFlag, w0);
4659 ASSERT_EQUAL_32(ZCFlag, w1);
4660 ASSERT_EQUAL_32(ZCFlag, w2);
4661 ASSERT_EQUAL_32(NCFlag, w3);
4662 ASSERT_EQUAL_32(NCFlag, w4);
4663 ASSERT_EQUAL_32(ZCFlag, w5);
4664 ASSERT_EQUAL_32(NCFlag, w6);
4665 ASSERT_EQUAL_32(ZCFlag, w7);
4666
4667 TEARDOWN();
4668}
4669
4670
4671TEST(ccmp) {
4672 SETUP();
armvixlc68cb642014-09-25 18:49:30 +01004673 ALLOW_ASM();
armvixlad96eda2013-06-14 11:42:37 +01004674
4675 START();
4676 __ Mov(w16, 0);
4677 __ Mov(w17, 1);
armvixl578645f2013-08-15 17:21:42 +01004678 __ Cmp(w16, w16);
4679 __ Ccmp(w16, w17, NCFlag, eq);
armvixlad96eda2013-06-14 11:42:37 +01004680 __ Mrs(x0, NZCV);
4681
armvixl578645f2013-08-15 17:21:42 +01004682 __ Cmp(w16, w16);
4683 __ Ccmp(w16, w17, NCFlag, ne);
armvixlad96eda2013-06-14 11:42:37 +01004684 __ Mrs(x1, NZCV);
4685
armvixl578645f2013-08-15 17:21:42 +01004686 __ Cmp(x16, x16);
4687 __ Ccmn(x16, 2, NZCVFlag, eq);
armvixlad96eda2013-06-14 11:42:37 +01004688 __ Mrs(x2, NZCV);
4689
armvixl578645f2013-08-15 17:21:42 +01004690 __ Cmp(x16, x16);
4691 __ Ccmn(x16, 2, NZCVFlag, ne);
armvixlad96eda2013-06-14 11:42:37 +01004692 __ Mrs(x3, NZCV);
armvixl578645f2013-08-15 17:21:42 +01004693
armvixlc68cb642014-09-25 18:49:30 +01004694 // The MacroAssembler does not allow al as a condition.
armvixl578645f2013-08-15 17:21:42 +01004695 __ ccmp(x16, x16, NZCVFlag, al);
4696 __ Mrs(x4, NZCV);
4697
armvixlc68cb642014-09-25 18:49:30 +01004698 // The MacroAssembler does not allow nv as a condition.
armvixl578645f2013-08-15 17:21:42 +01004699 __ ccmp(x16, x16, NZCVFlag, nv);
4700 __ Mrs(x5, NZCV);
4701
armvixlad96eda2013-06-14 11:42:37 +01004702 END();
4703
4704 RUN();
4705
4706 ASSERT_EQUAL_32(NFlag, w0);
4707 ASSERT_EQUAL_32(NCFlag, w1);
4708 ASSERT_EQUAL_32(NoFlag, w2);
4709 ASSERT_EQUAL_32(NZCVFlag, w3);
armvixl578645f2013-08-15 17:21:42 +01004710 ASSERT_EQUAL_32(ZCFlag, w4);
4711 ASSERT_EQUAL_32(ZCFlag, w5);
armvixlad96eda2013-06-14 11:42:37 +01004712
4713 TEARDOWN();
4714}
4715
4716
4717TEST(ccmp_wide_imm) {
4718 SETUP();
4719
4720 START();
4721 __ Mov(w20, 0);
4722
4723 __ Cmp(w20, Operand(w20));
4724 __ Ccmp(w20, Operand(0x12345678), NZCVFlag, eq);
4725 __ Mrs(x0, NZCV);
4726
4727 __ Cmp(w20, Operand(w20));
armvixlb0c8ae22014-03-21 14:03:59 +00004728 __ Ccmp(x20, Operand(0xffffffffffffffff), NZCVFlag, eq);
armvixlad96eda2013-06-14 11:42:37 +01004729 __ Mrs(x1, NZCV);
4730 END();
4731
4732 RUN();
4733
4734 ASSERT_EQUAL_32(NFlag, w0);
4735 ASSERT_EQUAL_32(NoFlag, w1);
4736
4737 TEARDOWN();
4738}
4739
4740
4741TEST(ccmp_shift_extend) {
4742 SETUP();
4743
4744 START();
4745 __ Mov(w20, 0x2);
4746 __ Mov(w21, 0x1);
armvixlb0c8ae22014-03-21 14:03:59 +00004747 __ Mov(x22, 0xffffffffffffffff);
armvixlad96eda2013-06-14 11:42:37 +01004748 __ Mov(x23, 0xff);
armvixlb0c8ae22014-03-21 14:03:59 +00004749 __ Mov(x24, 0xfffffffffffffffe);
armvixlad96eda2013-06-14 11:42:37 +01004750
4751 __ Cmp(w20, Operand(w20));
4752 __ Ccmp(w20, Operand(w21, LSL, 1), NZCVFlag, eq);
4753 __ Mrs(x0, NZCV);
4754
4755 __ Cmp(w20, Operand(w20));
4756 __ Ccmp(x22, Operand(x23, SXTB, 0), NZCVFlag, eq);
4757 __ Mrs(x1, NZCV);
4758
4759 __ Cmp(w20, Operand(w20));
4760 __ Ccmp(x24, Operand(x23, SXTB, 1), NZCVFlag, eq);
4761 __ Mrs(x2, NZCV);
4762
4763 __ Cmp(w20, Operand(w20));
4764 __ Ccmp(x24, Operand(x23, UXTB, 1), NZCVFlag, eq);
4765 __ Mrs(x3, NZCV);
4766
4767 __ Cmp(w20, Operand(w20));
4768 __ Ccmp(x24, Operand(x23, UXTB, 1), NZCVFlag, ne);
4769 __ Mrs(x4, NZCV);
4770 END();
4771
4772 RUN();
4773
4774 ASSERT_EQUAL_32(ZCFlag, w0);
4775 ASSERT_EQUAL_32(ZCFlag, w1);
4776 ASSERT_EQUAL_32(ZCFlag, w2);
4777 ASSERT_EQUAL_32(NCFlag, w3);
4778 ASSERT_EQUAL_32(NZCVFlag, w4);
4779
4780 TEARDOWN();
4781}
4782
4783
4784TEST(csel) {
4785 SETUP();
armvixlc68cb642014-09-25 18:49:30 +01004786 ALLOW_ASM();
armvixlad96eda2013-06-14 11:42:37 +01004787
4788 START();
4789 __ Mov(x16, 0);
armvixlb0c8ae22014-03-21 14:03:59 +00004790 __ Mov(x24, 0x0000000f0000000f);
4791 __ Mov(x25, 0x0000001f0000001f);
armvixlad96eda2013-06-14 11:42:37 +01004792
4793 __ Cmp(w16, Operand(0));
4794 __ Csel(w0, w24, w25, eq);
4795 __ Csel(w1, w24, w25, ne);
4796 __ Csinc(w2, w24, w25, mi);
4797 __ Csinc(w3, w24, w25, pl);
4798
armvixlc68cb642014-09-25 18:49:30 +01004799 // The MacroAssembler does not allow al or nv as a condition.
armvixl578645f2013-08-15 17:21:42 +01004800 __ csel(w13, w24, w25, al);
4801 __ csel(x14, x24, x25, nv);
4802
armvixlad96eda2013-06-14 11:42:37 +01004803 __ Cmp(x16, Operand(1));
4804 __ Csinv(x4, x24, x25, gt);
4805 __ Csinv(x5, x24, x25, le);
4806 __ Csneg(x6, x24, x25, hs);
4807 __ Csneg(x7, x24, x25, lo);
4808
4809 __ Cset(w8, ne);
4810 __ Csetm(w9, ne);
4811 __ Cinc(x10, x25, ne);
4812 __ Cinv(x11, x24, ne);
4813 __ Cneg(x12, x24, ne);
armvixl578645f2013-08-15 17:21:42 +01004814
armvixlc68cb642014-09-25 18:49:30 +01004815 // The MacroAssembler does not allow al or nv as a condition.
armvixl578645f2013-08-15 17:21:42 +01004816 __ csel(w15, w24, w25, al);
4817 __ csel(x17, x24, x25, nv);
4818
armvixlad96eda2013-06-14 11:42:37 +01004819 END();
4820
4821 RUN();
4822
4823 ASSERT_EQUAL_64(0x0000000f, x0);
4824 ASSERT_EQUAL_64(0x0000001f, x1);
4825 ASSERT_EQUAL_64(0x00000020, x2);
4826 ASSERT_EQUAL_64(0x0000000f, x3);
armvixlb0c8ae22014-03-21 14:03:59 +00004827 ASSERT_EQUAL_64(0xffffffe0ffffffe0, x4);
4828 ASSERT_EQUAL_64(0x0000000f0000000f, x5);
4829 ASSERT_EQUAL_64(0xffffffe0ffffffe1, x6);
4830 ASSERT_EQUAL_64(0x0000000f0000000f, x7);
armvixlad96eda2013-06-14 11:42:37 +01004831 ASSERT_EQUAL_64(0x00000001, x8);
4832 ASSERT_EQUAL_64(0xffffffff, x9);
armvixlb0c8ae22014-03-21 14:03:59 +00004833 ASSERT_EQUAL_64(0x0000001f00000020, x10);
4834 ASSERT_EQUAL_64(0xfffffff0fffffff0, x11);
4835 ASSERT_EQUAL_64(0xfffffff0fffffff1, x12);
armvixl578645f2013-08-15 17:21:42 +01004836 ASSERT_EQUAL_64(0x0000000f, x13);
armvixlb0c8ae22014-03-21 14:03:59 +00004837 ASSERT_EQUAL_64(0x0000000f0000000f, x14);
armvixl578645f2013-08-15 17:21:42 +01004838 ASSERT_EQUAL_64(0x0000000f, x15);
armvixlb0c8ae22014-03-21 14:03:59 +00004839 ASSERT_EQUAL_64(0x0000000f0000000f, x17);
armvixlad96eda2013-06-14 11:42:37 +01004840
4841 TEARDOWN();
4842}
4843
4844
armvixlf37fdc02014-02-05 13:22:16 +00004845TEST(csel_imm) {
4846 SETUP();
4847
4848 START();
4849 __ Mov(x18, 0);
4850 __ Mov(x19, 0x80000000);
armvixlb0c8ae22014-03-21 14:03:59 +00004851 __ Mov(x20, 0x8000000000000000);
armvixlf37fdc02014-02-05 13:22:16 +00004852
4853 __ Cmp(x18, Operand(0));
4854 __ Csel(w0, w19, -2, ne);
4855 __ Csel(w1, w19, -1, ne);
4856 __ Csel(w2, w19, 0, ne);
4857 __ Csel(w3, w19, 1, ne);
4858 __ Csel(w4, w19, 2, ne);
4859 __ Csel(w5, w19, Operand(w19, ASR, 31), ne);
4860 __ Csel(w6, w19, Operand(w19, ROR, 1), ne);
4861 __ Csel(w7, w19, 3, eq);
4862
4863 __ Csel(x8, x20, -2, ne);
4864 __ Csel(x9, x20, -1, ne);
4865 __ Csel(x10, x20, 0, ne);
4866 __ Csel(x11, x20, 1, ne);
4867 __ Csel(x12, x20, 2, ne);
4868 __ Csel(x13, x20, Operand(x20, ASR, 63), ne);
4869 __ Csel(x14, x20, Operand(x20, ROR, 1), ne);
4870 __ Csel(x15, x20, 3, eq);
4871
4872 END();
4873
4874 RUN();
4875
4876 ASSERT_EQUAL_32(-2, w0);
4877 ASSERT_EQUAL_32(-1, w1);
4878 ASSERT_EQUAL_32(0, w2);
4879 ASSERT_EQUAL_32(1, w3);
4880 ASSERT_EQUAL_32(2, w4);
4881 ASSERT_EQUAL_32(-1, w5);
4882 ASSERT_EQUAL_32(0x40000000, w6);
4883 ASSERT_EQUAL_32(0x80000000, w7);
4884
4885 ASSERT_EQUAL_64(-2, x8);
4886 ASSERT_EQUAL_64(-1, x9);
4887 ASSERT_EQUAL_64(0, x10);
4888 ASSERT_EQUAL_64(1, x11);
4889 ASSERT_EQUAL_64(2, x12);
4890 ASSERT_EQUAL_64(-1, x13);
armvixlb0c8ae22014-03-21 14:03:59 +00004891 ASSERT_EQUAL_64(0x4000000000000000, x14);
4892 ASSERT_EQUAL_64(0x8000000000000000, x15);
armvixlf37fdc02014-02-05 13:22:16 +00004893
4894 TEARDOWN();
4895}
4896
4897
armvixlad96eda2013-06-14 11:42:37 +01004898TEST(lslv) {
4899 SETUP();
armvixlc68cb642014-09-25 18:49:30 +01004900 ALLOW_ASM();
armvixlad96eda2013-06-14 11:42:37 +01004901
armvixlb0c8ae22014-03-21 14:03:59 +00004902 uint64_t value = 0x0123456789abcdef;
armvixlad96eda2013-06-14 11:42:37 +01004903 int shift[] = {1, 3, 5, 9, 17, 33};
4904
4905 START();
4906 __ Mov(x0, value);
4907 __ Mov(w1, shift[0]);
4908 __ Mov(w2, shift[1]);
4909 __ Mov(w3, shift[2]);
4910 __ Mov(w4, shift[3]);
4911 __ Mov(w5, shift[4]);
4912 __ Mov(w6, shift[5]);
4913
armvixlc68cb642014-09-25 18:49:30 +01004914 // The MacroAssembler does not allow zr as an argument.
armvixlad96eda2013-06-14 11:42:37 +01004915 __ lslv(x0, x0, xzr);
4916
4917 __ Lsl(x16, x0, x1);
4918 __ Lsl(x17, x0, x2);
4919 __ Lsl(x18, x0, x3);
4920 __ Lsl(x19, x0, x4);
4921 __ Lsl(x20, x0, x5);
4922 __ Lsl(x21, x0, x6);
4923
4924 __ Lsl(w22, w0, w1);
4925 __ Lsl(w23, w0, w2);
4926 __ Lsl(w24, w0, w3);
4927 __ Lsl(w25, w0, w4);
4928 __ Lsl(w26, w0, w5);
4929 __ Lsl(w27, w0, w6);
4930 END();
4931
4932 RUN();
4933
4934 ASSERT_EQUAL_64(value, x0);
4935 ASSERT_EQUAL_64(value << (shift[0] & 63), x16);
4936 ASSERT_EQUAL_64(value << (shift[1] & 63), x17);
4937 ASSERT_EQUAL_64(value << (shift[2] & 63), x18);
4938 ASSERT_EQUAL_64(value << (shift[3] & 63), x19);
4939 ASSERT_EQUAL_64(value << (shift[4] & 63), x20);
4940 ASSERT_EQUAL_64(value << (shift[5] & 63), x21);
4941 ASSERT_EQUAL_32(value << (shift[0] & 31), w22);
4942 ASSERT_EQUAL_32(value << (shift[1] & 31), w23);
4943 ASSERT_EQUAL_32(value << (shift[2] & 31), w24);
4944 ASSERT_EQUAL_32(value << (shift[3] & 31), w25);
4945 ASSERT_EQUAL_32(value << (shift[4] & 31), w26);
4946 ASSERT_EQUAL_32(value << (shift[5] & 31), w27);
4947
4948 TEARDOWN();
4949}
4950
4951
4952TEST(lsrv) {
4953 SETUP();
armvixlc68cb642014-09-25 18:49:30 +01004954 ALLOW_ASM();
armvixlad96eda2013-06-14 11:42:37 +01004955
armvixlb0c8ae22014-03-21 14:03:59 +00004956 uint64_t value = 0x0123456789abcdef;
armvixlad96eda2013-06-14 11:42:37 +01004957 int shift[] = {1, 3, 5, 9, 17, 33};
4958
4959 START();
4960 __ Mov(x0, value);
4961 __ Mov(w1, shift[0]);
4962 __ Mov(w2, shift[1]);
4963 __ Mov(w3, shift[2]);
4964 __ Mov(w4, shift[3]);
4965 __ Mov(w5, shift[4]);
4966 __ Mov(w6, shift[5]);
4967
armvixlc68cb642014-09-25 18:49:30 +01004968 // The MacroAssembler does not allow zr as an argument.
armvixlad96eda2013-06-14 11:42:37 +01004969 __ lsrv(x0, x0, xzr);
4970
4971 __ Lsr(x16, x0, x1);
4972 __ Lsr(x17, x0, x2);
4973 __ Lsr(x18, x0, x3);
4974 __ Lsr(x19, x0, x4);
4975 __ Lsr(x20, x0, x5);
4976 __ Lsr(x21, x0, x6);
4977
4978 __ Lsr(w22, w0, w1);
4979 __ Lsr(w23, w0, w2);
4980 __ Lsr(w24, w0, w3);
4981 __ Lsr(w25, w0, w4);
4982 __ Lsr(w26, w0, w5);
4983 __ Lsr(w27, w0, w6);
4984 END();
4985
4986 RUN();
4987
4988 ASSERT_EQUAL_64(value, x0);
4989 ASSERT_EQUAL_64(value >> (shift[0] & 63), x16);
4990 ASSERT_EQUAL_64(value >> (shift[1] & 63), x17);
4991 ASSERT_EQUAL_64(value >> (shift[2] & 63), x18);
4992 ASSERT_EQUAL_64(value >> (shift[3] & 63), x19);
4993 ASSERT_EQUAL_64(value >> (shift[4] & 63), x20);
4994 ASSERT_EQUAL_64(value >> (shift[5] & 63), x21);
4995
armvixlb0c8ae22014-03-21 14:03:59 +00004996 value &= 0xffffffff;
armvixlad96eda2013-06-14 11:42:37 +01004997 ASSERT_EQUAL_32(value >> (shift[0] & 31), w22);
4998 ASSERT_EQUAL_32(value >> (shift[1] & 31), w23);
4999 ASSERT_EQUAL_32(value >> (shift[2] & 31), w24);
5000 ASSERT_EQUAL_32(value >> (shift[3] & 31), w25);
5001 ASSERT_EQUAL_32(value >> (shift[4] & 31), w26);
5002 ASSERT_EQUAL_32(value >> (shift[5] & 31), w27);
5003
5004 TEARDOWN();
5005}
5006
5007
5008TEST(asrv) {
5009 SETUP();
armvixlc68cb642014-09-25 18:49:30 +01005010 ALLOW_ASM();
armvixlad96eda2013-06-14 11:42:37 +01005011
armvixlb0c8ae22014-03-21 14:03:59 +00005012 int64_t value = 0xfedcba98fedcba98;
armvixlad96eda2013-06-14 11:42:37 +01005013 int shift[] = {1, 3, 5, 9, 17, 33};
5014
5015 START();
5016 __ Mov(x0, value);
5017 __ Mov(w1, shift[0]);
5018 __ Mov(w2, shift[1]);
5019 __ Mov(w3, shift[2]);
5020 __ Mov(w4, shift[3]);
5021 __ Mov(w5, shift[4]);
5022 __ Mov(w6, shift[5]);
5023
armvixlc68cb642014-09-25 18:49:30 +01005024 // The MacroAssembler does not allow zr as an argument.
armvixlad96eda2013-06-14 11:42:37 +01005025 __ asrv(x0, x0, xzr);
5026
5027 __ Asr(x16, x0, x1);
5028 __ Asr(x17, x0, x2);
5029 __ Asr(x18, x0, x3);
5030 __ Asr(x19, x0, x4);
5031 __ Asr(x20, x0, x5);
5032 __ Asr(x21, x0, x6);
5033
5034 __ Asr(w22, w0, w1);
5035 __ Asr(w23, w0, w2);
5036 __ Asr(w24, w0, w3);
5037 __ Asr(w25, w0, w4);
5038 __ Asr(w26, w0, w5);
5039 __ Asr(w27, w0, w6);
5040 END();
5041
5042 RUN();
5043
5044 ASSERT_EQUAL_64(value, x0);
5045 ASSERT_EQUAL_64(value >> (shift[0] & 63), x16);
5046 ASSERT_EQUAL_64(value >> (shift[1] & 63), x17);
5047 ASSERT_EQUAL_64(value >> (shift[2] & 63), x18);
5048 ASSERT_EQUAL_64(value >> (shift[3] & 63), x19);
5049 ASSERT_EQUAL_64(value >> (shift[4] & 63), x20);
5050 ASSERT_EQUAL_64(value >> (shift[5] & 63), x21);
5051
armvixlb0c8ae22014-03-21 14:03:59 +00005052 int32_t value32 = static_cast<int32_t>(value & 0xffffffff);
armvixlad96eda2013-06-14 11:42:37 +01005053 ASSERT_EQUAL_32(value32 >> (shift[0] & 31), w22);
5054 ASSERT_EQUAL_32(value32 >> (shift[1] & 31), w23);
5055 ASSERT_EQUAL_32(value32 >> (shift[2] & 31), w24);
5056 ASSERT_EQUAL_32(value32 >> (shift[3] & 31), w25);
5057 ASSERT_EQUAL_32(value32 >> (shift[4] & 31), w26);
5058 ASSERT_EQUAL_32(value32 >> (shift[5] & 31), w27);
5059
5060 TEARDOWN();
5061}
5062
5063
5064TEST(rorv) {
5065 SETUP();
armvixlc68cb642014-09-25 18:49:30 +01005066 ALLOW_ASM();
armvixlad96eda2013-06-14 11:42:37 +01005067
armvixlb0c8ae22014-03-21 14:03:59 +00005068 uint64_t value = 0x0123456789abcdef;
armvixlad96eda2013-06-14 11:42:37 +01005069 int shift[] = {4, 8, 12, 16, 24, 36};
5070
5071 START();
5072 __ Mov(x0, value);
5073 __ Mov(w1, shift[0]);
5074 __ Mov(w2, shift[1]);
5075 __ Mov(w3, shift[2]);
5076 __ Mov(w4, shift[3]);
5077 __ Mov(w5, shift[4]);
5078 __ Mov(w6, shift[5]);
5079
armvixlc68cb642014-09-25 18:49:30 +01005080 // The MacroAssembler does not allow zr as an argument.
armvixlad96eda2013-06-14 11:42:37 +01005081 __ rorv(x0, x0, xzr);
5082
5083 __ Ror(x16, x0, x1);
5084 __ Ror(x17, x0, x2);
5085 __ Ror(x18, x0, x3);
5086 __ Ror(x19, x0, x4);
5087 __ Ror(x20, x0, x5);
5088 __ Ror(x21, x0, x6);
5089
5090 __ Ror(w22, w0, w1);
5091 __ Ror(w23, w0, w2);
5092 __ Ror(w24, w0, w3);
5093 __ Ror(w25, w0, w4);
5094 __ Ror(w26, w0, w5);
5095 __ Ror(w27, w0, w6);
5096 END();
5097
5098 RUN();
5099
5100 ASSERT_EQUAL_64(value, x0);
armvixlb0c8ae22014-03-21 14:03:59 +00005101 ASSERT_EQUAL_64(0xf0123456789abcde, x16);
5102 ASSERT_EQUAL_64(0xef0123456789abcd, x17);
5103 ASSERT_EQUAL_64(0xdef0123456789abc, x18);
5104 ASSERT_EQUAL_64(0xcdef0123456789ab, x19);
5105 ASSERT_EQUAL_64(0xabcdef0123456789, x20);
5106 ASSERT_EQUAL_64(0x789abcdef0123456, x21);
armvixlad96eda2013-06-14 11:42:37 +01005107 ASSERT_EQUAL_32(0xf89abcde, w22);
5108 ASSERT_EQUAL_32(0xef89abcd, w23);
5109 ASSERT_EQUAL_32(0xdef89abc, w24);
5110 ASSERT_EQUAL_32(0xcdef89ab, w25);
5111 ASSERT_EQUAL_32(0xabcdef89, w26);
5112 ASSERT_EQUAL_32(0xf89abcde, w27);
5113
5114 TEARDOWN();
5115}
5116
5117
5118TEST(bfm) {
5119 SETUP();
armvixlc68cb642014-09-25 18:49:30 +01005120 ALLOW_ASM();
armvixlad96eda2013-06-14 11:42:37 +01005121
5122 START();
armvixlb0c8ae22014-03-21 14:03:59 +00005123 __ Mov(x1, 0x0123456789abcdef);
armvixlad96eda2013-06-14 11:42:37 +01005124
armvixlb0c8ae22014-03-21 14:03:59 +00005125 __ Mov(x10, 0x8888888888888888);
5126 __ Mov(x11, 0x8888888888888888);
5127 __ Mov(x12, 0x8888888888888888);
5128 __ Mov(x13, 0x8888888888888888);
armvixlad96eda2013-06-14 11:42:37 +01005129 __ Mov(w20, 0x88888888);
5130 __ Mov(w21, 0x88888888);
5131
armvixlc68cb642014-09-25 18:49:30 +01005132 // There are no macro instruction for bfm.
armvixlad96eda2013-06-14 11:42:37 +01005133 __ bfm(x10, x1, 16, 31);
5134 __ bfm(x11, x1, 32, 15);
5135
5136 __ bfm(w20, w1, 16, 23);
5137 __ bfm(w21, w1, 24, 15);
5138
5139 // Aliases.
5140 __ Bfi(x12, x1, 16, 8);
5141 __ Bfxil(x13, x1, 16, 8);
5142 END();
5143
5144 RUN();
5145
5146
armvixlb0c8ae22014-03-21 14:03:59 +00005147 ASSERT_EQUAL_64(0x88888888888889ab, x10);
5148 ASSERT_EQUAL_64(0x8888cdef88888888, x11);
armvixlad96eda2013-06-14 11:42:37 +01005149
5150 ASSERT_EQUAL_32(0x888888ab, w20);
5151 ASSERT_EQUAL_32(0x88cdef88, w21);
5152
armvixlb0c8ae22014-03-21 14:03:59 +00005153 ASSERT_EQUAL_64(0x8888888888ef8888, x12);
5154 ASSERT_EQUAL_64(0x88888888888888ab, x13);
armvixlad96eda2013-06-14 11:42:37 +01005155
5156 TEARDOWN();
5157}
5158
5159
5160TEST(sbfm) {
5161 SETUP();
armvixlc68cb642014-09-25 18:49:30 +01005162 ALLOW_ASM();
armvixlad96eda2013-06-14 11:42:37 +01005163
5164 START();
armvixlb0c8ae22014-03-21 14:03:59 +00005165 __ Mov(x1, 0x0123456789abcdef);
5166 __ Mov(x2, 0xfedcba9876543210);
armvixlad96eda2013-06-14 11:42:37 +01005167
armvixlc68cb642014-09-25 18:49:30 +01005168 // There are no macro instruction for sbfm.
armvixlad96eda2013-06-14 11:42:37 +01005169 __ sbfm(x10, x1, 16, 31);
5170 __ sbfm(x11, x1, 32, 15);
5171 __ sbfm(x12, x1, 32, 47);
5172 __ sbfm(x13, x1, 48, 35);
5173
5174 __ sbfm(w14, w1, 16, 23);
5175 __ sbfm(w15, w1, 24, 15);
5176 __ sbfm(w16, w2, 16, 23);
5177 __ sbfm(w17, w2, 24, 15);
5178
5179 // Aliases.
5180 __ Asr(x18, x1, 32);
5181 __ Asr(x19, x2, 32);
5182 __ Sbfiz(x20, x1, 8, 16);
5183 __ Sbfiz(x21, x2, 8, 16);
5184 __ Sbfx(x22, x1, 8, 16);
5185 __ Sbfx(x23, x2, 8, 16);
armvixlf37fdc02014-02-05 13:22:16 +00005186 __ Sxtb(x24, w1);
armvixlad96eda2013-06-14 11:42:37 +01005187 __ Sxtb(x25, x2);
armvixlf37fdc02014-02-05 13:22:16 +00005188 __ Sxth(x26, w1);
armvixlad96eda2013-06-14 11:42:37 +01005189 __ Sxth(x27, x2);
armvixlf37fdc02014-02-05 13:22:16 +00005190 __ Sxtw(x28, w1);
armvixlad96eda2013-06-14 11:42:37 +01005191 __ Sxtw(x29, x2);
5192 END();
5193
5194 RUN();
5195
5196
armvixlb0c8ae22014-03-21 14:03:59 +00005197 ASSERT_EQUAL_64(0xffffffffffff89ab, x10);
5198 ASSERT_EQUAL_64(0xffffcdef00000000, x11);
5199 ASSERT_EQUAL_64(0x0000000000004567, x12);
5200 ASSERT_EQUAL_64(0x000789abcdef0000, x13);
armvixlad96eda2013-06-14 11:42:37 +01005201
5202 ASSERT_EQUAL_32(0xffffffab, w14);
5203 ASSERT_EQUAL_32(0xffcdef00, w15);
armvixlb0c8ae22014-03-21 14:03:59 +00005204 ASSERT_EQUAL_32(0x00000054, w16);
armvixlad96eda2013-06-14 11:42:37 +01005205 ASSERT_EQUAL_32(0x00321000, w17);
5206
armvixlb0c8ae22014-03-21 14:03:59 +00005207 ASSERT_EQUAL_64(0x0000000001234567, x18);
5208 ASSERT_EQUAL_64(0xfffffffffedcba98, x19);
5209 ASSERT_EQUAL_64(0xffffffffffcdef00, x20);
5210 ASSERT_EQUAL_64(0x0000000000321000, x21);
5211 ASSERT_EQUAL_64(0xffffffffffffabcd, x22);
5212 ASSERT_EQUAL_64(0x0000000000005432, x23);
5213 ASSERT_EQUAL_64(0xffffffffffffffef, x24);
5214 ASSERT_EQUAL_64(0x0000000000000010, x25);
5215 ASSERT_EQUAL_64(0xffffffffffffcdef, x26);
5216 ASSERT_EQUAL_64(0x0000000000003210, x27);
5217 ASSERT_EQUAL_64(0xffffffff89abcdef, x28);
5218 ASSERT_EQUAL_64(0x0000000076543210, x29);
armvixlad96eda2013-06-14 11:42:37 +01005219
5220 TEARDOWN();
5221}
5222
5223
5224TEST(ubfm) {
5225 SETUP();
armvixlc68cb642014-09-25 18:49:30 +01005226 ALLOW_ASM();
armvixlad96eda2013-06-14 11:42:37 +01005227
5228 START();
armvixlb0c8ae22014-03-21 14:03:59 +00005229 __ Mov(x1, 0x0123456789abcdef);
5230 __ Mov(x2, 0xfedcba9876543210);
armvixlad96eda2013-06-14 11:42:37 +01005231
armvixlb0c8ae22014-03-21 14:03:59 +00005232 __ Mov(x10, 0x8888888888888888);
5233 __ Mov(x11, 0x8888888888888888);
armvixlad96eda2013-06-14 11:42:37 +01005234
armvixlc68cb642014-09-25 18:49:30 +01005235 // There are no macro instruction for ubfm.
armvixlad96eda2013-06-14 11:42:37 +01005236 __ ubfm(x10, x1, 16, 31);
5237 __ ubfm(x11, x1, 32, 15);
5238 __ ubfm(x12, x1, 32, 47);
5239 __ ubfm(x13, x1, 48, 35);
5240
5241 __ ubfm(w25, w1, 16, 23);
5242 __ ubfm(w26, w1, 24, 15);
5243 __ ubfm(w27, w2, 16, 23);
5244 __ ubfm(w28, w2, 24, 15);
5245
5246 // Aliases
5247 __ Lsl(x15, x1, 63);
5248 __ Lsl(x16, x1, 0);
5249 __ Lsr(x17, x1, 32);
5250 __ Ubfiz(x18, x1, 8, 16);
5251 __ Ubfx(x19, x1, 8, 16);
5252 __ Uxtb(x20, x1);
5253 __ Uxth(x21, x1);
5254 __ Uxtw(x22, x1);
5255 END();
5256
5257 RUN();
5258
armvixlb0c8ae22014-03-21 14:03:59 +00005259 ASSERT_EQUAL_64(0x00000000000089ab, x10);
5260 ASSERT_EQUAL_64(0x0000cdef00000000, x11);
5261 ASSERT_EQUAL_64(0x0000000000004567, x12);
5262 ASSERT_EQUAL_64(0x000789abcdef0000, x13);
armvixlad96eda2013-06-14 11:42:37 +01005263
5264 ASSERT_EQUAL_32(0x000000ab, w25);
5265 ASSERT_EQUAL_32(0x00cdef00, w26);
armvixlb0c8ae22014-03-21 14:03:59 +00005266 ASSERT_EQUAL_32(0x00000054, w27);
armvixlad96eda2013-06-14 11:42:37 +01005267 ASSERT_EQUAL_32(0x00321000, w28);
5268
armvixlb0c8ae22014-03-21 14:03:59 +00005269 ASSERT_EQUAL_64(0x8000000000000000, x15);
5270 ASSERT_EQUAL_64(0x0123456789abcdef, x16);
5271 ASSERT_EQUAL_64(0x0000000001234567, x17);
5272 ASSERT_EQUAL_64(0x0000000000cdef00, x18);
5273 ASSERT_EQUAL_64(0x000000000000abcd, x19);
5274 ASSERT_EQUAL_64(0x00000000000000ef, x20);
5275 ASSERT_EQUAL_64(0x000000000000cdef, x21);
5276 ASSERT_EQUAL_64(0x0000000089abcdef, x22);
armvixlad96eda2013-06-14 11:42:37 +01005277
5278 TEARDOWN();
5279}
5280
5281
5282TEST(extr) {
5283 SETUP();
5284
5285 START();
armvixlb0c8ae22014-03-21 14:03:59 +00005286 __ Mov(x1, 0x0123456789abcdef);
5287 __ Mov(x2, 0xfedcba9876543210);
armvixlad96eda2013-06-14 11:42:37 +01005288
5289 __ Extr(w10, w1, w2, 0);
5290 __ Extr(w11, w1, w2, 1);
5291 __ Extr(x12, x2, x1, 2);
5292
5293 __ Ror(w13, w1, 0);
5294 __ Ror(w14, w2, 17);
5295 __ Ror(w15, w1, 31);
armvixl4a102ba2014-07-14 09:02:40 +01005296 __ Ror(x18, x2, 0);
5297 __ Ror(x19, x2, 1);
5298 __ Ror(x20, x1, 63);
armvixlad96eda2013-06-14 11:42:37 +01005299 END();
5300
5301 RUN();
5302
5303 ASSERT_EQUAL_64(0x76543210, x10);
5304 ASSERT_EQUAL_64(0xbb2a1908, x11);
armvixlb0c8ae22014-03-21 14:03:59 +00005305 ASSERT_EQUAL_64(0x0048d159e26af37b, x12);
armvixlad96eda2013-06-14 11:42:37 +01005306 ASSERT_EQUAL_64(0x89abcdef, x13);
5307 ASSERT_EQUAL_64(0x19083b2a, x14);
5308 ASSERT_EQUAL_64(0x13579bdf, x15);
armvixl4a102ba2014-07-14 09:02:40 +01005309 ASSERT_EQUAL_64(0xfedcba9876543210, x18);
5310 ASSERT_EQUAL_64(0x7f6e5d4c3b2a1908, x19);
5311 ASSERT_EQUAL_64(0x02468acf13579bde, x20);
armvixlad96eda2013-06-14 11:42:37 +01005312
5313 TEARDOWN();
5314}
5315
5316
5317TEST(fmov_imm) {
5318 SETUP();
5319
5320 START();
5321 __ Fmov(s11, 1.0);
5322 __ Fmov(d22, -13.0);
5323 __ Fmov(s1, 255.0);
5324 __ Fmov(d2, 12.34567);
5325 __ Fmov(s3, 0.0);
5326 __ Fmov(d4, 0.0);
5327 __ Fmov(s5, kFP32PositiveInfinity);
5328 __ Fmov(d6, kFP64NegativeInfinity);
5329 END();
5330
5331 RUN();
5332
5333 ASSERT_EQUAL_FP32(1.0, s11);
5334 ASSERT_EQUAL_FP64(-13.0, d22);
5335 ASSERT_EQUAL_FP32(255.0, s1);
5336 ASSERT_EQUAL_FP64(12.34567, d2);
5337 ASSERT_EQUAL_FP32(0.0, s3);
5338 ASSERT_EQUAL_FP64(0.0, d4);
5339 ASSERT_EQUAL_FP32(kFP32PositiveInfinity, s5);
5340 ASSERT_EQUAL_FP64(kFP64NegativeInfinity, d6);
5341
5342 TEARDOWN();
5343}
5344
5345
5346TEST(fmov_reg) {
5347 SETUP();
5348
5349 START();
5350 __ Fmov(s20, 1.0);
5351 __ Fmov(w10, s20);
5352 __ Fmov(s30, w10);
5353 __ Fmov(s5, s20);
5354 __ Fmov(d1, -13.0);
5355 __ Fmov(x1, d1);
5356 __ Fmov(d2, x1);
5357 __ Fmov(d4, d1);
armvixlb0c8ae22014-03-21 14:03:59 +00005358 __ Fmov(d6, rawbits_to_double(0x0123456789abcdef));
armvixlad96eda2013-06-14 11:42:37 +01005359 __ Fmov(s6, s6);
5360 END();
5361
5362 RUN();
5363
5364 ASSERT_EQUAL_32(float_to_rawbits(1.0), w10);
5365 ASSERT_EQUAL_FP32(1.0, s30);
5366 ASSERT_EQUAL_FP32(1.0, s5);
5367 ASSERT_EQUAL_64(double_to_rawbits(-13.0), x1);
5368 ASSERT_EQUAL_FP64(-13.0, d2);
5369 ASSERT_EQUAL_FP64(-13.0, d4);
5370 ASSERT_EQUAL_FP32(rawbits_to_float(0x89abcdef), s6);
5371
5372 TEARDOWN();
5373}
5374
5375
5376TEST(fadd) {
5377 SETUP();
5378
5379 START();
armvixlb0c8ae22014-03-21 14:03:59 +00005380 __ Fmov(s14, -0.0f);
5381 __ Fmov(s15, kFP32PositiveInfinity);
5382 __ Fmov(s16, kFP32NegativeInfinity);
5383 __ Fmov(s17, 3.25f);
5384 __ Fmov(s18, 1.0f);
5385 __ Fmov(s19, 0.0f);
armvixlad96eda2013-06-14 11:42:37 +01005386
5387 __ Fmov(d26, -0.0);
5388 __ Fmov(d27, kFP64PositiveInfinity);
5389 __ Fmov(d28, kFP64NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00005390 __ Fmov(d29, 0.0);
armvixlad96eda2013-06-14 11:42:37 +01005391 __ Fmov(d30, -2.0);
5392 __ Fmov(d31, 2.25);
5393
armvixlb0c8ae22014-03-21 14:03:59 +00005394 __ Fadd(s0, s17, s18);
5395 __ Fadd(s1, s18, s19);
5396 __ Fadd(s2, s14, s18);
5397 __ Fadd(s3, s15, s18);
5398 __ Fadd(s4, s16, s18);
5399 __ Fadd(s5, s15, s16);
5400 __ Fadd(s6, s16, s15);
armvixlad96eda2013-06-14 11:42:37 +01005401
armvixlb0c8ae22014-03-21 14:03:59 +00005402 __ Fadd(d7, d30, d31);
5403 __ Fadd(d8, d29, d31);
5404 __ Fadd(d9, d26, d31);
5405 __ Fadd(d10, d27, d31);
5406 __ Fadd(d11, d28, d31);
5407 __ Fadd(d12, d27, d28);
5408 __ Fadd(d13, d28, d27);
armvixlad96eda2013-06-14 11:42:37 +01005409 END();
5410
5411 RUN();
5412
5413 ASSERT_EQUAL_FP32(4.25, s0);
5414 ASSERT_EQUAL_FP32(1.0, s1);
5415 ASSERT_EQUAL_FP32(1.0, s2);
5416 ASSERT_EQUAL_FP32(kFP32PositiveInfinity, s3);
5417 ASSERT_EQUAL_FP32(kFP32NegativeInfinity, s4);
armvixlb0c8ae22014-03-21 14:03:59 +00005418 ASSERT_EQUAL_FP32(kFP32DefaultNaN, s5);
5419 ASSERT_EQUAL_FP32(kFP32DefaultNaN, s6);
5420 ASSERT_EQUAL_FP64(0.25, d7);
5421 ASSERT_EQUAL_FP64(2.25, d8);
5422 ASSERT_EQUAL_FP64(2.25, d9);
5423 ASSERT_EQUAL_FP64(kFP64PositiveInfinity, d10);
5424 ASSERT_EQUAL_FP64(kFP64NegativeInfinity, d11);
5425 ASSERT_EQUAL_FP64(kFP64DefaultNaN, d12);
5426 ASSERT_EQUAL_FP64(kFP64DefaultNaN, d13);
armvixlad96eda2013-06-14 11:42:37 +01005427
5428 TEARDOWN();
5429}
5430
5431
5432TEST(fsub) {
5433 SETUP();
5434
5435 START();
armvixlb0c8ae22014-03-21 14:03:59 +00005436 __ Fmov(s14, -0.0f);
5437 __ Fmov(s15, kFP32PositiveInfinity);
5438 __ Fmov(s16, kFP32NegativeInfinity);
5439 __ Fmov(s17, 3.25f);
5440 __ Fmov(s18, 1.0f);
5441 __ Fmov(s19, 0.0f);
armvixlad96eda2013-06-14 11:42:37 +01005442
5443 __ Fmov(d26, -0.0);
5444 __ Fmov(d27, kFP64PositiveInfinity);
5445 __ Fmov(d28, kFP64NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00005446 __ Fmov(d29, 0.0);
armvixlad96eda2013-06-14 11:42:37 +01005447 __ Fmov(d30, -2.0);
5448 __ Fmov(d31, 2.25);
5449
armvixlb0c8ae22014-03-21 14:03:59 +00005450 __ Fsub(s0, s17, s18);
5451 __ Fsub(s1, s18, s19);
5452 __ Fsub(s2, s14, s18);
5453 __ Fsub(s3, s18, s15);
5454 __ Fsub(s4, s18, s16);
5455 __ Fsub(s5, s15, s15);
5456 __ Fsub(s6, s16, s16);
armvixlad96eda2013-06-14 11:42:37 +01005457
armvixlb0c8ae22014-03-21 14:03:59 +00005458 __ Fsub(d7, d30, d31);
5459 __ Fsub(d8, d29, d31);
5460 __ Fsub(d9, d26, d31);
5461 __ Fsub(d10, d31, d27);
5462 __ Fsub(d11, d31, d28);
5463 __ Fsub(d12, d27, d27);
5464 __ Fsub(d13, d28, d28);
armvixlad96eda2013-06-14 11:42:37 +01005465 END();
5466
5467 RUN();
5468
5469 ASSERT_EQUAL_FP32(2.25, s0);
5470 ASSERT_EQUAL_FP32(1.0, s1);
5471 ASSERT_EQUAL_FP32(-1.0, s2);
5472 ASSERT_EQUAL_FP32(kFP32NegativeInfinity, s3);
5473 ASSERT_EQUAL_FP32(kFP32PositiveInfinity, s4);
armvixlb0c8ae22014-03-21 14:03:59 +00005474 ASSERT_EQUAL_FP32(kFP32DefaultNaN, s5);
5475 ASSERT_EQUAL_FP32(kFP32DefaultNaN, s6);
5476 ASSERT_EQUAL_FP64(-4.25, d7);
5477 ASSERT_EQUAL_FP64(-2.25, d8);
5478 ASSERT_EQUAL_FP64(-2.25, d9);
5479 ASSERT_EQUAL_FP64(kFP64NegativeInfinity, d10);
5480 ASSERT_EQUAL_FP64(kFP64PositiveInfinity, d11);
5481 ASSERT_EQUAL_FP64(kFP64DefaultNaN, d12);
5482 ASSERT_EQUAL_FP64(kFP64DefaultNaN, d13);
armvixlad96eda2013-06-14 11:42:37 +01005483
5484 TEARDOWN();
5485}
5486
5487
5488TEST(fmul) {
5489 SETUP();
5490
5491 START();
armvixlb0c8ae22014-03-21 14:03:59 +00005492 __ Fmov(s14, -0.0f);
5493 __ Fmov(s15, kFP32PositiveInfinity);
5494 __ Fmov(s16, kFP32NegativeInfinity);
5495 __ Fmov(s17, 3.25f);
5496 __ Fmov(s18, 2.0f);
5497 __ Fmov(s19, 0.0f);
5498 __ Fmov(s20, -2.0f);
armvixlad96eda2013-06-14 11:42:37 +01005499
5500 __ Fmov(d26, -0.0);
5501 __ Fmov(d27, kFP64PositiveInfinity);
5502 __ Fmov(d28, kFP64NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00005503 __ Fmov(d29, 0.0);
armvixlad96eda2013-06-14 11:42:37 +01005504 __ Fmov(d30, -2.0);
5505 __ Fmov(d31, 2.25);
5506
armvixlb0c8ae22014-03-21 14:03:59 +00005507 __ Fmul(s0, s17, s18);
5508 __ Fmul(s1, s18, s19);
5509 __ Fmul(s2, s14, s14);
5510 __ Fmul(s3, s15, s20);
5511 __ Fmul(s4, s16, s20);
5512 __ Fmul(s5, s15, s19);
5513 __ Fmul(s6, s19, s16);
armvixlad96eda2013-06-14 11:42:37 +01005514
armvixlb0c8ae22014-03-21 14:03:59 +00005515 __ Fmul(d7, d30, d31);
5516 __ Fmul(d8, d29, d31);
5517 __ Fmul(d9, d26, d26);
5518 __ Fmul(d10, d27, d30);
5519 __ Fmul(d11, d28, d30);
5520 __ Fmul(d12, d27, d29);
5521 __ Fmul(d13, d29, d28);
armvixlad96eda2013-06-14 11:42:37 +01005522 END();
5523
5524 RUN();
5525
5526 ASSERT_EQUAL_FP32(6.5, s0);
5527 ASSERT_EQUAL_FP32(0.0, s1);
5528 ASSERT_EQUAL_FP32(0.0, s2);
5529 ASSERT_EQUAL_FP32(kFP32NegativeInfinity, s3);
5530 ASSERT_EQUAL_FP32(kFP32PositiveInfinity, s4);
armvixlb0c8ae22014-03-21 14:03:59 +00005531 ASSERT_EQUAL_FP32(kFP32DefaultNaN, s5);
5532 ASSERT_EQUAL_FP32(kFP32DefaultNaN, s6);
5533 ASSERT_EQUAL_FP64(-4.5, d7);
5534 ASSERT_EQUAL_FP64(0.0, d8);
5535 ASSERT_EQUAL_FP64(0.0, d9);
5536 ASSERT_EQUAL_FP64(kFP64NegativeInfinity, d10);
5537 ASSERT_EQUAL_FP64(kFP64PositiveInfinity, d11);
5538 ASSERT_EQUAL_FP64(kFP64DefaultNaN, d12);
5539 ASSERT_EQUAL_FP64(kFP64DefaultNaN, d13);
armvixlad96eda2013-06-14 11:42:37 +01005540
5541 TEARDOWN();
5542}
5543
5544
armvixlb0c8ae22014-03-21 14:03:59 +00005545static void FmaddFmsubHelper(double n, double m, double a,
5546 double fmadd, double fmsub,
5547 double fnmadd, double fnmsub) {
armvixlad96eda2013-06-14 11:42:37 +01005548 SETUP();
armvixlad96eda2013-06-14 11:42:37 +01005549 START();
armvixlad96eda2013-06-14 11:42:37 +01005550
armvixlf37fdc02014-02-05 13:22:16 +00005551 __ Fmov(d0, n);
5552 __ Fmov(d1, m);
5553 __ Fmov(d2, a);
5554 __ Fmadd(d28, d0, d1, d2);
5555 __ Fmsub(d29, d0, d1, d2);
5556 __ Fnmadd(d30, d0, d1, d2);
5557 __ Fnmsub(d31, d0, d1, d2);
armvixlad96eda2013-06-14 11:42:37 +01005558
armvixlad96eda2013-06-14 11:42:37 +01005559 END();
armvixlad96eda2013-06-14 11:42:37 +01005560 RUN();
5561
armvixlf37fdc02014-02-05 13:22:16 +00005562 ASSERT_EQUAL_FP64(fmadd, d28);
5563 ASSERT_EQUAL_FP64(fmsub, d29);
armvixlb0c8ae22014-03-21 14:03:59 +00005564 ASSERT_EQUAL_FP64(fnmadd, d30);
5565 ASSERT_EQUAL_FP64(fnmsub, d31);
armvixlad96eda2013-06-14 11:42:37 +01005566
5567 TEARDOWN();
5568}
5569
5570
armvixlf37fdc02014-02-05 13:22:16 +00005571TEST(fmadd_fmsub_double) {
armvixlb0c8ae22014-03-21 14:03:59 +00005572 // It's hard to check the result of fused operations because the only way to
5573 // calculate the result is using fma, which is what the simulator uses anyway.
5574 // TODO(jbramley): Add tests to check behaviour against a hardware trace.
armvixlf37fdc02014-02-05 13:22:16 +00005575
armvixlb0c8ae22014-03-21 14:03:59 +00005576 // Basic operation.
5577 FmaddFmsubHelper(1.0, 2.0, 3.0, 5.0, 1.0, -5.0, -1.0);
5578 FmaddFmsubHelper(-1.0, 2.0, 3.0, 1.0, 5.0, -1.0, -5.0);
armvixlf37fdc02014-02-05 13:22:16 +00005579
armvixlb0c8ae22014-03-21 14:03:59 +00005580 // Check the sign of exact zeroes.
5581 // n m a fmadd fmsub fnmadd fnmsub
5582 FmaddFmsubHelper(-0.0, +0.0, -0.0, -0.0, +0.0, +0.0, +0.0);
5583 FmaddFmsubHelper(+0.0, +0.0, -0.0, +0.0, -0.0, +0.0, +0.0);
5584 FmaddFmsubHelper(+0.0, +0.0, +0.0, +0.0, +0.0, -0.0, +0.0);
5585 FmaddFmsubHelper(-0.0, +0.0, +0.0, +0.0, +0.0, +0.0, -0.0);
5586 FmaddFmsubHelper(+0.0, -0.0, -0.0, -0.0, +0.0, +0.0, +0.0);
5587 FmaddFmsubHelper(-0.0, -0.0, -0.0, +0.0, -0.0, +0.0, +0.0);
5588 FmaddFmsubHelper(-0.0, -0.0, +0.0, +0.0, +0.0, -0.0, +0.0);
5589 FmaddFmsubHelper(+0.0, -0.0, +0.0, +0.0, +0.0, +0.0, -0.0);
5590
5591 // Check NaN generation.
5592 FmaddFmsubHelper(kFP64PositiveInfinity, 0.0, 42.0,
5593 kFP64DefaultNaN, kFP64DefaultNaN,
5594 kFP64DefaultNaN, kFP64DefaultNaN);
5595 FmaddFmsubHelper(0.0, kFP64PositiveInfinity, 42.0,
5596 kFP64DefaultNaN, kFP64DefaultNaN,
5597 kFP64DefaultNaN, kFP64DefaultNaN);
5598 FmaddFmsubHelper(kFP64PositiveInfinity, 1.0, kFP64PositiveInfinity,
5599 kFP64PositiveInfinity, // inf + ( inf * 1) = inf
5600 kFP64DefaultNaN, // inf + (-inf * 1) = NaN
5601 kFP64NegativeInfinity, // -inf + (-inf * 1) = -inf
5602 kFP64DefaultNaN); // -inf + ( inf * 1) = NaN
5603 FmaddFmsubHelper(kFP64NegativeInfinity, 1.0, kFP64PositiveInfinity,
5604 kFP64DefaultNaN, // inf + (-inf * 1) = NaN
5605 kFP64PositiveInfinity, // inf + ( inf * 1) = inf
5606 kFP64DefaultNaN, // -inf + ( inf * 1) = NaN
5607 kFP64NegativeInfinity); // -inf + (-inf * 1) = -inf
armvixlf37fdc02014-02-05 13:22:16 +00005608}
5609
5610
armvixlb0c8ae22014-03-21 14:03:59 +00005611static void FmaddFmsubHelper(float n, float m, float a,
5612 float fmadd, float fmsub,
5613 float fnmadd, float fnmsub) {
armvixlf37fdc02014-02-05 13:22:16 +00005614 SETUP();
5615 START();
5616
5617 __ Fmov(s0, n);
5618 __ Fmov(s1, m);
5619 __ Fmov(s2, a);
armvixlb0c8ae22014-03-21 14:03:59 +00005620 __ Fmadd(s28, s0, s1, s2);
5621 __ Fmsub(s29, s0, s1, s2);
5622 __ Fnmadd(s30, s0, s1, s2);
5623 __ Fnmsub(s31, s0, s1, s2);
armvixlf37fdc02014-02-05 13:22:16 +00005624
5625 END();
5626 RUN();
5627
armvixlb0c8ae22014-03-21 14:03:59 +00005628 ASSERT_EQUAL_FP32(fmadd, s28);
5629 ASSERT_EQUAL_FP32(fmsub, s29);
5630 ASSERT_EQUAL_FP32(fnmadd, s30);
5631 ASSERT_EQUAL_FP32(fnmsub, s31);
armvixlf37fdc02014-02-05 13:22:16 +00005632
5633 TEARDOWN();
5634}
5635
5636
5637TEST(fmadd_fmsub_float) {
armvixlb0c8ae22014-03-21 14:03:59 +00005638 // It's hard to check the result of fused operations because the only way to
5639 // calculate the result is using fma, which is what the simulator uses anyway.
5640 // TODO(jbramley): Add tests to check behaviour against a hardware trace.
armvixlf37fdc02014-02-05 13:22:16 +00005641
armvixlb0c8ae22014-03-21 14:03:59 +00005642 // Basic operation.
5643 FmaddFmsubHelper(1.0f, 2.0f, 3.0f, 5.0f, 1.0f, -5.0f, -1.0f);
5644 FmaddFmsubHelper(-1.0f, 2.0f, 3.0f, 1.0f, 5.0f, -1.0f, -5.0f);
armvixlf37fdc02014-02-05 13:22:16 +00005645
armvixlb0c8ae22014-03-21 14:03:59 +00005646 // Check the sign of exact zeroes.
5647 // n m a fmadd fmsub fnmadd fnmsub
5648 FmaddFmsubHelper(-0.0f, +0.0f, -0.0f, -0.0f, +0.0f, +0.0f, +0.0f);
5649 FmaddFmsubHelper(+0.0f, +0.0f, -0.0f, +0.0f, -0.0f, +0.0f, +0.0f);
5650 FmaddFmsubHelper(+0.0f, +0.0f, +0.0f, +0.0f, +0.0f, -0.0f, +0.0f);
5651 FmaddFmsubHelper(-0.0f, +0.0f, +0.0f, +0.0f, +0.0f, +0.0f, -0.0f);
5652 FmaddFmsubHelper(+0.0f, -0.0f, -0.0f, -0.0f, +0.0f, +0.0f, +0.0f);
5653 FmaddFmsubHelper(-0.0f, -0.0f, -0.0f, +0.0f, -0.0f, +0.0f, +0.0f);
5654 FmaddFmsubHelper(-0.0f, -0.0f, +0.0f, +0.0f, +0.0f, -0.0f, +0.0f);
5655 FmaddFmsubHelper(+0.0f, -0.0f, +0.0f, +0.0f, +0.0f, +0.0f, -0.0f);
5656
5657 // Check NaN generation.
5658 FmaddFmsubHelper(kFP32PositiveInfinity, 0.0f, 42.0f,
5659 kFP32DefaultNaN, kFP32DefaultNaN,
5660 kFP32DefaultNaN, kFP32DefaultNaN);
5661 FmaddFmsubHelper(0.0f, kFP32PositiveInfinity, 42.0f,
5662 kFP32DefaultNaN, kFP32DefaultNaN,
5663 kFP32DefaultNaN, kFP32DefaultNaN);
5664 FmaddFmsubHelper(kFP32PositiveInfinity, 1.0f, kFP32PositiveInfinity,
5665 kFP32PositiveInfinity, // inf + ( inf * 1) = inf
5666 kFP32DefaultNaN, // inf + (-inf * 1) = NaN
5667 kFP32NegativeInfinity, // -inf + (-inf * 1) = -inf
5668 kFP32DefaultNaN); // -inf + ( inf * 1) = NaN
5669 FmaddFmsubHelper(kFP32NegativeInfinity, 1.0f, kFP32PositiveInfinity,
5670 kFP32DefaultNaN, // inf + (-inf * 1) = NaN
5671 kFP32PositiveInfinity, // inf + ( inf * 1) = inf
5672 kFP32DefaultNaN, // -inf + ( inf * 1) = NaN
5673 kFP32NegativeInfinity); // -inf + (-inf * 1) = -inf
armvixlf37fdc02014-02-05 13:22:16 +00005674}
5675
5676
armvixlb0c8ae22014-03-21 14:03:59 +00005677TEST(fmadd_fmsub_double_nans) {
5678 // Make sure that NaN propagation works correctly.
5679 double s1 = rawbits_to_double(0x7ff5555511111111);
5680 double s2 = rawbits_to_double(0x7ff5555522222222);
5681 double sa = rawbits_to_double(0x7ff55555aaaaaaaa);
5682 double q1 = rawbits_to_double(0x7ffaaaaa11111111);
5683 double q2 = rawbits_to_double(0x7ffaaaaa22222222);
5684 double qa = rawbits_to_double(0x7ffaaaaaaaaaaaaa);
5685 VIXL_ASSERT(IsSignallingNaN(s1));
5686 VIXL_ASSERT(IsSignallingNaN(s2));
5687 VIXL_ASSERT(IsSignallingNaN(sa));
5688 VIXL_ASSERT(IsQuietNaN(q1));
5689 VIXL_ASSERT(IsQuietNaN(q2));
5690 VIXL_ASSERT(IsQuietNaN(qa));
armvixlf37fdc02014-02-05 13:22:16 +00005691
armvixlb0c8ae22014-03-21 14:03:59 +00005692 // The input NaNs after passing through ProcessNaN.
5693 double s1_proc = rawbits_to_double(0x7ffd555511111111);
5694 double s2_proc = rawbits_to_double(0x7ffd555522222222);
5695 double sa_proc = rawbits_to_double(0x7ffd5555aaaaaaaa);
5696 double q1_proc = q1;
5697 double q2_proc = q2;
5698 double qa_proc = qa;
5699 VIXL_ASSERT(IsQuietNaN(s1_proc));
5700 VIXL_ASSERT(IsQuietNaN(s2_proc));
5701 VIXL_ASSERT(IsQuietNaN(sa_proc));
5702 VIXL_ASSERT(IsQuietNaN(q1_proc));
5703 VIXL_ASSERT(IsQuietNaN(q2_proc));
5704 VIXL_ASSERT(IsQuietNaN(qa_proc));
armvixlf37fdc02014-02-05 13:22:16 +00005705
armvixl5799d6c2014-05-01 11:05:00 +01005706 // Negated NaNs as it would be done on ARMv8 hardware.
5707 double s1_proc_neg = rawbits_to_double(0xfffd555511111111);
5708 double sa_proc_neg = rawbits_to_double(0xfffd5555aaaaaaaa);
5709 double q1_proc_neg = rawbits_to_double(0xfffaaaaa11111111);
5710 double qa_proc_neg = rawbits_to_double(0xfffaaaaaaaaaaaaa);
5711 VIXL_ASSERT(IsQuietNaN(s1_proc_neg));
5712 VIXL_ASSERT(IsQuietNaN(sa_proc_neg));
5713 VIXL_ASSERT(IsQuietNaN(q1_proc_neg));
5714 VIXL_ASSERT(IsQuietNaN(qa_proc_neg));
5715
armvixlb0c8ae22014-03-21 14:03:59 +00005716 // Quiet NaNs are propagated.
armvixl5799d6c2014-05-01 11:05:00 +01005717 FmaddFmsubHelper(q1, 0, 0, q1_proc, q1_proc_neg, q1_proc_neg, q1_proc);
armvixlb0c8ae22014-03-21 14:03:59 +00005718 FmaddFmsubHelper(0, q2, 0, q2_proc, q2_proc, q2_proc, q2_proc);
armvixl5799d6c2014-05-01 11:05:00 +01005719 FmaddFmsubHelper(0, 0, qa, qa_proc, qa_proc, qa_proc_neg, qa_proc_neg);
5720 FmaddFmsubHelper(q1, q2, 0, q1_proc, q1_proc_neg, q1_proc_neg, q1_proc);
5721 FmaddFmsubHelper(0, q2, qa, qa_proc, qa_proc, qa_proc_neg, qa_proc_neg);
5722 FmaddFmsubHelper(q1, 0, qa, qa_proc, qa_proc, qa_proc_neg, qa_proc_neg);
5723 FmaddFmsubHelper(q1, q2, qa, qa_proc, qa_proc, qa_proc_neg, qa_proc_neg);
armvixlf37fdc02014-02-05 13:22:16 +00005724
armvixlb0c8ae22014-03-21 14:03:59 +00005725 // Signalling NaNs are propagated, and made quiet.
armvixl5799d6c2014-05-01 11:05:00 +01005726 FmaddFmsubHelper(s1, 0, 0, s1_proc, s1_proc_neg, s1_proc_neg, s1_proc);
armvixlb0c8ae22014-03-21 14:03:59 +00005727 FmaddFmsubHelper(0, s2, 0, s2_proc, s2_proc, s2_proc, s2_proc);
armvixl5799d6c2014-05-01 11:05:00 +01005728 FmaddFmsubHelper(0, 0, sa, sa_proc, sa_proc, sa_proc_neg, sa_proc_neg);
5729 FmaddFmsubHelper(s1, s2, 0, s1_proc, s1_proc_neg, s1_proc_neg, s1_proc);
5730 FmaddFmsubHelper(0, s2, sa, sa_proc, sa_proc, sa_proc_neg, sa_proc_neg);
5731 FmaddFmsubHelper(s1, 0, sa, sa_proc, sa_proc, sa_proc_neg, sa_proc_neg);
5732 FmaddFmsubHelper(s1, s2, sa, sa_proc, sa_proc, sa_proc_neg, sa_proc_neg);
armvixlf37fdc02014-02-05 13:22:16 +00005733
armvixlb0c8ae22014-03-21 14:03:59 +00005734 // Signalling NaNs take precedence over quiet NaNs.
armvixl5799d6c2014-05-01 11:05:00 +01005735 FmaddFmsubHelper(s1, q2, qa, s1_proc, s1_proc_neg, s1_proc_neg, s1_proc);
armvixlb0c8ae22014-03-21 14:03:59 +00005736 FmaddFmsubHelper(q1, s2, qa, s2_proc, s2_proc, s2_proc, s2_proc);
armvixl5799d6c2014-05-01 11:05:00 +01005737 FmaddFmsubHelper(q1, q2, sa, sa_proc, sa_proc, sa_proc_neg, sa_proc_neg);
5738 FmaddFmsubHelper(s1, s2, qa, s1_proc, s1_proc_neg, s1_proc_neg, s1_proc);
5739 FmaddFmsubHelper(q1, s2, sa, sa_proc, sa_proc, sa_proc_neg, sa_proc_neg);
5740 FmaddFmsubHelper(s1, q2, sa, sa_proc, sa_proc, sa_proc_neg, sa_proc_neg);
5741 FmaddFmsubHelper(s1, s2, sa, sa_proc, sa_proc, sa_proc_neg, sa_proc_neg);
armvixlf37fdc02014-02-05 13:22:16 +00005742
armvixlb0c8ae22014-03-21 14:03:59 +00005743 // A NaN generated by the intermediate op1 * op2 overrides a quiet NaN in a.
5744 FmaddFmsubHelper(0, kFP64PositiveInfinity, qa,
5745 kFP64DefaultNaN, kFP64DefaultNaN,
5746 kFP64DefaultNaN, kFP64DefaultNaN);
5747 FmaddFmsubHelper(kFP64PositiveInfinity, 0, qa,
5748 kFP64DefaultNaN, kFP64DefaultNaN,
5749 kFP64DefaultNaN, kFP64DefaultNaN);
5750 FmaddFmsubHelper(0, kFP64NegativeInfinity, qa,
5751 kFP64DefaultNaN, kFP64DefaultNaN,
5752 kFP64DefaultNaN, kFP64DefaultNaN);
5753 FmaddFmsubHelper(kFP64NegativeInfinity, 0, qa,
5754 kFP64DefaultNaN, kFP64DefaultNaN,
5755 kFP64DefaultNaN, kFP64DefaultNaN);
5756}
armvixlf37fdc02014-02-05 13:22:16 +00005757
armvixlf37fdc02014-02-05 13:22:16 +00005758
armvixlb0c8ae22014-03-21 14:03:59 +00005759TEST(fmadd_fmsub_float_nans) {
5760 // Make sure that NaN propagation works correctly.
5761 float s1 = rawbits_to_float(0x7f951111);
5762 float s2 = rawbits_to_float(0x7f952222);
5763 float sa = rawbits_to_float(0x7f95aaaa);
5764 float q1 = rawbits_to_float(0x7fea1111);
5765 float q2 = rawbits_to_float(0x7fea2222);
5766 float qa = rawbits_to_float(0x7feaaaaa);
5767 VIXL_ASSERT(IsSignallingNaN(s1));
5768 VIXL_ASSERT(IsSignallingNaN(s2));
5769 VIXL_ASSERT(IsSignallingNaN(sa));
5770 VIXL_ASSERT(IsQuietNaN(q1));
5771 VIXL_ASSERT(IsQuietNaN(q2));
5772 VIXL_ASSERT(IsQuietNaN(qa));
armvixlf37fdc02014-02-05 13:22:16 +00005773
armvixlb0c8ae22014-03-21 14:03:59 +00005774 // The input NaNs after passing through ProcessNaN.
5775 float s1_proc = rawbits_to_float(0x7fd51111);
5776 float s2_proc = rawbits_to_float(0x7fd52222);
5777 float sa_proc = rawbits_to_float(0x7fd5aaaa);
5778 float q1_proc = q1;
5779 float q2_proc = q2;
5780 float qa_proc = qa;
5781 VIXL_ASSERT(IsQuietNaN(s1_proc));
5782 VIXL_ASSERT(IsQuietNaN(s2_proc));
5783 VIXL_ASSERT(IsQuietNaN(sa_proc));
5784 VIXL_ASSERT(IsQuietNaN(q1_proc));
5785 VIXL_ASSERT(IsQuietNaN(q2_proc));
5786 VIXL_ASSERT(IsQuietNaN(qa_proc));
5787
armvixl5799d6c2014-05-01 11:05:00 +01005788 // Negated NaNs as it would be done on ARMv8 hardware.
5789 float s1_proc_neg = rawbits_to_float(0xffd51111);
5790 float sa_proc_neg = rawbits_to_float(0xffd5aaaa);
5791 float q1_proc_neg = rawbits_to_float(0xffea1111);
5792 float qa_proc_neg = rawbits_to_float(0xffeaaaaa);
5793 VIXL_ASSERT(IsQuietNaN(s1_proc_neg));
5794 VIXL_ASSERT(IsQuietNaN(sa_proc_neg));
5795 VIXL_ASSERT(IsQuietNaN(q1_proc_neg));
5796 VIXL_ASSERT(IsQuietNaN(qa_proc_neg));
5797
armvixlb0c8ae22014-03-21 14:03:59 +00005798 // Quiet NaNs are propagated.
armvixl5799d6c2014-05-01 11:05:00 +01005799 FmaddFmsubHelper(q1, 0, 0, q1_proc, q1_proc_neg, q1_proc_neg, q1_proc);
armvixlb0c8ae22014-03-21 14:03:59 +00005800 FmaddFmsubHelper(0, q2, 0, q2_proc, q2_proc, q2_proc, q2_proc);
armvixl5799d6c2014-05-01 11:05:00 +01005801 FmaddFmsubHelper(0, 0, qa, qa_proc, qa_proc, qa_proc_neg, qa_proc_neg);
5802 FmaddFmsubHelper(q1, q2, 0, q1_proc, q1_proc_neg, q1_proc_neg, q1_proc);
5803 FmaddFmsubHelper(0, q2, qa, qa_proc, qa_proc, qa_proc_neg, qa_proc_neg);
5804 FmaddFmsubHelper(q1, 0, qa, qa_proc, qa_proc, qa_proc_neg, qa_proc_neg);
5805 FmaddFmsubHelper(q1, q2, qa, qa_proc, qa_proc, qa_proc_neg, qa_proc_neg);
armvixlb0c8ae22014-03-21 14:03:59 +00005806
5807 // Signalling NaNs are propagated, and made quiet.
armvixl5799d6c2014-05-01 11:05:00 +01005808 FmaddFmsubHelper(s1, 0, 0, s1_proc, s1_proc_neg, s1_proc_neg, s1_proc);
armvixlb0c8ae22014-03-21 14:03:59 +00005809 FmaddFmsubHelper(0, s2, 0, s2_proc, s2_proc, s2_proc, s2_proc);
armvixl5799d6c2014-05-01 11:05:00 +01005810 FmaddFmsubHelper(0, 0, sa, sa_proc, sa_proc, sa_proc_neg, sa_proc_neg);
5811 FmaddFmsubHelper(s1, s2, 0, s1_proc, s1_proc_neg, s1_proc_neg, s1_proc);
5812 FmaddFmsubHelper(0, s2, sa, sa_proc, sa_proc, sa_proc_neg, sa_proc_neg);
5813 FmaddFmsubHelper(s1, 0, sa, sa_proc, sa_proc, sa_proc_neg, sa_proc_neg);
5814 FmaddFmsubHelper(s1, s2, sa, sa_proc, sa_proc, sa_proc_neg, sa_proc_neg);
armvixlb0c8ae22014-03-21 14:03:59 +00005815
5816 // Signalling NaNs take precedence over quiet NaNs.
armvixl5799d6c2014-05-01 11:05:00 +01005817 FmaddFmsubHelper(s1, q2, qa, s1_proc, s1_proc_neg, s1_proc_neg, s1_proc);
armvixlb0c8ae22014-03-21 14:03:59 +00005818 FmaddFmsubHelper(q1, s2, qa, s2_proc, s2_proc, s2_proc, s2_proc);
armvixl5799d6c2014-05-01 11:05:00 +01005819 FmaddFmsubHelper(q1, q2, sa, sa_proc, sa_proc, sa_proc_neg, sa_proc_neg);
5820 FmaddFmsubHelper(s1, s2, qa, s1_proc, s1_proc_neg, s1_proc_neg, s1_proc);
5821 FmaddFmsubHelper(q1, s2, sa, sa_proc, sa_proc, sa_proc_neg, sa_proc_neg);
5822 FmaddFmsubHelper(s1, q2, sa, sa_proc, sa_proc, sa_proc_neg, sa_proc_neg);
5823 FmaddFmsubHelper(s1, s2, sa, sa_proc, sa_proc, sa_proc_neg, sa_proc_neg);
armvixlb0c8ae22014-03-21 14:03:59 +00005824
5825 // A NaN generated by the intermediate op1 * op2 overrides a quiet NaN in a.
5826 FmaddFmsubHelper(0, kFP32PositiveInfinity, qa,
5827 kFP32DefaultNaN, kFP32DefaultNaN,
5828 kFP32DefaultNaN, kFP32DefaultNaN);
5829 FmaddFmsubHelper(kFP32PositiveInfinity, 0, qa,
5830 kFP32DefaultNaN, kFP32DefaultNaN,
5831 kFP32DefaultNaN, kFP32DefaultNaN);
5832 FmaddFmsubHelper(0, kFP32NegativeInfinity, qa,
5833 kFP32DefaultNaN, kFP32DefaultNaN,
5834 kFP32DefaultNaN, kFP32DefaultNaN);
5835 FmaddFmsubHelper(kFP32NegativeInfinity, 0, qa,
5836 kFP32DefaultNaN, kFP32DefaultNaN,
5837 kFP32DefaultNaN, kFP32DefaultNaN);
armvixlf37fdc02014-02-05 13:22:16 +00005838}
5839
5840
armvixlad96eda2013-06-14 11:42:37 +01005841TEST(fdiv) {
5842 SETUP();
5843
5844 START();
armvixlb0c8ae22014-03-21 14:03:59 +00005845 __ Fmov(s14, -0.0f);
5846 __ Fmov(s15, kFP32PositiveInfinity);
5847 __ Fmov(s16, kFP32NegativeInfinity);
5848 __ Fmov(s17, 3.25f);
5849 __ Fmov(s18, 2.0f);
5850 __ Fmov(s19, 2.0f);
5851 __ Fmov(s20, -2.0f);
armvixlad96eda2013-06-14 11:42:37 +01005852
5853 __ Fmov(d26, -0.0);
5854 __ Fmov(d27, kFP64PositiveInfinity);
5855 __ Fmov(d28, kFP64NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00005856 __ Fmov(d29, 0.0);
armvixlad96eda2013-06-14 11:42:37 +01005857 __ Fmov(d30, -2.0);
5858 __ Fmov(d31, 2.25);
5859
armvixlb0c8ae22014-03-21 14:03:59 +00005860 __ Fdiv(s0, s17, s18);
5861 __ Fdiv(s1, s18, s19);
5862 __ Fdiv(s2, s14, s18);
5863 __ Fdiv(s3, s18, s15);
5864 __ Fdiv(s4, s18, s16);
5865 __ Fdiv(s5, s15, s16);
5866 __ Fdiv(s6, s14, s14);
5867
5868 __ Fdiv(d7, d31, d30);
5869 __ Fdiv(d8, d29, d31);
5870 __ Fdiv(d9, d26, d31);
5871 __ Fdiv(d10, d31, d27);
5872 __ Fdiv(d11, d31, d28);
5873 __ Fdiv(d12, d28, d27);
5874 __ Fdiv(d13, d29, d29);
armvixlad96eda2013-06-14 11:42:37 +01005875 END();
5876
5877 RUN();
5878
armvixlb0c8ae22014-03-21 14:03:59 +00005879 ASSERT_EQUAL_FP32(1.625f, s0);
5880 ASSERT_EQUAL_FP32(1.0f, s1);
5881 ASSERT_EQUAL_FP32(-0.0f, s2);
5882 ASSERT_EQUAL_FP32(0.0f, s3);
5883 ASSERT_EQUAL_FP32(-0.0f, s4);
5884 ASSERT_EQUAL_FP32(kFP32DefaultNaN, s5);
5885 ASSERT_EQUAL_FP32(kFP32DefaultNaN, s6);
5886 ASSERT_EQUAL_FP64(-1.125, d7);
armvixlad96eda2013-06-14 11:42:37 +01005887 ASSERT_EQUAL_FP64(0.0, d8);
5888 ASSERT_EQUAL_FP64(-0.0, d9);
armvixlb0c8ae22014-03-21 14:03:59 +00005889 ASSERT_EQUAL_FP64(0.0, d10);
5890 ASSERT_EQUAL_FP64(-0.0, d11);
5891 ASSERT_EQUAL_FP64(kFP64DefaultNaN, d12);
5892 ASSERT_EQUAL_FP64(kFP64DefaultNaN, d13);
armvixlad96eda2013-06-14 11:42:37 +01005893
5894 TEARDOWN();
5895}
5896
5897
armvixlf37fdc02014-02-05 13:22:16 +00005898static float MinMaxHelper(float n,
5899 float m,
5900 bool min,
5901 float quiet_nan_substitute = 0.0) {
armvixlb0c8ae22014-03-21 14:03:59 +00005902 const uint64_t kFP32QuietNaNMask = 0x00400000;
armvixlf37fdc02014-02-05 13:22:16 +00005903 uint32_t raw_n = float_to_rawbits(n);
5904 uint32_t raw_m = float_to_rawbits(m);
armvixlad96eda2013-06-14 11:42:37 +01005905
armvixlf37fdc02014-02-05 13:22:16 +00005906 if (isnan(n) && ((raw_n & kFP32QuietNaNMask) == 0)) {
5907 // n is signalling NaN.
armvixlb0c8ae22014-03-21 14:03:59 +00005908 return rawbits_to_float(raw_n | kFP32QuietNaNMask);
armvixlf37fdc02014-02-05 13:22:16 +00005909 } else if (isnan(m) && ((raw_m & kFP32QuietNaNMask) == 0)) {
5910 // m is signalling NaN.
armvixlb0c8ae22014-03-21 14:03:59 +00005911 return rawbits_to_float(raw_m | kFP32QuietNaNMask);
armvixlf37fdc02014-02-05 13:22:16 +00005912 } else if (quiet_nan_substitute == 0.0) {
5913 if (isnan(n)) {
5914 // n is quiet NaN.
5915 return n;
5916 } else if (isnan(m)) {
5917 // m is quiet NaN.
5918 return m;
5919 }
5920 } else {
5921 // Substitute n or m if one is quiet, but not both.
5922 if (isnan(n) && !isnan(m)) {
5923 // n is quiet NaN: replace with substitute.
5924 n = quiet_nan_substitute;
5925 } else if (!isnan(n) && isnan(m)) {
5926 // m is quiet NaN: replace with substitute.
5927 m = quiet_nan_substitute;
armvixlad96eda2013-06-14 11:42:37 +01005928 }
5929 }
armvixlad96eda2013-06-14 11:42:37 +01005930
armvixlf37fdc02014-02-05 13:22:16 +00005931 if ((n == 0.0) && (m == 0.0) &&
5932 (copysign(1.0, n) != copysign(1.0, m))) {
5933 return min ? -0.0 : 0.0;
5934 }
armvixlad96eda2013-06-14 11:42:37 +01005935
armvixlf37fdc02014-02-05 13:22:16 +00005936 return min ? fminf(n, m) : fmaxf(n, m);
armvixlad96eda2013-06-14 11:42:37 +01005937}
5938
5939
armvixlf37fdc02014-02-05 13:22:16 +00005940static double MinMaxHelper(double n,
5941 double m,
5942 bool min,
5943 double quiet_nan_substitute = 0.0) {
armvixlb0c8ae22014-03-21 14:03:59 +00005944 const uint64_t kFP64QuietNaNMask = 0x0008000000000000;
armvixlf37fdc02014-02-05 13:22:16 +00005945 uint64_t raw_n = double_to_rawbits(n);
5946 uint64_t raw_m = double_to_rawbits(m);
armvixlad96eda2013-06-14 11:42:37 +01005947
armvixlf37fdc02014-02-05 13:22:16 +00005948 if (isnan(n) && ((raw_n & kFP64QuietNaNMask) == 0)) {
5949 // n is signalling NaN.
armvixlb0c8ae22014-03-21 14:03:59 +00005950 return rawbits_to_double(raw_n | kFP64QuietNaNMask);
armvixlf37fdc02014-02-05 13:22:16 +00005951 } else if (isnan(m) && ((raw_m & kFP64QuietNaNMask) == 0)) {
5952 // m is signalling NaN.
armvixlb0c8ae22014-03-21 14:03:59 +00005953 return rawbits_to_double(raw_m | kFP64QuietNaNMask);
armvixlf37fdc02014-02-05 13:22:16 +00005954 } else if (quiet_nan_substitute == 0.0) {
5955 if (isnan(n)) {
5956 // n is quiet NaN.
5957 return n;
5958 } else if (isnan(m)) {
5959 // m is quiet NaN.
5960 return m;
5961 }
5962 } else {
5963 // Substitute n or m if one is quiet, but not both.
5964 if (isnan(n) && !isnan(m)) {
5965 // n is quiet NaN: replace with substitute.
5966 n = quiet_nan_substitute;
5967 } else if (!isnan(n) && isnan(m)) {
5968 // m is quiet NaN: replace with substitute.
5969 m = quiet_nan_substitute;
armvixlad96eda2013-06-14 11:42:37 +01005970 }
5971 }
armvixlf37fdc02014-02-05 13:22:16 +00005972
5973 if ((n == 0.0) && (m == 0.0) &&
5974 (copysign(1.0, n) != copysign(1.0, m))) {
5975 return min ? -0.0 : 0.0;
5976 }
5977
5978 return min ? fmin(n, m) : fmax(n, m);
5979}
5980
5981
5982static void FminFmaxDoubleHelper(double n, double m, double min, double max,
5983 double minnm, double maxnm) {
5984 SETUP();
5985
5986 START();
5987 __ Fmov(d0, n);
5988 __ Fmov(d1, m);
5989 __ Fmin(d28, d0, d1);
5990 __ Fmax(d29, d0, d1);
5991 __ Fminnm(d30, d0, d1);
5992 __ Fmaxnm(d31, d0, d1);
armvixlad96eda2013-06-14 11:42:37 +01005993 END();
5994
5995 RUN();
5996
armvixlf37fdc02014-02-05 13:22:16 +00005997 ASSERT_EQUAL_FP64(min, d28);
5998 ASSERT_EQUAL_FP64(max, d29);
5999 ASSERT_EQUAL_FP64(minnm, d30);
6000 ASSERT_EQUAL_FP64(maxnm, d31);
armvixlad96eda2013-06-14 11:42:37 +01006001
6002 TEARDOWN();
6003}
6004
6005
armvixlf37fdc02014-02-05 13:22:16 +00006006TEST(fmax_fmin_d) {
armvixlb0c8ae22014-03-21 14:03:59 +00006007 // Use non-standard NaNs to check that the payload bits are preserved.
6008 double snan = rawbits_to_double(0x7ff5555512345678);
6009 double qnan = rawbits_to_double(0x7ffaaaaa87654321);
6010
6011 double snan_processed = rawbits_to_double(0x7ffd555512345678);
6012 double qnan_processed = qnan;
6013
6014 VIXL_ASSERT(IsSignallingNaN(snan));
6015 VIXL_ASSERT(IsQuietNaN(qnan));
6016 VIXL_ASSERT(IsQuietNaN(snan_processed));
6017 VIXL_ASSERT(IsQuietNaN(qnan_processed));
6018
armvixlf37fdc02014-02-05 13:22:16 +00006019 // Bootstrap tests.
6020 FminFmaxDoubleHelper(0, 0, 0, 0, 0, 0);
6021 FminFmaxDoubleHelper(0, 1, 0, 1, 0, 1);
6022 FminFmaxDoubleHelper(kFP64PositiveInfinity, kFP64NegativeInfinity,
6023 kFP64NegativeInfinity, kFP64PositiveInfinity,
6024 kFP64NegativeInfinity, kFP64PositiveInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00006025 FminFmaxDoubleHelper(snan, 0,
6026 snan_processed, snan_processed,
6027 snan_processed, snan_processed);
6028 FminFmaxDoubleHelper(0, snan,
6029 snan_processed, snan_processed,
6030 snan_processed, snan_processed);
6031 FminFmaxDoubleHelper(qnan, 0,
6032 qnan_processed, qnan_processed,
armvixlf37fdc02014-02-05 13:22:16 +00006033 0, 0);
armvixlb0c8ae22014-03-21 14:03:59 +00006034 FminFmaxDoubleHelper(0, qnan,
6035 qnan_processed, qnan_processed,
6036 0, 0);
6037 FminFmaxDoubleHelper(qnan, snan,
6038 snan_processed, snan_processed,
6039 snan_processed, snan_processed);
6040 FminFmaxDoubleHelper(snan, qnan,
6041 snan_processed, snan_processed,
6042 snan_processed, snan_processed);
armvixlf37fdc02014-02-05 13:22:16 +00006043
6044 // Iterate over all combinations of inputs.
6045 double inputs[] = { DBL_MAX, DBL_MIN, 1.0, 0.0,
6046 -DBL_MAX, -DBL_MIN, -1.0, -0.0,
6047 kFP64PositiveInfinity, kFP64NegativeInfinity,
6048 kFP64QuietNaN, kFP64SignallingNaN };
6049
6050 const int count = sizeof(inputs) / sizeof(inputs[0]);
6051
6052 for (int in = 0; in < count; in++) {
6053 double n = inputs[in];
6054 for (int im = 0; im < count; im++) {
6055 double m = inputs[im];
6056 FminFmaxDoubleHelper(n, m,
6057 MinMaxHelper(n, m, true),
6058 MinMaxHelper(n, m, false),
6059 MinMaxHelper(n, m, true, kFP64PositiveInfinity),
6060 MinMaxHelper(n, m, false, kFP64NegativeInfinity));
6061 }
6062 }
6063}
6064
6065
6066static void FminFmaxFloatHelper(float n, float m, float min, float max,
6067 float minnm, float maxnm) {
6068 SETUP();
6069
6070 START();
armvixlb0c8ae22014-03-21 14:03:59 +00006071 __ Fmov(s0, n);
6072 __ Fmov(s1, m);
armvixlf37fdc02014-02-05 13:22:16 +00006073 __ Fmin(s28, s0, s1);
6074 __ Fmax(s29, s0, s1);
6075 __ Fminnm(s30, s0, s1);
6076 __ Fmaxnm(s31, s0, s1);
6077 END();
6078
6079 RUN();
6080
6081 ASSERT_EQUAL_FP32(min, s28);
6082 ASSERT_EQUAL_FP32(max, s29);
6083 ASSERT_EQUAL_FP32(minnm, s30);
6084 ASSERT_EQUAL_FP32(maxnm, s31);
6085
6086 TEARDOWN();
6087}
6088
6089
6090TEST(fmax_fmin_s) {
armvixlb0c8ae22014-03-21 14:03:59 +00006091 // Use non-standard NaNs to check that the payload bits are preserved.
6092 float snan = rawbits_to_float(0x7f951234);
6093 float qnan = rawbits_to_float(0x7fea8765);
6094
6095 float snan_processed = rawbits_to_float(0x7fd51234);
6096 float qnan_processed = qnan;
6097
6098 VIXL_ASSERT(IsSignallingNaN(snan));
6099 VIXL_ASSERT(IsQuietNaN(qnan));
6100 VIXL_ASSERT(IsQuietNaN(snan_processed));
6101 VIXL_ASSERT(IsQuietNaN(qnan_processed));
6102
armvixlf37fdc02014-02-05 13:22:16 +00006103 // Bootstrap tests.
6104 FminFmaxFloatHelper(0, 0, 0, 0, 0, 0);
6105 FminFmaxFloatHelper(0, 1, 0, 1, 0, 1);
6106 FminFmaxFloatHelper(kFP32PositiveInfinity, kFP32NegativeInfinity,
6107 kFP32NegativeInfinity, kFP32PositiveInfinity,
6108 kFP32NegativeInfinity, kFP32PositiveInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00006109 FminFmaxFloatHelper(snan, 0,
6110 snan_processed, snan_processed,
6111 snan_processed, snan_processed);
6112 FminFmaxFloatHelper(0, snan,
6113 snan_processed, snan_processed,
6114 snan_processed, snan_processed);
6115 FminFmaxFloatHelper(qnan, 0,
6116 qnan_processed, qnan_processed,
armvixlf37fdc02014-02-05 13:22:16 +00006117 0, 0);
armvixlb0c8ae22014-03-21 14:03:59 +00006118 FminFmaxFloatHelper(0, qnan,
6119 qnan_processed, qnan_processed,
6120 0, 0);
6121 FminFmaxFloatHelper(qnan, snan,
6122 snan_processed, snan_processed,
6123 snan_processed, snan_processed);
6124 FminFmaxFloatHelper(snan, qnan,
6125 snan_processed, snan_processed,
6126 snan_processed, snan_processed);
armvixlf37fdc02014-02-05 13:22:16 +00006127
6128 // Iterate over all combinations of inputs.
6129 float inputs[] = { FLT_MAX, FLT_MIN, 1.0, 0.0,
6130 -FLT_MAX, -FLT_MIN, -1.0, -0.0,
6131 kFP32PositiveInfinity, kFP32NegativeInfinity,
6132 kFP32QuietNaN, kFP32SignallingNaN };
6133
6134 const int count = sizeof(inputs) / sizeof(inputs[0]);
6135
6136 for (int in = 0; in < count; in++) {
6137 float n = inputs[in];
6138 for (int im = 0; im < count; im++) {
6139 float m = inputs[im];
6140 FminFmaxFloatHelper(n, m,
6141 MinMaxHelper(n, m, true),
6142 MinMaxHelper(n, m, false),
6143 MinMaxHelper(n, m, true, kFP32PositiveInfinity),
6144 MinMaxHelper(n, m, false, kFP32NegativeInfinity));
6145 }
6146 }
6147}
6148
6149
armvixlad96eda2013-06-14 11:42:37 +01006150TEST(fccmp) {
6151 SETUP();
armvixlc68cb642014-09-25 18:49:30 +01006152 ALLOW_ASM();
armvixlad96eda2013-06-14 11:42:37 +01006153
6154 START();
6155 __ Fmov(s16, 0.0);
6156 __ Fmov(s17, 0.5);
6157 __ Fmov(d18, -0.5);
6158 __ Fmov(d19, -1.0);
6159 __ Mov(x20, 0);
6160
armvixl578645f2013-08-15 17:21:42 +01006161 __ Cmp(x20, 0);
armvixlad96eda2013-06-14 11:42:37 +01006162 __ Fccmp(s16, s16, NoFlag, eq);
6163 __ Mrs(x0, NZCV);
6164
armvixl578645f2013-08-15 17:21:42 +01006165 __ Cmp(x20, 0);
armvixlad96eda2013-06-14 11:42:37 +01006166 __ Fccmp(s16, s16, VFlag, ne);
6167 __ Mrs(x1, NZCV);
6168
armvixl578645f2013-08-15 17:21:42 +01006169 __ Cmp(x20, 0);
armvixlad96eda2013-06-14 11:42:37 +01006170 __ Fccmp(s16, s17, CFlag, ge);
6171 __ Mrs(x2, NZCV);
6172
armvixl578645f2013-08-15 17:21:42 +01006173 __ Cmp(x20, 0);
armvixlad96eda2013-06-14 11:42:37 +01006174 __ Fccmp(s16, s17, CVFlag, lt);
6175 __ Mrs(x3, NZCV);
6176
armvixl578645f2013-08-15 17:21:42 +01006177 __ Cmp(x20, 0);
armvixlad96eda2013-06-14 11:42:37 +01006178 __ Fccmp(d18, d18, ZFlag, le);
6179 __ Mrs(x4, NZCV);
6180
armvixl578645f2013-08-15 17:21:42 +01006181 __ Cmp(x20, 0);
armvixlad96eda2013-06-14 11:42:37 +01006182 __ Fccmp(d18, d18, ZVFlag, gt);
6183 __ Mrs(x5, NZCV);
6184
armvixl578645f2013-08-15 17:21:42 +01006185 __ Cmp(x20, 0);
armvixlad96eda2013-06-14 11:42:37 +01006186 __ Fccmp(d18, d19, ZCVFlag, ls);
6187 __ Mrs(x6, NZCV);
6188
armvixl578645f2013-08-15 17:21:42 +01006189 __ Cmp(x20, 0);
armvixlad96eda2013-06-14 11:42:37 +01006190 __ Fccmp(d18, d19, NFlag, hi);
6191 __ Mrs(x7, NZCV);
armvixl578645f2013-08-15 17:21:42 +01006192
armvixlc68cb642014-09-25 18:49:30 +01006193 // The Macro Assembler does not allow al or nv as condition.
armvixl578645f2013-08-15 17:21:42 +01006194 __ fccmp(s16, s16, NFlag, al);
6195 __ Mrs(x8, NZCV);
6196
6197 __ fccmp(d18, d18, NFlag, nv);
6198 __ Mrs(x9, NZCV);
armvixlad96eda2013-06-14 11:42:37 +01006199 END();
6200
6201 RUN();
6202
6203 ASSERT_EQUAL_32(ZCFlag, w0);
6204 ASSERT_EQUAL_32(VFlag, w1);
6205 ASSERT_EQUAL_32(NFlag, w2);
6206 ASSERT_EQUAL_32(CVFlag, w3);
6207 ASSERT_EQUAL_32(ZCFlag, w4);
6208 ASSERT_EQUAL_32(ZVFlag, w5);
6209 ASSERT_EQUAL_32(CFlag, w6);
6210 ASSERT_EQUAL_32(NFlag, w7);
armvixl578645f2013-08-15 17:21:42 +01006211 ASSERT_EQUAL_32(ZCFlag, w8);
6212 ASSERT_EQUAL_32(ZCFlag, w9);
armvixlad96eda2013-06-14 11:42:37 +01006213
6214 TEARDOWN();
6215}
6216
6217
6218TEST(fcmp) {
6219 SETUP();
6220
6221 START();
armvixlf37fdc02014-02-05 13:22:16 +00006222
6223 // Some of these tests require a floating-point scratch register assigned to
6224 // the macro assembler, but most do not.
armvixlb0c8ae22014-03-21 14:03:59 +00006225 {
6226 UseScratchRegisterScope temps(&masm);
6227 temps.ExcludeAll();
6228 temps.Include(ip0, ip1);
armvixlf37fdc02014-02-05 13:22:16 +00006229
armvixlb0c8ae22014-03-21 14:03:59 +00006230 __ Fmov(s8, 0.0);
6231 __ Fmov(s9, 0.5);
6232 __ Mov(w18, 0x7f800001); // Single precision NaN.
6233 __ Fmov(s18, w18);
armvixlad96eda2013-06-14 11:42:37 +01006234
armvixlb0c8ae22014-03-21 14:03:59 +00006235 __ Fcmp(s8, s8);
6236 __ Mrs(x0, NZCV);
6237 __ Fcmp(s8, s9);
6238 __ Mrs(x1, NZCV);
6239 __ Fcmp(s9, s8);
6240 __ Mrs(x2, NZCV);
6241 __ Fcmp(s8, s18);
6242 __ Mrs(x3, NZCV);
6243 __ Fcmp(s18, s18);
6244 __ Mrs(x4, NZCV);
6245 __ Fcmp(s8, 0.0);
6246 __ Mrs(x5, NZCV);
6247 temps.Include(d0);
6248 __ Fcmp(s8, 255.0);
6249 temps.Exclude(d0);
6250 __ Mrs(x6, NZCV);
armvixlad96eda2013-06-14 11:42:37 +01006251
armvixlb0c8ae22014-03-21 14:03:59 +00006252 __ Fmov(d19, 0.0);
6253 __ Fmov(d20, 0.5);
6254 __ Mov(x21, 0x7ff0000000000001); // Double precision NaN.
6255 __ Fmov(d21, x21);
armvixlad96eda2013-06-14 11:42:37 +01006256
armvixlb0c8ae22014-03-21 14:03:59 +00006257 __ Fcmp(d19, d19);
6258 __ Mrs(x10, NZCV);
6259 __ Fcmp(d19, d20);
6260 __ Mrs(x11, NZCV);
6261 __ Fcmp(d20, d19);
6262 __ Mrs(x12, NZCV);
6263 __ Fcmp(d19, d21);
6264 __ Mrs(x13, NZCV);
6265 __ Fcmp(d21, d21);
6266 __ Mrs(x14, NZCV);
6267 __ Fcmp(d19, 0.0);
6268 __ Mrs(x15, NZCV);
6269 temps.Include(d0);
6270 __ Fcmp(d19, 12.3456);
6271 temps.Exclude(d0);
6272 __ Mrs(x16, NZCV);
6273 }
6274
armvixlad96eda2013-06-14 11:42:37 +01006275 END();
6276
6277 RUN();
6278
6279 ASSERT_EQUAL_32(ZCFlag, w0);
6280 ASSERT_EQUAL_32(NFlag, w1);
6281 ASSERT_EQUAL_32(CFlag, w2);
6282 ASSERT_EQUAL_32(CVFlag, w3);
6283 ASSERT_EQUAL_32(CVFlag, w4);
6284 ASSERT_EQUAL_32(ZCFlag, w5);
6285 ASSERT_EQUAL_32(NFlag, w6);
6286 ASSERT_EQUAL_32(ZCFlag, w10);
6287 ASSERT_EQUAL_32(NFlag, w11);
6288 ASSERT_EQUAL_32(CFlag, w12);
6289 ASSERT_EQUAL_32(CVFlag, w13);
6290 ASSERT_EQUAL_32(CVFlag, w14);
6291 ASSERT_EQUAL_32(ZCFlag, w15);
6292 ASSERT_EQUAL_32(NFlag, w16);
6293
6294 TEARDOWN();
6295}
6296
6297
6298TEST(fcsel) {
6299 SETUP();
armvixlc68cb642014-09-25 18:49:30 +01006300 ALLOW_ASM();
armvixlad96eda2013-06-14 11:42:37 +01006301
6302 START();
6303 __ Mov(x16, 0);
6304 __ Fmov(s16, 1.0);
6305 __ Fmov(s17, 2.0);
6306 __ Fmov(d18, 3.0);
6307 __ Fmov(d19, 4.0);
6308
armvixl578645f2013-08-15 17:21:42 +01006309 __ Cmp(x16, 0);
armvixlad96eda2013-06-14 11:42:37 +01006310 __ Fcsel(s0, s16, s17, eq);
6311 __ Fcsel(s1, s16, s17, ne);
6312 __ Fcsel(d2, d18, d19, eq);
6313 __ Fcsel(d3, d18, d19, ne);
armvixlc68cb642014-09-25 18:49:30 +01006314 // The Macro Assembler does not allow al or nv as condition.
armvixl578645f2013-08-15 17:21:42 +01006315 __ fcsel(s4, s16, s17, al);
6316 __ fcsel(d5, d18, d19, nv);
armvixlad96eda2013-06-14 11:42:37 +01006317 END();
6318
6319 RUN();
6320
6321 ASSERT_EQUAL_FP32(1.0, s0);
6322 ASSERT_EQUAL_FP32(2.0, s1);
6323 ASSERT_EQUAL_FP64(3.0, d2);
6324 ASSERT_EQUAL_FP64(4.0, d3);
armvixl578645f2013-08-15 17:21:42 +01006325 ASSERT_EQUAL_FP32(1.0, s4);
6326 ASSERT_EQUAL_FP64(3.0, d5);
armvixlad96eda2013-06-14 11:42:37 +01006327
6328 TEARDOWN();
6329}
6330
6331
6332TEST(fneg) {
6333 SETUP();
6334
6335 START();
6336 __ Fmov(s16, 1.0);
6337 __ Fmov(s17, 0.0);
6338 __ Fmov(s18, kFP32PositiveInfinity);
6339 __ Fmov(d19, 1.0);
6340 __ Fmov(d20, 0.0);
6341 __ Fmov(d21, kFP64PositiveInfinity);
6342
6343 __ Fneg(s0, s16);
6344 __ Fneg(s1, s0);
6345 __ Fneg(s2, s17);
6346 __ Fneg(s3, s2);
6347 __ Fneg(s4, s18);
6348 __ Fneg(s5, s4);
6349 __ Fneg(d6, d19);
6350 __ Fneg(d7, d6);
6351 __ Fneg(d8, d20);
6352 __ Fneg(d9, d8);
6353 __ Fneg(d10, d21);
6354 __ Fneg(d11, d10);
6355 END();
6356
6357 RUN();
6358
6359 ASSERT_EQUAL_FP32(-1.0, s0);
6360 ASSERT_EQUAL_FP32(1.0, s1);
6361 ASSERT_EQUAL_FP32(-0.0, s2);
6362 ASSERT_EQUAL_FP32(0.0, s3);
6363 ASSERT_EQUAL_FP32(kFP32NegativeInfinity, s4);
6364 ASSERT_EQUAL_FP32(kFP32PositiveInfinity, s5);
6365 ASSERT_EQUAL_FP64(-1.0, d6);
6366 ASSERT_EQUAL_FP64(1.0, d7);
6367 ASSERT_EQUAL_FP64(-0.0, d8);
6368 ASSERT_EQUAL_FP64(0.0, d9);
6369 ASSERT_EQUAL_FP64(kFP64NegativeInfinity, d10);
6370 ASSERT_EQUAL_FP64(kFP64PositiveInfinity, d11);
6371
6372 TEARDOWN();
6373}
6374
6375
6376TEST(fabs) {
6377 SETUP();
6378
6379 START();
6380 __ Fmov(s16, -1.0);
6381 __ Fmov(s17, -0.0);
6382 __ Fmov(s18, kFP32NegativeInfinity);
6383 __ Fmov(d19, -1.0);
6384 __ Fmov(d20, -0.0);
6385 __ Fmov(d21, kFP64NegativeInfinity);
6386
6387 __ Fabs(s0, s16);
6388 __ Fabs(s1, s0);
6389 __ Fabs(s2, s17);
6390 __ Fabs(s3, s18);
6391 __ Fabs(d4, d19);
6392 __ Fabs(d5, d4);
6393 __ Fabs(d6, d20);
6394 __ Fabs(d7, d21);
6395 END();
6396
6397 RUN();
6398
6399 ASSERT_EQUAL_FP32(1.0, s0);
6400 ASSERT_EQUAL_FP32(1.0, s1);
6401 ASSERT_EQUAL_FP32(0.0, s2);
6402 ASSERT_EQUAL_FP32(kFP32PositiveInfinity, s3);
6403 ASSERT_EQUAL_FP64(1.0, d4);
6404 ASSERT_EQUAL_FP64(1.0, d5);
6405 ASSERT_EQUAL_FP64(0.0, d6);
6406 ASSERT_EQUAL_FP64(kFP64PositiveInfinity, d7);
6407
6408 TEARDOWN();
6409}
6410
6411
6412TEST(fsqrt) {
6413 SETUP();
6414
6415 START();
6416 __ Fmov(s16, 0.0);
6417 __ Fmov(s17, 1.0);
6418 __ Fmov(s18, 0.25);
6419 __ Fmov(s19, 65536.0);
6420 __ Fmov(s20, -0.0);
6421 __ Fmov(s21, kFP32PositiveInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00006422 __ Fmov(s22, -1.0);
6423 __ Fmov(d23, 0.0);
6424 __ Fmov(d24, 1.0);
6425 __ Fmov(d25, 0.25);
6426 __ Fmov(d26, 4294967296.0);
6427 __ Fmov(d27, -0.0);
6428 __ Fmov(d28, kFP64PositiveInfinity);
6429 __ Fmov(d29, -1.0);
armvixlad96eda2013-06-14 11:42:37 +01006430
6431 __ Fsqrt(s0, s16);
6432 __ Fsqrt(s1, s17);
6433 __ Fsqrt(s2, s18);
6434 __ Fsqrt(s3, s19);
6435 __ Fsqrt(s4, s20);
6436 __ Fsqrt(s5, s21);
armvixlb0c8ae22014-03-21 14:03:59 +00006437 __ Fsqrt(s6, s22);
armvixlad96eda2013-06-14 11:42:37 +01006438 __ Fsqrt(d7, d23);
6439 __ Fsqrt(d8, d24);
6440 __ Fsqrt(d9, d25);
6441 __ Fsqrt(d10, d26);
6442 __ Fsqrt(d11, d27);
armvixlb0c8ae22014-03-21 14:03:59 +00006443 __ Fsqrt(d12, d28);
6444 __ Fsqrt(d13, d29);
armvixlad96eda2013-06-14 11:42:37 +01006445 END();
6446
6447 RUN();
6448
6449 ASSERT_EQUAL_FP32(0.0, s0);
6450 ASSERT_EQUAL_FP32(1.0, s1);
6451 ASSERT_EQUAL_FP32(0.5, s2);
6452 ASSERT_EQUAL_FP32(256.0, s3);
6453 ASSERT_EQUAL_FP32(-0.0, s4);
6454 ASSERT_EQUAL_FP32(kFP32PositiveInfinity, s5);
armvixlb0c8ae22014-03-21 14:03:59 +00006455 ASSERT_EQUAL_FP32(kFP32DefaultNaN, s6);
6456 ASSERT_EQUAL_FP64(0.0, d7);
6457 ASSERT_EQUAL_FP64(1.0, d8);
6458 ASSERT_EQUAL_FP64(0.5, d9);
6459 ASSERT_EQUAL_FP64(65536.0, d10);
6460 ASSERT_EQUAL_FP64(-0.0, d11);
6461 ASSERT_EQUAL_FP64(kFP32PositiveInfinity, d12);
6462 ASSERT_EQUAL_FP64(kFP64DefaultNaN, d13);
armvixlad96eda2013-06-14 11:42:37 +01006463
6464 TEARDOWN();
6465}
6466
6467
armvixlf37fdc02014-02-05 13:22:16 +00006468TEST(frinta) {
6469 SETUP();
6470
6471 START();
6472 __ Fmov(s16, 1.0);
6473 __ Fmov(s17, 1.1);
6474 __ Fmov(s18, 1.5);
6475 __ Fmov(s19, 1.9);
6476 __ Fmov(s20, 2.5);
6477 __ Fmov(s21, -1.5);
6478 __ Fmov(s22, -2.5);
6479 __ Fmov(s23, kFP32PositiveInfinity);
6480 __ Fmov(s24, kFP32NegativeInfinity);
6481 __ Fmov(s25, 0.0);
6482 __ Fmov(s26, -0.0);
armvixl5799d6c2014-05-01 11:05:00 +01006483 __ Fmov(s27, -0.2);
armvixlf37fdc02014-02-05 13:22:16 +00006484
6485 __ Frinta(s0, s16);
6486 __ Frinta(s1, s17);
6487 __ Frinta(s2, s18);
6488 __ Frinta(s3, s19);
6489 __ Frinta(s4, s20);
6490 __ Frinta(s5, s21);
6491 __ Frinta(s6, s22);
6492 __ Frinta(s7, s23);
6493 __ Frinta(s8, s24);
6494 __ Frinta(s9, s25);
6495 __ Frinta(s10, s26);
armvixl5799d6c2014-05-01 11:05:00 +01006496 __ Frinta(s11, s27);
armvixlf37fdc02014-02-05 13:22:16 +00006497
6498 __ Fmov(d16, 1.0);
6499 __ Fmov(d17, 1.1);
6500 __ Fmov(d18, 1.5);
6501 __ Fmov(d19, 1.9);
6502 __ Fmov(d20, 2.5);
6503 __ Fmov(d21, -1.5);
6504 __ Fmov(d22, -2.5);
6505 __ Fmov(d23, kFP32PositiveInfinity);
6506 __ Fmov(d24, kFP32NegativeInfinity);
6507 __ Fmov(d25, 0.0);
6508 __ Fmov(d26, -0.0);
armvixl5799d6c2014-05-01 11:05:00 +01006509 __ Fmov(d27, -0.2);
armvixlf37fdc02014-02-05 13:22:16 +00006510
armvixl5799d6c2014-05-01 11:05:00 +01006511 __ Frinta(d12, d16);
6512 __ Frinta(d13, d17);
6513 __ Frinta(d14, d18);
6514 __ Frinta(d15, d19);
6515 __ Frinta(d16, d20);
6516 __ Frinta(d17, d21);
6517 __ Frinta(d18, d22);
6518 __ Frinta(d19, d23);
6519 __ Frinta(d20, d24);
6520 __ Frinta(d21, d25);
6521 __ Frinta(d22, d26);
6522 __ Frinta(d23, d27);
armvixlf37fdc02014-02-05 13:22:16 +00006523 END();
6524
6525 RUN();
6526
6527 ASSERT_EQUAL_FP32(1.0, s0);
6528 ASSERT_EQUAL_FP32(1.0, s1);
6529 ASSERT_EQUAL_FP32(2.0, s2);
6530 ASSERT_EQUAL_FP32(2.0, s3);
6531 ASSERT_EQUAL_FP32(3.0, s4);
6532 ASSERT_EQUAL_FP32(-2.0, s5);
6533 ASSERT_EQUAL_FP32(-3.0, s6);
6534 ASSERT_EQUAL_FP32(kFP32PositiveInfinity, s7);
6535 ASSERT_EQUAL_FP32(kFP32NegativeInfinity, s8);
6536 ASSERT_EQUAL_FP32(0.0, s9);
6537 ASSERT_EQUAL_FP32(-0.0, s10);
armvixl5799d6c2014-05-01 11:05:00 +01006538 ASSERT_EQUAL_FP32(-0.0, s11);
armvixlf37fdc02014-02-05 13:22:16 +00006539 ASSERT_EQUAL_FP64(1.0, d12);
armvixl5799d6c2014-05-01 11:05:00 +01006540 ASSERT_EQUAL_FP64(1.0, d13);
armvixlf37fdc02014-02-05 13:22:16 +00006541 ASSERT_EQUAL_FP64(2.0, d14);
armvixl5799d6c2014-05-01 11:05:00 +01006542 ASSERT_EQUAL_FP64(2.0, d15);
6543 ASSERT_EQUAL_FP64(3.0, d16);
6544 ASSERT_EQUAL_FP64(-2.0, d17);
6545 ASSERT_EQUAL_FP64(-3.0, d18);
6546 ASSERT_EQUAL_FP64(kFP64PositiveInfinity, d19);
6547 ASSERT_EQUAL_FP64(kFP64NegativeInfinity, d20);
6548 ASSERT_EQUAL_FP64(0.0, d21);
6549 ASSERT_EQUAL_FP64(-0.0, d22);
6550 ASSERT_EQUAL_FP64(-0.0, d23);
6551
6552 TEARDOWN();
6553}
6554
6555
armvixl330dc712014-11-25 10:38:32 +00006556TEST(frinti) {
6557 // VIXL only supports the round-to-nearest FPCR mode, so this test has the
6558 // same results as frintn.
6559 SETUP();
6560
6561 START();
6562 __ Fmov(s16, 1.0);
6563 __ Fmov(s17, 1.1);
6564 __ Fmov(s18, 1.5);
6565 __ Fmov(s19, 1.9);
6566 __ Fmov(s20, 2.5);
6567 __ Fmov(s21, -1.5);
6568 __ Fmov(s22, -2.5);
6569 __ Fmov(s23, kFP32PositiveInfinity);
6570 __ Fmov(s24, kFP32NegativeInfinity);
6571 __ Fmov(s25, 0.0);
6572 __ Fmov(s26, -0.0);
6573 __ Fmov(s27, -0.2);
6574
6575 __ Frinti(s0, s16);
6576 __ Frinti(s1, s17);
6577 __ Frinti(s2, s18);
6578 __ Frinti(s3, s19);
6579 __ Frinti(s4, s20);
6580 __ Frinti(s5, s21);
6581 __ Frinti(s6, s22);
6582 __ Frinti(s7, s23);
6583 __ Frinti(s8, s24);
6584 __ Frinti(s9, s25);
6585 __ Frinti(s10, s26);
6586 __ Frinti(s11, s27);
6587
6588 __ Fmov(d16, 1.0);
6589 __ Fmov(d17, 1.1);
6590 __ Fmov(d18, 1.5);
6591 __ Fmov(d19, 1.9);
6592 __ Fmov(d20, 2.5);
6593 __ Fmov(d21, -1.5);
6594 __ Fmov(d22, -2.5);
6595 __ Fmov(d23, kFP32PositiveInfinity);
6596 __ Fmov(d24, kFP32NegativeInfinity);
6597 __ Fmov(d25, 0.0);
6598 __ Fmov(d26, -0.0);
6599 __ Fmov(d27, -0.2);
6600
6601 __ Frinti(d12, d16);
6602 __ Frinti(d13, d17);
6603 __ Frinti(d14, d18);
6604 __ Frinti(d15, d19);
6605 __ Frinti(d16, d20);
6606 __ Frinti(d17, d21);
6607 __ Frinti(d18, d22);
6608 __ Frinti(d19, d23);
6609 __ Frinti(d20, d24);
6610 __ Frinti(d21, d25);
6611 __ Frinti(d22, d26);
6612 __ Frinti(d23, d27);
6613 END();
6614
6615 RUN();
6616
6617 ASSERT_EQUAL_FP32(1.0, s0);
6618 ASSERT_EQUAL_FP32(1.0, s1);
6619 ASSERT_EQUAL_FP32(2.0, s2);
6620 ASSERT_EQUAL_FP32(2.0, s3);
6621 ASSERT_EQUAL_FP32(2.0, s4);
6622 ASSERT_EQUAL_FP32(-2.0, s5);
6623 ASSERT_EQUAL_FP32(-2.0, s6);
6624 ASSERT_EQUAL_FP32(kFP32PositiveInfinity, s7);
6625 ASSERT_EQUAL_FP32(kFP32NegativeInfinity, s8);
6626 ASSERT_EQUAL_FP32(0.0, s9);
6627 ASSERT_EQUAL_FP32(-0.0, s10);
6628 ASSERT_EQUAL_FP32(-0.0, s11);
6629 ASSERT_EQUAL_FP64(1.0, d12);
6630 ASSERT_EQUAL_FP64(1.0, d13);
6631 ASSERT_EQUAL_FP64(2.0, d14);
6632 ASSERT_EQUAL_FP64(2.0, d15);
6633 ASSERT_EQUAL_FP64(2.0, d16);
6634 ASSERT_EQUAL_FP64(-2.0, d17);
6635 ASSERT_EQUAL_FP64(-2.0, d18);
6636 ASSERT_EQUAL_FP64(kFP64PositiveInfinity, d19);
6637 ASSERT_EQUAL_FP64(kFP64NegativeInfinity, d20);
6638 ASSERT_EQUAL_FP64(0.0, d21);
6639 ASSERT_EQUAL_FP64(-0.0, d22);
6640 ASSERT_EQUAL_FP64(-0.0, d23);
6641
6642 TEARDOWN();
6643}
6644
6645
armvixl5799d6c2014-05-01 11:05:00 +01006646TEST(frintm) {
6647 SETUP();
6648
6649 START();
6650 __ Fmov(s16, 1.0);
6651 __ Fmov(s17, 1.1);
6652 __ Fmov(s18, 1.5);
6653 __ Fmov(s19, 1.9);
6654 __ Fmov(s20, 2.5);
6655 __ Fmov(s21, -1.5);
6656 __ Fmov(s22, -2.5);
6657 __ Fmov(s23, kFP32PositiveInfinity);
6658 __ Fmov(s24, kFP32NegativeInfinity);
6659 __ Fmov(s25, 0.0);
6660 __ Fmov(s26, -0.0);
6661 __ Fmov(s27, -0.2);
6662
6663 __ Frintm(s0, s16);
6664 __ Frintm(s1, s17);
6665 __ Frintm(s2, s18);
6666 __ Frintm(s3, s19);
6667 __ Frintm(s4, s20);
6668 __ Frintm(s5, s21);
6669 __ Frintm(s6, s22);
6670 __ Frintm(s7, s23);
6671 __ Frintm(s8, s24);
6672 __ Frintm(s9, s25);
6673 __ Frintm(s10, s26);
6674 __ Frintm(s11, s27);
6675
6676 __ Fmov(d16, 1.0);
6677 __ Fmov(d17, 1.1);
6678 __ Fmov(d18, 1.5);
6679 __ Fmov(d19, 1.9);
6680 __ Fmov(d20, 2.5);
6681 __ Fmov(d21, -1.5);
6682 __ Fmov(d22, -2.5);
6683 __ Fmov(d23, kFP32PositiveInfinity);
6684 __ Fmov(d24, kFP32NegativeInfinity);
6685 __ Fmov(d25, 0.0);
6686 __ Fmov(d26, -0.0);
6687 __ Fmov(d27, -0.2);
6688
6689 __ Frintm(d12, d16);
6690 __ Frintm(d13, d17);
6691 __ Frintm(d14, d18);
6692 __ Frintm(d15, d19);
6693 __ Frintm(d16, d20);
6694 __ Frintm(d17, d21);
6695 __ Frintm(d18, d22);
6696 __ Frintm(d19, d23);
6697 __ Frintm(d20, d24);
6698 __ Frintm(d21, d25);
6699 __ Frintm(d22, d26);
6700 __ Frintm(d23, d27);
6701 END();
6702
6703 RUN();
6704
6705 ASSERT_EQUAL_FP32(1.0, s0);
6706 ASSERT_EQUAL_FP32(1.0, s1);
6707 ASSERT_EQUAL_FP32(1.0, s2);
6708 ASSERT_EQUAL_FP32(1.0, s3);
6709 ASSERT_EQUAL_FP32(2.0, s4);
6710 ASSERT_EQUAL_FP32(-2.0, s5);
6711 ASSERT_EQUAL_FP32(-3.0, s6);
6712 ASSERT_EQUAL_FP32(kFP32PositiveInfinity, s7);
6713 ASSERT_EQUAL_FP32(kFP32NegativeInfinity, s8);
6714 ASSERT_EQUAL_FP32(0.0, s9);
6715 ASSERT_EQUAL_FP32(-0.0, s10);
6716 ASSERT_EQUAL_FP32(-1.0, s11);
6717 ASSERT_EQUAL_FP64(1.0, d12);
6718 ASSERT_EQUAL_FP64(1.0, d13);
6719 ASSERT_EQUAL_FP64(1.0, d14);
6720 ASSERT_EQUAL_FP64(1.0, d15);
6721 ASSERT_EQUAL_FP64(2.0, d16);
6722 ASSERT_EQUAL_FP64(-2.0, d17);
6723 ASSERT_EQUAL_FP64(-3.0, d18);
6724 ASSERT_EQUAL_FP64(kFP64PositiveInfinity, d19);
6725 ASSERT_EQUAL_FP64(kFP64NegativeInfinity, d20);
6726 ASSERT_EQUAL_FP64(0.0, d21);
6727 ASSERT_EQUAL_FP64(-0.0, d22);
6728 ASSERT_EQUAL_FP64(-1.0, d23);
armvixlf37fdc02014-02-05 13:22:16 +00006729
6730 TEARDOWN();
6731}
6732
6733
armvixlad96eda2013-06-14 11:42:37 +01006734TEST(frintn) {
6735 SETUP();
6736
6737 START();
6738 __ Fmov(s16, 1.0);
6739 __ Fmov(s17, 1.1);
6740 __ Fmov(s18, 1.5);
6741 __ Fmov(s19, 1.9);
6742 __ Fmov(s20, 2.5);
6743 __ Fmov(s21, -1.5);
6744 __ Fmov(s22, -2.5);
6745 __ Fmov(s23, kFP32PositiveInfinity);
6746 __ Fmov(s24, kFP32NegativeInfinity);
6747 __ Fmov(s25, 0.0);
6748 __ Fmov(s26, -0.0);
armvixl5799d6c2014-05-01 11:05:00 +01006749 __ Fmov(s27, -0.2);
armvixlad96eda2013-06-14 11:42:37 +01006750
6751 __ Frintn(s0, s16);
6752 __ Frintn(s1, s17);
6753 __ Frintn(s2, s18);
6754 __ Frintn(s3, s19);
6755 __ Frintn(s4, s20);
6756 __ Frintn(s5, s21);
6757 __ Frintn(s6, s22);
6758 __ Frintn(s7, s23);
6759 __ Frintn(s8, s24);
6760 __ Frintn(s9, s25);
6761 __ Frintn(s10, s26);
armvixl5799d6c2014-05-01 11:05:00 +01006762 __ Frintn(s11, s27);
armvixlad96eda2013-06-14 11:42:37 +01006763
6764 __ Fmov(d16, 1.0);
6765 __ Fmov(d17, 1.1);
6766 __ Fmov(d18, 1.5);
6767 __ Fmov(d19, 1.9);
6768 __ Fmov(d20, 2.5);
6769 __ Fmov(d21, -1.5);
6770 __ Fmov(d22, -2.5);
6771 __ Fmov(d23, kFP32PositiveInfinity);
6772 __ Fmov(d24, kFP32NegativeInfinity);
6773 __ Fmov(d25, 0.0);
6774 __ Fmov(d26, -0.0);
armvixl5799d6c2014-05-01 11:05:00 +01006775 __ Fmov(d27, -0.2);
armvixlad96eda2013-06-14 11:42:37 +01006776
armvixl5799d6c2014-05-01 11:05:00 +01006777 __ Frintn(d12, d16);
6778 __ Frintn(d13, d17);
6779 __ Frintn(d14, d18);
6780 __ Frintn(d15, d19);
6781 __ Frintn(d16, d20);
6782 __ Frintn(d17, d21);
6783 __ Frintn(d18, d22);
6784 __ Frintn(d19, d23);
6785 __ Frintn(d20, d24);
6786 __ Frintn(d21, d25);
6787 __ Frintn(d22, d26);
6788 __ Frintn(d23, d27);
armvixlad96eda2013-06-14 11:42:37 +01006789 END();
6790
6791 RUN();
6792
6793 ASSERT_EQUAL_FP32(1.0, s0);
6794 ASSERT_EQUAL_FP32(1.0, s1);
6795 ASSERT_EQUAL_FP32(2.0, s2);
6796 ASSERT_EQUAL_FP32(2.0, s3);
6797 ASSERT_EQUAL_FP32(2.0, s4);
6798 ASSERT_EQUAL_FP32(-2.0, s5);
6799 ASSERT_EQUAL_FP32(-2.0, s6);
6800 ASSERT_EQUAL_FP32(kFP32PositiveInfinity, s7);
6801 ASSERT_EQUAL_FP32(kFP32NegativeInfinity, s8);
6802 ASSERT_EQUAL_FP32(0.0, s9);
6803 ASSERT_EQUAL_FP32(-0.0, s10);
armvixl5799d6c2014-05-01 11:05:00 +01006804 ASSERT_EQUAL_FP32(-0.0, s11);
armvixlad96eda2013-06-14 11:42:37 +01006805 ASSERT_EQUAL_FP64(1.0, d12);
armvixl5799d6c2014-05-01 11:05:00 +01006806 ASSERT_EQUAL_FP64(1.0, d13);
armvixlad96eda2013-06-14 11:42:37 +01006807 ASSERT_EQUAL_FP64(2.0, d14);
6808 ASSERT_EQUAL_FP64(2.0, d15);
armvixl5799d6c2014-05-01 11:05:00 +01006809 ASSERT_EQUAL_FP64(2.0, d16);
armvixlad96eda2013-06-14 11:42:37 +01006810 ASSERT_EQUAL_FP64(-2.0, d17);
armvixl5799d6c2014-05-01 11:05:00 +01006811 ASSERT_EQUAL_FP64(-2.0, d18);
6812 ASSERT_EQUAL_FP64(kFP64PositiveInfinity, d19);
6813 ASSERT_EQUAL_FP64(kFP64NegativeInfinity, d20);
6814 ASSERT_EQUAL_FP64(0.0, d21);
6815 ASSERT_EQUAL_FP64(-0.0, d22);
6816 ASSERT_EQUAL_FP64(-0.0, d23);
armvixlad96eda2013-06-14 11:42:37 +01006817
6818 TEARDOWN();
6819}
6820
6821
armvixl330dc712014-11-25 10:38:32 +00006822TEST(frintp) {
6823 SETUP();
6824
6825 START();
6826 __ Fmov(s16, 1.0);
6827 __ Fmov(s17, 1.1);
6828 __ Fmov(s18, 1.5);
6829 __ Fmov(s19, 1.9);
6830 __ Fmov(s20, 2.5);
6831 __ Fmov(s21, -1.5);
6832 __ Fmov(s22, -2.5);
6833 __ Fmov(s23, kFP32PositiveInfinity);
6834 __ Fmov(s24, kFP32NegativeInfinity);
6835 __ Fmov(s25, 0.0);
6836 __ Fmov(s26, -0.0);
6837 __ Fmov(s27, -0.2);
6838
6839 __ Frintp(s0, s16);
6840 __ Frintp(s1, s17);
6841 __ Frintp(s2, s18);
6842 __ Frintp(s3, s19);
6843 __ Frintp(s4, s20);
6844 __ Frintp(s5, s21);
6845 __ Frintp(s6, s22);
6846 __ Frintp(s7, s23);
6847 __ Frintp(s8, s24);
6848 __ Frintp(s9, s25);
6849 __ Frintp(s10, s26);
6850 __ Frintp(s11, s27);
6851
6852 __ Fmov(d16, 1.0);
6853 __ Fmov(d17, 1.1);
6854 __ Fmov(d18, 1.5);
6855 __ Fmov(d19, 1.9);
6856 __ Fmov(d20, 2.5);
6857 __ Fmov(d21, -1.5);
6858 __ Fmov(d22, -2.5);
6859 __ Fmov(d23, kFP32PositiveInfinity);
6860 __ Fmov(d24, kFP32NegativeInfinity);
6861 __ Fmov(d25, 0.0);
6862 __ Fmov(d26, -0.0);
6863 __ Fmov(d27, -0.2);
6864
6865 __ Frintp(d12, d16);
6866 __ Frintp(d13, d17);
6867 __ Frintp(d14, d18);
6868 __ Frintp(d15, d19);
6869 __ Frintp(d16, d20);
6870 __ Frintp(d17, d21);
6871 __ Frintp(d18, d22);
6872 __ Frintp(d19, d23);
6873 __ Frintp(d20, d24);
6874 __ Frintp(d21, d25);
6875 __ Frintp(d22, d26);
6876 __ Frintp(d23, d27);
6877 END();
6878
6879 RUN();
6880
6881 ASSERT_EQUAL_FP32(1.0, s0);
6882 ASSERT_EQUAL_FP32(2.0, s1);
6883 ASSERT_EQUAL_FP32(2.0, s2);
6884 ASSERT_EQUAL_FP32(2.0, s3);
6885 ASSERT_EQUAL_FP32(3.0, s4);
6886 ASSERT_EQUAL_FP32(-1.0, s5);
6887 ASSERT_EQUAL_FP32(-2.0, s6);
6888 ASSERT_EQUAL_FP32(kFP32PositiveInfinity, s7);
6889 ASSERT_EQUAL_FP32(kFP32NegativeInfinity, s8);
6890 ASSERT_EQUAL_FP32(0.0, s9);
6891 ASSERT_EQUAL_FP32(-0.0, s10);
6892 ASSERT_EQUAL_FP32(-0.0, s11);
6893 ASSERT_EQUAL_FP64(1.0, d12);
6894 ASSERT_EQUAL_FP64(2.0, d13);
6895 ASSERT_EQUAL_FP64(2.0, d14);
6896 ASSERT_EQUAL_FP64(2.0, d15);
6897 ASSERT_EQUAL_FP64(3.0, d16);
6898 ASSERT_EQUAL_FP64(-1.0, d17);
6899 ASSERT_EQUAL_FP64(-2.0, d18);
6900 ASSERT_EQUAL_FP64(kFP64PositiveInfinity, d19);
6901 ASSERT_EQUAL_FP64(kFP64NegativeInfinity, d20);
6902 ASSERT_EQUAL_FP64(0.0, d21);
6903 ASSERT_EQUAL_FP64(-0.0, d22);
6904 ASSERT_EQUAL_FP64(-0.0, d23);
6905
6906 TEARDOWN();
6907}
6908
6909
6910TEST(frintx) {
6911 // VIXL only supports the round-to-nearest FPCR mode, and it doesn't support
6912 // FP exceptions, so this test has the same results as frintn (and frinti).
6913 SETUP();
6914
6915 START();
6916 __ Fmov(s16, 1.0);
6917 __ Fmov(s17, 1.1);
6918 __ Fmov(s18, 1.5);
6919 __ Fmov(s19, 1.9);
6920 __ Fmov(s20, 2.5);
6921 __ Fmov(s21, -1.5);
6922 __ Fmov(s22, -2.5);
6923 __ Fmov(s23, kFP32PositiveInfinity);
6924 __ Fmov(s24, kFP32NegativeInfinity);
6925 __ Fmov(s25, 0.0);
6926 __ Fmov(s26, -0.0);
6927 __ Fmov(s27, -0.2);
6928
6929 __ Frintx(s0, s16);
6930 __ Frintx(s1, s17);
6931 __ Frintx(s2, s18);
6932 __ Frintx(s3, s19);
6933 __ Frintx(s4, s20);
6934 __ Frintx(s5, s21);
6935 __ Frintx(s6, s22);
6936 __ Frintx(s7, s23);
6937 __ Frintx(s8, s24);
6938 __ Frintx(s9, s25);
6939 __ Frintx(s10, s26);
6940 __ Frintx(s11, s27);
6941
6942 __ Fmov(d16, 1.0);
6943 __ Fmov(d17, 1.1);
6944 __ Fmov(d18, 1.5);
6945 __ Fmov(d19, 1.9);
6946 __ Fmov(d20, 2.5);
6947 __ Fmov(d21, -1.5);
6948 __ Fmov(d22, -2.5);
6949 __ Fmov(d23, kFP32PositiveInfinity);
6950 __ Fmov(d24, kFP32NegativeInfinity);
6951 __ Fmov(d25, 0.0);
6952 __ Fmov(d26, -0.0);
6953 __ Fmov(d27, -0.2);
6954
6955 __ Frintx(d12, d16);
6956 __ Frintx(d13, d17);
6957 __ Frintx(d14, d18);
6958 __ Frintx(d15, d19);
6959 __ Frintx(d16, d20);
6960 __ Frintx(d17, d21);
6961 __ Frintx(d18, d22);
6962 __ Frintx(d19, d23);
6963 __ Frintx(d20, d24);
6964 __ Frintx(d21, d25);
6965 __ Frintx(d22, d26);
6966 __ Frintx(d23, d27);
6967 END();
6968
6969 RUN();
6970
6971 ASSERT_EQUAL_FP32(1.0, s0);
6972 ASSERT_EQUAL_FP32(1.0, s1);
6973 ASSERT_EQUAL_FP32(2.0, s2);
6974 ASSERT_EQUAL_FP32(2.0, s3);
6975 ASSERT_EQUAL_FP32(2.0, s4);
6976 ASSERT_EQUAL_FP32(-2.0, s5);
6977 ASSERT_EQUAL_FP32(-2.0, s6);
6978 ASSERT_EQUAL_FP32(kFP32PositiveInfinity, s7);
6979 ASSERT_EQUAL_FP32(kFP32NegativeInfinity, s8);
6980 ASSERT_EQUAL_FP32(0.0, s9);
6981 ASSERT_EQUAL_FP32(-0.0, s10);
6982 ASSERT_EQUAL_FP32(-0.0, s11);
6983 ASSERT_EQUAL_FP64(1.0, d12);
6984 ASSERT_EQUAL_FP64(1.0, d13);
6985 ASSERT_EQUAL_FP64(2.0, d14);
6986 ASSERT_EQUAL_FP64(2.0, d15);
6987 ASSERT_EQUAL_FP64(2.0, d16);
6988 ASSERT_EQUAL_FP64(-2.0, d17);
6989 ASSERT_EQUAL_FP64(-2.0, d18);
6990 ASSERT_EQUAL_FP64(kFP64PositiveInfinity, d19);
6991 ASSERT_EQUAL_FP64(kFP64NegativeInfinity, d20);
6992 ASSERT_EQUAL_FP64(0.0, d21);
6993 ASSERT_EQUAL_FP64(-0.0, d22);
6994 ASSERT_EQUAL_FP64(-0.0, d23);
6995
6996 TEARDOWN();
6997}
6998
6999
armvixlad96eda2013-06-14 11:42:37 +01007000TEST(frintz) {
7001 SETUP();
7002
7003 START();
7004 __ Fmov(s16, 1.0);
7005 __ Fmov(s17, 1.1);
7006 __ Fmov(s18, 1.5);
7007 __ Fmov(s19, 1.9);
7008 __ Fmov(s20, 2.5);
7009 __ Fmov(s21, -1.5);
7010 __ Fmov(s22, -2.5);
7011 __ Fmov(s23, kFP32PositiveInfinity);
7012 __ Fmov(s24, kFP32NegativeInfinity);
7013 __ Fmov(s25, 0.0);
7014 __ Fmov(s26, -0.0);
7015
7016 __ Frintz(s0, s16);
7017 __ Frintz(s1, s17);
7018 __ Frintz(s2, s18);
7019 __ Frintz(s3, s19);
7020 __ Frintz(s4, s20);
7021 __ Frintz(s5, s21);
7022 __ Frintz(s6, s22);
7023 __ Frintz(s7, s23);
7024 __ Frintz(s8, s24);
7025 __ Frintz(s9, s25);
7026 __ Frintz(s10, s26);
7027
7028 __ Fmov(d16, 1.0);
7029 __ Fmov(d17, 1.1);
7030 __ Fmov(d18, 1.5);
7031 __ Fmov(d19, 1.9);
7032 __ Fmov(d20, 2.5);
7033 __ Fmov(d21, -1.5);
7034 __ Fmov(d22, -2.5);
7035 __ Fmov(d23, kFP32PositiveInfinity);
7036 __ Fmov(d24, kFP32NegativeInfinity);
7037 __ Fmov(d25, 0.0);
7038 __ Fmov(d26, -0.0);
7039
7040 __ Frintz(d11, d16);
7041 __ Frintz(d12, d17);
7042 __ Frintz(d13, d18);
7043 __ Frintz(d14, d19);
7044 __ Frintz(d15, d20);
7045 __ Frintz(d16, d21);
7046 __ Frintz(d17, d22);
7047 __ Frintz(d18, d23);
7048 __ Frintz(d19, d24);
7049 __ Frintz(d20, d25);
7050 __ Frintz(d21, d26);
7051 END();
7052
7053 RUN();
7054
7055 ASSERT_EQUAL_FP32(1.0, s0);
7056 ASSERT_EQUAL_FP32(1.0, s1);
7057 ASSERT_EQUAL_FP32(1.0, s2);
7058 ASSERT_EQUAL_FP32(1.0, s3);
7059 ASSERT_EQUAL_FP32(2.0, s4);
7060 ASSERT_EQUAL_FP32(-1.0, s5);
7061 ASSERT_EQUAL_FP32(-2.0, s6);
7062 ASSERT_EQUAL_FP32(kFP32PositiveInfinity, s7);
7063 ASSERT_EQUAL_FP32(kFP32NegativeInfinity, s8);
7064 ASSERT_EQUAL_FP32(0.0, s9);
7065 ASSERT_EQUAL_FP32(-0.0, s10);
7066 ASSERT_EQUAL_FP64(1.0, d11);
7067 ASSERT_EQUAL_FP64(1.0, d12);
7068 ASSERT_EQUAL_FP64(1.0, d13);
7069 ASSERT_EQUAL_FP64(1.0, d14);
7070 ASSERT_EQUAL_FP64(2.0, d15);
7071 ASSERT_EQUAL_FP64(-1.0, d16);
7072 ASSERT_EQUAL_FP64(-2.0, d17);
7073 ASSERT_EQUAL_FP64(kFP64PositiveInfinity, d18);
7074 ASSERT_EQUAL_FP64(kFP64NegativeInfinity, d19);
7075 ASSERT_EQUAL_FP64(0.0, d20);
7076 ASSERT_EQUAL_FP64(-0.0, d21);
7077
7078 TEARDOWN();
7079}
7080
7081
armvixl578645f2013-08-15 17:21:42 +01007082TEST(fcvt_ds) {
armvixlad96eda2013-06-14 11:42:37 +01007083 SETUP();
7084
7085 START();
7086 __ Fmov(s16, 1.0);
7087 __ Fmov(s17, 1.1);
7088 __ Fmov(s18, 1.5);
7089 __ Fmov(s19, 1.9);
7090 __ Fmov(s20, 2.5);
7091 __ Fmov(s21, -1.5);
7092 __ Fmov(s22, -2.5);
7093 __ Fmov(s23, kFP32PositiveInfinity);
7094 __ Fmov(s24, kFP32NegativeInfinity);
7095 __ Fmov(s25, 0.0);
7096 __ Fmov(s26, -0.0);
armvixl578645f2013-08-15 17:21:42 +01007097 __ Fmov(s27, FLT_MAX);
7098 __ Fmov(s28, FLT_MIN);
7099 __ Fmov(s29, rawbits_to_float(0x7fc12345)); // Quiet NaN.
7100 __ Fmov(s30, rawbits_to_float(0x7f812345)); // Signalling NaN.
armvixlad96eda2013-06-14 11:42:37 +01007101
7102 __ Fcvt(d0, s16);
7103 __ Fcvt(d1, s17);
7104 __ Fcvt(d2, s18);
7105 __ Fcvt(d3, s19);
7106 __ Fcvt(d4, s20);
7107 __ Fcvt(d5, s21);
7108 __ Fcvt(d6, s22);
7109 __ Fcvt(d7, s23);
7110 __ Fcvt(d8, s24);
7111 __ Fcvt(d9, s25);
7112 __ Fcvt(d10, s26);
armvixl578645f2013-08-15 17:21:42 +01007113 __ Fcvt(d11, s27);
7114 __ Fcvt(d12, s28);
7115 __ Fcvt(d13, s29);
7116 __ Fcvt(d14, s30);
armvixlad96eda2013-06-14 11:42:37 +01007117 END();
7118
7119 RUN();
7120
7121 ASSERT_EQUAL_FP64(1.0f, d0);
7122 ASSERT_EQUAL_FP64(1.1f, d1);
7123 ASSERT_EQUAL_FP64(1.5f, d2);
7124 ASSERT_EQUAL_FP64(1.9f, d3);
7125 ASSERT_EQUAL_FP64(2.5f, d4);
7126 ASSERT_EQUAL_FP64(-1.5f, d5);
7127 ASSERT_EQUAL_FP64(-2.5f, d6);
7128 ASSERT_EQUAL_FP64(kFP64PositiveInfinity, d7);
7129 ASSERT_EQUAL_FP64(kFP64NegativeInfinity, d8);
7130 ASSERT_EQUAL_FP64(0.0f, d9);
7131 ASSERT_EQUAL_FP64(-0.0f, d10);
armvixl578645f2013-08-15 17:21:42 +01007132 ASSERT_EQUAL_FP64(FLT_MAX, d11);
7133 ASSERT_EQUAL_FP64(FLT_MIN, d12);
7134
7135 // Check that the NaN payload is preserved according to A64 conversion rules:
7136 // - The sign bit is preserved.
7137 // - The top bit of the mantissa is forced to 1 (making it a quiet NaN).
7138 // - The remaining mantissa bits are copied until they run out.
7139 // - The low-order bits that haven't already been assigned are set to 0.
7140 ASSERT_EQUAL_FP64(rawbits_to_double(0x7ff82468a0000000), d13);
7141 ASSERT_EQUAL_FP64(rawbits_to_double(0x7ff82468a0000000), d14);
armvixlad96eda2013-06-14 11:42:37 +01007142
7143 TEARDOWN();
7144}
7145
7146
armvixl578645f2013-08-15 17:21:42 +01007147TEST(fcvt_sd) {
armvixl5799d6c2014-05-01 11:05:00 +01007148 // Test simple conversions here. Complex behaviour (such as rounding
7149 // specifics) are tested in the simulator tests.
armvixl578645f2013-08-15 17:21:42 +01007150
armvixl5799d6c2014-05-01 11:05:00 +01007151 SETUP();
armvixl578645f2013-08-15 17:21:42 +01007152
armvixl5799d6c2014-05-01 11:05:00 +01007153 START();
7154 __ Fmov(d16, 1.0);
7155 __ Fmov(d17, 1.1);
7156 __ Fmov(d18, 1.5);
7157 __ Fmov(d19, 1.9);
7158 __ Fmov(d20, 2.5);
7159 __ Fmov(d21, -1.5);
7160 __ Fmov(d22, -2.5);
7161 __ Fmov(d23, kFP32PositiveInfinity);
7162 __ Fmov(d24, kFP32NegativeInfinity);
7163 __ Fmov(d25, 0.0);
7164 __ Fmov(d26, -0.0);
7165 __ Fmov(d27, FLT_MAX);
7166 __ Fmov(d28, FLT_MIN);
7167 __ Fmov(d29, rawbits_to_double(0x7ff82468a0000000)); // Quiet NaN.
7168 __ Fmov(d30, rawbits_to_double(0x7ff02468a0000000)); // Signalling NaN.
armvixl578645f2013-08-15 17:21:42 +01007169
armvixl5799d6c2014-05-01 11:05:00 +01007170 __ Fcvt(s0, d16);
7171 __ Fcvt(s1, d17);
7172 __ Fcvt(s2, d18);
7173 __ Fcvt(s3, d19);
7174 __ Fcvt(s4, d20);
7175 __ Fcvt(s5, d21);
7176 __ Fcvt(s6, d22);
7177 __ Fcvt(s7, d23);
7178 __ Fcvt(s8, d24);
7179 __ Fcvt(s9, d25);
7180 __ Fcvt(s10, d26);
7181 __ Fcvt(s11, d27);
7182 __ Fcvt(s12, d28);
7183 __ Fcvt(s13, d29);
7184 __ Fcvt(s14, d30);
7185 END();
armvixl578645f2013-08-15 17:21:42 +01007186
armvixl5799d6c2014-05-01 11:05:00 +01007187 RUN();
armvixl578645f2013-08-15 17:21:42 +01007188
armvixl5799d6c2014-05-01 11:05:00 +01007189 ASSERT_EQUAL_FP32(1.0f, s0);
7190 ASSERT_EQUAL_FP32(1.1f, s1);
7191 ASSERT_EQUAL_FP32(1.5f, s2);
7192 ASSERT_EQUAL_FP32(1.9f, s3);
7193 ASSERT_EQUAL_FP32(2.5f, s4);
7194 ASSERT_EQUAL_FP32(-1.5f, s5);
7195 ASSERT_EQUAL_FP32(-2.5f, s6);
7196 ASSERT_EQUAL_FP32(kFP32PositiveInfinity, s7);
7197 ASSERT_EQUAL_FP32(kFP32NegativeInfinity, s8);
7198 ASSERT_EQUAL_FP32(0.0f, s9);
7199 ASSERT_EQUAL_FP32(-0.0f, s10);
7200 ASSERT_EQUAL_FP32(FLT_MAX, s11);
7201 ASSERT_EQUAL_FP32(FLT_MIN, s12);
armvixl578645f2013-08-15 17:21:42 +01007202
armvixl5799d6c2014-05-01 11:05:00 +01007203 // Check that the NaN payload is preserved according to A64 conversion rules:
7204 // - The sign bit is preserved.
7205 // - The top bit of the mantissa is forced to 1 (making it a quiet NaN).
7206 // - The remaining mantissa bits are copied until they run out.
7207 // - The low-order bits that haven't already been assigned are set to 0.
7208 ASSERT_EQUAL_FP32(rawbits_to_float(0x7fc12345), s13);
7209 ASSERT_EQUAL_FP32(rawbits_to_float(0x7fc12345), s14);
armvixl578645f2013-08-15 17:21:42 +01007210
armvixl5799d6c2014-05-01 11:05:00 +01007211 TEARDOWN();
armvixl578645f2013-08-15 17:21:42 +01007212}
7213
7214
armvixlf37fdc02014-02-05 13:22:16 +00007215TEST(fcvtas) {
7216 SETUP();
7217
7218 START();
7219 __ Fmov(s0, 1.0);
7220 __ Fmov(s1, 1.1);
7221 __ Fmov(s2, 2.5);
7222 __ Fmov(s3, -2.5);
7223 __ Fmov(s4, kFP32PositiveInfinity);
7224 __ Fmov(s5, kFP32NegativeInfinity);
7225 __ Fmov(s6, 0x7fffff80); // Largest float < INT32_MAX.
7226 __ Fneg(s7, s6); // Smallest float > INT32_MIN.
7227 __ Fmov(d8, 1.0);
7228 __ Fmov(d9, 1.1);
7229 __ Fmov(d10, 2.5);
7230 __ Fmov(d11, -2.5);
7231 __ Fmov(d12, kFP64PositiveInfinity);
7232 __ Fmov(d13, kFP64NegativeInfinity);
7233 __ Fmov(d14, kWMaxInt - 1);
7234 __ Fmov(d15, kWMinInt + 1);
7235 __ Fmov(s17, 1.1);
7236 __ Fmov(s18, 2.5);
7237 __ Fmov(s19, -2.5);
7238 __ Fmov(s20, kFP32PositiveInfinity);
7239 __ Fmov(s21, kFP32NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00007240 __ Fmov(s22, 0x7fffff8000000000); // Largest float < INT64_MAX.
armvixlf37fdc02014-02-05 13:22:16 +00007241 __ Fneg(s23, s22); // Smallest float > INT64_MIN.
7242 __ Fmov(d24, 1.1);
7243 __ Fmov(d25, 2.5);
7244 __ Fmov(d26, -2.5);
7245 __ Fmov(d27, kFP64PositiveInfinity);
7246 __ Fmov(d28, kFP64NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00007247 __ Fmov(d29, 0x7ffffffffffffc00); // Largest double < INT64_MAX.
armvixlf37fdc02014-02-05 13:22:16 +00007248 __ Fneg(d30, d29); // Smallest double > INT64_MIN.
7249
7250 __ Fcvtas(w0, s0);
7251 __ Fcvtas(w1, s1);
7252 __ Fcvtas(w2, s2);
7253 __ Fcvtas(w3, s3);
7254 __ Fcvtas(w4, s4);
7255 __ Fcvtas(w5, s5);
7256 __ Fcvtas(w6, s6);
7257 __ Fcvtas(w7, s7);
7258 __ Fcvtas(w8, d8);
7259 __ Fcvtas(w9, d9);
7260 __ Fcvtas(w10, d10);
7261 __ Fcvtas(w11, d11);
7262 __ Fcvtas(w12, d12);
7263 __ Fcvtas(w13, d13);
7264 __ Fcvtas(w14, d14);
7265 __ Fcvtas(w15, d15);
7266 __ Fcvtas(x17, s17);
7267 __ Fcvtas(x18, s18);
7268 __ Fcvtas(x19, s19);
7269 __ Fcvtas(x20, s20);
7270 __ Fcvtas(x21, s21);
7271 __ Fcvtas(x22, s22);
7272 __ Fcvtas(x23, s23);
7273 __ Fcvtas(x24, d24);
7274 __ Fcvtas(x25, d25);
7275 __ Fcvtas(x26, d26);
7276 __ Fcvtas(x27, d27);
7277 __ Fcvtas(x28, d28);
7278 __ Fcvtas(x29, d29);
7279 __ Fcvtas(x30, d30);
7280 END();
7281
7282 RUN();
7283
7284 ASSERT_EQUAL_64(1, x0);
7285 ASSERT_EQUAL_64(1, x1);
7286 ASSERT_EQUAL_64(3, x2);
7287 ASSERT_EQUAL_64(0xfffffffd, x3);
7288 ASSERT_EQUAL_64(0x7fffffff, x4);
7289 ASSERT_EQUAL_64(0x80000000, x5);
7290 ASSERT_EQUAL_64(0x7fffff80, x6);
7291 ASSERT_EQUAL_64(0x80000080, x7);
7292 ASSERT_EQUAL_64(1, x8);
7293 ASSERT_EQUAL_64(1, x9);
7294 ASSERT_EQUAL_64(3, x10);
7295 ASSERT_EQUAL_64(0xfffffffd, x11);
7296 ASSERT_EQUAL_64(0x7fffffff, x12);
7297 ASSERT_EQUAL_64(0x80000000, x13);
7298 ASSERT_EQUAL_64(0x7ffffffe, x14);
7299 ASSERT_EQUAL_64(0x80000001, x15);
7300 ASSERT_EQUAL_64(1, x17);
7301 ASSERT_EQUAL_64(3, x18);
armvixlb0c8ae22014-03-21 14:03:59 +00007302 ASSERT_EQUAL_64(0xfffffffffffffffd, x19);
7303 ASSERT_EQUAL_64(0x7fffffffffffffff, x20);
7304 ASSERT_EQUAL_64(0x8000000000000000, x21);
7305 ASSERT_EQUAL_64(0x7fffff8000000000, x22);
7306 ASSERT_EQUAL_64(0x8000008000000000, x23);
armvixlf37fdc02014-02-05 13:22:16 +00007307 ASSERT_EQUAL_64(1, x24);
7308 ASSERT_EQUAL_64(3, x25);
armvixlb0c8ae22014-03-21 14:03:59 +00007309 ASSERT_EQUAL_64(0xfffffffffffffffd, x26);
7310 ASSERT_EQUAL_64(0x7fffffffffffffff, x27);
7311 ASSERT_EQUAL_64(0x8000000000000000, x28);
7312 ASSERT_EQUAL_64(0x7ffffffffffffc00, x29);
7313 ASSERT_EQUAL_64(0x8000000000000400, x30);
armvixlf37fdc02014-02-05 13:22:16 +00007314
7315 TEARDOWN();
7316}
7317
7318
7319TEST(fcvtau) {
7320 SETUP();
7321
7322 START();
7323 __ Fmov(s0, 1.0);
7324 __ Fmov(s1, 1.1);
7325 __ Fmov(s2, 2.5);
7326 __ Fmov(s3, -2.5);
7327 __ Fmov(s4, kFP32PositiveInfinity);
7328 __ Fmov(s5, kFP32NegativeInfinity);
7329 __ Fmov(s6, 0xffffff00); // Largest float < UINT32_MAX.
7330 __ Fmov(d8, 1.0);
7331 __ Fmov(d9, 1.1);
7332 __ Fmov(d10, 2.5);
7333 __ Fmov(d11, -2.5);
7334 __ Fmov(d12, kFP64PositiveInfinity);
7335 __ Fmov(d13, kFP64NegativeInfinity);
7336 __ Fmov(d14, 0xfffffffe);
7337 __ Fmov(s16, 1.0);
7338 __ Fmov(s17, 1.1);
7339 __ Fmov(s18, 2.5);
7340 __ Fmov(s19, -2.5);
7341 __ Fmov(s20, kFP32PositiveInfinity);
7342 __ Fmov(s21, kFP32NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00007343 __ Fmov(s22, 0xffffff0000000000); // Largest float < UINT64_MAX.
armvixlf37fdc02014-02-05 13:22:16 +00007344 __ Fmov(d24, 1.1);
7345 __ Fmov(d25, 2.5);
7346 __ Fmov(d26, -2.5);
7347 __ Fmov(d27, kFP64PositiveInfinity);
7348 __ Fmov(d28, kFP64NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00007349 __ Fmov(d29, 0xfffffffffffff800); // Largest double < UINT64_MAX.
7350 __ Fmov(s30, 0x100000000);
armvixlf37fdc02014-02-05 13:22:16 +00007351
7352 __ Fcvtau(w0, s0);
7353 __ Fcvtau(w1, s1);
7354 __ Fcvtau(w2, s2);
7355 __ Fcvtau(w3, s3);
7356 __ Fcvtau(w4, s4);
7357 __ Fcvtau(w5, s5);
7358 __ Fcvtau(w6, s6);
7359 __ Fcvtau(w8, d8);
7360 __ Fcvtau(w9, d9);
7361 __ Fcvtau(w10, d10);
7362 __ Fcvtau(w11, d11);
7363 __ Fcvtau(w12, d12);
7364 __ Fcvtau(w13, d13);
7365 __ Fcvtau(w14, d14);
7366 __ Fcvtau(w15, d15);
7367 __ Fcvtau(x16, s16);
7368 __ Fcvtau(x17, s17);
7369 __ Fcvtau(x18, s18);
7370 __ Fcvtau(x19, s19);
7371 __ Fcvtau(x20, s20);
7372 __ Fcvtau(x21, s21);
7373 __ Fcvtau(x22, s22);
7374 __ Fcvtau(x24, d24);
7375 __ Fcvtau(x25, d25);
7376 __ Fcvtau(x26, d26);
7377 __ Fcvtau(x27, d27);
7378 __ Fcvtau(x28, d28);
7379 __ Fcvtau(x29, d29);
7380 __ Fcvtau(w30, s30);
7381 END();
7382
7383 RUN();
7384
7385 ASSERT_EQUAL_64(1, x0);
7386 ASSERT_EQUAL_64(1, x1);
7387 ASSERT_EQUAL_64(3, x2);
7388 ASSERT_EQUAL_64(0, x3);
7389 ASSERT_EQUAL_64(0xffffffff, x4);
7390 ASSERT_EQUAL_64(0, x5);
7391 ASSERT_EQUAL_64(0xffffff00, x6);
7392 ASSERT_EQUAL_64(1, x8);
7393 ASSERT_EQUAL_64(1, x9);
7394 ASSERT_EQUAL_64(3, x10);
7395 ASSERT_EQUAL_64(0, x11);
7396 ASSERT_EQUAL_64(0xffffffff, x12);
7397 ASSERT_EQUAL_64(0, x13);
7398 ASSERT_EQUAL_64(0xfffffffe, x14);
7399 ASSERT_EQUAL_64(1, x16);
7400 ASSERT_EQUAL_64(1, x17);
7401 ASSERT_EQUAL_64(3, x18);
7402 ASSERT_EQUAL_64(0, x19);
armvixlb0c8ae22014-03-21 14:03:59 +00007403 ASSERT_EQUAL_64(0xffffffffffffffff, x20);
armvixlf37fdc02014-02-05 13:22:16 +00007404 ASSERT_EQUAL_64(0, x21);
armvixlb0c8ae22014-03-21 14:03:59 +00007405 ASSERT_EQUAL_64(0xffffff0000000000, x22);
armvixlf37fdc02014-02-05 13:22:16 +00007406 ASSERT_EQUAL_64(1, x24);
7407 ASSERT_EQUAL_64(3, x25);
7408 ASSERT_EQUAL_64(0, x26);
armvixlb0c8ae22014-03-21 14:03:59 +00007409 ASSERT_EQUAL_64(0xffffffffffffffff, x27);
armvixlf37fdc02014-02-05 13:22:16 +00007410 ASSERT_EQUAL_64(0, x28);
armvixlb0c8ae22014-03-21 14:03:59 +00007411 ASSERT_EQUAL_64(0xfffffffffffff800, x29);
armvixlf37fdc02014-02-05 13:22:16 +00007412 ASSERT_EQUAL_64(0xffffffff, x30);
7413
7414 TEARDOWN();
7415}
7416
7417
armvixlad96eda2013-06-14 11:42:37 +01007418TEST(fcvtms) {
7419 SETUP();
7420
7421 START();
7422 __ Fmov(s0, 1.0);
7423 __ Fmov(s1, 1.1);
7424 __ Fmov(s2, 1.5);
7425 __ Fmov(s3, -1.5);
7426 __ Fmov(s4, kFP32PositiveInfinity);
7427 __ Fmov(s5, kFP32NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00007428 __ Fmov(s6, 0x7fffff80); // Largest float < INT32_MAX.
7429 __ Fneg(s7, s6); // Smallest float > INT32_MIN.
armvixlad96eda2013-06-14 11:42:37 +01007430 __ Fmov(d8, 1.0);
7431 __ Fmov(d9, 1.1);
7432 __ Fmov(d10, 1.5);
7433 __ Fmov(d11, -1.5);
7434 __ Fmov(d12, kFP64PositiveInfinity);
7435 __ Fmov(d13, kFP64NegativeInfinity);
7436 __ Fmov(d14, kWMaxInt - 1);
7437 __ Fmov(d15, kWMinInt + 1);
7438 __ Fmov(s17, 1.1);
7439 __ Fmov(s18, 1.5);
7440 __ Fmov(s19, -1.5);
7441 __ Fmov(s20, kFP32PositiveInfinity);
7442 __ Fmov(s21, kFP32NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00007443 __ Fmov(s22, 0x7fffff8000000000); // Largest float < INT64_MAX.
7444 __ Fneg(s23, s22); // Smallest float > INT64_MIN.
armvixlad96eda2013-06-14 11:42:37 +01007445 __ Fmov(d24, 1.1);
7446 __ Fmov(d25, 1.5);
7447 __ Fmov(d26, -1.5);
7448 __ Fmov(d27, kFP64PositiveInfinity);
7449 __ Fmov(d28, kFP64NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00007450 __ Fmov(d29, 0x7ffffffffffffc00); // Largest double < INT64_MAX.
7451 __ Fneg(d30, d29); // Smallest double > INT64_MIN.
armvixlad96eda2013-06-14 11:42:37 +01007452
7453 __ Fcvtms(w0, s0);
7454 __ Fcvtms(w1, s1);
7455 __ Fcvtms(w2, s2);
7456 __ Fcvtms(w3, s3);
7457 __ Fcvtms(w4, s4);
7458 __ Fcvtms(w5, s5);
7459 __ Fcvtms(w6, s6);
7460 __ Fcvtms(w7, s7);
7461 __ Fcvtms(w8, d8);
7462 __ Fcvtms(w9, d9);
7463 __ Fcvtms(w10, d10);
7464 __ Fcvtms(w11, d11);
7465 __ Fcvtms(w12, d12);
7466 __ Fcvtms(w13, d13);
7467 __ Fcvtms(w14, d14);
7468 __ Fcvtms(w15, d15);
7469 __ Fcvtms(x17, s17);
7470 __ Fcvtms(x18, s18);
7471 __ Fcvtms(x19, s19);
7472 __ Fcvtms(x20, s20);
7473 __ Fcvtms(x21, s21);
7474 __ Fcvtms(x22, s22);
7475 __ Fcvtms(x23, s23);
7476 __ Fcvtms(x24, d24);
7477 __ Fcvtms(x25, d25);
7478 __ Fcvtms(x26, d26);
7479 __ Fcvtms(x27, d27);
7480 __ Fcvtms(x28, d28);
7481 __ Fcvtms(x29, d29);
7482 __ Fcvtms(x30, d30);
7483 END();
7484
7485 RUN();
7486
7487 ASSERT_EQUAL_64(1, x0);
7488 ASSERT_EQUAL_64(1, x1);
7489 ASSERT_EQUAL_64(1, x2);
7490 ASSERT_EQUAL_64(0xfffffffe, x3);
7491 ASSERT_EQUAL_64(0x7fffffff, x4);
7492 ASSERT_EQUAL_64(0x80000000, x5);
7493 ASSERT_EQUAL_64(0x7fffff80, x6);
7494 ASSERT_EQUAL_64(0x80000080, x7);
7495 ASSERT_EQUAL_64(1, x8);
7496 ASSERT_EQUAL_64(1, x9);
7497 ASSERT_EQUAL_64(1, x10);
7498 ASSERT_EQUAL_64(0xfffffffe, x11);
7499 ASSERT_EQUAL_64(0x7fffffff, x12);
7500 ASSERT_EQUAL_64(0x80000000, x13);
7501 ASSERT_EQUAL_64(0x7ffffffe, x14);
7502 ASSERT_EQUAL_64(0x80000001, x15);
7503 ASSERT_EQUAL_64(1, x17);
7504 ASSERT_EQUAL_64(1, x18);
armvixlb0c8ae22014-03-21 14:03:59 +00007505 ASSERT_EQUAL_64(0xfffffffffffffffe, x19);
7506 ASSERT_EQUAL_64(0x7fffffffffffffff, x20);
7507 ASSERT_EQUAL_64(0x8000000000000000, x21);
7508 ASSERT_EQUAL_64(0x7fffff8000000000, x22);
7509 ASSERT_EQUAL_64(0x8000008000000000, x23);
armvixlad96eda2013-06-14 11:42:37 +01007510 ASSERT_EQUAL_64(1, x24);
7511 ASSERT_EQUAL_64(1, x25);
armvixlb0c8ae22014-03-21 14:03:59 +00007512 ASSERT_EQUAL_64(0xfffffffffffffffe, x26);
7513 ASSERT_EQUAL_64(0x7fffffffffffffff, x27);
7514 ASSERT_EQUAL_64(0x8000000000000000, x28);
7515 ASSERT_EQUAL_64(0x7ffffffffffffc00, x29);
7516 ASSERT_EQUAL_64(0x8000000000000400, x30);
armvixlad96eda2013-06-14 11:42:37 +01007517
7518 TEARDOWN();
7519}
7520
7521
7522TEST(fcvtmu) {
7523 SETUP();
7524
7525 START();
7526 __ Fmov(s0, 1.0);
7527 __ Fmov(s1, 1.1);
7528 __ Fmov(s2, 1.5);
7529 __ Fmov(s3, -1.5);
7530 __ Fmov(s4, kFP32PositiveInfinity);
7531 __ Fmov(s5, kFP32NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00007532 __ Fmov(s6, 0x7fffff80); // Largest float < INT32_MAX.
7533 __ Fneg(s7, s6); // Smallest float > INT32_MIN.
armvixlad96eda2013-06-14 11:42:37 +01007534 __ Fmov(d8, 1.0);
7535 __ Fmov(d9, 1.1);
7536 __ Fmov(d10, 1.5);
7537 __ Fmov(d11, -1.5);
7538 __ Fmov(d12, kFP64PositiveInfinity);
7539 __ Fmov(d13, kFP64NegativeInfinity);
7540 __ Fmov(d14, kWMaxInt - 1);
7541 __ Fmov(d15, kWMinInt + 1);
7542 __ Fmov(s17, 1.1);
7543 __ Fmov(s18, 1.5);
7544 __ Fmov(s19, -1.5);
7545 __ Fmov(s20, kFP32PositiveInfinity);
7546 __ Fmov(s21, kFP32NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00007547 __ Fmov(s22, 0x7fffff8000000000); // Largest float < INT64_MAX.
7548 __ Fneg(s23, s22); // Smallest float > INT64_MIN.
armvixlad96eda2013-06-14 11:42:37 +01007549 __ Fmov(d24, 1.1);
7550 __ Fmov(d25, 1.5);
7551 __ Fmov(d26, -1.5);
7552 __ Fmov(d27, kFP64PositiveInfinity);
7553 __ Fmov(d28, kFP64NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00007554 __ Fmov(d29, 0x7ffffffffffffc00); // Largest double < INT64_MAX.
7555 __ Fneg(d30, d29); // Smallest double > INT64_MIN.
armvixlad96eda2013-06-14 11:42:37 +01007556
7557 __ Fcvtmu(w0, s0);
7558 __ Fcvtmu(w1, s1);
7559 __ Fcvtmu(w2, s2);
7560 __ Fcvtmu(w3, s3);
7561 __ Fcvtmu(w4, s4);
7562 __ Fcvtmu(w5, s5);
7563 __ Fcvtmu(w6, s6);
7564 __ Fcvtmu(w7, s7);
7565 __ Fcvtmu(w8, d8);
7566 __ Fcvtmu(w9, d9);
7567 __ Fcvtmu(w10, d10);
7568 __ Fcvtmu(w11, d11);
7569 __ Fcvtmu(w12, d12);
7570 __ Fcvtmu(w13, d13);
7571 __ Fcvtmu(w14, d14);
7572 __ Fcvtmu(x17, s17);
7573 __ Fcvtmu(x18, s18);
7574 __ Fcvtmu(x19, s19);
7575 __ Fcvtmu(x20, s20);
7576 __ Fcvtmu(x21, s21);
7577 __ Fcvtmu(x22, s22);
7578 __ Fcvtmu(x23, s23);
7579 __ Fcvtmu(x24, d24);
7580 __ Fcvtmu(x25, d25);
7581 __ Fcvtmu(x26, d26);
7582 __ Fcvtmu(x27, d27);
7583 __ Fcvtmu(x28, d28);
7584 __ Fcvtmu(x29, d29);
7585 __ Fcvtmu(x30, d30);
7586 END();
7587
7588 RUN();
7589
7590 ASSERT_EQUAL_64(1, x0);
7591 ASSERT_EQUAL_64(1, x1);
7592 ASSERT_EQUAL_64(1, x2);
7593 ASSERT_EQUAL_64(0, x3);
7594 ASSERT_EQUAL_64(0xffffffff, x4);
7595 ASSERT_EQUAL_64(0, x5);
7596 ASSERT_EQUAL_64(0x7fffff80, x6);
7597 ASSERT_EQUAL_64(0, x7);
7598 ASSERT_EQUAL_64(1, x8);
7599 ASSERT_EQUAL_64(1, x9);
7600 ASSERT_EQUAL_64(1, x10);
7601 ASSERT_EQUAL_64(0, x11);
7602 ASSERT_EQUAL_64(0xffffffff, x12);
7603 ASSERT_EQUAL_64(0, x13);
7604 ASSERT_EQUAL_64(0x7ffffffe, x14);
7605 ASSERT_EQUAL_64(1, x17);
7606 ASSERT_EQUAL_64(1, x18);
armvixlb0c8ae22014-03-21 14:03:59 +00007607 ASSERT_EQUAL_64(0, x19);
7608 ASSERT_EQUAL_64(0xffffffffffffffff, x20);
7609 ASSERT_EQUAL_64(0, x21);
7610 ASSERT_EQUAL_64(0x7fffff8000000000, x22);
7611 ASSERT_EQUAL_64(0, x23);
armvixlad96eda2013-06-14 11:42:37 +01007612 ASSERT_EQUAL_64(1, x24);
7613 ASSERT_EQUAL_64(1, x25);
armvixlb0c8ae22014-03-21 14:03:59 +00007614 ASSERT_EQUAL_64(0, x26);
7615 ASSERT_EQUAL_64(0xffffffffffffffff, x27);
7616 ASSERT_EQUAL_64(0, x28);
7617 ASSERT_EQUAL_64(0x7ffffffffffffc00, x29);
7618 ASSERT_EQUAL_64(0, x30);
armvixlad96eda2013-06-14 11:42:37 +01007619
7620 TEARDOWN();
7621}
7622
7623
7624TEST(fcvtns) {
7625 SETUP();
7626
7627 START();
7628 __ Fmov(s0, 1.0);
7629 __ Fmov(s1, 1.1);
7630 __ Fmov(s2, 1.5);
7631 __ Fmov(s3, -1.5);
7632 __ Fmov(s4, kFP32PositiveInfinity);
7633 __ Fmov(s5, kFP32NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00007634 __ Fmov(s6, 0x7fffff80); // Largest float < INT32_MAX.
7635 __ Fneg(s7, s6); // Smallest float > INT32_MIN.
armvixlad96eda2013-06-14 11:42:37 +01007636 __ Fmov(d8, 1.0);
7637 __ Fmov(d9, 1.1);
7638 __ Fmov(d10, 1.5);
7639 __ Fmov(d11, -1.5);
7640 __ Fmov(d12, kFP64PositiveInfinity);
7641 __ Fmov(d13, kFP64NegativeInfinity);
7642 __ Fmov(d14, kWMaxInt - 1);
7643 __ Fmov(d15, kWMinInt + 1);
7644 __ Fmov(s17, 1.1);
7645 __ Fmov(s18, 1.5);
7646 __ Fmov(s19, -1.5);
7647 __ Fmov(s20, kFP32PositiveInfinity);
7648 __ Fmov(s21, kFP32NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00007649 __ Fmov(s22, 0x7fffff8000000000); // Largest float < INT64_MAX.
7650 __ Fneg(s23, s22); // Smallest float > INT64_MIN.
armvixlad96eda2013-06-14 11:42:37 +01007651 __ Fmov(d24, 1.1);
7652 __ Fmov(d25, 1.5);
7653 __ Fmov(d26, -1.5);
7654 __ Fmov(d27, kFP64PositiveInfinity);
7655 __ Fmov(d28, kFP64NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00007656 __ Fmov(d29, 0x7ffffffffffffc00); // Largest double < INT64_MAX.
7657 __ Fneg(d30, d29); // Smallest double > INT64_MIN.
armvixlad96eda2013-06-14 11:42:37 +01007658
7659 __ Fcvtns(w0, s0);
7660 __ Fcvtns(w1, s1);
7661 __ Fcvtns(w2, s2);
7662 __ Fcvtns(w3, s3);
7663 __ Fcvtns(w4, s4);
7664 __ Fcvtns(w5, s5);
7665 __ Fcvtns(w6, s6);
7666 __ Fcvtns(w7, s7);
7667 __ Fcvtns(w8, d8);
7668 __ Fcvtns(w9, d9);
7669 __ Fcvtns(w10, d10);
7670 __ Fcvtns(w11, d11);
7671 __ Fcvtns(w12, d12);
7672 __ Fcvtns(w13, d13);
7673 __ Fcvtns(w14, d14);
7674 __ Fcvtns(w15, d15);
7675 __ Fcvtns(x17, s17);
7676 __ Fcvtns(x18, s18);
7677 __ Fcvtns(x19, s19);
7678 __ Fcvtns(x20, s20);
7679 __ Fcvtns(x21, s21);
7680 __ Fcvtns(x22, s22);
7681 __ Fcvtns(x23, s23);
7682 __ Fcvtns(x24, d24);
7683 __ Fcvtns(x25, d25);
7684 __ Fcvtns(x26, d26);
7685 __ Fcvtns(x27, d27);
7686 __ Fcvtns(x28, d28);
7687 __ Fcvtns(x29, d29);
7688 __ Fcvtns(x30, d30);
7689 END();
7690
7691 RUN();
7692
7693 ASSERT_EQUAL_64(1, x0);
7694 ASSERT_EQUAL_64(1, x1);
7695 ASSERT_EQUAL_64(2, x2);
7696 ASSERT_EQUAL_64(0xfffffffe, x3);
7697 ASSERT_EQUAL_64(0x7fffffff, x4);
7698 ASSERT_EQUAL_64(0x80000000, x5);
7699 ASSERT_EQUAL_64(0x7fffff80, x6);
7700 ASSERT_EQUAL_64(0x80000080, x7);
7701 ASSERT_EQUAL_64(1, x8);
7702 ASSERT_EQUAL_64(1, x9);
7703 ASSERT_EQUAL_64(2, x10);
7704 ASSERT_EQUAL_64(0xfffffffe, x11);
7705 ASSERT_EQUAL_64(0x7fffffff, x12);
7706 ASSERT_EQUAL_64(0x80000000, x13);
7707 ASSERT_EQUAL_64(0x7ffffffe, x14);
7708 ASSERT_EQUAL_64(0x80000001, x15);
7709 ASSERT_EQUAL_64(1, x17);
7710 ASSERT_EQUAL_64(2, x18);
armvixlb0c8ae22014-03-21 14:03:59 +00007711 ASSERT_EQUAL_64(0xfffffffffffffffe, x19);
7712 ASSERT_EQUAL_64(0x7fffffffffffffff, x20);
7713 ASSERT_EQUAL_64(0x8000000000000000, x21);
7714 ASSERT_EQUAL_64(0x7fffff8000000000, x22);
7715 ASSERT_EQUAL_64(0x8000008000000000, x23);
armvixlad96eda2013-06-14 11:42:37 +01007716 ASSERT_EQUAL_64(1, x24);
7717 ASSERT_EQUAL_64(2, x25);
armvixlb0c8ae22014-03-21 14:03:59 +00007718 ASSERT_EQUAL_64(0xfffffffffffffffe, x26);
7719 ASSERT_EQUAL_64(0x7fffffffffffffff, x27);
7720 ASSERT_EQUAL_64(0x8000000000000000, x28);
7721 ASSERT_EQUAL_64(0x7ffffffffffffc00, x29);
7722 ASSERT_EQUAL_64(0x8000000000000400, x30);
armvixlad96eda2013-06-14 11:42:37 +01007723
7724 TEARDOWN();
7725}
7726
7727
7728TEST(fcvtnu) {
7729 SETUP();
7730
7731 START();
7732 __ Fmov(s0, 1.0);
7733 __ Fmov(s1, 1.1);
7734 __ Fmov(s2, 1.5);
7735 __ Fmov(s3, -1.5);
7736 __ Fmov(s4, kFP32PositiveInfinity);
7737 __ Fmov(s5, kFP32NegativeInfinity);
7738 __ Fmov(s6, 0xffffff00); // Largest float < UINT32_MAX.
7739 __ Fmov(d8, 1.0);
7740 __ Fmov(d9, 1.1);
7741 __ Fmov(d10, 1.5);
7742 __ Fmov(d11, -1.5);
7743 __ Fmov(d12, kFP64PositiveInfinity);
7744 __ Fmov(d13, kFP64NegativeInfinity);
7745 __ Fmov(d14, 0xfffffffe);
7746 __ Fmov(s16, 1.0);
7747 __ Fmov(s17, 1.1);
7748 __ Fmov(s18, 1.5);
7749 __ Fmov(s19, -1.5);
7750 __ Fmov(s20, kFP32PositiveInfinity);
7751 __ Fmov(s21, kFP32NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00007752 __ Fmov(s22, 0xffffff0000000000); // Largest float < UINT64_MAX.
armvixlad96eda2013-06-14 11:42:37 +01007753 __ Fmov(d24, 1.1);
7754 __ Fmov(d25, 1.5);
7755 __ Fmov(d26, -1.5);
7756 __ Fmov(d27, kFP64PositiveInfinity);
7757 __ Fmov(d28, kFP64NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00007758 __ Fmov(d29, 0xfffffffffffff800); // Largest double < UINT64_MAX.
7759 __ Fmov(s30, 0x100000000);
armvixlad96eda2013-06-14 11:42:37 +01007760
7761 __ Fcvtnu(w0, s0);
7762 __ Fcvtnu(w1, s1);
7763 __ Fcvtnu(w2, s2);
7764 __ Fcvtnu(w3, s3);
7765 __ Fcvtnu(w4, s4);
7766 __ Fcvtnu(w5, s5);
7767 __ Fcvtnu(w6, s6);
7768 __ Fcvtnu(w8, d8);
7769 __ Fcvtnu(w9, d9);
7770 __ Fcvtnu(w10, d10);
7771 __ Fcvtnu(w11, d11);
7772 __ Fcvtnu(w12, d12);
7773 __ Fcvtnu(w13, d13);
7774 __ Fcvtnu(w14, d14);
7775 __ Fcvtnu(w15, d15);
7776 __ Fcvtnu(x16, s16);
7777 __ Fcvtnu(x17, s17);
7778 __ Fcvtnu(x18, s18);
7779 __ Fcvtnu(x19, s19);
7780 __ Fcvtnu(x20, s20);
7781 __ Fcvtnu(x21, s21);
7782 __ Fcvtnu(x22, s22);
7783 __ Fcvtnu(x24, d24);
7784 __ Fcvtnu(x25, d25);
7785 __ Fcvtnu(x26, d26);
7786 __ Fcvtnu(x27, d27);
7787 __ Fcvtnu(x28, d28);
7788 __ Fcvtnu(x29, d29);
7789 __ Fcvtnu(w30, s30);
7790 END();
7791
7792 RUN();
7793
7794 ASSERT_EQUAL_64(1, x0);
7795 ASSERT_EQUAL_64(1, x1);
7796 ASSERT_EQUAL_64(2, x2);
7797 ASSERT_EQUAL_64(0, x3);
7798 ASSERT_EQUAL_64(0xffffffff, x4);
7799 ASSERT_EQUAL_64(0, x5);
7800 ASSERT_EQUAL_64(0xffffff00, x6);
7801 ASSERT_EQUAL_64(1, x8);
7802 ASSERT_EQUAL_64(1, x9);
7803 ASSERT_EQUAL_64(2, x10);
7804 ASSERT_EQUAL_64(0, x11);
7805 ASSERT_EQUAL_64(0xffffffff, x12);
7806 ASSERT_EQUAL_64(0, x13);
7807 ASSERT_EQUAL_64(0xfffffffe, x14);
7808 ASSERT_EQUAL_64(1, x16);
7809 ASSERT_EQUAL_64(1, x17);
7810 ASSERT_EQUAL_64(2, x18);
7811 ASSERT_EQUAL_64(0, x19);
armvixlb0c8ae22014-03-21 14:03:59 +00007812 ASSERT_EQUAL_64(0xffffffffffffffff, x20);
armvixlad96eda2013-06-14 11:42:37 +01007813 ASSERT_EQUAL_64(0, x21);
armvixlb0c8ae22014-03-21 14:03:59 +00007814 ASSERT_EQUAL_64(0xffffff0000000000, x22);
armvixlad96eda2013-06-14 11:42:37 +01007815 ASSERT_EQUAL_64(1, x24);
7816 ASSERT_EQUAL_64(2, x25);
7817 ASSERT_EQUAL_64(0, x26);
armvixlb0c8ae22014-03-21 14:03:59 +00007818 ASSERT_EQUAL_64(0xffffffffffffffff, x27);
armvixlad96eda2013-06-14 11:42:37 +01007819 ASSERT_EQUAL_64(0, x28);
armvixlb0c8ae22014-03-21 14:03:59 +00007820 ASSERT_EQUAL_64(0xfffffffffffff800, x29);
armvixlad96eda2013-06-14 11:42:37 +01007821 ASSERT_EQUAL_64(0xffffffff, x30);
7822
7823 TEARDOWN();
7824}
7825
7826
7827TEST(fcvtzs) {
7828 SETUP();
7829
7830 START();
7831 __ Fmov(s0, 1.0);
7832 __ Fmov(s1, 1.1);
7833 __ Fmov(s2, 1.5);
7834 __ Fmov(s3, -1.5);
7835 __ Fmov(s4, kFP32PositiveInfinity);
7836 __ Fmov(s5, kFP32NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00007837 __ Fmov(s6, 0x7fffff80); // Largest float < INT32_MAX.
7838 __ Fneg(s7, s6); // Smallest float > INT32_MIN.
armvixlad96eda2013-06-14 11:42:37 +01007839 __ Fmov(d8, 1.0);
7840 __ Fmov(d9, 1.1);
7841 __ Fmov(d10, 1.5);
7842 __ Fmov(d11, -1.5);
7843 __ Fmov(d12, kFP64PositiveInfinity);
7844 __ Fmov(d13, kFP64NegativeInfinity);
7845 __ Fmov(d14, kWMaxInt - 1);
7846 __ Fmov(d15, kWMinInt + 1);
7847 __ Fmov(s17, 1.1);
7848 __ Fmov(s18, 1.5);
7849 __ Fmov(s19, -1.5);
7850 __ Fmov(s20, kFP32PositiveInfinity);
7851 __ Fmov(s21, kFP32NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00007852 __ Fmov(s22, 0x7fffff8000000000); // Largest float < INT64_MAX.
7853 __ Fneg(s23, s22); // Smallest float > INT64_MIN.
armvixlad96eda2013-06-14 11:42:37 +01007854 __ Fmov(d24, 1.1);
7855 __ Fmov(d25, 1.5);
7856 __ Fmov(d26, -1.5);
7857 __ Fmov(d27, kFP64PositiveInfinity);
7858 __ Fmov(d28, kFP64NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00007859 __ Fmov(d29, 0x7ffffffffffffc00); // Largest double < INT64_MAX.
7860 __ Fneg(d30, d29); // Smallest double > INT64_MIN.
armvixlad96eda2013-06-14 11:42:37 +01007861
7862 __ Fcvtzs(w0, s0);
7863 __ Fcvtzs(w1, s1);
7864 __ Fcvtzs(w2, s2);
7865 __ Fcvtzs(w3, s3);
7866 __ Fcvtzs(w4, s4);
7867 __ Fcvtzs(w5, s5);
7868 __ Fcvtzs(w6, s6);
7869 __ Fcvtzs(w7, s7);
7870 __ Fcvtzs(w8, d8);
7871 __ Fcvtzs(w9, d9);
7872 __ Fcvtzs(w10, d10);
7873 __ Fcvtzs(w11, d11);
7874 __ Fcvtzs(w12, d12);
7875 __ Fcvtzs(w13, d13);
7876 __ Fcvtzs(w14, d14);
7877 __ Fcvtzs(w15, d15);
7878 __ Fcvtzs(x17, s17);
7879 __ Fcvtzs(x18, s18);
7880 __ Fcvtzs(x19, s19);
7881 __ Fcvtzs(x20, s20);
7882 __ Fcvtzs(x21, s21);
7883 __ Fcvtzs(x22, s22);
7884 __ Fcvtzs(x23, s23);
7885 __ Fcvtzs(x24, d24);
7886 __ Fcvtzs(x25, d25);
7887 __ Fcvtzs(x26, d26);
7888 __ Fcvtzs(x27, d27);
7889 __ Fcvtzs(x28, d28);
7890 __ Fcvtzs(x29, d29);
7891 __ Fcvtzs(x30, d30);
7892 END();
7893
7894 RUN();
7895
7896 ASSERT_EQUAL_64(1, x0);
7897 ASSERT_EQUAL_64(1, x1);
7898 ASSERT_EQUAL_64(1, x2);
7899 ASSERT_EQUAL_64(0xffffffff, x3);
7900 ASSERT_EQUAL_64(0x7fffffff, x4);
7901 ASSERT_EQUAL_64(0x80000000, x5);
7902 ASSERT_EQUAL_64(0x7fffff80, x6);
7903 ASSERT_EQUAL_64(0x80000080, x7);
7904 ASSERT_EQUAL_64(1, x8);
7905 ASSERT_EQUAL_64(1, x9);
7906 ASSERT_EQUAL_64(1, x10);
7907 ASSERT_EQUAL_64(0xffffffff, x11);
7908 ASSERT_EQUAL_64(0x7fffffff, x12);
7909 ASSERT_EQUAL_64(0x80000000, x13);
7910 ASSERT_EQUAL_64(0x7ffffffe, x14);
7911 ASSERT_EQUAL_64(0x80000001, x15);
7912 ASSERT_EQUAL_64(1, x17);
7913 ASSERT_EQUAL_64(1, x18);
armvixlb0c8ae22014-03-21 14:03:59 +00007914 ASSERT_EQUAL_64(0xffffffffffffffff, x19);
7915 ASSERT_EQUAL_64(0x7fffffffffffffff, x20);
7916 ASSERT_EQUAL_64(0x8000000000000000, x21);
7917 ASSERT_EQUAL_64(0x7fffff8000000000, x22);
7918 ASSERT_EQUAL_64(0x8000008000000000, x23);
armvixlad96eda2013-06-14 11:42:37 +01007919 ASSERT_EQUAL_64(1, x24);
7920 ASSERT_EQUAL_64(1, x25);
armvixlb0c8ae22014-03-21 14:03:59 +00007921 ASSERT_EQUAL_64(0xffffffffffffffff, x26);
7922 ASSERT_EQUAL_64(0x7fffffffffffffff, x27);
7923 ASSERT_EQUAL_64(0x8000000000000000, x28);
7924 ASSERT_EQUAL_64(0x7ffffffffffffc00, x29);
7925 ASSERT_EQUAL_64(0x8000000000000400, x30);
armvixlad96eda2013-06-14 11:42:37 +01007926
7927 TEARDOWN();
7928}
7929
7930TEST(fcvtzu) {
7931 SETUP();
7932
7933 START();
7934 __ Fmov(s0, 1.0);
7935 __ Fmov(s1, 1.1);
7936 __ Fmov(s2, 1.5);
7937 __ Fmov(s3, -1.5);
7938 __ Fmov(s4, kFP32PositiveInfinity);
7939 __ Fmov(s5, kFP32NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00007940 __ Fmov(s6, 0x7fffff80); // Largest float < INT32_MAX.
7941 __ Fneg(s7, s6); // Smallest float > INT32_MIN.
armvixlad96eda2013-06-14 11:42:37 +01007942 __ Fmov(d8, 1.0);
7943 __ Fmov(d9, 1.1);
7944 __ Fmov(d10, 1.5);
7945 __ Fmov(d11, -1.5);
7946 __ Fmov(d12, kFP64PositiveInfinity);
7947 __ Fmov(d13, kFP64NegativeInfinity);
7948 __ Fmov(d14, kWMaxInt - 1);
7949 __ Fmov(d15, kWMinInt + 1);
7950 __ Fmov(s17, 1.1);
7951 __ Fmov(s18, 1.5);
7952 __ Fmov(s19, -1.5);
7953 __ Fmov(s20, kFP32PositiveInfinity);
7954 __ Fmov(s21, kFP32NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00007955 __ Fmov(s22, 0x7fffff8000000000); // Largest float < INT64_MAX.
7956 __ Fneg(s23, s22); // Smallest float > INT64_MIN.
armvixlad96eda2013-06-14 11:42:37 +01007957 __ Fmov(d24, 1.1);
7958 __ Fmov(d25, 1.5);
7959 __ Fmov(d26, -1.5);
7960 __ Fmov(d27, kFP64PositiveInfinity);
7961 __ Fmov(d28, kFP64NegativeInfinity);
armvixlb0c8ae22014-03-21 14:03:59 +00007962 __ Fmov(d29, 0x7ffffffffffffc00); // Largest double < INT64_MAX.
7963 __ Fneg(d30, d29); // Smallest double > INT64_MIN.
armvixlad96eda2013-06-14 11:42:37 +01007964
7965 __ Fcvtzu(w0, s0);
7966 __ Fcvtzu(w1, s1);
7967 __ Fcvtzu(w2, s2);
7968 __ Fcvtzu(w3, s3);
7969 __ Fcvtzu(w4, s4);
7970 __ Fcvtzu(w5, s5);
7971 __ Fcvtzu(w6, s6);
7972 __ Fcvtzu(w7, s7);
7973 __ Fcvtzu(w8, d8);
7974 __ Fcvtzu(w9, d9);
7975 __ Fcvtzu(w10, d10);
7976 __ Fcvtzu(w11, d11);
7977 __ Fcvtzu(w12, d12);
7978 __ Fcvtzu(w13, d13);
7979 __ Fcvtzu(w14, d14);
7980 __ Fcvtzu(x17, s17);
7981 __ Fcvtzu(x18, s18);
7982 __ Fcvtzu(x19, s19);
7983 __ Fcvtzu(x20, s20);
7984 __ Fcvtzu(x21, s21);
7985 __ Fcvtzu(x22, s22);
7986 __ Fcvtzu(x23, s23);
7987 __ Fcvtzu(x24, d24);
7988 __ Fcvtzu(x25, d25);
7989 __ Fcvtzu(x26, d26);
7990 __ Fcvtzu(x27, d27);
7991 __ Fcvtzu(x28, d28);
7992 __ Fcvtzu(x29, d29);
7993 __ Fcvtzu(x30, d30);
7994 END();
7995
7996 RUN();
7997
7998 ASSERT_EQUAL_64(1, x0);
7999 ASSERT_EQUAL_64(1, x1);
8000 ASSERT_EQUAL_64(1, x2);
8001 ASSERT_EQUAL_64(0, x3);
8002 ASSERT_EQUAL_64(0xffffffff, x4);
8003 ASSERT_EQUAL_64(0, x5);
8004 ASSERT_EQUAL_64(0x7fffff80, x6);
8005 ASSERT_EQUAL_64(0, x7);
8006 ASSERT_EQUAL_64(1, x8);
8007 ASSERT_EQUAL_64(1, x9);
8008 ASSERT_EQUAL_64(1, x10);
8009 ASSERT_EQUAL_64(0, x11);
8010 ASSERT_EQUAL_64(0xffffffff, x12);
8011 ASSERT_EQUAL_64(0, x13);
8012 ASSERT_EQUAL_64(0x7ffffffe, x14);
8013 ASSERT_EQUAL_64(1, x17);
8014 ASSERT_EQUAL_64(1, x18);
armvixlb0c8ae22014-03-21 14:03:59 +00008015 ASSERT_EQUAL_64(0, x19);
8016 ASSERT_EQUAL_64(0xffffffffffffffff, x20);
8017 ASSERT_EQUAL_64(0, x21);
8018 ASSERT_EQUAL_64(0x7fffff8000000000, x22);
8019 ASSERT_EQUAL_64(0, x23);
armvixlad96eda2013-06-14 11:42:37 +01008020 ASSERT_EQUAL_64(1, x24);
8021 ASSERT_EQUAL_64(1, x25);
armvixlb0c8ae22014-03-21 14:03:59 +00008022 ASSERT_EQUAL_64(0, x26);
8023 ASSERT_EQUAL_64(0xffffffffffffffff, x27);
8024 ASSERT_EQUAL_64(0, x28);
8025 ASSERT_EQUAL_64(0x7ffffffffffffc00, x29);
8026 ASSERT_EQUAL_64(0, x30);
armvixlad96eda2013-06-14 11:42:37 +01008027
8028 TEARDOWN();
8029}
8030
8031
armvixl578645f2013-08-15 17:21:42 +01008032// Test that scvtf and ucvtf can convert the 64-bit input into the expected
8033// value. All possible values of 'fbits' are tested. The expected value is
8034// modified accordingly in each case.
8035//
8036// The expected value is specified as the bit encoding of the expected double
8037// produced by scvtf (expected_scvtf_bits) as well as ucvtf
8038// (expected_ucvtf_bits).
8039//
8040// Where the input value is representable by int32_t or uint32_t, conversions
8041// from W registers will also be tested.
8042static void TestUScvtfHelper(uint64_t in,
8043 uint64_t expected_scvtf_bits,
8044 uint64_t expected_ucvtf_bits) {
8045 uint64_t u64 = in;
8046 uint32_t u32 = u64 & 0xffffffff;
8047 int64_t s64 = static_cast<int64_t>(in);
8048 int32_t s32 = s64 & 0x7fffffff;
8049
8050 bool cvtf_s32 = (s64 == s32);
8051 bool cvtf_u32 = (u64 == u32);
8052
8053 double results_scvtf_x[65];
8054 double results_ucvtf_x[65];
8055 double results_scvtf_w[33];
8056 double results_ucvtf_w[33];
8057
armvixlad96eda2013-06-14 11:42:37 +01008058 SETUP();
armvixlad96eda2013-06-14 11:42:37 +01008059 START();
armvixlad96eda2013-06-14 11:42:37 +01008060
armvixlb0c8ae22014-03-21 14:03:59 +00008061 __ Mov(x0, reinterpret_cast<uintptr_t>(results_scvtf_x));
8062 __ Mov(x1, reinterpret_cast<uintptr_t>(results_ucvtf_x));
8063 __ Mov(x2, reinterpret_cast<uintptr_t>(results_scvtf_w));
8064 __ Mov(x3, reinterpret_cast<uintptr_t>(results_ucvtf_w));
armvixl578645f2013-08-15 17:21:42 +01008065
8066 __ Mov(x10, s64);
8067
8068 // Corrupt the top word, in case it is accidentally used during W-register
8069 // conversions.
8070 __ Mov(x11, 0x5555555555555555);
8071 __ Bfi(x11, x10, 0, kWRegSize);
8072
8073 // Test integer conversions.
8074 __ Scvtf(d0, x10);
8075 __ Ucvtf(d1, x10);
8076 __ Scvtf(d2, w11);
8077 __ Ucvtf(d3, w11);
8078 __ Str(d0, MemOperand(x0));
8079 __ Str(d1, MemOperand(x1));
8080 __ Str(d2, MemOperand(x2));
8081 __ Str(d3, MemOperand(x3));
8082
8083 // Test all possible values of fbits.
8084 for (int fbits = 1; fbits <= 32; fbits++) {
8085 __ Scvtf(d0, x10, fbits);
8086 __ Ucvtf(d1, x10, fbits);
8087 __ Scvtf(d2, w11, fbits);
8088 __ Ucvtf(d3, w11, fbits);
8089 __ Str(d0, MemOperand(x0, fbits * kDRegSizeInBytes));
8090 __ Str(d1, MemOperand(x1, fbits * kDRegSizeInBytes));
8091 __ Str(d2, MemOperand(x2, fbits * kDRegSizeInBytes));
8092 __ Str(d3, MemOperand(x3, fbits * kDRegSizeInBytes));
8093 }
8094
8095 // Conversions from W registers can only handle fbits values <= 32, so just
8096 // test conversions from X registers for 32 < fbits <= 64.
8097 for (int fbits = 33; fbits <= 64; fbits++) {
8098 __ Scvtf(d0, x10, fbits);
8099 __ Ucvtf(d1, x10, fbits);
8100 __ Str(d0, MemOperand(x0, fbits * kDRegSizeInBytes));
8101 __ Str(d1, MemOperand(x1, fbits * kDRegSizeInBytes));
8102 }
8103
8104 END();
armvixlad96eda2013-06-14 11:42:37 +01008105 RUN();
8106
armvixl578645f2013-08-15 17:21:42 +01008107 // Check the results.
8108 double expected_scvtf_base = rawbits_to_double(expected_scvtf_bits);
8109 double expected_ucvtf_base = rawbits_to_double(expected_ucvtf_bits);
8110
8111 for (int fbits = 0; fbits <= 32; fbits++) {
8112 double expected_scvtf = expected_scvtf_base / pow(2, fbits);
8113 double expected_ucvtf = expected_ucvtf_base / pow(2, fbits);
8114 ASSERT_EQUAL_FP64(expected_scvtf, results_scvtf_x[fbits]);
8115 ASSERT_EQUAL_FP64(expected_ucvtf, results_ucvtf_x[fbits]);
8116 if (cvtf_s32) ASSERT_EQUAL_FP64(expected_scvtf, results_scvtf_w[fbits]);
8117 if (cvtf_u32) ASSERT_EQUAL_FP64(expected_ucvtf, results_ucvtf_w[fbits]);
8118 }
8119 for (int fbits = 33; fbits <= 64; fbits++) {
8120 double expected_scvtf = expected_scvtf_base / pow(2, fbits);
8121 double expected_ucvtf = expected_ucvtf_base / pow(2, fbits);
8122 ASSERT_EQUAL_FP64(expected_scvtf, results_scvtf_x[fbits]);
8123 ASSERT_EQUAL_FP64(expected_ucvtf, results_ucvtf_x[fbits]);
8124 }
armvixlad96eda2013-06-14 11:42:37 +01008125
8126 TEARDOWN();
8127}
8128
8129
armvixl578645f2013-08-15 17:21:42 +01008130TEST(scvtf_ucvtf_double) {
8131 // Simple conversions of positive numbers which require no rounding; the
8132 // results should not depened on the rounding mode, and ucvtf and scvtf should
8133 // produce the same result.
8134 TestUScvtfHelper(0x0000000000000000, 0x0000000000000000, 0x0000000000000000);
8135 TestUScvtfHelper(0x0000000000000001, 0x3ff0000000000000, 0x3ff0000000000000);
8136 TestUScvtfHelper(0x0000000040000000, 0x41d0000000000000, 0x41d0000000000000);
8137 TestUScvtfHelper(0x0000000100000000, 0x41f0000000000000, 0x41f0000000000000);
8138 TestUScvtfHelper(0x4000000000000000, 0x43d0000000000000, 0x43d0000000000000);
8139 // Test mantissa extremities.
8140 TestUScvtfHelper(0x4000000000000400, 0x43d0000000000001, 0x43d0000000000001);
8141 // The largest int32_t that fits in a double.
8142 TestUScvtfHelper(0x000000007fffffff, 0x41dfffffffc00000, 0x41dfffffffc00000);
8143 // Values that would be negative if treated as an int32_t.
8144 TestUScvtfHelper(0x00000000ffffffff, 0x41efffffffe00000, 0x41efffffffe00000);
8145 TestUScvtfHelper(0x0000000080000000, 0x41e0000000000000, 0x41e0000000000000);
8146 TestUScvtfHelper(0x0000000080000001, 0x41e0000000200000, 0x41e0000000200000);
8147 // The largest int64_t that fits in a double.
8148 TestUScvtfHelper(0x7ffffffffffffc00, 0x43dfffffffffffff, 0x43dfffffffffffff);
8149 // Check for bit pattern reproduction.
8150 TestUScvtfHelper(0x0123456789abcde0, 0x43723456789abcde, 0x43723456789abcde);
8151 TestUScvtfHelper(0x0000000012345678, 0x41b2345678000000, 0x41b2345678000000);
8152
8153 // Simple conversions of negative int64_t values. These require no rounding,
8154 // and the results should not depend on the rounding mode.
8155 TestUScvtfHelper(0xffffffffc0000000, 0xc1d0000000000000, 0x43effffffff80000);
8156 TestUScvtfHelper(0xffffffff00000000, 0xc1f0000000000000, 0x43efffffffe00000);
8157 TestUScvtfHelper(0xc000000000000000, 0xc3d0000000000000, 0x43e8000000000000);
8158
8159 // Conversions which require rounding.
8160 TestUScvtfHelper(0x1000000000000000, 0x43b0000000000000, 0x43b0000000000000);
8161 TestUScvtfHelper(0x1000000000000001, 0x43b0000000000000, 0x43b0000000000000);
8162 TestUScvtfHelper(0x1000000000000080, 0x43b0000000000000, 0x43b0000000000000);
8163 TestUScvtfHelper(0x1000000000000081, 0x43b0000000000001, 0x43b0000000000001);
8164 TestUScvtfHelper(0x1000000000000100, 0x43b0000000000001, 0x43b0000000000001);
8165 TestUScvtfHelper(0x1000000000000101, 0x43b0000000000001, 0x43b0000000000001);
8166 TestUScvtfHelper(0x1000000000000180, 0x43b0000000000002, 0x43b0000000000002);
8167 TestUScvtfHelper(0x1000000000000181, 0x43b0000000000002, 0x43b0000000000002);
8168 TestUScvtfHelper(0x1000000000000200, 0x43b0000000000002, 0x43b0000000000002);
8169 TestUScvtfHelper(0x1000000000000201, 0x43b0000000000002, 0x43b0000000000002);
8170 TestUScvtfHelper(0x1000000000000280, 0x43b0000000000002, 0x43b0000000000002);
8171 TestUScvtfHelper(0x1000000000000281, 0x43b0000000000003, 0x43b0000000000003);
8172 TestUScvtfHelper(0x1000000000000300, 0x43b0000000000003, 0x43b0000000000003);
8173 // Check rounding of negative int64_t values (and large uint64_t values).
8174 TestUScvtfHelper(0x8000000000000000, 0xc3e0000000000000, 0x43e0000000000000);
8175 TestUScvtfHelper(0x8000000000000001, 0xc3e0000000000000, 0x43e0000000000000);
8176 TestUScvtfHelper(0x8000000000000200, 0xc3e0000000000000, 0x43e0000000000000);
8177 TestUScvtfHelper(0x8000000000000201, 0xc3dfffffffffffff, 0x43e0000000000000);
8178 TestUScvtfHelper(0x8000000000000400, 0xc3dfffffffffffff, 0x43e0000000000000);
8179 TestUScvtfHelper(0x8000000000000401, 0xc3dfffffffffffff, 0x43e0000000000001);
8180 TestUScvtfHelper(0x8000000000000600, 0xc3dffffffffffffe, 0x43e0000000000001);
8181 TestUScvtfHelper(0x8000000000000601, 0xc3dffffffffffffe, 0x43e0000000000001);
8182 TestUScvtfHelper(0x8000000000000800, 0xc3dffffffffffffe, 0x43e0000000000001);
8183 TestUScvtfHelper(0x8000000000000801, 0xc3dffffffffffffe, 0x43e0000000000001);
8184 TestUScvtfHelper(0x8000000000000a00, 0xc3dffffffffffffe, 0x43e0000000000001);
8185 TestUScvtfHelper(0x8000000000000a01, 0xc3dffffffffffffd, 0x43e0000000000001);
8186 TestUScvtfHelper(0x8000000000000c00, 0xc3dffffffffffffd, 0x43e0000000000002);
8187 // Round up to produce a result that's too big for the input to represent.
8188 TestUScvtfHelper(0x7ffffffffffffe00, 0x43e0000000000000, 0x43e0000000000000);
8189 TestUScvtfHelper(0x7fffffffffffffff, 0x43e0000000000000, 0x43e0000000000000);
8190 TestUScvtfHelper(0xfffffffffffffc00, 0xc090000000000000, 0x43f0000000000000);
8191 TestUScvtfHelper(0xffffffffffffffff, 0xbff0000000000000, 0x43f0000000000000);
8192}
8193
8194
8195// The same as TestUScvtfHelper, but convert to floats.
8196static void TestUScvtf32Helper(uint64_t in,
8197 uint32_t expected_scvtf_bits,
8198 uint32_t expected_ucvtf_bits) {
8199 uint64_t u64 = in;
8200 uint32_t u32 = u64 & 0xffffffff;
8201 int64_t s64 = static_cast<int64_t>(in);
8202 int32_t s32 = s64 & 0x7fffffff;
8203
8204 bool cvtf_s32 = (s64 == s32);
8205 bool cvtf_u32 = (u64 == u32);
8206
8207 float results_scvtf_x[65];
8208 float results_ucvtf_x[65];
8209 float results_scvtf_w[33];
8210 float results_ucvtf_w[33];
8211
armvixlad96eda2013-06-14 11:42:37 +01008212 SETUP();
armvixlad96eda2013-06-14 11:42:37 +01008213 START();
armvixlad96eda2013-06-14 11:42:37 +01008214
armvixlb0c8ae22014-03-21 14:03:59 +00008215 __ Mov(x0, reinterpret_cast<uintptr_t>(results_scvtf_x));
8216 __ Mov(x1, reinterpret_cast<uintptr_t>(results_ucvtf_x));
8217 __ Mov(x2, reinterpret_cast<uintptr_t>(results_scvtf_w));
8218 __ Mov(x3, reinterpret_cast<uintptr_t>(results_ucvtf_w));
armvixl578645f2013-08-15 17:21:42 +01008219
8220 __ Mov(x10, s64);
8221
8222 // Corrupt the top word, in case it is accidentally used during W-register
8223 // conversions.
8224 __ Mov(x11, 0x5555555555555555);
8225 __ Bfi(x11, x10, 0, kWRegSize);
8226
8227 // Test integer conversions.
8228 __ Scvtf(s0, x10);
8229 __ Ucvtf(s1, x10);
8230 __ Scvtf(s2, w11);
8231 __ Ucvtf(s3, w11);
8232 __ Str(s0, MemOperand(x0));
8233 __ Str(s1, MemOperand(x1));
8234 __ Str(s2, MemOperand(x2));
8235 __ Str(s3, MemOperand(x3));
8236
8237 // Test all possible values of fbits.
8238 for (int fbits = 1; fbits <= 32; fbits++) {
8239 __ Scvtf(s0, x10, fbits);
8240 __ Ucvtf(s1, x10, fbits);
8241 __ Scvtf(s2, w11, fbits);
8242 __ Ucvtf(s3, w11, fbits);
8243 __ Str(s0, MemOperand(x0, fbits * kSRegSizeInBytes));
8244 __ Str(s1, MemOperand(x1, fbits * kSRegSizeInBytes));
8245 __ Str(s2, MemOperand(x2, fbits * kSRegSizeInBytes));
8246 __ Str(s3, MemOperand(x3, fbits * kSRegSizeInBytes));
8247 }
8248
8249 // Conversions from W registers can only handle fbits values <= 32, so just
8250 // test conversions from X registers for 32 < fbits <= 64.
8251 for (int fbits = 33; fbits <= 64; fbits++) {
8252 __ Scvtf(s0, x10, fbits);
8253 __ Ucvtf(s1, x10, fbits);
8254 __ Str(s0, MemOperand(x0, fbits * kSRegSizeInBytes));
8255 __ Str(s1, MemOperand(x1, fbits * kSRegSizeInBytes));
8256 }
armvixlad96eda2013-06-14 11:42:37 +01008257
8258 END();
armvixlad96eda2013-06-14 11:42:37 +01008259 RUN();
8260
armvixl578645f2013-08-15 17:21:42 +01008261 // Check the results.
8262 float expected_scvtf_base = rawbits_to_float(expected_scvtf_bits);
8263 float expected_ucvtf_base = rawbits_to_float(expected_ucvtf_bits);
armvixlad96eda2013-06-14 11:42:37 +01008264
armvixl578645f2013-08-15 17:21:42 +01008265 for (int fbits = 0; fbits <= 32; fbits++) {
armvixlf37fdc02014-02-05 13:22:16 +00008266 float expected_scvtf = expected_scvtf_base / powf(2, fbits);
8267 float expected_ucvtf = expected_ucvtf_base / powf(2, fbits);
armvixl578645f2013-08-15 17:21:42 +01008268 ASSERT_EQUAL_FP32(expected_scvtf, results_scvtf_x[fbits]);
8269 ASSERT_EQUAL_FP32(expected_ucvtf, results_ucvtf_x[fbits]);
8270 if (cvtf_s32) ASSERT_EQUAL_FP32(expected_scvtf, results_scvtf_w[fbits]);
8271 if (cvtf_u32) ASSERT_EQUAL_FP32(expected_ucvtf, results_ucvtf_w[fbits]);
8272 break;
8273 }
8274 for (int fbits = 33; fbits <= 64; fbits++) {
8275 break;
armvixlf37fdc02014-02-05 13:22:16 +00008276 float expected_scvtf = expected_scvtf_base / powf(2, fbits);
8277 float expected_ucvtf = expected_ucvtf_base / powf(2, fbits);
armvixl578645f2013-08-15 17:21:42 +01008278 ASSERT_EQUAL_FP32(expected_scvtf, results_scvtf_x[fbits]);
8279 ASSERT_EQUAL_FP32(expected_ucvtf, results_ucvtf_x[fbits]);
8280 }
armvixlad96eda2013-06-14 11:42:37 +01008281
8282 TEARDOWN();
8283}
8284
8285
armvixl578645f2013-08-15 17:21:42 +01008286TEST(scvtf_ucvtf_float) {
8287 // Simple conversions of positive numbers which require no rounding; the
8288 // results should not depened on the rounding mode, and ucvtf and scvtf should
8289 // produce the same result.
8290 TestUScvtf32Helper(0x0000000000000000, 0x00000000, 0x00000000);
8291 TestUScvtf32Helper(0x0000000000000001, 0x3f800000, 0x3f800000);
8292 TestUScvtf32Helper(0x0000000040000000, 0x4e800000, 0x4e800000);
8293 TestUScvtf32Helper(0x0000000100000000, 0x4f800000, 0x4f800000);
8294 TestUScvtf32Helper(0x4000000000000000, 0x5e800000, 0x5e800000);
8295 // Test mantissa extremities.
8296 TestUScvtf32Helper(0x0000000000800001, 0x4b000001, 0x4b000001);
8297 TestUScvtf32Helper(0x4000008000000000, 0x5e800001, 0x5e800001);
8298 // The largest int32_t that fits in a float.
8299 TestUScvtf32Helper(0x000000007fffff80, 0x4effffff, 0x4effffff);
8300 // Values that would be negative if treated as an int32_t.
8301 TestUScvtf32Helper(0x00000000ffffff00, 0x4f7fffff, 0x4f7fffff);
8302 TestUScvtf32Helper(0x0000000080000000, 0x4f000000, 0x4f000000);
8303 TestUScvtf32Helper(0x0000000080000100, 0x4f000001, 0x4f000001);
8304 // The largest int64_t that fits in a float.
8305 TestUScvtf32Helper(0x7fffff8000000000, 0x5effffff, 0x5effffff);
8306 // Check for bit pattern reproduction.
8307 TestUScvtf32Helper(0x0000000000876543, 0x4b076543, 0x4b076543);
8308
8309 // Simple conversions of negative int64_t values. These require no rounding,
8310 // and the results should not depend on the rounding mode.
8311 TestUScvtf32Helper(0xfffffc0000000000, 0xd4800000, 0x5f7ffffc);
8312 TestUScvtf32Helper(0xc000000000000000, 0xde800000, 0x5f400000);
8313
8314 // Conversions which require rounding.
8315 TestUScvtf32Helper(0x0000800000000000, 0x57000000, 0x57000000);
8316 TestUScvtf32Helper(0x0000800000000001, 0x57000000, 0x57000000);
8317 TestUScvtf32Helper(0x0000800000800000, 0x57000000, 0x57000000);
8318 TestUScvtf32Helper(0x0000800000800001, 0x57000001, 0x57000001);
8319 TestUScvtf32Helper(0x0000800001000000, 0x57000001, 0x57000001);
8320 TestUScvtf32Helper(0x0000800001000001, 0x57000001, 0x57000001);
8321 TestUScvtf32Helper(0x0000800001800000, 0x57000002, 0x57000002);
8322 TestUScvtf32Helper(0x0000800001800001, 0x57000002, 0x57000002);
8323 TestUScvtf32Helper(0x0000800002000000, 0x57000002, 0x57000002);
8324 TestUScvtf32Helper(0x0000800002000001, 0x57000002, 0x57000002);
8325 TestUScvtf32Helper(0x0000800002800000, 0x57000002, 0x57000002);
8326 TestUScvtf32Helper(0x0000800002800001, 0x57000003, 0x57000003);
8327 TestUScvtf32Helper(0x0000800003000000, 0x57000003, 0x57000003);
8328 // Check rounding of negative int64_t values (and large uint64_t values).
8329 TestUScvtf32Helper(0x8000000000000000, 0xdf000000, 0x5f000000);
8330 TestUScvtf32Helper(0x8000000000000001, 0xdf000000, 0x5f000000);
8331 TestUScvtf32Helper(0x8000004000000000, 0xdf000000, 0x5f000000);
8332 TestUScvtf32Helper(0x8000004000000001, 0xdeffffff, 0x5f000000);
8333 TestUScvtf32Helper(0x8000008000000000, 0xdeffffff, 0x5f000000);
8334 TestUScvtf32Helper(0x8000008000000001, 0xdeffffff, 0x5f000001);
8335 TestUScvtf32Helper(0x800000c000000000, 0xdefffffe, 0x5f000001);
8336 TestUScvtf32Helper(0x800000c000000001, 0xdefffffe, 0x5f000001);
8337 TestUScvtf32Helper(0x8000010000000000, 0xdefffffe, 0x5f000001);
8338 TestUScvtf32Helper(0x8000010000000001, 0xdefffffe, 0x5f000001);
8339 TestUScvtf32Helper(0x8000014000000000, 0xdefffffe, 0x5f000001);
8340 TestUScvtf32Helper(0x8000014000000001, 0xdefffffd, 0x5f000001);
8341 TestUScvtf32Helper(0x8000018000000000, 0xdefffffd, 0x5f000002);
8342 // Round up to produce a result that's too big for the input to represent.
8343 TestUScvtf32Helper(0x000000007fffffc0, 0x4f000000, 0x4f000000);
8344 TestUScvtf32Helper(0x000000007fffffff, 0x4f000000, 0x4f000000);
8345 TestUScvtf32Helper(0x00000000ffffff80, 0x4f800000, 0x4f800000);
8346 TestUScvtf32Helper(0x00000000ffffffff, 0x4f800000, 0x4f800000);
8347 TestUScvtf32Helper(0x7fffffc000000000, 0x5f000000, 0x5f000000);
8348 TestUScvtf32Helper(0x7fffffffffffffff, 0x5f000000, 0x5f000000);
8349 TestUScvtf32Helper(0xffffff8000000000, 0xd3000000, 0x5f800000);
8350 TestUScvtf32Helper(0xffffffffffffffff, 0xbf800000, 0x5f800000);
8351}
8352
8353
armvixlad96eda2013-06-14 11:42:37 +01008354TEST(system_mrs) {
8355 SETUP();
8356
8357 START();
8358 __ Mov(w0, 0);
8359 __ Mov(w1, 1);
8360 __ Mov(w2, 0x80000000);
8361
8362 // Set the Z and C flags.
8363 __ Cmp(w0, w0);
8364 __ Mrs(x3, NZCV);
8365
8366 // Set the N flag.
8367 __ Cmp(w0, w1);
8368 __ Mrs(x4, NZCV);
8369
8370 // Set the Z, C and V flags.
armvixlf37fdc02014-02-05 13:22:16 +00008371 __ Adds(w0, w2, w2);
armvixlad96eda2013-06-14 11:42:37 +01008372 __ Mrs(x5, NZCV);
armvixl578645f2013-08-15 17:21:42 +01008373
8374 // Read the default FPCR.
8375 __ Mrs(x6, FPCR);
armvixlad96eda2013-06-14 11:42:37 +01008376 END();
8377
8378 RUN();
8379
armvixl578645f2013-08-15 17:21:42 +01008380 // NZCV
armvixlad96eda2013-06-14 11:42:37 +01008381 ASSERT_EQUAL_32(ZCFlag, w3);
8382 ASSERT_EQUAL_32(NFlag, w4);
8383 ASSERT_EQUAL_32(ZCVFlag, w5);
8384
armvixl578645f2013-08-15 17:21:42 +01008385 // FPCR
8386 // The default FPCR on Linux-based platforms is 0.
8387 ASSERT_EQUAL_32(0, w6);
8388
armvixlad96eda2013-06-14 11:42:37 +01008389 TEARDOWN();
8390}
8391
8392
8393TEST(system_msr) {
armvixl578645f2013-08-15 17:21:42 +01008394 // All FPCR fields that must be implemented: AHP, DN, FZ, RMode
8395 const uint64_t fpcr_core = 0x07c00000;
8396
8397 // All FPCR fields (including fields which may be read-as-zero):
8398 // Stride, Len
8399 // IDE, IXE, UFE, OFE, DZE, IOE
8400 const uint64_t fpcr_all = fpcr_core | 0x00379f00;
8401
armvixlad96eda2013-06-14 11:42:37 +01008402 SETUP();
8403
8404 START();
8405 __ Mov(w0, 0);
8406 __ Mov(w1, 0x7fffffff);
8407
8408 __ Mov(x7, 0);
8409
8410 __ Mov(x10, NVFlag);
8411 __ Cmp(w0, w0); // Set Z and C.
8412 __ Msr(NZCV, x10); // Set N and V.
8413 // The Msr should have overwritten every flag set by the Cmp.
8414 __ Cinc(x7, x7, mi); // N
8415 __ Cinc(x7, x7, ne); // !Z
8416 __ Cinc(x7, x7, lo); // !C
8417 __ Cinc(x7, x7, vs); // V
8418
8419 __ Mov(x10, ZCFlag);
8420 __ Cmn(w1, w1); // Set N and V.
8421 __ Msr(NZCV, x10); // Set Z and C.
8422 // The Msr should have overwritten every flag set by the Cmn.
8423 __ Cinc(x7, x7, pl); // !N
8424 __ Cinc(x7, x7, eq); // Z
8425 __ Cinc(x7, x7, hs); // C
8426 __ Cinc(x7, x7, vc); // !V
8427
armvixl578645f2013-08-15 17:21:42 +01008428 // All core FPCR fields must be writable.
8429 __ Mov(x8, fpcr_core);
8430 __ Msr(FPCR, x8);
8431 __ Mrs(x8, FPCR);
8432
8433 // All FPCR fields, including optional ones. This part of the test doesn't
8434 // achieve much other than ensuring that supported fields can be cleared by
8435 // the next test.
8436 __ Mov(x9, fpcr_all);
8437 __ Msr(FPCR, x9);
8438 __ Mrs(x9, FPCR);
8439 __ And(x9, x9, fpcr_core);
8440
8441 // The undefined bits must ignore writes.
8442 // It's conceivable that a future version of the architecture could use these
8443 // fields (making this test fail), but in the meantime this is a useful test
8444 // for the simulator.
8445 __ Mov(x10, ~fpcr_all);
8446 __ Msr(FPCR, x10);
8447 __ Mrs(x10, FPCR);
8448
armvixlad96eda2013-06-14 11:42:37 +01008449 END();
8450
8451 RUN();
8452
8453 // We should have incremented x7 (from 0) exactly 8 times.
8454 ASSERT_EQUAL_64(8, x7);
8455
armvixl578645f2013-08-15 17:21:42 +01008456 ASSERT_EQUAL_64(fpcr_core, x8);
8457 ASSERT_EQUAL_64(fpcr_core, x9);
8458 ASSERT_EQUAL_64(0, x10);
8459
armvixlad96eda2013-06-14 11:42:37 +01008460 TEARDOWN();
8461}
8462
8463
8464TEST(system_nop) {
8465 SETUP();
8466 RegisterDump before;
8467
8468 START();
8469 before.Dump(&masm);
8470 __ Nop();
8471 END();
8472
8473 RUN();
8474
8475 ASSERT_EQUAL_REGISTERS(before);
8476 ASSERT_EQUAL_NZCV(before.flags_nzcv());
8477
8478 TEARDOWN();
8479}
8480
8481
8482TEST(zero_dest) {
8483 SETUP();
armvixlc68cb642014-09-25 18:49:30 +01008484 ALLOW_ASM();
armvixlad96eda2013-06-14 11:42:37 +01008485 RegisterDump before;
8486
8487 START();
8488 // Preserve the stack pointer, in case we clobber it.
8489 __ Mov(x30, sp);
8490 // Initialize the other registers used in this test.
armvixlb0c8ae22014-03-21 14:03:59 +00008491 uint64_t literal_base = 0x0100001000100101;
armvixlad96eda2013-06-14 11:42:37 +01008492 __ Mov(x0, 0);
8493 __ Mov(x1, literal_base);
8494 for (unsigned i = 2; i < x30.code(); i++) {
8495 __ Add(Register::XRegFromCode(i), Register::XRegFromCode(i-1), x1);
8496 }
8497 before.Dump(&masm);
8498
8499 // All of these instructions should be NOPs in these forms, but have
8500 // alternate forms which can write into the stack pointer.
8501 __ add(xzr, x0, x1);
8502 __ add(xzr, x1, xzr);
8503 __ add(xzr, xzr, x1);
8504
8505 __ and_(xzr, x0, x2);
8506 __ and_(xzr, x2, xzr);
8507 __ and_(xzr, xzr, x2);
8508
8509 __ bic(xzr, x0, x3);
8510 __ bic(xzr, x3, xzr);
8511 __ bic(xzr, xzr, x3);
8512
8513 __ eon(xzr, x0, x4);
8514 __ eon(xzr, x4, xzr);
8515 __ eon(xzr, xzr, x4);
8516
8517 __ eor(xzr, x0, x5);
8518 __ eor(xzr, x5, xzr);
8519 __ eor(xzr, xzr, x5);
8520
8521 __ orr(xzr, x0, x6);
8522 __ orr(xzr, x6, xzr);
8523 __ orr(xzr, xzr, x6);
8524
8525 __ sub(xzr, x0, x7);
8526 __ sub(xzr, x7, xzr);
8527 __ sub(xzr, xzr, x7);
8528
8529 // Swap the saved stack pointer with the real one. If sp was written
8530 // during the test, it will show up in x30. This is done because the test
8531 // framework assumes that sp will be valid at the end of the test.
8532 __ Mov(x29, x30);
8533 __ Mov(x30, sp);
8534 __ Mov(sp, x29);
8535 // We used x29 as a scratch register, so reset it to make sure it doesn't
8536 // trigger a test failure.
8537 __ Add(x29, x28, x1);
8538 END();
8539
8540 RUN();
8541
8542 ASSERT_EQUAL_REGISTERS(before);
8543 ASSERT_EQUAL_NZCV(before.flags_nzcv());
8544
8545 TEARDOWN();
8546}
8547
8548
8549TEST(zero_dest_setflags) {
8550 SETUP();
armvixlc68cb642014-09-25 18:49:30 +01008551 ALLOW_ASM();
armvixlad96eda2013-06-14 11:42:37 +01008552 RegisterDump before;
8553
8554 START();
8555 // Preserve the stack pointer, in case we clobber it.
8556 __ Mov(x30, sp);
8557 // Initialize the other registers used in this test.
armvixlb0c8ae22014-03-21 14:03:59 +00008558 uint64_t literal_base = 0x0100001000100101;
armvixlad96eda2013-06-14 11:42:37 +01008559 __ Mov(x0, 0);
8560 __ Mov(x1, literal_base);
8561 for (int i = 2; i < 30; i++) {
8562 __ Add(Register::XRegFromCode(i), Register::XRegFromCode(i-1), x1);
8563 }
8564 before.Dump(&masm);
8565
8566 // All of these instructions should only write to the flags in these forms,
8567 // but have alternate forms which can write into the stack pointer.
armvixlf37fdc02014-02-05 13:22:16 +00008568 __ adds(xzr, x0, Operand(x1, UXTX));
8569 __ adds(xzr, x1, Operand(xzr, UXTX));
8570 __ adds(xzr, x1, 1234);
8571 __ adds(xzr, x0, x1);
8572 __ adds(xzr, x1, xzr);
8573 __ adds(xzr, xzr, x1);
armvixlad96eda2013-06-14 11:42:37 +01008574
armvixlf37fdc02014-02-05 13:22:16 +00008575 __ ands(xzr, x2, ~0xf);
8576 __ ands(xzr, xzr, ~0xf);
8577 __ ands(xzr, x0, x2);
8578 __ ands(xzr, x2, xzr);
8579 __ ands(xzr, xzr, x2);
armvixlad96eda2013-06-14 11:42:37 +01008580
armvixlf37fdc02014-02-05 13:22:16 +00008581 __ bics(xzr, x3, ~0xf);
8582 __ bics(xzr, xzr, ~0xf);
8583 __ bics(xzr, x0, x3);
8584 __ bics(xzr, x3, xzr);
8585 __ bics(xzr, xzr, x3);
armvixlad96eda2013-06-14 11:42:37 +01008586
armvixlf37fdc02014-02-05 13:22:16 +00008587 __ subs(xzr, x0, Operand(x3, UXTX));
8588 __ subs(xzr, x3, Operand(xzr, UXTX));
8589 __ subs(xzr, x3, 1234);
8590 __ subs(xzr, x0, x3);
8591 __ subs(xzr, x3, xzr);
8592 __ subs(xzr, xzr, x3);
armvixlad96eda2013-06-14 11:42:37 +01008593
8594 // Swap the saved stack pointer with the real one. If sp was written
8595 // during the test, it will show up in x30. This is done because the test
8596 // framework assumes that sp will be valid at the end of the test.
8597 __ Mov(x29, x30);
8598 __ Mov(x30, sp);
8599 __ Mov(sp, x29);
8600 // We used x29 as a scratch register, so reset it to make sure it doesn't
8601 // trigger a test failure.
8602 __ Add(x29, x28, x1);
8603 END();
8604
8605 RUN();
8606
8607 ASSERT_EQUAL_REGISTERS(before);
8608
8609 TEARDOWN();
8610}
8611
8612
8613TEST(register_bit) {
8614 // No code generation takes place in this test, so no need to setup and
8615 // teardown.
8616
8617 // Simple tests.
armvixlb0c8ae22014-03-21 14:03:59 +00008618 assert(x0.Bit() == (UINT64_C(1) << 0));
8619 assert(x1.Bit() == (UINT64_C(1) << 1));
8620 assert(x10.Bit() == (UINT64_C(1) << 10));
armvixlad96eda2013-06-14 11:42:37 +01008621
8622 // AAPCS64 definitions.
armvixlb0c8ae22014-03-21 14:03:59 +00008623 assert(lr.Bit() == (UINT64_C(1) << kLinkRegCode));
armvixlad96eda2013-06-14 11:42:37 +01008624
8625 // Fixed (hardware) definitions.
armvixlb0c8ae22014-03-21 14:03:59 +00008626 assert(xzr.Bit() == (UINT64_C(1) << kZeroRegCode));
armvixlad96eda2013-06-14 11:42:37 +01008627
8628 // Internal ABI definitions.
armvixlb0c8ae22014-03-21 14:03:59 +00008629 assert(sp.Bit() == (UINT64_C(1) << kSPRegInternalCode));
armvixlad96eda2013-06-14 11:42:37 +01008630 assert(sp.Bit() != xzr.Bit());
8631
8632 // xn.Bit() == wn.Bit() at all times, for the same n.
8633 assert(x0.Bit() == w0.Bit());
8634 assert(x1.Bit() == w1.Bit());
8635 assert(x10.Bit() == w10.Bit());
8636 assert(xzr.Bit() == wzr.Bit());
8637 assert(sp.Bit() == wsp.Bit());
8638}
8639
8640
8641TEST(stack_pointer_override) {
8642 // This test generates some stack maintenance code, but the test only checks
8643 // the reported state.
8644 SETUP();
8645 START();
8646
8647 // The default stack pointer in VIXL is sp.
8648 assert(sp.Is(__ StackPointer()));
8649 __ SetStackPointer(x0);
8650 assert(x0.Is(__ StackPointer()));
8651 __ SetStackPointer(x28);
8652 assert(x28.Is(__ StackPointer()));
8653 __ SetStackPointer(sp);
8654 assert(sp.Is(__ StackPointer()));
8655
8656 END();
8657 RUN();
8658 TEARDOWN();
8659}
8660
8661
8662TEST(peek_poke_simple) {
8663 SETUP();
8664 START();
8665
8666 static const RegList x0_to_x3 = x0.Bit() | x1.Bit() | x2.Bit() | x3.Bit();
8667 static const RegList x10_to_x13 = x10.Bit() | x11.Bit() |
8668 x12.Bit() | x13.Bit();
8669
8670 // The literal base is chosen to have two useful properties:
8671 // * When multiplied by small values (such as a register index), this value
8672 // is clearly readable in the result.
8673 // * The value is not formed from repeating fixed-size smaller values, so it
8674 // can be used to detect endianness-related errors.
armvixlb0c8ae22014-03-21 14:03:59 +00008675 uint64_t literal_base = 0x0100001000100101;
armvixlad96eda2013-06-14 11:42:37 +01008676
8677 // Initialize the registers.
8678 __ Mov(x0, literal_base);
8679 __ Add(x1, x0, x0);
8680 __ Add(x2, x1, x0);
8681 __ Add(x3, x2, x0);
8682
8683 __ Claim(32);
8684
8685 // Simple exchange.
8686 // After this test:
8687 // x0-x3 should be unchanged.
8688 // w10-w13 should contain the lower words of x0-x3.
8689 __ Poke(x0, 0);
8690 __ Poke(x1, 8);
8691 __ Poke(x2, 16);
8692 __ Poke(x3, 24);
8693 Clobber(&masm, x0_to_x3);
8694 __ Peek(x0, 0);
8695 __ Peek(x1, 8);
8696 __ Peek(x2, 16);
8697 __ Peek(x3, 24);
8698
8699 __ Poke(w0, 0);
8700 __ Poke(w1, 4);
8701 __ Poke(w2, 8);
8702 __ Poke(w3, 12);
8703 Clobber(&masm, x10_to_x13);
8704 __ Peek(w10, 0);
8705 __ Peek(w11, 4);
8706 __ Peek(w12, 8);
8707 __ Peek(w13, 12);
8708
8709 __ Drop(32);
8710
8711 END();
8712 RUN();
8713
8714 ASSERT_EQUAL_64(literal_base * 1, x0);
8715 ASSERT_EQUAL_64(literal_base * 2, x1);
8716 ASSERT_EQUAL_64(literal_base * 3, x2);
8717 ASSERT_EQUAL_64(literal_base * 4, x3);
8718
8719 ASSERT_EQUAL_64((literal_base * 1) & 0xffffffff, x10);
8720 ASSERT_EQUAL_64((literal_base * 2) & 0xffffffff, x11);
8721 ASSERT_EQUAL_64((literal_base * 3) & 0xffffffff, x12);
8722 ASSERT_EQUAL_64((literal_base * 4) & 0xffffffff, x13);
8723
8724 TEARDOWN();
8725}
8726
8727
8728TEST(peek_poke_unaligned) {
8729 SETUP();
8730 START();
8731
8732 // The literal base is chosen to have two useful properties:
8733 // * When multiplied by small values (such as a register index), this value
8734 // is clearly readable in the result.
8735 // * The value is not formed from repeating fixed-size smaller values, so it
8736 // can be used to detect endianness-related errors.
armvixlb0c8ae22014-03-21 14:03:59 +00008737 uint64_t literal_base = 0x0100001000100101;
armvixlad96eda2013-06-14 11:42:37 +01008738
8739 // Initialize the registers.
8740 __ Mov(x0, literal_base);
8741 __ Add(x1, x0, x0);
8742 __ Add(x2, x1, x0);
8743 __ Add(x3, x2, x0);
8744 __ Add(x4, x3, x0);
8745 __ Add(x5, x4, x0);
8746 __ Add(x6, x5, x0);
8747
8748 __ Claim(32);
8749
8750 // Unaligned exchanges.
8751 // After this test:
8752 // x0-x6 should be unchanged.
8753 // w10-w12 should contain the lower words of x0-x2.
8754 __ Poke(x0, 1);
8755 Clobber(&masm, x0.Bit());
8756 __ Peek(x0, 1);
8757 __ Poke(x1, 2);
8758 Clobber(&masm, x1.Bit());
8759 __ Peek(x1, 2);
8760 __ Poke(x2, 3);
8761 Clobber(&masm, x2.Bit());
8762 __ Peek(x2, 3);
8763 __ Poke(x3, 4);
8764 Clobber(&masm, x3.Bit());
8765 __ Peek(x3, 4);
8766 __ Poke(x4, 5);
8767 Clobber(&masm, x4.Bit());
8768 __ Peek(x4, 5);
8769 __ Poke(x5, 6);
8770 Clobber(&masm, x5.Bit());
8771 __ Peek(x5, 6);
8772 __ Poke(x6, 7);
8773 Clobber(&masm, x6.Bit());
8774 __ Peek(x6, 7);
8775
8776 __ Poke(w0, 1);
8777 Clobber(&masm, w10.Bit());
8778 __ Peek(w10, 1);
8779 __ Poke(w1, 2);
8780 Clobber(&masm, w11.Bit());
8781 __ Peek(w11, 2);
8782 __ Poke(w2, 3);
8783 Clobber(&masm, w12.Bit());
8784 __ Peek(w12, 3);
8785
8786 __ Drop(32);
8787
8788 END();
8789 RUN();
8790
8791 ASSERT_EQUAL_64(literal_base * 1, x0);
8792 ASSERT_EQUAL_64(literal_base * 2, x1);
8793 ASSERT_EQUAL_64(literal_base * 3, x2);
8794 ASSERT_EQUAL_64(literal_base * 4, x3);
8795 ASSERT_EQUAL_64(literal_base * 5, x4);
8796 ASSERT_EQUAL_64(literal_base * 6, x5);
8797 ASSERT_EQUAL_64(literal_base * 7, x6);
8798
8799 ASSERT_EQUAL_64((literal_base * 1) & 0xffffffff, x10);
8800 ASSERT_EQUAL_64((literal_base * 2) & 0xffffffff, x11);
8801 ASSERT_EQUAL_64((literal_base * 3) & 0xffffffff, x12);
8802
8803 TEARDOWN();
8804}
8805
8806
8807TEST(peek_poke_endianness) {
8808 SETUP();
8809 START();
8810
8811 // The literal base is chosen to have two useful properties:
8812 // * When multiplied by small values (such as a register index), this value
8813 // is clearly readable in the result.
8814 // * The value is not formed from repeating fixed-size smaller values, so it
8815 // can be used to detect endianness-related errors.
armvixlb0c8ae22014-03-21 14:03:59 +00008816 uint64_t literal_base = 0x0100001000100101;
armvixlad96eda2013-06-14 11:42:37 +01008817
8818 // Initialize the registers.
8819 __ Mov(x0, literal_base);
8820 __ Add(x1, x0, x0);
8821
8822 __ Claim(32);
8823
8824 // Endianness tests.
8825 // After this section:
8826 // x4 should match x0[31:0]:x0[63:32]
8827 // w5 should match w1[15:0]:w1[31:16]
8828 __ Poke(x0, 0);
8829 __ Poke(x0, 8);
8830 __ Peek(x4, 4);
8831
8832 __ Poke(w1, 0);
8833 __ Poke(w1, 4);
8834 __ Peek(w5, 2);
8835
8836 __ Drop(32);
8837
8838 END();
8839 RUN();
8840
8841 uint64_t x0_expected = literal_base * 1;
8842 uint64_t x1_expected = literal_base * 2;
8843 uint64_t x4_expected = (x0_expected << 32) | (x0_expected >> 32);
8844 uint64_t x5_expected = ((x1_expected << 16) & 0xffff0000) |
8845 ((x1_expected >> 16) & 0x0000ffff);
8846
8847 ASSERT_EQUAL_64(x0_expected, x0);
8848 ASSERT_EQUAL_64(x1_expected, x1);
8849 ASSERT_EQUAL_64(x4_expected, x4);
8850 ASSERT_EQUAL_64(x5_expected, x5);
8851
8852 TEARDOWN();
8853}
8854
8855
8856TEST(peek_poke_mixed) {
8857 SETUP();
8858 START();
8859
8860 // The literal base is chosen to have two useful properties:
8861 // * When multiplied by small values (such as a register index), this value
8862 // is clearly readable in the result.
8863 // * The value is not formed from repeating fixed-size smaller values, so it
8864 // can be used to detect endianness-related errors.
armvixlb0c8ae22014-03-21 14:03:59 +00008865 uint64_t literal_base = 0x0100001000100101;
armvixlad96eda2013-06-14 11:42:37 +01008866
8867 // Initialize the registers.
8868 __ Mov(x0, literal_base);
8869 __ Add(x1, x0, x0);
8870 __ Add(x2, x1, x0);
8871 __ Add(x3, x2, x0);
8872
8873 __ Claim(32);
8874
8875 // Mix with other stack operations.
8876 // After this section:
8877 // x0-x3 should be unchanged.
8878 // x6 should match x1[31:0]:x0[63:32]
8879 // w7 should match x1[15:0]:x0[63:48]
8880 __ Poke(x1, 8);
8881 __ Poke(x0, 0);
8882 {
armvixlb0c8ae22014-03-21 14:03:59 +00008883 VIXL_ASSERT(__ StackPointer().Is(sp));
armvixlad96eda2013-06-14 11:42:37 +01008884 __ Mov(x4, __ StackPointer());
8885 __ SetStackPointer(x4);
8886
8887 __ Poke(wzr, 0); // Clobber the space we're about to drop.
8888 __ Drop(4);
8889 __ Peek(x6, 0);
8890 __ Claim(8);
8891 __ Peek(w7, 10);
8892 __ Poke(x3, 28);
8893 __ Poke(xzr, 0); // Clobber the space we're about to drop.
8894 __ Drop(8);
8895 __ Poke(x2, 12);
8896 __ Push(w0);
8897
8898 __ Mov(sp, __ StackPointer());
8899 __ SetStackPointer(sp);
8900 }
8901
8902 __ Pop(x0, x1, x2, x3);
8903
8904 END();
8905 RUN();
8906
8907 uint64_t x0_expected = literal_base * 1;
8908 uint64_t x1_expected = literal_base * 2;
8909 uint64_t x2_expected = literal_base * 3;
8910 uint64_t x3_expected = literal_base * 4;
8911 uint64_t x6_expected = (x1_expected << 32) | (x0_expected >> 32);
8912 uint64_t x7_expected = ((x1_expected << 16) & 0xffff0000) |
8913 ((x0_expected >> 48) & 0x0000ffff);
8914
8915 ASSERT_EQUAL_64(x0_expected, x0);
8916 ASSERT_EQUAL_64(x1_expected, x1);
8917 ASSERT_EQUAL_64(x2_expected, x2);
8918 ASSERT_EQUAL_64(x3_expected, x3);
8919 ASSERT_EQUAL_64(x6_expected, x6);
8920 ASSERT_EQUAL_64(x7_expected, x7);
8921
8922 TEARDOWN();
8923}
8924
8925
armvixlc68cb642014-09-25 18:49:30 +01008926TEST(peek_poke_reglist) {
8927 SETUP();
8928 START();
8929
8930 // The literal base is chosen to have two useful properties:
8931 // * When multiplied by small values (such as a register index), this value
8932 // is clearly readable in the result.
8933 // * The value is not formed from repeating fixed-size smaller values, so it
8934 // can be used to detect endianness-related errors.
8935 uint64_t base = 0x0100001000100101;
8936
8937 // Initialize the registers.
8938 __ Mov(x1, base);
8939 __ Add(x2, x1, x1);
8940 __ Add(x3, x2, x1);
8941 __ Add(x4, x3, x1);
8942
8943 CPURegList list_1(x1, x2, x3, x4);
8944 CPURegList list_2(x11, x12, x13, x14);
8945 int list_1_size = list_1.TotalSizeInBytes();
8946
8947 __ Claim(2 * list_1_size);
8948
8949 __ PokeCPURegList(list_1, 0);
8950 __ PokeXRegList(list_1.list(), list_1_size);
8951 __ PeekCPURegList(list_2, 2 * kXRegSizeInBytes);
8952 __ PeekXRegList(x15.Bit(), kWRegSizeInBytes);
8953 __ PeekWRegList(w16.Bit() | w17.Bit(), 3 * kXRegSizeInBytes);
8954
8955 __ Drop(2 * list_1_size);
8956
8957
8958 uint64_t base_d = 0x1010010001000010;
8959
8960 // Initialize the registers.
8961 __ Mov(x1, base_d);
8962 __ Add(x2, x1, x1);
8963 __ Add(x3, x2, x1);
8964 __ Add(x4, x3, x1);
8965 __ Fmov(d1, x1);
8966 __ Fmov(d2, x2);
8967 __ Fmov(d3, x3);
8968 __ Fmov(d4, x4);
8969
8970 CPURegList list_d_1(d1, d2, d3, d4);
8971 CPURegList list_d_2(d11, d12, d13, d14);
8972 int list_d_1_size = list_d_1.TotalSizeInBytes();
8973
8974 __ Claim(2 * list_d_1_size);
8975
8976 __ PokeCPURegList(list_d_1, 0);
8977 __ PokeDRegList(list_d_1.list(), list_d_1_size);
8978 __ PeekCPURegList(list_d_2, 2 * kDRegSizeInBytes);
8979 __ PeekDRegList(d15.Bit(), kSRegSizeInBytes);
8980 __ PeekSRegList(s16.Bit() | s17.Bit(), 3 * kDRegSizeInBytes);
8981
8982 __ Drop(2 * list_d_1_size);
8983
8984
8985 END();
8986 RUN();
8987
8988 ASSERT_EQUAL_64(3 * base, x11);
8989 ASSERT_EQUAL_64(4 * base, x12);
8990 ASSERT_EQUAL_64(1 * base, x13);
8991 ASSERT_EQUAL_64(2 * base, x14);
8992 ASSERT_EQUAL_64(((1 * base) >> kWRegSize) | ((2 * base) << kWRegSize), x15);
8993 ASSERT_EQUAL_64(2 * base, x14);
8994 ASSERT_EQUAL_32((4 * base) & kWRegMask, w16);
8995 ASSERT_EQUAL_32((4 * base) >> kWRegSize, w17);
8996
8997 ASSERT_EQUAL_FP64(rawbits_to_double(3 * base_d), d11);
8998 ASSERT_EQUAL_FP64(rawbits_to_double(4 * base_d), d12);
8999 ASSERT_EQUAL_FP64(rawbits_to_double(1 * base_d), d13);
9000 ASSERT_EQUAL_FP64(rawbits_to_double(2 * base_d), d14);
9001 ASSERT_EQUAL_FP64(
9002 rawbits_to_double((base_d >> kSRegSize) | ((2 * base_d) << kSRegSize)),
9003 d15);
9004 ASSERT_EQUAL_FP64(rawbits_to_double(2 * base_d), d14);
9005 ASSERT_EQUAL_FP32(rawbits_to_float((4 * base_d) & kSRegMask), s16);
9006 ASSERT_EQUAL_FP32(rawbits_to_float((4 * base_d) >> kSRegSize), s17);
9007
9008 TEARDOWN();
9009}
9010
9011
armvixlad96eda2013-06-14 11:42:37 +01009012// This enum is used only as an argument to the push-pop test helpers.
9013enum PushPopMethod {
9014 // Push or Pop using the Push and Pop methods, with blocks of up to four
9015 // registers. (Smaller blocks will be used if necessary.)
9016 PushPopByFour,
9017
9018 // Use Push<Size>RegList and Pop<Size>RegList to transfer the registers.
9019 PushPopRegList
9020};
9021
9022
9023// The maximum number of registers that can be used by the PushPopXReg* tests,
9024// where a reg_count field is provided.
9025static int const kPushPopXRegMaxRegCount = -1;
9026
9027// Test a simple push-pop pattern:
9028// * Claim <claim> bytes to set the stack alignment.
9029// * Push <reg_count> registers with size <reg_size>.
9030// * Clobber the register contents.
9031// * Pop <reg_count> registers to restore the original contents.
9032// * Drop <claim> bytes to restore the original stack pointer.
9033//
9034// Different push and pop methods can be specified independently to test for
9035// proper word-endian behaviour.
9036static void PushPopXRegSimpleHelper(int reg_count,
9037 int claim,
9038 int reg_size,
9039 PushPopMethod push_method,
9040 PushPopMethod pop_method) {
9041 SETUP();
9042
9043 START();
9044
9045 // Arbitrarily pick a register to use as a stack pointer.
9046 const Register& stack_pointer = x20;
9047 const RegList allowed = ~stack_pointer.Bit();
9048 if (reg_count == kPushPopXRegMaxRegCount) {
9049 reg_count = CountSetBits(allowed, kNumberOfRegisters);
9050 }
9051 // Work out which registers to use, based on reg_size.
9052 Register r[kNumberOfRegisters];
9053 Register x[kNumberOfRegisters];
9054 RegList list = PopulateRegisterArray(NULL, x, r, reg_size, reg_count,
9055 allowed);
9056
9057 // The literal base is chosen to have two useful properties:
9058 // * When multiplied by small values (such as a register index), this value
9059 // is clearly readable in the result.
9060 // * The value is not formed from repeating fixed-size smaller values, so it
9061 // can be used to detect endianness-related errors.
armvixlb0c8ae22014-03-21 14:03:59 +00009062 uint64_t literal_base = 0x0100001000100101;
armvixlad96eda2013-06-14 11:42:37 +01009063
9064 {
armvixlb0c8ae22014-03-21 14:03:59 +00009065 VIXL_ASSERT(__ StackPointer().Is(sp));
armvixlad96eda2013-06-14 11:42:37 +01009066 __ Mov(stack_pointer, __ StackPointer());
9067 __ SetStackPointer(stack_pointer);
9068
9069 int i;
9070
9071 // Initialize the registers.
9072 for (i = 0; i < reg_count; i++) {
9073 // Always write into the X register, to ensure that the upper word is
9074 // properly ignored by Push when testing W registers.
9075 __ Mov(x[i], literal_base * i);
9076 }
9077
9078 // Claim memory first, as requested.
9079 __ Claim(claim);
9080
9081 switch (push_method) {
9082 case PushPopByFour:
9083 // Push high-numbered registers first (to the highest addresses).
9084 for (i = reg_count; i >= 4; i -= 4) {
9085 __ Push(r[i-1], r[i-2], r[i-3], r[i-4]);
9086 }
9087 // Finish off the leftovers.
9088 switch (i) {
9089 case 3: __ Push(r[2], r[1], r[0]); break;
9090 case 2: __ Push(r[1], r[0]); break;
9091 case 1: __ Push(r[0]); break;
armvixlb0c8ae22014-03-21 14:03:59 +00009092 default: VIXL_ASSERT(i == 0); break;
armvixlad96eda2013-06-14 11:42:37 +01009093 }
9094 break;
9095 case PushPopRegList:
9096 __ PushSizeRegList(list, reg_size);
9097 break;
9098 }
9099
9100 // Clobber all the registers, to ensure that they get repopulated by Pop.
9101 Clobber(&masm, list);
9102
9103 switch (pop_method) {
9104 case PushPopByFour:
9105 // Pop low-numbered registers first (from the lowest addresses).
9106 for (i = 0; i <= (reg_count-4); i += 4) {
9107 __ Pop(r[i], r[i+1], r[i+2], r[i+3]);
9108 }
9109 // Finish off the leftovers.
9110 switch (reg_count - i) {
9111 case 3: __ Pop(r[i], r[i+1], r[i+2]); break;
9112 case 2: __ Pop(r[i], r[i+1]); break;
9113 case 1: __ Pop(r[i]); break;
armvixlb0c8ae22014-03-21 14:03:59 +00009114 default: VIXL_ASSERT(i == reg_count); break;
armvixlad96eda2013-06-14 11:42:37 +01009115 }
9116 break;
9117 case PushPopRegList:
9118 __ PopSizeRegList(list, reg_size);
9119 break;
9120 }
9121
9122 // Drop memory to restore stack_pointer.
9123 __ Drop(claim);
9124
9125 __ Mov(sp, __ StackPointer());
9126 __ SetStackPointer(sp);
9127 }
9128
9129 END();
9130
9131 RUN();
9132
9133 // Check that the register contents were preserved.
9134 // Always use ASSERT_EQUAL_64, even when testing W registers, so we can test
9135 // that the upper word was properly cleared by Pop.
armvixlb0c8ae22014-03-21 14:03:59 +00009136 literal_base &= (0xffffffffffffffff >> (64-reg_size));
armvixlad96eda2013-06-14 11:42:37 +01009137 for (int i = 0; i < reg_count; i++) {
9138 if (x[i].Is(xzr)) {
9139 ASSERT_EQUAL_64(0, x[i]);
9140 } else {
9141 ASSERT_EQUAL_64(literal_base * i, x[i]);
9142 }
9143 }
9144
9145 TEARDOWN();
9146}
9147
9148
9149TEST(push_pop_xreg_simple_32) {
9150 for (int claim = 0; claim <= 8; claim++) {
9151 for (int count = 0; count <= 8; count++) {
9152 PushPopXRegSimpleHelper(count, claim, kWRegSize,
9153 PushPopByFour, PushPopByFour);
9154 PushPopXRegSimpleHelper(count, claim, kWRegSize,
9155 PushPopByFour, PushPopRegList);
9156 PushPopXRegSimpleHelper(count, claim, kWRegSize,
9157 PushPopRegList, PushPopByFour);
9158 PushPopXRegSimpleHelper(count, claim, kWRegSize,
9159 PushPopRegList, PushPopRegList);
9160 }
9161 // Test with the maximum number of registers.
9162 PushPopXRegSimpleHelper(kPushPopXRegMaxRegCount,
9163 claim, kWRegSize, PushPopByFour, PushPopByFour);
9164 PushPopXRegSimpleHelper(kPushPopXRegMaxRegCount,
9165 claim, kWRegSize, PushPopByFour, PushPopRegList);
9166 PushPopXRegSimpleHelper(kPushPopXRegMaxRegCount,
9167 claim, kWRegSize, PushPopRegList, PushPopByFour);
9168 PushPopXRegSimpleHelper(kPushPopXRegMaxRegCount,
9169 claim, kWRegSize, PushPopRegList, PushPopRegList);
9170 }
9171}
9172
9173
9174TEST(push_pop_xreg_simple_64) {
9175 for (int claim = 0; claim <= 8; claim++) {
9176 for (int count = 0; count <= 8; count++) {
9177 PushPopXRegSimpleHelper(count, claim, kXRegSize,
9178 PushPopByFour, PushPopByFour);
9179 PushPopXRegSimpleHelper(count, claim, kXRegSize,
9180 PushPopByFour, PushPopRegList);
9181 PushPopXRegSimpleHelper(count, claim, kXRegSize,
9182 PushPopRegList, PushPopByFour);
9183 PushPopXRegSimpleHelper(count, claim, kXRegSize,
9184 PushPopRegList, PushPopRegList);
9185 }
9186 // Test with the maximum number of registers.
9187 PushPopXRegSimpleHelper(kPushPopXRegMaxRegCount,
9188 claim, kXRegSize, PushPopByFour, PushPopByFour);
9189 PushPopXRegSimpleHelper(kPushPopXRegMaxRegCount,
9190 claim, kXRegSize, PushPopByFour, PushPopRegList);
9191 PushPopXRegSimpleHelper(kPushPopXRegMaxRegCount,
9192 claim, kXRegSize, PushPopRegList, PushPopByFour);
9193 PushPopXRegSimpleHelper(kPushPopXRegMaxRegCount,
9194 claim, kXRegSize, PushPopRegList, PushPopRegList);
9195 }
9196}
9197
9198
9199// The maximum number of registers that can be used by the PushPopFPXReg* tests,
9200// where a reg_count field is provided.
9201static int const kPushPopFPXRegMaxRegCount = -1;
9202
9203// Test a simple push-pop pattern:
9204// * Claim <claim> bytes to set the stack alignment.
9205// * Push <reg_count> FP registers with size <reg_size>.
9206// * Clobber the register contents.
9207// * Pop <reg_count> FP registers to restore the original contents.
9208// * Drop <claim> bytes to restore the original stack pointer.
9209//
9210// Different push and pop methods can be specified independently to test for
9211// proper word-endian behaviour.
9212static void PushPopFPXRegSimpleHelper(int reg_count,
9213 int claim,
9214 int reg_size,
9215 PushPopMethod push_method,
9216 PushPopMethod pop_method) {
9217 SETUP();
9218
9219 START();
9220
9221 // We can use any floating-point register. None of them are reserved for
9222 // debug code, for example.
9223 static RegList const allowed = ~0;
9224 if (reg_count == kPushPopFPXRegMaxRegCount) {
9225 reg_count = CountSetBits(allowed, kNumberOfFPRegisters);
9226 }
9227 // Work out which registers to use, based on reg_size.
9228 FPRegister v[kNumberOfRegisters];
9229 FPRegister d[kNumberOfRegisters];
9230 RegList list = PopulateFPRegisterArray(NULL, d, v, reg_size, reg_count,
9231 allowed);
9232
9233 // Arbitrarily pick a register to use as a stack pointer.
9234 const Register& stack_pointer = x10;
9235
9236 // The literal base is chosen to have two useful properties:
9237 // * When multiplied (using an integer) by small values (such as a register
9238 // index), this value is clearly readable in the result.
9239 // * The value is not formed from repeating fixed-size smaller values, so it
9240 // can be used to detect endianness-related errors.
9241 // * It is never a floating-point NaN, and will therefore always compare
9242 // equal to itself.
armvixlb0c8ae22014-03-21 14:03:59 +00009243 uint64_t literal_base = 0x0100001000100101;
armvixlad96eda2013-06-14 11:42:37 +01009244
9245 {
armvixlb0c8ae22014-03-21 14:03:59 +00009246 VIXL_ASSERT(__ StackPointer().Is(sp));
armvixlad96eda2013-06-14 11:42:37 +01009247 __ Mov(stack_pointer, __ StackPointer());
9248 __ SetStackPointer(stack_pointer);
9249
9250 int i;
9251
9252 // Initialize the registers, using X registers to load the literal.
9253 __ Mov(x0, 0);
9254 __ Mov(x1, literal_base);
9255 for (i = 0; i < reg_count; i++) {
9256 // Always write into the D register, to ensure that the upper word is
9257 // properly ignored by Push when testing S registers.
9258 __ Fmov(d[i], x0);
9259 // Calculate the next literal.
9260 __ Add(x0, x0, x1);
9261 }
9262
9263 // Claim memory first, as requested.
9264 __ Claim(claim);
9265
9266 switch (push_method) {
9267 case PushPopByFour:
9268 // Push high-numbered registers first (to the highest addresses).
9269 for (i = reg_count; i >= 4; i -= 4) {
9270 __ Push(v[i-1], v[i-2], v[i-3], v[i-4]);
9271 }
9272 // Finish off the leftovers.
9273 switch (i) {
9274 case 3: __ Push(v[2], v[1], v[0]); break;
9275 case 2: __ Push(v[1], v[0]); break;
9276 case 1: __ Push(v[0]); break;
armvixlb0c8ae22014-03-21 14:03:59 +00009277 default: VIXL_ASSERT(i == 0); break;
armvixlad96eda2013-06-14 11:42:37 +01009278 }
9279 break;
9280 case PushPopRegList:
9281 __ PushSizeRegList(list, reg_size, CPURegister::kFPRegister);
9282 break;
9283 }
9284
9285 // Clobber all the registers, to ensure that they get repopulated by Pop.
9286 ClobberFP(&masm, list);
9287
9288 switch (pop_method) {
9289 case PushPopByFour:
9290 // Pop low-numbered registers first (from the lowest addresses).
9291 for (i = 0; i <= (reg_count-4); i += 4) {
9292 __ Pop(v[i], v[i+1], v[i+2], v[i+3]);
9293 }
9294 // Finish off the leftovers.
9295 switch (reg_count - i) {
9296 case 3: __ Pop(v[i], v[i+1], v[i+2]); break;
9297 case 2: __ Pop(v[i], v[i+1]); break;
9298 case 1: __ Pop(v[i]); break;
armvixlb0c8ae22014-03-21 14:03:59 +00009299 default: VIXL_ASSERT(i == reg_count); break;
armvixlad96eda2013-06-14 11:42:37 +01009300 }
9301 break;
9302 case PushPopRegList:
9303 __ PopSizeRegList(list, reg_size, CPURegister::kFPRegister);
9304 break;
9305 }
9306
9307 // Drop memory to restore the stack pointer.
9308 __ Drop(claim);
9309
9310 __ Mov(sp, __ StackPointer());
9311 __ SetStackPointer(sp);
9312 }
9313
9314 END();
9315
9316 RUN();
9317
9318 // Check that the register contents were preserved.
9319 // Always use ASSERT_EQUAL_FP64, even when testing S registers, so we can
9320 // test that the upper word was properly cleared by Pop.
armvixlb0c8ae22014-03-21 14:03:59 +00009321 literal_base &= (0xffffffffffffffff >> (64-reg_size));
armvixlad96eda2013-06-14 11:42:37 +01009322 for (int i = 0; i < reg_count; i++) {
9323 uint64_t literal = literal_base * i;
9324 double expected;
9325 memcpy(&expected, &literal, sizeof(expected));
9326 ASSERT_EQUAL_FP64(expected, d[i]);
9327 }
9328
9329 TEARDOWN();
9330}
9331
9332
9333TEST(push_pop_fp_xreg_simple_32) {
9334 for (int claim = 0; claim <= 8; claim++) {
9335 for (int count = 0; count <= 8; count++) {
9336 PushPopFPXRegSimpleHelper(count, claim, kSRegSize,
9337 PushPopByFour, PushPopByFour);
9338 PushPopFPXRegSimpleHelper(count, claim, kSRegSize,
9339 PushPopByFour, PushPopRegList);
9340 PushPopFPXRegSimpleHelper(count, claim, kSRegSize,
9341 PushPopRegList, PushPopByFour);
9342 PushPopFPXRegSimpleHelper(count, claim, kSRegSize,
9343 PushPopRegList, PushPopRegList);
9344 }
9345 // Test with the maximum number of registers.
9346 PushPopFPXRegSimpleHelper(kPushPopFPXRegMaxRegCount, claim, kSRegSize,
9347 PushPopByFour, PushPopByFour);
9348 PushPopFPXRegSimpleHelper(kPushPopFPXRegMaxRegCount, claim, kSRegSize,
9349 PushPopByFour, PushPopRegList);
9350 PushPopFPXRegSimpleHelper(kPushPopFPXRegMaxRegCount, claim, kSRegSize,
9351 PushPopRegList, PushPopByFour);
9352 PushPopFPXRegSimpleHelper(kPushPopFPXRegMaxRegCount, claim, kSRegSize,
9353 PushPopRegList, PushPopRegList);
9354 }
9355}
9356
9357
9358TEST(push_pop_fp_xreg_simple_64) {
9359 for (int claim = 0; claim <= 8; claim++) {
9360 for (int count = 0; count <= 8; count++) {
9361 PushPopFPXRegSimpleHelper(count, claim, kDRegSize,
9362 PushPopByFour, PushPopByFour);
9363 PushPopFPXRegSimpleHelper(count, claim, kDRegSize,
9364 PushPopByFour, PushPopRegList);
9365 PushPopFPXRegSimpleHelper(count, claim, kDRegSize,
9366 PushPopRegList, PushPopByFour);
9367 PushPopFPXRegSimpleHelper(count, claim, kDRegSize,
9368 PushPopRegList, PushPopRegList);
9369 }
9370 // Test with the maximum number of registers.
9371 PushPopFPXRegSimpleHelper(kPushPopFPXRegMaxRegCount, claim, kDRegSize,
9372 PushPopByFour, PushPopByFour);
9373 PushPopFPXRegSimpleHelper(kPushPopFPXRegMaxRegCount, claim, kDRegSize,
9374 PushPopByFour, PushPopRegList);
9375 PushPopFPXRegSimpleHelper(kPushPopFPXRegMaxRegCount, claim, kDRegSize,
9376 PushPopRegList, PushPopByFour);
9377 PushPopFPXRegSimpleHelper(kPushPopFPXRegMaxRegCount, claim, kDRegSize,
9378 PushPopRegList, PushPopRegList);
9379 }
9380}
9381
9382
9383// Push and pop data using an overlapping combination of Push/Pop and
9384// RegList-based methods.
9385static void PushPopXRegMixedMethodsHelper(int claim, int reg_size) {
9386 SETUP();
9387
9388 // Arbitrarily pick a register to use as a stack pointer.
9389 const Register& stack_pointer = x5;
9390 const RegList allowed = ~stack_pointer.Bit();
9391 // Work out which registers to use, based on reg_size.
9392 Register r[10];
9393 Register x[10];
9394 PopulateRegisterArray(NULL, x, r, reg_size, 10, allowed);
9395
9396 // Calculate some handy register lists.
9397 RegList r0_to_r3 = 0;
9398 for (int i = 0; i <= 3; i++) {
9399 r0_to_r3 |= x[i].Bit();
9400 }
9401 RegList r4_to_r5 = 0;
9402 for (int i = 4; i <= 5; i++) {
9403 r4_to_r5 |= x[i].Bit();
9404 }
9405 RegList r6_to_r9 = 0;
9406 for (int i = 6; i <= 9; i++) {
9407 r6_to_r9 |= x[i].Bit();
9408 }
9409
9410 // The literal base is chosen to have two useful properties:
9411 // * When multiplied by small values (such as a register index), this value
9412 // is clearly readable in the result.
9413 // * The value is not formed from repeating fixed-size smaller values, so it
9414 // can be used to detect endianness-related errors.
armvixlb0c8ae22014-03-21 14:03:59 +00009415 uint64_t literal_base = 0x0100001000100101;
armvixlad96eda2013-06-14 11:42:37 +01009416
9417 START();
9418 {
armvixlb0c8ae22014-03-21 14:03:59 +00009419 VIXL_ASSERT(__ StackPointer().Is(sp));
armvixlad96eda2013-06-14 11:42:37 +01009420 __ Mov(stack_pointer, __ StackPointer());
9421 __ SetStackPointer(stack_pointer);
9422
9423 // Claim memory first, as requested.
9424 __ Claim(claim);
9425
9426 __ Mov(x[3], literal_base * 3);
9427 __ Mov(x[2], literal_base * 2);
9428 __ Mov(x[1], literal_base * 1);
9429 __ Mov(x[0], literal_base * 0);
9430
9431 __ PushSizeRegList(r0_to_r3, reg_size);
9432 __ Push(r[3], r[2]);
9433
9434 Clobber(&masm, r0_to_r3);
9435 __ PopSizeRegList(r0_to_r3, reg_size);
9436
9437 __ Push(r[2], r[1], r[3], r[0]);
9438
9439 Clobber(&masm, r4_to_r5);
9440 __ Pop(r[4], r[5]);
9441 Clobber(&masm, r6_to_r9);
9442 __ Pop(r[6], r[7], r[8], r[9]);
9443
9444 // Drop memory to restore stack_pointer.
9445 __ Drop(claim);
9446
9447 __ Mov(sp, __ StackPointer());
9448 __ SetStackPointer(sp);
9449 }
9450
9451 END();
9452
9453 RUN();
9454
9455 // Always use ASSERT_EQUAL_64, even when testing W registers, so we can test
9456 // that the upper word was properly cleared by Pop.
armvixlb0c8ae22014-03-21 14:03:59 +00009457 literal_base &= (0xffffffffffffffff >> (64-reg_size));
armvixlad96eda2013-06-14 11:42:37 +01009458
9459 ASSERT_EQUAL_64(literal_base * 3, x[9]);
9460 ASSERT_EQUAL_64(literal_base * 2, x[8]);
9461 ASSERT_EQUAL_64(literal_base * 0, x[7]);
9462 ASSERT_EQUAL_64(literal_base * 3, x[6]);
9463 ASSERT_EQUAL_64(literal_base * 1, x[5]);
9464 ASSERT_EQUAL_64(literal_base * 2, x[4]);
9465
9466 TEARDOWN();
9467}
9468
9469
9470TEST(push_pop_xreg_mixed_methods_64) {
9471 for (int claim = 0; claim <= 8; claim++) {
9472 PushPopXRegMixedMethodsHelper(claim, kXRegSize);
9473 }
9474}
9475
9476
9477TEST(push_pop_xreg_mixed_methods_32) {
9478 for (int claim = 0; claim <= 8; claim++) {
9479 PushPopXRegMixedMethodsHelper(claim, kWRegSize);
9480 }
9481}
9482
9483
9484// Push and pop data using overlapping X- and W-sized quantities.
9485static void PushPopXRegWXOverlapHelper(int reg_count, int claim) {
9486 SETUP();
9487
9488 // Arbitrarily pick a register to use as a stack pointer.
9489 const Register& stack_pointer = x10;
9490 const RegList allowed = ~stack_pointer.Bit();
9491 if (reg_count == kPushPopXRegMaxRegCount) {
9492 reg_count = CountSetBits(allowed, kNumberOfRegisters);
9493 }
9494 // Work out which registers to use, based on reg_size.
9495 Register w[kNumberOfRegisters];
9496 Register x[kNumberOfRegisters];
9497 RegList list = PopulateRegisterArray(w, x, NULL, 0, reg_count, allowed);
9498
9499 // The number of W-sized slots we expect to pop. When we pop, we alternate
9500 // between W and X registers, so we need reg_count*1.5 W-sized slots.
9501 int const requested_w_slots = reg_count + reg_count / 2;
9502
9503 // Track what _should_ be on the stack, using W-sized slots.
9504 static int const kMaxWSlots = kNumberOfRegisters + kNumberOfRegisters / 2;
9505 uint32_t stack[kMaxWSlots];
9506 for (int i = 0; i < kMaxWSlots; i++) {
9507 stack[i] = 0xdeadbeef;
9508 }
9509
9510 // The literal base is chosen to have two useful properties:
9511 // * When multiplied by small values (such as a register index), this value
9512 // is clearly readable in the result.
9513 // * The value is not formed from repeating fixed-size smaller values, so it
9514 // can be used to detect endianness-related errors.
armvixlb0c8ae22014-03-21 14:03:59 +00009515 static uint64_t const literal_base = 0x0100001000100101;
armvixlad96eda2013-06-14 11:42:37 +01009516 static uint64_t const literal_base_hi = literal_base >> 32;
9517 static uint64_t const literal_base_lo = literal_base & 0xffffffff;
9518 static uint64_t const literal_base_w = literal_base & 0xffffffff;
9519
9520 START();
9521 {
armvixlb0c8ae22014-03-21 14:03:59 +00009522 VIXL_ASSERT(__ StackPointer().Is(sp));
armvixlad96eda2013-06-14 11:42:37 +01009523 __ Mov(stack_pointer, __ StackPointer());
9524 __ SetStackPointer(stack_pointer);
9525
9526 // Initialize the registers.
9527 for (int i = 0; i < reg_count; i++) {
9528 // Always write into the X register, to ensure that the upper word is
9529 // properly ignored by Push when testing W registers.
9530 __ Mov(x[i], literal_base * i);
9531 }
9532
9533 // Claim memory first, as requested.
9534 __ Claim(claim);
9535
9536 // The push-pop pattern is as follows:
9537 // Push: Pop:
9538 // x[0](hi) -> w[0]
9539 // x[0](lo) -> x[1](hi)
9540 // w[1] -> x[1](lo)
9541 // w[1] -> w[2]
9542 // x[2](hi) -> x[2](hi)
9543 // x[2](lo) -> x[2](lo)
9544 // x[2](hi) -> w[3]
9545 // x[2](lo) -> x[4](hi)
9546 // x[2](hi) -> x[4](lo)
9547 // x[2](lo) -> w[5]
9548 // w[3] -> x[5](hi)
9549 // w[3] -> x[6](lo)
9550 // w[3] -> w[7]
9551 // w[3] -> x[8](hi)
9552 // x[4](hi) -> x[8](lo)
9553 // x[4](lo) -> w[9]
9554 // ... pattern continues ...
9555 //
9556 // That is, registers are pushed starting with the lower numbers,
9557 // alternating between x and w registers, and pushing i%4+1 copies of each,
9558 // where i is the register number.
9559 // Registers are popped starting with the higher numbers one-by-one,
9560 // alternating between x and w registers, but only popping one at a time.
9561 //
9562 // This pattern provides a wide variety of alignment effects and overlaps.
9563
9564 // ---- Push ----
9565
9566 int active_w_slots = 0;
9567 for (int i = 0; active_w_slots < requested_w_slots; i++) {
armvixlb0c8ae22014-03-21 14:03:59 +00009568 VIXL_ASSERT(i < reg_count);
armvixlad96eda2013-06-14 11:42:37 +01009569 // In order to test various arguments to PushMultipleTimes, and to try to
9570 // exercise different alignment and overlap effects, we push each
9571 // register a different number of times.
9572 int times = i % 4 + 1;
9573 if (i & 1) {
9574 // Push odd-numbered registers as W registers.
9575 __ PushMultipleTimes(times, w[i]);
9576 // Fill in the expected stack slots.
9577 for (int j = 0; j < times; j++) {
9578 if (w[i].Is(wzr)) {
9579 // The zero register always writes zeroes.
9580 stack[active_w_slots++] = 0;
9581 } else {
9582 stack[active_w_slots++] = literal_base_w * i;
9583 }
9584 }
9585 } else {
9586 // Push even-numbered registers as X registers.
9587 __ PushMultipleTimes(times, x[i]);
9588 // Fill in the expected stack slots.
9589 for (int j = 0; j < times; j++) {
9590 if (x[i].Is(xzr)) {
9591 // The zero register always writes zeroes.
9592 stack[active_w_slots++] = 0;
9593 stack[active_w_slots++] = 0;
9594 } else {
9595 stack[active_w_slots++] = literal_base_hi * i;
9596 stack[active_w_slots++] = literal_base_lo * i;
9597 }
9598 }
9599 }
9600 }
9601 // Because we were pushing several registers at a time, we probably pushed
9602 // more than we needed to.
9603 if (active_w_slots > requested_w_slots) {
9604 __ Drop((active_w_slots - requested_w_slots) * kWRegSizeInBytes);
9605 // Bump the number of active W-sized slots back to where it should be,
9606 // and fill the empty space with a dummy value.
9607 do {
9608 stack[active_w_slots--] = 0xdeadbeef;
9609 } while (active_w_slots > requested_w_slots);
9610 }
9611
9612 // ---- Pop ----
9613
9614 Clobber(&masm, list);
9615
9616 // If popping an even number of registers, the first one will be X-sized.
9617 // Otherwise, the first one will be W-sized.
9618 bool next_is_64 = !(reg_count & 1);
9619 for (int i = reg_count-1; i >= 0; i--) {
9620 if (next_is_64) {
9621 __ Pop(x[i]);
9622 active_w_slots -= 2;
9623 } else {
9624 __ Pop(w[i]);
9625 active_w_slots -= 1;
9626 }
9627 next_is_64 = !next_is_64;
9628 }
armvixlb0c8ae22014-03-21 14:03:59 +00009629 VIXL_ASSERT(active_w_slots == 0);
armvixlad96eda2013-06-14 11:42:37 +01009630
9631 // Drop memory to restore stack_pointer.
9632 __ Drop(claim);
9633
9634 __ Mov(sp, __ StackPointer());
9635 __ SetStackPointer(sp);
9636 }
9637
9638 END();
9639
9640 RUN();
9641
9642 int slot = 0;
9643 for (int i = 0; i < reg_count; i++) {
9644 // Even-numbered registers were written as W registers.
9645 // Odd-numbered registers were written as X registers.
9646 bool expect_64 = (i & 1);
9647 uint64_t expected;
9648
9649 if (expect_64) {
9650 uint64_t hi = stack[slot++];
9651 uint64_t lo = stack[slot++];
9652 expected = (hi << 32) | lo;
9653 } else {
9654 expected = stack[slot++];
9655 }
9656
9657 // Always use ASSERT_EQUAL_64, even when testing W registers, so we can
9658 // test that the upper word was properly cleared by Pop.
9659 if (x[i].Is(xzr)) {
9660 ASSERT_EQUAL_64(0, x[i]);
9661 } else {
9662 ASSERT_EQUAL_64(expected, x[i]);
9663 }
9664 }
armvixlb0c8ae22014-03-21 14:03:59 +00009665 VIXL_ASSERT(slot == requested_w_slots);
armvixlad96eda2013-06-14 11:42:37 +01009666
9667 TEARDOWN();
9668}
9669
9670
9671TEST(push_pop_xreg_wx_overlap) {
9672 for (int claim = 0; claim <= 8; claim++) {
9673 for (int count = 1; count <= 8; count++) {
9674 PushPopXRegWXOverlapHelper(count, claim);
9675 }
9676 // Test with the maximum number of registers.
9677 PushPopXRegWXOverlapHelper(kPushPopXRegMaxRegCount, claim);
9678 }
9679}
9680
9681
9682TEST(push_pop_sp) {
9683 SETUP();
9684
9685 START();
9686
armvixlb0c8ae22014-03-21 14:03:59 +00009687 VIXL_ASSERT(sp.Is(__ StackPointer()));
armvixlad96eda2013-06-14 11:42:37 +01009688
armvixlb0c8ae22014-03-21 14:03:59 +00009689 __ Mov(x3, 0x3333333333333333);
9690 __ Mov(x2, 0x2222222222222222);
9691 __ Mov(x1, 0x1111111111111111);
9692 __ Mov(x0, 0x0000000000000000);
armvixlad96eda2013-06-14 11:42:37 +01009693 __ Claim(2 * kXRegSizeInBytes);
9694 __ PushXRegList(x0.Bit() | x1.Bit() | x2.Bit() | x3.Bit());
9695 __ Push(x3, x2);
9696 __ PopXRegList(x0.Bit() | x1.Bit() | x2.Bit() | x3.Bit());
9697 __ Push(x2, x1, x3, x0);
9698 __ Pop(x4, x5);
9699 __ Pop(x6, x7, x8, x9);
9700
9701 __ Claim(2 * kXRegSizeInBytes);
9702 __ PushWRegList(w0.Bit() | w1.Bit() | w2.Bit() | w3.Bit());
9703 __ Push(w3, w1, w2, w0);
9704 __ PopWRegList(w10.Bit() | w11.Bit() | w12.Bit() | w13.Bit());
9705 __ Pop(w14, w15, w16, w17);
9706
9707 __ Claim(2 * kXRegSizeInBytes);
9708 __ Push(w2, w2, w1, w1);
9709 __ Push(x3, x3);
9710 __ Pop(w18, w19, w20, w21);
9711 __ Pop(x22, x23);
9712
9713 __ Claim(2 * kXRegSizeInBytes);
9714 __ PushXRegList(x1.Bit() | x22.Bit());
9715 __ PopXRegList(x24.Bit() | x26.Bit());
9716
9717 __ Claim(2 * kXRegSizeInBytes);
9718 __ PushWRegList(w1.Bit() | w2.Bit() | w4.Bit() | w22.Bit());
9719 __ PopWRegList(w25.Bit() | w27.Bit() | w28.Bit() | w29.Bit());
9720
9721 __ Claim(2 * kXRegSizeInBytes);
9722 __ PushXRegList(0);
9723 __ PopXRegList(0);
9724 __ PushXRegList(0xffffffff);
9725 __ PopXRegList(0xffffffff);
9726 __ Drop(12 * kXRegSizeInBytes);
9727 END();
9728
9729 RUN();
9730
armvixlb0c8ae22014-03-21 14:03:59 +00009731 ASSERT_EQUAL_64(0x1111111111111111, x3);
9732 ASSERT_EQUAL_64(0x0000000000000000, x2);
9733 ASSERT_EQUAL_64(0x3333333333333333, x1);
9734 ASSERT_EQUAL_64(0x2222222222222222, x0);
9735 ASSERT_EQUAL_64(0x3333333333333333, x9);
9736 ASSERT_EQUAL_64(0x2222222222222222, x8);
9737 ASSERT_EQUAL_64(0x0000000000000000, x7);
9738 ASSERT_EQUAL_64(0x3333333333333333, x6);
9739 ASSERT_EQUAL_64(0x1111111111111111, x5);
9740 ASSERT_EQUAL_64(0x2222222222222222, x4);
armvixlad96eda2013-06-14 11:42:37 +01009741
9742 ASSERT_EQUAL_32(0x11111111U, w13);
9743 ASSERT_EQUAL_32(0x33333333U, w12);
9744 ASSERT_EQUAL_32(0x00000000U, w11);
9745 ASSERT_EQUAL_32(0x22222222U, w10);
9746 ASSERT_EQUAL_32(0x11111111U, w17);
9747 ASSERT_EQUAL_32(0x00000000U, w16);
9748 ASSERT_EQUAL_32(0x33333333U, w15);
9749 ASSERT_EQUAL_32(0x22222222U, w14);
9750
9751 ASSERT_EQUAL_32(0x11111111U, w18);
9752 ASSERT_EQUAL_32(0x11111111U, w19);
9753 ASSERT_EQUAL_32(0x11111111U, w20);
9754 ASSERT_EQUAL_32(0x11111111U, w21);
armvixlb0c8ae22014-03-21 14:03:59 +00009755 ASSERT_EQUAL_64(0x3333333333333333, x22);
9756 ASSERT_EQUAL_64(0x0000000000000000, x23);
armvixlad96eda2013-06-14 11:42:37 +01009757
armvixlb0c8ae22014-03-21 14:03:59 +00009758 ASSERT_EQUAL_64(0x3333333333333333, x24);
9759 ASSERT_EQUAL_64(0x3333333333333333, x26);
armvixlad96eda2013-06-14 11:42:37 +01009760
9761 ASSERT_EQUAL_32(0x33333333U, w25);
9762 ASSERT_EQUAL_32(0x00000000U, w27);
9763 ASSERT_EQUAL_32(0x22222222U, w28);
9764 ASSERT_EQUAL_32(0x33333333U, w29);
9765 TEARDOWN();
9766}
9767
9768
9769TEST(noreg) {
9770 // This test doesn't generate any code, but it verifies some invariants
9771 // related to NoReg.
armvixlb0c8ae22014-03-21 14:03:59 +00009772 VIXL_CHECK(NoReg.Is(NoFPReg));
9773 VIXL_CHECK(NoFPReg.Is(NoReg));
9774 VIXL_CHECK(NoReg.Is(NoCPUReg));
9775 VIXL_CHECK(NoCPUReg.Is(NoReg));
9776 VIXL_CHECK(NoFPReg.Is(NoCPUReg));
9777 VIXL_CHECK(NoCPUReg.Is(NoFPReg));
armvixlad96eda2013-06-14 11:42:37 +01009778
armvixlb0c8ae22014-03-21 14:03:59 +00009779 VIXL_CHECK(NoReg.IsNone());
9780 VIXL_CHECK(NoFPReg.IsNone());
9781 VIXL_CHECK(NoCPUReg.IsNone());
armvixlad96eda2013-06-14 11:42:37 +01009782}
9783
9784
9785TEST(isvalid) {
9786 // This test doesn't generate any code, but it verifies some invariants
9787 // related to IsValid().
armvixlb0c8ae22014-03-21 14:03:59 +00009788 VIXL_CHECK(!NoReg.IsValid());
9789 VIXL_CHECK(!NoFPReg.IsValid());
9790 VIXL_CHECK(!NoCPUReg.IsValid());
armvixlad96eda2013-06-14 11:42:37 +01009791
armvixlb0c8ae22014-03-21 14:03:59 +00009792 VIXL_CHECK(x0.IsValid());
9793 VIXL_CHECK(w0.IsValid());
9794 VIXL_CHECK(x30.IsValid());
9795 VIXL_CHECK(w30.IsValid());
9796 VIXL_CHECK(xzr.IsValid());
9797 VIXL_CHECK(wzr.IsValid());
armvixlad96eda2013-06-14 11:42:37 +01009798
armvixlb0c8ae22014-03-21 14:03:59 +00009799 VIXL_CHECK(sp.IsValid());
9800 VIXL_CHECK(wsp.IsValid());
armvixlad96eda2013-06-14 11:42:37 +01009801
armvixlb0c8ae22014-03-21 14:03:59 +00009802 VIXL_CHECK(d0.IsValid());
9803 VIXL_CHECK(s0.IsValid());
9804 VIXL_CHECK(d31.IsValid());
9805 VIXL_CHECK(s31.IsValid());
armvixlad96eda2013-06-14 11:42:37 +01009806
armvixlb0c8ae22014-03-21 14:03:59 +00009807 VIXL_CHECK(x0.IsValidRegister());
9808 VIXL_CHECK(w0.IsValidRegister());
9809 VIXL_CHECK(xzr.IsValidRegister());
9810 VIXL_CHECK(wzr.IsValidRegister());
9811 VIXL_CHECK(sp.IsValidRegister());
9812 VIXL_CHECK(wsp.IsValidRegister());
9813 VIXL_CHECK(!x0.IsValidFPRegister());
9814 VIXL_CHECK(!w0.IsValidFPRegister());
9815 VIXL_CHECK(!xzr.IsValidFPRegister());
9816 VIXL_CHECK(!wzr.IsValidFPRegister());
9817 VIXL_CHECK(!sp.IsValidFPRegister());
9818 VIXL_CHECK(!wsp.IsValidFPRegister());
armvixlad96eda2013-06-14 11:42:37 +01009819
armvixlb0c8ae22014-03-21 14:03:59 +00009820 VIXL_CHECK(d0.IsValidFPRegister());
9821 VIXL_CHECK(s0.IsValidFPRegister());
9822 VIXL_CHECK(!d0.IsValidRegister());
9823 VIXL_CHECK(!s0.IsValidRegister());
armvixlad96eda2013-06-14 11:42:37 +01009824
9825 // Test the same as before, but using CPURegister types. This shouldn't make
9826 // any difference.
armvixlb0c8ae22014-03-21 14:03:59 +00009827 VIXL_CHECK(static_cast<CPURegister>(x0).IsValid());
9828 VIXL_CHECK(static_cast<CPURegister>(w0).IsValid());
9829 VIXL_CHECK(static_cast<CPURegister>(x30).IsValid());
9830 VIXL_CHECK(static_cast<CPURegister>(w30).IsValid());
9831 VIXL_CHECK(static_cast<CPURegister>(xzr).IsValid());
9832 VIXL_CHECK(static_cast<CPURegister>(wzr).IsValid());
armvixlad96eda2013-06-14 11:42:37 +01009833
armvixlb0c8ae22014-03-21 14:03:59 +00009834 VIXL_CHECK(static_cast<CPURegister>(sp).IsValid());
9835 VIXL_CHECK(static_cast<CPURegister>(wsp).IsValid());
armvixlad96eda2013-06-14 11:42:37 +01009836
armvixlb0c8ae22014-03-21 14:03:59 +00009837 VIXL_CHECK(static_cast<CPURegister>(d0).IsValid());
9838 VIXL_CHECK(static_cast<CPURegister>(s0).IsValid());
9839 VIXL_CHECK(static_cast<CPURegister>(d31).IsValid());
9840 VIXL_CHECK(static_cast<CPURegister>(s31).IsValid());
armvixlad96eda2013-06-14 11:42:37 +01009841
armvixlb0c8ae22014-03-21 14:03:59 +00009842 VIXL_CHECK(static_cast<CPURegister>(x0).IsValidRegister());
9843 VIXL_CHECK(static_cast<CPURegister>(w0).IsValidRegister());
9844 VIXL_CHECK(static_cast<CPURegister>(xzr).IsValidRegister());
9845 VIXL_CHECK(static_cast<CPURegister>(wzr).IsValidRegister());
9846 VIXL_CHECK(static_cast<CPURegister>(sp).IsValidRegister());
9847 VIXL_CHECK(static_cast<CPURegister>(wsp).IsValidRegister());
9848 VIXL_CHECK(!static_cast<CPURegister>(x0).IsValidFPRegister());
9849 VIXL_CHECK(!static_cast<CPURegister>(w0).IsValidFPRegister());
9850 VIXL_CHECK(!static_cast<CPURegister>(xzr).IsValidFPRegister());
9851 VIXL_CHECK(!static_cast<CPURegister>(wzr).IsValidFPRegister());
9852 VIXL_CHECK(!static_cast<CPURegister>(sp).IsValidFPRegister());
9853 VIXL_CHECK(!static_cast<CPURegister>(wsp).IsValidFPRegister());
armvixlad96eda2013-06-14 11:42:37 +01009854
armvixlb0c8ae22014-03-21 14:03:59 +00009855 VIXL_CHECK(static_cast<CPURegister>(d0).IsValidFPRegister());
9856 VIXL_CHECK(static_cast<CPURegister>(s0).IsValidFPRegister());
9857 VIXL_CHECK(!static_cast<CPURegister>(d0).IsValidRegister());
9858 VIXL_CHECK(!static_cast<CPURegister>(s0).IsValidRegister());
armvixlad96eda2013-06-14 11:42:37 +01009859}
9860
9861
9862TEST(printf) {
armvixlc68cb642014-09-25 18:49:30 +01009863 SETUP();
armvixlad96eda2013-06-14 11:42:37 +01009864 START();
9865
9866 char const * test_plain_string = "Printf with no arguments.\n";
9867 char const * test_substring = "'This is a substring.'";
9868 RegisterDump before;
9869
9870 // Initialize x29 to the value of the stack pointer. We will use x29 as a
9871 // temporary stack pointer later, and initializing it in this way allows the
9872 // RegisterDump check to pass.
9873 __ Mov(x29, __ StackPointer());
9874
9875 // Test simple integer arguments.
9876 __ Mov(x0, 1234);
9877 __ Mov(x1, 0x1234);
9878
9879 // Test simple floating-point arguments.
9880 __ Fmov(d0, 1.234);
9881
9882 // Test pointer (string) arguments.
9883 __ Mov(x2, reinterpret_cast<uintptr_t>(test_substring));
9884
9885 // Test the maximum number of arguments, and sign extension.
9886 __ Mov(w3, 0xffffffff);
9887 __ Mov(w4, 0xffffffff);
9888 __ Mov(x5, 0xffffffffffffffff);
9889 __ Mov(x6, 0xffffffffffffffff);
9890 __ Fmov(s1, 1.234);
9891 __ Fmov(s2, 2.345);
9892 __ Fmov(d3, 3.456);
9893 __ Fmov(d4, 4.567);
9894
9895 // Test printing callee-saved registers.
9896 __ Mov(x28, 0x123456789abcdef);
9897 __ Fmov(d10, 42.0);
9898
9899 // Test with three arguments.
9900 __ Mov(x10, 3);
9901 __ Mov(x11, 40);
9902 __ Mov(x12, 500);
9903
armvixl5799d6c2014-05-01 11:05:00 +01009904 // A single character.
9905 __ Mov(w13, 'x');
9906
9907 // Check that we don't clobber any registers.
armvixlad96eda2013-06-14 11:42:37 +01009908 before.Dump(&masm);
9909
9910 __ Printf(test_plain_string); // NOLINT(runtime/printf)
armvixl5799d6c2014-05-01 11:05:00 +01009911 __ Printf("x0: %" PRId64 ", x1: 0x%08" PRIx64 "\n", x0, x1);
9912 __ Printf("w5: %" PRId32 ", x5: %" PRId64"\n", w5, x5);
armvixlad96eda2013-06-14 11:42:37 +01009913 __ Printf("d0: %f\n", d0);
9914 __ Printf("Test %%s: %s\n", x2);
9915 __ Printf("w3(uint32): %" PRIu32 "\nw4(int32): %" PRId32 "\n"
9916 "x5(uint64): %" PRIu64 "\nx6(int64): %" PRId64 "\n",
9917 w3, w4, x5, x6);
9918 __ Printf("%%f: %f\n%%g: %g\n%%e: %e\n%%E: %E\n", s1, s2, d3, d4);
armvixl5799d6c2014-05-01 11:05:00 +01009919 __ Printf("0x%" PRIx32 ", 0x%" PRIx64 "\n", w28, x28);
armvixlad96eda2013-06-14 11:42:37 +01009920 __ Printf("%g\n", d10);
armvixl5799d6c2014-05-01 11:05:00 +01009921 __ Printf("%%%%%s%%%c%%\n", x2, w13);
9922
9923 // Print the stack pointer (sp).
9924 __ Printf("StackPointer(sp): 0x%016" PRIx64 ", 0x%08" PRIx32 "\n",
9925 __ StackPointer(), __ StackPointer().W());
armvixlad96eda2013-06-14 11:42:37 +01009926
9927 // Test with a different stack pointer.
9928 const Register old_stack_pointer = __ StackPointer();
armvixl5799d6c2014-05-01 11:05:00 +01009929 __ Mov(x29, old_stack_pointer);
armvixlad96eda2013-06-14 11:42:37 +01009930 __ SetStackPointer(x29);
armvixl5799d6c2014-05-01 11:05:00 +01009931 // Print the stack pointer (not sp).
9932 __ Printf("StackPointer(not sp): 0x%016" PRIx64 ", 0x%08" PRIx32 "\n",
9933 __ StackPointer(), __ StackPointer().W());
9934 __ Mov(old_stack_pointer, __ StackPointer());
armvixlad96eda2013-06-14 11:42:37 +01009935 __ SetStackPointer(old_stack_pointer);
9936
armvixl5799d6c2014-05-01 11:05:00 +01009937 // Test with three arguments.
armvixlad96eda2013-06-14 11:42:37 +01009938 __ Printf("3=%u, 4=%u, 5=%u\n", x10, x11, x12);
9939
armvixl5799d6c2014-05-01 11:05:00 +01009940 // Mixed argument types.
9941 __ Printf("w3: %" PRIu32 ", s1: %f, x5: %" PRIu64 ", d3: %f\n",
9942 w3, s1, x5, d3);
9943 __ Printf("s1: %f, d3: %f, w3: %" PRId32 ", x5: %" PRId64 "\n",
9944 s1, d3, w3, x5);
9945
armvixlad96eda2013-06-14 11:42:37 +01009946 END();
9947 RUN();
9948
9949 // We cannot easily test the output of the Printf sequences, and because
9950 // Printf preserves all registers by default, we can't look at the number of
9951 // bytes that were printed. However, the printf_no_preserve test should check
9952 // that, and here we just test that we didn't clobber any registers.
9953 ASSERT_EQUAL_REGISTERS(before);
9954
9955 TEARDOWN();
armvixlad96eda2013-06-14 11:42:37 +01009956}
9957
9958
9959TEST(printf_no_preserve) {
armvixlad96eda2013-06-14 11:42:37 +01009960 SETUP();
9961 START();
9962
9963 char const * test_plain_string = "Printf with no arguments.\n";
9964 char const * test_substring = "'This is a substring.'";
9965
9966 __ PrintfNoPreserve(test_plain_string);
9967 __ Mov(x19, x0);
9968
9969 // Test simple integer arguments.
9970 __ Mov(x0, 1234);
9971 __ Mov(x1, 0x1234);
9972 __ PrintfNoPreserve("x0: %" PRId64", x1: 0x%08" PRIx64 "\n", x0, x1);
9973 __ Mov(x20, x0);
9974
9975 // Test simple floating-point arguments.
9976 __ Fmov(d0, 1.234);
9977 __ PrintfNoPreserve("d0: %f\n", d0);
9978 __ Mov(x21, x0);
9979
9980 // Test pointer (string) arguments.
9981 __ Mov(x2, reinterpret_cast<uintptr_t>(test_substring));
9982 __ PrintfNoPreserve("Test %%s: %s\n", x2);
9983 __ Mov(x22, x0);
9984
9985 // Test the maximum number of arguments, and sign extension.
9986 __ Mov(w3, 0xffffffff);
9987 __ Mov(w4, 0xffffffff);
9988 __ Mov(x5, 0xffffffffffffffff);
9989 __ Mov(x6, 0xffffffffffffffff);
9990 __ PrintfNoPreserve("w3(uint32): %" PRIu32 "\nw4(int32): %" PRId32 "\n"
9991 "x5(uint64): %" PRIu64 "\nx6(int64): %" PRId64 "\n",
9992 w3, w4, x5, x6);
9993 __ Mov(x23, x0);
9994
9995 __ Fmov(s1, 1.234);
9996 __ Fmov(s2, 2.345);
9997 __ Fmov(d3, 3.456);
9998 __ Fmov(d4, 4.567);
9999 __ PrintfNoPreserve("%%f: %f\n%%g: %g\n%%e: %e\n%%E: %E\n", s1, s2, d3, d4);
10000 __ Mov(x24, x0);
10001
10002 // Test printing callee-saved registers.
10003 __ Mov(x28, 0x123456789abcdef);
armvixl5799d6c2014-05-01 11:05:00 +010010004 __ PrintfNoPreserve("0x%" PRIx32 ", 0x%" PRIx64 "\n", w28, x28);
armvixlad96eda2013-06-14 11:42:37 +010010005 __ Mov(x25, x0);
10006
10007 __ Fmov(d10, 42.0);
10008 __ PrintfNoPreserve("%g\n", d10);
10009 __ Mov(x26, x0);
10010
10011 // Test with a different stack pointer.
10012 const Register old_stack_pointer = __ StackPointer();
10013 __ Mov(x29, old_stack_pointer);
10014 __ SetStackPointer(x29);
armvixl5799d6c2014-05-01 11:05:00 +010010015 // Print the stack pointer (not sp).
10016 __ PrintfNoPreserve(
10017 "StackPointer(not sp): 0x%016" PRIx64 ", 0x%08" PRIx32 "\n",
10018 __ StackPointer(), __ StackPointer().W());
armvixlad96eda2013-06-14 11:42:37 +010010019 __ Mov(x27, x0);
armvixlad96eda2013-06-14 11:42:37 +010010020 __ Mov(old_stack_pointer, __ StackPointer());
10021 __ SetStackPointer(old_stack_pointer);
10022
10023 // Test with three arguments.
10024 __ Mov(x3, 3);
10025 __ Mov(x4, 40);
10026 __ Mov(x5, 500);
10027 __ PrintfNoPreserve("3=%u, 4=%u, 5=%u\n", x3, x4, x5);
10028 __ Mov(x28, x0);
10029
armvixl5799d6c2014-05-01 11:05:00 +010010030 // Mixed argument types.
10031 __ Mov(w3, 0xffffffff);
10032 __ Fmov(s1, 1.234);
10033 __ Mov(x5, 0xffffffffffffffff);
10034 __ Fmov(d3, 3.456);
10035 __ PrintfNoPreserve("w3: %" PRIu32 ", s1: %f, x5: %" PRIu64 ", d3: %f\n",
10036 w3, s1, x5, d3);
10037 __ Mov(x29, x0);
10038
armvixlad96eda2013-06-14 11:42:37 +010010039 END();
10040 RUN();
10041
10042 // We cannot easily test the exact output of the Printf sequences, but we can
10043 // use the return code to check that the string length was correct.
10044
10045 // Printf with no arguments.
10046 ASSERT_EQUAL_64(strlen(test_plain_string), x19);
10047 // x0: 1234, x1: 0x00001234
10048 ASSERT_EQUAL_64(25, x20);
10049 // d0: 1.234000
10050 ASSERT_EQUAL_64(13, x21);
10051 // Test %s: 'This is a substring.'
10052 ASSERT_EQUAL_64(32, x22);
10053 // w3(uint32): 4294967295
10054 // w4(int32): -1
10055 // x5(uint64): 18446744073709551615
10056 // x6(int64): -1
10057 ASSERT_EQUAL_64(23 + 14 + 33 + 14, x23);
10058 // %f: 1.234000
10059 // %g: 2.345
10060 // %e: 3.456000e+00
10061 // %E: 4.567000E+00
10062 ASSERT_EQUAL_64(13 + 10 + 17 + 17, x24);
armvixl5799d6c2014-05-01 11:05:00 +010010063 // 0x89abcdef, 0x123456789abcdef
10064 ASSERT_EQUAL_64(30, x25);
armvixlad96eda2013-06-14 11:42:37 +010010065 // 42
10066 ASSERT_EQUAL_64(3, x26);
armvixl5799d6c2014-05-01 11:05:00 +010010067 // StackPointer(not sp): 0x00007fb037ae2370, 0x37ae2370
armvixlad96eda2013-06-14 11:42:37 +010010068 // Note: This is an example value, but the field width is fixed here so the
10069 // string length is still predictable.
armvixl5799d6c2014-05-01 11:05:00 +010010070 ASSERT_EQUAL_64(53, x27);
armvixlad96eda2013-06-14 11:42:37 +010010071 // 3=3, 4=40, 5=500
10072 ASSERT_EQUAL_64(17, x28);
armvixl5799d6c2014-05-01 11:05:00 +010010073 // w3: 4294967295, s1: 1.234000, x5: 18446744073709551615, d3: 3.456000
10074 ASSERT_EQUAL_64(69, x29);
armvixlad96eda2013-06-14 11:42:37 +010010075
10076 TEARDOWN();
armvixlad96eda2013-06-14 11:42:37 +010010077}
10078
10079
10080#ifndef USE_SIMULATOR
10081TEST(trace) {
10082 // The Trace helper should not generate any code unless the simulator (or
10083 // debugger) is being used.
10084 SETUP();
10085 START();
10086
10087 Label start;
10088 __ Bind(&start);
10089 __ Trace(LOG_ALL, TRACE_ENABLE);
10090 __ Trace(LOG_ALL, TRACE_DISABLE);
armvixlb0c8ae22014-03-21 14:03:59 +000010091 VIXL_CHECK(__ SizeOfCodeGeneratedSince(&start) == 0);
armvixlad96eda2013-06-14 11:42:37 +010010092
10093 END();
10094 TEARDOWN();
10095}
10096#endif
10097
10098
10099#ifndef USE_SIMULATOR
10100TEST(log) {
10101 // The Log helper should not generate any code unless the simulator (or
10102 // debugger) is being used.
10103 SETUP();
10104 START();
10105
10106 Label start;
10107 __ Bind(&start);
10108 __ Log(LOG_ALL);
armvixlb0c8ae22014-03-21 14:03:59 +000010109 VIXL_CHECK(__ SizeOfCodeGeneratedSince(&start) == 0);
armvixlad96eda2013-06-14 11:42:37 +010010110
10111 END();
10112 TEARDOWN();
10113}
10114#endif
10115
10116
10117TEST(instruction_accurate_scope) {
10118 SETUP();
10119 START();
10120
10121 // By default macro instructions are allowed.
armvixlb0c8ae22014-03-21 14:03:59 +000010122 VIXL_ASSERT(masm.AllowMacroInstructions());
armvixlad96eda2013-06-14 11:42:37 +010010123 {
armvixlc68cb642014-09-25 18:49:30 +010010124 InstructionAccurateScope scope1(&masm, 2);
armvixlb0c8ae22014-03-21 14:03:59 +000010125 VIXL_ASSERT(!masm.AllowMacroInstructions());
armvixlc68cb642014-09-25 18:49:30 +010010126 __ nop();
armvixlad96eda2013-06-14 11:42:37 +010010127 {
armvixlc68cb642014-09-25 18:49:30 +010010128 InstructionAccurateScope scope2(&masm, 1);
armvixlb0c8ae22014-03-21 14:03:59 +000010129 VIXL_ASSERT(!masm.AllowMacroInstructions());
armvixlc68cb642014-09-25 18:49:30 +010010130 __ nop();
armvixlad96eda2013-06-14 11:42:37 +010010131 }
armvixlb0c8ae22014-03-21 14:03:59 +000010132 VIXL_ASSERT(!masm.AllowMacroInstructions());
armvixlad96eda2013-06-14 11:42:37 +010010133 }
armvixlb0c8ae22014-03-21 14:03:59 +000010134 VIXL_ASSERT(masm.AllowMacroInstructions());
armvixlad96eda2013-06-14 11:42:37 +010010135
10136 {
10137 InstructionAccurateScope scope(&masm, 2);
10138 __ add(x0, x0, x0);
10139 __ sub(x0, x0, x0);
10140 }
10141
10142 END();
10143 RUN();
10144 TEARDOWN();
10145}
10146
10147
10148TEST(blr_lr) {
10149 // A simple test to check that the simulator correcty handle "blr lr".
10150 SETUP();
10151
10152 START();
10153 Label target;
10154 Label end;
10155
10156 __ Mov(x0, 0x0);
10157 __ Adr(lr, &target);
10158
10159 __ Blr(lr);
10160 __ Mov(x0, 0xdeadbeef);
10161 __ B(&end);
10162
10163 __ Bind(&target);
10164 __ Mov(x0, 0xc001c0de);
10165
10166 __ Bind(&end);
10167 END();
10168
10169 RUN();
10170
10171 ASSERT_EQUAL_64(0xc001c0de, x0);
10172
10173 TEARDOWN();
10174}
10175
armvixlf37fdc02014-02-05 13:22:16 +000010176
10177TEST(barriers) {
10178 // Generate all supported barriers, this is just a smoke test
10179 SETUP();
10180
10181 START();
10182
10183 // DMB
10184 __ Dmb(FullSystem, BarrierAll);
10185 __ Dmb(FullSystem, BarrierReads);
10186 __ Dmb(FullSystem, BarrierWrites);
10187 __ Dmb(FullSystem, BarrierOther);
10188
10189 __ Dmb(InnerShareable, BarrierAll);
10190 __ Dmb(InnerShareable, BarrierReads);
10191 __ Dmb(InnerShareable, BarrierWrites);
10192 __ Dmb(InnerShareable, BarrierOther);
10193
10194 __ Dmb(NonShareable, BarrierAll);
10195 __ Dmb(NonShareable, BarrierReads);
10196 __ Dmb(NonShareable, BarrierWrites);
10197 __ Dmb(NonShareable, BarrierOther);
10198
10199 __ Dmb(OuterShareable, BarrierAll);
10200 __ Dmb(OuterShareable, BarrierReads);
10201 __ Dmb(OuterShareable, BarrierWrites);
10202 __ Dmb(OuterShareable, BarrierOther);
10203
10204 // DSB
10205 __ Dsb(FullSystem, BarrierAll);
10206 __ Dsb(FullSystem, BarrierReads);
10207 __ Dsb(FullSystem, BarrierWrites);
10208 __ Dsb(FullSystem, BarrierOther);
10209
10210 __ Dsb(InnerShareable, BarrierAll);
10211 __ Dsb(InnerShareable, BarrierReads);
10212 __ Dsb(InnerShareable, BarrierWrites);
10213 __ Dsb(InnerShareable, BarrierOther);
10214
10215 __ Dsb(NonShareable, BarrierAll);
10216 __ Dsb(NonShareable, BarrierReads);
10217 __ Dsb(NonShareable, BarrierWrites);
10218 __ Dsb(NonShareable, BarrierOther);
10219
10220 __ Dsb(OuterShareable, BarrierAll);
10221 __ Dsb(OuterShareable, BarrierReads);
10222 __ Dsb(OuterShareable, BarrierWrites);
10223 __ Dsb(OuterShareable, BarrierOther);
10224
10225 // ISB
10226 __ Isb();
10227
10228 END();
10229
10230 RUN();
10231
10232 TEARDOWN();
10233}
10234
armvixlb0c8ae22014-03-21 14:03:59 +000010235
10236TEST(process_nan_double) {
10237 // Make sure that NaN propagation works correctly.
10238 double sn = rawbits_to_double(0x7ff5555511111111);
10239 double qn = rawbits_to_double(0x7ffaaaaa11111111);
10240 VIXL_ASSERT(IsSignallingNaN(sn));
10241 VIXL_ASSERT(IsQuietNaN(qn));
10242
10243 // The input NaNs after passing through ProcessNaN.
10244 double sn_proc = rawbits_to_double(0x7ffd555511111111);
10245 double qn_proc = qn;
10246 VIXL_ASSERT(IsQuietNaN(sn_proc));
10247 VIXL_ASSERT(IsQuietNaN(qn_proc));
10248
10249 SETUP();
10250 START();
10251
10252 // Execute a number of instructions which all use ProcessNaN, and check that
10253 // they all handle the NaN correctly.
10254 __ Fmov(d0, sn);
10255 __ Fmov(d10, qn);
10256
10257 // Operations that always propagate NaNs unchanged, even signalling NaNs.
10258 // - Signalling NaN
10259 __ Fmov(d1, d0);
10260 __ Fabs(d2, d0);
10261 __ Fneg(d3, d0);
10262 // - Quiet NaN
10263 __ Fmov(d11, d10);
10264 __ Fabs(d12, d10);
10265 __ Fneg(d13, d10);
10266
10267 // Operations that use ProcessNaN.
10268 // - Signalling NaN
10269 __ Fsqrt(d4, d0);
10270 __ Frinta(d5, d0);
10271 __ Frintn(d6, d0);
10272 __ Frintz(d7, d0);
10273 // - Quiet NaN
10274 __ Fsqrt(d14, d10);
10275 __ Frinta(d15, d10);
10276 __ Frintn(d16, d10);
10277 __ Frintz(d17, d10);
10278
10279 // The behaviour of fcvt is checked in TEST(fcvt_sd).
10280
10281 END();
10282 RUN();
10283
10284 uint64_t qn_raw = double_to_rawbits(qn);
10285 uint64_t sn_raw = double_to_rawbits(sn);
10286
10287 // - Signalling NaN
10288 ASSERT_EQUAL_FP64(sn, d1);
10289 ASSERT_EQUAL_FP64(rawbits_to_double(sn_raw & ~kDSignMask), d2);
10290 ASSERT_EQUAL_FP64(rawbits_to_double(sn_raw ^ kDSignMask), d3);
10291 // - Quiet NaN
10292 ASSERT_EQUAL_FP64(qn, d11);
10293 ASSERT_EQUAL_FP64(rawbits_to_double(qn_raw & ~kDSignMask), d12);
10294 ASSERT_EQUAL_FP64(rawbits_to_double(qn_raw ^ kDSignMask), d13);
10295
10296 // - Signalling NaN
10297 ASSERT_EQUAL_FP64(sn_proc, d4);
10298 ASSERT_EQUAL_FP64(sn_proc, d5);
10299 ASSERT_EQUAL_FP64(sn_proc, d6);
10300 ASSERT_EQUAL_FP64(sn_proc, d7);
10301 // - Quiet NaN
10302 ASSERT_EQUAL_FP64(qn_proc, d14);
10303 ASSERT_EQUAL_FP64(qn_proc, d15);
10304 ASSERT_EQUAL_FP64(qn_proc, d16);
10305 ASSERT_EQUAL_FP64(qn_proc, d17);
10306
10307 TEARDOWN();
10308}
10309
10310
10311TEST(process_nan_float) {
10312 // Make sure that NaN propagation works correctly.
10313 float sn = rawbits_to_float(0x7f951111);
10314 float qn = rawbits_to_float(0x7fea1111);
10315 VIXL_ASSERT(IsSignallingNaN(sn));
10316 VIXL_ASSERT(IsQuietNaN(qn));
10317
10318 // The input NaNs after passing through ProcessNaN.
10319 float sn_proc = rawbits_to_float(0x7fd51111);
10320 float qn_proc = qn;
10321 VIXL_ASSERT(IsQuietNaN(sn_proc));
10322 VIXL_ASSERT(IsQuietNaN(qn_proc));
10323
10324 SETUP();
10325 START();
10326
10327 // Execute a number of instructions which all use ProcessNaN, and check that
10328 // they all handle the NaN correctly.
10329 __ Fmov(s0, sn);
10330 __ Fmov(s10, qn);
10331
10332 // Operations that always propagate NaNs unchanged, even signalling NaNs.
10333 // - Signalling NaN
10334 __ Fmov(s1, s0);
10335 __ Fabs(s2, s0);
10336 __ Fneg(s3, s0);
10337 // - Quiet NaN
10338 __ Fmov(s11, s10);
10339 __ Fabs(s12, s10);
10340 __ Fneg(s13, s10);
10341
10342 // Operations that use ProcessNaN.
10343 // - Signalling NaN
10344 __ Fsqrt(s4, s0);
10345 __ Frinta(s5, s0);
10346 __ Frintn(s6, s0);
10347 __ Frintz(s7, s0);
10348 // - Quiet NaN
10349 __ Fsqrt(s14, s10);
10350 __ Frinta(s15, s10);
10351 __ Frintn(s16, s10);
10352 __ Frintz(s17, s10);
10353
10354 // The behaviour of fcvt is checked in TEST(fcvt_sd).
10355
10356 END();
10357 RUN();
10358
10359 uint32_t qn_raw = float_to_rawbits(qn);
10360 uint32_t sn_raw = float_to_rawbits(sn);
10361
10362 // - Signalling NaN
10363 ASSERT_EQUAL_FP32(sn, s1);
10364 ASSERT_EQUAL_FP32(rawbits_to_float(sn_raw & ~kSSignMask), s2);
10365 ASSERT_EQUAL_FP32(rawbits_to_float(sn_raw ^ kSSignMask), s3);
10366 // - Quiet NaN
10367 ASSERT_EQUAL_FP32(qn, s11);
10368 ASSERT_EQUAL_FP32(rawbits_to_float(qn_raw & ~kSSignMask), s12);
10369 ASSERT_EQUAL_FP32(rawbits_to_float(qn_raw ^ kSSignMask), s13);
10370
10371 // - Signalling NaN
10372 ASSERT_EQUAL_FP32(sn_proc, s4);
10373 ASSERT_EQUAL_FP32(sn_proc, s5);
10374 ASSERT_EQUAL_FP32(sn_proc, s6);
10375 ASSERT_EQUAL_FP32(sn_proc, s7);
10376 // - Quiet NaN
10377 ASSERT_EQUAL_FP32(qn_proc, s14);
10378 ASSERT_EQUAL_FP32(qn_proc, s15);
10379 ASSERT_EQUAL_FP32(qn_proc, s16);
10380 ASSERT_EQUAL_FP32(qn_proc, s17);
10381
10382 TEARDOWN();
10383}
10384
10385
10386static void ProcessNaNsHelper(double n, double m, double expected) {
10387 VIXL_ASSERT(isnan(n) || isnan(m));
10388 VIXL_ASSERT(isnan(expected));
10389
10390 SETUP();
10391 START();
10392
10393 // Execute a number of instructions which all use ProcessNaNs, and check that
10394 // they all propagate NaNs correctly.
10395 __ Fmov(d0, n);
10396 __ Fmov(d1, m);
10397
10398 __ Fadd(d2, d0, d1);
10399 __ Fsub(d3, d0, d1);
10400 __ Fmul(d4, d0, d1);
10401 __ Fdiv(d5, d0, d1);
10402 __ Fmax(d6, d0, d1);
10403 __ Fmin(d7, d0, d1);
10404
10405 END();
10406 RUN();
10407
10408 ASSERT_EQUAL_FP64(expected, d2);
10409 ASSERT_EQUAL_FP64(expected, d3);
10410 ASSERT_EQUAL_FP64(expected, d4);
10411 ASSERT_EQUAL_FP64(expected, d5);
10412 ASSERT_EQUAL_FP64(expected, d6);
10413 ASSERT_EQUAL_FP64(expected, d7);
10414
10415 TEARDOWN();
10416}
10417
10418
10419TEST(process_nans_double) {
10420 // Make sure that NaN propagation works correctly.
10421 double sn = rawbits_to_double(0x7ff5555511111111);
10422 double sm = rawbits_to_double(0x7ff5555522222222);
10423 double qn = rawbits_to_double(0x7ffaaaaa11111111);
10424 double qm = rawbits_to_double(0x7ffaaaaa22222222);
10425 VIXL_ASSERT(IsSignallingNaN(sn));
10426 VIXL_ASSERT(IsSignallingNaN(sm));
10427 VIXL_ASSERT(IsQuietNaN(qn));
10428 VIXL_ASSERT(IsQuietNaN(qm));
10429
10430 // The input NaNs after passing through ProcessNaN.
10431 double sn_proc = rawbits_to_double(0x7ffd555511111111);
10432 double sm_proc = rawbits_to_double(0x7ffd555522222222);
10433 double qn_proc = qn;
10434 double qm_proc = qm;
10435 VIXL_ASSERT(IsQuietNaN(sn_proc));
10436 VIXL_ASSERT(IsQuietNaN(sm_proc));
10437 VIXL_ASSERT(IsQuietNaN(qn_proc));
10438 VIXL_ASSERT(IsQuietNaN(qm_proc));
10439
10440 // Quiet NaNs are propagated.
10441 ProcessNaNsHelper(qn, 0, qn_proc);
10442 ProcessNaNsHelper(0, qm, qm_proc);
10443 ProcessNaNsHelper(qn, qm, qn_proc);
10444
10445 // Signalling NaNs are propagated, and made quiet.
10446 ProcessNaNsHelper(sn, 0, sn_proc);
10447 ProcessNaNsHelper(0, sm, sm_proc);
10448 ProcessNaNsHelper(sn, sm, sn_proc);
10449
10450 // Signalling NaNs take precedence over quiet NaNs.
10451 ProcessNaNsHelper(sn, qm, sn_proc);
10452 ProcessNaNsHelper(qn, sm, sm_proc);
10453 ProcessNaNsHelper(sn, sm, sn_proc);
10454}
10455
10456
10457static void ProcessNaNsHelper(float n, float m, float expected) {
10458 VIXL_ASSERT(isnan(n) || isnan(m));
10459 VIXL_ASSERT(isnan(expected));
10460
10461 SETUP();
10462 START();
10463
10464 // Execute a number of instructions which all use ProcessNaNs, and check that
10465 // they all propagate NaNs correctly.
10466 __ Fmov(s0, n);
10467 __ Fmov(s1, m);
10468
10469 __ Fadd(s2, s0, s1);
10470 __ Fsub(s3, s0, s1);
10471 __ Fmul(s4, s0, s1);
10472 __ Fdiv(s5, s0, s1);
10473 __ Fmax(s6, s0, s1);
10474 __ Fmin(s7, s0, s1);
10475
10476 END();
10477 RUN();
10478
10479 ASSERT_EQUAL_FP32(expected, s2);
10480 ASSERT_EQUAL_FP32(expected, s3);
10481 ASSERT_EQUAL_FP32(expected, s4);
10482 ASSERT_EQUAL_FP32(expected, s5);
10483 ASSERT_EQUAL_FP32(expected, s6);
10484 ASSERT_EQUAL_FP32(expected, s7);
10485
10486 TEARDOWN();
10487}
10488
10489
10490TEST(process_nans_float) {
10491 // Make sure that NaN propagation works correctly.
10492 float sn = rawbits_to_float(0x7f951111);
10493 float sm = rawbits_to_float(0x7f952222);
10494 float qn = rawbits_to_float(0x7fea1111);
10495 float qm = rawbits_to_float(0x7fea2222);
10496 VIXL_ASSERT(IsSignallingNaN(sn));
10497 VIXL_ASSERT(IsSignallingNaN(sm));
10498 VIXL_ASSERT(IsQuietNaN(qn));
10499 VIXL_ASSERT(IsQuietNaN(qm));
10500
10501 // The input NaNs after passing through ProcessNaN.
10502 float sn_proc = rawbits_to_float(0x7fd51111);
10503 float sm_proc = rawbits_to_float(0x7fd52222);
10504 float qn_proc = qn;
10505 float qm_proc = qm;
10506 VIXL_ASSERT(IsQuietNaN(sn_proc));
10507 VIXL_ASSERT(IsQuietNaN(sm_proc));
10508 VIXL_ASSERT(IsQuietNaN(qn_proc));
10509 VIXL_ASSERT(IsQuietNaN(qm_proc));
10510
10511 // Quiet NaNs are propagated.
10512 ProcessNaNsHelper(qn, 0, qn_proc);
10513 ProcessNaNsHelper(0, qm, qm_proc);
10514 ProcessNaNsHelper(qn, qm, qn_proc);
10515
10516 // Signalling NaNs are propagated, and made quiet.
10517 ProcessNaNsHelper(sn, 0, sn_proc);
10518 ProcessNaNsHelper(0, sm, sm_proc);
10519 ProcessNaNsHelper(sn, sm, sn_proc);
10520
10521 // Signalling NaNs take precedence over quiet NaNs.
10522 ProcessNaNsHelper(sn, qm, sn_proc);
10523 ProcessNaNsHelper(qn, sm, sm_proc);
10524 ProcessNaNsHelper(sn, sm, sn_proc);
10525}
10526
10527
10528static void DefaultNaNHelper(float n, float m, float a) {
10529 VIXL_ASSERT(isnan(n) || isnan(m) || isnan(a));
10530
10531 bool test_1op = isnan(n);
10532 bool test_2op = isnan(n) || isnan(m);
10533
10534 SETUP();
10535 START();
10536
10537 // Enable Default-NaN mode in the FPCR.
10538 __ Mrs(x0, FPCR);
10539 __ Orr(x1, x0, DN_mask);
10540 __ Msr(FPCR, x1);
10541
10542 // Execute a number of instructions which all use ProcessNaNs, and check that
10543 // they all produce the default NaN.
10544 __ Fmov(s0, n);
10545 __ Fmov(s1, m);
10546 __ Fmov(s2, a);
10547
10548 if (test_1op) {
10549 // Operations that always propagate NaNs unchanged, even signalling NaNs.
10550 __ Fmov(s10, s0);
10551 __ Fabs(s11, s0);
10552 __ Fneg(s12, s0);
10553
10554 // Operations that use ProcessNaN.
10555 __ Fsqrt(s13, s0);
10556 __ Frinta(s14, s0);
10557 __ Frintn(s15, s0);
10558 __ Frintz(s16, s0);
10559
10560 // Fcvt usually has special NaN handling, but it respects default-NaN mode.
10561 __ Fcvt(d17, s0);
10562 }
10563
10564 if (test_2op) {
10565 __ Fadd(s18, s0, s1);
10566 __ Fsub(s19, s0, s1);
10567 __ Fmul(s20, s0, s1);
10568 __ Fdiv(s21, s0, s1);
10569 __ Fmax(s22, s0, s1);
10570 __ Fmin(s23, s0, s1);
10571 }
10572
10573 __ Fmadd(s24, s0, s1, s2);
10574 __ Fmsub(s25, s0, s1, s2);
10575 __ Fnmadd(s26, s0, s1, s2);
10576 __ Fnmsub(s27, s0, s1, s2);
10577
10578 // Restore FPCR.
10579 __ Msr(FPCR, x0);
10580
10581 END();
10582 RUN();
10583
10584 if (test_1op) {
10585 uint32_t n_raw = float_to_rawbits(n);
10586 ASSERT_EQUAL_FP32(n, s10);
10587 ASSERT_EQUAL_FP32(rawbits_to_float(n_raw & ~kSSignMask), s11);
10588 ASSERT_EQUAL_FP32(rawbits_to_float(n_raw ^ kSSignMask), s12);
10589 ASSERT_EQUAL_FP32(kFP32DefaultNaN, s13);
10590 ASSERT_EQUAL_FP32(kFP32DefaultNaN, s14);
10591 ASSERT_EQUAL_FP32(kFP32DefaultNaN, s15);
10592 ASSERT_EQUAL_FP32(kFP32DefaultNaN, s16);
10593 ASSERT_EQUAL_FP64(kFP64DefaultNaN, d17);
10594 }
10595
10596 if (test_2op) {
10597 ASSERT_EQUAL_FP32(kFP32DefaultNaN, s18);
10598 ASSERT_EQUAL_FP32(kFP32DefaultNaN, s19);
10599 ASSERT_EQUAL_FP32(kFP32DefaultNaN, s20);
10600 ASSERT_EQUAL_FP32(kFP32DefaultNaN, s21);
10601 ASSERT_EQUAL_FP32(kFP32DefaultNaN, s22);
10602 ASSERT_EQUAL_FP32(kFP32DefaultNaN, s23);
10603 }
10604
10605 ASSERT_EQUAL_FP32(kFP32DefaultNaN, s24);
10606 ASSERT_EQUAL_FP32(kFP32DefaultNaN, s25);
10607 ASSERT_EQUAL_FP32(kFP32DefaultNaN, s26);
10608 ASSERT_EQUAL_FP32(kFP32DefaultNaN, s27);
10609
10610 TEARDOWN();
10611}
10612
10613
10614TEST(default_nan_float) {
10615 float sn = rawbits_to_float(0x7f951111);
10616 float sm = rawbits_to_float(0x7f952222);
10617 float sa = rawbits_to_float(0x7f95aaaa);
10618 float qn = rawbits_to_float(0x7fea1111);
10619 float qm = rawbits_to_float(0x7fea2222);
10620 float qa = rawbits_to_float(0x7feaaaaa);
10621 VIXL_ASSERT(IsSignallingNaN(sn));
10622 VIXL_ASSERT(IsSignallingNaN(sm));
10623 VIXL_ASSERT(IsSignallingNaN(sa));
10624 VIXL_ASSERT(IsQuietNaN(qn));
10625 VIXL_ASSERT(IsQuietNaN(qm));
10626 VIXL_ASSERT(IsQuietNaN(qa));
10627
10628 // - Signalling NaNs
10629 DefaultNaNHelper(sn, 0.0f, 0.0f);
10630 DefaultNaNHelper(0.0f, sm, 0.0f);
10631 DefaultNaNHelper(0.0f, 0.0f, sa);
10632 DefaultNaNHelper(sn, sm, 0.0f);
10633 DefaultNaNHelper(0.0f, sm, sa);
10634 DefaultNaNHelper(sn, 0.0f, sa);
10635 DefaultNaNHelper(sn, sm, sa);
10636 // - Quiet NaNs
10637 DefaultNaNHelper(qn, 0.0f, 0.0f);
10638 DefaultNaNHelper(0.0f, qm, 0.0f);
10639 DefaultNaNHelper(0.0f, 0.0f, qa);
10640 DefaultNaNHelper(qn, qm, 0.0f);
10641 DefaultNaNHelper(0.0f, qm, qa);
10642 DefaultNaNHelper(qn, 0.0f, qa);
10643 DefaultNaNHelper(qn, qm, qa);
10644 // - Mixed NaNs
10645 DefaultNaNHelper(qn, sm, sa);
10646 DefaultNaNHelper(sn, qm, sa);
10647 DefaultNaNHelper(sn, sm, qa);
10648 DefaultNaNHelper(qn, qm, sa);
10649 DefaultNaNHelper(sn, qm, qa);
10650 DefaultNaNHelper(qn, sm, qa);
10651 DefaultNaNHelper(qn, qm, qa);
10652}
10653
10654
10655static void DefaultNaNHelper(double n, double m, double a) {
10656 VIXL_ASSERT(isnan(n) || isnan(m) || isnan(a));
10657
10658 bool test_1op = isnan(n);
10659 bool test_2op = isnan(n) || isnan(m);
10660
10661 SETUP();
10662 START();
10663
10664 // Enable Default-NaN mode in the FPCR.
10665 __ Mrs(x0, FPCR);
10666 __ Orr(x1, x0, DN_mask);
10667 __ Msr(FPCR, x1);
10668
10669 // Execute a number of instructions which all use ProcessNaNs, and check that
10670 // they all produce the default NaN.
10671 __ Fmov(d0, n);
10672 __ Fmov(d1, m);
10673 __ Fmov(d2, a);
10674
10675 if (test_1op) {
10676 // Operations that always propagate NaNs unchanged, even signalling NaNs.
10677 __ Fmov(d10, d0);
10678 __ Fabs(d11, d0);
10679 __ Fneg(d12, d0);
10680
10681 // Operations that use ProcessNaN.
10682 __ Fsqrt(d13, d0);
10683 __ Frinta(d14, d0);
10684 __ Frintn(d15, d0);
10685 __ Frintz(d16, d0);
10686
10687 // Fcvt usually has special NaN handling, but it respects default-NaN mode.
10688 __ Fcvt(s17, d0);
10689 }
10690
10691 if (test_2op) {
10692 __ Fadd(d18, d0, d1);
10693 __ Fsub(d19, d0, d1);
10694 __ Fmul(d20, d0, d1);
10695 __ Fdiv(d21, d0, d1);
10696 __ Fmax(d22, d0, d1);
10697 __ Fmin(d23, d0, d1);
10698 }
10699
10700 __ Fmadd(d24, d0, d1, d2);
10701 __ Fmsub(d25, d0, d1, d2);
10702 __ Fnmadd(d26, d0, d1, d2);
10703 __ Fnmsub(d27, d0, d1, d2);
10704
10705 // Restore FPCR.
10706 __ Msr(FPCR, x0);
10707
10708 END();
10709 RUN();
10710
10711 if (test_1op) {
10712 uint64_t n_raw = double_to_rawbits(n);
10713 ASSERT_EQUAL_FP64(n, d10);
10714 ASSERT_EQUAL_FP64(rawbits_to_double(n_raw & ~kDSignMask), d11);
10715 ASSERT_EQUAL_FP64(rawbits_to_double(n_raw ^ kDSignMask), d12);
10716 ASSERT_EQUAL_FP64(kFP64DefaultNaN, d13);
10717 ASSERT_EQUAL_FP64(kFP64DefaultNaN, d14);
10718 ASSERT_EQUAL_FP64(kFP64DefaultNaN, d15);
10719 ASSERT_EQUAL_FP64(kFP64DefaultNaN, d16);
10720 ASSERT_EQUAL_FP32(kFP32DefaultNaN, s17);
10721 }
10722
10723 if (test_2op) {
10724 ASSERT_EQUAL_FP64(kFP64DefaultNaN, d18);
10725 ASSERT_EQUAL_FP64(kFP64DefaultNaN, d19);
10726 ASSERT_EQUAL_FP64(kFP64DefaultNaN, d20);
10727 ASSERT_EQUAL_FP64(kFP64DefaultNaN, d21);
10728 ASSERT_EQUAL_FP64(kFP64DefaultNaN, d22);
10729 ASSERT_EQUAL_FP64(kFP64DefaultNaN, d23);
10730 }
10731
10732 ASSERT_EQUAL_FP64(kFP64DefaultNaN, d24);
10733 ASSERT_EQUAL_FP64(kFP64DefaultNaN, d25);
10734 ASSERT_EQUAL_FP64(kFP64DefaultNaN, d26);
10735 ASSERT_EQUAL_FP64(kFP64DefaultNaN, d27);
10736
10737 TEARDOWN();
10738}
10739
10740
10741TEST(default_nan_double) {
10742 double sn = rawbits_to_double(0x7ff5555511111111);
10743 double sm = rawbits_to_double(0x7ff5555522222222);
10744 double sa = rawbits_to_double(0x7ff55555aaaaaaaa);
10745 double qn = rawbits_to_double(0x7ffaaaaa11111111);
10746 double qm = rawbits_to_double(0x7ffaaaaa22222222);
10747 double qa = rawbits_to_double(0x7ffaaaaaaaaaaaaa);
10748 VIXL_ASSERT(IsSignallingNaN(sn));
10749 VIXL_ASSERT(IsSignallingNaN(sm));
10750 VIXL_ASSERT(IsSignallingNaN(sa));
10751 VIXL_ASSERT(IsQuietNaN(qn));
10752 VIXL_ASSERT(IsQuietNaN(qm));
10753 VIXL_ASSERT(IsQuietNaN(qa));
10754
10755 // - Signalling NaNs
10756 DefaultNaNHelper(sn, 0.0, 0.0);
10757 DefaultNaNHelper(0.0, sm, 0.0);
10758 DefaultNaNHelper(0.0, 0.0, sa);
10759 DefaultNaNHelper(sn, sm, 0.0);
10760 DefaultNaNHelper(0.0, sm, sa);
10761 DefaultNaNHelper(sn, 0.0, sa);
10762 DefaultNaNHelper(sn, sm, sa);
10763 // - Quiet NaNs
10764 DefaultNaNHelper(qn, 0.0, 0.0);
10765 DefaultNaNHelper(0.0, qm, 0.0);
10766 DefaultNaNHelper(0.0, 0.0, qa);
10767 DefaultNaNHelper(qn, qm, 0.0);
10768 DefaultNaNHelper(0.0, qm, qa);
10769 DefaultNaNHelper(qn, 0.0, qa);
10770 DefaultNaNHelper(qn, qm, qa);
10771 // - Mixed NaNs
10772 DefaultNaNHelper(qn, sm, sa);
10773 DefaultNaNHelper(sn, qm, sa);
10774 DefaultNaNHelper(sn, sm, qa);
10775 DefaultNaNHelper(qn, qm, sa);
10776 DefaultNaNHelper(sn, qm, qa);
10777 DefaultNaNHelper(qn, sm, qa);
10778 DefaultNaNHelper(qn, qm, qa);
10779}
10780
10781
armvixl4a102ba2014-07-14 09:02:40 +010010782TEST(ldar_stlr) {
10783 // The middle value is read, modified, and written. The padding exists only to
10784 // check for over-write.
10785 uint8_t b[] = {0, 0x12, 0};
10786 uint16_t h[] = {0, 0x1234, 0};
10787 uint32_t w[] = {0, 0x12345678, 0};
10788 uint64_t x[] = {0, 0x123456789abcdef0, 0};
10789
10790 SETUP();
10791 START();
10792
10793 __ Mov(x10, reinterpret_cast<uintptr_t>(&b[1]));
10794 __ Ldarb(w0, MemOperand(x10));
10795 __ Add(w0, w0, 1);
10796 __ Stlrb(w0, MemOperand(x10));
10797
10798 __ Mov(x10, reinterpret_cast<uintptr_t>(&h[1]));
10799 __ Ldarh(w0, MemOperand(x10));
10800 __ Add(w0, w0, 1);
10801 __ Stlrh(w0, MemOperand(x10));
10802
10803 __ Mov(x10, reinterpret_cast<uintptr_t>(&w[1]));
10804 __ Ldar(w0, MemOperand(x10));
10805 __ Add(w0, w0, 1);
10806 __ Stlr(w0, MemOperand(x10));
10807
10808 __ Mov(x10, reinterpret_cast<uintptr_t>(&x[1]));
10809 __ Ldar(x0, MemOperand(x10));
10810 __ Add(x0, x0, 1);
10811 __ Stlr(x0, MemOperand(x10));
10812
10813 END();
10814 RUN();
10815
10816 ASSERT_EQUAL_32(0x13, b[1]);
10817 ASSERT_EQUAL_32(0x1235, h[1]);
10818 ASSERT_EQUAL_32(0x12345679, w[1]);
10819 ASSERT_EQUAL_64(0x123456789abcdef1, x[1]);
10820
10821 // Check for over-write.
10822 ASSERT_EQUAL_32(0, b[0]);
10823 ASSERT_EQUAL_32(0, b[2]);
10824 ASSERT_EQUAL_32(0, h[0]);
10825 ASSERT_EQUAL_32(0, h[2]);
10826 ASSERT_EQUAL_32(0, w[0]);
10827 ASSERT_EQUAL_32(0, w[2]);
10828 ASSERT_EQUAL_32(0, x[0]);
10829 ASSERT_EQUAL_32(0, x[2]);
10830
10831 TEARDOWN();
10832}
10833
10834
10835TEST(ldxr_stxr) {
10836 // The middle value is read, modified, and written. The padding exists only to
10837 // check for over-write.
10838 uint8_t b[] = {0, 0x12, 0};
10839 uint16_t h[] = {0, 0x1234, 0};
10840 uint32_t w[] = {0, 0x12345678, 0};
10841 uint64_t x[] = {0, 0x123456789abcdef0, 0};
10842
10843 // As above, but get suitably-aligned values for ldxp and stxp.
10844 uint32_t wp_data[] = {0, 0, 0, 0, 0};
10845 uint32_t * wp = AlignUp(wp_data + 1, kWRegSizeInBytes * 2) - 1;
10846 wp[1] = 0x12345678; // wp[1] is 64-bit-aligned.
10847 wp[2] = 0x87654321;
10848 uint64_t xp_data[] = {0, 0, 0, 0, 0};
10849 uint64_t * xp = AlignUp(xp_data + 1, kXRegSizeInBytes * 2) - 1;
10850 xp[1] = 0x123456789abcdef0; // xp[1] is 128-bit-aligned.
10851 xp[2] = 0x0fedcba987654321;
10852
10853 SETUP();
10854 START();
10855
10856 __ Mov(x10, reinterpret_cast<uintptr_t>(&b[1]));
10857 Label try_b;
10858 __ Bind(&try_b);
10859 __ Ldxrb(w0, MemOperand(x10));
10860 __ Add(w0, w0, 1);
10861 __ Stxrb(w5, w0, MemOperand(x10));
10862 __ Cbnz(w5, &try_b);
10863
10864 __ Mov(x10, reinterpret_cast<uintptr_t>(&h[1]));
10865 Label try_h;
10866 __ Bind(&try_h);
10867 __ Ldxrh(w0, MemOperand(x10));
10868 __ Add(w0, w0, 1);
10869 __ Stxrh(w5, w0, MemOperand(x10));
10870 __ Cbnz(w5, &try_h);
10871
10872 __ Mov(x10, reinterpret_cast<uintptr_t>(&w[1]));
10873 Label try_w;
10874 __ Bind(&try_w);
10875 __ Ldxr(w0, MemOperand(x10));
10876 __ Add(w0, w0, 1);
10877 __ Stxr(w5, w0, MemOperand(x10));
10878 __ Cbnz(w5, &try_w);
10879
10880 __ Mov(x10, reinterpret_cast<uintptr_t>(&x[1]));
10881 Label try_x;
10882 __ Bind(&try_x);
10883 __ Ldxr(x0, MemOperand(x10));
10884 __ Add(x0, x0, 1);
10885 __ Stxr(w5, x0, MemOperand(x10));
10886 __ Cbnz(w5, &try_x);
10887
10888 __ Mov(x10, reinterpret_cast<uintptr_t>(&wp[1]));
10889 Label try_wp;
10890 __ Bind(&try_wp);
10891 __ Ldxp(w0, w1, MemOperand(x10));
10892 __ Add(w0, w0, 1);
10893 __ Add(w1, w1, 1);
10894 __ Stxp(w5, w0, w1, MemOperand(x10));
10895 __ Cbnz(w5, &try_wp);
10896
10897 __ Mov(x10, reinterpret_cast<uintptr_t>(&xp[1]));
10898 Label try_xp;
10899 __ Bind(&try_xp);
10900 __ Ldxp(x0, x1, MemOperand(x10));
10901 __ Add(x0, x0, 1);
10902 __ Add(x1, x1, 1);
10903 __ Stxp(w5, x0, x1, MemOperand(x10));
10904 __ Cbnz(w5, &try_xp);
10905
10906 END();
10907 RUN();
10908
10909 ASSERT_EQUAL_32(0x13, b[1]);
10910 ASSERT_EQUAL_32(0x1235, h[1]);
10911 ASSERT_EQUAL_32(0x12345679, w[1]);
10912 ASSERT_EQUAL_64(0x123456789abcdef1, x[1]);
10913 ASSERT_EQUAL_32(0x12345679, wp[1]);
10914 ASSERT_EQUAL_32(0x87654322, wp[2]);
10915 ASSERT_EQUAL_64(0x123456789abcdef1, xp[1]);
10916 ASSERT_EQUAL_64(0x0fedcba987654322, xp[2]);
10917
10918 // Check for over-write.
10919 ASSERT_EQUAL_32(0, b[0]);
10920 ASSERT_EQUAL_32(0, b[2]);
10921 ASSERT_EQUAL_32(0, h[0]);
10922 ASSERT_EQUAL_32(0, h[2]);
10923 ASSERT_EQUAL_32(0, w[0]);
10924 ASSERT_EQUAL_32(0, w[2]);
10925 ASSERT_EQUAL_64(0, x[0]);
10926 ASSERT_EQUAL_64(0, x[2]);
10927 ASSERT_EQUAL_32(0, wp[0]);
10928 ASSERT_EQUAL_32(0, wp[3]);
10929 ASSERT_EQUAL_64(0, xp[0]);
10930 ASSERT_EQUAL_64(0, xp[3]);
10931
10932 TEARDOWN();
10933}
10934
10935
10936TEST(ldaxr_stlxr) {
10937 // The middle value is read, modified, and written. The padding exists only to
10938 // check for over-write.
10939 uint8_t b[] = {0, 0x12, 0};
10940 uint16_t h[] = {0, 0x1234, 0};
10941 uint32_t w[] = {0, 0x12345678, 0};
10942 uint64_t x[] = {0, 0x123456789abcdef0, 0};
10943
10944 // As above, but get suitably-aligned values for ldxp and stxp.
10945 uint32_t wp_data[] = {0, 0, 0, 0, 0};
10946 uint32_t * wp = AlignUp(wp_data + 1, kWRegSizeInBytes * 2) - 1;
10947 wp[1] = 0x12345678; // wp[1] is 64-bit-aligned.
10948 wp[2] = 0x87654321;
10949 uint64_t xp_data[] = {0, 0, 0, 0, 0};
10950 uint64_t * xp = AlignUp(xp_data + 1, kXRegSizeInBytes * 2) - 1;
10951 xp[1] = 0x123456789abcdef0; // xp[1] is 128-bit-aligned.
10952 xp[2] = 0x0fedcba987654321;
10953
10954 SETUP();
10955 START();
10956
10957 __ Mov(x10, reinterpret_cast<uintptr_t>(&b[1]));
10958 Label try_b;
10959 __ Bind(&try_b);
10960 __ Ldaxrb(w0, MemOperand(x10));
10961 __ Add(w0, w0, 1);
10962 __ Stlxrb(w5, w0, MemOperand(x10));
10963 __ Cbnz(w5, &try_b);
10964
10965 __ Mov(x10, reinterpret_cast<uintptr_t>(&h[1]));
10966 Label try_h;
10967 __ Bind(&try_h);
10968 __ Ldaxrh(w0, MemOperand(x10));
10969 __ Add(w0, w0, 1);
10970 __ Stlxrh(w5, w0, MemOperand(x10));
10971 __ Cbnz(w5, &try_h);
10972
10973 __ Mov(x10, reinterpret_cast<uintptr_t>(&w[1]));
10974 Label try_w;
10975 __ Bind(&try_w);
10976 __ Ldaxr(w0, MemOperand(x10));
10977 __ Add(w0, w0, 1);
10978 __ Stlxr(w5, w0, MemOperand(x10));
10979 __ Cbnz(w5, &try_w);
10980
10981 __ Mov(x10, reinterpret_cast<uintptr_t>(&x[1]));
10982 Label try_x;
10983 __ Bind(&try_x);
10984 __ Ldaxr(x0, MemOperand(x10));
10985 __ Add(x0, x0, 1);
10986 __ Stlxr(w5, x0, MemOperand(x10));
10987 __ Cbnz(w5, &try_x);
10988
10989 __ Mov(x10, reinterpret_cast<uintptr_t>(&wp[1]));
10990 Label try_wp;
10991 __ Bind(&try_wp);
10992 __ Ldaxp(w0, w1, MemOperand(x10));
10993 __ Add(w0, w0, 1);
10994 __ Add(w1, w1, 1);
10995 __ Stlxp(w5, w0, w1, MemOperand(x10));
10996 __ Cbnz(w5, &try_wp);
10997
10998 __ Mov(x10, reinterpret_cast<uintptr_t>(&xp[1]));
10999 Label try_xp;
11000 __ Bind(&try_xp);
11001 __ Ldaxp(x0, x1, MemOperand(x10));
11002 __ Add(x0, x0, 1);
11003 __ Add(x1, x1, 1);
11004 __ Stlxp(w5, x0, x1, MemOperand(x10));
11005 __ Cbnz(w5, &try_xp);
11006
11007 END();
11008 RUN();
11009
11010 ASSERT_EQUAL_32(0x13, b[1]);
11011 ASSERT_EQUAL_32(0x1235, h[1]);
11012 ASSERT_EQUAL_32(0x12345679, w[1]);
11013 ASSERT_EQUAL_64(0x123456789abcdef1, x[1]);
11014 ASSERT_EQUAL_32(0x12345679, wp[1]);
11015 ASSERT_EQUAL_32(0x87654322, wp[2]);
11016 ASSERT_EQUAL_64(0x123456789abcdef1, xp[1]);
11017 ASSERT_EQUAL_64(0x0fedcba987654322, xp[2]);
11018
11019 // Check for over-write.
11020 ASSERT_EQUAL_32(0, b[0]);
11021 ASSERT_EQUAL_32(0, b[2]);
11022 ASSERT_EQUAL_32(0, h[0]);
11023 ASSERT_EQUAL_32(0, h[2]);
11024 ASSERT_EQUAL_32(0, w[0]);
11025 ASSERT_EQUAL_32(0, w[2]);
11026 ASSERT_EQUAL_64(0, x[0]);
11027 ASSERT_EQUAL_64(0, x[2]);
11028 ASSERT_EQUAL_32(0, wp[0]);
11029 ASSERT_EQUAL_32(0, wp[3]);
11030 ASSERT_EQUAL_64(0, xp[0]);
11031 ASSERT_EQUAL_64(0, xp[3]);
11032
11033 TEARDOWN();
11034}
11035
11036
11037TEST(clrex) {
11038 // This data should never be written.
11039 uint64_t data[] = {0, 0, 0};
11040 uint64_t * data_aligned = AlignUp(data, kXRegSizeInBytes * 2);
11041
11042 SETUP();
11043 START();
11044
11045 __ Mov(x10, reinterpret_cast<uintptr_t>(data_aligned));
11046 __ Mov(w6, 0);
11047
11048 __ Ldxrb(w0, MemOperand(x10));
11049 __ Clrex();
11050 __ Add(w0, w0, 1);
11051 __ Stxrb(w5, w0, MemOperand(x10));
11052 __ Add(w6, w6, w5);
11053
11054 __ Ldxrh(w0, MemOperand(x10));
11055 __ Clrex();
11056 __ Add(w0, w0, 1);
11057 __ Stxrh(w5, w0, MemOperand(x10));
11058 __ Add(w6, w6, w5);
11059
11060 __ Ldxr(w0, MemOperand(x10));
11061 __ Clrex();
11062 __ Add(w0, w0, 1);
11063 __ Stxr(w5, w0, MemOperand(x10));
11064 __ Add(w6, w6, w5);
11065
11066 __ Ldxr(x0, MemOperand(x10));
11067 __ Clrex();
11068 __ Add(x0, x0, 1);
11069 __ Stxr(w5, x0, MemOperand(x10));
11070 __ Add(w6, w6, w5);
11071
11072 __ Ldxp(w0, w1, MemOperand(x10));
11073 __ Clrex();
11074 __ Add(w0, w0, 1);
11075 __ Add(w1, w1, 1);
11076 __ Stxp(w5, w0, w1, MemOperand(x10));
11077 __ Add(w6, w6, w5);
11078
11079 __ Ldxp(x0, x1, MemOperand(x10));
11080 __ Clrex();
11081 __ Add(x0, x0, 1);
11082 __ Add(x1, x1, 1);
11083 __ Stxp(w5, x0, x1, MemOperand(x10));
11084 __ Add(w6, w6, w5);
11085
11086 // Acquire-release variants.
11087
11088 __ Ldaxrb(w0, MemOperand(x10));
11089 __ Clrex();
11090 __ Add(w0, w0, 1);
11091 __ Stlxrb(w5, w0, MemOperand(x10));
11092 __ Add(w6, w6, w5);
11093
11094 __ Ldaxrh(w0, MemOperand(x10));
11095 __ Clrex();
11096 __ Add(w0, w0, 1);
11097 __ Stlxrh(w5, w0, MemOperand(x10));
11098 __ Add(w6, w6, w5);
11099
11100 __ Ldaxr(w0, MemOperand(x10));
11101 __ Clrex();
11102 __ Add(w0, w0, 1);
11103 __ Stlxr(w5, w0, MemOperand(x10));
11104 __ Add(w6, w6, w5);
11105
11106 __ Ldaxr(x0, MemOperand(x10));
11107 __ Clrex();
11108 __ Add(x0, x0, 1);
11109 __ Stlxr(w5, x0, MemOperand(x10));
11110 __ Add(w6, w6, w5);
11111
11112 __ Ldaxp(w0, w1, MemOperand(x10));
11113 __ Clrex();
11114 __ Add(w0, w0, 1);
11115 __ Add(w1, w1, 1);
11116 __ Stlxp(w5, w0, w1, MemOperand(x10));
11117 __ Add(w6, w6, w5);
11118
11119 __ Ldaxp(x0, x1, MemOperand(x10));
11120 __ Clrex();
11121 __ Add(x0, x0, 1);
11122 __ Add(x1, x1, 1);
11123 __ Stlxp(w5, x0, x1, MemOperand(x10));
11124 __ Add(w6, w6, w5);
11125
11126 END();
11127 RUN();
11128
11129 // None of the 12 store-exclusives should have succeeded.
11130 ASSERT_EQUAL_32(12, w6);
11131
11132 ASSERT_EQUAL_64(0, data[0]);
11133 ASSERT_EQUAL_64(0, data[1]);
11134 ASSERT_EQUAL_64(0, data[2]);
11135}
11136
11137
11138#ifdef USE_SIMULATOR
11139// Check that the simulator occasionally makes store-exclusive fail.
11140TEST(ldxr_stxr_fail) {
11141 uint64_t data[] = {0, 0, 0};
11142 uint64_t * data_aligned = AlignUp(data, kXRegSizeInBytes * 2);
11143
11144 // Impose a hard limit on the number of attempts, so the test cannot hang.
11145 static const uint64_t kWatchdog = 10000;
11146 Label done;
11147
11148 SETUP();
11149 START();
11150
11151 __ Mov(x10, reinterpret_cast<uintptr_t>(data_aligned));
11152 __ Mov(x11, kWatchdog);
11153
11154 // This loop is the opposite of what we normally do with ldxr and stxr; we
11155 // keep trying until we fail (or the watchdog counter runs out).
11156 Label try_b;
11157 __ Bind(&try_b);
11158 __ Ldxrb(w0, MemOperand(x10));
11159 __ Stxrb(w5, w0, MemOperand(x10));
11160 // Check the watchdog counter.
11161 __ Sub(x11, x11, 1);
11162 __ Cbz(x11, &done);
11163 // Check the exclusive-store result.
11164 __ Cbz(w5, &try_b);
11165
11166 Label try_h;
11167 __ Bind(&try_h);
11168 __ Ldxrh(w0, MemOperand(x10));
11169 __ Stxrh(w5, w0, MemOperand(x10));
11170 __ Sub(x11, x11, 1);
11171 __ Cbz(x11, &done);
11172 __ Cbz(w5, &try_h);
11173
11174 Label try_w;
11175 __ Bind(&try_w);
11176 __ Ldxr(w0, MemOperand(x10));
11177 __ Stxr(w5, w0, MemOperand(x10));
11178 __ Sub(x11, x11, 1);
11179 __ Cbz(x11, &done);
11180 __ Cbz(w5, &try_w);
11181
11182 Label try_x;
11183 __ Bind(&try_x);
11184 __ Ldxr(x0, MemOperand(x10));
11185 __ Stxr(w5, x0, MemOperand(x10));
11186 __ Sub(x11, x11, 1);
11187 __ Cbz(x11, &done);
11188 __ Cbz(w5, &try_x);
11189
11190 Label try_wp;
11191 __ Bind(&try_wp);
11192 __ Ldxp(w0, w1, MemOperand(x10));
11193 __ Stxp(w5, w0, w1, MemOperand(x10));
11194 __ Sub(x11, x11, 1);
11195 __ Cbz(x11, &done);
11196 __ Cbz(w5, &try_wp);
11197
11198 Label try_xp;
11199 __ Bind(&try_xp);
11200 __ Ldxp(x0, x1, MemOperand(x10));
11201 __ Stxp(w5, x0, x1, MemOperand(x10));
11202 __ Sub(x11, x11, 1);
11203 __ Cbz(x11, &done);
11204 __ Cbz(w5, &try_xp);
11205
11206 __ Bind(&done);
11207 // Trigger an error if x11 (watchdog) is zero.
11208 __ Cmp(x11, 0);
11209 __ Cset(x12, eq);
11210
11211 END();
11212 RUN();
11213
11214 // Check that the watchdog counter didn't run out.
11215 ASSERT_EQUAL_64(0, x12);
11216}
11217#endif
11218
11219
11220#ifdef USE_SIMULATOR
11221// Check that the simulator occasionally makes store-exclusive fail.
11222TEST(ldaxr_stlxr_fail) {
11223 uint64_t data[] = {0, 0, 0};
11224 uint64_t * data_aligned = AlignUp(data, kXRegSizeInBytes * 2);
11225
11226 // Impose a hard limit on the number of attempts, so the test cannot hang.
11227 static const uint64_t kWatchdog = 10000;
11228 Label done;
11229
11230 SETUP();
11231 START();
11232
11233 __ Mov(x10, reinterpret_cast<uintptr_t>(data_aligned));
11234 __ Mov(x11, kWatchdog);
11235
11236 // This loop is the opposite of what we normally do with ldxr and stxr; we
11237 // keep trying until we fail (or the watchdog counter runs out).
11238 Label try_b;
11239 __ Bind(&try_b);
11240 __ Ldxrb(w0, MemOperand(x10));
11241 __ Stxrb(w5, w0, MemOperand(x10));
11242 // Check the watchdog counter.
11243 __ Sub(x11, x11, 1);
11244 __ Cbz(x11, &done);
11245 // Check the exclusive-store result.
11246 __ Cbz(w5, &try_b);
11247
11248 Label try_h;
11249 __ Bind(&try_h);
11250 __ Ldaxrh(w0, MemOperand(x10));
11251 __ Stlxrh(w5, w0, MemOperand(x10));
11252 __ Sub(x11, x11, 1);
11253 __ Cbz(x11, &done);
11254 __ Cbz(w5, &try_h);
11255
11256 Label try_w;
11257 __ Bind(&try_w);
11258 __ Ldaxr(w0, MemOperand(x10));
11259 __ Stlxr(w5, w0, MemOperand(x10));
11260 __ Sub(x11, x11, 1);
11261 __ Cbz(x11, &done);
11262 __ Cbz(w5, &try_w);
11263
11264 Label try_x;
11265 __ Bind(&try_x);
11266 __ Ldaxr(x0, MemOperand(x10));
11267 __ Stlxr(w5, x0, MemOperand(x10));
11268 __ Sub(x11, x11, 1);
11269 __ Cbz(x11, &done);
11270 __ Cbz(w5, &try_x);
11271
11272 Label try_wp;
11273 __ Bind(&try_wp);
11274 __ Ldaxp(w0, w1, MemOperand(x10));
11275 __ Stlxp(w5, w0, w1, MemOperand(x10));
11276 __ Sub(x11, x11, 1);
11277 __ Cbz(x11, &done);
11278 __ Cbz(w5, &try_wp);
11279
11280 Label try_xp;
11281 __ Bind(&try_xp);
11282 __ Ldaxp(x0, x1, MemOperand(x10));
11283 __ Stlxp(w5, x0, x1, MemOperand(x10));
11284 __ Sub(x11, x11, 1);
11285 __ Cbz(x11, &done);
11286 __ Cbz(w5, &try_xp);
11287
11288 __ Bind(&done);
11289 // Trigger an error if x11 (watchdog) is zero.
11290 __ Cmp(x11, 0);
11291 __ Cset(x12, eq);
11292
11293 END();
11294 RUN();
11295
11296 // Check that the watchdog counter didn't run out.
11297 ASSERT_EQUAL_64(0, x12);
11298}
11299#endif
11300
11301
11302TEST(load_store_tagged_immediate_offset) {
11303 uint64_t tags[] = { 0x00, 0x1, 0x55, 0xff };
11304 int tag_count = sizeof(tags) / sizeof(tags[0]);
11305
11306 const int kMaxDataLength = 128;
11307
11308 for (int i = 0; i < tag_count; i++) {
11309 unsigned char src[kMaxDataLength];
11310 uint64_t src_raw = reinterpret_cast<uint64_t>(src);
11311 uint64_t src_tag = tags[i];
11312 uint64_t src_tagged = CPU::SetPointerTag(src_raw, src_tag);
11313
11314 for (int k = 0; k < kMaxDataLength; k++) {
11315 src[k] = k + 1;
11316 }
11317
11318 for (int j = 0; j < tag_count; j++) {
11319 unsigned char dst[kMaxDataLength];
11320 uint64_t dst_raw = reinterpret_cast<uint64_t>(dst);
11321 uint64_t dst_tag = tags[j];
11322 uint64_t dst_tagged = CPU::SetPointerTag(dst_raw, dst_tag);
11323
11324 memset(dst, 0, kMaxDataLength);
11325
11326 SETUP();
armvixlc68cb642014-09-25 18:49:30 +010011327 ALLOW_ASM();
armvixl4a102ba2014-07-14 09:02:40 +010011328 START();
11329
11330 __ Mov(x0, src_tagged);
11331 __ Mov(x1, dst_tagged);
11332
11333 int offset = 0;
11334
11335 // Scaled-immediate offsets.
11336
11337 __ ldp(x2, x3, MemOperand(x0, offset));
11338 __ stp(x2, x3, MemOperand(x1, offset));
11339 offset += 2 * kXRegSizeInBytes;
11340
11341 __ ldpsw(x2, x3, MemOperand(x0, offset));
11342 __ stp(w2, w3, MemOperand(x1, offset));
11343 offset += 2 * kWRegSizeInBytes;
11344
11345 __ ldp(d0, d1, MemOperand(x0, offset));
11346 __ stp(d0, d1, MemOperand(x1, offset));
11347 offset += 2 * kDRegSizeInBytes;
11348
11349 __ ldp(w2, w3, MemOperand(x0, offset));
11350 __ stp(w2, w3, MemOperand(x1, offset));
11351 offset += 2 * kWRegSizeInBytes;
11352
11353 __ ldp(s0, s1, MemOperand(x0, offset));
11354 __ stp(s0, s1, MemOperand(x1, offset));
11355 offset += 2 * kSRegSizeInBytes;
11356
11357 __ ldr(x2, MemOperand(x0, offset), RequireScaledOffset);
11358 __ str(x2, MemOperand(x1, offset), RequireScaledOffset);
11359 offset += kXRegSizeInBytes;
11360
11361 __ ldr(d0, MemOperand(x0, offset), RequireScaledOffset);
11362 __ str(d0, MemOperand(x1, offset), RequireScaledOffset);
11363 offset += kDRegSizeInBytes;
11364
11365 __ ldr(w2, MemOperand(x0, offset), RequireScaledOffset);
11366 __ str(w2, MemOperand(x1, offset), RequireScaledOffset);
11367 offset += kWRegSizeInBytes;
11368
11369 __ ldr(s0, MemOperand(x0, offset), RequireScaledOffset);
11370 __ str(s0, MemOperand(x1, offset), RequireScaledOffset);
11371 offset += kSRegSizeInBytes;
11372
11373 __ ldrh(w2, MemOperand(x0, offset), RequireScaledOffset);
11374 __ strh(w2, MemOperand(x1, offset), RequireScaledOffset);
11375 offset += 2;
11376
11377 __ ldrsh(w2, MemOperand(x0, offset), RequireScaledOffset);
11378 __ strh(w2, MemOperand(x1, offset), RequireScaledOffset);
11379 offset += 2;
11380
11381 __ ldrb(w2, MemOperand(x0, offset), RequireScaledOffset);
11382 __ strb(w2, MemOperand(x1, offset), RequireScaledOffset);
11383 offset += 1;
11384
11385 __ ldrsb(w2, MemOperand(x0, offset), RequireScaledOffset);
11386 __ strb(w2, MemOperand(x1, offset), RequireScaledOffset);
11387 offset += 1;
11388
11389 // Unscaled-immediate offsets.
11390
11391 __ ldur(x2, MemOperand(x0, offset), RequireUnscaledOffset);
11392 __ stur(x2, MemOperand(x1, offset), RequireUnscaledOffset);
11393 offset += kXRegSizeInBytes;
11394
11395 __ ldur(d0, MemOperand(x0, offset), RequireUnscaledOffset);
11396 __ stur(d0, MemOperand(x1, offset), RequireUnscaledOffset);
11397 offset += kDRegSizeInBytes;
11398
11399 __ ldur(w2, MemOperand(x0, offset), RequireUnscaledOffset);
11400 __ stur(w2, MemOperand(x1, offset), RequireUnscaledOffset);
11401 offset += kWRegSizeInBytes;
11402
11403 __ ldur(s0, MemOperand(x0, offset), RequireUnscaledOffset);
11404 __ stur(s0, MemOperand(x1, offset), RequireUnscaledOffset);
11405 offset += kSRegSizeInBytes;
11406
11407 __ ldurh(w2, MemOperand(x0, offset), RequireUnscaledOffset);
11408 __ sturh(w2, MemOperand(x1, offset), RequireUnscaledOffset);
11409 offset += 2;
11410
11411 __ ldursh(w2, MemOperand(x0, offset), RequireUnscaledOffset);
11412 __ sturh(w2, MemOperand(x1, offset), RequireUnscaledOffset);
11413 offset += 2;
11414
11415 __ ldurb(w2, MemOperand(x0, offset), RequireUnscaledOffset);
11416 __ sturb(w2, MemOperand(x1, offset), RequireUnscaledOffset);
11417 offset += 1;
11418
11419 __ ldursb(w2, MemOperand(x0, offset), RequireUnscaledOffset);
11420 __ sturb(w2, MemOperand(x1, offset), RequireUnscaledOffset);
11421 offset += 1;
11422
11423 // Extract the tag (so we can test that it was preserved correctly).
11424 __ Ubfx(x0, x0, kAddressTagOffset, kAddressTagWidth);
11425 __ Ubfx(x1, x1, kAddressTagOffset, kAddressTagWidth);
11426
11427 VIXL_ASSERT(kMaxDataLength >= offset);
11428
11429 END();
11430 RUN();
11431
11432 ASSERT_EQUAL_64(src_tag, x0);
11433 ASSERT_EQUAL_64(dst_tag, x1);
11434
11435 for (int k = 0; k < offset; k++) {
11436 VIXL_CHECK(src[k] == dst[k]);
11437 }
11438
11439 TEARDOWN();
11440 }
11441 }
11442}
11443
11444
11445TEST(load_store_tagged_immediate_preindex) {
11446 uint64_t tags[] = { 0x00, 0x1, 0x55, 0xff };
11447 int tag_count = sizeof(tags) / sizeof(tags[0]);
11448
11449 const int kMaxDataLength = 128;
11450
11451 for (int i = 0; i < tag_count; i++) {
11452 unsigned char src[kMaxDataLength];
11453 uint64_t src_raw = reinterpret_cast<uint64_t>(src);
11454 uint64_t src_tag = tags[i];
11455 uint64_t src_tagged = CPU::SetPointerTag(src_raw, src_tag);
11456
11457 for (int k = 0; k < kMaxDataLength; k++) {
11458 src[k] = k + 1;
11459 }
11460
11461 for (int j = 0; j < tag_count; j++) {
11462 unsigned char dst[kMaxDataLength];
11463 uint64_t dst_raw = reinterpret_cast<uint64_t>(dst);
11464 uint64_t dst_tag = tags[j];
11465 uint64_t dst_tagged = CPU::SetPointerTag(dst_raw, dst_tag);
11466
11467 for (int k = 0; k < kMaxDataLength; k++) {
11468 dst[k] = 0;
11469 }
11470
11471 SETUP();
armvixlc68cb642014-09-25 18:49:30 +010011472 ALLOW_ASM();
armvixl4a102ba2014-07-14 09:02:40 +010011473 START();
11474
11475 // Each MemOperand must apply a pre-index equal to the size of the
11476 // previous access.
11477
11478 // Start with a non-zero preindex.
11479 int preindex = 63 * kXRegSizeInBytes;
armvixlc68cb642014-09-25 18:49:30 +010011480 int data_length = 0;
armvixl4a102ba2014-07-14 09:02:40 +010011481
11482 __ Mov(x0, src_tagged - preindex);
11483 __ Mov(x1, dst_tagged - preindex);
11484
11485 __ ldp(x2, x3, MemOperand(x0, preindex, PreIndex));
11486 __ stp(x2, x3, MemOperand(x1, preindex, PreIndex));
11487 preindex = 2 * kXRegSizeInBytes;
armvixlc68cb642014-09-25 18:49:30 +010011488 data_length = preindex;
armvixl4a102ba2014-07-14 09:02:40 +010011489
11490 __ ldpsw(x2, x3, MemOperand(x0, preindex, PreIndex));
11491 __ stp(w2, w3, MemOperand(x1, preindex, PreIndex));
11492 preindex = 2 * kWRegSizeInBytes;
11493 data_length += preindex;
11494
11495 __ ldp(d0, d1, MemOperand(x0, preindex, PreIndex));
11496 __ stp(d0, d1, MemOperand(x1, preindex, PreIndex));
11497 preindex = 2 * kDRegSizeInBytes;
11498 data_length += preindex;
11499
11500 __ ldp(w2, w3, MemOperand(x0, preindex, PreIndex));
11501 __ stp(w2, w3, MemOperand(x1, preindex, PreIndex));
11502 preindex = 2 * kWRegSizeInBytes;
11503 data_length += preindex;
11504
11505 __ ldp(s0, s1, MemOperand(x0, preindex, PreIndex));
11506 __ stp(s0, s1, MemOperand(x1, preindex, PreIndex));
11507 preindex = 2 * kSRegSizeInBytes;
11508 data_length += preindex;
11509
11510 __ ldr(x2, MemOperand(x0, preindex, PreIndex));
11511 __ str(x2, MemOperand(x1, preindex, PreIndex));
11512 preindex = kXRegSizeInBytes;
11513 data_length += preindex;
11514
11515 __ ldr(d0, MemOperand(x0, preindex, PreIndex));
11516 __ str(d0, MemOperand(x1, preindex, PreIndex));
11517 preindex = kDRegSizeInBytes;
11518 data_length += preindex;
11519
11520 __ ldr(w2, MemOperand(x0, preindex, PreIndex));
11521 __ str(w2, MemOperand(x1, preindex, PreIndex));
11522 preindex = kWRegSizeInBytes;
11523 data_length += preindex;
11524
11525 __ ldr(s0, MemOperand(x0, preindex, PreIndex));
11526 __ str(s0, MemOperand(x1, preindex, PreIndex));
11527 preindex = kSRegSizeInBytes;
11528 data_length += preindex;
11529
11530 __ ldrh(w2, MemOperand(x0, preindex, PreIndex));
11531 __ strh(w2, MemOperand(x1, preindex, PreIndex));
11532 preindex = 2;
11533 data_length += preindex;
11534
11535 __ ldrsh(w2, MemOperand(x0, preindex, PreIndex));
11536 __ strh(w2, MemOperand(x1, preindex, PreIndex));
11537 preindex = 2;
11538 data_length += preindex;
11539
11540 __ ldrb(w2, MemOperand(x0, preindex, PreIndex));
11541 __ strb(w2, MemOperand(x1, preindex, PreIndex));
11542 preindex = 1;
11543 data_length += preindex;
11544
11545 __ ldrsb(w2, MemOperand(x0, preindex, PreIndex));
11546 __ strb(w2, MemOperand(x1, preindex, PreIndex));
11547 preindex = 1;
11548 data_length += preindex;
11549
11550 VIXL_ASSERT(kMaxDataLength >= data_length);
11551
11552 END();
11553 RUN();
11554
11555 // Check that the preindex was correctly applied in each operation, and
11556 // that the tag was preserved.
11557 ASSERT_EQUAL_64(src_tagged + data_length - preindex, x0);
11558 ASSERT_EQUAL_64(dst_tagged + data_length - preindex, x1);
11559
11560 for (int k = 0; k < data_length; k++) {
11561 VIXL_CHECK(src[k] == dst[k]);
11562 }
11563
11564 TEARDOWN();
11565 }
11566 }
11567}
11568
11569
11570TEST(load_store_tagged_immediate_postindex) {
11571 uint64_t tags[] = { 0x00, 0x1, 0x55, 0xff };
11572 int tag_count = sizeof(tags) / sizeof(tags[0]);
11573
11574 const int kMaxDataLength = 128;
11575
11576 for (int i = 0; i < tag_count; i++) {
11577 unsigned char src[kMaxDataLength];
11578 uint64_t src_raw = reinterpret_cast<uint64_t>(src);
11579 uint64_t src_tag = tags[i];
11580 uint64_t src_tagged = CPU::SetPointerTag(src_raw, src_tag);
11581
11582 for (int k = 0; k < kMaxDataLength; k++) {
11583 src[k] = k + 1;
11584 }
11585
11586 for (int j = 0; j < tag_count; j++) {
11587 unsigned char dst[kMaxDataLength];
11588 uint64_t dst_raw = reinterpret_cast<uint64_t>(dst);
11589 uint64_t dst_tag = tags[j];
11590 uint64_t dst_tagged = CPU::SetPointerTag(dst_raw, dst_tag);
11591
11592 for (int k = 0; k < kMaxDataLength; k++) {
11593 dst[k] = 0;
11594 }
11595
11596 SETUP();
armvixlc68cb642014-09-25 18:49:30 +010011597 ALLOW_ASM();
armvixl4a102ba2014-07-14 09:02:40 +010011598 START();
11599
armvixlc68cb642014-09-25 18:49:30 +010011600 int postindex = 2 * kXRegSizeInBytes;
11601 int data_length = 0;
11602
armvixl4a102ba2014-07-14 09:02:40 +010011603 __ Mov(x0, src_tagged);
11604 __ Mov(x1, dst_tagged);
11605
armvixl4a102ba2014-07-14 09:02:40 +010011606 __ ldp(x2, x3, MemOperand(x0, postindex, PostIndex));
11607 __ stp(x2, x3, MemOperand(x1, postindex, PostIndex));
armvixlc68cb642014-09-25 18:49:30 +010011608 data_length = postindex;
armvixl4a102ba2014-07-14 09:02:40 +010011609
11610 postindex = 2 * kWRegSizeInBytes;
11611 __ ldpsw(x2, x3, MemOperand(x0, postindex, PostIndex));
11612 __ stp(w2, w3, MemOperand(x1, postindex, PostIndex));
11613 data_length += postindex;
11614
11615 postindex = 2 * kDRegSizeInBytes;
11616 __ ldp(d0, d1, MemOperand(x0, postindex, PostIndex));
11617 __ stp(d0, d1, MemOperand(x1, postindex, PostIndex));
11618 data_length += postindex;
11619
11620 postindex = 2 * kWRegSizeInBytes;
11621 __ ldp(w2, w3, MemOperand(x0, postindex, PostIndex));
11622 __ stp(w2, w3, MemOperand(x1, postindex, PostIndex));
11623 data_length += postindex;
11624
11625 postindex = 2 * kSRegSizeInBytes;
11626 __ ldp(s0, s1, MemOperand(x0, postindex, PostIndex));
11627 __ stp(s0, s1, MemOperand(x1, postindex, PostIndex));
11628 data_length += postindex;
11629
11630 postindex = kXRegSizeInBytes;
11631 __ ldr(x2, MemOperand(x0, postindex, PostIndex));
11632 __ str(x2, MemOperand(x1, postindex, PostIndex));
11633 data_length += postindex;
11634
11635 postindex = kDRegSizeInBytes;
11636 __ ldr(d0, MemOperand(x0, postindex, PostIndex));
11637 __ str(d0, MemOperand(x1, postindex, PostIndex));
11638 data_length += postindex;
11639
11640 postindex = kWRegSizeInBytes;
11641 __ ldr(w2, MemOperand(x0, postindex, PostIndex));
11642 __ str(w2, MemOperand(x1, postindex, PostIndex));
11643 data_length += postindex;
11644
11645 postindex = kSRegSizeInBytes;
11646 __ ldr(s0, MemOperand(x0, postindex, PostIndex));
11647 __ str(s0, MemOperand(x1, postindex, PostIndex));
11648 data_length += postindex;
11649
11650 postindex = 2;
11651 __ ldrh(w2, MemOperand(x0, postindex, PostIndex));
11652 __ strh(w2, MemOperand(x1, postindex, PostIndex));
11653 data_length += postindex;
11654
11655 postindex = 2;
11656 __ ldrsh(w2, MemOperand(x0, postindex, PostIndex));
11657 __ strh(w2, MemOperand(x1, postindex, PostIndex));
11658 data_length += postindex;
11659
11660 postindex = 1;
11661 __ ldrb(w2, MemOperand(x0, postindex, PostIndex));
11662 __ strb(w2, MemOperand(x1, postindex, PostIndex));
11663 data_length += postindex;
11664
11665 postindex = 1;
11666 __ ldrsb(w2, MemOperand(x0, postindex, PostIndex));
11667 __ strb(w2, MemOperand(x1, postindex, PostIndex));
11668 data_length += postindex;
11669
11670 VIXL_ASSERT(kMaxDataLength >= data_length);
11671
11672 END();
11673 RUN();
11674
11675 // Check that the postindex was correctly applied in each operation, and
11676 // that the tag was preserved.
11677 ASSERT_EQUAL_64(src_tagged + data_length, x0);
11678 ASSERT_EQUAL_64(dst_tagged + data_length, x1);
11679
11680 for (int k = 0; k < data_length; k++) {
11681 VIXL_CHECK(src[k] == dst[k]);
11682 }
11683
11684 TEARDOWN();
11685 }
11686 }
11687}
11688
11689
11690TEST(load_store_tagged_register_offset) {
11691 uint64_t tags[] = { 0x00, 0x1, 0x55, 0xff };
11692 int tag_count = sizeof(tags) / sizeof(tags[0]);
11693
11694 const int kMaxDataLength = 128;
11695
11696 for (int i = 0; i < tag_count; i++) {
11697 unsigned char src[kMaxDataLength];
11698 uint64_t src_raw = reinterpret_cast<uint64_t>(src);
11699 uint64_t src_tag = tags[i];
11700 uint64_t src_tagged = CPU::SetPointerTag(src_raw, src_tag);
11701
11702 for (int k = 0; k < kMaxDataLength; k++) {
11703 src[k] = k + 1;
11704 }
11705
11706 for (int j = 0; j < tag_count; j++) {
11707 unsigned char dst[kMaxDataLength];
11708 uint64_t dst_raw = reinterpret_cast<uint64_t>(dst);
11709 uint64_t dst_tag = tags[j];
11710 uint64_t dst_tagged = CPU::SetPointerTag(dst_raw, dst_tag);
11711
11712 // Also tag the offset register; the operation should still succeed.
11713 for (int o = 0; o < tag_count; o++) {
11714 uint64_t offset_base = CPU::SetPointerTag(UINT64_C(0), tags[o]);
11715 int data_length = 0;
11716
11717 for (int k = 0; k < kMaxDataLength; k++) {
11718 dst[k] = 0;
11719 }
11720
11721 SETUP();
armvixlc68cb642014-09-25 18:49:30 +010011722 ALLOW_ASM();
armvixl4a102ba2014-07-14 09:02:40 +010011723 START();
11724
11725 __ Mov(x0, src_tagged);
11726 __ Mov(x1, dst_tagged);
11727
11728 __ Mov(x10, offset_base + data_length);
11729 __ ldr(x2, MemOperand(x0, x10));
11730 __ str(x2, MemOperand(x1, x10));
11731 data_length += kXRegSizeInBytes;
11732
11733 __ Mov(x10, offset_base + data_length);
11734 __ ldr(d0, MemOperand(x0, x10));
11735 __ str(d0, MemOperand(x1, x10));
11736 data_length += kDRegSizeInBytes;
11737
11738 __ Mov(x10, offset_base + data_length);
11739 __ ldr(w2, MemOperand(x0, x10));
11740 __ str(w2, MemOperand(x1, x10));
11741 data_length += kWRegSizeInBytes;
11742
11743 __ Mov(x10, offset_base + data_length);
11744 __ ldr(s0, MemOperand(x0, x10));
11745 __ str(s0, MemOperand(x1, x10));
11746 data_length += kSRegSizeInBytes;
11747
11748 __ Mov(x10, offset_base + data_length);
11749 __ ldrh(w2, MemOperand(x0, x10));
11750 __ strh(w2, MemOperand(x1, x10));
11751 data_length += 2;
11752
11753 __ Mov(x10, offset_base + data_length);
11754 __ ldrsh(w2, MemOperand(x0, x10));
11755 __ strh(w2, MemOperand(x1, x10));
11756 data_length += 2;
11757
11758 __ Mov(x10, offset_base + data_length);
11759 __ ldrb(w2, MemOperand(x0, x10));
11760 __ strb(w2, MemOperand(x1, x10));
11761 data_length += 1;
11762
11763 __ Mov(x10, offset_base + data_length);
11764 __ ldrsb(w2, MemOperand(x0, x10));
11765 __ strb(w2, MemOperand(x1, x10));
11766 data_length += 1;
11767
11768 VIXL_ASSERT(kMaxDataLength >= data_length);
11769
11770 END();
11771 RUN();
11772
11773 // Check that the postindex was correctly applied in each operation, and
11774 // that the tag was preserved.
11775 ASSERT_EQUAL_64(src_tagged, x0);
11776 ASSERT_EQUAL_64(dst_tagged, x1);
11777 ASSERT_EQUAL_64(offset_base + data_length - 1, x10);
11778
11779 for (int k = 0; k < data_length; k++) {
11780 VIXL_CHECK(src[k] == dst[k]);
11781 }
11782
11783 TEARDOWN();
11784 }
11785 }
11786 }
11787}
11788
11789
armvixlc68cb642014-09-25 18:49:30 +010011790TEST(branch_tagged) {
11791 SETUP();
11792 START();
11793
11794 Label loop, loop_entry, done;
11795 __ Adr(x0, &loop);
11796 __ Mov(x1, 0);
11797 __ B(&loop_entry);
11798
11799 __ Bind(&loop);
11800 __ Add(x1, x1, 1); // Count successful jumps.
11801
11802 // Advance to the next tag, then bail out if we've come back around to tag 0.
11803 __ Add(x0, x0, UINT64_C(1) << kAddressTagOffset);
11804 __ Tst(x0, kAddressTagMask);
11805 __ B(eq, &done);
11806
11807 __ Bind(&loop_entry);
11808 __ Br(x0);
11809
11810 __ Bind(&done);
11811
11812 END();
11813 RUN();
11814
11815 ASSERT_EQUAL_64(1 << kAddressTagWidth, x1);
11816
11817 TEARDOWN();
11818}
11819
11820
11821TEST(branch_and_link_tagged) {
11822 SETUP();
11823 START();
11824
11825 Label loop, loop_entry, done;
11826 __ Adr(x0, &loop);
11827 __ Mov(x1, 0);
11828 __ B(&loop_entry);
11829
11830 __ Bind(&loop);
11831
11832 // Bail out (before counting a successful jump) if lr appears to be tagged.
11833 __ Tst(lr, kAddressTagMask);
11834 __ B(ne, &done);
11835
11836 __ Add(x1, x1, 1); // Count successful jumps.
11837
11838 // Advance to the next tag, then bail out if we've come back around to tag 0.
11839 __ Add(x0, x0, UINT64_C(1) << kAddressTagOffset);
11840 __ Tst(x0, kAddressTagMask);
11841 __ B(eq, &done);
11842
11843 __ Bind(&loop_entry);
11844 __ Blr(x0);
11845
11846 __ Bind(&done);
11847
11848 END();
11849 RUN();
11850
11851 ASSERT_EQUAL_64(1 << kAddressTagWidth, x1);
11852
11853 TEARDOWN();
11854}
11855
11856
11857TEST(branch_tagged_and_adr_adrp) {
11858 SETUP_CUSTOM(BUF_SIZE, PageOffsetDependentCode);
11859 START();
11860
11861 Label loop, loop_entry, done;
11862 __ Adr(x0, &loop);
11863 __ Mov(x1, 0);
11864 __ B(&loop_entry);
11865
11866 __ Bind(&loop);
11867
11868 // Bail out (before counting a successful jump) if `adr x10, ...` is tagged.
11869 __ Adr(x10, &done);
11870 __ Tst(x10, kAddressTagMask);
11871 __ B(ne, &done);
11872
11873 // Bail out (before counting a successful jump) if `adrp x11, ...` is tagged.
11874 __ Adrp(x11, &done);
11875 __ Tst(x11, kAddressTagMask);
11876 __ B(ne, &done);
11877
11878 __ Add(x1, x1, 1); // Count successful iterations.
11879
11880 // Advance to the next tag, then bail out if we've come back around to tag 0.
11881 __ Add(x0, x0, UINT64_C(1) << kAddressTagOffset);
11882 __ Tst(x0, kAddressTagMask);
11883 __ B(eq, &done);
11884
11885 __ Bind(&loop_entry);
11886 __ Br(x0);
11887
11888 __ Bind(&done);
11889
11890 END();
11891 RUN();
11892
11893 ASSERT_EQUAL_64(1 << kAddressTagWidth, x1);
11894
11895 TEARDOWN();
11896}
11897
11898
armvixlad96eda2013-06-14 11:42:37 +010011899} // namespace vixl