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 | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 415 | if (CpuFeatures::IsSupported(ARMv7)) { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 416 | CpuFeatureScope scope(&assm, ARMv7); |
Kristian Monsen | 50ef84f | 2010-07-29 15:18:00 +0100 | [diff] [blame] | 417 | __ usat(r1, 8, Operand(r0)); // Sat 0xFFFF to 0-255 = 0xFF. |
| 418 | __ usat(r2, 12, Operand(r0, ASR, 9)); // Sat (0xFFFF>>9) to 0-4095 = 0x7F. |
| 419 | __ usat(r3, 1, Operand(r0, LSL, 16)); // Sat (0xFFFF<<16) to 0-1 = 0x0. |
| 420 | __ add(r0, r1, Operand(r2)); |
| 421 | __ add(r0, r0, Operand(r3)); |
| 422 | __ mov(pc, Operand(lr)); |
| 423 | |
| 424 | CodeDesc desc; |
| 425 | assm.GetCode(&desc); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 426 | Handle<Code> code = isolate->factory()->NewCode( |
| 427 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
Kristian Monsen | 50ef84f | 2010-07-29 15:18:00 +0100 | [diff] [blame] | 428 | #ifdef DEBUG |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 429 | OFStream os(stdout); |
| 430 | code->Print(os); |
Kristian Monsen | 50ef84f | 2010-07-29 15:18:00 +0100 | [diff] [blame] | 431 | #endif |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 432 | F1 f = FUNCTION_CAST<F1>(code->entry()); |
Kristian Monsen | 50ef84f | 2010-07-29 15:18:00 +0100 | [diff] [blame] | 433 | int res = reinterpret_cast<int>( |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 434 | CALL_GENERATED_CODE(isolate, f, 0xFFFF, 0, 0, 0, 0)); |
Kristian Monsen | 50ef84f | 2010-07-29 15:18:00 +0100 | [diff] [blame] | 435 | ::printf("f() = %d\n", res); |
| 436 | CHECK_EQ(382, res); |
| 437 | } |
| 438 | } |
| 439 | |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 440 | |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 441 | enum VCVTTypes { |
| 442 | s32_f64, |
| 443 | u32_f64 |
| 444 | }; |
| 445 | |
| 446 | static void TestRoundingMode(VCVTTypes types, |
| 447 | VFPRoundingMode mode, |
| 448 | double value, |
| 449 | int expected, |
| 450 | bool expected_exception = false) { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 451 | Isolate* isolate = CcTest::i_isolate(); |
| 452 | HandleScope scope(isolate); |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 453 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 454 | Assembler assm(isolate, NULL, 0); |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 455 | |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 456 | if (CpuFeatures::IsSupported(VFP3)) { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 457 | CpuFeatureScope scope(&assm, VFP3); |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 458 | |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 459 | Label wrong_exception; |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 460 | |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 461 | __ vmrs(r1); |
| 462 | // Set custom FPSCR. |
| 463 | __ bic(r2, r1, Operand(kVFPRoundingModeMask | kVFPExceptionMask)); |
| 464 | __ orr(r2, r2, Operand(mode)); |
| 465 | __ vmsr(r2); |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 466 | |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 467 | // Load value, convert, and move back result to r0 if everything went well. |
| 468 | __ vmov(d1, value); |
| 469 | switch (types) { |
| 470 | case s32_f64: |
| 471 | __ vcvt_s32_f64(s0, d1, kFPSCRRounding); |
| 472 | break; |
| 473 | |
| 474 | case u32_f64: |
| 475 | __ vcvt_u32_f64(s0, d1, kFPSCRRounding); |
| 476 | break; |
| 477 | |
| 478 | default: |
| 479 | UNREACHABLE(); |
| 480 | break; |
| 481 | } |
| 482 | // Check for vfp exceptions |
| 483 | __ vmrs(r2); |
| 484 | __ tst(r2, Operand(kVFPExceptionMask)); |
| 485 | // Check that we behaved as expected. |
| 486 | __ b(&wrong_exception, |
| 487 | expected_exception ? eq : ne); |
| 488 | // There was no exception. Retrieve the result and return. |
| 489 | __ vmov(r0, s0); |
| 490 | __ mov(pc, Operand(lr)); |
| 491 | |
| 492 | // The exception behaviour is not what we expected. |
| 493 | // Load a special value and return. |
| 494 | __ bind(&wrong_exception); |
| 495 | __ mov(r0, Operand(11223344)); |
| 496 | __ mov(pc, Operand(lr)); |
| 497 | |
| 498 | CodeDesc desc; |
| 499 | assm.GetCode(&desc); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 500 | Handle<Code> code = isolate->factory()->NewCode( |
| 501 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 502 | #ifdef DEBUG |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 503 | OFStream os(stdout); |
| 504 | code->Print(os); |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 505 | #endif |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 506 | F1 f = FUNCTION_CAST<F1>(code->entry()); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 507 | int res = |
| 508 | 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] | 509 | ::printf("res = %d\n", res); |
| 510 | CHECK_EQ(expected, res); |
| 511 | } |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 512 | } |
| 513 | |
| 514 | |
| 515 | TEST(7) { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 516 | CcTest::InitializeVM(); |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 517 | // Test vfp rounding modes. |
| 518 | |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 519 | // s32_f64 (double to integer). |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 520 | |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 521 | TestRoundingMode(s32_f64, RN, 0, 0); |
| 522 | TestRoundingMode(s32_f64, RN, 0.5, 0); |
| 523 | TestRoundingMode(s32_f64, RN, -0.5, 0); |
| 524 | TestRoundingMode(s32_f64, RN, 1.5, 2); |
| 525 | TestRoundingMode(s32_f64, RN, -1.5, -2); |
| 526 | TestRoundingMode(s32_f64, RN, 123.7, 124); |
| 527 | TestRoundingMode(s32_f64, RN, -123.7, -124); |
| 528 | TestRoundingMode(s32_f64, RN, 123456.2, 123456); |
| 529 | TestRoundingMode(s32_f64, RN, -123456.2, -123456); |
| 530 | TestRoundingMode(s32_f64, RN, static_cast<double>(kMaxInt), kMaxInt); |
| 531 | TestRoundingMode(s32_f64, RN, (kMaxInt + 0.49), kMaxInt); |
| 532 | TestRoundingMode(s32_f64, RN, (kMaxInt + 1.0), kMaxInt, true); |
| 533 | TestRoundingMode(s32_f64, RN, (kMaxInt + 0.5), kMaxInt, true); |
| 534 | TestRoundingMode(s32_f64, RN, static_cast<double>(kMinInt), kMinInt); |
| 535 | TestRoundingMode(s32_f64, RN, (kMinInt - 0.5), kMinInt); |
| 536 | TestRoundingMode(s32_f64, RN, (kMinInt - 1.0), kMinInt, true); |
| 537 | TestRoundingMode(s32_f64, RN, (kMinInt - 0.51), kMinInt, true); |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 538 | |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 539 | TestRoundingMode(s32_f64, RM, 0, 0); |
| 540 | TestRoundingMode(s32_f64, RM, 0.5, 0); |
| 541 | TestRoundingMode(s32_f64, RM, -0.5, -1); |
| 542 | TestRoundingMode(s32_f64, RM, 123.7, 123); |
| 543 | TestRoundingMode(s32_f64, RM, -123.7, -124); |
| 544 | TestRoundingMode(s32_f64, RM, 123456.2, 123456); |
| 545 | TestRoundingMode(s32_f64, RM, -123456.2, -123457); |
| 546 | TestRoundingMode(s32_f64, RM, static_cast<double>(kMaxInt), kMaxInt); |
| 547 | TestRoundingMode(s32_f64, RM, (kMaxInt + 0.5), kMaxInt); |
| 548 | TestRoundingMode(s32_f64, RM, (kMaxInt + 1.0), kMaxInt, true); |
| 549 | TestRoundingMode(s32_f64, RM, static_cast<double>(kMinInt), kMinInt); |
| 550 | TestRoundingMode(s32_f64, RM, (kMinInt - 0.5), kMinInt, true); |
| 551 | TestRoundingMode(s32_f64, RM, (kMinInt + 0.5), kMinInt); |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 552 | |
Steve Block | 1e0659c | 2011-05-24 12:43:12 +0100 | [diff] [blame] | 553 | TestRoundingMode(s32_f64, RZ, 0, 0); |
| 554 | TestRoundingMode(s32_f64, RZ, 0.5, 0); |
| 555 | TestRoundingMode(s32_f64, RZ, -0.5, 0); |
| 556 | TestRoundingMode(s32_f64, RZ, 123.7, 123); |
| 557 | TestRoundingMode(s32_f64, RZ, -123.7, -123); |
| 558 | TestRoundingMode(s32_f64, RZ, 123456.2, 123456); |
| 559 | TestRoundingMode(s32_f64, RZ, -123456.2, -123456); |
| 560 | TestRoundingMode(s32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt); |
| 561 | TestRoundingMode(s32_f64, RZ, (kMaxInt + 0.5), kMaxInt); |
| 562 | TestRoundingMode(s32_f64, RZ, (kMaxInt + 1.0), kMaxInt, true); |
| 563 | TestRoundingMode(s32_f64, RZ, static_cast<double>(kMinInt), kMinInt); |
| 564 | TestRoundingMode(s32_f64, RZ, (kMinInt - 0.5), kMinInt); |
| 565 | TestRoundingMode(s32_f64, RZ, (kMinInt - 1.0), kMinInt, true); |
| 566 | |
| 567 | |
| 568 | // u32_f64 (double to integer). |
| 569 | |
| 570 | // Negative values. |
| 571 | TestRoundingMode(u32_f64, RN, -0.5, 0); |
| 572 | TestRoundingMode(u32_f64, RN, -123456.7, 0, true); |
| 573 | TestRoundingMode(u32_f64, RN, static_cast<double>(kMinInt), 0, true); |
| 574 | TestRoundingMode(u32_f64, RN, kMinInt - 1.0, 0, true); |
| 575 | |
| 576 | TestRoundingMode(u32_f64, RM, -0.5, 0, true); |
| 577 | TestRoundingMode(u32_f64, RM, -123456.7, 0, true); |
| 578 | TestRoundingMode(u32_f64, RM, static_cast<double>(kMinInt), 0, true); |
| 579 | TestRoundingMode(u32_f64, RM, kMinInt - 1.0, 0, true); |
| 580 | |
| 581 | TestRoundingMode(u32_f64, RZ, -0.5, 0); |
| 582 | TestRoundingMode(u32_f64, RZ, -123456.7, 0, true); |
| 583 | TestRoundingMode(u32_f64, RZ, static_cast<double>(kMinInt), 0, true); |
| 584 | TestRoundingMode(u32_f64, RZ, kMinInt - 1.0, 0, true); |
| 585 | |
| 586 | // Positive values. |
| 587 | // kMaxInt is the maximum *signed* integer: 0x7fffffff. |
| 588 | static const uint32_t kMaxUInt = 0xffffffffu; |
| 589 | TestRoundingMode(u32_f64, RZ, 0, 0); |
| 590 | TestRoundingMode(u32_f64, RZ, 0.5, 0); |
| 591 | TestRoundingMode(u32_f64, RZ, 123.7, 123); |
| 592 | TestRoundingMode(u32_f64, RZ, 123456.2, 123456); |
| 593 | TestRoundingMode(u32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt); |
| 594 | TestRoundingMode(u32_f64, RZ, (kMaxInt + 0.5), kMaxInt); |
| 595 | TestRoundingMode(u32_f64, RZ, (kMaxInt + 1.0), |
| 596 | static_cast<uint32_t>(kMaxInt) + 1); |
| 597 | TestRoundingMode(u32_f64, RZ, (kMaxUInt + 0.5), kMaxUInt); |
| 598 | TestRoundingMode(u32_f64, RZ, (kMaxUInt + 1.0), kMaxUInt, true); |
| 599 | |
| 600 | TestRoundingMode(u32_f64, RM, 0, 0); |
| 601 | TestRoundingMode(u32_f64, RM, 0.5, 0); |
| 602 | TestRoundingMode(u32_f64, RM, 123.7, 123); |
| 603 | TestRoundingMode(u32_f64, RM, 123456.2, 123456); |
| 604 | TestRoundingMode(u32_f64, RM, static_cast<double>(kMaxInt), kMaxInt); |
| 605 | TestRoundingMode(u32_f64, RM, (kMaxInt + 0.5), kMaxInt); |
| 606 | TestRoundingMode(u32_f64, RM, (kMaxInt + 1.0), |
| 607 | static_cast<uint32_t>(kMaxInt) + 1); |
| 608 | TestRoundingMode(u32_f64, RM, (kMaxUInt + 0.5), kMaxUInt); |
| 609 | TestRoundingMode(u32_f64, RM, (kMaxUInt + 1.0), kMaxUInt, true); |
| 610 | |
| 611 | TestRoundingMode(u32_f64, RN, 0, 0); |
| 612 | TestRoundingMode(u32_f64, RN, 0.5, 0); |
| 613 | TestRoundingMode(u32_f64, RN, 1.5, 2); |
| 614 | TestRoundingMode(u32_f64, RN, 123.7, 124); |
| 615 | TestRoundingMode(u32_f64, RN, 123456.2, 123456); |
| 616 | TestRoundingMode(u32_f64, RN, static_cast<double>(kMaxInt), kMaxInt); |
| 617 | TestRoundingMode(u32_f64, RN, (kMaxInt + 0.49), kMaxInt); |
| 618 | TestRoundingMode(u32_f64, RN, (kMaxInt + 0.5), |
| 619 | static_cast<uint32_t>(kMaxInt) + 1); |
| 620 | TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.49), kMaxUInt); |
| 621 | TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.5), kMaxUInt, true); |
| 622 | TestRoundingMode(u32_f64, RN, (kMaxUInt + 1.0), kMaxUInt, true); |
Russell Brenner | 90bac25 | 2010-11-18 13:33:46 -0800 | [diff] [blame] | 623 | } |
| 624 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 625 | |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 626 | TEST(8) { |
| 627 | // Test VFP multi load/store with ia_w. |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 628 | CcTest::InitializeVM(); |
| 629 | Isolate* isolate = CcTest::i_isolate(); |
| 630 | HandleScope scope(isolate); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 631 | |
| 632 | typedef struct { |
| 633 | double a; |
| 634 | double b; |
| 635 | double c; |
| 636 | double d; |
| 637 | double e; |
| 638 | double f; |
| 639 | double g; |
| 640 | double h; |
| 641 | } D; |
| 642 | D d; |
| 643 | |
| 644 | typedef struct { |
| 645 | float a; |
| 646 | float b; |
| 647 | float c; |
| 648 | float d; |
| 649 | float e; |
| 650 | float f; |
| 651 | float g; |
| 652 | float h; |
| 653 | } F; |
| 654 | F f; |
| 655 | |
| 656 | // Create a function that uses vldm/vstm to move some double and |
| 657 | // single precision values around in memory. |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 658 | Assembler assm(isolate, NULL, 0); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 659 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 660 | __ mov(ip, Operand(sp)); |
| 661 | __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); |
| 662 | __ sub(fp, ip, Operand(4)); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 663 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 664 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, a)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 665 | __ vldm(ia_w, r4, d0, d3); |
| 666 | __ vldm(ia_w, r4, d4, d7); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 667 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 668 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, a)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 669 | __ vstm(ia_w, r4, d6, d7); |
| 670 | __ vstm(ia_w, r4, d0, d5); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 671 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 672 | __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, a)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 673 | __ vldm(ia_w, r4, s0, s3); |
| 674 | __ vldm(ia_w, r4, s4, s7); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 675 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 676 | __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, a)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 677 | __ vstm(ia_w, r4, s6, s7); |
| 678 | __ vstm(ia_w, r4, s0, s5); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 679 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 680 | __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 681 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 682 | CodeDesc desc; |
| 683 | assm.GetCode(&desc); |
| 684 | Handle<Code> code = isolate->factory()->NewCode( |
| 685 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 686 | #ifdef DEBUG |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 687 | OFStream os(stdout); |
| 688 | code->Print(os); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 689 | #endif |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 690 | F4 fn = FUNCTION_CAST<F4>(code->entry()); |
| 691 | d.a = 1.1; |
| 692 | d.b = 2.2; |
| 693 | d.c = 3.3; |
| 694 | d.d = 4.4; |
| 695 | d.e = 5.5; |
| 696 | d.f = 6.6; |
| 697 | d.g = 7.7; |
| 698 | d.h = 8.8; |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 699 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 700 | f.a = 1.0; |
| 701 | f.b = 2.0; |
| 702 | f.c = 3.0; |
| 703 | f.d = 4.0; |
| 704 | f.e = 5.0; |
| 705 | f.f = 6.0; |
| 706 | f.g = 7.0; |
| 707 | f.h = 8.0; |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 708 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 709 | Object* dummy = CALL_GENERATED_CODE(isolate, fn, &d, &f, 0, 0, 0); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 710 | USE(dummy); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 711 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 712 | CHECK_EQ(7.7, d.a); |
| 713 | CHECK_EQ(8.8, d.b); |
| 714 | CHECK_EQ(1.1, d.c); |
| 715 | CHECK_EQ(2.2, d.d); |
| 716 | CHECK_EQ(3.3, d.e); |
| 717 | CHECK_EQ(4.4, d.f); |
| 718 | CHECK_EQ(5.5, d.g); |
| 719 | CHECK_EQ(6.6, d.h); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 720 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 721 | CHECK_EQ(7.0f, f.a); |
| 722 | CHECK_EQ(8.0f, f.b); |
| 723 | CHECK_EQ(1.0f, f.c); |
| 724 | CHECK_EQ(2.0f, f.d); |
| 725 | CHECK_EQ(3.0f, f.e); |
| 726 | CHECK_EQ(4.0f, f.f); |
| 727 | CHECK_EQ(5.0f, f.g); |
| 728 | CHECK_EQ(6.0f, f.h); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 729 | } |
| 730 | |
| 731 | |
| 732 | TEST(9) { |
| 733 | // Test VFP multi load/store with ia. |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 734 | CcTest::InitializeVM(); |
| 735 | Isolate* isolate = CcTest::i_isolate(); |
| 736 | HandleScope scope(isolate); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 737 | |
| 738 | typedef struct { |
| 739 | double a; |
| 740 | double b; |
| 741 | double c; |
| 742 | double d; |
| 743 | double e; |
| 744 | double f; |
| 745 | double g; |
| 746 | double h; |
| 747 | } D; |
| 748 | D d; |
| 749 | |
| 750 | typedef struct { |
| 751 | float a; |
| 752 | float b; |
| 753 | float c; |
| 754 | float d; |
| 755 | float e; |
| 756 | float f; |
| 757 | float g; |
| 758 | float h; |
| 759 | } F; |
| 760 | F f; |
| 761 | |
| 762 | // Create a function that uses vldm/vstm to move some double and |
| 763 | // single precision values around in memory. |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 764 | Assembler assm(isolate, NULL, 0); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 765 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 766 | __ mov(ip, Operand(sp)); |
| 767 | __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); |
| 768 | __ sub(fp, ip, Operand(4)); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 769 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 770 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, a)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 771 | __ vldm(ia, r4, d0, d3); |
| 772 | __ add(r4, r4, Operand(4 * 8)); |
| 773 | __ vldm(ia, r4, d4, d7); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 774 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 775 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, a)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 776 | __ vstm(ia, r4, d6, d7); |
| 777 | __ add(r4, r4, Operand(2 * 8)); |
| 778 | __ vstm(ia, r4, d0, d5); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 779 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 780 | __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, a)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 781 | __ vldm(ia, r4, s0, s3); |
| 782 | __ add(r4, r4, Operand(4 * 4)); |
| 783 | __ vldm(ia, r4, s4, s7); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 784 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 785 | __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, a)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 786 | __ vstm(ia, r4, s6, s7); |
| 787 | __ add(r4, r4, Operand(2 * 4)); |
| 788 | __ vstm(ia, r4, s0, s5); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 789 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 790 | __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 791 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 792 | CodeDesc desc; |
| 793 | assm.GetCode(&desc); |
| 794 | Handle<Code> code = isolate->factory()->NewCode( |
| 795 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 796 | #ifdef DEBUG |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 797 | OFStream os(stdout); |
| 798 | code->Print(os); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 799 | #endif |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 800 | F4 fn = FUNCTION_CAST<F4>(code->entry()); |
| 801 | d.a = 1.1; |
| 802 | d.b = 2.2; |
| 803 | d.c = 3.3; |
| 804 | d.d = 4.4; |
| 805 | d.e = 5.5; |
| 806 | d.f = 6.6; |
| 807 | d.g = 7.7; |
| 808 | d.h = 8.8; |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 809 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 810 | f.a = 1.0; |
| 811 | f.b = 2.0; |
| 812 | f.c = 3.0; |
| 813 | f.d = 4.0; |
| 814 | f.e = 5.0; |
| 815 | f.f = 6.0; |
| 816 | f.g = 7.0; |
| 817 | f.h = 8.0; |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 818 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 819 | Object* dummy = CALL_GENERATED_CODE(isolate, fn, &d, &f, 0, 0, 0); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 820 | USE(dummy); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 821 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 822 | CHECK_EQ(7.7, d.a); |
| 823 | CHECK_EQ(8.8, d.b); |
| 824 | CHECK_EQ(1.1, d.c); |
| 825 | CHECK_EQ(2.2, d.d); |
| 826 | CHECK_EQ(3.3, d.e); |
| 827 | CHECK_EQ(4.4, d.f); |
| 828 | CHECK_EQ(5.5, d.g); |
| 829 | CHECK_EQ(6.6, d.h); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 830 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 831 | CHECK_EQ(7.0f, f.a); |
| 832 | CHECK_EQ(8.0f, f.b); |
| 833 | CHECK_EQ(1.0f, f.c); |
| 834 | CHECK_EQ(2.0f, f.d); |
| 835 | CHECK_EQ(3.0f, f.e); |
| 836 | CHECK_EQ(4.0f, f.f); |
| 837 | CHECK_EQ(5.0f, f.g); |
| 838 | CHECK_EQ(6.0f, f.h); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 839 | } |
| 840 | |
| 841 | |
| 842 | TEST(10) { |
| 843 | // Test VFP multi load/store with db_w. |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 844 | CcTest::InitializeVM(); |
| 845 | Isolate* isolate = CcTest::i_isolate(); |
| 846 | HandleScope scope(isolate); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 847 | |
| 848 | typedef struct { |
| 849 | double a; |
| 850 | double b; |
| 851 | double c; |
| 852 | double d; |
| 853 | double e; |
| 854 | double f; |
| 855 | double g; |
| 856 | double h; |
| 857 | } D; |
| 858 | D d; |
| 859 | |
| 860 | typedef struct { |
| 861 | float a; |
| 862 | float b; |
| 863 | float c; |
| 864 | float d; |
| 865 | float e; |
| 866 | float f; |
| 867 | float g; |
| 868 | float h; |
| 869 | } F; |
| 870 | F f; |
| 871 | |
| 872 | // Create a function that uses vldm/vstm to move some double and |
| 873 | // single precision values around in memory. |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 874 | Assembler assm(isolate, NULL, 0); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 875 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 876 | __ mov(ip, Operand(sp)); |
| 877 | __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); |
| 878 | __ sub(fp, ip, Operand(4)); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 879 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 880 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, h)) + 8)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 881 | __ vldm(db_w, r4, d4, d7); |
| 882 | __ vldm(db_w, r4, d0, d3); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 883 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 884 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(D, h)) + 8)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 885 | __ vstm(db_w, r4, d0, d5); |
| 886 | __ vstm(db_w, r4, d6, d7); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 887 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 888 | __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, h)) + 4)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 889 | __ vldm(db_w, r4, s4, s7); |
| 890 | __ vldm(db_w, r4, s0, s3); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 891 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 892 | __ add(r4, r1, Operand(static_cast<int32_t>(offsetof(F, h)) + 4)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 893 | __ vstm(db_w, r4, s0, s5); |
| 894 | __ vstm(db_w, r4, s6, s7); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 895 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 896 | __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 897 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 898 | CodeDesc desc; |
| 899 | assm.GetCode(&desc); |
| 900 | Handle<Code> code = isolate->factory()->NewCode( |
| 901 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 902 | #ifdef DEBUG |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 903 | OFStream os(stdout); |
| 904 | code->Print(os); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 905 | #endif |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 906 | F4 fn = FUNCTION_CAST<F4>(code->entry()); |
| 907 | d.a = 1.1; |
| 908 | d.b = 2.2; |
| 909 | d.c = 3.3; |
| 910 | d.d = 4.4; |
| 911 | d.e = 5.5; |
| 912 | d.f = 6.6; |
| 913 | d.g = 7.7; |
| 914 | d.h = 8.8; |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 915 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 916 | f.a = 1.0; |
| 917 | f.b = 2.0; |
| 918 | f.c = 3.0; |
| 919 | f.d = 4.0; |
| 920 | f.e = 5.0; |
| 921 | f.f = 6.0; |
| 922 | f.g = 7.0; |
| 923 | f.h = 8.0; |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 924 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 925 | Object* dummy = CALL_GENERATED_CODE(isolate, fn, &d, &f, 0, 0, 0); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 926 | USE(dummy); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 927 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 928 | CHECK_EQ(7.7, d.a); |
| 929 | CHECK_EQ(8.8, d.b); |
| 930 | CHECK_EQ(1.1, d.c); |
| 931 | CHECK_EQ(2.2, d.d); |
| 932 | CHECK_EQ(3.3, d.e); |
| 933 | CHECK_EQ(4.4, d.f); |
| 934 | CHECK_EQ(5.5, d.g); |
| 935 | CHECK_EQ(6.6, d.h); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 936 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 937 | CHECK_EQ(7.0f, f.a); |
| 938 | CHECK_EQ(8.0f, f.b); |
| 939 | CHECK_EQ(1.0f, f.c); |
| 940 | CHECK_EQ(2.0f, f.d); |
| 941 | CHECK_EQ(3.0f, f.e); |
| 942 | CHECK_EQ(4.0f, f.f); |
| 943 | CHECK_EQ(5.0f, f.g); |
| 944 | CHECK_EQ(6.0f, f.h); |
Ben Murdoch | 8b112d2 | 2011-06-08 16:22:53 +0100 | [diff] [blame] | 945 | } |
| 946 | |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 947 | |
| 948 | TEST(11) { |
| 949 | // Test instructions using the carry flag. |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 950 | CcTest::InitializeVM(); |
| 951 | Isolate* isolate = CcTest::i_isolate(); |
| 952 | HandleScope scope(isolate); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 953 | |
| 954 | typedef struct { |
| 955 | int32_t a; |
| 956 | int32_t b; |
| 957 | int32_t c; |
| 958 | int32_t d; |
| 959 | } I; |
| 960 | I i; |
| 961 | |
| 962 | i.a = 0xabcd0001; |
| 963 | i.b = 0xabcd0000; |
| 964 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 965 | Assembler assm(isolate, NULL, 0); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 966 | |
| 967 | // Test HeapObject untagging. |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 968 | __ ldr(r1, MemOperand(r0, offsetof(I, a))); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 969 | __ mov(r1, Operand(r1, ASR, 1), SetCC); |
| 970 | __ adc(r1, r1, Operand(r1), LeaveCC, cs); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 971 | __ str(r1, MemOperand(r0, offsetof(I, a))); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 972 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 973 | __ ldr(r2, MemOperand(r0, offsetof(I, b))); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 974 | __ mov(r2, Operand(r2, ASR, 1), SetCC); |
| 975 | __ adc(r2, r2, Operand(r2), LeaveCC, cs); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 976 | __ str(r2, MemOperand(r0, offsetof(I, b))); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 977 | |
| 978 | // Test corner cases. |
| 979 | __ mov(r1, Operand(0xffffffff)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 980 | __ mov(r2, Operand::Zero()); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 981 | __ mov(r3, Operand(r1, ASR, 1), SetCC); // Set the carry. |
| 982 | __ adc(r3, r1, Operand(r2)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 983 | __ str(r3, MemOperand(r0, offsetof(I, c))); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 984 | |
| 985 | __ mov(r1, Operand(0xffffffff)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 986 | __ mov(r2, Operand::Zero()); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 987 | __ mov(r3, Operand(r2, ASR, 1), SetCC); // Unset the carry. |
| 988 | __ adc(r3, r1, Operand(r2)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 989 | __ str(r3, MemOperand(r0, offsetof(I, d))); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 990 | |
| 991 | __ mov(pc, Operand(lr)); |
| 992 | |
| 993 | CodeDesc desc; |
| 994 | assm.GetCode(&desc); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 995 | Handle<Code> code = isolate->factory()->NewCode( |
| 996 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 997 | #ifdef DEBUG |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 998 | OFStream os(stdout); |
| 999 | code->Print(os); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 1000 | #endif |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1001 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1002 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &i, 0, 0, 0, 0); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 1003 | USE(dummy); |
| 1004 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1005 | CHECK_EQ(static_cast<int32_t>(0xabcd0001), i.a); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 1006 | CHECK_EQ(static_cast<int32_t>(0xabcd0000) >> 1, i.b); |
| 1007 | CHECK_EQ(0x00000000, i.c); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1008 | CHECK_EQ(static_cast<int32_t>(0xffffffff), i.d); |
Ben Murdoch | 257744e | 2011-11-30 15:57:28 +0000 | [diff] [blame] | 1009 | } |
| 1010 | |
Ben Murdoch | 69a99ed | 2011-11-30 16:03:39 +0000 | [diff] [blame] | 1011 | |
| 1012 | TEST(12) { |
| 1013 | // Test chaining of label usages within instructions (issue 1644). |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1014 | CcTest::InitializeVM(); |
| 1015 | Isolate* isolate = CcTest::i_isolate(); |
| 1016 | HandleScope scope(isolate); |
Ben Murdoch | 69a99ed | 2011-11-30 16:03:39 +0000 | [diff] [blame] | 1017 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1018 | Assembler assm(isolate, NULL, 0); |
Ben Murdoch | 69a99ed | 2011-11-30 16:03:39 +0000 | [diff] [blame] | 1019 | Label target; |
| 1020 | __ b(eq, &target); |
| 1021 | __ b(ne, &target); |
| 1022 | __ bind(&target); |
| 1023 | __ nop(); |
| 1024 | } |
| 1025 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1026 | |
| 1027 | TEST(13) { |
| 1028 | // Test VFP instructions using registers d16-d31. |
| 1029 | CcTest::InitializeVM(); |
| 1030 | Isolate* isolate = CcTest::i_isolate(); |
| 1031 | HandleScope scope(isolate); |
| 1032 | |
| 1033 | if (!CpuFeatures::IsSupported(VFP32DREGS)) { |
| 1034 | return; |
| 1035 | } |
| 1036 | |
| 1037 | typedef struct { |
| 1038 | double a; |
| 1039 | double b; |
| 1040 | double c; |
| 1041 | double x; |
| 1042 | double y; |
| 1043 | double z; |
| 1044 | double i; |
| 1045 | double j; |
| 1046 | double k; |
| 1047 | uint32_t low; |
| 1048 | uint32_t high; |
| 1049 | } T; |
| 1050 | T t; |
| 1051 | |
| 1052 | // Create a function that accepts &t, and loads, manipulates, and stores |
| 1053 | // the doubles and floats. |
| 1054 | Assembler assm(isolate, NULL, 0); |
| 1055 | Label L, C; |
| 1056 | |
| 1057 | |
| 1058 | if (CpuFeatures::IsSupported(VFP3)) { |
| 1059 | CpuFeatureScope scope(&assm, VFP3); |
| 1060 | |
| 1061 | __ stm(db_w, sp, r4.bit() | lr.bit()); |
| 1062 | |
| 1063 | // Load a, b, c into d16, d17, d18. |
| 1064 | __ mov(r4, Operand(r0)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1065 | __ vldr(d16, r4, offsetof(T, a)); |
| 1066 | __ vldr(d17, r4, offsetof(T, b)); |
| 1067 | __ vldr(d18, r4, offsetof(T, c)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1068 | |
| 1069 | __ vneg(d25, d16); |
| 1070 | __ vadd(d25, d25, d17); |
| 1071 | __ vsub(d25, d25, d18); |
| 1072 | __ vmul(d25, d25, d25); |
| 1073 | __ vdiv(d25, d25, d18); |
| 1074 | |
| 1075 | __ vmov(d16, d25); |
| 1076 | __ vsqrt(d17, d25); |
| 1077 | __ vneg(d17, d17); |
| 1078 | __ vabs(d17, d17); |
| 1079 | __ vmla(d18, d16, d17); |
| 1080 | |
| 1081 | // Store d16, d17, d18 into a, b, c. |
| 1082 | __ mov(r4, Operand(r0)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1083 | __ vstr(d16, r4, offsetof(T, a)); |
| 1084 | __ vstr(d17, r4, offsetof(T, b)); |
| 1085 | __ vstr(d18, r4, offsetof(T, c)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1086 | |
| 1087 | // Load x, y, z into d29-d31. |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1088 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, x)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1089 | __ vldm(ia_w, r4, d29, d31); |
| 1090 | |
| 1091 | // Swap d29 and d30 via r registers. |
| 1092 | __ vmov(r1, r2, d29); |
| 1093 | __ vmov(d29, d30); |
| 1094 | __ vmov(d30, r1, r2); |
| 1095 | |
| 1096 | // Convert to and from integer. |
| 1097 | __ vcvt_s32_f64(s1, d31); |
| 1098 | __ vcvt_f64_u32(d31, s1); |
| 1099 | |
| 1100 | // Store d29-d31 into x, y, z. |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1101 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, x)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1102 | __ vstm(ia_w, r4, d29, d31); |
| 1103 | |
| 1104 | // Move constants into d20, d21, d22 and store into i, j, k. |
| 1105 | __ vmov(d20, 14.7610017472335499); |
| 1106 | __ vmov(d21, 16.0); |
| 1107 | __ mov(r1, Operand(372106121)); |
| 1108 | __ mov(r2, Operand(1079146608)); |
| 1109 | __ vmov(d22, VmovIndexLo, r1); |
| 1110 | __ vmov(d22, VmovIndexHi, r2); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1111 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, i)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1112 | __ vstm(ia_w, r4, d20, d22); |
| 1113 | // Move d22 into low and high. |
| 1114 | __ vmov(r4, VmovIndexLo, d22); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1115 | __ str(r4, MemOperand(r0, offsetof(T, low))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1116 | __ vmov(r4, VmovIndexHi, d22); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1117 | __ str(r4, MemOperand(r0, offsetof(T, high))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1118 | |
| 1119 | __ ldm(ia_w, sp, r4.bit() | pc.bit()); |
| 1120 | |
| 1121 | CodeDesc desc; |
| 1122 | assm.GetCode(&desc); |
| 1123 | Handle<Code> code = isolate->factory()->NewCode( |
| 1124 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1125 | #ifdef DEBUG |
| 1126 | OFStream os(stdout); |
| 1127 | code->Print(os); |
| 1128 | #endif |
| 1129 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1130 | t.a = 1.5; |
| 1131 | t.b = 2.75; |
| 1132 | t.c = 17.17; |
| 1133 | t.x = 1.5; |
| 1134 | t.y = 2.75; |
| 1135 | t.z = 17.17; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1136 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1137 | USE(dummy); |
| 1138 | CHECK_EQ(14.7610017472335499, t.a); |
| 1139 | CHECK_EQ(3.84200491244266251, t.b); |
| 1140 | CHECK_EQ(73.8818412254460241, t.c); |
| 1141 | CHECK_EQ(2.75, t.x); |
| 1142 | CHECK_EQ(1.5, t.y); |
| 1143 | CHECK_EQ(17.0, t.z); |
| 1144 | CHECK_EQ(14.7610017472335499, t.i); |
| 1145 | CHECK_EQ(16.0, t.j); |
| 1146 | CHECK_EQ(73.8818412254460241, t.k); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1147 | CHECK_EQ(372106121u, t.low); |
| 1148 | CHECK_EQ(1079146608u, t.high); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1149 | } |
| 1150 | } |
| 1151 | |
| 1152 | |
| 1153 | TEST(14) { |
| 1154 | // Test the VFP Canonicalized Nan mode. |
| 1155 | CcTest::InitializeVM(); |
| 1156 | Isolate* isolate = CcTest::i_isolate(); |
| 1157 | HandleScope scope(isolate); |
| 1158 | |
| 1159 | typedef struct { |
| 1160 | double left; |
| 1161 | double right; |
| 1162 | double add_result; |
| 1163 | double sub_result; |
| 1164 | double mul_result; |
| 1165 | double div_result; |
| 1166 | } T; |
| 1167 | T t; |
| 1168 | |
| 1169 | // Create a function that makes the four basic operations. |
| 1170 | Assembler assm(isolate, NULL, 0); |
| 1171 | |
| 1172 | // Ensure FPSCR state (as JSEntryStub does). |
| 1173 | Label fpscr_done; |
| 1174 | __ vmrs(r1); |
| 1175 | __ tst(r1, Operand(kVFPDefaultNaNModeControlBit)); |
| 1176 | __ b(ne, &fpscr_done); |
| 1177 | __ orr(r1, r1, Operand(kVFPDefaultNaNModeControlBit)); |
| 1178 | __ vmsr(r1); |
| 1179 | __ bind(&fpscr_done); |
| 1180 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1181 | __ vldr(d0, r0, offsetof(T, left)); |
| 1182 | __ vldr(d1, r0, offsetof(T, right)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1183 | __ vadd(d2, d0, d1); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1184 | __ vstr(d2, r0, offsetof(T, add_result)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1185 | __ vsub(d2, d0, d1); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1186 | __ vstr(d2, r0, offsetof(T, sub_result)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1187 | __ vmul(d2, d0, d1); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1188 | __ vstr(d2, r0, offsetof(T, mul_result)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1189 | __ vdiv(d2, d0, d1); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1190 | __ vstr(d2, r0, offsetof(T, div_result)); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1191 | |
| 1192 | __ mov(pc, Operand(lr)); |
| 1193 | |
| 1194 | CodeDesc desc; |
| 1195 | assm.GetCode(&desc); |
| 1196 | Handle<Code> code = isolate->factory()->NewCode( |
| 1197 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1198 | #ifdef DEBUG |
| 1199 | OFStream os(stdout); |
| 1200 | code->Print(os); |
| 1201 | #endif |
| 1202 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1203 | t.left = bit_cast<double>(kHoleNanInt64); |
| 1204 | t.right = 1; |
| 1205 | t.add_result = 0; |
| 1206 | t.sub_result = 0; |
| 1207 | t.mul_result = 0; |
| 1208 | t.div_result = 0; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1209 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1210 | USE(dummy); |
| 1211 | const uint32_t kArmNanUpper32 = 0x7ff80000; |
| 1212 | const uint32_t kArmNanLower32 = 0x00000000; |
| 1213 | #ifdef DEBUG |
| 1214 | const uint64_t kArmNanInt64 = |
| 1215 | (static_cast<uint64_t>(kArmNanUpper32) << 32) | kArmNanLower32; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1216 | CHECK(kArmNanInt64 != kHoleNanInt64); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1217 | #endif |
| 1218 | // With VFP2 the sign of the canonicalized Nan is undefined. So |
| 1219 | // we remove the sign bit for the upper tests. |
| 1220 | CHECK_EQ(kArmNanUpper32, |
| 1221 | (bit_cast<int64_t>(t.add_result) >> 32) & 0x7fffffff); |
| 1222 | CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.add_result) & 0xffffffffu); |
| 1223 | CHECK_EQ(kArmNanUpper32, |
| 1224 | (bit_cast<int64_t>(t.sub_result) >> 32) & 0x7fffffff); |
| 1225 | CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.sub_result) & 0xffffffffu); |
| 1226 | CHECK_EQ(kArmNanUpper32, |
| 1227 | (bit_cast<int64_t>(t.mul_result) >> 32) & 0x7fffffff); |
| 1228 | CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.mul_result) & 0xffffffffu); |
| 1229 | CHECK_EQ(kArmNanUpper32, |
| 1230 | (bit_cast<int64_t>(t.div_result) >> 32) & 0x7fffffff); |
| 1231 | CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.div_result) & 0xffffffffu); |
| 1232 | } |
| 1233 | |
| 1234 | |
| 1235 | TEST(15) { |
| 1236 | // Test the Neon instructions. |
| 1237 | CcTest::InitializeVM(); |
| 1238 | Isolate* isolate = CcTest::i_isolate(); |
| 1239 | HandleScope scope(isolate); |
| 1240 | |
| 1241 | typedef struct { |
| 1242 | uint32_t src0; |
| 1243 | uint32_t src1; |
| 1244 | uint32_t src2; |
| 1245 | uint32_t src3; |
| 1246 | uint32_t src4; |
| 1247 | uint32_t src5; |
| 1248 | uint32_t src6; |
| 1249 | uint32_t src7; |
| 1250 | uint32_t dst0; |
| 1251 | uint32_t dst1; |
| 1252 | uint32_t dst2; |
| 1253 | uint32_t dst3; |
| 1254 | uint32_t dst4; |
| 1255 | uint32_t dst5; |
| 1256 | uint32_t dst6; |
| 1257 | uint32_t dst7; |
| 1258 | uint32_t srcA0; |
| 1259 | uint32_t srcA1; |
| 1260 | uint32_t dstA0; |
| 1261 | uint32_t dstA1; |
| 1262 | uint32_t dstA2; |
| 1263 | uint32_t dstA3; |
| 1264 | uint32_t dstA4; |
| 1265 | uint32_t dstA5; |
| 1266 | uint32_t dstA6; |
| 1267 | uint32_t dstA7; |
| 1268 | } T; |
| 1269 | T t; |
| 1270 | |
| 1271 | // Create a function that accepts &t, and loads, manipulates, and stores |
| 1272 | // the doubles and floats. |
| 1273 | Assembler assm(isolate, NULL, 0); |
| 1274 | |
| 1275 | |
| 1276 | if (CpuFeatures::IsSupported(NEON)) { |
| 1277 | CpuFeatureScope scope(&assm, NEON); |
| 1278 | |
| 1279 | __ stm(db_w, sp, r4.bit() | lr.bit()); |
| 1280 | // Move 32 bytes with neon. |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1281 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, src0)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1282 | __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1283 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, dst0)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1284 | __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4)); |
| 1285 | |
| 1286 | // Expand 8 bytes into 8 words(16 bits). |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1287 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, srcA0)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1288 | __ vld1(Neon8, NeonListOperand(d0), NeonMemOperand(r4)); |
| 1289 | __ vmovl(NeonU8, q0, d0); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1290 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, dstA0)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1291 | __ vst1(Neon8, NeonListOperand(d0, 2), NeonMemOperand(r4)); |
| 1292 | |
| 1293 | // The same expansion, but with different source and destination registers. |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1294 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, srcA0)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1295 | __ vld1(Neon8, NeonListOperand(d1), NeonMemOperand(r4)); |
| 1296 | __ vmovl(NeonU8, q1, d1); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1297 | __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, dstA4)))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1298 | __ vst1(Neon8, NeonListOperand(d2, 2), NeonMemOperand(r4)); |
| 1299 | |
| 1300 | __ ldm(ia_w, sp, r4.bit() | pc.bit()); |
| 1301 | |
| 1302 | CodeDesc desc; |
| 1303 | assm.GetCode(&desc); |
| 1304 | Handle<Code> code = isolate->factory()->NewCode( |
| 1305 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1306 | #ifdef DEBUG |
| 1307 | OFStream os(stdout); |
| 1308 | code->Print(os); |
| 1309 | #endif |
| 1310 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1311 | t.src0 = 0x01020304; |
| 1312 | t.src1 = 0x11121314; |
| 1313 | t.src2 = 0x21222324; |
| 1314 | t.src3 = 0x31323334; |
| 1315 | t.src4 = 0x41424344; |
| 1316 | t.src5 = 0x51525354; |
| 1317 | t.src6 = 0x61626364; |
| 1318 | t.src7 = 0x71727374; |
| 1319 | t.dst0 = 0; |
| 1320 | t.dst1 = 0; |
| 1321 | t.dst2 = 0; |
| 1322 | t.dst3 = 0; |
| 1323 | t.dst4 = 0; |
| 1324 | t.dst5 = 0; |
| 1325 | t.dst6 = 0; |
| 1326 | t.dst7 = 0; |
| 1327 | t.srcA0 = 0x41424344; |
| 1328 | t.srcA1 = 0x81828384; |
| 1329 | t.dstA0 = 0; |
| 1330 | t.dstA1 = 0; |
| 1331 | t.dstA2 = 0; |
| 1332 | t.dstA3 = 0; |
| 1333 | t.dstA4 = 0; |
| 1334 | t.dstA5 = 0; |
| 1335 | t.dstA6 = 0; |
| 1336 | t.dstA7 = 0; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1337 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1338 | USE(dummy); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1339 | CHECK_EQ(0x01020304u, t.dst0); |
| 1340 | CHECK_EQ(0x11121314u, t.dst1); |
| 1341 | CHECK_EQ(0x21222324u, t.dst2); |
| 1342 | CHECK_EQ(0x31323334u, t.dst3); |
| 1343 | CHECK_EQ(0x41424344u, t.dst4); |
| 1344 | CHECK_EQ(0x51525354u, t.dst5); |
| 1345 | CHECK_EQ(0x61626364u, t.dst6); |
| 1346 | CHECK_EQ(0x71727374u, t.dst7); |
| 1347 | CHECK_EQ(0x00430044u, t.dstA0); |
| 1348 | CHECK_EQ(0x00410042u, t.dstA1); |
| 1349 | CHECK_EQ(0x00830084u, t.dstA2); |
| 1350 | CHECK_EQ(0x00810082u, t.dstA3); |
| 1351 | CHECK_EQ(0x00430044u, t.dstA4); |
| 1352 | CHECK_EQ(0x00410042u, t.dstA5); |
| 1353 | CHECK_EQ(0x00830084u, t.dstA6); |
| 1354 | CHECK_EQ(0x00810082u, t.dstA7); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1355 | } |
| 1356 | } |
| 1357 | |
| 1358 | |
| 1359 | TEST(16) { |
| 1360 | // Test the pkh, uxtb, uxtab and uxtb16 instructions. |
| 1361 | CcTest::InitializeVM(); |
| 1362 | Isolate* isolate = CcTest::i_isolate(); |
| 1363 | HandleScope scope(isolate); |
| 1364 | |
| 1365 | typedef struct { |
| 1366 | uint32_t src0; |
| 1367 | uint32_t src1; |
| 1368 | uint32_t src2; |
| 1369 | uint32_t dst0; |
| 1370 | uint32_t dst1; |
| 1371 | uint32_t dst2; |
| 1372 | uint32_t dst3; |
| 1373 | uint32_t dst4; |
| 1374 | } T; |
| 1375 | T t; |
| 1376 | |
| 1377 | // Create a function that accepts &t, and loads, manipulates, and stores |
| 1378 | // the doubles and floats. |
| 1379 | Assembler assm(isolate, NULL, 0); |
| 1380 | |
| 1381 | __ stm(db_w, sp, r4.bit() | lr.bit()); |
| 1382 | |
| 1383 | __ mov(r4, Operand(r0)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1384 | __ ldr(r0, MemOperand(r4, offsetof(T, src0))); |
| 1385 | __ ldr(r1, MemOperand(r4, offsetof(T, src1))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1386 | |
| 1387 | __ pkhbt(r2, r0, Operand(r1, LSL, 8)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1388 | __ str(r2, MemOperand(r4, offsetof(T, dst0))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1389 | |
| 1390 | __ pkhtb(r2, r0, Operand(r1, ASR, 8)); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1391 | __ str(r2, MemOperand(r4, offsetof(T, dst1))); |
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 | __ uxtb16(r2, r0, 8); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1394 | __ str(r2, MemOperand(r4, offsetof(T, dst2))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1395 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1396 | __ uxtb(r2, r0, 8); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1397 | __ str(r2, MemOperand(r4, offsetof(T, dst3))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1398 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1399 | __ ldr(r0, MemOperand(r4, offsetof(T, src2))); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1400 | __ uxtab(r2, r0, r1, 8); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1401 | __ str(r2, MemOperand(r4, offsetof(T, dst4))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1402 | |
| 1403 | __ ldm(ia_w, sp, r4.bit() | pc.bit()); |
| 1404 | |
| 1405 | CodeDesc desc; |
| 1406 | assm.GetCode(&desc); |
| 1407 | Handle<Code> code = isolate->factory()->NewCode( |
| 1408 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1409 | #ifdef DEBUG |
| 1410 | OFStream os(stdout); |
| 1411 | code->Print(os); |
| 1412 | #endif |
| 1413 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1414 | t.src0 = 0x01020304; |
| 1415 | t.src1 = 0x11121314; |
| 1416 | t.src2 = 0x11121300; |
| 1417 | t.dst0 = 0; |
| 1418 | t.dst1 = 0; |
| 1419 | t.dst2 = 0; |
| 1420 | t.dst3 = 0; |
| 1421 | t.dst4 = 0; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1422 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1423 | USE(dummy); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1424 | CHECK_EQ(0x12130304u, t.dst0); |
| 1425 | CHECK_EQ(0x01021213u, t.dst1); |
| 1426 | CHECK_EQ(0x00010003u, t.dst2); |
| 1427 | CHECK_EQ(0x00000003u, t.dst3); |
| 1428 | CHECK_EQ(0x11121313u, t.dst4); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1429 | } |
| 1430 | |
| 1431 | |
| 1432 | TEST(17) { |
| 1433 | // Test generating labels at high addresses. |
| 1434 | // Should not assert. |
| 1435 | CcTest::InitializeVM(); |
| 1436 | Isolate* isolate = CcTest::i_isolate(); |
| 1437 | HandleScope scope(isolate); |
| 1438 | |
| 1439 | // Generate a code segment that will be longer than 2^24 bytes. |
| 1440 | Assembler assm(isolate, NULL, 0); |
| 1441 | for (size_t i = 0; i < 1 << 23 ; ++i) { // 2^23 |
| 1442 | __ nop(); |
| 1443 | } |
| 1444 | |
| 1445 | Label target; |
| 1446 | __ b(eq, &target); |
| 1447 | __ bind(&target); |
| 1448 | __ nop(); |
| 1449 | } |
| 1450 | |
| 1451 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1452 | #define TEST_SDIV(expected_, dividend_, divisor_) \ |
| 1453 | t.dividend = dividend_; \ |
| 1454 | t.divisor = divisor_; \ |
| 1455 | t.result = 0; \ |
| 1456 | dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); \ |
| 1457 | CHECK_EQ(expected_, t.result); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1458 | |
| 1459 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1460 | TEST(sdiv) { |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1461 | // Test the sdiv. |
| 1462 | CcTest::InitializeVM(); |
| 1463 | Isolate* isolate = CcTest::i_isolate(); |
| 1464 | HandleScope scope(isolate); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1465 | Assembler assm(isolate, NULL, 0); |
| 1466 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1467 | struct T { |
| 1468 | int32_t dividend; |
| 1469 | int32_t divisor; |
| 1470 | int32_t result; |
| 1471 | } t; |
| 1472 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1473 | if (CpuFeatures::IsSupported(SUDIV)) { |
| 1474 | CpuFeatureScope scope(&assm, SUDIV); |
| 1475 | |
| 1476 | __ mov(r3, Operand(r0)); |
| 1477 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1478 | __ ldr(r0, MemOperand(r3, offsetof(T, dividend))); |
| 1479 | __ ldr(r1, MemOperand(r3, offsetof(T, divisor))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1480 | |
| 1481 | __ sdiv(r2, r0, r1); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1482 | __ str(r2, MemOperand(r3, offsetof(T, result))); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1483 | |
| 1484 | __ bx(lr); |
| 1485 | |
| 1486 | CodeDesc desc; |
| 1487 | assm.GetCode(&desc); |
| 1488 | Handle<Code> code = isolate->factory()->NewCode( |
| 1489 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1490 | #ifdef DEBUG |
| 1491 | OFStream os(stdout); |
| 1492 | code->Print(os); |
| 1493 | #endif |
| 1494 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1495 | Object* dummy; |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1496 | TEST_SDIV(0, kMinInt, 0); |
| 1497 | TEST_SDIV(0, 1024, 0); |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1498 | TEST_SDIV(1073741824, kMinInt, -2); |
| 1499 | TEST_SDIV(kMinInt, kMinInt, -1); |
| 1500 | TEST_SDIV(5, 10, 2); |
| 1501 | TEST_SDIV(3, 10, 3); |
| 1502 | TEST_SDIV(-5, 10, -2); |
| 1503 | TEST_SDIV(-3, 10, -3); |
| 1504 | TEST_SDIV(-5, -10, 2); |
| 1505 | TEST_SDIV(-3, -10, 3); |
| 1506 | TEST_SDIV(5, -10, -2); |
| 1507 | TEST_SDIV(3, -10, -3); |
| 1508 | USE(dummy); |
| 1509 | } |
| 1510 | } |
| 1511 | |
| 1512 | |
| 1513 | #undef TEST_SDIV |
| 1514 | |
| 1515 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1516 | #define TEST_UDIV(expected_, dividend_, divisor_) \ |
| 1517 | t.dividend = dividend_; \ |
| 1518 | t.divisor = divisor_; \ |
| 1519 | t.result = 0; \ |
| 1520 | dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); \ |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1521 | CHECK_EQ(expected_, t.result); |
| 1522 | |
| 1523 | |
| 1524 | TEST(udiv) { |
| 1525 | // Test the udiv. |
| 1526 | CcTest::InitializeVM(); |
| 1527 | Isolate* isolate = CcTest::i_isolate(); |
| 1528 | HandleScope scope(isolate); |
| 1529 | Assembler assm(isolate, NULL, 0); |
| 1530 | |
| 1531 | struct T { |
| 1532 | uint32_t dividend; |
| 1533 | uint32_t divisor; |
| 1534 | uint32_t result; |
| 1535 | } t; |
| 1536 | |
| 1537 | if (CpuFeatures::IsSupported(SUDIV)) { |
| 1538 | CpuFeatureScope scope(&assm, SUDIV); |
| 1539 | |
| 1540 | __ mov(r3, Operand(r0)); |
| 1541 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1542 | __ ldr(r0, MemOperand(r3, offsetof(T, dividend))); |
| 1543 | __ ldr(r1, MemOperand(r3, offsetof(T, divisor))); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1544 | |
| 1545 | __ sdiv(r2, r0, r1); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1546 | __ str(r2, MemOperand(r3, offsetof(T, result))); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1547 | |
| 1548 | __ bx(lr); |
| 1549 | |
| 1550 | CodeDesc desc; |
| 1551 | assm.GetCode(&desc); |
| 1552 | Handle<Code> code = isolate->factory()->NewCode( |
| 1553 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1554 | #ifdef DEBUG |
| 1555 | OFStream os(stdout); |
| 1556 | code->Print(os); |
| 1557 | #endif |
| 1558 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1559 | Object* dummy; |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1560 | TEST_UDIV(0u, 0, 0); |
| 1561 | TEST_UDIV(0u, 1024, 0); |
| 1562 | TEST_UDIV(5u, 10, 2); |
| 1563 | TEST_UDIV(3u, 10, 3); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1564 | USE(dummy); |
| 1565 | } |
| 1566 | } |
| 1567 | |
| 1568 | |
| 1569 | #undef TEST_UDIV |
| 1570 | |
| 1571 | |
| 1572 | TEST(smmla) { |
| 1573 | CcTest::InitializeVM(); |
| 1574 | Isolate* const isolate = CcTest::i_isolate(); |
| 1575 | HandleScope scope(isolate); |
| 1576 | RandomNumberGenerator* const rng = isolate->random_number_generator(); |
| 1577 | Assembler assm(isolate, nullptr, 0); |
| 1578 | __ smmla(r1, r1, r2, r3); |
| 1579 | __ str(r1, MemOperand(r0)); |
| 1580 | __ bx(lr); |
| 1581 | CodeDesc desc; |
| 1582 | assm.GetCode(&desc); |
| 1583 | Handle<Code> code = isolate->factory()->NewCode( |
| 1584 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1585 | #ifdef OBJECT_PRINT |
| 1586 | code->Print(std::cout); |
| 1587 | #endif |
| 1588 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1589 | for (size_t i = 0; i < 128; ++i) { |
| 1590 | int32_t r, x = rng->NextInt(), y = rng->NextInt(), z = rng->NextInt(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1591 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, y, z, 0); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1592 | CHECK_EQ(bits::SignedMulHighAndAdd32(x, y, z), r); |
| 1593 | USE(dummy); |
| 1594 | } |
| 1595 | } |
| 1596 | |
| 1597 | |
| 1598 | TEST(smmul) { |
| 1599 | CcTest::InitializeVM(); |
| 1600 | Isolate* const isolate = CcTest::i_isolate(); |
| 1601 | HandleScope scope(isolate); |
| 1602 | RandomNumberGenerator* const rng = isolate->random_number_generator(); |
| 1603 | Assembler assm(isolate, nullptr, 0); |
| 1604 | __ smmul(r1, r1, r2); |
| 1605 | __ str(r1, MemOperand(r0)); |
| 1606 | __ bx(lr); |
| 1607 | CodeDesc desc; |
| 1608 | assm.GetCode(&desc); |
| 1609 | Handle<Code> code = isolate->factory()->NewCode( |
| 1610 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1611 | #ifdef OBJECT_PRINT |
| 1612 | code->Print(std::cout); |
| 1613 | #endif |
| 1614 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1615 | for (size_t i = 0; i < 128; ++i) { |
| 1616 | int32_t r, x = rng->NextInt(), y = rng->NextInt(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1617 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, y, 0, 0); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1618 | CHECK_EQ(bits::SignedMulHigh32(x, y), r); |
| 1619 | USE(dummy); |
| 1620 | } |
| 1621 | } |
| 1622 | |
| 1623 | |
| 1624 | TEST(sxtb) { |
| 1625 | CcTest::InitializeVM(); |
| 1626 | Isolate* const isolate = CcTest::i_isolate(); |
| 1627 | HandleScope scope(isolate); |
| 1628 | RandomNumberGenerator* const rng = isolate->random_number_generator(); |
| 1629 | Assembler assm(isolate, nullptr, 0); |
| 1630 | __ sxtb(r1, r1); |
| 1631 | __ str(r1, MemOperand(r0)); |
| 1632 | __ bx(lr); |
| 1633 | CodeDesc desc; |
| 1634 | assm.GetCode(&desc); |
| 1635 | Handle<Code> code = isolate->factory()->NewCode( |
| 1636 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1637 | #ifdef OBJECT_PRINT |
| 1638 | code->Print(std::cout); |
| 1639 | #endif |
| 1640 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1641 | for (size_t i = 0; i < 128; ++i) { |
| 1642 | int32_t r, x = rng->NextInt(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1643 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, 0, 0, 0); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1644 | CHECK_EQ(static_cast<int32_t>(static_cast<int8_t>(x)), r); |
| 1645 | USE(dummy); |
| 1646 | } |
| 1647 | } |
| 1648 | |
| 1649 | |
| 1650 | TEST(sxtab) { |
| 1651 | CcTest::InitializeVM(); |
| 1652 | Isolate* const isolate = CcTest::i_isolate(); |
| 1653 | HandleScope scope(isolate); |
| 1654 | RandomNumberGenerator* const rng = isolate->random_number_generator(); |
| 1655 | Assembler assm(isolate, nullptr, 0); |
| 1656 | __ sxtab(r1, r2, r1); |
| 1657 | __ str(r1, MemOperand(r0)); |
| 1658 | __ bx(lr); |
| 1659 | CodeDesc desc; |
| 1660 | assm.GetCode(&desc); |
| 1661 | Handle<Code> code = isolate->factory()->NewCode( |
| 1662 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1663 | #ifdef OBJECT_PRINT |
| 1664 | code->Print(std::cout); |
| 1665 | #endif |
| 1666 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1667 | for (size_t i = 0; i < 128; ++i) { |
| 1668 | int32_t r, x = rng->NextInt(), y = rng->NextInt(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1669 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, y, 0, 0); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1670 | CHECK_EQ(static_cast<int32_t>(static_cast<int8_t>(x)) + y, r); |
| 1671 | USE(dummy); |
| 1672 | } |
| 1673 | } |
| 1674 | |
| 1675 | |
| 1676 | TEST(sxth) { |
| 1677 | CcTest::InitializeVM(); |
| 1678 | Isolate* const isolate = CcTest::i_isolate(); |
| 1679 | HandleScope scope(isolate); |
| 1680 | RandomNumberGenerator* const rng = isolate->random_number_generator(); |
| 1681 | Assembler assm(isolate, nullptr, 0); |
| 1682 | __ sxth(r1, r1); |
| 1683 | __ str(r1, MemOperand(r0)); |
| 1684 | __ bx(lr); |
| 1685 | CodeDesc desc; |
| 1686 | assm.GetCode(&desc); |
| 1687 | Handle<Code> code = isolate->factory()->NewCode( |
| 1688 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1689 | #ifdef OBJECT_PRINT |
| 1690 | code->Print(std::cout); |
| 1691 | #endif |
| 1692 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1693 | for (size_t i = 0; i < 128; ++i) { |
| 1694 | int32_t r, x = rng->NextInt(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1695 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, 0, 0, 0); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1696 | CHECK_EQ(static_cast<int32_t>(static_cast<int16_t>(x)), r); |
| 1697 | USE(dummy); |
| 1698 | } |
| 1699 | } |
| 1700 | |
| 1701 | |
| 1702 | TEST(sxtah) { |
| 1703 | CcTest::InitializeVM(); |
| 1704 | Isolate* const isolate = CcTest::i_isolate(); |
| 1705 | HandleScope scope(isolate); |
| 1706 | RandomNumberGenerator* const rng = isolate->random_number_generator(); |
| 1707 | Assembler assm(isolate, nullptr, 0); |
| 1708 | __ sxtah(r1, r2, r1); |
| 1709 | __ str(r1, MemOperand(r0)); |
| 1710 | __ bx(lr); |
| 1711 | CodeDesc desc; |
| 1712 | assm.GetCode(&desc); |
| 1713 | Handle<Code> code = isolate->factory()->NewCode( |
| 1714 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1715 | #ifdef OBJECT_PRINT |
| 1716 | code->Print(std::cout); |
| 1717 | #endif |
| 1718 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1719 | for (size_t i = 0; i < 128; ++i) { |
| 1720 | int32_t r, x = rng->NextInt(), y = rng->NextInt(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1721 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, y, 0, 0); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1722 | CHECK_EQ(static_cast<int32_t>(static_cast<int16_t>(x)) + y, r); |
| 1723 | USE(dummy); |
| 1724 | } |
| 1725 | } |
| 1726 | |
| 1727 | |
| 1728 | TEST(uxtb) { |
| 1729 | CcTest::InitializeVM(); |
| 1730 | Isolate* const isolate = CcTest::i_isolate(); |
| 1731 | HandleScope scope(isolate); |
| 1732 | RandomNumberGenerator* const rng = isolate->random_number_generator(); |
| 1733 | Assembler assm(isolate, nullptr, 0); |
| 1734 | __ uxtb(r1, r1); |
| 1735 | __ str(r1, MemOperand(r0)); |
| 1736 | __ bx(lr); |
| 1737 | CodeDesc desc; |
| 1738 | assm.GetCode(&desc); |
| 1739 | Handle<Code> code = isolate->factory()->NewCode( |
| 1740 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1741 | #ifdef OBJECT_PRINT |
| 1742 | code->Print(std::cout); |
| 1743 | #endif |
| 1744 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1745 | for (size_t i = 0; i < 128; ++i) { |
| 1746 | int32_t r, x = rng->NextInt(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1747 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, 0, 0, 0); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1748 | CHECK_EQ(static_cast<int32_t>(static_cast<uint8_t>(x)), r); |
| 1749 | USE(dummy); |
| 1750 | } |
| 1751 | } |
| 1752 | |
| 1753 | |
| 1754 | TEST(uxtab) { |
| 1755 | CcTest::InitializeVM(); |
| 1756 | Isolate* const isolate = CcTest::i_isolate(); |
| 1757 | HandleScope scope(isolate); |
| 1758 | RandomNumberGenerator* const rng = isolate->random_number_generator(); |
| 1759 | Assembler assm(isolate, nullptr, 0); |
| 1760 | __ uxtab(r1, r2, r1); |
| 1761 | __ str(r1, MemOperand(r0)); |
| 1762 | __ bx(lr); |
| 1763 | CodeDesc desc; |
| 1764 | assm.GetCode(&desc); |
| 1765 | Handle<Code> code = isolate->factory()->NewCode( |
| 1766 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1767 | #ifdef OBJECT_PRINT |
| 1768 | code->Print(std::cout); |
| 1769 | #endif |
| 1770 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1771 | for (size_t i = 0; i < 128; ++i) { |
| 1772 | int32_t r, x = rng->NextInt(), y = rng->NextInt(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1773 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, y, 0, 0); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1774 | CHECK_EQ(static_cast<int32_t>(static_cast<uint8_t>(x)) + y, r); |
| 1775 | USE(dummy); |
| 1776 | } |
| 1777 | } |
| 1778 | |
| 1779 | |
| 1780 | TEST(uxth) { |
| 1781 | CcTest::InitializeVM(); |
| 1782 | Isolate* const isolate = CcTest::i_isolate(); |
| 1783 | HandleScope scope(isolate); |
| 1784 | RandomNumberGenerator* const rng = isolate->random_number_generator(); |
| 1785 | Assembler assm(isolate, nullptr, 0); |
| 1786 | __ uxth(r1, r1); |
| 1787 | __ str(r1, MemOperand(r0)); |
| 1788 | __ bx(lr); |
| 1789 | CodeDesc desc; |
| 1790 | assm.GetCode(&desc); |
| 1791 | Handle<Code> code = isolate->factory()->NewCode( |
| 1792 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1793 | #ifdef OBJECT_PRINT |
| 1794 | code->Print(std::cout); |
| 1795 | #endif |
| 1796 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1797 | for (size_t i = 0; i < 128; ++i) { |
| 1798 | int32_t r, x = rng->NextInt(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1799 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, 0, 0, 0); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1800 | CHECK_EQ(static_cast<int32_t>(static_cast<uint16_t>(x)), r); |
| 1801 | USE(dummy); |
| 1802 | } |
| 1803 | } |
| 1804 | |
| 1805 | |
| 1806 | TEST(uxtah) { |
| 1807 | CcTest::InitializeVM(); |
| 1808 | Isolate* const isolate = CcTest::i_isolate(); |
| 1809 | HandleScope scope(isolate); |
| 1810 | RandomNumberGenerator* const rng = isolate->random_number_generator(); |
| 1811 | Assembler assm(isolate, nullptr, 0); |
| 1812 | __ uxtah(r1, r2, r1); |
| 1813 | __ str(r1, MemOperand(r0)); |
| 1814 | __ bx(lr); |
| 1815 | CodeDesc desc; |
| 1816 | assm.GetCode(&desc); |
| 1817 | Handle<Code> code = isolate->factory()->NewCode( |
| 1818 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1819 | #ifdef OBJECT_PRINT |
| 1820 | code->Print(std::cout); |
| 1821 | #endif |
| 1822 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1823 | for (size_t i = 0; i < 128; ++i) { |
| 1824 | int32_t r, x = rng->NextInt(), y = rng->NextInt(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1825 | Object* dummy = CALL_GENERATED_CODE(isolate, f, &r, x, y, 0, 0); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 1826 | CHECK_EQ(static_cast<int32_t>(static_cast<uint16_t>(x)) + y, r); |
| 1827 | USE(dummy); |
| 1828 | } |
| 1829 | } |
| 1830 | |
| 1831 | |
Ben Murdoch | 097c5b2 | 2016-05-18 11:27:45 +0100 | [diff] [blame] | 1832 | #define TEST_RBIT(expected_, input_) \ |
| 1833 | t.input = input_; \ |
| 1834 | t.result = 0; \ |
| 1835 | dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); \ |
| 1836 | CHECK_EQ(expected_, t.result); |
| 1837 | |
| 1838 | |
| 1839 | TEST(rbit) { |
| 1840 | CcTest::InitializeVM(); |
| 1841 | Isolate* const isolate = CcTest::i_isolate(); |
| 1842 | HandleScope scope(isolate); |
| 1843 | Assembler assm(isolate, nullptr, 0); |
| 1844 | |
| 1845 | if (CpuFeatures::IsSupported(ARMv7)) { |
| 1846 | CpuFeatureScope scope(&assm, ARMv7); |
| 1847 | |
| 1848 | typedef struct { |
| 1849 | uint32_t input; |
| 1850 | uint32_t result; |
| 1851 | } T; |
| 1852 | T t; |
| 1853 | |
| 1854 | __ ldr(r1, MemOperand(r0, offsetof(T, input))); |
| 1855 | __ rbit(r1, r1); |
| 1856 | __ str(r1, MemOperand(r0, offsetof(T, result))); |
| 1857 | __ bx(lr); |
| 1858 | |
| 1859 | CodeDesc desc; |
| 1860 | assm.GetCode(&desc); |
| 1861 | Handle<Code> code = isolate->factory()->NewCode( |
| 1862 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1863 | |
| 1864 | #ifdef OBJECT_PRINT |
| 1865 | code->Print(std::cout); |
| 1866 | #endif |
| 1867 | |
| 1868 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 1869 | Object* dummy = NULL; |
| 1870 | TEST_RBIT(0xffffffff, 0xffffffff); |
| 1871 | TEST_RBIT(0x00000000, 0x00000000); |
| 1872 | TEST_RBIT(0xffff0000, 0x0000ffff); |
| 1873 | TEST_RBIT(0xff00ff00, 0x00ff00ff); |
| 1874 | TEST_RBIT(0xf0f0f0f0, 0x0f0f0f0f); |
| 1875 | TEST_RBIT(0x1e6a2c48, 0x12345678); |
| 1876 | USE(dummy); |
| 1877 | } |
| 1878 | } |
| 1879 | |
| 1880 | |
Ben Murdoch | b8a8cc1 | 2014-11-26 15:28:44 +0000 | [diff] [blame] | 1881 | TEST(code_relative_offset) { |
| 1882 | // Test extracting the offset of a label from the beginning of the code |
| 1883 | // in a register. |
| 1884 | CcTest::InitializeVM(); |
| 1885 | Isolate* isolate = CcTest::i_isolate(); |
| 1886 | HandleScope scope(isolate); |
| 1887 | // Initialize a code object that will contain the code. |
| 1888 | Handle<Object> code_object(isolate->heap()->undefined_value(), isolate); |
| 1889 | |
| 1890 | Assembler assm(isolate, NULL, 0); |
| 1891 | |
| 1892 | Label start, target_away, target_faraway; |
| 1893 | |
| 1894 | __ stm(db_w, sp, r4.bit() | r5.bit() | lr.bit()); |
| 1895 | |
| 1896 | // r3 is used as the address zero, the test will crash when we load it. |
| 1897 | __ mov(r3, Operand::Zero()); |
| 1898 | |
| 1899 | // r5 will be a pointer to the start of the code. |
| 1900 | __ mov(r5, Operand(code_object)); |
| 1901 | __ mov_label_offset(r4, &start); |
| 1902 | |
| 1903 | __ mov_label_offset(r1, &target_faraway); |
| 1904 | __ str(r1, MemOperand(sp, kPointerSize, NegPreIndex)); |
| 1905 | |
| 1906 | __ mov_label_offset(r1, &target_away); |
| 1907 | |
| 1908 | // Jump straight to 'target_away' the first time and use the relative |
| 1909 | // position the second time. This covers the case when extracting the |
| 1910 | // position of a label which is linked. |
| 1911 | __ mov(r2, Operand::Zero()); |
| 1912 | __ bind(&start); |
| 1913 | __ cmp(r2, Operand::Zero()); |
| 1914 | __ b(eq, &target_away); |
| 1915 | __ add(pc, r5, r1); |
| 1916 | // Emit invalid instructions to push the label between 2^8 and 2^16 |
| 1917 | // instructions away. The test will crash if they are reached. |
| 1918 | for (int i = 0; i < (1 << 10); i++) { |
| 1919 | __ ldr(r3, MemOperand(r3)); |
| 1920 | } |
| 1921 | __ bind(&target_away); |
| 1922 | // This will be hit twice: r0 = r0 + 5 + 5. |
| 1923 | __ add(r0, r0, Operand(5)); |
| 1924 | |
| 1925 | __ ldr(r1, MemOperand(sp, kPointerSize, PostIndex), ne); |
| 1926 | __ add(pc, r5, r4, LeaveCC, ne); |
| 1927 | |
| 1928 | __ mov(r2, Operand(1)); |
| 1929 | __ b(&start); |
| 1930 | // Emit invalid instructions to push the label between 2^16 and 2^24 |
| 1931 | // instructions away. The test will crash if they are reached. |
| 1932 | for (int i = 0; i < (1 << 21); i++) { |
| 1933 | __ ldr(r3, MemOperand(r3)); |
| 1934 | } |
| 1935 | __ bind(&target_faraway); |
| 1936 | // r0 = r0 + 5 + 5 + 11 |
| 1937 | __ add(r0, r0, Operand(11)); |
| 1938 | |
| 1939 | __ ldm(ia_w, sp, r4.bit() | r5.bit() | pc.bit()); |
| 1940 | |
| 1941 | CodeDesc desc; |
| 1942 | assm.GetCode(&desc); |
| 1943 | Handle<Code> code = isolate->factory()->NewCode( |
| 1944 | desc, Code::ComputeFlags(Code::STUB), code_object); |
| 1945 | F1 f = FUNCTION_CAST<F1>(code->entry()); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 1946 | int res = |
| 1947 | 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] | 1948 | ::printf("f() = %d\n", res); |
| 1949 | CHECK_EQ(42, res); |
| 1950 | } |
| 1951 | |
Ben Murdoch | da12d29 | 2016-06-02 14:46:10 +0100 | [diff] [blame^] | 1952 | TEST(msr_mrs) { |
| 1953 | // Test msr and mrs. |
| 1954 | CcTest::InitializeVM(); |
| 1955 | Isolate* isolate = CcTest::i_isolate(); |
| 1956 | HandleScope scope(isolate); |
| 1957 | |
| 1958 | Assembler assm(isolate, NULL, 0); |
| 1959 | |
| 1960 | // Create a helper function: |
| 1961 | // void TestMsrMrs(uint32_t nzcv, |
| 1962 | // uint32_t * result_conditionals, |
| 1963 | // uint32_t * result_mrs); |
| 1964 | __ msr(CPSR_f, Operand(r0)); |
| 1965 | |
| 1966 | // Test that the condition flags have taken effect. |
| 1967 | __ mov(r3, Operand(0)); |
| 1968 | __ orr(r3, r3, Operand(1 << 31), LeaveCC, mi); // N |
| 1969 | __ orr(r3, r3, Operand(1 << 30), LeaveCC, eq); // Z |
| 1970 | __ orr(r3, r3, Operand(1 << 29), LeaveCC, cs); // C |
| 1971 | __ orr(r3, r3, Operand(1 << 28), LeaveCC, vs); // V |
| 1972 | __ str(r3, MemOperand(r1)); |
| 1973 | |
| 1974 | // Also check mrs, ignoring everything other than the flags. |
| 1975 | __ mrs(r3, CPSR); |
| 1976 | __ and_(r3, r3, Operand(kSpecialCondition)); |
| 1977 | __ str(r3, MemOperand(r2)); |
| 1978 | |
| 1979 | __ bx(lr); |
| 1980 | |
| 1981 | CodeDesc desc; |
| 1982 | assm.GetCode(&desc); |
| 1983 | Handle<Code> code = isolate->factory()->NewCode( |
| 1984 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 1985 | #ifdef DEBUG |
| 1986 | OFStream os(stdout); |
| 1987 | code->Print(os); |
| 1988 | #endif |
| 1989 | F5 f = FUNCTION_CAST<F5>(code->entry()); |
| 1990 | Object* dummy = nullptr; |
| 1991 | USE(dummy); |
| 1992 | |
| 1993 | #define CHECK_MSR_MRS(n, z, c, v) \ |
| 1994 | do { \ |
| 1995 | uint32_t nzcv = (n << 31) | (z << 30) | (c << 29) | (v << 28); \ |
| 1996 | uint32_t result_conditionals = -1; \ |
| 1997 | uint32_t result_mrs = -1; \ |
| 1998 | dummy = CALL_GENERATED_CODE(isolate, f, nzcv, &result_conditionals, \ |
| 1999 | &result_mrs, 0, 0); \ |
| 2000 | CHECK_EQ(nzcv, result_conditionals); \ |
| 2001 | CHECK_EQ(nzcv, result_mrs); \ |
| 2002 | } while (0); |
| 2003 | |
| 2004 | // N Z C V |
| 2005 | CHECK_MSR_MRS(0, 0, 0, 0); |
| 2006 | CHECK_MSR_MRS(0, 0, 0, 1); |
| 2007 | CHECK_MSR_MRS(0, 0, 1, 0); |
| 2008 | CHECK_MSR_MRS(0, 0, 1, 1); |
| 2009 | CHECK_MSR_MRS(0, 1, 0, 0); |
| 2010 | CHECK_MSR_MRS(0, 1, 0, 1); |
| 2011 | CHECK_MSR_MRS(0, 1, 1, 0); |
| 2012 | CHECK_MSR_MRS(0, 1, 1, 1); |
| 2013 | CHECK_MSR_MRS(1, 0, 0, 0); |
| 2014 | CHECK_MSR_MRS(1, 0, 0, 1); |
| 2015 | CHECK_MSR_MRS(1, 0, 1, 0); |
| 2016 | CHECK_MSR_MRS(1, 0, 1, 1); |
| 2017 | CHECK_MSR_MRS(1, 1, 0, 0); |
| 2018 | CHECK_MSR_MRS(1, 1, 0, 1); |
| 2019 | CHECK_MSR_MRS(1, 1, 1, 0); |
| 2020 | CHECK_MSR_MRS(1, 1, 1, 1); |
| 2021 | |
| 2022 | #undef CHECK_MSR_MRS |
| 2023 | } |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2024 | |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2025 | TEST(ARMv8_float32_vrintX) { |
| 2026 | // Test the vrintX floating point instructions. |
| 2027 | CcTest::InitializeVM(); |
| 2028 | Isolate* isolate = CcTest::i_isolate(); |
| 2029 | HandleScope scope(isolate); |
| 2030 | |
| 2031 | typedef struct { |
| 2032 | float input; |
| 2033 | float ar; |
| 2034 | float nr; |
| 2035 | float mr; |
| 2036 | float pr; |
| 2037 | float zr; |
| 2038 | } T; |
| 2039 | T t; |
| 2040 | |
| 2041 | // Create a function that accepts &t, and loads, manipulates, and stores |
| 2042 | // the floats. |
| 2043 | Assembler assm(isolate, NULL, 0); |
| 2044 | Label L, C; |
| 2045 | |
| 2046 | |
| 2047 | if (CpuFeatures::IsSupported(ARMv8)) { |
| 2048 | CpuFeatureScope scope(&assm, ARMv8); |
| 2049 | |
| 2050 | __ mov(ip, Operand(sp)); |
| 2051 | __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); |
| 2052 | |
| 2053 | __ mov(r4, Operand(r0)); |
| 2054 | |
| 2055 | // Test vrinta |
| 2056 | __ vldr(s6, r4, offsetof(T, input)); |
| 2057 | __ vrinta(s5, s6); |
| 2058 | __ vstr(s5, r4, offsetof(T, ar)); |
| 2059 | |
| 2060 | // Test vrintn |
| 2061 | __ vldr(s6, r4, offsetof(T, input)); |
| 2062 | __ vrintn(s5, s6); |
| 2063 | __ vstr(s5, r4, offsetof(T, nr)); |
| 2064 | |
| 2065 | // Test vrintp |
| 2066 | __ vldr(s6, r4, offsetof(T, input)); |
| 2067 | __ vrintp(s5, s6); |
| 2068 | __ vstr(s5, r4, offsetof(T, pr)); |
| 2069 | |
| 2070 | // Test vrintm |
| 2071 | __ vldr(s6, r4, offsetof(T, input)); |
| 2072 | __ vrintm(s5, s6); |
| 2073 | __ vstr(s5, r4, offsetof(T, mr)); |
| 2074 | |
| 2075 | // Test vrintz |
| 2076 | __ vldr(s6, r4, offsetof(T, input)); |
| 2077 | __ vrintz(s5, s6); |
| 2078 | __ vstr(s5, r4, offsetof(T, zr)); |
| 2079 | |
| 2080 | __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); |
| 2081 | |
| 2082 | CodeDesc desc; |
| 2083 | assm.GetCode(&desc); |
| 2084 | Handle<Code> code = isolate->factory()->NewCode( |
| 2085 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 2086 | #ifdef DEBUG |
| 2087 | OFStream os(stdout); |
| 2088 | code->Print(os); |
| 2089 | #endif |
| 2090 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 2091 | |
| 2092 | Object* dummy = nullptr; |
| 2093 | USE(dummy); |
| 2094 | |
| 2095 | #define CHECK_VRINT(input_val, ares, nres, mres, pres, zres) \ |
| 2096 | t.input = input_val; \ |
| 2097 | dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); \ |
| 2098 | CHECK_EQ(ares, t.ar); \ |
| 2099 | CHECK_EQ(nres, t.nr); \ |
| 2100 | CHECK_EQ(mres, t.mr); \ |
| 2101 | CHECK_EQ(pres, t.pr); \ |
| 2102 | CHECK_EQ(zres, t.zr); |
| 2103 | |
| 2104 | CHECK_VRINT(-0.5, -1.0, -0.0, -1.0, -0.0, -0.0) |
| 2105 | CHECK_VRINT(-0.6, -1.0, -1.0, -1.0, -0.0, -0.0) |
| 2106 | CHECK_VRINT(-1.1, -1.0, -1.0, -2.0, -1.0, -1.0) |
| 2107 | CHECK_VRINT(0.5, 1.0, 0.0, 0.0, 1.0, 0.0) |
| 2108 | CHECK_VRINT(0.6, 1.0, 1.0, 0.0, 1.0, 0.0) |
| 2109 | CHECK_VRINT(1.1, 1.0, 1.0, 1.0, 2.0, 1.0) |
| 2110 | float inf = std::numeric_limits<float>::infinity(); |
| 2111 | CHECK_VRINT(inf, inf, inf, inf, inf, inf) |
| 2112 | CHECK_VRINT(-inf, -inf, -inf, -inf, -inf, -inf) |
| 2113 | CHECK_VRINT(-0.0, -0.0, -0.0, -0.0, -0.0, -0.0) |
| 2114 | |
| 2115 | // Check NaN propagation. |
| 2116 | float nan = std::numeric_limits<float>::quiet_NaN(); |
| 2117 | t.input = nan; |
| 2118 | dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); |
| 2119 | CHECK_EQ(bit_cast<int32_t>(nan), bit_cast<int32_t>(t.ar)); |
| 2120 | CHECK_EQ(bit_cast<int32_t>(nan), bit_cast<int32_t>(t.nr)); |
| 2121 | CHECK_EQ(bit_cast<int32_t>(nan), bit_cast<int32_t>(t.mr)); |
| 2122 | CHECK_EQ(bit_cast<int32_t>(nan), bit_cast<int32_t>(t.pr)); |
| 2123 | CHECK_EQ(bit_cast<int32_t>(nan), bit_cast<int32_t>(t.zr)); |
| 2124 | |
| 2125 | #undef CHECK_VRINT |
| 2126 | } |
| 2127 | } |
| 2128 | |
| 2129 | |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2130 | TEST(ARMv8_vrintX) { |
| 2131 | // Test the vrintX floating point instructions. |
| 2132 | CcTest::InitializeVM(); |
| 2133 | Isolate* isolate = CcTest::i_isolate(); |
| 2134 | HandleScope scope(isolate); |
| 2135 | |
| 2136 | typedef struct { |
| 2137 | double input; |
| 2138 | double ar; |
| 2139 | double nr; |
| 2140 | double mr; |
| 2141 | double pr; |
| 2142 | double zr; |
| 2143 | } T; |
| 2144 | T t; |
| 2145 | |
| 2146 | // Create a function that accepts &t, and loads, manipulates, and stores |
| 2147 | // the doubles and floats. |
| 2148 | Assembler assm(isolate, NULL, 0); |
| 2149 | Label L, C; |
| 2150 | |
| 2151 | |
| 2152 | if (CpuFeatures::IsSupported(ARMv8)) { |
| 2153 | CpuFeatureScope scope(&assm, ARMv8); |
| 2154 | |
| 2155 | __ mov(ip, Operand(sp)); |
| 2156 | __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); |
| 2157 | |
| 2158 | __ mov(r4, Operand(r0)); |
| 2159 | |
| 2160 | // Test vrinta |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2161 | __ vldr(d6, r4, offsetof(T, input)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2162 | __ vrinta(d5, d6); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2163 | __ vstr(d5, r4, offsetof(T, ar)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2164 | |
| 2165 | // Test vrintn |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2166 | __ vldr(d6, r4, offsetof(T, input)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2167 | __ vrintn(d5, d6); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2168 | __ vstr(d5, r4, offsetof(T, nr)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2169 | |
| 2170 | // Test vrintp |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2171 | __ vldr(d6, r4, offsetof(T, input)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2172 | __ vrintp(d5, d6); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2173 | __ vstr(d5, r4, offsetof(T, pr)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2174 | |
| 2175 | // Test vrintm |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2176 | __ vldr(d6, r4, offsetof(T, input)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2177 | __ vrintm(d5, d6); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2178 | __ vstr(d5, r4, offsetof(T, mr)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2179 | |
| 2180 | // Test vrintz |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2181 | __ vldr(d6, r4, offsetof(T, input)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2182 | __ vrintz(d5, d6); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2183 | __ vstr(d5, r4, offsetof(T, zr)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2184 | |
| 2185 | __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); |
| 2186 | |
| 2187 | CodeDesc desc; |
| 2188 | assm.GetCode(&desc); |
| 2189 | Handle<Code> code = isolate->factory()->NewCode( |
| 2190 | desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 2191 | #ifdef DEBUG |
| 2192 | OFStream os(stdout); |
| 2193 | code->Print(os); |
| 2194 | #endif |
| 2195 | F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 2196 | |
| 2197 | Object* dummy = nullptr; |
| 2198 | USE(dummy); |
| 2199 | |
| 2200 | #define CHECK_VRINT(input_val, ares, nres, mres, pres, zres) \ |
| 2201 | t.input = input_val; \ |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2202 | dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); \ |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2203 | CHECK_EQ(ares, t.ar); \ |
| 2204 | CHECK_EQ(nres, t.nr); \ |
| 2205 | CHECK_EQ(mres, t.mr); \ |
| 2206 | CHECK_EQ(pres, t.pr); \ |
| 2207 | CHECK_EQ(zres, t.zr); |
| 2208 | |
| 2209 | CHECK_VRINT(-0.5, -1.0, -0.0, -1.0, -0.0, -0.0) |
| 2210 | CHECK_VRINT(-0.6, -1.0, -1.0, -1.0, -0.0, -0.0) |
| 2211 | CHECK_VRINT(-1.1, -1.0, -1.0, -2.0, -1.0, -1.0) |
| 2212 | CHECK_VRINT(0.5, 1.0, 0.0, 0.0, 1.0, 0.0) |
| 2213 | CHECK_VRINT(0.6, 1.0, 1.0, 0.0, 1.0, 0.0) |
| 2214 | CHECK_VRINT(1.1, 1.0, 1.0, 1.0, 2.0, 1.0) |
| 2215 | double inf = std::numeric_limits<double>::infinity(); |
| 2216 | CHECK_VRINT(inf, inf, inf, inf, inf, inf) |
| 2217 | CHECK_VRINT(-inf, -inf, -inf, -inf, -inf, -inf) |
| 2218 | CHECK_VRINT(-0.0, -0.0, -0.0, -0.0, -0.0, -0.0) |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2219 | |
| 2220 | // Check NaN propagation. |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2221 | double nan = std::numeric_limits<double>::quiet_NaN(); |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2222 | t.input = nan; |
| 2223 | dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); |
| 2224 | CHECK_EQ(bit_cast<int64_t>(nan), bit_cast<int64_t>(t.ar)); |
| 2225 | CHECK_EQ(bit_cast<int64_t>(nan), bit_cast<int64_t>(t.nr)); |
| 2226 | CHECK_EQ(bit_cast<int64_t>(nan), bit_cast<int64_t>(t.mr)); |
| 2227 | CHECK_EQ(bit_cast<int64_t>(nan), bit_cast<int64_t>(t.pr)); |
| 2228 | CHECK_EQ(bit_cast<int64_t>(nan), bit_cast<int64_t>(t.zr)); |
Emily Bernier | d0a1eb7 | 2015-03-24 16:35:39 -0400 | [diff] [blame] | 2229 | |
| 2230 | #undef CHECK_VRINT |
| 2231 | } |
| 2232 | } |
Ben Murdoch | 4a90d5f | 2016-03-22 12:00:34 +0000 | [diff] [blame] | 2233 | |
| 2234 | |
| 2235 | TEST(regress4292_b) { |
| 2236 | CcTest::InitializeVM(); |
| 2237 | Isolate* isolate = CcTest::i_isolate(); |
| 2238 | HandleScope scope(isolate); |
| 2239 | |
| 2240 | Assembler assm(isolate, NULL, 0); |
| 2241 | Label end; |
| 2242 | __ mov(r0, Operand(isolate->factory()->infinity_value())); |
| 2243 | for (int i = 0; i < 1020; ++i) { |
| 2244 | __ b(hi, &end); |
| 2245 | } |
| 2246 | __ bind(&end); |
| 2247 | } |
| 2248 | |
| 2249 | |
| 2250 | TEST(regress4292_bl) { |
| 2251 | CcTest::InitializeVM(); |
| 2252 | Isolate* isolate = CcTest::i_isolate(); |
| 2253 | HandleScope scope(isolate); |
| 2254 | |
| 2255 | Assembler assm(isolate, NULL, 0); |
| 2256 | Label end; |
| 2257 | __ mov(r0, Operand(isolate->factory()->infinity_value())); |
| 2258 | for (int i = 0; i < 1020; ++i) { |
| 2259 | __ bl(hi, &end); |
| 2260 | } |
| 2261 | __ bind(&end); |
| 2262 | } |
| 2263 | |
| 2264 | |
| 2265 | TEST(regress4292_blx) { |
| 2266 | CcTest::InitializeVM(); |
| 2267 | Isolate* isolate = CcTest::i_isolate(); |
| 2268 | HandleScope scope(isolate); |
| 2269 | |
| 2270 | Assembler assm(isolate, NULL, 0); |
| 2271 | Label end; |
| 2272 | __ mov(r0, Operand(isolate->factory()->infinity_value())); |
| 2273 | for (int i = 0; i < 1020; ++i) { |
| 2274 | __ blx(&end); |
| 2275 | } |
| 2276 | __ bind(&end); |
| 2277 | } |
| 2278 | |
| 2279 | |
| 2280 | TEST(regress4292_CheckConstPool) { |
| 2281 | CcTest::InitializeVM(); |
| 2282 | Isolate* isolate = CcTest::i_isolate(); |
| 2283 | HandleScope scope(isolate); |
| 2284 | |
| 2285 | Assembler assm(isolate, NULL, 0); |
| 2286 | __ mov(r0, Operand(isolate->factory()->infinity_value())); |
| 2287 | __ BlockConstPoolFor(1019); |
| 2288 | for (int i = 0; i < 1019; ++i) __ nop(); |
| 2289 | __ vldr(d0, MemOperand(r0, 0)); |
| 2290 | } |
| 2291 | |
Steve Block | a7e24c1 | 2009-10-30 11:49:00 +0000 | [diff] [blame] | 2292 | #undef __ |