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