| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 InitializeVM(); | 222 InitializeVM(); |
| 223 v8::HandleScope scope; | 223 v8::HandleScope scope; |
| 224 | 224 |
| 225 typedef struct { | 225 typedef struct { |
| 226 double a; | 226 double a; |
| 227 double b; | 227 double b; |
| 228 double c; | 228 double c; |
| 229 double d; | 229 double d; |
| 230 double e; | 230 double e; |
| 231 double f; | 231 double f; |
| 232 double g; |
| 233 double h; |
| 232 int i; | 234 int i; |
| 233 float x; | 235 float x; |
| 234 float y; | 236 float y; |
| 235 } T; | 237 } T; |
| 236 T t; | 238 T t; |
| 237 | 239 |
| 238 // Create a function that accepts &t, and loads, manipulates, and stores | 240 // Create a function that accepts &t, and loads, manipulates, and stores |
| 239 // the doubles and floats. | 241 // the doubles and floats. |
| 240 Assembler assm(NULL, 0); | 242 Assembler assm(NULL, 0); |
| 241 Label L, C; | 243 Label L, C; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 // Convert from floating point to integer. | 281 // Convert from floating point to integer. |
| 280 __ vmov(d4, 2.0); | 282 __ vmov(d4, 2.0); |
| 281 __ vcvt_s32_f64(s31, d4); | 283 __ vcvt_s32_f64(s31, d4); |
| 282 __ vstr(s31, r4, OFFSET_OF(T, i)); | 284 __ vstr(s31, r4, OFFSET_OF(T, i)); |
| 283 | 285 |
| 284 // Convert from integer to floating point. | 286 // Convert from integer to floating point. |
| 285 __ mov(lr, Operand(42)); | 287 __ mov(lr, Operand(42)); |
| 286 __ vmov(s31, lr); | 288 __ vmov(s31, lr); |
| 287 __ vcvt_f64_s32(d4, s31); | 289 __ vcvt_f64_s32(d4, s31); |
| 288 __ vstr(d4, r4, OFFSET_OF(T, f)); | 290 __ vstr(d4, r4, OFFSET_OF(T, f)); |
| 291 |
| 292 // Test vabs. |
| 293 __ vldr(d1, r4, OFFSET_OF(T, g)); |
| 294 __ vabs(d0, d1); |
| 295 __ vstr(d0, r4, OFFSET_OF(T, g)); |
| 296 __ vldr(d2, r4, OFFSET_OF(T, h)); |
| 297 __ vabs(d0, d2); |
| 298 __ vstr(d0, r4, OFFSET_OF(T, h)); |
| 299 |
| 289 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); | 300 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); |
| 290 | 301 |
| 291 CodeDesc desc; | 302 CodeDesc desc; |
| 292 assm.GetCode(&desc); | 303 assm.GetCode(&desc); |
| 293 Object* code = HEAP->CreateCode( | 304 Object* code = HEAP->CreateCode( |
| 294 desc, | 305 desc, |
| 295 Code::ComputeFlags(Code::STUB), | 306 Code::ComputeFlags(Code::STUB), |
| 296 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); | 307 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); |
| 297 CHECK(code->IsCode()); | 308 CHECK(code->IsCode()); |
| 298 #ifdef DEBUG | 309 #ifdef DEBUG |
| 299 Code::cast(code)->Print(); | 310 Code::cast(code)->Print(); |
| 300 #endif | 311 #endif |
| 301 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); | 312 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); |
| 302 t.a = 1.5; | 313 t.a = 1.5; |
| 303 t.b = 2.75; | 314 t.b = 2.75; |
| 304 t.c = 17.17; | 315 t.c = 17.17; |
| 305 t.d = 0.0; | 316 t.d = 0.0; |
| 306 t.e = 0.0; | 317 t.e = 0.0; |
| 307 t.f = 0.0; | 318 t.f = 0.0; |
| 319 t.g = -2718.2818; |
| 320 t.h = 31415926.5; |
| 308 t.i = 0; | 321 t.i = 0; |
| 309 t.x = 4.5; | 322 t.x = 4.5; |
| 310 t.y = 9.0; | 323 t.y = 9.0; |
| 311 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); | 324 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); |
| 312 USE(dummy); | 325 USE(dummy); |
| 313 CHECK_EQ(4.5, t.y); | 326 CHECK_EQ(4.5, t.y); |
| 314 CHECK_EQ(9.0, t.x); | 327 CHECK_EQ(9.0, t.x); |
| 315 CHECK_EQ(2, t.i); | 328 CHECK_EQ(2, t.i); |
| 329 CHECK_EQ(2718.2818, t.g); |
| 330 CHECK_EQ(31415926.5, t.h); |
| 316 CHECK_EQ(42.0, t.f); | 331 CHECK_EQ(42.0, t.f); |
| 317 CHECK_EQ(1.0, t.e); | 332 CHECK_EQ(1.0, t.e); |
| 318 CHECK_EQ(1.000000059604644775390625, t.d); | 333 CHECK_EQ(1.000000059604644775390625, t.d); |
| 319 CHECK_EQ(4.25, t.c); | 334 CHECK_EQ(4.25, t.c); |
| 320 CHECK_EQ(4.25, t.b); | 335 CHECK_EQ(4.25, t.b); |
| 321 CHECK_EQ(1.5, t.a); | 336 CHECK_EQ(1.5, t.a); |
| 322 } | 337 } |
| 323 } | 338 } |
| 324 | 339 |
| 325 | 340 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 #endif | 402 #endif |
| 388 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry()); | 403 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry()); |
| 389 int res = reinterpret_cast<int>( | 404 int res = reinterpret_cast<int>( |
| 390 CALL_GENERATED_CODE(f, 0xFFFF, 0, 0, 0, 0)); | 405 CALL_GENERATED_CODE(f, 0xFFFF, 0, 0, 0, 0)); |
| 391 ::printf("f() = %d\n", res); | 406 ::printf("f() = %d\n", res); |
| 392 CHECK_EQ(382, res); | 407 CHECK_EQ(382, res); |
| 393 } | 408 } |
| 394 } | 409 } |
| 395 | 410 |
| 396 | 411 |
| 397 static void TestRoundingMode(int32_t mode, double value, int expected) { | 412 enum VCVTTypes { |
| 413 s32_f64, |
| 414 u32_f64 |
| 415 }; |
| 416 |
| 417 static void TestRoundingMode(VCVTTypes types, |
| 418 VFPRoundingMode mode, |
| 419 double value, |
| 420 int expected, |
| 421 bool expected_exception = false) { |
| 398 InitializeVM(); | 422 InitializeVM(); |
| 399 v8::HandleScope scope; | 423 v8::HandleScope scope; |
| 400 | 424 |
| 401 Assembler assm(NULL, 0); | 425 Assembler assm(NULL, 0); |
| 402 | 426 |
| 403 __ vmrs(r1); | 427 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { |
| 404 // Set custom FPSCR. | 428 CpuFeatures::Scope scope(VFP3); |
| 405 __ bic(r2, r1, Operand(((mode ^ 3) << 22) | 0xf)); | |
| 406 __ orr(r2, r2, Operand(mode << 22)); | |
| 407 __ vmsr(r2); | |
| 408 | 429 |
| 409 // Load value, convert, and move back result to r0. | 430 Label wrong_exception; |
| 410 __ vmov(d1, value); | |
| 411 __ vcvt_s32_f64(s0, d1, Assembler::FPSCRRounding, al); | |
| 412 __ vmov(r0, s0); | |
| 413 | 431 |
| 414 __ mov(pc, Operand(lr)); | 432 __ vmrs(r1); |
| 433 // Set custom FPSCR. |
| 434 __ bic(r2, r1, Operand(kVFPRoundingModeMask | kVFPExceptionMask)); |
| 435 __ orr(r2, r2, Operand(mode)); |
| 436 __ vmsr(r2); |
| 415 | 437 |
| 416 CodeDesc desc; | 438 // Load value, convert, and move back result to r0 if everything went well. |
| 417 assm.GetCode(&desc); | 439 __ vmov(d1, value); |
| 418 Object* code = HEAP->CreateCode( | 440 switch (types) { |
| 419 desc, | 441 case s32_f64: |
| 420 Code::ComputeFlags(Code::STUB), | 442 __ vcvt_s32_f64(s0, d1, kFPSCRRounding); |
| 421 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); | 443 break; |
| 422 CHECK(code->IsCode()); | 444 |
| 445 case u32_f64: |
| 446 __ vcvt_u32_f64(s0, d1, kFPSCRRounding); |
| 447 break; |
| 448 |
| 449 default: |
| 450 UNREACHABLE(); |
| 451 break; |
| 452 } |
| 453 // Check for vfp exceptions |
| 454 __ vmrs(r2); |
| 455 __ tst(r2, Operand(kVFPExceptionMask)); |
| 456 // Check that we behaved as expected. |
| 457 __ b(&wrong_exception, |
| 458 expected_exception ? eq : ne); |
| 459 // There was no exception. Retrieve the result and return. |
| 460 __ vmov(r0, s0); |
| 461 __ mov(pc, Operand(lr)); |
| 462 |
| 463 // The exception behaviour is not what we expected. |
| 464 // Load a special value and return. |
| 465 __ bind(&wrong_exception); |
| 466 __ mov(r0, Operand(11223344)); |
| 467 __ mov(pc, Operand(lr)); |
| 468 |
| 469 CodeDesc desc; |
| 470 assm.GetCode(&desc); |
| 471 Object* code = HEAP->CreateCode( |
| 472 desc, |
| 473 Code::ComputeFlags(Code::STUB), |
| 474 Handle<Object>(HEAP->undefined_value()))->ToObjectChecked(); |
| 475 CHECK(code->IsCode()); |
| 423 #ifdef DEBUG | 476 #ifdef DEBUG |
| 424 Code::cast(code)->Print(); | 477 Code::cast(code)->Print(); |
| 425 #endif | 478 #endif |
| 426 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry()); | 479 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry()); |
| 427 int res = reinterpret_cast<int>( | 480 int res = reinterpret_cast<int>( |
| 428 CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); | 481 CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); |
| 429 ::printf("res = %d\n", res); | 482 ::printf("res = %d\n", res); |
| 430 CHECK_EQ(expected, res); | 483 CHECK_EQ(expected, res); |
| 484 } |
| 431 } | 485 } |
| 432 | 486 |
| 433 | 487 |
| 434 TEST(7) { | 488 TEST(7) { |
| 435 // Test vfp rounding modes. | 489 // Test vfp rounding modes. |
| 436 | 490 |
| 437 // See ARM DDI 0406B Page A2-29. | 491 // s32_f64 (double to integer). |
| 438 enum FPSCRRoungingMode { | |
| 439 RN, // Round to Nearest. | |
| 440 RP, // Round towards Plus Infinity. | |
| 441 RM, // Round towards Minus Infinity. | |
| 442 RZ // Round towards zero. | |
| 443 }; | |
| 444 | 492 |
| 445 if (Isolate::Current()->cpu_features()->IsSupported(VFP3)) { | 493 TestRoundingMode(s32_f64, RN, 0, 0); |
| 446 CpuFeatures::Scope scope(VFP3); | 494 TestRoundingMode(s32_f64, RN, 0.5, 0); |
| 495 TestRoundingMode(s32_f64, RN, -0.5, 0); |
| 496 TestRoundingMode(s32_f64, RN, 1.5, 2); |
| 497 TestRoundingMode(s32_f64, RN, -1.5, -2); |
| 498 TestRoundingMode(s32_f64, RN, 123.7, 124); |
| 499 TestRoundingMode(s32_f64, RN, -123.7, -124); |
| 500 TestRoundingMode(s32_f64, RN, 123456.2, 123456); |
| 501 TestRoundingMode(s32_f64, RN, -123456.2, -123456); |
| 502 TestRoundingMode(s32_f64, RN, static_cast<double>(kMaxInt), kMaxInt); |
| 503 TestRoundingMode(s32_f64, RN, (kMaxInt + 0.49), kMaxInt); |
| 504 TestRoundingMode(s32_f64, RN, (kMaxInt + 1.0), kMaxInt, true); |
| 505 TestRoundingMode(s32_f64, RN, (kMaxInt + 0.5), kMaxInt, true); |
| 506 TestRoundingMode(s32_f64, RN, static_cast<double>(kMinInt), kMinInt); |
| 507 TestRoundingMode(s32_f64, RN, (kMinInt - 0.5), kMinInt); |
| 508 TestRoundingMode(s32_f64, RN, (kMinInt - 1.0), kMinInt, true); |
| 509 TestRoundingMode(s32_f64, RN, (kMinInt - 0.51), kMinInt, true); |
| 447 | 510 |
| 448 TestRoundingMode(RZ, 0.5, 0); | 511 TestRoundingMode(s32_f64, RM, 0, 0); |
| 449 TestRoundingMode(RZ, -0.5, 0); | 512 TestRoundingMode(s32_f64, RM, 0.5, 0); |
| 450 TestRoundingMode(RZ, 123.7, 123); | 513 TestRoundingMode(s32_f64, RM, -0.5, -1); |
| 451 TestRoundingMode(RZ, -123.7, -123); | 514 TestRoundingMode(s32_f64, RM, 123.7, 123); |
| 452 TestRoundingMode(RZ, 123456.2, 123456); | 515 TestRoundingMode(s32_f64, RM, -123.7, -124); |
| 453 TestRoundingMode(RZ, -123456.2, -123456); | 516 TestRoundingMode(s32_f64, RM, 123456.2, 123456); |
| 517 TestRoundingMode(s32_f64, RM, -123456.2, -123457); |
| 518 TestRoundingMode(s32_f64, RM, static_cast<double>(kMaxInt), kMaxInt); |
| 519 TestRoundingMode(s32_f64, RM, (kMaxInt + 0.5), kMaxInt); |
| 520 TestRoundingMode(s32_f64, RM, (kMaxInt + 1.0), kMaxInt, true); |
| 521 TestRoundingMode(s32_f64, RM, static_cast<double>(kMinInt), kMinInt); |
| 522 TestRoundingMode(s32_f64, RM, (kMinInt - 0.5), kMinInt, true); |
| 523 TestRoundingMode(s32_f64, RM, (kMinInt + 0.5), kMinInt); |
| 454 | 524 |
| 455 TestRoundingMode(RM, 0.5, 0); | 525 TestRoundingMode(s32_f64, RZ, 0, 0); |
| 456 TestRoundingMode(RM, -0.5, -1); | 526 TestRoundingMode(s32_f64, RZ, 0.5, 0); |
| 457 TestRoundingMode(RM, 123.7, 123); | 527 TestRoundingMode(s32_f64, RZ, -0.5, 0); |
| 458 TestRoundingMode(RM, -123.7, -124); | 528 TestRoundingMode(s32_f64, RZ, 123.7, 123); |
| 459 TestRoundingMode(RM, 123456.2, 123456); | 529 TestRoundingMode(s32_f64, RZ, -123.7, -123); |
| 460 TestRoundingMode(RM, -123456.2, -123457); | 530 TestRoundingMode(s32_f64, RZ, 123456.2, 123456); |
| 461 } | 531 TestRoundingMode(s32_f64, RZ, -123456.2, -123456); |
| 532 TestRoundingMode(s32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt); |
| 533 TestRoundingMode(s32_f64, RZ, (kMaxInt + 0.5), kMaxInt); |
| 534 TestRoundingMode(s32_f64, RZ, (kMaxInt + 1.0), kMaxInt, true); |
| 535 TestRoundingMode(s32_f64, RZ, static_cast<double>(kMinInt), kMinInt); |
| 536 TestRoundingMode(s32_f64, RZ, (kMinInt - 0.5), kMinInt); |
| 537 TestRoundingMode(s32_f64, RZ, (kMinInt - 1.0), kMinInt, true); |
| 538 |
| 539 |
| 540 // u32_f64 (double to integer). |
| 541 |
| 542 // Negative values. |
| 543 TestRoundingMode(u32_f64, RN, -0.5, 0); |
| 544 TestRoundingMode(u32_f64, RN, -123456.7, 0, true); |
| 545 TestRoundingMode(u32_f64, RN, static_cast<double>(kMinInt), 0, true); |
| 546 TestRoundingMode(u32_f64, RN, kMinInt - 1.0, 0, true); |
| 547 |
| 548 TestRoundingMode(u32_f64, RM, -0.5, 0, true); |
| 549 TestRoundingMode(u32_f64, RM, -123456.7, 0, true); |
| 550 TestRoundingMode(u32_f64, RM, static_cast<double>(kMinInt), 0, true); |
| 551 TestRoundingMode(u32_f64, RM, kMinInt - 1.0, 0, true); |
| 552 |
| 553 TestRoundingMode(u32_f64, RZ, -0.5, 0); |
| 554 TestRoundingMode(u32_f64, RZ, -123456.7, 0, true); |
| 555 TestRoundingMode(u32_f64, RZ, static_cast<double>(kMinInt), 0, true); |
| 556 TestRoundingMode(u32_f64, RZ, kMinInt - 1.0, 0, true); |
| 557 |
| 558 // Positive values. |
| 559 // kMaxInt is the maximum *signed* integer: 0x7fffffff. |
| 560 static const uint32_t kMaxUInt = 0xffffffffu; |
| 561 TestRoundingMode(u32_f64, RZ, 0, 0); |
| 562 TestRoundingMode(u32_f64, RZ, 0.5, 0); |
| 563 TestRoundingMode(u32_f64, RZ, 123.7, 123); |
| 564 TestRoundingMode(u32_f64, RZ, 123456.2, 123456); |
| 565 TestRoundingMode(u32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt); |
| 566 TestRoundingMode(u32_f64, RZ, (kMaxInt + 0.5), kMaxInt); |
| 567 TestRoundingMode(u32_f64, RZ, (kMaxInt + 1.0), |
| 568 static_cast<uint32_t>(kMaxInt) + 1); |
| 569 TestRoundingMode(u32_f64, RZ, (kMaxUInt + 0.5), kMaxUInt); |
| 570 TestRoundingMode(u32_f64, RZ, (kMaxUInt + 1.0), kMaxUInt, true); |
| 571 |
| 572 TestRoundingMode(u32_f64, RM, 0, 0); |
| 573 TestRoundingMode(u32_f64, RM, 0.5, 0); |
| 574 TestRoundingMode(u32_f64, RM, 123.7, 123); |
| 575 TestRoundingMode(u32_f64, RM, 123456.2, 123456); |
| 576 TestRoundingMode(u32_f64, RM, static_cast<double>(kMaxInt), kMaxInt); |
| 577 TestRoundingMode(u32_f64, RM, (kMaxInt + 0.5), kMaxInt); |
| 578 TestRoundingMode(u32_f64, RM, (kMaxInt + 1.0), |
| 579 static_cast<uint32_t>(kMaxInt) + 1); |
| 580 TestRoundingMode(u32_f64, RM, (kMaxUInt + 0.5), kMaxUInt); |
| 581 TestRoundingMode(u32_f64, RM, (kMaxUInt + 1.0), kMaxUInt, true); |
| 582 |
| 583 TestRoundingMode(u32_f64, RN, 0, 0); |
| 584 TestRoundingMode(u32_f64, RN, 0.5, 0); |
| 585 TestRoundingMode(u32_f64, RN, 1.5, 2); |
| 586 TestRoundingMode(u32_f64, RN, 123.7, 124); |
| 587 TestRoundingMode(u32_f64, RN, 123456.2, 123456); |
| 588 TestRoundingMode(u32_f64, RN, static_cast<double>(kMaxInt), kMaxInt); |
| 589 TestRoundingMode(u32_f64, RN, (kMaxInt + 0.49), kMaxInt); |
| 590 TestRoundingMode(u32_f64, RN, (kMaxInt + 0.5), |
| 591 static_cast<uint32_t>(kMaxInt) + 1); |
| 592 TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.49), kMaxUInt); |
| 593 TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.5), kMaxUInt, true); |
| 594 TestRoundingMode(u32_f64, RN, (kMaxUInt + 1.0), kMaxUInt, true); |
| 462 } | 595 } |
| 463 | 596 |
| 464 #undef __ | 597 #undef __ |
| OLD | NEW |