1 // Copyright 2012 the V8 project authors. All rights reserved. 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 28 #include "src/v8.h" 29 #include "test/cctest/cctest.h" 30 31 #include "src/arm/assembler-arm-inl.h" 32 #include "src/arm/simulator-arm.h" 33 #include "src/disassembler.h" 34 #include "src/factory.h" 35 #include "src/ostreams.h" 36 37 using namespace v8::internal; 38 39 40 // Define these function prototypes to match JSEntryFunction in execution.cc. 41 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4); 42 typedef Object* (*F2)(int x, int y, int p2, int p3, int p4); 43 typedef Object* (*F3)(void* p0, int p1, int p2, int p3, int p4); 44 typedef Object* (*F4)(void* p0, void* p1, int p2, int p3, int p4); 45 46 47 #define __ assm. 48 49 TEST(0) { 50 CcTest::InitializeVM(); 51 Isolate* isolate = CcTest::i_isolate(); 52 HandleScope scope(isolate); 53 54 Assembler assm(isolate, NULL, 0); 55 56 __ add(r0, r0, Operand(r1)); 57 __ mov(pc, Operand(lr)); 58 59 CodeDesc desc; 60 assm.GetCode(&desc); 61 Handle<Code> code = isolate->factory()->NewCode( 62 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 63 #ifdef DEBUG 64 OFStream os(stdout); 65 code->Print(os); 66 #endif 67 F2 f = FUNCTION_CAST<F2>(code->entry()); 68 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 3, 4, 0, 0, 0)); 69 ::printf("f() = %d\n", res); 70 CHECK_EQ(7, res); 71 } 72 73 74 TEST(1) { 75 CcTest::InitializeVM(); 76 Isolate* isolate = CcTest::i_isolate(); 77 HandleScope scope(isolate); 78 79 Assembler assm(isolate, NULL, 0); 80 Label L, C; 81 82 __ mov(r1, Operand(r0)); 83 __ mov(r0, Operand::Zero()); 84 __ b(&C); 85 86 __ bind(&L); 87 __ add(r0, r0, Operand(r1)); 88 __ sub(r1, r1, Operand(1)); 89 90 __ bind(&C); 91 __ teq(r1, Operand::Zero()); 92 __ b(ne, &L); 93 __ mov(pc, Operand(lr)); 94 95 CodeDesc desc; 96 assm.GetCode(&desc); 97 Handle<Code> code = isolate->factory()->NewCode( 98 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 99 #ifdef DEBUG 100 OFStream os(stdout); 101 code->Print(os); 102 #endif 103 F1 f = FUNCTION_CAST<F1>(code->entry()); 104 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 100, 0, 0, 0, 0)); 105 ::printf("f() = %d\n", res); 106 CHECK_EQ(5050, res); 107 } 108 109 110 TEST(2) { 111 CcTest::InitializeVM(); 112 Isolate* isolate = CcTest::i_isolate(); 113 HandleScope scope(isolate); 114 115 Assembler assm(isolate, NULL, 0); 116 Label L, C; 117 118 __ mov(r1, Operand(r0)); 119 __ mov(r0, Operand(1)); 120 __ b(&C); 121 122 __ bind(&L); 123 __ mul(r0, r1, r0); 124 __ sub(r1, r1, Operand(1)); 125 126 __ bind(&C); 127 __ teq(r1, Operand::Zero()); 128 __ b(ne, &L); 129 __ mov(pc, Operand(lr)); 130 131 // some relocated stuff here, not executed 132 __ RecordComment("dead code, just testing relocations"); 133 __ mov(r0, Operand(isolate->factory()->true_value())); 134 __ RecordComment("dead code, just testing immediate operands"); 135 __ mov(r0, Operand(-1)); 136 __ mov(r0, Operand(0xFF000000)); 137 __ mov(r0, Operand(0xF0F0F0F0)); 138 __ mov(r0, Operand(0xFFF0FFFF)); 139 140 CodeDesc desc; 141 assm.GetCode(&desc); 142 Handle<Code> code = isolate->factory()->NewCode( 143 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 144 #ifdef DEBUG 145 OFStream os(stdout); 146 code->Print(os); 147 #endif 148 F1 f = FUNCTION_CAST<F1>(code->entry()); 149 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 10, 0, 0, 0, 0)); 150 ::printf("f() = %d\n", res); 151 CHECK_EQ(3628800, res); 152 } 153 154 155 TEST(3) { 156 CcTest::InitializeVM(); 157 Isolate* isolate = CcTest::i_isolate(); 158 HandleScope scope(isolate); 159 160 typedef struct { 161 int i; 162 char c; 163 int16_t s; 164 } T; 165 T t; 166 167 Assembler assm(isolate, NULL, 0); 168 Label L, C; 169 170 __ mov(ip, Operand(sp)); 171 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); 172 __ sub(fp, ip, Operand(4)); 173 __ mov(r4, Operand(r0)); 174 __ ldr(r0, MemOperand(r4, OFFSET_OF(T, i))); 175 __ mov(r2, Operand(r0, ASR, 1)); 176 __ str(r2, MemOperand(r4, OFFSET_OF(T, i))); 177 __ ldrsb(r2, MemOperand(r4, OFFSET_OF(T, c))); 178 __ add(r0, r2, Operand(r0)); 179 __ mov(r2, Operand(r2, LSL, 2)); 180 __ strb(r2, MemOperand(r4, OFFSET_OF(T, c))); 181 __ ldrsh(r2, MemOperand(r4, OFFSET_OF(T, s))); 182 __ add(r0, r2, Operand(r0)); 183 __ mov(r2, Operand(r2, ASR, 3)); 184 __ strh(r2, MemOperand(r4, OFFSET_OF(T, s))); 185 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); 186 187 CodeDesc desc; 188 assm.GetCode(&desc); 189 Handle<Code> code = isolate->factory()->NewCode( 190 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 191 #ifdef DEBUG 192 OFStream os(stdout); 193 code->Print(os); 194 #endif 195 F3 f = FUNCTION_CAST<F3>(code->entry()); 196 t.i = 100000; 197 t.c = 10; 198 t.s = 1000; 199 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0)); 200 ::printf("f() = %d\n", res); 201 CHECK_EQ(101010, res); 202 CHECK_EQ(100000/2, t.i); 203 CHECK_EQ(10*4, t.c); 204 CHECK_EQ(1000/8, t.s); 205 } 206 207 208 TEST(4) { 209 // Test the VFP floating point instructions. 210 CcTest::InitializeVM(); 211 Isolate* isolate = CcTest::i_isolate(); 212 HandleScope scope(isolate); 213 214 typedef struct { 215 double a; 216 double b; 217 double c; 218 double d; 219 double e; 220 double f; 221 double g; 222 double h; 223 int i; 224 double j; 225 double m; 226 double n; 227 float x; 228 float y; 229 } T; 230 T t; 231 232 // Create a function that accepts &t, and loads, manipulates, and stores 233 // the doubles and floats. 234 Assembler assm(isolate, NULL, 0); 235 Label L, C; 236 237 238 if (CpuFeatures::IsSupported(VFP3)) { 239 CpuFeatureScope scope(&assm, VFP3); 240 241 __ mov(ip, Operand(sp)); 242 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); 243 __ sub(fp, ip, Operand(4)); 244 245 __ mov(r4, Operand(r0)); 246 __ vldr(d6, r4, OFFSET_OF(T, a)); 247 __ vldr(d7, r4, OFFSET_OF(T, b)); 248 __ vadd(d5, d6, d7); 249 __ vstr(d5, r4, OFFSET_OF(T, c)); 250 251 __ vmla(d5, d6, d7); 252 __ vmls(d5, d5, d6); 253 254 __ vmov(r2, r3, d5); 255 __ vmov(d4, r2, r3); 256 __ vstr(d4, r4, OFFSET_OF(T, b)); 257 258 // Load t.x and t.y, switch values, and store back to the struct. 259 __ vldr(s0, r4, OFFSET_OF(T, x)); 260 __ vldr(s31, r4, OFFSET_OF(T, y)); 261 __ vmov(s16, s0); 262 __ vmov(s0, s31); 263 __ vmov(s31, s16); 264 __ vstr(s0, r4, OFFSET_OF(T, x)); 265 __ vstr(s31, r4, OFFSET_OF(T, y)); 266 267 // Move a literal into a register that can be encoded in the instruction. 268 __ vmov(d4, 1.0); 269 __ vstr(d4, r4, OFFSET_OF(T, e)); 270 271 // Move a literal into a register that requires 64 bits to encode. 272 // 0x3ff0000010000000 = 1.000000059604644775390625 273 __ vmov(d4, 1.000000059604644775390625); 274 __ vstr(d4, r4, OFFSET_OF(T, d)); 275 276 // Convert from floating point to integer. 277 __ vmov(d4, 2.0); 278 __ vcvt_s32_f64(s31, d4); 279 __ vstr(s31, r4, OFFSET_OF(T, i)); 280 281 // Convert from integer to floating point. 282 __ mov(lr, Operand(42)); 283 __ vmov(s31, lr); 284 __ vcvt_f64_s32(d4, s31); 285 __ vstr(d4, r4, OFFSET_OF(T, f)); 286 287 // Convert from fixed point to floating point. 288 __ mov(lr, Operand(2468)); 289 __ vmov(s8, lr); 290 __ vcvt_f64_s32(d4, 2); 291 __ vstr(d4, r4, OFFSET_OF(T, j)); 292 293 // Test vabs. 294 __ vldr(d1, r4, OFFSET_OF(T, g)); 295 __ vabs(d0, d1); 296 __ vstr(d0, r4, OFFSET_OF(T, g)); 297 __ vldr(d2, r4, OFFSET_OF(T, h)); 298 __ vabs(d0, d2); 299 __ vstr(d0, r4, OFFSET_OF(T, h)); 300 301 // Test vneg. 302 __ vldr(d1, r4, OFFSET_OF(T, m)); 303 __ vneg(d0, d1); 304 __ vstr(d0, r4, OFFSET_OF(T, m)); 305 __ vldr(d1, r4, OFFSET_OF(T, n)); 306 __ vneg(d0, d1); 307 __ vstr(d0, r4, OFFSET_OF(T, n)); 308 309 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); 310 311 CodeDesc desc; 312 assm.GetCode(&desc); 313 Handle<Code> code = isolate->factory()->NewCode( 314 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 315 #ifdef DEBUG 316 OFStream os(stdout); 317 code->Print(os); 318 #endif 319 F3 f = FUNCTION_CAST<F3>(code->entry()); 320 t.a = 1.5; 321 t.b = 2.75; 322 t.c = 17.17; 323 t.d = 0.0; 324 t.e = 0.0; 325 t.f = 0.0; 326 t.g = -2718.2818; 327 t.h = 31415926.5; 328 t.i = 0; 329 t.j = 0; 330 t.m = -2718.2818; 331 t.n = 123.456; 332 t.x = 4.5; 333 t.y = 9.0; 334 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); 335 USE(dummy); 336 CHECK_EQ(4.5, t.y); 337 CHECK_EQ(9.0, t.x); 338 CHECK_EQ(-123.456, t.n); 339 CHECK_EQ(2718.2818, t.m); 340 CHECK_EQ(2, t.i); 341 CHECK_EQ(2718.2818, t.g); 342 CHECK_EQ(31415926.5, t.h); 343 CHECK_EQ(617.0, t.j); 344 CHECK_EQ(42.0, t.f); 345 CHECK_EQ(1.0, t.e); 346 CHECK_EQ(1.000000059604644775390625, t.d); 347 CHECK_EQ(4.25, t.c); 348 CHECK_EQ(-4.1875, t.b); 349 CHECK_EQ(1.5, t.a); 350 } 351 } 352 353 354 TEST(5) { 355 // Test the ARMv7 bitfield instructions. 356 CcTest::InitializeVM(); 357 Isolate* isolate = CcTest::i_isolate(); 358 HandleScope scope(isolate); 359 360 Assembler assm(isolate, NULL, 0); 361 362 if (CpuFeatures::IsSupported(ARMv7)) { 363 CpuFeatureScope scope(&assm, ARMv7); 364 // On entry, r0 = 0xAAAAAAAA = 0b10..10101010. 365 __ ubfx(r0, r0, 1, 12); // 0b00..010101010101 = 0x555 366 __ sbfx(r0, r0, 0, 5); // 0b11..111111110101 = -11 367 __ bfc(r0, 1, 3); // 0b11..111111110001 = -15 368 __ mov(r1, Operand(7)); 369 __ bfi(r0, r1, 3, 3); // 0b11..111111111001 = -7 370 __ mov(pc, Operand(lr)); 371 372 CodeDesc desc; 373 assm.GetCode(&desc); 374 Handle<Code> code = isolate->factory()->NewCode( 375 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 376 #ifdef DEBUG 377 OFStream os(stdout); 378 code->Print(os); 379 #endif 380 F1 f = FUNCTION_CAST<F1>(code->entry()); 381 int res = reinterpret_cast<int>( 382 CALL_GENERATED_CODE(f, 0xAAAAAAAA, 0, 0, 0, 0)); 383 ::printf("f() = %d\n", res); 384 CHECK_EQ(-7, res); 385 } 386 } 387 388 389 TEST(6) { 390 // Test saturating instructions. 391 CcTest::InitializeVM(); 392 Isolate* isolate = CcTest::i_isolate(); 393 HandleScope scope(isolate); 394 395 Assembler assm(isolate, NULL, 0); 396 397 if (CpuFeatures::IsSupported(ARMv7)) { 398 CpuFeatureScope scope(&assm, ARMv7); 399 __ usat(r1, 8, Operand(r0)); // Sat 0xFFFF to 0-255 = 0xFF. 400 __ usat(r2, 12, Operand(r0, ASR, 9)); // Sat (0xFFFF>>9) to 0-4095 = 0x7F. 401 __ usat(r3, 1, Operand(r0, LSL, 16)); // Sat (0xFFFF<<16) to 0-1 = 0x0. 402 __ add(r0, r1, Operand(r2)); 403 __ add(r0, r0, Operand(r3)); 404 __ mov(pc, Operand(lr)); 405 406 CodeDesc desc; 407 assm.GetCode(&desc); 408 Handle<Code> code = isolate->factory()->NewCode( 409 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 410 #ifdef DEBUG 411 OFStream os(stdout); 412 code->Print(os); 413 #endif 414 F1 f = FUNCTION_CAST<F1>(code->entry()); 415 int res = reinterpret_cast<int>( 416 CALL_GENERATED_CODE(f, 0xFFFF, 0, 0, 0, 0)); 417 ::printf("f() = %d\n", res); 418 CHECK_EQ(382, res); 419 } 420 } 421 422 423 enum VCVTTypes { 424 s32_f64, 425 u32_f64 426 }; 427 428 static void TestRoundingMode(VCVTTypes types, 429 VFPRoundingMode mode, 430 double value, 431 int expected, 432 bool expected_exception = false) { 433 Isolate* isolate = CcTest::i_isolate(); 434 HandleScope scope(isolate); 435 436 Assembler assm(isolate, NULL, 0); 437 438 if (CpuFeatures::IsSupported(VFP3)) { 439 CpuFeatureScope scope(&assm, VFP3); 440 441 Label wrong_exception; 442 443 __ vmrs(r1); 444 // Set custom FPSCR. 445 __ bic(r2, r1, Operand(kVFPRoundingModeMask | kVFPExceptionMask)); 446 __ orr(r2, r2, Operand(mode)); 447 __ vmsr(r2); 448 449 // Load value, convert, and move back result to r0 if everything went well. 450 __ vmov(d1, value); 451 switch (types) { 452 case s32_f64: 453 __ vcvt_s32_f64(s0, d1, kFPSCRRounding); 454 break; 455 456 case u32_f64: 457 __ vcvt_u32_f64(s0, d1, kFPSCRRounding); 458 break; 459 460 default: 461 UNREACHABLE(); 462 break; 463 } 464 // Check for vfp exceptions 465 __ vmrs(r2); 466 __ tst(r2, Operand(kVFPExceptionMask)); 467 // Check that we behaved as expected. 468 __ b(&wrong_exception, 469 expected_exception ? eq : ne); 470 // There was no exception. Retrieve the result and return. 471 __ vmov(r0, s0); 472 __ mov(pc, Operand(lr)); 473 474 // The exception behaviour is not what we expected. 475 // Load a special value and return. 476 __ bind(&wrong_exception); 477 __ mov(r0, Operand(11223344)); 478 __ mov(pc, Operand(lr)); 479 480 CodeDesc desc; 481 assm.GetCode(&desc); 482 Handle<Code> code = isolate->factory()->NewCode( 483 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 484 #ifdef DEBUG 485 OFStream os(stdout); 486 code->Print(os); 487 #endif 488 F1 f = FUNCTION_CAST<F1>(code->entry()); 489 int res = reinterpret_cast<int>( 490 CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); 491 ::printf("res = %d\n", res); 492 CHECK_EQ(expected, res); 493 } 494 } 495 496 497 TEST(7) { 498 CcTest::InitializeVM(); 499 // Test vfp rounding modes. 500 501 // s32_f64 (double to integer). 502 503 TestRoundingMode(s32_f64, RN, 0, 0); 504 TestRoundingMode(s32_f64, RN, 0.5, 0); 505 TestRoundingMode(s32_f64, RN, -0.5, 0); 506 TestRoundingMode(s32_f64, RN, 1.5, 2); 507 TestRoundingMode(s32_f64, RN, -1.5, -2); 508 TestRoundingMode(s32_f64, RN, 123.7, 124); 509 TestRoundingMode(s32_f64, RN, -123.7, -124); 510 TestRoundingMode(s32_f64, RN, 123456.2, 123456); 511 TestRoundingMode(s32_f64, RN, -123456.2, -123456); 512 TestRoundingMode(s32_f64, RN, static_cast<double>(kMaxInt), kMaxInt); 513 TestRoundingMode(s32_f64, RN, (kMaxInt + 0.49), kMaxInt); 514 TestRoundingMode(s32_f64, RN, (kMaxInt + 1.0), kMaxInt, true); 515 TestRoundingMode(s32_f64, RN, (kMaxInt + 0.5), kMaxInt, true); 516 TestRoundingMode(s32_f64, RN, static_cast<double>(kMinInt), kMinInt); 517 TestRoundingMode(s32_f64, RN, (kMinInt - 0.5), kMinInt); 518 TestRoundingMode(s32_f64, RN, (kMinInt - 1.0), kMinInt, true); 519 TestRoundingMode(s32_f64, RN, (kMinInt - 0.51), kMinInt, true); 520 521 TestRoundingMode(s32_f64, RM, 0, 0); 522 TestRoundingMode(s32_f64, RM, 0.5, 0); 523 TestRoundingMode(s32_f64, RM, -0.5, -1); 524 TestRoundingMode(s32_f64, RM, 123.7, 123); 525 TestRoundingMode(s32_f64, RM, -123.7, -124); 526 TestRoundingMode(s32_f64, RM, 123456.2, 123456); 527 TestRoundingMode(s32_f64, RM, -123456.2, -123457); 528 TestRoundingMode(s32_f64, RM, static_cast<double>(kMaxInt), kMaxInt); 529 TestRoundingMode(s32_f64, RM, (kMaxInt + 0.5), kMaxInt); 530 TestRoundingMode(s32_f64, RM, (kMaxInt + 1.0), kMaxInt, true); 531 TestRoundingMode(s32_f64, RM, static_cast<double>(kMinInt), kMinInt); 532 TestRoundingMode(s32_f64, RM, (kMinInt - 0.5), kMinInt, true); 533 TestRoundingMode(s32_f64, RM, (kMinInt + 0.5), kMinInt); 534 535 TestRoundingMode(s32_f64, RZ, 0, 0); 536 TestRoundingMode(s32_f64, RZ, 0.5, 0); 537 TestRoundingMode(s32_f64, RZ, -0.5, 0); 538 TestRoundingMode(s32_f64, RZ, 123.7, 123); 539 TestRoundingMode(s32_f64, RZ, -123.7, -123); 540 TestRoundingMode(s32_f64, RZ, 123456.2, 123456); 541 TestRoundingMode(s32_f64, RZ, -123456.2, -123456); 542 TestRoundingMode(s32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt); 543 TestRoundingMode(s32_f64, RZ, (kMaxInt + 0.5), kMaxInt); 544 TestRoundingMode(s32_f64, RZ, (kMaxInt + 1.0), kMaxInt, true); 545 TestRoundingMode(s32_f64, RZ, static_cast<double>(kMinInt), kMinInt); 546 TestRoundingMode(s32_f64, RZ, (kMinInt - 0.5), kMinInt); 547 TestRoundingMode(s32_f64, RZ, (kMinInt - 1.0), kMinInt, true); 548 549 550 // u32_f64 (double to integer). 551 552 // Negative values. 553 TestRoundingMode(u32_f64, RN, -0.5, 0); 554 TestRoundingMode(u32_f64, RN, -123456.7, 0, true); 555 TestRoundingMode(u32_f64, RN, static_cast<double>(kMinInt), 0, true); 556 TestRoundingMode(u32_f64, RN, kMinInt - 1.0, 0, true); 557 558 TestRoundingMode(u32_f64, RM, -0.5, 0, true); 559 TestRoundingMode(u32_f64, RM, -123456.7, 0, true); 560 TestRoundingMode(u32_f64, RM, static_cast<double>(kMinInt), 0, true); 561 TestRoundingMode(u32_f64, RM, kMinInt - 1.0, 0, true); 562 563 TestRoundingMode(u32_f64, RZ, -0.5, 0); 564 TestRoundingMode(u32_f64, RZ, -123456.7, 0, true); 565 TestRoundingMode(u32_f64, RZ, static_cast<double>(kMinInt), 0, true); 566 TestRoundingMode(u32_f64, RZ, kMinInt - 1.0, 0, true); 567 568 // Positive values. 569 // kMaxInt is the maximum *signed* integer: 0x7fffffff. 570 static const uint32_t kMaxUInt = 0xffffffffu; 571 TestRoundingMode(u32_f64, RZ, 0, 0); 572 TestRoundingMode(u32_f64, RZ, 0.5, 0); 573 TestRoundingMode(u32_f64, RZ, 123.7, 123); 574 TestRoundingMode(u32_f64, RZ, 123456.2, 123456); 575 TestRoundingMode(u32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt); 576 TestRoundingMode(u32_f64, RZ, (kMaxInt + 0.5), kMaxInt); 577 TestRoundingMode(u32_f64, RZ, (kMaxInt + 1.0), 578 static_cast<uint32_t>(kMaxInt) + 1); 579 TestRoundingMode(u32_f64, RZ, (kMaxUInt + 0.5), kMaxUInt); 580 TestRoundingMode(u32_f64, RZ, (kMaxUInt + 1.0), kMaxUInt, true); 581 582 TestRoundingMode(u32_f64, RM, 0, 0); 583 TestRoundingMode(u32_f64, RM, 0.5, 0); 584 TestRoundingMode(u32_f64, RM, 123.7, 123); 585 TestRoundingMode(u32_f64, RM, 123456.2, 123456); 586 TestRoundingMode(u32_f64, RM, static_cast<double>(kMaxInt), kMaxInt); 587 TestRoundingMode(u32_f64, RM, (kMaxInt + 0.5), kMaxInt); 588 TestRoundingMode(u32_f64, RM, (kMaxInt + 1.0), 589 static_cast<uint32_t>(kMaxInt) + 1); 590 TestRoundingMode(u32_f64, RM, (kMaxUInt + 0.5), kMaxUInt); 591 TestRoundingMode(u32_f64, RM, (kMaxUInt + 1.0), kMaxUInt, true); 592 593 TestRoundingMode(u32_f64, RN, 0, 0); 594 TestRoundingMode(u32_f64, RN, 0.5, 0); 595 TestRoundingMode(u32_f64, RN, 1.5, 2); 596 TestRoundingMode(u32_f64, RN, 123.7, 124); 597 TestRoundingMode(u32_f64, RN, 123456.2, 123456); 598 TestRoundingMode(u32_f64, RN, static_cast<double>(kMaxInt), kMaxInt); 599 TestRoundingMode(u32_f64, RN, (kMaxInt + 0.49), kMaxInt); 600 TestRoundingMode(u32_f64, RN, (kMaxInt + 0.5), 601 static_cast<uint32_t>(kMaxInt) + 1); 602 TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.49), kMaxUInt); 603 TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.5), kMaxUInt, true); 604 TestRoundingMode(u32_f64, RN, (kMaxUInt + 1.0), kMaxUInt, true); 605 } 606 607 608 TEST(8) { 609 // Test VFP multi load/store with ia_w. 610 CcTest::InitializeVM(); 611 Isolate* isolate = CcTest::i_isolate(); 612 HandleScope scope(isolate); 613 614 typedef struct { 615 double a; 616 double b; 617 double c; 618 double d; 619 double e; 620 double f; 621 double g; 622 double h; 623 } D; 624 D d; 625 626 typedef struct { 627 float a; 628 float b; 629 float c; 630 float d; 631 float e; 632 float f; 633 float g; 634 float h; 635 } F; 636 F f; 637 638 // Create a function that uses vldm/vstm to move some double and 639 // single precision values around in memory. 640 Assembler assm(isolate, NULL, 0); 641 642 __ mov(ip, Operand(sp)); 643 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); 644 __ sub(fp, ip, Operand(4)); 645 646 __ add(r4, r0, Operand(OFFSET_OF(D, a))); 647 __ vldm(ia_w, r4, d0, d3); 648 __ vldm(ia_w, r4, d4, d7); 649 650 __ add(r4, r0, Operand(OFFSET_OF(D, a))); 651 __ vstm(ia_w, r4, d6, d7); 652 __ vstm(ia_w, r4, d0, d5); 653 654 __ add(r4, r1, Operand(OFFSET_OF(F, a))); 655 __ vldm(ia_w, r4, s0, s3); 656 __ vldm(ia_w, r4, s4, s7); 657 658 __ add(r4, r1, Operand(OFFSET_OF(F, a))); 659 __ vstm(ia_w, r4, s6, s7); 660 __ vstm(ia_w, r4, s0, s5); 661 662 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); 663 664 CodeDesc desc; 665 assm.GetCode(&desc); 666 Handle<Code> code = isolate->factory()->NewCode( 667 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 668 #ifdef DEBUG 669 OFStream os(stdout); 670 code->Print(os); 671 #endif 672 F4 fn = FUNCTION_CAST<F4>(code->entry()); 673 d.a = 1.1; 674 d.b = 2.2; 675 d.c = 3.3; 676 d.d = 4.4; 677 d.e = 5.5; 678 d.f = 6.6; 679 d.g = 7.7; 680 d.h = 8.8; 681 682 f.a = 1.0; 683 f.b = 2.0; 684 f.c = 3.0; 685 f.d = 4.0; 686 f.e = 5.0; 687 f.f = 6.0; 688 f.g = 7.0; 689 f.h = 8.0; 690 691 Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0); 692 USE(dummy); 693 694 CHECK_EQ(7.7, d.a); 695 CHECK_EQ(8.8, d.b); 696 CHECK_EQ(1.1, d.c); 697 CHECK_EQ(2.2, d.d); 698 CHECK_EQ(3.3, d.e); 699 CHECK_EQ(4.4, d.f); 700 CHECK_EQ(5.5, d.g); 701 CHECK_EQ(6.6, d.h); 702 703 CHECK_EQ(7.0, f.a); 704 CHECK_EQ(8.0, f.b); 705 CHECK_EQ(1.0, f.c); 706 CHECK_EQ(2.0, f.d); 707 CHECK_EQ(3.0, f.e); 708 CHECK_EQ(4.0, f.f); 709 CHECK_EQ(5.0, f.g); 710 CHECK_EQ(6.0, f.h); 711 } 712 713 714 TEST(9) { 715 // Test VFP multi load/store with ia. 716 CcTest::InitializeVM(); 717 Isolate* isolate = CcTest::i_isolate(); 718 HandleScope scope(isolate); 719 720 typedef struct { 721 double a; 722 double b; 723 double c; 724 double d; 725 double e; 726 double f; 727 double g; 728 double h; 729 } D; 730 D d; 731 732 typedef struct { 733 float a; 734 float b; 735 float c; 736 float d; 737 float e; 738 float f; 739 float g; 740 float h; 741 } F; 742 F f; 743 744 // Create a function that uses vldm/vstm to move some double and 745 // single precision values around in memory. 746 Assembler assm(isolate, NULL, 0); 747 748 __ mov(ip, Operand(sp)); 749 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); 750 __ sub(fp, ip, Operand(4)); 751 752 __ add(r4, r0, Operand(OFFSET_OF(D, a))); 753 __ vldm(ia, r4, d0, d3); 754 __ add(r4, r4, Operand(4 * 8)); 755 __ vldm(ia, r4, d4, d7); 756 757 __ add(r4, r0, Operand(OFFSET_OF(D, a))); 758 __ vstm(ia, r4, d6, d7); 759 __ add(r4, r4, Operand(2 * 8)); 760 __ vstm(ia, r4, d0, d5); 761 762 __ add(r4, r1, Operand(OFFSET_OF(F, a))); 763 __ vldm(ia, r4, s0, s3); 764 __ add(r4, r4, Operand(4 * 4)); 765 __ vldm(ia, r4, s4, s7); 766 767 __ add(r4, r1, Operand(OFFSET_OF(F, a))); 768 __ vstm(ia, r4, s6, s7); 769 __ add(r4, r4, Operand(2 * 4)); 770 __ vstm(ia, r4, s0, s5); 771 772 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); 773 774 CodeDesc desc; 775 assm.GetCode(&desc); 776 Handle<Code> code = isolate->factory()->NewCode( 777 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 778 #ifdef DEBUG 779 OFStream os(stdout); 780 code->Print(os); 781 #endif 782 F4 fn = FUNCTION_CAST<F4>(code->entry()); 783 d.a = 1.1; 784 d.b = 2.2; 785 d.c = 3.3; 786 d.d = 4.4; 787 d.e = 5.5; 788 d.f = 6.6; 789 d.g = 7.7; 790 d.h = 8.8; 791 792 f.a = 1.0; 793 f.b = 2.0; 794 f.c = 3.0; 795 f.d = 4.0; 796 f.e = 5.0; 797 f.f = 6.0; 798 f.g = 7.0; 799 f.h = 8.0; 800 801 Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0); 802 USE(dummy); 803 804 CHECK_EQ(7.7, d.a); 805 CHECK_EQ(8.8, d.b); 806 CHECK_EQ(1.1, d.c); 807 CHECK_EQ(2.2, d.d); 808 CHECK_EQ(3.3, d.e); 809 CHECK_EQ(4.4, d.f); 810 CHECK_EQ(5.5, d.g); 811 CHECK_EQ(6.6, d.h); 812 813 CHECK_EQ(7.0, f.a); 814 CHECK_EQ(8.0, f.b); 815 CHECK_EQ(1.0, f.c); 816 CHECK_EQ(2.0, f.d); 817 CHECK_EQ(3.0, f.e); 818 CHECK_EQ(4.0, f.f); 819 CHECK_EQ(5.0, f.g); 820 CHECK_EQ(6.0, f.h); 821 } 822 823 824 TEST(10) { 825 // Test VFP multi load/store with db_w. 826 CcTest::InitializeVM(); 827 Isolate* isolate = CcTest::i_isolate(); 828 HandleScope scope(isolate); 829 830 typedef struct { 831 double a; 832 double b; 833 double c; 834 double d; 835 double e; 836 double f; 837 double g; 838 double h; 839 } D; 840 D d; 841 842 typedef struct { 843 float a; 844 float b; 845 float c; 846 float d; 847 float e; 848 float f; 849 float g; 850 float h; 851 } F; 852 F f; 853 854 // Create a function that uses vldm/vstm to move some double and 855 // single precision values around in memory. 856 Assembler assm(isolate, NULL, 0); 857 858 __ mov(ip, Operand(sp)); 859 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); 860 __ sub(fp, ip, Operand(4)); 861 862 __ add(r4, r0, Operand(OFFSET_OF(D, h) + 8)); 863 __ vldm(db_w, r4, d4, d7); 864 __ vldm(db_w, r4, d0, d3); 865 866 __ add(r4, r0, Operand(OFFSET_OF(D, h) + 8)); 867 __ vstm(db_w, r4, d0, d5); 868 __ vstm(db_w, r4, d6, d7); 869 870 __ add(r4, r1, Operand(OFFSET_OF(F, h) + 4)); 871 __ vldm(db_w, r4, s4, s7); 872 __ vldm(db_w, r4, s0, s3); 873 874 __ add(r4, r1, Operand(OFFSET_OF(F, h) + 4)); 875 __ vstm(db_w, r4, s0, s5); 876 __ vstm(db_w, r4, s6, s7); 877 878 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); 879 880 CodeDesc desc; 881 assm.GetCode(&desc); 882 Handle<Code> code = isolate->factory()->NewCode( 883 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 884 #ifdef DEBUG 885 OFStream os(stdout); 886 code->Print(os); 887 #endif 888 F4 fn = FUNCTION_CAST<F4>(code->entry()); 889 d.a = 1.1; 890 d.b = 2.2; 891 d.c = 3.3; 892 d.d = 4.4; 893 d.e = 5.5; 894 d.f = 6.6; 895 d.g = 7.7; 896 d.h = 8.8; 897 898 f.a = 1.0; 899 f.b = 2.0; 900 f.c = 3.0; 901 f.d = 4.0; 902 f.e = 5.0; 903 f.f = 6.0; 904 f.g = 7.0; 905 f.h = 8.0; 906 907 Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0); 908 USE(dummy); 909 910 CHECK_EQ(7.7, d.a); 911 CHECK_EQ(8.8, d.b); 912 CHECK_EQ(1.1, d.c); 913 CHECK_EQ(2.2, d.d); 914 CHECK_EQ(3.3, d.e); 915 CHECK_EQ(4.4, d.f); 916 CHECK_EQ(5.5, d.g); 917 CHECK_EQ(6.6, d.h); 918 919 CHECK_EQ(7.0, f.a); 920 CHECK_EQ(8.0, f.b); 921 CHECK_EQ(1.0, f.c); 922 CHECK_EQ(2.0, f.d); 923 CHECK_EQ(3.0, f.e); 924 CHECK_EQ(4.0, f.f); 925 CHECK_EQ(5.0, f.g); 926 CHECK_EQ(6.0, f.h); 927 } 928 929 930 TEST(11) { 931 // Test instructions using the carry flag. 932 CcTest::InitializeVM(); 933 Isolate* isolate = CcTest::i_isolate(); 934 HandleScope scope(isolate); 935 936 typedef struct { 937 int32_t a; 938 int32_t b; 939 int32_t c; 940 int32_t d; 941 } I; 942 I i; 943 944 i.a = 0xabcd0001; 945 i.b = 0xabcd0000; 946 947 Assembler assm(isolate, NULL, 0); 948 949 // Test HeapObject untagging. 950 __ ldr(r1, MemOperand(r0, OFFSET_OF(I, a))); 951 __ mov(r1, Operand(r1, ASR, 1), SetCC); 952 __ adc(r1, r1, Operand(r1), LeaveCC, cs); 953 __ str(r1, MemOperand(r0, OFFSET_OF(I, a))); 954 955 __ ldr(r2, MemOperand(r0, OFFSET_OF(I, b))); 956 __ mov(r2, Operand(r2, ASR, 1), SetCC); 957 __ adc(r2, r2, Operand(r2), LeaveCC, cs); 958 __ str(r2, MemOperand(r0, OFFSET_OF(I, b))); 959 960 // Test corner cases. 961 __ mov(r1, Operand(0xffffffff)); 962 __ mov(r2, Operand::Zero()); 963 __ mov(r3, Operand(r1, ASR, 1), SetCC); // Set the carry. 964 __ adc(r3, r1, Operand(r2)); 965 __ str(r3, MemOperand(r0, OFFSET_OF(I, c))); 966 967 __ mov(r1, Operand(0xffffffff)); 968 __ mov(r2, Operand::Zero()); 969 __ mov(r3, Operand(r2, ASR, 1), SetCC); // Unset the carry. 970 __ adc(r3, r1, Operand(r2)); 971 __ str(r3, MemOperand(r0, OFFSET_OF(I, d))); 972 973 __ mov(pc, Operand(lr)); 974 975 CodeDesc desc; 976 assm.GetCode(&desc); 977 Handle<Code> code = isolate->factory()->NewCode( 978 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 979 #ifdef DEBUG 980 OFStream os(stdout); 981 code->Print(os); 982 #endif 983 F3 f = FUNCTION_CAST<F3>(code->entry()); 984 Object* dummy = CALL_GENERATED_CODE(f, &i, 0, 0, 0, 0); 985 USE(dummy); 986 987 CHECK_EQ(0xabcd0001, i.a); 988 CHECK_EQ(static_cast<int32_t>(0xabcd0000) >> 1, i.b); 989 CHECK_EQ(0x00000000, i.c); 990 CHECK_EQ(0xffffffff, i.d); 991 } 992 993 994 TEST(12) { 995 // Test chaining of label usages within instructions (issue 1644). 996 CcTest::InitializeVM(); 997 Isolate* isolate = CcTest::i_isolate(); 998 HandleScope scope(isolate); 999 1000 Assembler assm(isolate, NULL, 0); 1001 Label target; 1002 __ b(eq, &target); 1003 __ b(ne, &target); 1004 __ bind(&target); 1005 __ nop(); 1006 } 1007 1008 1009 TEST(13) { 1010 // Test VFP instructions using registers d16-d31. 1011 CcTest::InitializeVM(); 1012 Isolate* isolate = CcTest::i_isolate(); 1013 HandleScope scope(isolate); 1014 1015 if (!CpuFeatures::IsSupported(VFP32DREGS)) { 1016 return; 1017 } 1018 1019 typedef struct { 1020 double a; 1021 double b; 1022 double c; 1023 double x; 1024 double y; 1025 double z; 1026 double i; 1027 double j; 1028 double k; 1029 uint32_t low; 1030 uint32_t high; 1031 } T; 1032 T t; 1033 1034 // Create a function that accepts &t, and loads, manipulates, and stores 1035 // the doubles and floats. 1036 Assembler assm(isolate, NULL, 0); 1037 Label L, C; 1038 1039 1040 if (CpuFeatures::IsSupported(VFP3)) { 1041 CpuFeatureScope scope(&assm, VFP3); 1042 1043 __ stm(db_w, sp, r4.bit() | lr.bit()); 1044 1045 // Load a, b, c into d16, d17, d18. 1046 __ mov(r4, Operand(r0)); 1047 __ vldr(d16, r4, OFFSET_OF(T, a)); 1048 __ vldr(d17, r4, OFFSET_OF(T, b)); 1049 __ vldr(d18, r4, OFFSET_OF(T, c)); 1050 1051 __ vneg(d25, d16); 1052 __ vadd(d25, d25, d17); 1053 __ vsub(d25, d25, d18); 1054 __ vmul(d25, d25, d25); 1055 __ vdiv(d25, d25, d18); 1056 1057 __ vmov(d16, d25); 1058 __ vsqrt(d17, d25); 1059 __ vneg(d17, d17); 1060 __ vabs(d17, d17); 1061 __ vmla(d18, d16, d17); 1062 1063 // Store d16, d17, d18 into a, b, c. 1064 __ mov(r4, Operand(r0)); 1065 __ vstr(d16, r4, OFFSET_OF(T, a)); 1066 __ vstr(d17, r4, OFFSET_OF(T, b)); 1067 __ vstr(d18, r4, OFFSET_OF(T, c)); 1068 1069 // Load x, y, z into d29-d31. 1070 __ add(r4, r0, Operand(OFFSET_OF(T, x))); 1071 __ vldm(ia_w, r4, d29, d31); 1072 1073 // Swap d29 and d30 via r registers. 1074 __ vmov(r1, r2, d29); 1075 __ vmov(d29, d30); 1076 __ vmov(d30, r1, r2); 1077 1078 // Convert to and from integer. 1079 __ vcvt_s32_f64(s1, d31); 1080 __ vcvt_f64_u32(d31, s1); 1081 1082 // Store d29-d31 into x, y, z. 1083 __ add(r4, r0, Operand(OFFSET_OF(T, x))); 1084 __ vstm(ia_w, r4, d29, d31); 1085 1086 // Move constants into d20, d21, d22 and store into i, j, k. 1087 __ vmov(d20, 14.7610017472335499); 1088 __ vmov(d21, 16.0); 1089 __ mov(r1, Operand(372106121)); 1090 __ mov(r2, Operand(1079146608)); 1091 __ vmov(d22, VmovIndexLo, r1); 1092 __ vmov(d22, VmovIndexHi, r2); 1093 __ add(r4, r0, Operand(OFFSET_OF(T, i))); 1094 __ vstm(ia_w, r4, d20, d22); 1095 // Move d22 into low and high. 1096 __ vmov(r4, VmovIndexLo, d22); 1097 __ str(r4, MemOperand(r0, OFFSET_OF(T, low))); 1098 __ vmov(r4, VmovIndexHi, d22); 1099 __ str(r4, MemOperand(r0, OFFSET_OF(T, high))); 1100 1101 __ ldm(ia_w, sp, r4.bit() | pc.bit()); 1102 1103 CodeDesc desc; 1104 assm.GetCode(&desc); 1105 Handle<Code> code = isolate->factory()->NewCode( 1106 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 1107 #ifdef DEBUG 1108 OFStream os(stdout); 1109 code->Print(os); 1110 #endif 1111 F3 f = FUNCTION_CAST<F3>(code->entry()); 1112 t.a = 1.5; 1113 t.b = 2.75; 1114 t.c = 17.17; 1115 t.x = 1.5; 1116 t.y = 2.75; 1117 t.z = 17.17; 1118 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); 1119 USE(dummy); 1120 CHECK_EQ(14.7610017472335499, t.a); 1121 CHECK_EQ(3.84200491244266251, t.b); 1122 CHECK_EQ(73.8818412254460241, t.c); 1123 CHECK_EQ(2.75, t.x); 1124 CHECK_EQ(1.5, t.y); 1125 CHECK_EQ(17.0, t.z); 1126 CHECK_EQ(14.7610017472335499, t.i); 1127 CHECK_EQ(16.0, t.j); 1128 CHECK_EQ(73.8818412254460241, t.k); 1129 CHECK_EQ(372106121, t.low); 1130 CHECK_EQ(1079146608, t.high); 1131 } 1132 } 1133 1134 1135 TEST(14) { 1136 // Test the VFP Canonicalized Nan mode. 1137 CcTest::InitializeVM(); 1138 Isolate* isolate = CcTest::i_isolate(); 1139 HandleScope scope(isolate); 1140 1141 typedef struct { 1142 double left; 1143 double right; 1144 double add_result; 1145 double sub_result; 1146 double mul_result; 1147 double div_result; 1148 } T; 1149 T t; 1150 1151 // Create a function that makes the four basic operations. 1152 Assembler assm(isolate, NULL, 0); 1153 1154 // Ensure FPSCR state (as JSEntryStub does). 1155 Label fpscr_done; 1156 __ vmrs(r1); 1157 __ tst(r1, Operand(kVFPDefaultNaNModeControlBit)); 1158 __ b(ne, &fpscr_done); 1159 __ orr(r1, r1, Operand(kVFPDefaultNaNModeControlBit)); 1160 __ vmsr(r1); 1161 __ bind(&fpscr_done); 1162 1163 __ vldr(d0, r0, OFFSET_OF(T, left)); 1164 __ vldr(d1, r0, OFFSET_OF(T, right)); 1165 __ vadd(d2, d0, d1); 1166 __ vstr(d2, r0, OFFSET_OF(T, add_result)); 1167 __ vsub(d2, d0, d1); 1168 __ vstr(d2, r0, OFFSET_OF(T, sub_result)); 1169 __ vmul(d2, d0, d1); 1170 __ vstr(d2, r0, OFFSET_OF(T, mul_result)); 1171 __ vdiv(d2, d0, d1); 1172 __ vstr(d2, r0, OFFSET_OF(T, div_result)); 1173 1174 __ mov(pc, Operand(lr)); 1175 1176 CodeDesc desc; 1177 assm.GetCode(&desc); 1178 Handle<Code> code = isolate->factory()->NewCode( 1179 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 1180 #ifdef DEBUG 1181 OFStream os(stdout); 1182 code->Print(os); 1183 #endif 1184 F3 f = FUNCTION_CAST<F3>(code->entry()); 1185 t.left = bit_cast<double>(kHoleNanInt64); 1186 t.right = 1; 1187 t.add_result = 0; 1188 t.sub_result = 0; 1189 t.mul_result = 0; 1190 t.div_result = 0; 1191 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); 1192 USE(dummy); 1193 const uint32_t kArmNanUpper32 = 0x7ff80000; 1194 const uint32_t kArmNanLower32 = 0x00000000; 1195 #ifdef DEBUG 1196 const uint64_t kArmNanInt64 = 1197 (static_cast<uint64_t>(kArmNanUpper32) << 32) | kArmNanLower32; 1198 DCHECK(kArmNanInt64 != kHoleNanInt64); 1199 #endif 1200 // With VFP2 the sign of the canonicalized Nan is undefined. So 1201 // we remove the sign bit for the upper tests. 1202 CHECK_EQ(kArmNanUpper32, 1203 (bit_cast<int64_t>(t.add_result) >> 32) & 0x7fffffff); 1204 CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.add_result) & 0xffffffffu); 1205 CHECK_EQ(kArmNanUpper32, 1206 (bit_cast<int64_t>(t.sub_result) >> 32) & 0x7fffffff); 1207 CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.sub_result) & 0xffffffffu); 1208 CHECK_EQ(kArmNanUpper32, 1209 (bit_cast<int64_t>(t.mul_result) >> 32) & 0x7fffffff); 1210 CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.mul_result) & 0xffffffffu); 1211 CHECK_EQ(kArmNanUpper32, 1212 (bit_cast<int64_t>(t.div_result) >> 32) & 0x7fffffff); 1213 CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.div_result) & 0xffffffffu); 1214 } 1215 1216 1217 TEST(15) { 1218 // Test the Neon instructions. 1219 CcTest::InitializeVM(); 1220 Isolate* isolate = CcTest::i_isolate(); 1221 HandleScope scope(isolate); 1222 1223 typedef struct { 1224 uint32_t src0; 1225 uint32_t src1; 1226 uint32_t src2; 1227 uint32_t src3; 1228 uint32_t src4; 1229 uint32_t src5; 1230 uint32_t src6; 1231 uint32_t src7; 1232 uint32_t dst0; 1233 uint32_t dst1; 1234 uint32_t dst2; 1235 uint32_t dst3; 1236 uint32_t dst4; 1237 uint32_t dst5; 1238 uint32_t dst6; 1239 uint32_t dst7; 1240 uint32_t srcA0; 1241 uint32_t srcA1; 1242 uint32_t dstA0; 1243 uint32_t dstA1; 1244 uint32_t dstA2; 1245 uint32_t dstA3; 1246 uint32_t dstA4; 1247 uint32_t dstA5; 1248 uint32_t dstA6; 1249 uint32_t dstA7; 1250 } T; 1251 T t; 1252 1253 // Create a function that accepts &t, and loads, manipulates, and stores 1254 // the doubles and floats. 1255 Assembler assm(isolate, NULL, 0); 1256 1257 1258 if (CpuFeatures::IsSupported(NEON)) { 1259 CpuFeatureScope scope(&assm, NEON); 1260 1261 __ stm(db_w, sp, r4.bit() | lr.bit()); 1262 // Move 32 bytes with neon. 1263 __ add(r4, r0, Operand(OFFSET_OF(T, src0))); 1264 __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4)); 1265 __ add(r4, r0, Operand(OFFSET_OF(T, dst0))); 1266 __ vst1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4)); 1267 1268 // Expand 8 bytes into 8 words(16 bits). 1269 __ add(r4, r0, Operand(OFFSET_OF(T, srcA0))); 1270 __ vld1(Neon8, NeonListOperand(d0), NeonMemOperand(r4)); 1271 __ vmovl(NeonU8, q0, d0); 1272 __ add(r4, r0, Operand(OFFSET_OF(T, dstA0))); 1273 __ vst1(Neon8, NeonListOperand(d0, 2), NeonMemOperand(r4)); 1274 1275 // The same expansion, but with different source and destination registers. 1276 __ add(r4, r0, Operand(OFFSET_OF(T, srcA0))); 1277 __ vld1(Neon8, NeonListOperand(d1), NeonMemOperand(r4)); 1278 __ vmovl(NeonU8, q1, d1); 1279 __ add(r4, r0, Operand(OFFSET_OF(T, dstA4))); 1280 __ vst1(Neon8, NeonListOperand(d2, 2), NeonMemOperand(r4)); 1281 1282 __ ldm(ia_w, sp, r4.bit() | pc.bit()); 1283 1284 CodeDesc desc; 1285 assm.GetCode(&desc); 1286 Handle<Code> code = isolate->factory()->NewCode( 1287 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 1288 #ifdef DEBUG 1289 OFStream os(stdout); 1290 code->Print(os); 1291 #endif 1292 F3 f = FUNCTION_CAST<F3>(code->entry()); 1293 t.src0 = 0x01020304; 1294 t.src1 = 0x11121314; 1295 t.src2 = 0x21222324; 1296 t.src3 = 0x31323334; 1297 t.src4 = 0x41424344; 1298 t.src5 = 0x51525354; 1299 t.src6 = 0x61626364; 1300 t.src7 = 0x71727374; 1301 t.dst0 = 0; 1302 t.dst1 = 0; 1303 t.dst2 = 0; 1304 t.dst3 = 0; 1305 t.dst4 = 0; 1306 t.dst5 = 0; 1307 t.dst6 = 0; 1308 t.dst7 = 0; 1309 t.srcA0 = 0x41424344; 1310 t.srcA1 = 0x81828384; 1311 t.dstA0 = 0; 1312 t.dstA1 = 0; 1313 t.dstA2 = 0; 1314 t.dstA3 = 0; 1315 t.dstA4 = 0; 1316 t.dstA5 = 0; 1317 t.dstA6 = 0; 1318 t.dstA7 = 0; 1319 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); 1320 USE(dummy); 1321 CHECK_EQ(0x01020304, t.dst0); 1322 CHECK_EQ(0x11121314, t.dst1); 1323 CHECK_EQ(0x21222324, t.dst2); 1324 CHECK_EQ(0x31323334, t.dst3); 1325 CHECK_EQ(0x41424344, t.dst4); 1326 CHECK_EQ(0x51525354, t.dst5); 1327 CHECK_EQ(0x61626364, t.dst6); 1328 CHECK_EQ(0x71727374, t.dst7); 1329 CHECK_EQ(0x00430044, t.dstA0); 1330 CHECK_EQ(0x00410042, t.dstA1); 1331 CHECK_EQ(0x00830084, t.dstA2); 1332 CHECK_EQ(0x00810082, t.dstA3); 1333 CHECK_EQ(0x00430044, t.dstA4); 1334 CHECK_EQ(0x00410042, t.dstA5); 1335 CHECK_EQ(0x00830084, t.dstA6); 1336 CHECK_EQ(0x00810082, t.dstA7); 1337 } 1338 } 1339 1340 1341 TEST(16) { 1342 // Test the pkh, uxtb, uxtab and uxtb16 instructions. 1343 CcTest::InitializeVM(); 1344 Isolate* isolate = CcTest::i_isolate(); 1345 HandleScope scope(isolate); 1346 1347 typedef struct { 1348 uint32_t src0; 1349 uint32_t src1; 1350 uint32_t src2; 1351 uint32_t dst0; 1352 uint32_t dst1; 1353 uint32_t dst2; 1354 uint32_t dst3; 1355 uint32_t dst4; 1356 } T; 1357 T t; 1358 1359 // Create a function that accepts &t, and loads, manipulates, and stores 1360 // the doubles and floats. 1361 Assembler assm(isolate, NULL, 0); 1362 1363 __ stm(db_w, sp, r4.bit() | lr.bit()); 1364 1365 __ mov(r4, Operand(r0)); 1366 __ ldr(r0, MemOperand(r4, OFFSET_OF(T, src0))); 1367 __ ldr(r1, MemOperand(r4, OFFSET_OF(T, src1))); 1368 1369 __ pkhbt(r2, r0, Operand(r1, LSL, 8)); 1370 __ str(r2, MemOperand(r4, OFFSET_OF(T, dst0))); 1371 1372 __ pkhtb(r2, r0, Operand(r1, ASR, 8)); 1373 __ str(r2, MemOperand(r4, OFFSET_OF(T, dst1))); 1374 1375 __ uxtb16(r2, Operand(r0, ROR, 8)); 1376 __ str(r2, MemOperand(r4, OFFSET_OF(T, dst2))); 1377 1378 __ uxtb(r2, Operand(r0, ROR, 8)); 1379 __ str(r2, MemOperand(r4, OFFSET_OF(T, dst3))); 1380 1381 __ ldr(r0, MemOperand(r4, OFFSET_OF(T, src2))); 1382 __ uxtab(r2, r0, Operand(r1, ROR, 8)); 1383 __ str(r2, MemOperand(r4, OFFSET_OF(T, dst4))); 1384 1385 __ ldm(ia_w, sp, r4.bit() | pc.bit()); 1386 1387 CodeDesc desc; 1388 assm.GetCode(&desc); 1389 Handle<Code> code = isolate->factory()->NewCode( 1390 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 1391 #ifdef DEBUG 1392 OFStream os(stdout); 1393 code->Print(os); 1394 #endif 1395 F3 f = FUNCTION_CAST<F3>(code->entry()); 1396 t.src0 = 0x01020304; 1397 t.src1 = 0x11121314; 1398 t.src2 = 0x11121300; 1399 t.dst0 = 0; 1400 t.dst1 = 0; 1401 t.dst2 = 0; 1402 t.dst3 = 0; 1403 t.dst4 = 0; 1404 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); 1405 USE(dummy); 1406 CHECK_EQ(0x12130304, t.dst0); 1407 CHECK_EQ(0x01021213, t.dst1); 1408 CHECK_EQ(0x00010003, t.dst2); 1409 CHECK_EQ(0x00000003, t.dst3); 1410 CHECK_EQ(0x11121313, t.dst4); 1411 } 1412 1413 1414 TEST(17) { 1415 // Test generating labels at high addresses. 1416 // Should not assert. 1417 CcTest::InitializeVM(); 1418 Isolate* isolate = CcTest::i_isolate(); 1419 HandleScope scope(isolate); 1420 1421 // Generate a code segment that will be longer than 2^24 bytes. 1422 Assembler assm(isolate, NULL, 0); 1423 for (size_t i = 0; i < 1 << 23 ; ++i) { // 2^23 1424 __ nop(); 1425 } 1426 1427 Label target; 1428 __ b(eq, &target); 1429 __ bind(&target); 1430 __ nop(); 1431 } 1432 1433 1434 #define TEST_SDIV(expected_, dividend_, divisor_) \ 1435 t.dividend = dividend_; \ 1436 t.divisor = divisor_; \ 1437 t.result = 0; \ 1438 dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); \ 1439 CHECK_EQ(expected_, t.result); 1440 1441 1442 TEST(18) { 1443 // Test the sdiv. 1444 CcTest::InitializeVM(); 1445 Isolate* isolate = CcTest::i_isolate(); 1446 HandleScope scope(isolate); 1447 1448 typedef struct { 1449 uint32_t dividend; 1450 uint32_t divisor; 1451 uint32_t result; 1452 } T; 1453 T t; 1454 1455 Assembler assm(isolate, NULL, 0); 1456 1457 if (CpuFeatures::IsSupported(SUDIV)) { 1458 CpuFeatureScope scope(&assm, SUDIV); 1459 1460 __ mov(r3, Operand(r0)); 1461 1462 __ ldr(r0, MemOperand(r3, OFFSET_OF(T, dividend))); 1463 __ ldr(r1, MemOperand(r3, OFFSET_OF(T, divisor))); 1464 1465 __ sdiv(r2, r0, r1); 1466 __ str(r2, MemOperand(r3, OFFSET_OF(T, result))); 1467 1468 __ bx(lr); 1469 1470 CodeDesc desc; 1471 assm.GetCode(&desc); 1472 Handle<Code> code = isolate->factory()->NewCode( 1473 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 1474 #ifdef DEBUG 1475 OFStream os(stdout); 1476 code->Print(os); 1477 #endif 1478 F3 f = FUNCTION_CAST<F3>(code->entry()); 1479 Object* dummy; 1480 TEST_SDIV(1073741824, kMinInt, -2); 1481 TEST_SDIV(kMinInt, kMinInt, -1); 1482 TEST_SDIV(5, 10, 2); 1483 TEST_SDIV(3, 10, 3); 1484 TEST_SDIV(-5, 10, -2); 1485 TEST_SDIV(-3, 10, -3); 1486 TEST_SDIV(-5, -10, 2); 1487 TEST_SDIV(-3, -10, 3); 1488 TEST_SDIV(5, -10, -2); 1489 TEST_SDIV(3, -10, -3); 1490 USE(dummy); 1491 } 1492 } 1493 1494 1495 #undef TEST_SDIV 1496 1497 1498 TEST(code_relative_offset) { 1499 // Test extracting the offset of a label from the beginning of the code 1500 // in a register. 1501 CcTest::InitializeVM(); 1502 Isolate* isolate = CcTest::i_isolate(); 1503 HandleScope scope(isolate); 1504 // Initialize a code object that will contain the code. 1505 Handle<Object> code_object(isolate->heap()->undefined_value(), isolate); 1506 1507 Assembler assm(isolate, NULL, 0); 1508 1509 Label start, target_away, target_faraway; 1510 1511 __ stm(db_w, sp, r4.bit() | r5.bit() | lr.bit()); 1512 1513 // r3 is used as the address zero, the test will crash when we load it. 1514 __ mov(r3, Operand::Zero()); 1515 1516 // r5 will be a pointer to the start of the code. 1517 __ mov(r5, Operand(code_object)); 1518 __ mov_label_offset(r4, &start); 1519 1520 __ mov_label_offset(r1, &target_faraway); 1521 __ str(r1, MemOperand(sp, kPointerSize, NegPreIndex)); 1522 1523 __ mov_label_offset(r1, &target_away); 1524 1525 // Jump straight to 'target_away' the first time and use the relative 1526 // position the second time. This covers the case when extracting the 1527 // position of a label which is linked. 1528 __ mov(r2, Operand::Zero()); 1529 __ bind(&start); 1530 __ cmp(r2, Operand::Zero()); 1531 __ b(eq, &target_away); 1532 __ add(pc, r5, r1); 1533 // Emit invalid instructions to push the label between 2^8 and 2^16 1534 // instructions away. The test will crash if they are reached. 1535 for (int i = 0; i < (1 << 10); i++) { 1536 __ ldr(r3, MemOperand(r3)); 1537 } 1538 __ bind(&target_away); 1539 // This will be hit twice: r0 = r0 + 5 + 5. 1540 __ add(r0, r0, Operand(5)); 1541 1542 __ ldr(r1, MemOperand(sp, kPointerSize, PostIndex), ne); 1543 __ add(pc, r5, r4, LeaveCC, ne); 1544 1545 __ mov(r2, Operand(1)); 1546 __ b(&start); 1547 // Emit invalid instructions to push the label between 2^16 and 2^24 1548 // instructions away. The test will crash if they are reached. 1549 for (int i = 0; i < (1 << 21); i++) { 1550 __ ldr(r3, MemOperand(r3)); 1551 } 1552 __ bind(&target_faraway); 1553 // r0 = r0 + 5 + 5 + 11 1554 __ add(r0, r0, Operand(11)); 1555 1556 __ ldm(ia_w, sp, r4.bit() | r5.bit() | pc.bit()); 1557 1558 CodeDesc desc; 1559 assm.GetCode(&desc); 1560 Handle<Code> code = isolate->factory()->NewCode( 1561 desc, Code::ComputeFlags(Code::STUB), code_object); 1562 F1 f = FUNCTION_CAST<F1>(code->entry()); 1563 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 21, 0, 0, 0, 0)); 1564 ::printf("f() = %d\n", res); 1565 CHECK_EQ(42, res); 1566 } 1567 1568 #undef __ 1569