OLD | NEW |
---|---|
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
462 Isolate* isolate = Isolate::Current(); | 462 Isolate* isolate = Isolate::Current(); |
463 next_ = isolate->simulator_redirection(); | 463 next_ = isolate->simulator_redirection(); |
464 // TODO(all): Simulator flush I cache | 464 // TODO(all): Simulator flush I cache |
465 isolate->set_simulator_redirection(this); | 465 isolate->set_simulator_redirection(this); |
466 } | 466 } |
467 | 467 |
468 void* address_of_redirect_call() { | 468 void* address_of_redirect_call() { |
469 return reinterpret_cast<void*>(&redirect_call_); | 469 return reinterpret_cast<void*>(&redirect_call_); |
470 } | 470 } |
471 | 471 |
472 void* external_function() { return external_function_; } | 472 template <typename T> |
473 T external_function() { return reinterpret_cast<T>(external_function_); } | |
ulan
2014/03/19 08:53:19
Indentation is off
Alexandre Rames
2014/03/20 09:49:33
Fixing before landing.
| |
473 ExternalReference::Type type() { return type_; } | 474 ExternalReference::Type type() { return type_; } |
474 | 475 |
475 static Redirection* Get(void* external_function, | 476 static Redirection* Get(void* external_function, |
476 ExternalReference::Type type) { | 477 ExternalReference::Type type) { |
477 Isolate* isolate = Isolate::Current(); | 478 Isolate* isolate = Isolate::Current(); |
478 Redirection* current = isolate->simulator_redirection(); | 479 Redirection* current = isolate->simulator_redirection(); |
479 for (; current != NULL; current = current->next_) { | 480 for (; current != NULL; current = current->next_) { |
480 if (current->external_function_ == external_function) { | 481 if (current->external_function_ == external_function) { |
481 ASSERT_EQ(current->type(), type); | 482 ASSERT_EQ(current->type(), type); |
482 return current; | 483 return current; |
483 } | 484 } |
484 } | 485 } |
485 return new Redirection(external_function, type); | 486 return new Redirection(external_function, type); |
486 } | 487 } |
487 | 488 |
488 static Redirection* FromHltInstruction(Instruction* redirect_call) { | 489 static Redirection* FromHltInstruction(Instruction* redirect_call) { |
489 char* addr_of_hlt = reinterpret_cast<char*>(redirect_call); | 490 char* addr_of_hlt = reinterpret_cast<char*>(redirect_call); |
490 char* addr_of_redirection = | 491 char* addr_of_redirection = |
491 addr_of_hlt - OFFSET_OF(Redirection, redirect_call_); | 492 addr_of_hlt - OFFSET_OF(Redirection, redirect_call_); |
492 return reinterpret_cast<Redirection*>(addr_of_redirection); | 493 return reinterpret_cast<Redirection*>(addr_of_redirection); |
493 } | 494 } |
494 | 495 |
495 static void* ReverseRedirection(int64_t reg) { | 496 static void* ReverseRedirection(int64_t reg) { |
496 Redirection* redirection = | 497 Redirection* redirection = |
497 FromHltInstruction(reinterpret_cast<Instruction*>(reg)); | 498 FromHltInstruction(reinterpret_cast<Instruction*>(reg)); |
498 return redirection->external_function(); | 499 return redirection->external_function<void*>(); |
499 } | 500 } |
500 | 501 |
501 private: | 502 private: |
502 void* external_function_; | 503 void* external_function_; |
503 Instruction redirect_call_; | 504 Instruction redirect_call_; |
504 ExternalReference::Type type_; | 505 ExternalReference::Type type_; |
505 Redirection* next_; | 506 Redirection* next_; |
506 }; | 507 }; |
507 | 508 |
508 | 509 |
510 // Calls into the V8 runtime are based on this very simple interface. | |
511 // Note: To be able to return two values from some calls the code in runtime.cc | |
512 // uses the ObjectPair structure. | |
513 // The simulator assumes all runtime calls return two 64-bits values. If they | |
514 // don't, register x1 is clobbered. This is fine because x1 is caller-saved. | |
515 struct ObjectPair { | |
516 int64_t res0; | |
517 int64_t res1; | |
518 }; | |
519 | |
520 | |
521 typedef ObjectPair (*SimulatorRuntimeCall)(int64_t arg0, | |
522 int64_t arg1, | |
523 int64_t arg2, | |
524 int64_t arg3, | |
525 int64_t arg4, | |
526 int64_t arg5, | |
527 int64_t arg6, | |
528 int64_t arg7); | |
529 | |
530 typedef int64_t (*SimulatorRuntimeCompareCall)(double arg1, double arg2); | |
531 typedef double (*SimulatorRuntimeFPFPCall)(double arg1, double arg2); | |
532 typedef double (*SimulatorRuntimeFPCall)(double arg1); | |
533 typedef double (*SimulatorRuntimeFPIntCall)(double arg1, int32_t arg2); | |
534 | |
535 // This signature supports direct call in to API function native callback | |
536 // (refer to InvocationCallback in v8.h). | |
537 typedef void (*SimulatorRuntimeDirectApiCall)(int64_t arg0); | |
538 typedef void (*SimulatorRuntimeProfilingApiCall)(int64_t arg0, void* arg1); | |
539 | |
540 // This signature supports direct call to accessor getter callback. | |
541 typedef void (*SimulatorRuntimeDirectGetterCall)(int64_t arg0, int64_t arg1); | |
542 typedef void (*SimulatorRuntimeProfilingGetterCall)(int64_t arg0, int64_t arg1, | |
543 void* arg2); | |
544 | |
545 void Simulator::DoRuntimeCall(Instruction* instr) { | |
546 Redirection* redirection = Redirection::FromHltInstruction(instr); | |
547 | |
548 // The called C code might itself call simulated code, so any | |
549 // caller-saved registers (including lr) could still be clobbered by a | |
550 // redirected call. | |
551 Instruction* return_address = lr(); | |
552 | |
553 int64_t external = redirection->external_function<int64_t>(); | |
554 | |
555 TraceSim("Call to host function at %p\n", | |
556 redirection->external_function<void*>()); | |
557 | |
558 // SP must be 16-byte-aligned at the call interface. | |
559 bool stack_alignment_exception = ((sp() & 0xf) != 0); | |
560 if (stack_alignment_exception) { | |
561 TraceSim(" with unaligned stack 0x%016" PRIx64 ".\n", sp()); | |
562 FATAL("ALIGNMENT EXCEPTION"); | |
563 } | |
564 | |
565 switch (redirection->type()) { | |
566 default: | |
567 TraceSim("Type: Unknown.\n"); | |
568 UNREACHABLE(); | |
569 break; | |
570 | |
571 case ExternalReference::BUILTIN_CALL: { | |
572 // MaybeObject* f(v8::internal::Arguments). | |
573 TraceSim("Type: BUILTIN_CALL\n"); | |
574 SimulatorRuntimeCall target = | |
575 reinterpret_cast<SimulatorRuntimeCall>(external); | |
576 | |
577 // We don't know how many arguments are being passed, but we can | |
578 // pass 8 without touching the stack. They will be ignored by the | |
579 // host function if they aren't used. | |
580 TraceSim("Arguments: " | |
581 "0x%016" PRIx64 ", 0x%016" PRIx64 ", " | |
582 "0x%016" PRIx64 ", 0x%016" PRIx64 ", " | |
583 "0x%016" PRIx64 ", 0x%016" PRIx64 ", " | |
584 "0x%016" PRIx64 ", 0x%016" PRIx64, | |
585 xreg(0), xreg(1), xreg(2), xreg(3), | |
586 xreg(4), xreg(5), xreg(6), xreg(7)); | |
587 ObjectPair result = target(xreg(0), xreg(1), xreg(2), xreg(3), | |
588 xreg(4), xreg(5), xreg(6), xreg(7)); | |
589 TraceSim("Returned: {0x%" PRIx64 ", 0x%" PRIx64 "}\n", | |
590 result.res0, result.res1); | |
591 #ifdef DEBUG | |
592 CorruptAllCallerSavedCPURegisters(); | |
593 #endif | |
594 set_xreg(0, result.res0); | |
595 set_xreg(1, result.res1); | |
596 break; | |
597 } | |
598 | |
599 case ExternalReference::DIRECT_API_CALL: { | |
600 // void f(v8::FunctionCallbackInfo&) | |
601 TraceSim("Type: DIRECT_API_CALL\n"); | |
602 SimulatorRuntimeDirectApiCall target = | |
603 reinterpret_cast<SimulatorRuntimeDirectApiCall>(external); | |
604 TraceSim("Arguments: 0x%016" PRIx64 "\n", xreg(0)); | |
605 target(xreg(0)); | |
606 TraceSim("No return value."); | |
607 #ifdef DEBUG | |
608 CorruptAllCallerSavedCPURegisters(); | |
609 #endif | |
610 break; | |
611 } | |
612 | |
613 case ExternalReference::BUILTIN_COMPARE_CALL: { | |
614 // int f(double, double) | |
615 TraceSim("Type: BUILTIN_COMPARE_CALL\n"); | |
616 SimulatorRuntimeCompareCall target = | |
617 reinterpret_cast<SimulatorRuntimeCompareCall>(external); | |
618 TraceSim("Arguments: %f, %f\n", dreg(0), dreg(1)); | |
619 int64_t result = target(dreg(0), dreg(1)); | |
620 TraceSim("Returned: %" PRId64 "\n", result); | |
621 #ifdef DEBUG | |
622 CorruptAllCallerSavedCPURegisters(); | |
623 #endif | |
624 set_xreg(0, result); | |
625 break; | |
626 } | |
627 | |
628 case ExternalReference::BUILTIN_FP_CALL: { | |
629 // double f(double) | |
630 TraceSim("Type: BUILTIN_FP_CALL\n"); | |
631 SimulatorRuntimeFPCall target = | |
632 reinterpret_cast<SimulatorRuntimeFPCall>(external); | |
633 TraceSim("Argument: %f\n", dreg(0)); | |
634 double result = target(dreg(0)); | |
635 TraceSim("Returned: %f\n", result); | |
636 #ifdef DEBUG | |
637 CorruptAllCallerSavedCPURegisters(); | |
638 #endif | |
639 set_dreg(0, result); | |
640 break; | |
641 } | |
642 | |
643 case ExternalReference::BUILTIN_FP_FP_CALL: { | |
644 // double f(double, double) | |
645 TraceSim("Type: BUILTIN_FP_FP_CALL\n"); | |
646 SimulatorRuntimeFPFPCall target = | |
647 reinterpret_cast<SimulatorRuntimeFPFPCall>(external); | |
648 TraceSim("Arguments: %f, %f\n", dreg(0), dreg(1)); | |
649 double result = target(dreg(0), dreg(1)); | |
650 TraceSim("Returned: %f\n", result); | |
651 #ifdef DEBUG | |
652 CorruptAllCallerSavedCPURegisters(); | |
653 #endif | |
654 set_dreg(0, result); | |
655 break; | |
656 } | |
657 | |
658 case ExternalReference::BUILTIN_FP_INT_CALL: { | |
659 // double f(double, int) | |
660 TraceSim("Type: BUILTIN_FP_INT_CALL\n"); | |
661 SimulatorRuntimeFPIntCall target = | |
662 reinterpret_cast<SimulatorRuntimeFPIntCall>(external); | |
663 TraceSim("Arguments: %f, %d\n", dreg(0), wreg(0)); | |
664 double result = target(dreg(0), wreg(0)); | |
665 TraceSim("Returned: %f\n", result); | |
666 #ifdef DEBUG | |
667 CorruptAllCallerSavedCPURegisters(); | |
668 #endif | |
669 set_dreg(0, result); | |
670 break; | |
671 } | |
672 | |
673 case ExternalReference::DIRECT_GETTER_CALL: { | |
674 // void f(Local<String> property, PropertyCallbackInfo& info) | |
675 TraceSim("Type: DIRECT_GETTER_CALL\n"); | |
676 SimulatorRuntimeDirectGetterCall target = | |
677 reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external); | |
678 TraceSim("Arguments: 0x%016" PRIx64 ", 0x%016" PRIx64 "\n", | |
679 xreg(0), xreg(1)); | |
680 target(xreg(0), xreg(1)); | |
681 TraceSim("No return value."); | |
682 #ifdef DEBUG | |
683 CorruptAllCallerSavedCPURegisters(); | |
684 #endif | |
685 break; | |
686 } | |
687 | |
688 case ExternalReference::PROFILING_API_CALL: { | |
689 // void f(v8::FunctionCallbackInfo&, v8::FunctionCallback) | |
690 TraceSim("Type: PROFILING_API_CALL\n"); | |
691 SimulatorRuntimeProfilingApiCall target = | |
692 reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external); | |
693 void* arg1 = Redirection::ReverseRedirection(xreg(1)); | |
694 TraceSim("Arguments: 0x%016" PRIx64 ", %p\n", xreg(0), arg1); | |
695 target(xreg(0), arg1); | |
696 TraceSim("No return value."); | |
697 #ifdef DEBUG | |
698 CorruptAllCallerSavedCPURegisters(); | |
699 #endif | |
700 break; | |
701 } | |
702 | |
703 case ExternalReference::PROFILING_GETTER_CALL: { | |
704 // void f(Local<String> property, PropertyCallbackInfo& info, | |
705 // AccessorGetterCallback callback) | |
706 TraceSim("Type: PROFILING_GETTER_CALL\n"); | |
707 SimulatorRuntimeProfilingGetterCall target = | |
708 reinterpret_cast<SimulatorRuntimeProfilingGetterCall>( | |
709 external); | |
710 void* arg2 = Redirection::ReverseRedirection(xreg(2)); | |
711 TraceSim("Arguments: 0x%016" PRIx64 ", 0x%016" PRIx64 ", %p\n", | |
712 xreg(0), xreg(1), arg2); | |
713 target(xreg(0), xreg(1), arg2); | |
714 TraceSim("No return value."); | |
715 #ifdef DEBUG | |
716 CorruptAllCallerSavedCPURegisters(); | |
717 #endif | |
718 break; | |
719 } | |
720 } | |
721 | |
722 set_lr(return_address); | |
723 set_pc(return_address); | |
724 } | |
725 | |
726 | |
509 void* Simulator::RedirectExternalReference(void* external_function, | 727 void* Simulator::RedirectExternalReference(void* external_function, |
510 ExternalReference::Type type) { | 728 ExternalReference::Type type) { |
511 Redirection* redirection = Redirection::Get(external_function, type); | 729 Redirection* redirection = Redirection::Get(external_function, type); |
512 return redirection->address_of_redirect_call(); | 730 return redirection->address_of_redirect_call(); |
513 } | 731 } |
514 | 732 |
515 | 733 |
516 const char* Simulator::xreg_names[] = { | 734 const char* Simulator::xreg_names[] = { |
517 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", | 735 "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", |
518 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", | 736 "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", |
(...skipping 2773 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3292 PrintF("Use 'help' for more information.\n"); | 3510 PrintF("Use 'help' for more information.\n"); |
3293 } | 3511 } |
3294 } | 3512 } |
3295 if (cleared_log_disasm_bit == true) { | 3513 if (cleared_log_disasm_bit == true) { |
3296 set_log_parameters(log_parameters_ | LOG_DISASM); | 3514 set_log_parameters(log_parameters_ | LOG_DISASM); |
3297 } | 3515 } |
3298 } | 3516 } |
3299 } | 3517 } |
3300 | 3518 |
3301 | 3519 |
3302 // Calls into the V8 runtime are based on this very simple interface. | |
3303 // Note: To be able to return two values from some calls the code in runtime.cc | |
3304 // uses the ObjectPair structure. | |
3305 // The simulator assumes all runtime calls return two 64-bits values. If they | |
3306 // don't, register x1 is clobbered. This is fine because x1 is caller-saved. | |
3307 struct ObjectPair { | |
3308 int64_t res0; | |
3309 int64_t res1; | |
3310 }; | |
3311 | |
3312 | |
3313 typedef ObjectPair (*SimulatorRuntimeCall)(int64_t arg0, | |
3314 int64_t arg1, | |
3315 int64_t arg2, | |
3316 int64_t arg3, | |
3317 int64_t arg4, | |
3318 int64_t arg5, | |
3319 int64_t arg6, | |
3320 int64_t arg7); | |
3321 | |
3322 typedef int64_t (*SimulatorRuntimeCompareCall)(double arg1, double arg2); | |
3323 typedef double (*SimulatorRuntimeFPFPCall)(double arg1, double arg2); | |
3324 typedef double (*SimulatorRuntimeFPCall)(double arg1); | |
3325 typedef double (*SimulatorRuntimeFPIntCall)(double arg1, int32_t arg2); | |
3326 | |
3327 // This signature supports direct call in to API function native callback | |
3328 // (refer to InvocationCallback in v8.h). | |
3329 typedef void (*SimulatorRuntimeDirectApiCall)(int64_t arg0); | |
3330 typedef void (*SimulatorRuntimeProfilingApiCall)(int64_t arg0, void* arg1); | |
3331 | |
3332 // This signature supports direct call to accessor getter callback. | |
3333 typedef void (*SimulatorRuntimeDirectGetterCall)(int64_t arg0, int64_t arg1); | |
3334 typedef void (*SimulatorRuntimeProfilingGetterCall)(int64_t arg0, int64_t arg1, | |
3335 void* arg2); | |
3336 | |
3337 void Simulator::VisitException(Instruction* instr) { | 3520 void Simulator::VisitException(Instruction* instr) { |
3338 // Define some colour codes to use for log messages. | 3521 // Define some colour codes to use for log messages. |
3339 // TODO(jbramley): Find a more elegant way of defining these. | 3522 // TODO(jbramley): Find a more elegant way of defining these. |
3340 char const* const clr_normal = (FLAG_log_colour) ? ("\033[m") | 3523 char const* const clr_normal = (FLAG_log_colour) ? ("\033[m") |
3341 : (""); | 3524 : (""); |
3342 char const* const clr_debug_number = (FLAG_log_colour) ? ("\033[1;33m") | 3525 char const* const clr_debug_number = (FLAG_log_colour) ? ("\033[1;33m") |
3343 : (""); | 3526 : (""); |
3344 char const* const clr_debug_message = (FLAG_log_colour) ? ("\033[0;33m") | 3527 char const* const clr_debug_message = (FLAG_log_colour) ? ("\033[0;33m") |
3345 : (""); | 3528 : (""); |
3346 char const* const clr_printf = (FLAG_log_colour) ? ("\033[0;32m") | 3529 char const* const clr_printf = (FLAG_log_colour) ? ("\033[0;32m") |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3414 // - Verify that the unreachable marker is present. | 3597 // - Verify that the unreachable marker is present. |
3415 ASSERT(pc_->Mask(ExceptionMask) == HLT); | 3598 ASSERT(pc_->Mask(ExceptionMask) == HLT); |
3416 ASSERT(pc_->ImmException() == kImmExceptionIsUnreachable); | 3599 ASSERT(pc_->ImmException() == kImmExceptionIsUnreachable); |
3417 // - Skip past the unreachable marker. | 3600 // - Skip past the unreachable marker. |
3418 set_pc(pc_->following()); | 3601 set_pc(pc_->following()); |
3419 | 3602 |
3420 // Check if the debugger should break. | 3603 // Check if the debugger should break. |
3421 if (parameters & BREAK) Debug(); | 3604 if (parameters & BREAK) Debug(); |
3422 | 3605 |
3423 } else if (instr->ImmException() == kImmExceptionIsRedirectedCall) { | 3606 } else if (instr->ImmException() == kImmExceptionIsRedirectedCall) { |
3424 // TODO(all): Extract the call redirection code into a separate | 3607 DoRuntimeCall(instr); |
3425 // function. | |
3426 | |
3427 Redirection* redirection = Redirection::FromHltInstruction(instr); | |
3428 | |
3429 // The called C code might itself call simulated code, so any | |
3430 // caller-saved registers (including lr) could still be clobbered by a | |
3431 // redirected call. | |
3432 Instruction* return_address = lr(); | |
3433 | |
3434 // TODO(jbramley): Make external_function() a template so that we don't | |
3435 // have to explicitly cast the result for each redirection type. | |
3436 int64_t external = | |
3437 reinterpret_cast<int64_t>(redirection->external_function()); | |
3438 | |
3439 TraceSim("Call to host function at %p\n", | |
3440 reinterpret_cast<void*>(redirection->external_function())); | |
3441 | |
3442 // SP must be 16 bytes aligned at the call interface. | |
3443 bool stack_alignment_exception = ((sp() & 0xf) != 0); | |
3444 if (stack_alignment_exception) { | |
3445 TraceSim(" with unaligned stack 0x%016" PRIx64 ".\n", sp()); | |
3446 FATAL("ALIGNMENT EXCEPTION"); | |
3447 } | |
3448 | |
3449 switch (redirection->type()) { | |
3450 default: | |
3451 TraceSim("Type: Unknown.\n"); | |
3452 UNREACHABLE(); | |
3453 break; | |
3454 | |
3455 case ExternalReference::BUILTIN_CALL: { | |
3456 // MaybeObject* f(v8::internal::Arguments). | |
3457 TraceSim("Type: BUILTIN_CALL\n"); | |
3458 SimulatorRuntimeCall target = | |
3459 reinterpret_cast<SimulatorRuntimeCall>(external); | |
3460 | |
3461 // We don't know how many arguments are being passed, but we can | |
3462 // pass 8 without touching the stack. They will be ignored by the | |
3463 // host function if they aren't used. | |
3464 TraceSim("Arguments: " | |
3465 "0x%016" PRIx64 ", 0x%016" PRIx64 ", " | |
3466 "0x%016" PRIx64 ", 0x%016" PRIx64 ", " | |
3467 "0x%016" PRIx64 ", 0x%016" PRIx64 ", " | |
3468 "0x%016" PRIx64 ", 0x%016" PRIx64, | |
3469 xreg(0), xreg(1), xreg(2), xreg(3), | |
3470 xreg(4), xreg(5), xreg(6), xreg(7)); | |
3471 ObjectPair result = target(xreg(0), xreg(1), xreg(2), xreg(3), | |
3472 xreg(4), xreg(5), xreg(6), xreg(7)); | |
3473 TraceSim("Returned: {0x%" PRIx64 ", 0x%" PRIx64"}\n", | |
3474 result.res0, result.res1); | |
3475 #ifdef DEBUG | |
3476 CorruptAllCallerSavedCPURegisters(); | |
3477 #endif | |
3478 set_xreg(0, result.res0); | |
3479 set_xreg(1, result.res1); | |
3480 break; | |
3481 } | |
3482 | |
3483 case ExternalReference::DIRECT_API_CALL: { | |
3484 // void f(v8::FunctionCallbackInfo&) | |
3485 TraceSim("Type: DIRECT_API_CALL\n"); | |
3486 SimulatorRuntimeDirectApiCall target = | |
3487 reinterpret_cast<SimulatorRuntimeDirectApiCall>(external); | |
3488 TraceSim("Arguments: 0x%016" PRIx64 "\n", xreg(0)); | |
3489 target(xreg(0)); | |
3490 TraceSim("No return value."); | |
3491 #ifdef DEBUG | |
3492 CorruptAllCallerSavedCPURegisters(); | |
3493 #endif | |
3494 break; | |
3495 } | |
3496 | |
3497 case ExternalReference::BUILTIN_COMPARE_CALL: { | |
3498 // int f(double, double) | |
3499 TraceSim("Type: BUILTIN_COMPARE_CALL\n"); | |
3500 SimulatorRuntimeCompareCall target = | |
3501 reinterpret_cast<SimulatorRuntimeCompareCall>(external); | |
3502 TraceSim("Arguments: %f, %f\n", dreg(0), dreg(1)); | |
3503 int64_t result = target(dreg(0), dreg(1)); | |
3504 TraceSim("Returned: %" PRId64 "\n", result); | |
3505 #ifdef DEBUG | |
3506 CorruptAllCallerSavedCPURegisters(); | |
3507 #endif | |
3508 set_xreg(0, result); | |
3509 break; | |
3510 } | |
3511 | |
3512 case ExternalReference::BUILTIN_FP_CALL: { | |
3513 // double f(double) | |
3514 TraceSim("Type: BUILTIN_FP_CALL\n"); | |
3515 SimulatorRuntimeFPCall target = | |
3516 reinterpret_cast<SimulatorRuntimeFPCall>(external); | |
3517 TraceSim("Argument: %f\n", dreg(0)); | |
3518 double result = target(dreg(0)); | |
3519 TraceSim("Returned: %f\n", result); | |
3520 #ifdef DEBUG | |
3521 CorruptAllCallerSavedCPURegisters(); | |
3522 #endif | |
3523 set_dreg(0, result); | |
3524 break; | |
3525 } | |
3526 | |
3527 case ExternalReference::BUILTIN_FP_FP_CALL: { | |
3528 // double f(double, double) | |
3529 TraceSim("Type: BUILTIN_FP_FP_CALL\n"); | |
3530 SimulatorRuntimeFPFPCall target = | |
3531 reinterpret_cast<SimulatorRuntimeFPFPCall>(external); | |
3532 TraceSim("Arguments: %f, %f\n", dreg(0), dreg(1)); | |
3533 double result = target(dreg(0), dreg(1)); | |
3534 TraceSim("Returned: %f\n", result); | |
3535 #ifdef DEBUG | |
3536 CorruptAllCallerSavedCPURegisters(); | |
3537 #endif | |
3538 set_dreg(0, result); | |
3539 break; | |
3540 } | |
3541 | |
3542 case ExternalReference::BUILTIN_FP_INT_CALL: { | |
3543 // double f(double, int) | |
3544 TraceSim("Type: BUILTIN_FP_INT_CALL\n"); | |
3545 SimulatorRuntimeFPIntCall target = | |
3546 reinterpret_cast<SimulatorRuntimeFPIntCall>(external); | |
3547 TraceSim("Arguments: %f, %d\n", dreg(0), wreg(0)); | |
3548 double result = target(dreg(0), wreg(0)); | |
3549 TraceSim("Returned: %f\n", result); | |
3550 #ifdef DEBUG | |
3551 CorruptAllCallerSavedCPURegisters(); | |
3552 #endif | |
3553 set_dreg(0, result); | |
3554 break; | |
3555 } | |
3556 | |
3557 case ExternalReference::DIRECT_GETTER_CALL: { | |
3558 // void f(Local<String> property, PropertyCallbackInfo& info) | |
3559 TraceSim("Type: DIRECT_GETTER_CALL\n"); | |
3560 SimulatorRuntimeDirectGetterCall target = | |
3561 reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external); | |
3562 TraceSim("Arguments: 0x%016" PRIx64 ", 0x%016" PRIx64 "\n", | |
3563 xreg(0), xreg(1)); | |
3564 target(xreg(0), xreg(1)); | |
3565 TraceSim("No return value."); | |
3566 #ifdef DEBUG | |
3567 CorruptAllCallerSavedCPURegisters(); | |
3568 #endif | |
3569 break; | |
3570 } | |
3571 | |
3572 case ExternalReference::PROFILING_API_CALL: { | |
3573 // void f(v8::FunctionCallbackInfo&, v8::FunctionCallback) | |
3574 TraceSim("Type: PROFILING_API_CALL\n"); | |
3575 SimulatorRuntimeProfilingApiCall target = | |
3576 reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external); | |
3577 void* arg1 = Redirection::ReverseRedirection(xreg(1)); | |
3578 TraceSim("Arguments: 0x%016" PRIx64 ", %p\n", xreg(0), arg1); | |
3579 target(xreg(0), arg1); | |
3580 TraceSim("No return value."); | |
3581 #ifdef DEBUG | |
3582 CorruptAllCallerSavedCPURegisters(); | |
3583 #endif | |
3584 break; | |
3585 } | |
3586 | |
3587 case ExternalReference::PROFILING_GETTER_CALL: { | |
3588 // void f(Local<String> property, PropertyCallbackInfo& info, | |
3589 // AccessorGetterCallback callback) | |
3590 TraceSim("Type: PROFILING_GETTER_CALL\n"); | |
3591 SimulatorRuntimeProfilingGetterCall target = | |
3592 reinterpret_cast<SimulatorRuntimeProfilingGetterCall>( | |
3593 external); | |
3594 void* arg2 = Redirection::ReverseRedirection(xreg(2)); | |
3595 TraceSim("Arguments: 0x%016" PRIx64 ", 0x%016" PRIx64 ", %p\n", | |
3596 xreg(0), xreg(1), arg2); | |
3597 target(xreg(0), xreg(1), arg2); | |
3598 TraceSim("No return value."); | |
3599 #ifdef DEBUG | |
3600 CorruptAllCallerSavedCPURegisters(); | |
3601 #endif | |
3602 break; | |
3603 } | |
3604 } | |
3605 | |
3606 set_lr(return_address); | |
3607 set_pc(return_address); | |
3608 } else if (instr->ImmException() == kImmExceptionIsPrintf) { | 3608 } else if (instr->ImmException() == kImmExceptionIsPrintf) { |
3609 // Read the argument encoded inline in the instruction stream. | 3609 // Read the argument encoded inline in the instruction stream. |
3610 uint32_t type; | 3610 uint32_t type; |
3611 memcpy(&type, | 3611 memcpy(&type, |
3612 pc_->InstructionAtOffset(kPrintfTypeOffset), | 3612 pc_->InstructionAtOffset(kPrintfTypeOffset), |
3613 sizeof(type)); | 3613 sizeof(type)); |
3614 | 3614 |
3615 const char* format = reg<const char*>(0); | 3615 const char* format = reg<const char*>(0); |
3616 | 3616 |
3617 // Pass all of the relevant PCS registers onto printf. It doesn't | 3617 // Pass all of the relevant PCS registers onto printf. It doesn't |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3655 default: | 3655 default: |
3656 UNIMPLEMENTED(); | 3656 UNIMPLEMENTED(); |
3657 } | 3657 } |
3658 } | 3658 } |
3659 | 3659 |
3660 #endif // USE_SIMULATOR | 3660 #endif // USE_SIMULATOR |
3661 | 3661 |
3662 } } // namespace v8::internal | 3662 } } // namespace v8::internal |
3663 | 3663 |
3664 #endif // V8_TARGET_ARCH_A64 | 3664 #endif // V8_TARGET_ARCH_A64 |
OLD | NEW |