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