Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1 | // Copyright 2012 the V8 project authors. All rights reserved. |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 2 | // Redistribution and use in source and binary forms, with or without |
| 3 | // modification, are permitted provided that the following conditions are |
| 4 | // met: |
| 5 | // |
| 6 | // * Redistributions of source code must retain the above copyright |
| 7 | // notice, this list of conditions and the following disclaimer. |
| 8 | // * Redistributions in binary form must reproduce the above |
| 9 | // copyright notice, this list of conditions and the following |
| 10 | // disclaimer in the documentation and/or other materials provided |
| 11 | // with the distribution. |
| 12 | // * Neither the name of Google Inc. nor the names of its |
| 13 | // contributors may be used to endorse or promote products derived |
| 14 | // from this software without specific prior written permission. |
| 15 | // |
| 16 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 28 | #include <iostream> // NOLINT(readability/streams) |
| 29 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 30 | #include "src/v8.h" |
| 31 | #include "test/cctest/cctest.h" |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 32 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 33 | #include "src/arm/assembler-arm-inl.h" |
| 34 | #include "src/arm/simulator-arm.h" |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 35 | #include "src/base/utils/random-number-generator.h" |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 36 | #include "src/disassembler.h" |
| 37 | #include "src/factory.h" |
| 38 | #include "src/ostreams.h" |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 39 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 40 | using namespace v8::base; |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 41 | using namespace v8::internal; |
| 42 | |
| 43 | |
| 44 | // Define these function prototypes to match JSEntryFunction in execution.cc. |
| 45 | typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4); |
| 46 | typedef Object* (*F2)(int x, int y, int p2, int p3, int p4); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 47 | typedef Object* (*F3)(void* p0, int p1, int p2, int p3, int p4); |
| 48 | typedef Object* (*F4)(void* p0, void* p1, int p2, int p3, int p4); |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 49 | typedef Object* (*F5)(uint32_t p0, void* p1, void* p2, int p3, int p4); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 50 | |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 51 | #define __ assm. |
| 52 | |
| 53 | TEST(0) { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 54 | CcTest::InitializeVM(); |
| 55 | Isolate* isolate = CcTest::i_isolate(); |
| 56 | HandleScope scope(isolate); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 57 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 58 | Assembler assm(isolate, NULL, 0); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 59 | |
| 60 | __ add(r0, r0, Operand(r1)); |
| 61 | __ mov(pc, Operand(lr)); |
| 62 | |
| 63 | CodeDesc desc; |
| 64 | assm.GetCode(&desc); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 65 | Handle<Code> code = isolate->factory()->NewCode( |
| 66 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 67 | #ifdef DEBUG |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 68 | OFStream os(stdout); |
| 69 | code->Print(os); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 70 | #endif |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 71 | F2 f = FUNCTION_CAST<F2>(code->entry()); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 72 | int res = |
| 73 | reinterpret_cast<int>(CALL_GENERATED_CODE(isolate, f, 3, 4, 0, 0, 0)); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 74 | ::printf("f() = %d\n", res); |
| 75 | CHECK_EQ(7, res); |
| 76 | } |
| 77 | |
| 78 | |
| 79 | TEST(1) { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 80 | CcTest::InitializeVM(); |
| 81 | Isolate* isolate = CcTest::i_isolate(); |
| 82 | HandleScope scope(isolate); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 83 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 84 | Assembler assm(isolate, NULL, 0); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 85 | Label L, C; |
| 86 | |
| 87 | __ mov(r1, Operand(r0)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 88 | __ mov(r0, Operand::Zero()); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 89 | __ b(&C); |
| 90 | |
| 91 | __ bind(&L); |
| 92 | __ add(r0, r0, Operand(r1)); |
| 93 | __ sub(r1, r1, Operand(1)); |
| 94 | |
| 95 | __ bind(&C); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 96 | __ teq(r1, Operand::Zero()); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 97 | __ b(ne, &L); |
| 98 | __ mov(pc, Operand(lr)); |
| 99 | |
| 100 | CodeDesc desc; |
| 101 | assm.GetCode(&desc); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 102 | Handle<Code> code = isolate->factory()->NewCode( |
| 103 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 104 | #ifdef DEBUG |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 105 | OFStream os(stdout); |
| 106 | code->Print(os); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 107 | #endif |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 108 | F1 f = FUNCTION_CAST<F1>(code->entry()); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 109 | int res = |
| 110 | reinterpret_cast<int>(CALL_GENERATED_CODE(isolate, f, 100, 0, 0, 0, 0)); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 111 | ::printf("f() = %d\n", res); |
| 112 | CHECK_EQ(5050, res); |
| 113 | } |
| 114 | |
| 115 | |
| 116 | TEST(2) { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 117 | CcTest::InitializeVM(); |
| 118 | Isolate* isolate = CcTest::i_isolate(); |
| 119 | HandleScope scope(isolate); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 120 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 121 | Assembler assm(isolate, NULL, 0); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 122 | Label L, C; |
| 123 | |
| 124 | __ mov(r1, Operand(r0)); |
| 125 | __ mov(r0, Operand(1)); |
| 126 | __ b(&C); |
| 127 | |
| 128 | __ bind(&L); |
| 129 | __ mul(r0, r1, r0); |
| 130 | __ sub(r1, r1, Operand(1)); |
| 131 | |
| 132 | __ bind(&C); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 133 | __ teq(r1, Operand::Zero()); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 134 | __ b(ne, &L); |
| 135 | __ mov(pc, Operand(lr)); |
| 136 | |
| 137 | // some relocated stuff here, not executed |
| 138 | __ RecordComment("dead code, just testing relocations"); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 139 | __ mov(r0, Operand(isolate->factory()->true_value())); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 140 | __ RecordComment("dead code, just testing immediate operands"); |
| 141 | __ mov(r0, Operand(-1)); |
| 142 | __ mov(r0, Operand(0xFF000000)); |
| 143 | __ mov(r0, Operand(0xF0F0F0F0)); |
| 144 | __ mov(r0, Operand(0xFFF0FFFF)); |
| 145 | |
| 146 | CodeDesc desc; |
| 147 | assm.GetCode(&desc); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 148 | Handle<Code> code = isolate->factory()->NewCode( |
| 149 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 150 | #ifdef DEBUG |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 151 | OFStream os(stdout); |
| 152 | code->Print(os); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 153 | #endif |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 154 | F1 f = FUNCTION_CAST<F1>(code->entry()); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 155 | int res = |
| 156 | reinterpret_cast<int>(CALL_GENERATED_CODE(isolate, f, 10, 0, 0, 0, 0)); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 157 | ::printf("f() = %d\n", res); |
| 158 | CHECK_EQ(3628800, res); |
| 159 | } |
| 160 | |
| 161 | |
| 162 | TEST(3) { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 163 | CcTest::InitializeVM(); |
| 164 | Isolate* isolate = CcTest::i_isolate(); |
| 165 | HandleScope scope(isolate); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 166 | |
| 167 | typedef struct { |
| 168 | int i; |
| 169 | char c; |
| 170 | int16_t s; |
| 171 | } T; |
| 172 | T t; |
| 173 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 174 | Assembler assm(isolate, NULL, 0); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 175 | Label L, C; |
| 176 | |
| 177 | __ mov(ip, Operand(sp)); |
| 178 | __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); |
| 179 | __ sub(fp, ip, Operand(4)); |
| 180 | __ mov(r4, Operand(r0)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 181 | __ ldr(r0, MemOperand(r4, offsetof(T, i))); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 182 | __ mov(r2, Operand(r0, ASR, 1)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 183 | __ str(r2, MemOperand(r4, offsetof(T, i))); |
| 184 | __ ldrsb(r2, MemOperand(r4, offsetof(T, c))); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 185 | __ add(r0, r2, Operand(r0)); |
| 186 | __ mov(r2, Operand(r2, LSL, 2)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 187 | __ strb(r2, MemOperand(r4, offsetof(T, c))); |
| 188 | __ ldrsh(r2, MemOperand(r4, offsetof(T, s))); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 189 | __ add(r0, r2, Operand(r0)); |
| 190 | __ mov(r2, Operand(r2, ASR, 3)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 191 | __ strh(r2, MemOperand(r4, offsetof(T, s))); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 192 | __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); |
| 193 | |
| 194 | CodeDesc desc; |
| 195 | assm.GetCode(&desc); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 196 | Handle<Code> code = isolate->factory()->NewCode( |
| 197 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 198 | #ifdef DEBUG |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 199 | OFStream os(stdout); |
| 200 | code->Print(os); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 201 | #endif |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 202 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 203 | t.i = 100000; |
| 204 | t.c = 10; |
| 205 | t.s = 1000; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 206 | int res = |
| 207 | reinterpret_cast<int>(CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0)); |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 208 | ::printf("f() = %d\n", res); |
| 209 | CHECK_EQ(101010, res); |
| 210 | CHECK_EQ(100000/2, t.i); |
| 211 | CHECK_EQ(10*4, t.c); |
| 212 | CHECK_EQ(1000/8, t.s); |
| 213 | } |
| 214 | |
| 215 | |
Leon Clarke | d91b9f7 | 2010-01-27 17:25:45 +0000 | [diff] [blame] | 216 | TEST(4) { |
| 217 | // Test the VFP floating point instructions. |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 218 | CcTest::InitializeVM(); |
| 219 | Isolate* isolate = CcTest::i_isolate(); |
| 220 | HandleScope scope(isolate); |
Leon Clarke | d91b9f7 | 2010-01-27 17:25:45 +0000 | [diff] [blame] | 221 | |
| 222 | typedef struct { |
| 223 | double a; |
| 224 | double b; |
| 225 | double c; |
Kristian Monsen | 80d68ea | 2010-09-08 11:05:35 +0100 | [diff] [blame] | 226 | double d; |
| 227 | double e; |
| 228 | double f; |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 229 | double g; |
| 230 | double h; |
Kristian Monsen | 80d68ea | 2010-09-08 11:05:35 +0100 | [diff] [blame] | 231 | int i; |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 232 | double j; |
Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 233 | double m; |
| 234 | double n; |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 235 | float o; |
| 236 | float p; |
Kristian Monsen | 80d68ea | 2010-09-08 11:05:35 +0100 | [diff] [blame] | 237 | float x; |
| 238 | float y; |
Leon Clarke | d91b9f7 | 2010-01-27 17:25:45 +0000 | [diff] [blame] | 239 | } T; |
| 240 | T t; |
| 241 | |
| 242 | // Create a function that accepts &t, and loads, manipulates, and stores |
Kristian Monsen | 80d68ea | 2010-09-08 11:05:35 +0100 | [diff] [blame] | 243 | // the doubles and floats. |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 244 | Assembler assm(isolate, NULL, 0); |
Leon Clarke | d91b9f7 | 2010-01-27 17:25:45 +0000 | [diff] [blame] | 245 | Label L, C; |
| 246 | |
| 247 | |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 248 | if (CpuFeatures::IsSupported(VFP3)) { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 249 | CpuFeatureScope scope(&assm, VFP3); |
Leon Clarke | d91b9f7 | 2010-01-27 17:25:45 +0000 | [diff] [blame] | 250 | |
| 251 | __ mov(ip, Operand(sp)); |
| 252 | __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); |
| 253 | __ sub(fp, ip, Operand(4)); |
| 254 | |
| 255 | __ mov(r4, Operand(r0)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 256 | __ vldr(d6, r4, offsetof(T, a)); |
| 257 | __ vldr(d7, r4, offsetof(T, b)); |
Leon Clarke | d91b9f7 | 2010-01-27 17:25:45 +0000 | [diff] [blame] | 258 | __ vadd(d5, d6, d7); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 259 | __ vstr(d5, r4, offsetof(T, c)); |
Leon Clarke | d91b9f7 | 2010-01-27 17:25:45 +0000 | [diff] [blame] | 260 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 261 | __ vmla(d5, d6, d7); |
| 262 | __ vmls(d5, d5, d6); |
| 263 | |
Leon Clarke | d91b9f7 | 2010-01-27 17:25:45 +0000 | [diff] [blame] | 264 | __ vmov(r2, r3, d5); |
| 265 | __ vmov(d4, r2, r3); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 266 | __ vstr(d4, r4, offsetof(T, b)); |
Leon Clarke | d91b9f7 | 2010-01-27 17:25:45 +0000 | [diff] [blame] | 267 | |
Kristian Monsen | 80d68ea | 2010-09-08 11:05:35 +0100 | [diff] [blame] | 268 | // Load t.x and t.y, switch values, and store back to the struct. |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 269 | __ vldr(s0, r4, offsetof(T, x)); |
| 270 | __ vldr(s31, r4, offsetof(T, y)); |
Kristian Monsen | 80d68ea | 2010-09-08 11:05:35 +0100 | [diff] [blame] | 271 | __ vmov(s16, s0); |
| 272 | __ vmov(s0, s31); |
| 273 | __ vmov(s31, s16); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 274 | __ vstr(s0, r4, offsetof(T, x)); |
| 275 | __ vstr(s31, r4, offsetof(T, y)); |
Iain Merrick | 7568138 | 2010-08-19 15:07:18 +0100 | [diff] [blame] | 276 | |
Kristian Monsen | 80d68ea | 2010-09-08 11:05:35 +0100 | [diff] [blame] | 277 | // Move a literal into a register that can be encoded in the instruction. |
| 278 | __ vmov(d4, 1.0); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 279 | __ vstr(d4, r4, offsetof(T, e)); |
Kristian Monsen | 80d68ea | 2010-09-08 11:05:35 +0100 | [diff] [blame] | 280 | |
| 281 | // Move a literal into a register that requires 64 bits to encode. |
| 282 | // 0x3ff0000010000000 = 1.000000059604644775390625 |
| 283 | __ vmov(d4, 1.000000059604644775390625); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 284 | __ vstr(d4, r4, offsetof(T, d)); |
Kristian Monsen | 80d68ea | 2010-09-08 11:05:35 +0100 | [diff] [blame] | 285 | |
| 286 | // Convert from floating point to integer. |
| 287 | __ vmov(d4, 2.0); |
| 288 | __ vcvt_s32_f64(s31, d4); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 289 | __ vstr(s31, r4, offsetof(T, i)); |
Kristian Monsen | 80d68ea | 2010-09-08 11:05:35 +0100 | [diff] [blame] | 290 | |
| 291 | // Convert from integer to floating point. |
| 292 | __ mov(lr, Operand(42)); |
| 293 | __ vmov(s31, lr); |
| 294 | __ vcvt_f64_s32(d4, s31); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 295 | __ vstr(d4, r4, offsetof(T, f)); |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 296 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 297 | // Convert from fixed point to floating point. |
| 298 | __ mov(lr, Operand(2468)); |
| 299 | __ vmov(s8, lr); |
| 300 | __ vcvt_f64_s32(d4, 2); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 301 | __ vstr(d4, r4, offsetof(T, j)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 302 | |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 303 | // Test vabs. |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 304 | __ vldr(d1, r4, offsetof(T, g)); |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 305 | __ vabs(d0, d1); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 306 | __ vstr(d0, r4, offsetof(T, g)); |
| 307 | __ vldr(d2, r4, offsetof(T, h)); |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 308 | __ vabs(d0, d2); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 309 | __ vstr(d0, r4, offsetof(T, h)); |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 310 | |
Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 311 | // Test vneg. |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 312 | __ vldr(d1, r4, offsetof(T, m)); |
Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 313 | __ vneg(d0, d1); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 314 | __ vstr(d0, r4, offsetof(T, m)); |
| 315 | __ vldr(d1, r4, offsetof(T, n)); |
Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 316 | __ vneg(d0, d1); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 317 | __ vstr(d0, r4, offsetof(T, n)); |
Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 318 | |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 319 | // Test vmov for single-precision immediates. |
| 320 | __ vmov(s0, 0.25f); |
| 321 | __ vstr(s0, r4, offsetof(T, o)); |
| 322 | __ vmov(s0, -16.0f); |
| 323 | __ vstr(s0, r4, offsetof(T, p)); |
| 324 | |
Leon Clarke | d91b9f7 | 2010-01-27 17:25:45 +0000 | [diff] [blame] | 325 | __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); |
| 326 | |
| 327 | CodeDesc desc; |
| 328 | assm.GetCode(&desc); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 329 | Handle<Code> code = isolate->factory()->NewCode( |
| 330 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
Leon Clarke | d91b9f7 | 2010-01-27 17:25:45 +0000 | [diff] [blame] | 331 | #ifdef DEBUG |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 332 | OFStream os(stdout); |
| 333 | code->Print(os); |
Leon Clarke | d91b9f7 | 2010-01-27 17:25:45 +0000 | [diff] [blame] | 334 | #endif |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 335 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
Leon Clarke | d91b9f7 | 2010-01-27 17:25:45 +0000 | [diff] [blame] | 336 | t.a = 1.5; |
| 337 | t.b = 2.75; |
| 338 | t.c = 17.17; |
Kristian Monsen | 80d68ea | 2010-09-08 11:05:35 +0100 | [diff] [blame] | 339 | t.d = 0.0; |
| 340 | t.e = 0.0; |
| 341 | t.f = 0.0; |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 342 | t.g = -2718.2818; |
| 343 | t.h = 31415926.5; |
Kristian Monsen | 80d68ea | 2010-09-08 11:05:35 +0100 | [diff] [blame] | 344 | t.i = 0; |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 345 | t.j = 0; |
Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 346 | t.m = -2718.2818; |
| 347 | t.n = 123.456; |
Kristian Monsen | 80d68ea | 2010-09-08 11:05:35 +0100 | [diff] [blame] | 348 | t.x = 4.5; |
| 349 | t.y = 9.0; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 350 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); |
Leon Clarke | d91b9f7 | 2010-01-27 17:25:45 +0000 | [diff] [blame] | 351 | USE(dummy); |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 352 | CHECK_EQ(-16.0f, t.p); |
| 353 | CHECK_EQ(0.25f, t.o); |
Steve Block | 44f0eee | 2011-05-26 01:26:41 +0100 | [diff] [blame] | 354 | CHECK_EQ(-123.456, t.n); |
| 355 | CHECK_EQ(2718.2818, t.m); |
Kristian Monsen | 80d68ea | 2010-09-08 11:05:35 +0100 | [diff] [blame] | 356 | CHECK_EQ(2, t.i); |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 357 | CHECK_EQ(2718.2818, t.g); |
| 358 | CHECK_EQ(31415926.5, t.h); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 359 | CHECK_EQ(617.0, t.j); |
Kristian Monsen | 80d68ea | 2010-09-08 11:05:35 +0100 | [diff] [blame] | 360 | CHECK_EQ(42.0, t.f); |
| 361 | CHECK_EQ(1.0, t.e); |
| 362 | CHECK_EQ(1.000000059604644775390625, t.d); |
Leon Clarke | d91b9f7 | 2010-01-27 17:25:45 +0000 | [diff] [blame] | 363 | CHECK_EQ(4.25, t.c); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 364 | CHECK_EQ(-4.1875, t.b); |
Leon Clarke | d91b9f7 | 2010-01-27 17:25:45 +0000 | [diff] [blame] | 365 | CHECK_EQ(1.5, t.a); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 366 | CHECK_EQ(4.5f, t.y); |
| 367 | CHECK_EQ(9.0f, t.x); |
Leon Clarke | d91b9f7 | 2010-01-27 17:25:45 +0000 | [diff] [blame] | 368 | } |
| 369 | } |
| 370 | |
Ben Murdoch | 7f4d5bd | 2010-06-15 11:15:29 +0100 | [diff] [blame] | 371 | |
| 372 | TEST(5) { |
| 373 | // Test the ARMv7 bitfield instructions. |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 374 | CcTest::InitializeVM(); |
| 375 | Isolate* isolate = CcTest::i_isolate(); |
| 376 | HandleScope scope(isolate); |
Ben Murdoch | 7f4d5bd | 2010-06-15 11:15:29 +0100 | [diff] [blame] | 377 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 378 | Assembler assm(isolate, NULL, 0); |
Ben Murdoch | 7f4d5bd | 2010-06-15 11:15:29 +0100 | [diff] [blame] | 379 | |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 380 | if (CpuFeatures::IsSupported(ARMv7)) { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 381 | CpuFeatureScope scope(&assm, ARMv7); |
Ben Murdoch | 7f4d5bd | 2010-06-15 11:15:29 +0100 | [diff] [blame] | 382 | // On entry, r0 = 0xAAAAAAAA = 0b10..10101010. |
| 383 | __ ubfx(r0, r0, 1, 12); // 0b00..010101010101 = 0x555 |
| 384 | __ sbfx(r0, r0, 0, 5); // 0b11..111111110101 = -11 |
| 385 | __ bfc(r0, 1, 3); // 0b11..111111110001 = -15 |
| 386 | __ mov(r1, Operand(7)); |
| 387 | __ bfi(r0, r1, 3, 3); // 0b11..111111111001 = -7 |
| 388 | __ mov(pc, Operand(lr)); |
| 389 | |
| 390 | CodeDesc desc; |
| 391 | assm.GetCode(&desc); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 392 | Handle<Code> code = isolate->factory()->NewCode( |
| 393 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
Ben Murdoch | 7f4d5bd | 2010-06-15 11:15:29 +0100 | [diff] [blame] | 394 | #ifdef DEBUG |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 395 | OFStream os(stdout); |
| 396 | code->Print(os); |
Ben Murdoch | 7f4d5bd | 2010-06-15 11:15:29 +0100 | [diff] [blame] | 397 | #endif |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 398 | F1 f = FUNCTION_CAST<F1>(code->entry()); |
Ben Murdoch | 7f4d5bd | 2010-06-15 11:15:29 +0100 | [diff] [blame] | 399 | int res = reinterpret_cast<int>( |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 400 | CALL_GENERATED_CODE(isolate, f, 0xAAAAAAAA, 0, 0, 0, 0)); |
Ben Murdoch | 7f4d5bd | 2010-06-15 11:15:29 +0100 | [diff] [blame] | 401 | ::printf("f() = %d\n", res); |
| 402 | CHECK_EQ(-7, res); |
| 403 | } |
| 404 | } |
| 405 | |
Kristian Monsen | 50ef84f | 2010-07-29 15:18:00 +0100 | [diff] [blame] | 406 | |
| 407 | TEST(6) { |
| 408 | // Test saturating instructions. |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 409 | CcTest::InitializeVM(); |
| 410 | Isolate* isolate = CcTest::i_isolate(); |
| 411 | HandleScope scope(isolate); |
Kristian Monsen | 50ef84f | 2010-07-29 15:18:00 +0100 | [diff] [blame] | 412 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 413 | Assembler assm(isolate, NULL, 0); |
Kristian Monsen | 50ef84f | 2010-07-29 15:18:00 +0100 | [diff] [blame] | 414 | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 415 | __ usat(r1, 8, Operand(r0)); // Sat 0xFFFF to 0-255 = 0xFF. |
| 416 | __ usat(r2, 12, Operand(r0, ASR, 9)); // Sat (0xFFFF>>9) to 0-4095 = 0x7F. |
| 417 | __ usat(r3, 1, Operand(r0, LSL, 16)); // Sat (0xFFFF<<16) to 0-1 = 0x0. |
| 418 | __ add(r0, r1, Operand(r2)); |
| 419 | __ add(r0, r0, Operand(r3)); |
| 420 | __ mov(pc, Operand(lr)); |
Kristian Monsen | 50ef84f | 2010-07-29 15:18:00 +0100 | [diff] [blame] | 421 | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 422 | CodeDesc desc; |
| 423 | assm.GetCode(&desc); |
| 424 | Handle<Code> code = isolate->factory()->NewCode( |
| 425 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
Kristian Monsen | 50ef84f | 2010-07-29 15:18:00 +0100 | [diff] [blame] | 426 | #ifdef DEBUG |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 427 | OFStream os(stdout); |
| 428 | code->Print(os); |
Kristian Monsen | 50ef84f | 2010-07-29 15:18:00 +0100 | [diff] [blame] | 429 | #endif |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 430 | F1 f = FUNCTION_CAST<F1>(code->entry()); |
| 431 | int res = reinterpret_cast<int>( |
| 432 | CALL_GENERATED_CODE(isolate, f, 0xFFFF, 0, 0, 0, 0)); |
| 433 | ::printf("f() = %d\n", res); |
| 434 | CHECK_EQ(382, res); |
Kristian Monsen | 50ef84f | 2010-07-29 15:18:00 +0100 | [diff] [blame] | 435 | } |
| 436 | |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 437 | |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 438 | enum VCVTTypes { |
| 439 | s32_f64, |
| 440 | u32_f64 |
| 441 | }; |
| 442 | |
| 443 | static void TestRoundingMode(VCVTTypes types, |
| 444 | VFPRoundingMode mode, |
| 445 | double value, |
| 446 | int expected, |
| 447 | bool expected_exception = false) { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 448 | Isolate* isolate = CcTest::i_isolate(); |
| 449 | HandleScope scope(isolate); |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 450 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 451 | Assembler assm(isolate, NULL, 0); |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 452 | |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 453 | if (CpuFeatures::IsSupported(VFP3)) { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 454 | CpuFeatureScope scope(&assm, VFP3); |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 455 | |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 456 | Label wrong_exception; |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 457 | |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 458 | __ vmrs(r1); |
| 459 | // Set custom FPSCR. |
| 460 | __ bic(r2, r1, Operand(kVFPRoundingModeMask | kVFPExceptionMask)); |
| 461 | __ orr(r2, r2, Operand(mode)); |
| 462 | __ vmsr(r2); |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 463 | |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 464 | // Load value, convert, and move back result to r0 if everything went well. |
| 465 | __ vmov(d1, value); |
| 466 | switch (types) { |
| 467 | case s32_f64: |
| 468 | __ vcvt_s32_f64(s0, d1, kFPSCRRounding); |
| 469 | break; |
| 470 | |
| 471 | case u32_f64: |
| 472 | __ vcvt_u32_f64(s0, d1, kFPSCRRounding); |
| 473 | break; |
| 474 | |
| 475 | default: |
| 476 | UNREACHABLE(); |
| 477 | break; |
| 478 | } |
| 479 | // Check for vfp exceptions |
| 480 | __ vmrs(r2); |
| 481 | __ tst(r2, Operand(kVFPExceptionMask)); |
| 482 | // Check that we behaved as expected. |
| 483 | __ b(&wrong_exception, |
| 484 | expected_exception ? eq : ne); |
| 485 | // There was no exception. Retrieve the result and return. |
| 486 | __ vmov(r0, s0); |
| 487 | __ mov(pc, Operand(lr)); |
| 488 | |
| 489 | // The exception behaviour is not what we expected. |
| 490 | // Load a special value and return. |
| 491 | __ bind(&wrong_exception); |
| 492 | __ mov(r0, Operand(11223344)); |
| 493 | __ mov(pc, Operand(lr)); |
| 494 | |
| 495 | CodeDesc desc; |
| 496 | assm.GetCode(&desc); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 497 | Handle<Code> code = isolate->factory()->NewCode( |
| 498 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 499 | #ifdef DEBUG |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 500 | OFStream os(stdout); |
| 501 | code->Print(os); |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 502 | #endif |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 503 | F1 f = FUNCTION_CAST<F1>(code->entry()); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 504 | int res = |
| 505 | reinterpret_cast<int>(CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 506 | ::printf("res = %d\n", res); |
| 507 | CHECK_EQ(expected, res); |
| 508 | } |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 509 | } |
| 510 | |
| 511 | |
| 512 | TEST(7) { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 513 | CcTest::InitializeVM(); |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 514 | // Test vfp rounding modes. |
| 515 | |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 516 | // s32_f64 (double to integer). |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 517 | |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 518 | TestRoundingMode(s32_f64, RN, 0, 0); |
| 519 | TestRoundingMode(s32_f64, RN, 0.5, 0); |
| 520 | TestRoundingMode(s32_f64, RN, -0.5, 0); |
| 521 | TestRoundingMode(s32_f64, RN, 1.5, 2); |
| 522 | TestRoundingMode(s32_f64, RN, -1.5, -2); |
| 523 | TestRoundingMode(s32_f64, RN, 123.7, 124); |
| 524 | TestRoundingMode(s32_f64, RN, -123.7, -124); |
| 525 | TestRoundingMode(s32_f64, RN, 123456.2, 123456); |
| 526 | TestRoundingMode(s32_f64, RN, -123456.2, -123456); |
| 527 | TestRoundingMode(s32_f64, RN, static_cast<double>(kMaxInt), kMaxInt); |
| 528 | TestRoundingMode(s32_f64, RN, (kMaxInt + 0.49), kMaxInt); |
| 529 | TestRoundingMode(s32_f64, RN, (kMaxInt + 1.0), kMaxInt, true); |
| 530 | TestRoundingMode(s32_f64, RN, (kMaxInt + 0.5), kMaxInt, true); |
| 531 | TestRoundingMode(s32_f64, RN, static_cast<double>(kMinInt), kMinInt); |
| 532 | TestRoundingMode(s32_f64, RN, (kMinInt - 0.5), kMinInt); |
| 533 | TestRoundingMode(s32_f64, RN, (kMinInt - 1.0), kMinInt, true); |
| 534 | TestRoundingMode(s32_f64, RN, (kMinInt - 0.51), kMinInt, true); |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 535 | |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 536 | TestRoundingMode(s32_f64, RM, 0, 0); |
| 537 | TestRoundingMode(s32_f64, RM, 0.5, 0); |
| 538 | TestRoundingMode(s32_f64, RM, -0.5, -1); |
| 539 | TestRoundingMode(s32_f64, RM, 123.7, 123); |
| 540 | TestRoundingMode(s32_f64, RM, -123.7, -124); |
| 541 | TestRoundingMode(s32_f64, RM, 123456.2, 123456); |
| 542 | TestRoundingMode(s32_f64, RM, -123456.2, -123457); |
| 543 | TestRoundingMode(s32_f64, RM, static_cast<double>(kMaxInt), kMaxInt); |
| 544 | TestRoundingMode(s32_f64, RM, (kMaxInt + 0.5), kMaxInt); |
| 545 | TestRoundingMode(s32_f64, RM, (kMaxInt + 1.0), kMaxInt, true); |
| 546 | TestRoundingMode(s32_f64, RM, static_cast<double>(kMinInt), kMinInt); |
| 547 | TestRoundingMode(s32_f64, RM, (kMinInt - 0.5), kMinInt, true); |
| 548 | TestRoundingMode(s32_f64, RM, (kMinInt + 0.5), kMinInt); |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 549 | |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 550 | TestRoundingMode(s32_f64, RZ, 0, 0); |
| 551 | TestRoundingMode(s32_f64, RZ, 0.5, 0); |
| 552 | TestRoundingMode(s32_f64, RZ, -0.5, 0); |
| 553 | TestRoundingMode(s32_f64, RZ, 123.7, 123); |
| 554 | TestRoundingMode(s32_f64, RZ, -123.7, -123); |
| 555 | TestRoundingMode(s32_f64, RZ, 123456.2, 123456); |
| 556 | TestRoundingMode(s32_f64, RZ, -123456.2, -123456); |
| 557 | TestRoundingMode(s32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt); |
| 558 | TestRoundingMode(s32_f64, RZ, (kMaxInt + 0.5), kMaxInt); |
| 559 | TestRoundingMode(s32_f64, RZ, (kMaxInt + 1.0), kMaxInt, true); |
| 560 | TestRoundingMode(s32_f64, RZ, static_cast<double>(kMinInt), kMinInt); |
| 561 | TestRoundingMode(s32_f64, RZ, (kMinInt - 0.5), kMinInt); |
| 562 | TestRoundingMode(s32_f64, RZ, (kMinInt - 1.0), kMinInt, true); |
| 563 | |
| 564 | |
| 565 | // u32_f64 (double to integer). |
| 566 | |
| 567 | // Negative values. |
| 568 | TestRoundingMode(u32_f64, RN, -0.5, 0); |
| 569 | TestRoundingMode(u32_f64, RN, -123456.7, 0, true); |
| 570 | TestRoundingMode(u32_f64, RN, static_cast<double>(kMinInt), 0, true); |
| 571 | TestRoundingMode(u32_f64, RN, kMinInt - 1.0, 0, true); |
| 572 | |
| 573 | TestRoundingMode(u32_f64, RM, -0.5, 0, true); |
| 574 | TestRoundingMode(u32_f64, RM, -123456.7, 0, true); |
| 575 | TestRoundingMode(u32_f64, RM, static_cast<double>(kMinInt), 0, true); |
| 576 | TestRoundingMode(u32_f64, RM, kMinInt - 1.0, 0, true); |
| 577 | |
| 578 | TestRoundingMode(u32_f64, RZ, -0.5, 0); |
| 579 | TestRoundingMode(u32_f64, RZ, -123456.7, 0, true); |
| 580 | TestRoundingMode(u32_f64, RZ, static_cast<double>(kMinInt), 0, true); |
| 581 | TestRoundingMode(u32_f64, RZ, kMinInt - 1.0, 0, true); |
| 582 | |
| 583 | // Positive values. |
| 584 | // kMaxInt is the maximum *signed* integer: 0x7fffffff. |
| 585 | static const uint32_t kMaxUInt = 0xffffffffu; |
| 586 | TestRoundingMode(u32_f64, RZ, 0, 0); |
| 587 | TestRoundingMode(u32_f64, RZ, 0.5, 0); |
| 588 | TestRoundingMode(u32_f64, RZ, 123.7, 123); |
| 589 | TestRoundingMode(u32_f64, RZ, 123456.2, 123456); |
| 590 | TestRoundingMode(u32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt); |
| 591 | TestRoundingMode(u32_f64, RZ, (kMaxInt + 0.5), kMaxInt); |
| 592 | TestRoundingMode(u32_f64, RZ, (kMaxInt + 1.0), |
| 593 | static_cast<uint32_t>(kMaxInt) + 1); |
| 594 | TestRoundingMode(u32_f64, RZ, (kMaxUInt + 0.5), kMaxUInt); |
| 595 | TestRoundingMode(u32_f64, RZ, (kMaxUInt + 1.0), kMaxUInt, true); |
| 596 | |
| 597 | TestRoundingMode(u32_f64, RM, 0, 0); |
| 598 | TestRoundingMode(u32_f64, RM, 0.5, 0); |
| 599 | TestRoundingMode(u32_f64, RM, 123.7, 123); |
| 600 | TestRoundingMode(u32_f64, RM, 123456.2, 123456); |
| 601 | TestRoundingMode(u32_f64, RM, static_cast<double>(kMaxInt), kMaxInt); |
| 602 | TestRoundingMode(u32_f64, RM, (kMaxInt + 0.5), kMaxInt); |
| 603 | TestRoundingMode(u32_f64, RM, (kMaxInt + 1.0), |
| 604 | static_cast<uint32_t>(kMaxInt) + 1); |
| 605 | TestRoundingMode(u32_f64, RM, (kMaxUInt + 0.5), kMaxUInt); |
| 606 | TestRoundingMode(u32_f64, RM, (kMaxUInt + 1.0), kMaxUInt, true); |
| 607 | |
| 608 | TestRoundingMode(u32_f64, RN, 0, 0); |
| 609 | TestRoundingMode(u32_f64, RN, 0.5, 0); |
| 610 | TestRoundingMode(u32_f64, RN, 1.5, 2); |
| 611 | TestRoundingMode(u32_f64, RN, 123.7, 124); |
| 612 | TestRoundingMode(u32_f64, RN, 123456.2, 123456); |
| 613 | TestRoundingMode(u32_f64, RN, static_cast<double>(kMaxInt), kMaxInt); |
| 614 | TestRoundingMode(u32_f64, RN, (kMaxInt + 0.49), kMaxInt); |
| 615 | TestRoundingMode(u32_f64, RN, (kMaxInt + 0.5), |
| 616 | static_cast<uint32_t>(kMaxInt) + 1); |
| 617 | TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.49), kMaxUInt); |
| 618 | TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.5), kMaxUInt, true); |
| 619 | TestRoundingMode(u32_f64, RN, (kMaxUInt + 1.0), kMaxUInt, true); |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 620 | } |
| 621 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 622 | |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 623 | TEST(8) { |
| 624 | // Test VFP multi load/store with ia_w. |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 625 | CcTest::InitializeVM(); |
| 626 | Isolate* isolate = CcTest::i_isolate(); |
| 627 | HandleScope scope(isolate); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 628 | |
| 629 | typedef struct { |
| 630 | double a; |
| 631 | double b; |
| 632 | double c; |
| 633 | double d; |
| 634 | double e; |
| 635 | double f; |
| 636 | double g; |
| 637 | double h; |
| 638 | } D; |
| 639 | D d; |
| 640 | |
| 641 | typedef struct { |
| 642 | float a; |
| 643 | float b; |
| 644 | float c; |
| 645 | float d; |
| 646 | float e; |
| 647 | float f; |
| 648 | float g; |
| 649 | float h; |
| 650 | } F; |
| 651 | F f; |
| 652 | |
| 653 | // Create a function that uses vldm/vstm to move some double and |
| 654 | // single precision values around in memory. |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 655 | Assembler assm(isolate, NULL, 0); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 656 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 657 | __ mov(ip, Operand(sp)); |
| 658 | __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); |
| 659 | __ sub(fp, ip, Operand(4)); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 660 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 661 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, a)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 662 | __ vldm(ia_w, r4, d0, d3); |
| 663 | __ vldm(ia_w, r4, d4, d7); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 664 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 665 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, a)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 666 | __ vstm(ia_w, r4, d6, d7); |
| 667 | __ vstm(ia_w, r4, d0, d5); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 668 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 669 | __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, a)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 670 | __ vldm(ia_w, r4, s0, s3); |
| 671 | __ vldm(ia_w, r4, s4, s7); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 672 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 673 | __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, a)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 674 | __ vstm(ia_w, r4, s6, s7); |
| 675 | __ vstm(ia_w, r4, s0, s5); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 676 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 677 | __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 678 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 679 | CodeDesc desc; |
| 680 | assm.GetCode(&desc); |
| 681 | Handle<Code> code = isolate->factory()->NewCode( |
| 682 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 683 | #ifdef DEBUG |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 684 | OFStream os(stdout); |
| 685 | code->Print(os); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 686 | #endif |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 687 | F4 fn = FUNCTION_CAST<F4>(code->entry()); |
| 688 | d.a = 1.1; |
| 689 | d.b = 2.2; |
| 690 | d.c = 3.3; |
| 691 | d.d = 4.4; |
| 692 | d.e = 5.5; |
| 693 | d.f = 6.6; |
| 694 | d.g = 7.7; |
| 695 | d.h = 8.8; |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 696 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 697 | f.a = 1.0; |
| 698 | f.b = 2.0; |
| 699 | f.c = 3.0; |
| 700 | f.d = 4.0; |
| 701 | f.e = 5.0; |
| 702 | f.f = 6.0; |
| 703 | f.g = 7.0; |
| 704 | f.h = 8.0; |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 705 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 706 | Object* dummy = CALL_GENERATED_CODE(isolate, fn, &d, &f, 0, 0, 0); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 707 | USE(dummy); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 708 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 709 | CHECK_EQ(7.7, d.a); |
| 710 | CHECK_EQ(8.8, d.b); |
| 711 | CHECK_EQ(1.1, d.c); |
| 712 | CHECK_EQ(2.2, d.d); |
| 713 | CHECK_EQ(3.3, d.e); |
| 714 | CHECK_EQ(4.4, d.f); |
| 715 | CHECK_EQ(5.5, d.g); |
| 716 | CHECK_EQ(6.6, d.h); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 717 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 718 | CHECK_EQ(7.0f, f.a); |
| 719 | CHECK_EQ(8.0f, f.b); |
| 720 | CHECK_EQ(1.0f, f.c); |
| 721 | CHECK_EQ(2.0f, f.d); |
| 722 | CHECK_EQ(3.0f, f.e); |
| 723 | CHECK_EQ(4.0f, f.f); |
| 724 | CHECK_EQ(5.0f, f.g); |
| 725 | CHECK_EQ(6.0f, f.h); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 726 | } |
| 727 | |
| 728 | |
| 729 | TEST(9) { |
| 730 | // Test VFP multi load/store with ia. |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 731 | CcTest::InitializeVM(); |
| 732 | Isolate* isolate = CcTest::i_isolate(); |
| 733 | HandleScope scope(isolate); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 734 | |
| 735 | typedef struct { |
| 736 | double a; |
| 737 | double b; |
| 738 | double c; |
| 739 | double d; |
| 740 | double e; |
| 741 | double f; |
| 742 | double g; |
| 743 | double h; |
| 744 | } D; |
| 745 | D d; |
| 746 | |
| 747 | typedef struct { |
| 748 | float a; |
| 749 | float b; |
| 750 | float c; |
| 751 | float d; |
| 752 | float e; |
| 753 | float f; |
| 754 | float g; |
| 755 | float h; |
| 756 | } F; |
| 757 | F f; |
| 758 | |
| 759 | // Create a function that uses vldm/vstm to move some double and |
| 760 | // single precision values around in memory. |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 761 | Assembler assm(isolate, NULL, 0); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 762 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 763 | __ mov(ip, Operand(sp)); |
| 764 | __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); |
| 765 | __ sub(fp, ip, Operand(4)); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 766 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 767 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, a)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 768 | __ vldm(ia, r4, d0, d3); |
| 769 | __ add(r4, r4, Operand(4 * 8)); |
| 770 | __ vldm(ia, r4, d4, d7); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 771 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 772 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, a)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 773 | __ vstm(ia, r4, d6, d7); |
| 774 | __ add(r4, r4, Operand(2 * 8)); |
| 775 | __ vstm(ia, r4, d0, d5); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 776 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 777 | __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, a)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 778 | __ vldm(ia, r4, s0, s3); |
| 779 | __ add(r4, r4, Operand(4 * 4)); |
| 780 | __ vldm(ia, r4, s4, s7); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 781 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 782 | __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, a)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 783 | __ vstm(ia, r4, s6, s7); |
| 784 | __ add(r4, r4, Operand(2 * 4)); |
| 785 | __ vstm(ia, r4, s0, s5); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 786 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 787 | __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 788 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 789 | CodeDesc desc; |
| 790 | assm.GetCode(&desc); |
| 791 | Handle<Code> code = isolate->factory()->NewCode( |
| 792 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 793 | #ifdef DEBUG |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 794 | OFStream os(stdout); |
| 795 | code->Print(os); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 796 | #endif |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 797 | F4 fn = FUNCTION_CAST<F4>(code->entry()); |
| 798 | d.a = 1.1; |
| 799 | d.b = 2.2; |
| 800 | d.c = 3.3; |
| 801 | d.d = 4.4; |
| 802 | d.e = 5.5; |
| 803 | d.f = 6.6; |
| 804 | d.g = 7.7; |
| 805 | d.h = 8.8; |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 806 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 807 | f.a = 1.0; |
| 808 | f.b = 2.0; |
| 809 | f.c = 3.0; |
| 810 | f.d = 4.0; |
| 811 | f.e = 5.0; |
| 812 | f.f = 6.0; |
| 813 | f.g = 7.0; |
| 814 | f.h = 8.0; |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 815 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 816 | Object* dummy = CALL_GENERATED_CODE(isolate, fn, &d, &f, 0, 0, 0); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 817 | USE(dummy); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 818 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 819 | CHECK_EQ(7.7, d.a); |
| 820 | CHECK_EQ(8.8, d.b); |
| 821 | CHECK_EQ(1.1, d.c); |
| 822 | CHECK_EQ(2.2, d.d); |
| 823 | CHECK_EQ(3.3, d.e); |
| 824 | CHECK_EQ(4.4, d.f); |
| 825 | CHECK_EQ(5.5, d.g); |
| 826 | CHECK_EQ(6.6, d.h); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 827 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 828 | CHECK_EQ(7.0f, f.a); |
| 829 | CHECK_EQ(8.0f, f.b); |
| 830 | CHECK_EQ(1.0f, f.c); |
| 831 | CHECK_EQ(2.0f, f.d); |
| 832 | CHECK_EQ(3.0f, f.e); |
| 833 | CHECK_EQ(4.0f, f.f); |
| 834 | CHECK_EQ(5.0f, f.g); |
| 835 | CHECK_EQ(6.0f, f.h); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 836 | } |
| 837 | |
| 838 | |
| 839 | TEST(10) { |
| 840 | // Test VFP multi load/store with db_w. |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 841 | CcTest::InitializeVM(); |
| 842 | Isolate* isolate = CcTest::i_isolate(); |
| 843 | HandleScope scope(isolate); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 844 | |
| 845 | typedef struct { |
| 846 | double a; |
| 847 | double b; |
| 848 | double c; |
| 849 | double d; |
| 850 | double e; |
| 851 | double f; |
| 852 | double g; |
| 853 | double h; |
| 854 | } D; |
| 855 | D d; |
| 856 | |
| 857 | typedef struct { |
| 858 | float a; |
| 859 | float b; |
| 860 | float c; |
| 861 | float d; |
| 862 | float e; |
| 863 | float f; |
| 864 | float g; |
| 865 | float h; |
| 866 | } F; |
| 867 | F f; |
| 868 | |
| 869 | // Create a function that uses vldm/vstm to move some double and |
| 870 | // single precision values around in memory. |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 871 | Assembler assm(isolate, NULL, 0); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 872 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 873 | __ mov(ip, Operand(sp)); |
| 874 | __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); |
| 875 | __ sub(fp, ip, Operand(4)); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 876 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 877 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, h)) + 8)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 878 | __ vldm(db_w, r4, d4, d7); |
| 879 | __ vldm(db_w, r4, d0, d3); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 880 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 881 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, h)) + 8)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 882 | __ vstm(db_w, r4, d0, d5); |
| 883 | __ vstm(db_w, r4, d6, d7); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 884 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 885 | __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, h)) + 4)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 886 | __ vldm(db_w, r4, s4, s7); |
| 887 | __ vldm(db_w, r4, s0, s3); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 888 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 889 | __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, h)) + 4)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 890 | __ vstm(db_w, r4, s0, s5); |
| 891 | __ vstm(db_w, r4, s6, s7); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 892 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 893 | __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 894 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 895 | CodeDesc desc; |
| 896 | assm.GetCode(&desc); |
| 897 | Handle<Code> code = isolate->factory()->NewCode( |
| 898 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 899 | #ifdef DEBUG |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 900 | OFStream os(stdout); |
| 901 | code->Print(os); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 902 | #endif |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 903 | F4 fn = FUNCTION_CAST<F4>(code->entry()); |
| 904 | d.a = 1.1; |
| 905 | d.b = 2.2; |
| 906 | d.c = 3.3; |
| 907 | d.d = 4.4; |
| 908 | d.e = 5.5; |
| 909 | d.f = 6.6; |
| 910 | d.g = 7.7; |
| 911 | d.h = 8.8; |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 912 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 913 | f.a = 1.0; |
| 914 | f.b = 2.0; |
| 915 | f.c = 3.0; |
| 916 | f.d = 4.0; |
| 917 | f.e = 5.0; |
| 918 | f.f = 6.0; |
| 919 | f.g = 7.0; |
| 920 | f.h = 8.0; |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 921 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 922 | Object* dummy = CALL_GENERATED_CODE(isolate, fn, &d, &f, 0, 0, 0); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 923 | USE(dummy); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 924 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 925 | CHECK_EQ(7.7, d.a); |
| 926 | CHECK_EQ(8.8, d.b); |
| 927 | CHECK_EQ(1.1, d.c); |
| 928 | CHECK_EQ(2.2, d.d); |
| 929 | CHECK_EQ(3.3, d.e); |
| 930 | CHECK_EQ(4.4, d.f); |
| 931 | CHECK_EQ(5.5, d.g); |
| 932 | CHECK_EQ(6.6, d.h); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 933 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 934 | CHECK_EQ(7.0f, f.a); |
| 935 | CHECK_EQ(8.0f, f.b); |
| 936 | CHECK_EQ(1.0f, f.c); |
| 937 | CHECK_EQ(2.0f, f.d); |
| 938 | CHECK_EQ(3.0f, f.e); |
| 939 | CHECK_EQ(4.0f, f.f); |
| 940 | CHECK_EQ(5.0f, f.g); |
| 941 | CHECK_EQ(6.0f, f.h); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 942 | } |
| 943 | |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 944 | |
| 945 | TEST(11) { |
| 946 | // Test instructions using the carry flag. |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 947 | CcTest::InitializeVM(); |
| 948 | Isolate* isolate = CcTest::i_isolate(); |
| 949 | HandleScope scope(isolate); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 950 | |
| 951 | typedef struct { |
| 952 | int32_t a; |
| 953 | int32_t b; |
| 954 | int32_t c; |
| 955 | int32_t d; |
| 956 | } I; |
| 957 | I i; |
| 958 | |
| 959 | i.a = 0xabcd0001; |
| 960 | i.b = 0xabcd0000; |
| 961 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 962 | Assembler assm(isolate, NULL, 0); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 963 | |
| 964 | // Test HeapObject untagging. |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 965 | __ ldr(r1, MemOperand(r0, offsetof(I, a))); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 966 | __ mov(r1, Operand(r1, ASR, 1), SetCC); |
| 967 | __ adc(r1, r1, Operand(r1), LeaveCC, cs); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 968 | __ str(r1, MemOperand(r0, offsetof(I, a))); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 969 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 970 | __ ldr(r2, MemOperand(r0, offsetof(I, b))); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 971 | __ mov(r2, Operand(r2, ASR, 1), SetCC); |
| 972 | __ adc(r2, r2, Operand(r2), LeaveCC, cs); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 973 | __ str(r2, MemOperand(r0, offsetof(I, b))); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 974 | |
| 975 | // Test corner cases. |
| 976 | __ mov(r1, Operand(0xffffffff)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 977 | __ mov(r2, Operand::Zero()); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 978 | __ mov(r3, Operand(r1, ASR, 1), SetCC); // Set the carry. |
| 979 | __ adc(r3, r1, Operand(r2)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 980 | __ str(r3, MemOperand(r0, offsetof(I, c))); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 981 | |
| 982 | __ mov(r1, Operand(0xffffffff)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 983 | __ mov(r2, Operand::Zero()); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 984 | __ mov(r3, Operand(r2, ASR, 1), SetCC); // Unset the carry. |
| 985 | __ adc(r3, r1, Operand(r2)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 986 | __ str(r3, MemOperand(r0, offsetof(I, d))); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 987 | |
| 988 | __ mov(pc, Operand(lr)); |
| 989 | |
| 990 | CodeDesc desc; |
| 991 | assm.GetCode(&desc); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 992 | Handle<Code> code = isolate->factory()->NewCode( |
| 993 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 994 | #ifdef DEBUG |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 995 | OFStream os(stdout); |
| 996 | code->Print(os); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 997 | #endif |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 998 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 999 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &i, 0, 0, 0, 0); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 1000 | USE(dummy); |
| 1001 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1002 | CHECK_EQ(static_cast<int32_t>(0xabcd0001), i.a); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 1003 | CHECK_EQ(static_cast<int32_t>(0xabcd0000) >> 1, i.b); |
| 1004 | CHECK_EQ(0x00000000, i.c); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1005 | CHECK_EQ(static_cast<int32_t>(0xffffffff), i.d); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 1006 | } |
| 1007 | |
Ben Murdoch | 69a99ed | 2011-11-30 16:03:39 +0000 | [diff] [blame] | 1008 | |
| 1009 | TEST(12) { |
| 1010 | // Test chaining of label usages within instructions (issue 1644). |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1011 | CcTest::InitializeVM(); |
| 1012 | Isolate* isolate = CcTest::i_isolate(); |
| 1013 | HandleScope scope(isolate); |
Ben Murdoch | 69a99ed | 2011-11-30 16:03:39 +0000 | [diff] [blame] | 1014 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1015 | Assembler assm(isolate, NULL, 0); |
Ben Murdoch | 69a99ed | 2011-11-30 16:03:39 +0000 | [diff] [blame] | 1016 | Label target; |
| 1017 | __ b(eq, &target); |
| 1018 | __ b(ne, &target); |
| 1019 | __ bind(&target); |
| 1020 | __ nop(); |
| 1021 | } |
| 1022 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1023 | |
| 1024 | TEST(13) { |
| 1025 | // Test VFP instructions using registers d16-d31. |
| 1026 | CcTest::InitializeVM(); |
| 1027 | Isolate* isolate = CcTest::i_isolate(); |
| 1028 | HandleScope scope(isolate); |
| 1029 | |
| 1030 | if (!CpuFeatures::IsSupported(VFP32DREGS)) { |
| 1031 | return; |
| 1032 | } |
| 1033 | |
| 1034 | typedef struct { |
| 1035 | double a; |
| 1036 | double b; |
| 1037 | double c; |
| 1038 | double x; |
| 1039 | double y; |
| 1040 | double z; |
| 1041 | double i; |
| 1042 | double j; |
| 1043 | double k; |
| 1044 | uint32_t low; |
| 1045 | uint32_t high; |
| 1046 | } T; |
| 1047 | T t; |
| 1048 | |
| 1049 | // Create a function that accepts &t, and loads, manipulates, and stores |
| 1050 | // the doubles and floats. |
| 1051 | Assembler assm(isolate, NULL, 0); |
| 1052 | Label L, C; |
| 1053 | |
| 1054 | |
| 1055 | if (CpuFeatures::IsSupported(VFP3)) { |
| 1056 | CpuFeatureScope scope(&assm, VFP3); |
| 1057 | |
| 1058 | __ stm(db_w, sp, r4.bit() | lr.bit()); |
| 1059 | |
| 1060 | // Load a, b, c into d16, d17, d18. |
| 1061 | __ mov(r4, Operand(r0)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1062 | __ vldr(d16, r4, offsetof(T, a)); |
| 1063 | __ vldr(d17, r4, offsetof(T, b)); |
| 1064 | __ vldr(d18, r4, offsetof(T, c)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1065 | |
| 1066 | __ vneg(d25, d16); |
| 1067 | __ vadd(d25, d25, d17); |
| 1068 | __ vsub(d25, d25, d18); |
| 1069 | __ vmul(d25, d25, d25); |
| 1070 | __ vdiv(d25, d25, d18); |
| 1071 | |
| 1072 | __ vmov(d16, d25); |
| 1073 | __ vsqrt(d17, d25); |
| 1074 | __ vneg(d17, d17); |
| 1075 | __ vabs(d17, d17); |
| 1076 | __ vmla(d18, d16, d17); |
| 1077 | |
| 1078 | // Store d16, d17, d18 into a, b, c. |
| 1079 | __ mov(r4, Operand(r0)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1080 | __ vstr(d16, r4, offsetof(T, a)); |
| 1081 | __ vstr(d17, r4, offsetof(T, b)); |
| 1082 | __ vstr(d18, r4, offsetof(T, c)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1083 | |
| 1084 | // Load x, y, z into d29-d31. |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1085 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, x)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1086 | __ vldm(ia_w, r4, d29, d31); |
| 1087 | |
| 1088 | // Swap d29 and d30 via r registers. |
| 1089 | __ vmov(r1, r2, d29); |
| 1090 | __ vmov(d29, d30); |
| 1091 | __ vmov(d30, r1, r2); |
| 1092 | |
| 1093 | // Convert to and from integer. |
| 1094 | __ vcvt_s32_f64(s1, d31); |
| 1095 | __ vcvt_f64_u32(d31, s1); |
| 1096 | |
| 1097 | // Store d29-d31 into x, y, z. |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1098 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, x)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1099 | __ vstm(ia_w, r4, d29, d31); |
| 1100 | |
| 1101 | // Move constants into d20, d21, d22 and store into i, j, k. |
| 1102 | __ vmov(d20, 14.7610017472335499); |
| 1103 | __ vmov(d21, 16.0); |
| 1104 | __ mov(r1, Operand(372106121)); |
| 1105 | __ mov(r2, Operand(1079146608)); |
| 1106 | __ vmov(d22, VmovIndexLo, r1); |
| 1107 | __ vmov(d22, VmovIndexHi, r2); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1108 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, i)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1109 | __ vstm(ia_w, r4, d20, d22); |
| 1110 | // Move d22 into low and high. |
| 1111 | __ vmov(r4, VmovIndexLo, d22); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1112 | __ str(r4, MemOperand(r0, offsetof(T, low))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1113 | __ vmov(r4, VmovIndexHi, d22); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1114 | __ str(r4, MemOperand(r0, offsetof(T, high))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1115 | |
| 1116 | __ ldm(ia_w, sp, r4.bit() | pc.bit()); |
| 1117 | |
| 1118 | CodeDesc desc; |
| 1119 | assm.GetCode(&desc); |
| 1120 | Handle<Code> code = isolate->factory()->NewCode( |
| 1121 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1122 | #ifdef DEBUG |
| 1123 | OFStream os(stdout); |
| 1124 | code->Print(os); |
| 1125 | #endif |
| 1126 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1127 | t.a = 1.5; |
| 1128 | t.b = 2.75; |
| 1129 | t.c = 17.17; |
| 1130 | t.x = 1.5; |
| 1131 | t.y = 2.75; |
| 1132 | t.z = 17.17; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1133 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1134 | USE(dummy); |
| 1135 | CHECK_EQ(14.7610017472335499, t.a); |
| 1136 | CHECK_EQ(3.84200491244266251, t.b); |
| 1137 | CHECK_EQ(73.8818412254460241, t.c); |
| 1138 | CHECK_EQ(2.75, t.x); |
| 1139 | CHECK_EQ(1.5, t.y); |
| 1140 | CHECK_EQ(17.0, t.z); |
| 1141 | CHECK_EQ(14.7610017472335499, t.i); |
| 1142 | CHECK_EQ(16.0, t.j); |
| 1143 | CHECK_EQ(73.8818412254460241, t.k); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1144 | CHECK_EQ(372106121u, t.low); |
| 1145 | CHECK_EQ(1079146608u, t.high); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1146 | } |
| 1147 | } |
| 1148 | |
| 1149 | |
| 1150 | TEST(14) { |
| 1151 | // Test the VFP Canonicalized Nan mode. |
| 1152 | CcTest::InitializeVM(); |
| 1153 | Isolate* isolate = CcTest::i_isolate(); |
| 1154 | HandleScope scope(isolate); |
| 1155 | |
| 1156 | typedef struct { |
| 1157 | double left; |
| 1158 | double right; |
| 1159 | double add_result; |
| 1160 | double sub_result; |
| 1161 | double mul_result; |
| 1162 | double div_result; |
| 1163 | } T; |
| 1164 | T t; |
| 1165 | |
| 1166 | // Create a function that makes the four basic operations. |
| 1167 | Assembler assm(isolate, NULL, 0); |
| 1168 | |
| 1169 | // Ensure FPSCR state (as JSEntryStub does). |
| 1170 | Label fpscr_done; |
| 1171 | __ vmrs(r1); |
| 1172 | __ tst(r1, Operand(kVFPDefaultNaNModeControlBit)); |
| 1173 | __ b(ne, &fpscr_done); |
| 1174 | __ orr(r1, r1, Operand(kVFPDefaultNaNModeControlBit)); |
| 1175 | __ vmsr(r1); |
| 1176 | __ bind(&fpscr_done); |
| 1177 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1178 | __ vldr(d0, r0, offsetof(T, left)); |
| 1179 | __ vldr(d1, r0, offsetof(T, right)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1180 | __ vadd(d2, d0, d1); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1181 | __ vstr(d2, r0, offsetof(T, add_result)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1182 | __ vsub(d2, d0, d1); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1183 | __ vstr(d2, r0, offsetof(T, sub_result)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1184 | __ vmul(d2, d0, d1); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1185 | __ vstr(d2, r0, offsetof(T, mul_result)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1186 | __ vdiv(d2, d0, d1); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1187 | __ vstr(d2, r0, offsetof(T, div_result)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1188 | |
| 1189 | __ mov(pc, Operand(lr)); |
| 1190 | |
| 1191 | CodeDesc desc; |
| 1192 | assm.GetCode(&desc); |
| 1193 | Handle<Code> code = isolate->factory()->NewCode( |
| 1194 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1195 | #ifdef DEBUG |
| 1196 | OFStream os(stdout); |
| 1197 | code->Print(os); |
| 1198 | #endif |
| 1199 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1200 | t.left = bit_cast<double>(kHoleNanInt64); |
| 1201 | t.right = 1; |
| 1202 | t.add_result = 0; |
| 1203 | t.sub_result = 0; |
| 1204 | t.mul_result = 0; |
| 1205 | t.div_result = 0; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1206 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1207 | USE(dummy); |
| 1208 | const uint32_t kArmNanUpper32 = 0x7ff80000; |
| 1209 | const uint32_t kArmNanLower32 = 0x00000000; |
| 1210 | #ifdef DEBUG |
| 1211 | const uint64_t kArmNanInt64 = |
| 1212 | (static_cast<uint64_t>(kArmNanUpper32) << 32) | kArmNanLower32; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1213 | CHECK(kArmNanInt64 != kHoleNanInt64); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1214 | #endif |
| 1215 | // With VFP2 the sign of the canonicalized Nan is undefined. So |
| 1216 | // we remove the sign bit for the upper tests. |
| 1217 | CHECK_EQ(kArmNanUpper32, |
| 1218 | (bit_cast<int64_t>(t.add_result) >> 32) & 0x7fffffff); |
| 1219 | CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.add_result) & 0xffffffffu); |
| 1220 | CHECK_EQ(kArmNanUpper32, |
| 1221 | (bit_cast<int64_t>(t.sub_result) >> 32) & 0x7fffffff); |
| 1222 | CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.sub_result) & 0xffffffffu); |
| 1223 | CHECK_EQ(kArmNanUpper32, |
| 1224 | (bit_cast<int64_t>(t.mul_result) >> 32) & 0x7fffffff); |
| 1225 | CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.mul_result) & 0xffffffffu); |
| 1226 | CHECK_EQ(kArmNanUpper32, |
| 1227 | (bit_cast<int64_t>(t.div_result) >> 32) & 0x7fffffff); |
| 1228 | CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.div_result) & 0xffffffffu); |
| 1229 | } |
| 1230 | |
| 1231 | |
| 1232 | TEST(15) { |
| 1233 | // Test the Neon instructions. |
| 1234 | CcTest::InitializeVM(); |
| 1235 | Isolate* isolate = CcTest::i_isolate(); |
| 1236 | HandleScope scope(isolate); |
| 1237 | |
| 1238 | typedef struct { |
| 1239 | uint32_t src0; |
| 1240 | uint32_t src1; |
| 1241 | uint32_t src2; |
| 1242 | uint32_t src3; |
| 1243 | uint32_t src4; |
| 1244 | uint32_t src5; |
| 1245 | uint32_t src6; |
| 1246 | uint32_t src7; |
| 1247 | uint32_t dst0; |
| 1248 | uint32_t dst1; |
| 1249 | uint32_t dst2; |
| 1250 | uint32_t dst3; |
| 1251 | uint32_t dst4; |
| 1252 | uint32_t dst5; |
| 1253 | uint32_t dst6; |
| 1254 | uint32_t dst7; |
| 1255 | uint32_t srcA0; |
| 1256 | uint32_t srcA1; |
| 1257 | uint32_t dstA0; |
| 1258 | uint32_t dstA1; |
| 1259 | uint32_t dstA2; |
| 1260 | uint32_t dstA3; |
| 1261 | uint32_t dstA4; |
| 1262 | uint32_t dstA5; |
| 1263 | uint32_t dstA6; |
| 1264 | uint32_t dstA7; |
| 1265 | } T; |
| 1266 | T t; |
| 1267 | |
| 1268 | // Create a function that accepts &t, and loads, manipulates, and stores |
| 1269 | // the doubles and floats. |
| 1270 | Assembler assm(isolate, NULL, 0); |
| 1271 | |
| 1272 | |
| 1273 | if (CpuFeatures::IsSupported(NEON)) { |
| 1274 | CpuFeatureScope scope(&assm, NEON); |
| 1275 | |
| 1276 | __ stm(db_w, sp, r4.bit() | lr.bit()); |
| 1277 | // Move 32 bytes with neon. |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1278 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, src0)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1279 | __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1280 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, dst0)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1281 | __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4)); |
| 1282 | |
| 1283 | // Expand 8 bytes into 8 words(16 bits). |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1284 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, srcA0)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1285 | __ vld1(Neon8, NeonListOperand(d0), NeonMemOperand(r4)); |
| 1286 | __ vmovl(NeonU8, q0, d0); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1287 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, dstA0)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1288 | __ vst1(Neon8, NeonListOperand(d0, 2), NeonMemOperand(r4)); |
| 1289 | |
| 1290 | // The same expansion, but with different source and destination registers. |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1291 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, srcA0)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1292 | __ vld1(Neon8, NeonListOperand(d1), NeonMemOperand(r4)); |
| 1293 | __ vmovl(NeonU8, q1, d1); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1294 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, dstA4)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1295 | __ vst1(Neon8, NeonListOperand(d2, 2), NeonMemOperand(r4)); |
| 1296 | |
| 1297 | __ ldm(ia_w, sp, r4.bit() | pc.bit()); |
| 1298 | |
| 1299 | CodeDesc desc; |
| 1300 | assm.GetCode(&desc); |
| 1301 | Handle<Code> code = isolate->factory()->NewCode( |
| 1302 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1303 | #ifdef DEBUG |
| 1304 | OFStream os(stdout); |
| 1305 | code->Print(os); |
| 1306 | #endif |
| 1307 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1308 | t.src0 = 0x01020304; |
| 1309 | t.src1 = 0x11121314; |
| 1310 | t.src2 = 0x21222324; |
| 1311 | t.src3 = 0x31323334; |
| 1312 | t.src4 = 0x41424344; |
| 1313 | t.src5 = 0x51525354; |
| 1314 | t.src6 = 0x61626364; |
| 1315 | t.src7 = 0x71727374; |
| 1316 | t.dst0 = 0; |
| 1317 | t.dst1 = 0; |
| 1318 | t.dst2 = 0; |
| 1319 | t.dst3 = 0; |
| 1320 | t.dst4 = 0; |
| 1321 | t.dst5 = 0; |
| 1322 | t.dst6 = 0; |
| 1323 | t.dst7 = 0; |
| 1324 | t.srcA0 = 0x41424344; |
| 1325 | t.srcA1 = 0x81828384; |
| 1326 | t.dstA0 = 0; |
| 1327 | t.dstA1 = 0; |
| 1328 | t.dstA2 = 0; |
| 1329 | t.dstA3 = 0; |
| 1330 | t.dstA4 = 0; |
| 1331 | t.dstA5 = 0; |
| 1332 | t.dstA6 = 0; |
| 1333 | t.dstA7 = 0; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1334 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1335 | USE(dummy); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1336 | CHECK_EQ(0x01020304u, t.dst0); |
| 1337 | CHECK_EQ(0x11121314u, t.dst1); |
| 1338 | CHECK_EQ(0x21222324u, t.dst2); |
| 1339 | CHECK_EQ(0x31323334u, t.dst3); |
| 1340 | CHECK_EQ(0x41424344u, t.dst4); |
| 1341 | CHECK_EQ(0x51525354u, t.dst5); |
| 1342 | CHECK_EQ(0x61626364u, t.dst6); |
| 1343 | CHECK_EQ(0x71727374u, t.dst7); |
| 1344 | CHECK_EQ(0x00430044u, t.dstA0); |
| 1345 | CHECK_EQ(0x00410042u, t.dstA1); |
| 1346 | CHECK_EQ(0x00830084u, t.dstA2); |
| 1347 | CHECK_EQ(0x00810082u, t.dstA3); |
| 1348 | CHECK_EQ(0x00430044u, t.dstA4); |
| 1349 | CHECK_EQ(0x00410042u, t.dstA5); |
| 1350 | CHECK_EQ(0x00830084u, t.dstA6); |
| 1351 | CHECK_EQ(0x00810082u, t.dstA7); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1352 | } |
| 1353 | } |
| 1354 | |
| 1355 | |
| 1356 | TEST(16) { |
| 1357 | // Test the pkh, uxtb, uxtab and uxtb16 instructions. |
| 1358 | CcTest::InitializeVM(); |
| 1359 | Isolate* isolate = CcTest::i_isolate(); |
| 1360 | HandleScope scope(isolate); |
| 1361 | |
| 1362 | typedef struct { |
| 1363 | uint32_t src0; |
| 1364 | uint32_t src1; |
| 1365 | uint32_t src2; |
| 1366 | uint32_t dst0; |
| 1367 | uint32_t dst1; |
| 1368 | uint32_t dst2; |
| 1369 | uint32_t dst3; |
| 1370 | uint32_t dst4; |
| 1371 | } T; |
| 1372 | T t; |
| 1373 | |
| 1374 | // Create a function that accepts &t, and loads, manipulates, and stores |
| 1375 | // the doubles and floats. |
| 1376 | Assembler assm(isolate, NULL, 0); |
| 1377 | |
| 1378 | __ stm(db_w, sp, r4.bit() | lr.bit()); |
| 1379 | |
| 1380 | __ mov(r4, Operand(r0)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1381 | __ ldr(r0, MemOperand(r4, offsetof(T, src0))); |
| 1382 | __ ldr(r1, MemOperand(r4, offsetof(T, src1))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1383 | |
| 1384 | __ pkhbt(r2, r0, Operand(r1, LSL, 8)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1385 | __ str(r2, MemOperand(r4, offsetof(T, dst0))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1386 | |
| 1387 | __ pkhtb(r2, r0, Operand(r1, ASR, 8)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1388 | __ str(r2, MemOperand(r4, offsetof(T, dst1))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1389 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1390 | __ uxtb16(r2, r0, 8); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1391 | __ str(r2, MemOperand(r4, offsetof(T, dst2))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1392 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1393 | __ uxtb(r2, r0, 8); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1394 | __ str(r2, MemOperand(r4, offsetof(T, dst3))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1395 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1396 | __ ldr(r0, MemOperand(r4, offsetof(T, src2))); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1397 | __ uxtab(r2, r0, r1, 8); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1398 | __ str(r2, MemOperand(r4, offsetof(T, dst4))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1399 | |
| 1400 | __ ldm(ia_w, sp, r4.bit() | pc.bit()); |
| 1401 | |
| 1402 | CodeDesc desc; |
| 1403 | assm.GetCode(&desc); |
| 1404 | Handle<Code> code = isolate->factory()->NewCode( |
| 1405 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1406 | #ifdef DEBUG |
| 1407 | OFStream os(stdout); |
| 1408 | code->Print(os); |
| 1409 | #endif |
| 1410 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1411 | t.src0 = 0x01020304; |
| 1412 | t.src1 = 0x11121314; |
| 1413 | t.src2 = 0x11121300; |
| 1414 | t.dst0 = 0; |
| 1415 | t.dst1 = 0; |
| 1416 | t.dst2 = 0; |
| 1417 | t.dst3 = 0; |
| 1418 | t.dst4 = 0; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1419 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1420 | USE(dummy); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1421 | CHECK_EQ(0x12130304u, t.dst0); |
| 1422 | CHECK_EQ(0x01021213u, t.dst1); |
| 1423 | CHECK_EQ(0x00010003u, t.dst2); |
| 1424 | CHECK_EQ(0x00000003u, t.dst3); |
| 1425 | CHECK_EQ(0x11121313u, t.dst4); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1426 | } |
| 1427 | |
| 1428 | |
| 1429 | TEST(17) { |
| 1430 | // Test generating labels at high addresses. |
| 1431 | // Should not assert. |
| 1432 | CcTest::InitializeVM(); |
| 1433 | Isolate* isolate = CcTest::i_isolate(); |
| 1434 | HandleScope scope(isolate); |
| 1435 | |
| 1436 | // Generate a code segment that will be longer than 2^24 bytes. |
| 1437 | Assembler assm(isolate, NULL, 0); |
| 1438 | for (size_t i = 0; i < 1 << 23 ; ++i) { // 2^23 |
| 1439 | __ nop(); |
| 1440 | } |
| 1441 | |
| 1442 | Label target; |
| 1443 | __ b(eq, &target); |
| 1444 | __ bind(&target); |
| 1445 | __ nop(); |
| 1446 | } |
| 1447 | |
| 1448 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1449 | #define TEST_SDIV(expected_, dividend_, divisor_) \ |
| 1450 | t.dividend = dividend_; \ |
| 1451 | t.divisor = divisor_; \ |
| 1452 | t.result = 0; \ |
| 1453 | dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); \ |
| 1454 | CHECK_EQ(expected_, t.result); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1455 | |
| 1456 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1457 | TEST(sdiv) { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1458 | // Test the sdiv. |
| 1459 | CcTest::InitializeVM(); |
| 1460 | Isolate* isolate = CcTest::i_isolate(); |
| 1461 | HandleScope scope(isolate); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1462 | Assembler assm(isolate, NULL, 0); |
| 1463 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1464 | struct T { |
| 1465 | int32_t dividend; |
| 1466 | int32_t divisor; |
| 1467 | int32_t result; |
| 1468 | } t; |
| 1469 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1470 | if (CpuFeatures::IsSupported(SUDIV)) { |
| 1471 | CpuFeatureScope scope(&assm, SUDIV); |
| 1472 | |
| 1473 | __ mov(r3, Operand(r0)); |
| 1474 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1475 | __ ldr(r0, MemOperand(r3, offsetof(T, dividend))); |
| 1476 | __ ldr(r1, MemOperand(r3, offsetof(T, divisor))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1477 | |
| 1478 | __ sdiv(r2, r0, r1); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1479 | __ str(r2, MemOperand(r3, offsetof(T, result))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1480 | |
| 1481 | __ bx(lr); |
| 1482 | |
| 1483 | CodeDesc desc; |
| 1484 | assm.GetCode(&desc); |
| 1485 | Handle<Code> code = isolate->factory()->NewCode( |
| 1486 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1487 | #ifdef DEBUG |
| 1488 | OFStream os(stdout); |
| 1489 | code->Print(os); |
| 1490 | #endif |
| 1491 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1492 | Object* dummy; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1493 | TEST_SDIV(0, kMinInt, 0); |
| 1494 | TEST_SDIV(0, 1024, 0); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1495 | TEST_SDIV(1073741824, kMinInt, -2); |
| 1496 | TEST_SDIV(kMinInt, kMinInt, -1); |
| 1497 | TEST_SDIV(5, 10, 2); |
| 1498 | TEST_SDIV(3, 10, 3); |
| 1499 | TEST_SDIV(-5, 10, -2); |
| 1500 | TEST_SDIV(-3, 10, -3); |
| 1501 | TEST_SDIV(-5, -10, 2); |
| 1502 | TEST_SDIV(-3, -10, 3); |
| 1503 | TEST_SDIV(5, -10, -2); |
| 1504 | TEST_SDIV(3, -10, -3); |
| 1505 | USE(dummy); |
| 1506 | } |
| 1507 | } |
| 1508 | |
| 1509 | |
| 1510 | #undef TEST_SDIV |
| 1511 | |
| 1512 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1513 | #define TEST_UDIV(expected_, dividend_, divisor_) \ |
| 1514 | t.dividend = dividend_; \ |
| 1515 | t.divisor = divisor_; \ |
| 1516 | t.result = 0; \ |
| 1517 | dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); \ |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1518 | CHECK_EQ(expected_, t.result); |
| 1519 | |
| 1520 | |
| 1521 | TEST(udiv) { |
| 1522 | // Test the udiv. |
| 1523 | CcTest::InitializeVM(); |
| 1524 | Isolate* isolate = CcTest::i_isolate(); |
| 1525 | HandleScope scope(isolate); |
| 1526 | Assembler assm(isolate, NULL, 0); |
| 1527 | |
| 1528 | struct T { |
| 1529 | uint32_t dividend; |
| 1530 | uint32_t divisor; |
| 1531 | uint32_t result; |
| 1532 | } t; |
| 1533 | |
| 1534 | if (CpuFeatures::IsSupported(SUDIV)) { |
| 1535 | CpuFeatureScope scope(&assm, SUDIV); |
| 1536 | |
| 1537 | __ mov(r3, Operand(r0)); |
| 1538 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1539 | __ ldr(r0, MemOperand(r3, offsetof(T, dividend))); |
| 1540 | __ ldr(r1, MemOperand(r3, offsetof(T, divisor))); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1541 | |
| 1542 | __ sdiv(r2, r0, r1); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1543 | __ str(r2, MemOperand(r3, offsetof(T, result))); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1544 | |
| 1545 | __ bx(lr); |
| 1546 | |
| 1547 | CodeDesc desc; |
| 1548 | assm.GetCode(&desc); |
| 1549 | Handle<Code> code = isolate->factory()->NewCode( |
| 1550 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1551 | #ifdef DEBUG |
| 1552 | OFStream os(stdout); |
| 1553 | code->Print(os); |
| 1554 | #endif |
| 1555 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1556 | Object* dummy; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1557 | TEST_UDIV(0u, 0, 0); |
| 1558 | TEST_UDIV(0u, 1024, 0); |
| 1559 | TEST_UDIV(5u, 10, 2); |
| 1560 | TEST_UDIV(3u, 10, 3); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1561 | USE(dummy); |
| 1562 | } |
| 1563 | } |
| 1564 | |
| 1565 | |
| 1566 | #undef TEST_UDIV |
| 1567 | |
| 1568 | |
| 1569 | TEST(smmla) { |
| 1570 | CcTest::InitializeVM(); |
| 1571 | Isolate* const isolate = CcTest::i_isolate(); |
| 1572 | HandleScope scope(isolate); |
| 1573 | RandomNumberGenerator* const rng = isolate->random_number_generator(); |
| 1574 | Assembler assm(isolate, nullptr, 0); |
| 1575 | __ smmla(r1, r1, r2, r3); |
| 1576 | __ str(r1, MemOperand(r0)); |
| 1577 | __ bx(lr); |
| 1578 | CodeDesc desc; |
| 1579 | assm.GetCode(&desc); |
| 1580 | Handle<Code> code = isolate->factory()->NewCode( |
| 1581 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1582 | #ifdef OBJECT_PRINT |
| 1583 | code->Print(std::cout); |
| 1584 | #endif |
| 1585 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1586 | for (size_t i = 0; i < 128; ++i) { |
| 1587 | int32_t r, x = rng->NextInt(), y = rng->NextInt(), z = rng->NextInt(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1588 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, y, z, 0); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1589 | CHECK_EQ(bits::SignedMulHighAndAdd32(x, y, z), r); |
| 1590 | USE(dummy); |
| 1591 | } |
| 1592 | } |
| 1593 | |
| 1594 | |
| 1595 | TEST(smmul) { |
| 1596 | CcTest::InitializeVM(); |
| 1597 | Isolate* const isolate = CcTest::i_isolate(); |
| 1598 | HandleScope scope(isolate); |
| 1599 | RandomNumberGenerator* const rng = isolate->random_number_generator(); |
| 1600 | Assembler assm(isolate, nullptr, 0); |
| 1601 | __ smmul(r1, r1, r2); |
| 1602 | __ str(r1, MemOperand(r0)); |
| 1603 | __ bx(lr); |
| 1604 | CodeDesc desc; |
| 1605 | assm.GetCode(&desc); |
| 1606 | Handle<Code> code = isolate->factory()->NewCode( |
| 1607 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1608 | #ifdef OBJECT_PRINT |
| 1609 | code->Print(std::cout); |
| 1610 | #endif |
| 1611 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1612 | for (size_t i = 0; i < 128; ++i) { |
| 1613 | int32_t r, x = rng->NextInt(), y = rng->NextInt(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1614 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, y, 0, 0); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1615 | CHECK_EQ(bits::SignedMulHigh32(x, y), r); |
| 1616 | USE(dummy); |
| 1617 | } |
| 1618 | } |
| 1619 | |
| 1620 | |
| 1621 | TEST(sxtb) { |
| 1622 | CcTest::InitializeVM(); |
| 1623 | Isolate* const isolate = CcTest::i_isolate(); |
| 1624 | HandleScope scope(isolate); |
| 1625 | RandomNumberGenerator* const rng = isolate->random_number_generator(); |
| 1626 | Assembler assm(isolate, nullptr, 0); |
| 1627 | __ sxtb(r1, r1); |
| 1628 | __ str(r1, MemOperand(r0)); |
| 1629 | __ bx(lr); |
| 1630 | CodeDesc desc; |
| 1631 | assm.GetCode(&desc); |
| 1632 | Handle<Code> code = isolate->factory()->NewCode( |
| 1633 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1634 | #ifdef OBJECT_PRINT |
| 1635 | code->Print(std::cout); |
| 1636 | #endif |
| 1637 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1638 | for (size_t i = 0; i < 128; ++i) { |
| 1639 | int32_t r, x = rng->NextInt(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1640 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, 0, 0, 0); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1641 | CHECK_EQ(static_cast<int32_t>(static_cast<int8_t>(x)), r); |
| 1642 | USE(dummy); |
| 1643 | } |
| 1644 | } |
| 1645 | |
| 1646 | |
| 1647 | TEST(sxtab) { |
| 1648 | CcTest::InitializeVM(); |
| 1649 | Isolate* const isolate = CcTest::i_isolate(); |
| 1650 | HandleScope scope(isolate); |
| 1651 | RandomNumberGenerator* const rng = isolate->random_number_generator(); |
| 1652 | Assembler assm(isolate, nullptr, 0); |
| 1653 | __ sxtab(r1, r2, r1); |
| 1654 | __ str(r1, MemOperand(r0)); |
| 1655 | __ bx(lr); |
| 1656 | CodeDesc desc; |
| 1657 | assm.GetCode(&desc); |
| 1658 | Handle<Code> code = isolate->factory()->NewCode( |
| 1659 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1660 | #ifdef OBJECT_PRINT |
| 1661 | code->Print(std::cout); |
| 1662 | #endif |
| 1663 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1664 | for (size_t i = 0; i < 128; ++i) { |
| 1665 | int32_t r, x = rng->NextInt(), y = rng->NextInt(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1666 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, y, 0, 0); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1667 | CHECK_EQ(static_cast<int32_t>(static_cast<int8_t>(x)) + y, r); |
| 1668 | USE(dummy); |
| 1669 | } |
| 1670 | } |
| 1671 | |
| 1672 | |
| 1673 | TEST(sxth) { |
| 1674 | CcTest::InitializeVM(); |
| 1675 | Isolate* const isolate = CcTest::i_isolate(); |
| 1676 | HandleScope scope(isolate); |
| 1677 | RandomNumberGenerator* const rng = isolate->random_number_generator(); |
| 1678 | Assembler assm(isolate, nullptr, 0); |
| 1679 | __ sxth(r1, r1); |
| 1680 | __ str(r1, MemOperand(r0)); |
| 1681 | __ bx(lr); |
| 1682 | CodeDesc desc; |
| 1683 | assm.GetCode(&desc); |
| 1684 | Handle<Code> code = isolate->factory()->NewCode( |
| 1685 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1686 | #ifdef OBJECT_PRINT |
| 1687 | code->Print(std::cout); |
| 1688 | #endif |
| 1689 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1690 | for (size_t i = 0; i < 128; ++i) { |
| 1691 | int32_t r, x = rng->NextInt(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1692 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, 0, 0, 0); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1693 | CHECK_EQ(static_cast<int32_t>(static_cast<int16_t>(x)), r); |
| 1694 | USE(dummy); |
| 1695 | } |
| 1696 | } |
| 1697 | |
| 1698 | |
| 1699 | TEST(sxtah) { |
| 1700 | CcTest::InitializeVM(); |
| 1701 | Isolate* const isolate = CcTest::i_isolate(); |
| 1702 | HandleScope scope(isolate); |
| 1703 | RandomNumberGenerator* const rng = isolate->random_number_generator(); |
| 1704 | Assembler assm(isolate, nullptr, 0); |
| 1705 | __ sxtah(r1, r2, r1); |
| 1706 | __ str(r1, MemOperand(r0)); |
| 1707 | __ bx(lr); |
| 1708 | CodeDesc desc; |
| 1709 | assm.GetCode(&desc); |
| 1710 | Handle<Code> code = isolate->factory()->NewCode( |
| 1711 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1712 | #ifdef OBJECT_PRINT |
| 1713 | code->Print(std::cout); |
| 1714 | #endif |
| 1715 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1716 | for (size_t i = 0; i < 128; ++i) { |
| 1717 | int32_t r, x = rng->NextInt(), y = rng->NextInt(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1718 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, y, 0, 0); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1719 | CHECK_EQ(static_cast<int32_t>(static_cast<int16_t>(x)) + y, r); |
| 1720 | USE(dummy); |
| 1721 | } |
| 1722 | } |
| 1723 | |
| 1724 | |
| 1725 | TEST(uxtb) { |
| 1726 | CcTest::InitializeVM(); |
| 1727 | Isolate* const isolate = CcTest::i_isolate(); |
| 1728 | HandleScope scope(isolate); |
| 1729 | RandomNumberGenerator* const rng = isolate->random_number_generator(); |
| 1730 | Assembler assm(isolate, nullptr, 0); |
| 1731 | __ uxtb(r1, r1); |
| 1732 | __ str(r1, MemOperand(r0)); |
| 1733 | __ bx(lr); |
| 1734 | CodeDesc desc; |
| 1735 | assm.GetCode(&desc); |
| 1736 | Handle<Code> code = isolate->factory()->NewCode( |
| 1737 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1738 | #ifdef OBJECT_PRINT |
| 1739 | code->Print(std::cout); |
| 1740 | #endif |
| 1741 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1742 | for (size_t i = 0; i < 128; ++i) { |
| 1743 | int32_t r, x = rng->NextInt(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1744 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, 0, 0, 0); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1745 | CHECK_EQ(static_cast<int32_t>(static_cast<uint8_t>(x)), r); |
| 1746 | USE(dummy); |
| 1747 | } |
| 1748 | } |
| 1749 | |
| 1750 | |
| 1751 | TEST(uxtab) { |
| 1752 | CcTest::InitializeVM(); |
| 1753 | Isolate* const isolate = CcTest::i_isolate(); |
| 1754 | HandleScope scope(isolate); |
| 1755 | RandomNumberGenerator* const rng = isolate->random_number_generator(); |
| 1756 | Assembler assm(isolate, nullptr, 0); |
| 1757 | __ uxtab(r1, r2, r1); |
| 1758 | __ str(r1, MemOperand(r0)); |
| 1759 | __ bx(lr); |
| 1760 | CodeDesc desc; |
| 1761 | assm.GetCode(&desc); |
| 1762 | Handle<Code> code = isolate->factory()->NewCode( |
| 1763 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1764 | #ifdef OBJECT_PRINT |
| 1765 | code->Print(std::cout); |
| 1766 | #endif |
| 1767 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1768 | for (size_t i = 0; i < 128; ++i) { |
| 1769 | int32_t r, x = rng->NextInt(), y = rng->NextInt(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1770 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, y, 0, 0); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1771 | CHECK_EQ(static_cast<int32_t>(static_cast<uint8_t>(x)) + y, r); |
| 1772 | USE(dummy); |
| 1773 | } |
| 1774 | } |
| 1775 | |
| 1776 | |
| 1777 | TEST(uxth) { |
| 1778 | CcTest::InitializeVM(); |
| 1779 | Isolate* const isolate = CcTest::i_isolate(); |
| 1780 | HandleScope scope(isolate); |
| 1781 | RandomNumberGenerator* const rng = isolate->random_number_generator(); |
| 1782 | Assembler assm(isolate, nullptr, 0); |
| 1783 | __ uxth(r1, r1); |
| 1784 | __ str(r1, MemOperand(r0)); |
| 1785 | __ bx(lr); |
| 1786 | CodeDesc desc; |
| 1787 | assm.GetCode(&desc); |
| 1788 | Handle<Code> code = isolate->factory()->NewCode( |
| 1789 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1790 | #ifdef OBJECT_PRINT |
| 1791 | code->Print(std::cout); |
| 1792 | #endif |
| 1793 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1794 | for (size_t i = 0; i < 128; ++i) { |
| 1795 | int32_t r, x = rng->NextInt(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1796 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, 0, 0, 0); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1797 | CHECK_EQ(static_cast<int32_t>(static_cast<uint16_t>(x)), r); |
| 1798 | USE(dummy); |
| 1799 | } |
| 1800 | } |
| 1801 | |
| 1802 | |
| 1803 | TEST(uxtah) { |
| 1804 | CcTest::InitializeVM(); |
| 1805 | Isolate* const isolate = CcTest::i_isolate(); |
| 1806 | HandleScope scope(isolate); |
| 1807 | RandomNumberGenerator* const rng = isolate->random_number_generator(); |
| 1808 | Assembler assm(isolate, nullptr, 0); |
| 1809 | __ uxtah(r1, r2, r1); |
| 1810 | __ str(r1, MemOperand(r0)); |
| 1811 | __ bx(lr); |
| 1812 | CodeDesc desc; |
| 1813 | assm.GetCode(&desc); |
| 1814 | Handle<Code> code = isolate->factory()->NewCode( |
| 1815 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1816 | #ifdef OBJECT_PRINT |
| 1817 | code->Print(std::cout); |
| 1818 | #endif |
| 1819 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1820 | for (size_t i = 0; i < 128; ++i) { |
| 1821 | int32_t r, x = rng->NextInt(), y = rng->NextInt(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1822 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, y, 0, 0); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1823 | CHECK_EQ(static_cast<int32_t>(static_cast<uint16_t>(x)) + y, r); |
| 1824 | USE(dummy); |
| 1825 | } |
| 1826 | } |
| 1827 | |
| 1828 | |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 1829 | #define TEST_RBIT(expected_, input_) \ |
| 1830 | t.input = input_; \ |
| 1831 | t.result = 0; \ |
| 1832 | dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); \ |
| 1833 | CHECK_EQ(expected_, t.result); |
| 1834 | |
| 1835 | |
| 1836 | TEST(rbit) { |
| 1837 | CcTest::InitializeVM(); |
| 1838 | Isolate* const isolate = CcTest::i_isolate(); |
| 1839 | HandleScope scope(isolate); |
| 1840 | Assembler assm(isolate, nullptr, 0); |
| 1841 | |
| 1842 | if (CpuFeatures::IsSupported(ARMv7)) { |
| 1843 | CpuFeatureScope scope(&assm, ARMv7); |
| 1844 | |
| 1845 | typedef struct { |
| 1846 | uint32_t input; |
| 1847 | uint32_t result; |
| 1848 | } T; |
| 1849 | T t; |
| 1850 | |
| 1851 | __ ldr(r1, MemOperand(r0, offsetof(T, input))); |
| 1852 | __ rbit(r1, r1); |
| 1853 | __ str(r1, MemOperand(r0, offsetof(T, result))); |
| 1854 | __ bx(lr); |
| 1855 | |
| 1856 | CodeDesc desc; |
| 1857 | assm.GetCode(&desc); |
| 1858 | Handle<Code> code = isolate->factory()->NewCode( |
| 1859 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1860 | |
| 1861 | #ifdef OBJECT_PRINT |
| 1862 | code->Print(std::cout); |
| 1863 | #endif |
| 1864 | |
| 1865 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1866 | Object* dummy = NULL; |
| 1867 | TEST_RBIT(0xffffffff, 0xffffffff); |
| 1868 | TEST_RBIT(0x00000000, 0x00000000); |
| 1869 | TEST_RBIT(0xffff0000, 0x0000ffff); |
| 1870 | TEST_RBIT(0xff00ff00, 0x00ff00ff); |
| 1871 | TEST_RBIT(0xf0f0f0f0, 0x0f0f0f0f); |
| 1872 | TEST_RBIT(0x1e6a2c48, 0x12345678); |
| 1873 | USE(dummy); |
| 1874 | } |
| 1875 | } |
| 1876 | |
| 1877 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1878 | TEST(code_relative_offset) { |
| 1879 | // Test extracting the offset of a label from the beginning of the code |
| 1880 | // in a register. |
| 1881 | CcTest::InitializeVM(); |
| 1882 | Isolate* isolate = CcTest::i_isolate(); |
| 1883 | HandleScope scope(isolate); |
| 1884 | // Initialize a code object that will contain the code. |
| 1885 | Handle<Object> code_object(isolate->heap()->undefined_value(), isolate); |
| 1886 | |
| 1887 | Assembler assm(isolate, NULL, 0); |
| 1888 | |
| 1889 | Label start, target_away, target_faraway; |
| 1890 | |
| 1891 | __ stm(db_w, sp, r4.bit() | r5.bit() | lr.bit()); |
| 1892 | |
| 1893 | // r3 is used as the address zero, the test will crash when we load it. |
| 1894 | __ mov(r3, Operand::Zero()); |
| 1895 | |
| 1896 | // r5 will be a pointer to the start of the code. |
| 1897 | __ mov(r5, Operand(code_object)); |
| 1898 | __ mov_label_offset(r4, &start); |
| 1899 | |
| 1900 | __ mov_label_offset(r1, &target_faraway); |
| 1901 | __ str(r1, MemOperand(sp, kPointerSize, NegPreIndex)); |
| 1902 | |
| 1903 | __ mov_label_offset(r1, &target_away); |
| 1904 | |
| 1905 | // Jump straight to 'target_away' the first time and use the relative |
| 1906 | // position the second time. This covers the case when extracting the |
| 1907 | // position of a label which is linked. |
| 1908 | __ mov(r2, Operand::Zero()); |
| 1909 | __ bind(&start); |
| 1910 | __ cmp(r2, Operand::Zero()); |
| 1911 | __ b(eq, &target_away); |
| 1912 | __ add(pc, r5, r1); |
| 1913 | // Emit invalid instructions to push the label between 2^8 and 2^16 |
| 1914 | // instructions away. The test will crash if they are reached. |
| 1915 | for (int i = 0; i < (1 << 10); i++) { |
| 1916 | __ ldr(r3, MemOperand(r3)); |
| 1917 | } |
| 1918 | __ bind(&target_away); |
| 1919 | // This will be hit twice: r0 = r0 + 5 + 5. |
| 1920 | __ add(r0, r0, Operand(5)); |
| 1921 | |
| 1922 | __ ldr(r1, MemOperand(sp, kPointerSize, PostIndex), ne); |
| 1923 | __ add(pc, r5, r4, LeaveCC, ne); |
| 1924 | |
| 1925 | __ mov(r2, Operand(1)); |
| 1926 | __ b(&start); |
| 1927 | // Emit invalid instructions to push the label between 2^16 and 2^24 |
| 1928 | // instructions away. The test will crash if they are reached. |
| 1929 | for (int i = 0; i < (1 << 21); i++) { |
| 1930 | __ ldr(r3, MemOperand(r3)); |
| 1931 | } |
| 1932 | __ bind(&target_faraway); |
| 1933 | // r0 = r0 + 5 + 5 + 11 |
| 1934 | __ add(r0, r0, Operand(11)); |
| 1935 | |
| 1936 | __ ldm(ia_w, sp, r4.bit() | r5.bit() | pc.bit()); |
| 1937 | |
| 1938 | CodeDesc desc; |
| 1939 | assm.GetCode(&desc); |
| 1940 | Handle<Code> code = isolate->factory()->NewCode( |
| 1941 | desc, Code::ComputeFlags(Code::STUB), code_object); |
| 1942 | F1 f = FUNCTION_CAST<F1>(code->entry()); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1943 | int res = |
| 1944 | reinterpret_cast<int>(CALL_GENERATED_CODE(isolate, f, 21, 0, 0, 0, 0)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1945 | ::printf("f() = %d\n", res); |
| 1946 | CHECK_EQ(42, res); |
| 1947 | } |
| 1948 | |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame] | 1949 | TEST(msr_mrs) { |
| 1950 | // Test msr and mrs. |
| 1951 | CcTest::InitializeVM(); |
| 1952 | Isolate* isolate = CcTest::i_isolate(); |
| 1953 | HandleScope scope(isolate); |
| 1954 | |
| 1955 | Assembler assm(isolate, NULL, 0); |
| 1956 | |
| 1957 | // Create a helper function: |
| 1958 | // void TestMsrMrs(uint32_t nzcv, |
| 1959 | // uint32_t * result_conditionals, |
| 1960 | // uint32_t * result_mrs); |
| 1961 | __ msr(CPSR_f, Operand(r0)); |
| 1962 | |
| 1963 | // Test that the condition flags have taken effect. |
| 1964 | __ mov(r3, Operand(0)); |
| 1965 | __ orr(r3, r3, Operand(1 << 31), LeaveCC, mi); // N |
| 1966 | __ orr(r3, r3, Operand(1 << 30), LeaveCC, eq); // Z |
| 1967 | __ orr(r3, r3, Operand(1 << 29), LeaveCC, cs); // C |
| 1968 | __ orr(r3, r3, Operand(1 << 28), LeaveCC, vs); // V |
| 1969 | __ str(r3, MemOperand(r1)); |
| 1970 | |
| 1971 | // Also check mrs, ignoring everything other than the flags. |
| 1972 | __ mrs(r3, CPSR); |
| 1973 | __ and_(r3, r3, Operand(kSpecialCondition)); |
| 1974 | __ str(r3, MemOperand(r2)); |
| 1975 | |
| 1976 | __ bx(lr); |
| 1977 | |
| 1978 | CodeDesc desc; |
| 1979 | assm.GetCode(&desc); |
| 1980 | Handle<Code> code = isolate->factory()->NewCode( |
| 1981 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1982 | #ifdef DEBUG |
| 1983 | OFStream os(stdout); |
| 1984 | code->Print(os); |
| 1985 | #endif |
| 1986 | F5 f = FUNCTION_CAST<F5>(code->entry()); |
| 1987 | Object* dummy = nullptr; |
| 1988 | USE(dummy); |
| 1989 | |
| 1990 | #define CHECK_MSR_MRS(n, z, c, v) \ |
| 1991 | do { \ |
| 1992 | uint32_t nzcv = (n << 31) | (z << 30) | (c << 29) | (v << 28); \ |
| 1993 | uint32_t result_conditionals = -1; \ |
| 1994 | uint32_t result_mrs = -1; \ |
| 1995 | dummy = CALL_GENERATED_CODE(isolate, f, nzcv, &result_conditionals, \ |
| 1996 | &result_mrs, 0, 0); \ |
| 1997 | CHECK_EQ(nzcv, result_conditionals); \ |
| 1998 | CHECK_EQ(nzcv, result_mrs); \ |
| 1999 | } while (0); |
| 2000 | |
| 2001 | // N Z C V |
| 2002 | CHECK_MSR_MRS(0, 0, 0, 0); |
| 2003 | CHECK_MSR_MRS(0, 0, 0, 1); |
| 2004 | CHECK_MSR_MRS(0, 0, 1, 0); |
| 2005 | CHECK_MSR_MRS(0, 0, 1, 1); |
| 2006 | CHECK_MSR_MRS(0, 1, 0, 0); |
| 2007 | CHECK_MSR_MRS(0, 1, 0, 1); |
| 2008 | CHECK_MSR_MRS(0, 1, 1, 0); |
| 2009 | CHECK_MSR_MRS(0, 1, 1, 1); |
| 2010 | CHECK_MSR_MRS(1, 0, 0, 0); |
| 2011 | CHECK_MSR_MRS(1, 0, 0, 1); |
| 2012 | CHECK_MSR_MRS(1, 0, 1, 0); |
| 2013 | CHECK_MSR_MRS(1, 0, 1, 1); |
| 2014 | CHECK_MSR_MRS(1, 1, 0, 0); |
| 2015 | CHECK_MSR_MRS(1, 1, 0, 1); |
| 2016 | CHECK_MSR_MRS(1, 1, 1, 0); |
| 2017 | CHECK_MSR_MRS(1, 1, 1, 1); |
| 2018 | |
| 2019 | #undef CHECK_MSR_MRS |
| 2020 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2021 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2022 | TEST(ARMv8_float32_vrintX) { |
| 2023 | // Test the vrintX floating point instructions. |
| 2024 | CcTest::InitializeVM(); |
| 2025 | Isolate* isolate = CcTest::i_isolate(); |
| 2026 | HandleScope scope(isolate); |
| 2027 | |
| 2028 | typedef struct { |
| 2029 | float input; |
| 2030 | float ar; |
| 2031 | float nr; |
| 2032 | float mr; |
| 2033 | float pr; |
| 2034 | float zr; |
| 2035 | } T; |
| 2036 | T t; |
| 2037 | |
| 2038 | // Create a function that accepts &t, and loads, manipulates, and stores |
| 2039 | // the floats. |
| 2040 | Assembler assm(isolate, NULL, 0); |
| 2041 | Label L, C; |
| 2042 | |
| 2043 | |
| 2044 | if (CpuFeatures::IsSupported(ARMv8)) { |
| 2045 | CpuFeatureScope scope(&assm, ARMv8); |
| 2046 | |
| 2047 | __ mov(ip, Operand(sp)); |
| 2048 | __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); |
| 2049 | |
| 2050 | __ mov(r4, Operand(r0)); |
| 2051 | |
| 2052 | // Test vrinta |
| 2053 | __ vldr(s6, r4, offsetof(T, input)); |
| 2054 | __ vrinta(s5, s6); |
| 2055 | __ vstr(s5, r4, offsetof(T, ar)); |
| 2056 | |
| 2057 | // Test vrintn |
| 2058 | __ vldr(s6, r4, offsetof(T, input)); |
| 2059 | __ vrintn(s5, s6); |
| 2060 | __ vstr(s5, r4, offsetof(T, nr)); |
| 2061 | |
| 2062 | // Test vrintp |
| 2063 | __ vldr(s6, r4, offsetof(T, input)); |
| 2064 | __ vrintp(s5, s6); |
| 2065 | __ vstr(s5, r4, offsetof(T, pr)); |
| 2066 | |
| 2067 | // Test vrintm |
| 2068 | __ vldr(s6, r4, offsetof(T, input)); |
| 2069 | __ vrintm(s5, s6); |
| 2070 | __ vstr(s5, r4, offsetof(T, mr)); |
| 2071 | |
| 2072 | // Test vrintz |
| 2073 | __ vldr(s6, r4, offsetof(T, input)); |
| 2074 | __ vrintz(s5, s6); |
| 2075 | __ vstr(s5, r4, offsetof(T, zr)); |
| 2076 | |
| 2077 | __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); |
| 2078 | |
| 2079 | CodeDesc desc; |
| 2080 | assm.GetCode(&desc); |
| 2081 | Handle<Code> code = isolate->factory()->NewCode( |
| 2082 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 2083 | #ifdef DEBUG |
| 2084 | OFStream os(stdout); |
| 2085 | code->Print(os); |
| 2086 | #endif |
| 2087 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 2088 | |
| 2089 | Object* dummy = nullptr; |
| 2090 | USE(dummy); |
| 2091 | |
| 2092 | #define CHECK_VRINT(input_val, ares, nres, mres, pres, zres) \ |
| 2093 | t.input = input_val; \ |
| 2094 | dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); \ |
| 2095 | CHECK_EQ(ares, t.ar); \ |
| 2096 | CHECK_EQ(nres, t.nr); \ |
| 2097 | CHECK_EQ(mres, t.mr); \ |
| 2098 | CHECK_EQ(pres, t.pr); \ |
| 2099 | CHECK_EQ(zres, t.zr); |
| 2100 | |
| 2101 | CHECK_VRINT(-0.5, -1.0, -0.0, -1.0, -0.0, -0.0) |
| 2102 | CHECK_VRINT(-0.6, -1.0, -1.0, -1.0, -0.0, -0.0) |
| 2103 | CHECK_VRINT(-1.1, -1.0, -1.0, -2.0, -1.0, -1.0) |
| 2104 | CHECK_VRINT(0.5, 1.0, 0.0, 0.0, 1.0, 0.0) |
| 2105 | CHECK_VRINT(0.6, 1.0, 1.0, 0.0, 1.0, 0.0) |
| 2106 | CHECK_VRINT(1.1, 1.0, 1.0, 1.0, 2.0, 1.0) |
| 2107 | float inf = std::numeric_limits<float>::infinity(); |
| 2108 | CHECK_VRINT(inf, inf, inf, inf, inf, inf) |
| 2109 | CHECK_VRINT(-inf, -inf, -inf, -inf, -inf, -inf) |
| 2110 | CHECK_VRINT(-0.0, -0.0, -0.0, -0.0, -0.0, -0.0) |
| 2111 | |
| 2112 | // Check NaN propagation. |
| 2113 | float nan = std::numeric_limits<float>::quiet_NaN(); |
| 2114 | t.input = nan; |
| 2115 | dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); |
| 2116 | CHECK_EQ(bit_cast<int32_t>(nan), bit_cast<int32_t>(t.ar)); |
| 2117 | CHECK_EQ(bit_cast<int32_t>(nan), bit_cast<int32_t>(t.nr)); |
| 2118 | CHECK_EQ(bit_cast<int32_t>(nan), bit_cast<int32_t>(t.mr)); |
| 2119 | CHECK_EQ(bit_cast<int32_t>(nan), bit_cast<int32_t>(t.pr)); |
| 2120 | CHECK_EQ(bit_cast<int32_t>(nan), bit_cast<int32_t>(t.zr)); |
| 2121 | |
| 2122 | #undef CHECK_VRINT |
| 2123 | } |
| 2124 | } |
| 2125 | |
| 2126 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2127 | TEST(ARMv8_vrintX) { |
| 2128 | // Test the vrintX floating point instructions. |
| 2129 | CcTest::InitializeVM(); |
| 2130 | Isolate* isolate = CcTest::i_isolate(); |
| 2131 | HandleScope scope(isolate); |
| 2132 | |
| 2133 | typedef struct { |
| 2134 | double input; |
| 2135 | double ar; |
| 2136 | double nr; |
| 2137 | double mr; |
| 2138 | double pr; |
| 2139 | double zr; |
| 2140 | } T; |
| 2141 | T t; |
| 2142 | |
| 2143 | // Create a function that accepts &t, and loads, manipulates, and stores |
| 2144 | // the doubles and floats. |
| 2145 | Assembler assm(isolate, NULL, 0); |
| 2146 | Label L, C; |
| 2147 | |
| 2148 | |
| 2149 | if (CpuFeatures::IsSupported(ARMv8)) { |
| 2150 | CpuFeatureScope scope(&assm, ARMv8); |
| 2151 | |
| 2152 | __ mov(ip, Operand(sp)); |
| 2153 | __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); |
| 2154 | |
| 2155 | __ mov(r4, Operand(r0)); |
| 2156 | |
| 2157 | // Test vrinta |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2158 | __ vldr(d6, r4, offsetof(T, input)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2159 | __ vrinta(d5, d6); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2160 | __ vstr(d5, r4, offsetof(T, ar)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2161 | |
| 2162 | // Test vrintn |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2163 | __ vldr(d6, r4, offsetof(T, input)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2164 | __ vrintn(d5, d6); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2165 | __ vstr(d5, r4, offsetof(T, nr)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2166 | |
| 2167 | // Test vrintp |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2168 | __ vldr(d6, r4, offsetof(T, input)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2169 | __ vrintp(d5, d6); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2170 | __ vstr(d5, r4, offsetof(T, pr)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2171 | |
| 2172 | // Test vrintm |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2173 | __ vldr(d6, r4, offsetof(T, input)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2174 | __ vrintm(d5, d6); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2175 | __ vstr(d5, r4, offsetof(T, mr)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2176 | |
| 2177 | // Test vrintz |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2178 | __ vldr(d6, r4, offsetof(T, input)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2179 | __ vrintz(d5, d6); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2180 | __ vstr(d5, r4, offsetof(T, zr)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2181 | |
| 2182 | __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); |
| 2183 | |
| 2184 | CodeDesc desc; |
| 2185 | assm.GetCode(&desc); |
| 2186 | Handle<Code> code = isolate->factory()->NewCode( |
| 2187 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 2188 | #ifdef DEBUG |
| 2189 | OFStream os(stdout); |
| 2190 | code->Print(os); |
| 2191 | #endif |
| 2192 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 2193 | |
| 2194 | Object* dummy = nullptr; |
| 2195 | USE(dummy); |
| 2196 | |
| 2197 | #define CHECK_VRINT(input_val, ares, nres, mres, pres, zres) \ |
| 2198 | t.input = input_val; \ |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2199 | dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); \ |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2200 | CHECK_EQ(ares, t.ar); \ |
| 2201 | CHECK_EQ(nres, t.nr); \ |
| 2202 | CHECK_EQ(mres, t.mr); \ |
| 2203 | CHECK_EQ(pres, t.pr); \ |
| 2204 | CHECK_EQ(zres, t.zr); |
| 2205 | |
| 2206 | CHECK_VRINT(-0.5, -1.0, -0.0, -1.0, -0.0, -0.0) |
| 2207 | CHECK_VRINT(-0.6, -1.0, -1.0, -1.0, -0.0, -0.0) |
| 2208 | CHECK_VRINT(-1.1, -1.0, -1.0, -2.0, -1.0, -1.0) |
| 2209 | CHECK_VRINT(0.5, 1.0, 0.0, 0.0, 1.0, 0.0) |
| 2210 | CHECK_VRINT(0.6, 1.0, 1.0, 0.0, 1.0, 0.0) |
| 2211 | CHECK_VRINT(1.1, 1.0, 1.0, 1.0, 2.0, 1.0) |
| 2212 | double inf = std::numeric_limits<double>::infinity(); |
| 2213 | CHECK_VRINT(inf, inf, inf, inf, inf, inf) |
| 2214 | CHECK_VRINT(-inf, -inf, -inf, -inf, -inf, -inf) |
| 2215 | CHECK_VRINT(-0.0, -0.0, -0.0, -0.0, -0.0, -0.0) |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2216 | |
| 2217 | // Check NaN propagation. |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2218 | double nan = std::numeric_limits<double>::quiet_NaN(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2219 | t.input = nan; |
| 2220 | dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); |
| 2221 | CHECK_EQ(bit_cast<int64_t>(nan), bit_cast<int64_t>(t.ar)); |
| 2222 | CHECK_EQ(bit_cast<int64_t>(nan), bit_cast<int64_t>(t.nr)); |
| 2223 | CHECK_EQ(bit_cast<int64_t>(nan), bit_cast<int64_t>(t.mr)); |
| 2224 | CHECK_EQ(bit_cast<int64_t>(nan), bit_cast<int64_t>(t.pr)); |
| 2225 | CHECK_EQ(bit_cast<int64_t>(nan), bit_cast<int64_t>(t.zr)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2226 | |
| 2227 | #undef CHECK_VRINT |
| 2228 | } |
| 2229 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2230 | |
Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame^] | 2231 | TEST(ARMv8_vsel) { |
| 2232 | // Test the vsel floating point instructions. |
| 2233 | CcTest::InitializeVM(); |
| 2234 | Isolate* isolate = CcTest::i_isolate(); |
| 2235 | HandleScope scope(isolate); |
| 2236 | |
| 2237 | Assembler assm(isolate, NULL, 0); |
| 2238 | |
| 2239 | // Used to indicate whether a condition passed or failed. |
| 2240 | static constexpr float kResultPass = 1.0f; |
| 2241 | static constexpr float kResultFail = -kResultPass; |
| 2242 | |
| 2243 | struct ResultsF32 { |
| 2244 | float vseleq_; |
| 2245 | float vselge_; |
| 2246 | float vselgt_; |
| 2247 | float vselvs_; |
| 2248 | |
| 2249 | // The following conditions aren't architecturally supported, but the |
| 2250 | // assembler implements them by swapping the inputs. |
| 2251 | float vselne_; |
| 2252 | float vsellt_; |
| 2253 | float vselle_; |
| 2254 | float vselvc_; |
| 2255 | }; |
| 2256 | |
| 2257 | struct ResultsF64 { |
| 2258 | double vseleq_; |
| 2259 | double vselge_; |
| 2260 | double vselgt_; |
| 2261 | double vselvs_; |
| 2262 | |
| 2263 | // The following conditions aren't architecturally supported, but the |
| 2264 | // assembler implements them by swapping the inputs. |
| 2265 | double vselne_; |
| 2266 | double vsellt_; |
| 2267 | double vselle_; |
| 2268 | double vselvc_; |
| 2269 | }; |
| 2270 | |
| 2271 | if (CpuFeatures::IsSupported(ARMv8)) { |
| 2272 | CpuFeatureScope scope(&assm, ARMv8); |
| 2273 | |
| 2274 | // Create a helper function: |
| 2275 | // void TestVsel(uint32_t nzcv, |
| 2276 | // ResultsF32* results_f32, |
| 2277 | // ResultsF64* results_f64); |
| 2278 | __ msr(CPSR_f, Operand(r0)); |
| 2279 | |
| 2280 | __ vmov(s1, kResultPass); |
| 2281 | __ vmov(s2, kResultFail); |
| 2282 | |
| 2283 | __ vsel(eq, s0, s1, s2); |
| 2284 | __ vstr(s0, r1, offsetof(ResultsF32, vseleq_)); |
| 2285 | __ vsel(ge, s0, s1, s2); |
| 2286 | __ vstr(s0, r1, offsetof(ResultsF32, vselge_)); |
| 2287 | __ vsel(gt, s0, s1, s2); |
| 2288 | __ vstr(s0, r1, offsetof(ResultsF32, vselgt_)); |
| 2289 | __ vsel(vs, s0, s1, s2); |
| 2290 | __ vstr(s0, r1, offsetof(ResultsF32, vselvs_)); |
| 2291 | |
| 2292 | __ vsel(ne, s0, s1, s2); |
| 2293 | __ vstr(s0, r1, offsetof(ResultsF32, vselne_)); |
| 2294 | __ vsel(lt, s0, s1, s2); |
| 2295 | __ vstr(s0, r1, offsetof(ResultsF32, vsellt_)); |
| 2296 | __ vsel(le, s0, s1, s2); |
| 2297 | __ vstr(s0, r1, offsetof(ResultsF32, vselle_)); |
| 2298 | __ vsel(vc, s0, s1, s2); |
| 2299 | __ vstr(s0, r1, offsetof(ResultsF32, vselvc_)); |
| 2300 | |
| 2301 | __ vmov(d1, kResultPass); |
| 2302 | __ vmov(d2, kResultFail); |
| 2303 | |
| 2304 | __ vsel(eq, d0, d1, d2); |
| 2305 | __ vstr(d0, r2, offsetof(ResultsF64, vseleq_)); |
| 2306 | __ vsel(ge, d0, d1, d2); |
| 2307 | __ vstr(d0, r2, offsetof(ResultsF64, vselge_)); |
| 2308 | __ vsel(gt, d0, d1, d2); |
| 2309 | __ vstr(d0, r2, offsetof(ResultsF64, vselgt_)); |
| 2310 | __ vsel(vs, d0, d1, d2); |
| 2311 | __ vstr(d0, r2, offsetof(ResultsF64, vselvs_)); |
| 2312 | |
| 2313 | __ vsel(ne, d0, d1, d2); |
| 2314 | __ vstr(d0, r2, offsetof(ResultsF64, vselne_)); |
| 2315 | __ vsel(lt, d0, d1, d2); |
| 2316 | __ vstr(d0, r2, offsetof(ResultsF64, vsellt_)); |
| 2317 | __ vsel(le, d0, d1, d2); |
| 2318 | __ vstr(d0, r2, offsetof(ResultsF64, vselle_)); |
| 2319 | __ vsel(vc, d0, d1, d2); |
| 2320 | __ vstr(d0, r2, offsetof(ResultsF64, vselvc_)); |
| 2321 | |
| 2322 | __ bx(lr); |
| 2323 | |
| 2324 | CodeDesc desc; |
| 2325 | assm.GetCode(&desc); |
| 2326 | Handle<Code> code = isolate->factory()->NewCode( |
| 2327 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 2328 | #ifdef DEBUG |
| 2329 | OFStream os(stdout); |
| 2330 | code->Print(os); |
| 2331 | #endif |
| 2332 | F5 f = FUNCTION_CAST<F5>(code->entry()); |
| 2333 | Object* dummy = nullptr; |
| 2334 | USE(dummy); |
| 2335 | |
| 2336 | STATIC_ASSERT(kResultPass == -kResultFail); |
| 2337 | #define CHECK_VSEL(n, z, c, v, vseleq, vselge, vselgt, vselvs) \ |
| 2338 | do { \ |
| 2339 | ResultsF32 results_f32; \ |
| 2340 | ResultsF64 results_f64; \ |
| 2341 | uint32_t nzcv = (n << 31) | (z << 30) | (c << 29) | (v << 28); \ |
| 2342 | dummy = CALL_GENERATED_CODE(isolate, f, nzcv, &results_f32, &results_f64, \ |
| 2343 | 0, 0); \ |
| 2344 | CHECK_EQ(vseleq, results_f32.vseleq_); \ |
| 2345 | CHECK_EQ(vselge, results_f32.vselge_); \ |
| 2346 | CHECK_EQ(vselgt, results_f32.vselgt_); \ |
| 2347 | CHECK_EQ(vselvs, results_f32.vselvs_); \ |
| 2348 | CHECK_EQ(-vseleq, results_f32.vselne_); \ |
| 2349 | CHECK_EQ(-vselge, results_f32.vsellt_); \ |
| 2350 | CHECK_EQ(-vselgt, results_f32.vselle_); \ |
| 2351 | CHECK_EQ(-vselvs, results_f32.vselvc_); \ |
| 2352 | CHECK_EQ(vseleq, results_f64.vseleq_); \ |
| 2353 | CHECK_EQ(vselge, results_f64.vselge_); \ |
| 2354 | CHECK_EQ(vselgt, results_f64.vselgt_); \ |
| 2355 | CHECK_EQ(vselvs, results_f64.vselvs_); \ |
| 2356 | CHECK_EQ(-vseleq, results_f64.vselne_); \ |
| 2357 | CHECK_EQ(-vselge, results_f64.vsellt_); \ |
| 2358 | CHECK_EQ(-vselgt, results_f64.vselle_); \ |
| 2359 | CHECK_EQ(-vselvs, results_f64.vselvc_); \ |
| 2360 | } while (0); |
| 2361 | |
| 2362 | // N Z C V vseleq vselge vselgt vselvs |
| 2363 | CHECK_VSEL(0, 0, 0, 0, kResultFail, kResultPass, kResultPass, kResultFail); |
| 2364 | CHECK_VSEL(0, 0, 0, 1, kResultFail, kResultFail, kResultFail, kResultPass); |
| 2365 | CHECK_VSEL(0, 0, 1, 0, kResultFail, kResultPass, kResultPass, kResultFail); |
| 2366 | CHECK_VSEL(0, 0, 1, 1, kResultFail, kResultFail, kResultFail, kResultPass); |
| 2367 | CHECK_VSEL(0, 1, 0, 0, kResultPass, kResultPass, kResultFail, kResultFail); |
| 2368 | CHECK_VSEL(0, 1, 0, 1, kResultPass, kResultFail, kResultFail, kResultPass); |
| 2369 | CHECK_VSEL(0, 1, 1, 0, kResultPass, kResultPass, kResultFail, kResultFail); |
| 2370 | CHECK_VSEL(0, 1, 1, 1, kResultPass, kResultFail, kResultFail, kResultPass); |
| 2371 | CHECK_VSEL(1, 0, 0, 0, kResultFail, kResultFail, kResultFail, kResultFail); |
| 2372 | CHECK_VSEL(1, 0, 0, 1, kResultFail, kResultPass, kResultPass, kResultPass); |
| 2373 | CHECK_VSEL(1, 0, 1, 0, kResultFail, kResultFail, kResultFail, kResultFail); |
| 2374 | CHECK_VSEL(1, 0, 1, 1, kResultFail, kResultPass, kResultPass, kResultPass); |
| 2375 | CHECK_VSEL(1, 1, 0, 0, kResultPass, kResultFail, kResultFail, kResultFail); |
| 2376 | CHECK_VSEL(1, 1, 0, 1, kResultPass, kResultPass, kResultFail, kResultPass); |
| 2377 | CHECK_VSEL(1, 1, 1, 0, kResultPass, kResultFail, kResultFail, kResultFail); |
| 2378 | CHECK_VSEL(1, 1, 1, 1, kResultPass, kResultPass, kResultFail, kResultPass); |
| 2379 | |
| 2380 | #undef CHECK_VSEL |
| 2381 | } |
| 2382 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2383 | |
| 2384 | TEST(regress4292_b) { |
| 2385 | CcTest::InitializeVM(); |
| 2386 | Isolate* isolate = CcTest::i_isolate(); |
| 2387 | HandleScope scope(isolate); |
| 2388 | |
| 2389 | Assembler assm(isolate, NULL, 0); |
| 2390 | Label end; |
| 2391 | __ mov(r0, Operand(isolate->factory()->infinity_value())); |
| 2392 | for (int i = 0; i < 1020; ++i) { |
| 2393 | __ b(hi, &end); |
| 2394 | } |
| 2395 | __ bind(&end); |
| 2396 | } |
| 2397 | |
| 2398 | |
| 2399 | TEST(regress4292_bl) { |
| 2400 | CcTest::InitializeVM(); |
| 2401 | Isolate* isolate = CcTest::i_isolate(); |
| 2402 | HandleScope scope(isolate); |
| 2403 | |
| 2404 | Assembler assm(isolate, NULL, 0); |
| 2405 | Label end; |
| 2406 | __ mov(r0, Operand(isolate->factory()->infinity_value())); |
| 2407 | for (int i = 0; i < 1020; ++i) { |
| 2408 | __ bl(hi, &end); |
| 2409 | } |
| 2410 | __ bind(&end); |
| 2411 | } |
| 2412 | |
| 2413 | |
| 2414 | TEST(regress4292_blx) { |
| 2415 | CcTest::InitializeVM(); |
| 2416 | Isolate* isolate = CcTest::i_isolate(); |
| 2417 | HandleScope scope(isolate); |
| 2418 | |
| 2419 | Assembler assm(isolate, NULL, 0); |
| 2420 | Label end; |
| 2421 | __ mov(r0, Operand(isolate->factory()->infinity_value())); |
| 2422 | for (int i = 0; i < 1020; ++i) { |
| 2423 | __ blx(&end); |
| 2424 | } |
| 2425 | __ bind(&end); |
| 2426 | } |
| 2427 | |
| 2428 | |
| 2429 | TEST(regress4292_CheckConstPool) { |
| 2430 | CcTest::InitializeVM(); |
| 2431 | Isolate* isolate = CcTest::i_isolate(); |
| 2432 | HandleScope scope(isolate); |
| 2433 | |
| 2434 | Assembler assm(isolate, NULL, 0); |
| 2435 | __ mov(r0, Operand(isolate->factory()->infinity_value())); |
| 2436 | __ BlockConstPoolFor(1019); |
| 2437 | for (int i = 0; i < 1019; ++i) __ nop(); |
| 2438 | __ vldr(d0, MemOperand(r0, 0)); |
| 2439 | } |
| 2440 | |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 2441 | #undef __ |