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/ppc/assembler-ppc-inl.h" 33#include "src/ppc/simulator-ppc.h" 34#include "test/cctest/cctest.h" 35 36using namespace v8::internal; 37 38 39// Define these function prototypes to match JSEntryFunction in execution.cc. 40typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4); 41typedef Object* (*F2)(int x, int y, int p2, int p3, int p4); 42typedef Object* (*F3)(void* p0, int p1, int p2, int p3, int p4); 43typedef Object* (*F4)(void* p0, void* p1, int p2, int p3, int p4); 44 45 46#define __ assm. 47 48// Simple add parameter 1 to parameter 2 and return 49TEST(0) { 50 CcTest::InitializeVM(); 51 Isolate* isolate = CcTest::i_isolate(); 52 HandleScope scope(isolate); 53 54 Assembler assm(isolate, NULL, 0); 55 56 __ function_descriptor(); 57 58 __ add(r3, r3, r4); 59 __ blr(); 60 61 CodeDesc desc; 62 assm.GetCode(&desc); 63 Handle<Code> code = isolate->factory()->NewCode( 64 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 65#ifdef DEBUG 66 code->Print(); 67#endif 68 F2 f = FUNCTION_CAST<F2>(code->entry()); 69 intptr_t res = reinterpret_cast<intptr_t>( 70 CALL_GENERATED_CODE(isolate, f, 3, 4, 0, 0, 0)); 71 ::printf("f() = %" V8PRIdPTR "\n", res); 72 CHECK_EQ(7, static_cast<int>(res)); 73} 74 75 76// Loop 100 times, adding loop counter to result 77TEST(1) { 78 CcTest::InitializeVM(); 79 Isolate* isolate = CcTest::i_isolate(); 80 HandleScope scope(isolate); 81 82 Assembler assm(isolate, NULL, 0); 83 Label L, C; 84 85 __ function_descriptor(); 86 87 __ mr(r4, r3); 88 __ li(r3, Operand::Zero()); 89 __ b(&C); 90 91 __ bind(&L); 92 __ add(r3, r3, r4); 93 __ subi(r4, r4, Operand(1)); 94 95 __ bind(&C); 96 __ cmpi(r4, Operand::Zero()); 97 __ bne(&L); 98 __ blr(); 99 100 CodeDesc desc; 101 assm.GetCode(&desc); 102 Handle<Code> code = isolate->factory()->NewCode( 103 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 104#ifdef DEBUG 105 code->Print(); 106#endif 107 F1 f = FUNCTION_CAST<F1>(code->entry()); 108 intptr_t res = reinterpret_cast<intptr_t>( 109 CALL_GENERATED_CODE(isolate, f, 100, 0, 0, 0, 0)); 110 ::printf("f() = %" V8PRIdPTR "\n", res); 111 CHECK_EQ(5050, static_cast<int>(res)); 112} 113 114 115TEST(2) { 116 CcTest::InitializeVM(); 117 Isolate* isolate = CcTest::i_isolate(); 118 HandleScope scope(isolate); 119 120 Assembler assm(isolate, NULL, 0); 121 Label L, C; 122 123 __ function_descriptor(); 124 125 __ mr(r4, r3); 126 __ li(r3, Operand(1)); 127 __ b(&C); 128 129 __ bind(&L); 130#if defined(V8_TARGET_ARCH_PPC64) 131 __ mulld(r3, r4, r3); 132#else 133 __ mullw(r3, r4, r3); 134#endif 135 __ subi(r4, r4, Operand(1)); 136 137 __ bind(&C); 138 __ cmpi(r4, Operand::Zero()); 139 __ bne(&L); 140 __ blr(); 141 142 // some relocated stuff here, not executed 143 __ RecordComment("dead code, just testing relocations"); 144 __ mov(r0, Operand(isolate->factory()->true_value())); 145 __ RecordComment("dead code, just testing immediate operands"); 146 __ mov(r0, Operand(-1)); 147 __ mov(r0, Operand(0xFF000000)); 148 __ mov(r0, Operand(0xF0F0F0F0)); 149 __ mov(r0, Operand(0xFFF0FFFF)); 150 151 CodeDesc desc; 152 assm.GetCode(&desc); 153 Handle<Code> code = isolate->factory()->NewCode( 154 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 155#ifdef DEBUG 156 code->Print(); 157#endif 158 F1 f = FUNCTION_CAST<F1>(code->entry()); 159 intptr_t res = reinterpret_cast<intptr_t>( 160 CALL_GENERATED_CODE(isolate, f, 10, 0, 0, 0, 0)); 161 ::printf("f() = %" V8PRIdPTR "\n", res); 162 CHECK_EQ(3628800, static_cast<int>(res)); 163} 164 165 166TEST(3) { 167 CcTest::InitializeVM(); 168 Isolate* isolate = CcTest::i_isolate(); 169 HandleScope scope(isolate); 170 171 typedef struct { 172 int i; 173 char c; 174 int16_t s; 175 } T; 176 T t; 177 178 Assembler assm(CcTest::i_isolate(), NULL, 0); 179 Label L, C; 180 181 __ function_descriptor(); 182 183// build a frame 184#if V8_TARGET_ARCH_PPC64 185 __ stdu(sp, MemOperand(sp, -32)); 186 __ std(fp, MemOperand(sp, 24)); 187#else 188 __ stwu(sp, MemOperand(sp, -16)); 189 __ stw(fp, MemOperand(sp, 12)); 190#endif 191 __ mr(fp, sp); 192 193 // r4 points to our struct 194 __ mr(r4, r3); 195 196 // modify field int i of struct 197 __ lwz(r3, MemOperand(r4, offsetof(T, i))); 198 __ srwi(r5, r3, Operand(1)); 199 __ stw(r5, MemOperand(r4, offsetof(T, i))); 200 201 // modify field char c of struct 202 __ lbz(r5, MemOperand(r4, offsetof(T, c))); 203 __ add(r3, r5, r3); 204 __ slwi(r5, r5, Operand(2)); 205 __ stb(r5, MemOperand(r4, offsetof(T, c))); 206 207 // modify field int16_t s of struct 208 __ lhz(r5, MemOperand(r4, offsetof(T, s))); 209 __ add(r3, r5, r3); 210 __ srwi(r5, r5, Operand(3)); 211 __ sth(r5, MemOperand(r4, offsetof(T, s))); 212 213// restore frame 214#if V8_TARGET_ARCH_PPC64 215 __ addi(r11, fp, Operand(32)); 216 __ ld(fp, MemOperand(r11, -8)); 217#else 218 __ addi(r11, fp, Operand(16)); 219 __ lwz(fp, MemOperand(r11, -4)); 220#endif 221 __ mr(sp, r11); 222 __ blr(); 223 224 CodeDesc desc; 225 assm.GetCode(&desc); 226 Handle<Code> code = isolate->factory()->NewCode( 227 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 228#ifdef DEBUG 229 code->Print(); 230#endif 231 F3 f = FUNCTION_CAST<F3>(code->entry()); 232 t.i = 100000; 233 t.c = 10; 234 t.s = 1000; 235 intptr_t res = reinterpret_cast<intptr_t>( 236 CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0)); 237 ::printf("f() = %" V8PRIdPTR "\n", res); 238 CHECK_EQ(101010, static_cast<int>(res)); 239 CHECK_EQ(100000 / 2, t.i); 240 CHECK_EQ(10 * 4, t.c); 241 CHECK_EQ(1000 / 8, t.s); 242} 243 244#if 0 245TEST(4) { 246 // Test the VFP floating point instructions. 247 CcTest::InitializeVM(); 248 Isolate* isolate = CcTest::i_isolate(); 249 HandleScope scope(isolate); 250 251 typedef struct { 252 double a; 253 double b; 254 double c; 255 double d; 256 double e; 257 double f; 258 double g; 259 double h; 260 int i; 261 double m; 262 double n; 263 float x; 264 float y; 265 } T; 266 T t; 267 268 // Create a function that accepts &t, and loads, manipulates, and stores 269 // the doubles and floats. 270 Assembler assm(CcTest::i_isolate(), NULL, 0); 271 Label L, C; 272 273 if (CpuFeatures::IsSupported(VFP3)) { 274 CpuFeatures::Scope scope(VFP3); 275 276 __ mov(ip, Operand(sp)); 277 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); 278 __ sub(fp, ip, Operand(4)); 279 280 __ mov(r4, Operand(r0)); 281 __ vldr(d6, r4, offsetof(T, a)); 282 __ vldr(d7, r4, offsetof(T, b)); 283 __ vadd(d5, d6, d7); 284 __ vstr(d5, r4, offsetof(T, c)); 285 286 __ vmov(r2, r3, d5); 287 __ vmov(d4, r2, r3); 288 __ vstr(d4, r4, offsetof(T, b)); 289 290 // Load t.x and t.y, switch values, and store back to the struct. 291 __ vldr(s0, r4, offsetof(T, x)); 292 __ vldr(s31, r4, offsetof(T, y)); 293 __ vmov(s16, s0); 294 __ vmov(s0, s31); 295 __ vmov(s31, s16); 296 __ vstr(s0, r4, offsetof(T, x)); 297 __ vstr(s31, r4, offsetof(T, y)); 298 299 // Move a literal into a register that can be encoded in the instruction. 300 __ vmov(d4, 1.0); 301 __ vstr(d4, r4, offsetof(T, e)); 302 303 // Move a literal into a register that requires 64 bits to encode. 304 // 0x3ff0000010000000 = 1.000000059604644775390625 305 __ vmov(d4, 1.000000059604644775390625); 306 __ vstr(d4, r4, offsetof(T, d)); 307 308 // Convert from floating point to integer. 309 __ vmov(d4, 2.0); 310 __ vcvt_s32_f64(s31, d4); 311 __ vstr(s31, r4, offsetof(T, i)); 312 313 // Convert from integer to floating point. 314 __ mov(lr, Operand(42)); 315 __ vmov(s31, lr); 316 __ vcvt_f64_s32(d4, s31); 317 __ vstr(d4, r4, offsetof(T, f)); 318 319 // Test vabs. 320 __ vldr(d1, r4, offsetof(T, g)); 321 __ vabs(d0, d1); 322 __ vstr(d0, r4, offsetof(T, g)); 323 __ vldr(d2, r4, offsetof(T, h)); 324 __ vabs(d0, d2); 325 __ vstr(d0, r4, offsetof(T, h)); 326 327 // Test vneg. 328 __ vldr(d1, r4, offsetof(T, m)); 329 __ vneg(d0, d1); 330 __ vstr(d0, r4, offsetof(T, m)); 331 __ vldr(d1, r4, offsetof(T, n)); 332 __ vneg(d0, d1); 333 __ vstr(d0, r4, offsetof(T, n)); 334 335 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); 336 337 CodeDesc desc; 338 assm.GetCode(&desc); 339 Object* code = isolate->heap()->CreateCode( 340 desc, 341 Code::ComputeFlags(Code::STUB), 342 Handle<Code>())->ToObjectChecked(); 343 CHECK(code->IsCode()); 344#ifdef DEBUG 345 Code::cast(code)->Print(); 346#endif 347 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); 348 t.a = 1.5; 349 t.b = 2.75; 350 t.c = 17.17; 351 t.d = 0.0; 352 t.e = 0.0; 353 t.f = 0.0; 354 t.g = -2718.2818; 355 t.h = 31415926.5; 356 t.i = 0; 357 t.m = -2718.2818; 358 t.n = 123.456; 359 t.x = 4.5; 360 t.y = 9.0; 361 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); 362 USE(dummy); 363 CHECK_EQ(4.5, t.y); 364 CHECK_EQ(9.0, t.x); 365 CHECK_EQ(-123.456, t.n); 366 CHECK_EQ(2718.2818, t.m); 367 CHECK_EQ(2, t.i); 368 CHECK_EQ(2718.2818, t.g); 369 CHECK_EQ(31415926.5, t.h); 370 CHECK_EQ(42.0, t.f); 371 CHECK_EQ(1.0, t.e); 372 CHECK_EQ(1.000000059604644775390625, t.d); 373 CHECK_EQ(4.25, t.c); 374 CHECK_EQ(4.25, t.b); 375 CHECK_EQ(1.5, t.a); 376 } 377} 378 379 380TEST(5) { 381 // Test the ARMv7 bitfield instructions. 382 CcTest::InitializeVM(); 383 Isolate* isolate = CcTest::i_isolate(); 384 HandleScope scope(isolate); 385 386 Assembler assm(isolate, NULL, 0); 387 388 if (CpuFeatures::IsSupported(ARMv7)) { 389 CpuFeatures::Scope scope(ARMv7); 390 // On entry, r0 = 0xAAAAAAAA = 0b10..10101010. 391 __ ubfx(r0, r0, 1, 12); // 0b00..010101010101 = 0x555 392 __ sbfx(r0, r0, 0, 5); // 0b11..111111110101 = -11 393 __ bfc(r0, 1, 3); // 0b11..111111110001 = -15 394 __ mov(r1, Operand(7)); 395 __ bfi(r0, r1, 3, 3); // 0b11..111111111001 = -7 396 __ mov(pc, Operand(lr)); 397 398 CodeDesc desc; 399 assm.GetCode(&desc); 400 Object* code = isolate->heap()->CreateCode( 401 desc, 402 Code::ComputeFlags(Code::STUB), 403 Handle<Code>())->ToObjectChecked(); 404 CHECK(code->IsCode()); 405#ifdef DEBUG 406 Code::cast(code)->Print(); 407#endif 408 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry()); 409 int res = reinterpret_cast<int>( 410 CALL_GENERATED_CODE(isolate, f, 0xAAAAAAAA, 0, 0, 0, 0)); 411 ::printf("f() = %d\n", res); 412 CHECK_EQ(-7, res); 413 } 414} 415 416 417TEST(6) { 418 // Test saturating instructions. 419 CcTest::InitializeVM(); 420 Isolate* isolate = CcTest::i_isolate(); 421 HandleScope scope(isolate); 422 423 Assembler assm(isolate, NULL, 0); 424 425 if (CpuFeatures::IsSupported(ARMv7)) { 426 CpuFeatures::Scope scope(ARMv7); 427 __ usat(r1, 8, Operand(r0)); // Sat 0xFFFF to 0-255 = 0xFF. 428 __ usat(r2, 12, Operand(r0, ASR, 9)); // Sat (0xFFFF>>9) to 0-4095 = 0x7F. 429 __ usat(r3, 1, Operand(r0, LSL, 16)); // Sat (0xFFFF<<16) to 0-1 = 0x0. 430 __ addi(r0, r1, Operand(r2)); 431 __ addi(r0, r0, Operand(r3)); 432 __ mov(pc, Operand(lr)); 433 434 CodeDesc desc; 435 assm.GetCode(&desc); 436 Object* code = isolate->heap()->CreateCode( 437 desc, 438 Code::ComputeFlags(Code::STUB), 439 Handle<Code>())->ToObjectChecked(); 440 CHECK(code->IsCode()); 441#ifdef DEBUG 442 Code::cast(code)->Print(); 443#endif 444 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry()); 445 int res = reinterpret_cast<int>( 446 CALL_GENERATED_CODE(isolate, f, 0xFFFF, 0, 0, 0, 0)); 447 ::printf("f() = %d\n", res); 448 CHECK_EQ(382, res); 449 } 450} 451 452enum VCVTTypes { 453 s32_f64, 454 u32_f64 455}; 456 457static void TestRoundingMode(VCVTTypes types, 458 VFPRoundingMode mode, 459 double value, 460 int expected, 461 bool expected_exception = false) { 462 CcTest::InitializeVM(); 463 Isolate* isolate = CcTest::i_isolate(); 464 HandleScope scope(isolate); 465 466 Assembler assm(isolate, NULL, 0); 467 468 if (CpuFeatures::IsSupported(VFP3)) { 469 CpuFeatures::Scope scope(VFP3); 470 471 Label wrong_exception; 472 473 __ vmrs(r1); 474 // Set custom FPSCR. 475 __ bic(r2, r1, Operand(kVFPRoundingModeMask | kVFPExceptionMask)); 476 __ orr(r2, r2, Operand(mode)); 477 __ vmsr(r2); 478 479 // Load value, convert, and move back result to r0 if everything went well. 480 __ vmov(d1, value); 481 switch (types) { 482 case s32_f64: 483 __ vcvt_s32_f64(s0, d1, kFPSCRRounding); 484 break; 485 486 case u32_f64: 487 __ vcvt_u32_f64(s0, d1, kFPSCRRounding); 488 break; 489 490 default: 491 UNREACHABLE(); 492 break; 493 } 494 // Check for vfp exceptions 495 __ vmrs(r2); 496 __ tst(r2, Operand(kVFPExceptionMask)); 497 // Check that we behaved as expected. 498 __ b(&wrong_exception, 499 expected_exception ? eq : ne); 500 // There was no exception. Retrieve the result and return. 501 __ vmov(r0, s0); 502 __ mov(pc, Operand(lr)); 503 504 // The exception behaviour is not what we expected. 505 // Load a special value and return. 506 __ bind(&wrong_exception); 507 __ mov(r0, Operand(11223344)); 508 __ mov(pc, Operand(lr)); 509 510 CodeDesc desc; 511 assm.GetCode(&desc); 512 Object* code = isolate->heap()->CreateCode( 513 desc, 514 Code::ComputeFlags(Code::STUB), 515 Handle<Code>())->ToObjectChecked(); 516 CHECK(code->IsCode()); 517#ifdef DEBUG 518 Code::cast(code)->Print(); 519#endif 520 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry()); 521 int res = reinterpret_cast<int>( 522 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); 523 ::printf("res = %d\n", res); 524 CHECK_EQ(expected, res); 525 } 526} 527 528 529TEST(7) { 530 // Test vfp rounding modes. 531 532 // s32_f64 (double to integer). 533 534 TestRoundingMode(s32_f64, RN, 0, 0); 535 TestRoundingMode(s32_f64, RN, 0.5, 0); 536 TestRoundingMode(s32_f64, RN, -0.5, 0); 537 TestRoundingMode(s32_f64, RN, 1.5, 2); 538 TestRoundingMode(s32_f64, RN, -1.5, -2); 539 TestRoundingMode(s32_f64, RN, 123.7, 124); 540 TestRoundingMode(s32_f64, RN, -123.7, -124); 541 TestRoundingMode(s32_f64, RN, 123456.2, 123456); 542 TestRoundingMode(s32_f64, RN, -123456.2, -123456); 543 TestRoundingMode(s32_f64, RN, static_cast<double>(kMaxInt), kMaxInt); 544 TestRoundingMode(s32_f64, RN, (kMaxInt + 0.49), kMaxInt); 545 TestRoundingMode(s32_f64, RN, (kMaxInt + 1.0), kMaxInt, true); 546 TestRoundingMode(s32_f64, RN, (kMaxInt + 0.5), kMaxInt, true); 547 TestRoundingMode(s32_f64, RN, static_cast<double>(kMinInt), kMinInt); 548 TestRoundingMode(s32_f64, RN, (kMinInt - 0.5), kMinInt); 549 TestRoundingMode(s32_f64, RN, (kMinInt - 1.0), kMinInt, true); 550 TestRoundingMode(s32_f64, RN, (kMinInt - 0.51), kMinInt, true); 551 552 TestRoundingMode(s32_f64, RM, 0, 0); 553 TestRoundingMode(s32_f64, RM, 0.5, 0); 554 TestRoundingMode(s32_f64, RM, -0.5, -1); 555 TestRoundingMode(s32_f64, RM, 123.7, 123); 556 TestRoundingMode(s32_f64, RM, -123.7, -124); 557 TestRoundingMode(s32_f64, RM, 123456.2, 123456); 558 TestRoundingMode(s32_f64, RM, -123456.2, -123457); 559 TestRoundingMode(s32_f64, RM, static_cast<double>(kMaxInt), kMaxInt); 560 TestRoundingMode(s32_f64, RM, (kMaxInt + 0.5), kMaxInt); 561 TestRoundingMode(s32_f64, RM, (kMaxInt + 1.0), kMaxInt, true); 562 TestRoundingMode(s32_f64, RM, static_cast<double>(kMinInt), kMinInt); 563 TestRoundingMode(s32_f64, RM, (kMinInt - 0.5), kMinInt, true); 564 TestRoundingMode(s32_f64, RM, (kMinInt + 0.5), kMinInt); 565 566 TestRoundingMode(s32_f64, RZ, 0, 0); 567 TestRoundingMode(s32_f64, RZ, 0.5, 0); 568 TestRoundingMode(s32_f64, RZ, -0.5, 0); 569 TestRoundingMode(s32_f64, RZ, 123.7, 123); 570 TestRoundingMode(s32_f64, RZ, -123.7, -123); 571 TestRoundingMode(s32_f64, RZ, 123456.2, 123456); 572 TestRoundingMode(s32_f64, RZ, -123456.2, -123456); 573 TestRoundingMode(s32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt); 574 TestRoundingMode(s32_f64, RZ, (kMaxInt + 0.5), kMaxInt); 575 TestRoundingMode(s32_f64, RZ, (kMaxInt + 1.0), kMaxInt, true); 576 TestRoundingMode(s32_f64, RZ, static_cast<double>(kMinInt), kMinInt); 577 TestRoundingMode(s32_f64, RZ, (kMinInt - 0.5), kMinInt); 578 TestRoundingMode(s32_f64, RZ, (kMinInt - 1.0), kMinInt, true); 579 580 581 // u32_f64 (double to integer). 582 583 // Negative values. 584 TestRoundingMode(u32_f64, RN, -0.5, 0); 585 TestRoundingMode(u32_f64, RN, -123456.7, 0, true); 586 TestRoundingMode(u32_f64, RN, static_cast<double>(kMinInt), 0, true); 587 TestRoundingMode(u32_f64, RN, kMinInt - 1.0, 0, true); 588 589 TestRoundingMode(u32_f64, RM, -0.5, 0, true); 590 TestRoundingMode(u32_f64, RM, -123456.7, 0, true); 591 TestRoundingMode(u32_f64, RM, static_cast<double>(kMinInt), 0, true); 592 TestRoundingMode(u32_f64, RM, kMinInt - 1.0, 0, true); 593 594 TestRoundingMode(u32_f64, RZ, -0.5, 0); 595 TestRoundingMode(u32_f64, RZ, -123456.7, 0, true); 596 TestRoundingMode(u32_f64, RZ, static_cast<double>(kMinInt), 0, true); 597 TestRoundingMode(u32_f64, RZ, kMinInt - 1.0, 0, true); 598 599 // Positive values. 600 // kMaxInt is the maximum *signed* integer: 0x7fffffff. 601 static const uint32_t kMaxUInt = 0xffffffffu; 602 TestRoundingMode(u32_f64, RZ, 0, 0); 603 TestRoundingMode(u32_f64, RZ, 0.5, 0); 604 TestRoundingMode(u32_f64, RZ, 123.7, 123); 605 TestRoundingMode(u32_f64, RZ, 123456.2, 123456); 606 TestRoundingMode(u32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt); 607 TestRoundingMode(u32_f64, RZ, (kMaxInt + 0.5), kMaxInt); 608 TestRoundingMode(u32_f64, RZ, (kMaxInt + 1.0), 609 static_cast<uint32_t>(kMaxInt) + 1); 610 TestRoundingMode(u32_f64, RZ, (kMaxUInt + 0.5), kMaxUInt); 611 TestRoundingMode(u32_f64, RZ, (kMaxUInt + 1.0), kMaxUInt, true); 612 613 TestRoundingMode(u32_f64, RM, 0, 0); 614 TestRoundingMode(u32_f64, RM, 0.5, 0); 615 TestRoundingMode(u32_f64, RM, 123.7, 123); 616 TestRoundingMode(u32_f64, RM, 123456.2, 123456); 617 TestRoundingMode(u32_f64, RM, static_cast<double>(kMaxInt), kMaxInt); 618 TestRoundingMode(u32_f64, RM, (kMaxInt + 0.5), kMaxInt); 619 TestRoundingMode(u32_f64, RM, (kMaxInt + 1.0), 620 static_cast<uint32_t>(kMaxInt) + 1); 621 TestRoundingMode(u32_f64, RM, (kMaxUInt + 0.5), kMaxUInt); 622 TestRoundingMode(u32_f64, RM, (kMaxUInt + 1.0), kMaxUInt, true); 623 624 TestRoundingMode(u32_f64, RN, 0, 0); 625 TestRoundingMode(u32_f64, RN, 0.5, 0); 626 TestRoundingMode(u32_f64, RN, 1.5, 2); 627 TestRoundingMode(u32_f64, RN, 123.7, 124); 628 TestRoundingMode(u32_f64, RN, 123456.2, 123456); 629 TestRoundingMode(u32_f64, RN, static_cast<double>(kMaxInt), kMaxInt); 630 TestRoundingMode(u32_f64, RN, (kMaxInt + 0.49), kMaxInt); 631 TestRoundingMode(u32_f64, RN, (kMaxInt + 0.5), 632 static_cast<uint32_t>(kMaxInt) + 1); 633 TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.49), kMaxUInt); 634 TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.5), kMaxUInt, true); 635 TestRoundingMode(u32_f64, RN, (kMaxUInt + 1.0), kMaxUInt, true); 636} 637 638 639TEST(8) { 640 // Test VFP multi load/store with ia_w. 641 CcTest::InitializeVM(); 642 Isolate* isolate = CcTest::i_isolate(); 643 HandleScope scope(isolate); 644 645 typedef struct { 646 double a; 647 double b; 648 double c; 649 double d; 650 double e; 651 double f; 652 double g; 653 double h; 654 } D; 655 D d; 656 657 typedef struct { 658 float a; 659 float b; 660 float c; 661 float d; 662 float e; 663 float f; 664 float g; 665 float h; 666 } F; 667 F f; 668 669 // Create a function that uses vldm/vstm to move some double and 670 // single precision values around in memory. 671 Assembler assm(isolate, NULL, 0); 672 673 if (CpuFeatures::IsSupported(VFP2)) { 674 CpuFeatures::Scope scope(VFP2); 675 676 __ mov(ip, Operand(sp)); 677 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); 678 __ sub(fp, ip, Operand(4)); 679 680 __ addi(r4, r0, Operand(offsetof(D, a))); 681 __ vldm(ia_w, r4, d0, d3); 682 __ vldm(ia_w, r4, d4, d7); 683 684 __ addi(r4, r0, Operand(offsetof(D, a))); 685 __ vstm(ia_w, r4, d6, d7); 686 __ vstm(ia_w, r4, d0, d5); 687 688 __ addi(r4, r1, Operand(offsetof(F, a))); 689 __ vldm(ia_w, r4, s0, s3); 690 __ vldm(ia_w, r4, s4, s7); 691 692 __ addi(r4, r1, Operand(offsetof(F, a))); 693 __ vstm(ia_w, r4, s6, s7); 694 __ vstm(ia_w, r4, s0, s5); 695 696 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); 697 698 CodeDesc desc; 699 assm.GetCode(&desc); 700 Object* code = isolate->heap()->CreateCode( 701 desc, 702 Code::ComputeFlags(Code::STUB), 703 Handle<Code>())->ToObjectChecked(); 704 CHECK(code->IsCode()); 705#ifdef DEBUG 706 Code::cast(code)->Print(); 707#endif 708 F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry()); 709 d.a = 1.1; 710 d.b = 2.2; 711 d.c = 3.3; 712 d.d = 4.4; 713 d.e = 5.5; 714 d.f = 6.6; 715 d.g = 7.7; 716 d.h = 8.8; 717 718 f.a = 1.0; 719 f.b = 2.0; 720 f.c = 3.0; 721 f.d = 4.0; 722 f.e = 5.0; 723 f.f = 6.0; 724 f.g = 7.0; 725 f.h = 8.0; 726 727 Object* dummy = CALL_GENERATED_CODE(isolate, fn, &d, &f, 0, 0, 0); 728 USE(dummy); 729 730 CHECK_EQ(7.7, d.a); 731 CHECK_EQ(8.8, d.b); 732 CHECK_EQ(1.1, d.c); 733 CHECK_EQ(2.2, d.d); 734 CHECK_EQ(3.3, d.e); 735 CHECK_EQ(4.4, d.f); 736 CHECK_EQ(5.5, d.g); 737 CHECK_EQ(6.6, d.h); 738 739 CHECK_EQ(7.0, f.a); 740 CHECK_EQ(8.0, f.b); 741 CHECK_EQ(1.0, f.c); 742 CHECK_EQ(2.0, f.d); 743 CHECK_EQ(3.0, f.e); 744 CHECK_EQ(4.0, f.f); 745 CHECK_EQ(5.0, f.g); 746 CHECK_EQ(6.0, f.h); 747 } 748} 749 750 751TEST(9) { 752 // Test VFP multi load/store with ia. 753 CcTest::InitializeVM(); 754 Isolate* isolate = CcTest::i_isolate(); 755 HandleScope scope(isolate); 756 757 typedef struct { 758 double a; 759 double b; 760 double c; 761 double d; 762 double e; 763 double f; 764 double g; 765 double h; 766 } D; 767 D d; 768 769 typedef struct { 770 float a; 771 float b; 772 float c; 773 float d; 774 float e; 775 float f; 776 float g; 777 float h; 778 } F; 779 F f; 780 781 // Create a function that uses vldm/vstm to move some double and 782 // single precision values around in memory. 783 Assembler assm(isolate, NULL, 0); 784 785 if (CpuFeatures::IsSupported(VFP2)) { 786 CpuFeatures::Scope scope(VFP2); 787 788 __ mov(ip, Operand(sp)); 789 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); 790 __ sub(fp, ip, Operand(4)); 791 792 __ addi(r4, r0, Operand(offsetof(D, a))); 793 __ vldm(ia, r4, d0, d3); 794 __ addi(r4, r4, Operand(4 * 8)); 795 __ vldm(ia, r4, d4, d7); 796 797 __ addi(r4, r0, Operand(offsetof(D, a))); 798 __ vstm(ia, r4, d6, d7); 799 __ addi(r4, r4, Operand(2 * 8)); 800 __ vstm(ia, r4, d0, d5); 801 802 __ addi(r4, r1, Operand(offsetof(F, a))); 803 __ vldm(ia, r4, s0, s3); 804 __ addi(r4, r4, Operand(4 * 4)); 805 __ vldm(ia, r4, s4, s7); 806 807 __ addi(r4, r1, Operand(offsetof(F, a))); 808 __ vstm(ia, r4, s6, s7); 809 __ addi(r4, r4, Operand(2 * 4)); 810 __ vstm(ia, r4, s0, s5); 811 812 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); 813 814 CodeDesc desc; 815 assm.GetCode(&desc); 816 Object* code = isolate->heap()->CreateCode( 817 desc, 818 Code::ComputeFlags(Code::STUB), 819 Handle<Code>())->ToObjectChecked(); 820 CHECK(code->IsCode()); 821#ifdef DEBUG 822 Code::cast(code)->Print(); 823#endif 824 F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry()); 825 d.a = 1.1; 826 d.b = 2.2; 827 d.c = 3.3; 828 d.d = 4.4; 829 d.e = 5.5; 830 d.f = 6.6; 831 d.g = 7.7; 832 d.h = 8.8; 833 834 f.a = 1.0; 835 f.b = 2.0; 836 f.c = 3.0; 837 f.d = 4.0; 838 f.e = 5.0; 839 f.f = 6.0; 840 f.g = 7.0; 841 f.h = 8.0; 842 843 Object* dummy = CALL_GENERATED_CODE(isolate, fn, &d, &f, 0, 0, 0); 844 USE(dummy); 845 846 CHECK_EQ(7.7, d.a); 847 CHECK_EQ(8.8, d.b); 848 CHECK_EQ(1.1, d.c); 849 CHECK_EQ(2.2, d.d); 850 CHECK_EQ(3.3, d.e); 851 CHECK_EQ(4.4, d.f); 852 CHECK_EQ(5.5, d.g); 853 CHECK_EQ(6.6, d.h); 854 855 CHECK_EQ(7.0, f.a); 856 CHECK_EQ(8.0, f.b); 857 CHECK_EQ(1.0, f.c); 858 CHECK_EQ(2.0, f.d); 859 CHECK_EQ(3.0, f.e); 860 CHECK_EQ(4.0, f.f); 861 CHECK_EQ(5.0, f.g); 862 CHECK_EQ(6.0, f.h); 863 } 864} 865 866 867TEST(10) { 868 // Test VFP multi load/store with db_w. 869 CcTest::InitializeVM(); 870 Isolate* isolate = CcTest::i_isolate(); 871 HandleScope scope(isolate); 872 873 typedef struct { 874 double a; 875 double b; 876 double c; 877 double d; 878 double e; 879 double f; 880 double g; 881 double h; 882 } D; 883 D d; 884 885 typedef struct { 886 float a; 887 float b; 888 float c; 889 float d; 890 float e; 891 float f; 892 float g; 893 float h; 894 } F; 895 F f; 896 897 // Create a function that uses vldm/vstm to move some double and 898 // single precision values around in memory. 899 Assembler assm(isolate, NULL, 0); 900 901 if (CpuFeatures::IsSupported(VFP2)) { 902 CpuFeatures::Scope scope(VFP2); 903 904 __ mov(ip, Operand(sp)); 905 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); 906 __ sub(fp, ip, Operand(4)); 907 908 __ addi(r4, r0, Operand(offsetof(D, h) + 8)); 909 __ vldm(db_w, r4, d4, d7); 910 __ vldm(db_w, r4, d0, d3); 911 912 __ addi(r4, r0, Operand(offsetof(D, h) + 8)); 913 __ vstm(db_w, r4, d0, d5); 914 __ vstm(db_w, r4, d6, d7); 915 916 __ addi(r4, r1, Operand(offsetof(F, h) + 4)); 917 __ vldm(db_w, r4, s4, s7); 918 __ vldm(db_w, r4, s0, s3); 919 920 __ addi(r4, r1, Operand(offsetof(F, h) + 4)); 921 __ vstm(db_w, r4, s0, s5); 922 __ vstm(db_w, r4, s6, s7); 923 924 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); 925 926 CodeDesc desc; 927 assm.GetCode(&desc); 928 Object* code = isolate->heap()->CreateCode( 929 desc, 930 Code::ComputeFlags(Code::STUB), 931 Handle<Code>())->ToObjectChecked(); 932 CHECK(code->IsCode()); 933#ifdef DEBUG 934 Code::cast(code)->Print(); 935#endif 936 F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry()); 937 d.a = 1.1; 938 d.b = 2.2; 939 d.c = 3.3; 940 d.d = 4.4; 941 d.e = 5.5; 942 d.f = 6.6; 943 d.g = 7.7; 944 d.h = 8.8; 945 946 f.a = 1.0; 947 f.b = 2.0; 948 f.c = 3.0; 949 f.d = 4.0; 950 f.e = 5.0; 951 f.f = 6.0; 952 f.g = 7.0; 953 f.h = 8.0; 954 955 Object* dummy = CALL_GENERATED_CODE(isolate, fn, &d, &f, 0, 0, 0); 956 USE(dummy); 957 958 CHECK_EQ(7.7, d.a); 959 CHECK_EQ(8.8, d.b); 960 CHECK_EQ(1.1, d.c); 961 CHECK_EQ(2.2, d.d); 962 CHECK_EQ(3.3, d.e); 963 CHECK_EQ(4.4, d.f); 964 CHECK_EQ(5.5, d.g); 965 CHECK_EQ(6.6, d.h); 966 967 CHECK_EQ(7.0, f.a); 968 CHECK_EQ(8.0, f.b); 969 CHECK_EQ(1.0, f.c); 970 CHECK_EQ(2.0, f.d); 971 CHECK_EQ(3.0, f.e); 972 CHECK_EQ(4.0, f.f); 973 CHECK_EQ(5.0, f.g); 974 CHECK_EQ(6.0, f.h); 975 } 976} 977 978 979TEST(11) { 980 // Test instructions using the carry flag. 981 CcTest::InitializeVM(); 982 Isolate* isolate = CcTest::i_isolate(); 983 HandleScope scope(isolate); 984 985 typedef struct { 986 int32_t a; 987 int32_t b; 988 int32_t c; 989 int32_t d; 990 } I; 991 I i; 992 993 i.a = 0xabcd0001; 994 i.b = 0xabcd0000; 995 996 Assembler assm(isolate, NULL, 0); 997 998 // Test HeapObject untagging. 999 __ ldr(r1, MemOperand(r0, offsetof(I, a))); 1000 __ mov(r1, Operand(r1, ASR, 1), SetCC); 1001 __ adc(r1, r1, Operand(r1), LeaveCC, cs); 1002 __ str(r1, MemOperand(r0, offsetof(I, a))); 1003 1004 __ ldr(r2, MemOperand(r0, offsetof(I, b))); 1005 __ mov(r2, Operand(r2, ASR, 1), SetCC); 1006 __ adc(r2, r2, Operand(r2), LeaveCC, cs); 1007 __ str(r2, MemOperand(r0, offsetof(I, b))); 1008 1009 // Test corner cases. 1010 __ mov(r1, Operand(0xffffffff)); 1011 __ mov(r2, Operand::Zero()); 1012 __ mov(r3, Operand(r1, ASR, 1), SetCC); // Set the carry. 1013 __ adc(r3, r1, Operand(r2)); 1014 __ str(r3, MemOperand(r0, offsetof(I, c))); 1015 1016 __ mov(r1, Operand(0xffffffff)); 1017 __ mov(r2, Operand::Zero()); 1018 __ mov(r3, Operand(r2, ASR, 1), SetCC); // Unset the carry. 1019 __ adc(r3, r1, Operand(r2)); 1020 __ str(r3, MemOperand(r0, offsetof(I, d))); 1021 1022 __ mov(pc, Operand(lr)); 1023 1024 CodeDesc desc; 1025 assm.GetCode(&desc); 1026 Object* code = isolate->heap()->CreateCode( 1027 desc, 1028 Code::ComputeFlags(Code::STUB), 1029 Handle<Code>())->ToObjectChecked(); 1030 CHECK(code->IsCode()); 1031#ifdef DEBUG 1032 Code::cast(code)->Print(); 1033#endif 1034 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); 1035 Object* dummy = CALL_GENERATED_CODE(isolate, f, &i, 0, 0, 0, 0); 1036 USE(dummy); 1037 1038 CHECK_EQ(0xabcd0001, i.a); 1039 CHECK_EQ(static_cast<int32_t>(0xabcd0000) >> 1, i.b); 1040 CHECK_EQ(0x00000000, i.c); 1041 CHECK_EQ(0xffffffff, i.d); 1042} 1043 1044 1045TEST(12) { 1046 // Test chaining of label usages within instructions (issue 1644). 1047 CcTest::InitializeVM(); 1048 Isolate* isolate = CcTest::i_isolate(); 1049 HandleScope scope(isolate); 1050 1051 Assembler assm(isolate, NULL, 0); 1052 Label target; 1053 __ b(eq, &target); 1054 __ b(ne, &target); 1055 __ bind(&target); 1056 __ nop(); 1057} 1058#endif 1059 1060#undef __ 1061