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 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
467 RedoBreakpoints(); | 467 RedoBreakpoints(); |
468 | 468 |
469 #undef COMMAND_SIZE | 469 #undef COMMAND_SIZE |
470 #undef ARG_SIZE | 470 #undef ARG_SIZE |
471 | 471 |
472 #undef STR | 472 #undef STR |
473 #undef XSTR | 473 #undef XSTR |
474 } | 474 } |
475 | 475 |
476 | 476 |
| 477 static bool ICacheMatch(void* one, void* two) { |
| 478 ASSERT((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0); |
| 479 ASSERT((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0); |
| 480 return one == two; |
| 481 } |
| 482 |
| 483 |
| 484 static uint32_t ICacheHash(void* key) { |
| 485 return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2; |
| 486 } |
| 487 |
| 488 |
| 489 static bool AllOnOnePage(uintptr_t start, int size) { |
| 490 intptr_t start_page = (start & ~CachePage::kPageMask); |
| 491 intptr_t end_page = ((start + size) & ~CachePage::kPageMask); |
| 492 return start_page == end_page; |
| 493 } |
| 494 |
| 495 |
| 496 void Simulator::FlushICache(void* start_addr, size_t size) { |
| 497 intptr_t start = reinterpret_cast<intptr_t>(start_addr); |
| 498 int intra_line = (start & CachePage::kLineMask); |
| 499 start -= intra_line; |
| 500 size += intra_line; |
| 501 size = ((size - 1) | CachePage::kLineMask) + 1; |
| 502 int offset = (start & CachePage::kPageMask); |
| 503 while (!AllOnOnePage(start, size - 1)) { |
| 504 int bytes_to_flush = CachePage::kPageSize - offset; |
| 505 FlushOnePage(start, bytes_to_flush); |
| 506 start += bytes_to_flush; |
| 507 size -= bytes_to_flush; |
| 508 ASSERT_EQ(0, start & CachePage::kPageMask); |
| 509 offset = 0; |
| 510 } |
| 511 if (size != 0) { |
| 512 FlushOnePage(start, size); |
| 513 } |
| 514 } |
| 515 |
| 516 |
| 517 CachePage* Simulator::GetCachePage(void* page) { |
| 518 v8::internal::HashMap::Entry* entry = i_cache_->Lookup(page, |
| 519 ICacheHash(page), |
| 520 true); |
| 521 if (entry->value == NULL) { |
| 522 CachePage* new_page = new CachePage(); |
| 523 entry->value = new_page; |
| 524 } |
| 525 return reinterpret_cast<CachePage*>(entry->value); |
| 526 } |
| 527 |
| 528 |
| 529 // Flush from start up to and not including start + size. |
| 530 void Simulator::FlushOnePage(intptr_t start, int size) { |
| 531 ASSERT(size <= CachePage::kPageSize); |
| 532 ASSERT(AllOnOnePage(start, size - 1)); |
| 533 ASSERT((start & CachePage::kLineMask) == 0); |
| 534 ASSERT((size & CachePage::kLineMask) == 0); |
| 535 void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask)); |
| 536 int offset = (start & CachePage::kPageMask); |
| 537 CachePage* cache_page = GetCachePage(page); |
| 538 char* valid_bytemap = cache_page->ValidityByte(offset); |
| 539 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift); |
| 540 } |
| 541 |
| 542 |
| 543 void Simulator::CheckICache(Instr* instr) { |
| 544 #ifdef DEBUG |
| 545 intptr_t address = reinterpret_cast<intptr_t>(instr); |
| 546 void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask)); |
| 547 void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask)); |
| 548 int offset = (address & CachePage::kPageMask); |
| 549 CachePage* cache_page = GetCachePage(page); |
| 550 char* cache_valid_byte = cache_page->ValidityByte(offset); |
| 551 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID); |
| 552 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask); |
| 553 if (cache_hit) { |
| 554 // Check that the data in memory matches the contents of the I-cache. |
| 555 CHECK(memcmp(reinterpret_cast<void*>(instr), |
| 556 cache_page->CachedData(offset), |
| 557 Instr::kInstrSize) == 0); |
| 558 } else { |
| 559 // Cache miss. Load memory into the cache. |
| 560 memcpy(cached_line, line, CachePage::kLineLength); |
| 561 *cache_valid_byte = CachePage::LINE_VALID; |
| 562 } |
| 563 #endif |
| 564 } |
| 565 |
| 566 |
477 // Create one simulator per thread and keep it in thread local storage. | 567 // Create one simulator per thread and keep it in thread local storage. |
478 static v8::internal::Thread::LocalStorageKey simulator_key; | 568 static v8::internal::Thread::LocalStorageKey simulator_key; |
479 | 569 |
480 | 570 |
481 bool Simulator::initialized_ = false; | 571 bool Simulator::initialized_ = false; |
482 | 572 |
483 | 573 |
484 void Simulator::Initialize() { | 574 void Simulator::Initialize() { |
485 if (initialized_) return; | 575 if (initialized_) return; |
486 simulator_key = v8::internal::Thread::CreateThreadLocalKey(); | 576 simulator_key = v8::internal::Thread::CreateThreadLocalKey(); |
487 initialized_ = true; | 577 initialized_ = true; |
488 ::v8::internal::ExternalReference::set_redirector(&RedirectExternalReference); | 578 ::v8::internal::ExternalReference::set_redirector(&RedirectExternalReference); |
489 } | 579 } |
490 | 580 |
491 | 581 |
| 582 v8::internal::HashMap* Simulator::i_cache_ = NULL; |
| 583 |
| 584 |
492 Simulator::Simulator() { | 585 Simulator::Simulator() { |
| 586 if (i_cache_ == NULL) { |
| 587 i_cache_ = new v8::internal::HashMap(&ICacheMatch); |
| 588 } |
493 Initialize(); | 589 Initialize(); |
494 // Setup simulator support first. Some of this information is needed to | 590 // Setup simulator support first. Some of this information is needed to |
495 // setup the architecture state. | 591 // setup the architecture state. |
496 size_t stack_size = 1 * 1024*1024; // allocate 1MB for stack | 592 size_t stack_size = 1 * 1024*1024; // allocate 1MB for stack |
497 stack_ = reinterpret_cast<char*>(malloc(stack_size)); | 593 stack_ = reinterpret_cast<char*>(malloc(stack_size)); |
498 pc_modified_ = false; | 594 pc_modified_ = false; |
499 icount_ = 0; | 595 icount_ = 0; |
500 break_pc_ = NULL; | 596 break_pc_ = NULL; |
501 break_instr_ = 0; | 597 break_instr_ = 0; |
502 | 598 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
547 // reference to a swi (software-interrupt) instruction that is handled by | 643 // reference to a swi (software-interrupt) instruction that is handled by |
548 // the simulator. We write the original destination of the jump just at a known | 644 // the simulator. We write the original destination of the jump just at a known |
549 // offset from the swi instruction so the simulator knows what to call. | 645 // offset from the swi instruction so the simulator knows what to call. |
550 class Redirection { | 646 class Redirection { |
551 public: | 647 public: |
552 Redirection(void* external_function, bool fp_return) | 648 Redirection(void* external_function, bool fp_return) |
553 : external_function_(external_function), | 649 : external_function_(external_function), |
554 swi_instruction_((AL << 28) | (0xf << 24) | call_rt_redirected), | 650 swi_instruction_((AL << 28) | (0xf << 24) | call_rt_redirected), |
555 fp_return_(fp_return), | 651 fp_return_(fp_return), |
556 next_(list_) { | 652 next_(list_) { |
| 653 Simulator::current()-> |
| 654 FlushICache(reinterpret_cast<void*>(&swi_instruction_), |
| 655 Instr::kInstrSize); |
557 list_ = this; | 656 list_ = this; |
558 } | 657 } |
559 | 658 |
560 void* address_of_swi_instruction() { | 659 void* address_of_swi_instruction() { |
561 return reinterpret_cast<void*>(&swi_instruction_); | 660 return reinterpret_cast<void*>(&swi_instruction_); |
562 } | 661 } |
563 | 662 |
564 void* external_function() { return external_function_; } | 663 void* external_function() { return external_function_; } |
565 bool fp_return() { return fp_return_; } | 664 bool fp_return() { return fp_return_; } |
566 | 665 |
(...skipping 1768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2335 break; | 2434 break; |
2336 } | 2435 } |
2337 } else { | 2436 } else { |
2338 UNIMPLEMENTED(); // Not used by V8. | 2437 UNIMPLEMENTED(); // Not used by V8. |
2339 } | 2438 } |
2340 } | 2439 } |
2341 | 2440 |
2342 | 2441 |
2343 // Executes the current instruction. | 2442 // Executes the current instruction. |
2344 void Simulator::InstructionDecode(Instr* instr) { | 2443 void Simulator::InstructionDecode(Instr* instr) { |
| 2444 CheckICache(instr); |
2345 pc_modified_ = false; | 2445 pc_modified_ = false; |
2346 if (::v8::internal::FLAG_trace_sim) { | 2446 if (::v8::internal::FLAG_trace_sim) { |
2347 disasm::NameConverter converter; | 2447 disasm::NameConverter converter; |
2348 disasm::Disassembler dasm(converter); | 2448 disasm::Disassembler dasm(converter); |
2349 // use a reasonably large buffer | 2449 // use a reasonably large buffer |
2350 v8::internal::EmbeddedVector<char, 256> buffer; | 2450 v8::internal::EmbeddedVector<char, 256> buffer; |
2351 dasm.InstructionDecode(buffer, | 2451 dasm.InstructionDecode(buffer, |
2352 reinterpret_cast<byte*>(instr)); | 2452 reinterpret_cast<byte*>(instr)); |
2353 PrintF(" 0x%08x %s\n", instr, buffer.start()); | 2453 PrintF(" 0x%08x %s\n", instr, buffer.start()); |
2354 } | 2454 } |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2529 | 2629 |
2530 | 2630 |
2531 uintptr_t Simulator::PopAddress() { | 2631 uintptr_t Simulator::PopAddress() { |
2532 int current_sp = get_register(sp); | 2632 int current_sp = get_register(sp); |
2533 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp); | 2633 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp); |
2534 uintptr_t address = *stack_slot; | 2634 uintptr_t address = *stack_slot; |
2535 set_register(sp, current_sp + sizeof(uintptr_t)); | 2635 set_register(sp, current_sp + sizeof(uintptr_t)); |
2536 return address; | 2636 return address; |
2537 } | 2637 } |
2538 | 2638 |
2539 | |
2540 } } // namespace assembler::arm | 2639 } } // namespace assembler::arm |
2541 | 2640 |
2542 #endif // __arm__ | 2641 #endif // __arm__ |
OLD | NEW |