Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Side by Side Diff: src/arm/simulator-arm.cc

Issue 6685088: Merge isolates to bleeding_edge. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/simulator-arm.h ('k') | src/arm/stub-cache-arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 // Only build the simulator if not compiling for real ARM hardware. 42 // Only build the simulator if not compiling for real ARM hardware.
43 namespace v8 { 43 namespace v8 {
44 namespace internal { 44 namespace internal {
45 45
46 // This macro provides a platform independent use of sscanf. The reason for 46 // This macro provides a platform independent use of sscanf. The reason for
47 // SScanF not being implemented in a platform independent way through 47 // SScanF not being implemented in a platform independent way through
48 // ::v8::internal::OS in the same way as SNPrintF is that the 48 // ::v8::internal::OS in the same way as SNPrintF is that the
49 // Windows C Run-Time Library does not provide vsscanf. 49 // Windows C Run-Time Library does not provide vsscanf.
50 #define SScanF sscanf // NOLINT 50 #define SScanF sscanf // NOLINT
51 51
52 // The Debugger class is used by the simulator while debugging simulated ARM 52 // The ArmDebugger class is used by the simulator while debugging simulated ARM
53 // code. 53 // code.
54 class Debugger { 54 class ArmDebugger {
55 public: 55 public:
56 explicit Debugger(Simulator* sim); 56 explicit ArmDebugger(Simulator* sim);
57 ~Debugger(); 57 ~ArmDebugger();
58 58
59 void Stop(Instruction* instr); 59 void Stop(Instruction* instr);
60 void Debug(); 60 void Debug();
61 61
62 private: 62 private:
63 static const Instr kBreakpointInstr = 63 static const Instr kBreakpointInstr =
64 (al | (7*B25) | (1*B24) | kBreakpoint); 64 (al | (7*B25) | (1*B24) | kBreakpoint);
65 static const Instr kNopInstr = (al | (13*B21)); 65 static const Instr kNopInstr = (al | (13*B21));
66 66
67 Simulator* sim_; 67 Simulator* sim_;
68 68
69 int32_t GetRegisterValue(int regnum); 69 int32_t GetRegisterValue(int regnum);
70 double GetVFPDoubleRegisterValue(int regnum); 70 double GetVFPDoubleRegisterValue(int regnum);
71 bool GetValue(const char* desc, int32_t* value); 71 bool GetValue(const char* desc, int32_t* value);
72 bool GetVFPSingleValue(const char* desc, float* value); 72 bool GetVFPSingleValue(const char* desc, float* value);
73 bool GetVFPDoubleValue(const char* desc, double* value); 73 bool GetVFPDoubleValue(const char* desc, double* value);
74 74
75 // Set or delete a breakpoint. Returns true if successful. 75 // Set or delete a breakpoint. Returns true if successful.
76 bool SetBreakpoint(Instruction* breakpc); 76 bool SetBreakpoint(Instruction* breakpc);
77 bool DeleteBreakpoint(Instruction* breakpc); 77 bool DeleteBreakpoint(Instruction* breakpc);
78 78
79 // Undo and redo all breakpoints. This is needed to bracket disassembly and 79 // Undo and redo all breakpoints. This is needed to bracket disassembly and
80 // execution to skip past breakpoints when run from the debugger. 80 // execution to skip past breakpoints when run from the debugger.
81 void UndoBreakpoints(); 81 void UndoBreakpoints();
82 void RedoBreakpoints(); 82 void RedoBreakpoints();
83 }; 83 };
84 84
85 85
86 Debugger::Debugger(Simulator* sim) { 86 ArmDebugger::ArmDebugger(Simulator* sim) {
87 sim_ = sim; 87 sim_ = sim;
88 } 88 }
89 89
90 90
91 Debugger::~Debugger() { 91 ArmDebugger::~ArmDebugger() {
92 } 92 }
93 93
94 94
95 95
96 #ifdef GENERATED_CODE_COVERAGE 96 #ifdef GENERATED_CODE_COVERAGE
97 static FILE* coverage_log = NULL; 97 static FILE* coverage_log = NULL;
98 98
99 99
100 static void InitializeCoverage() { 100 static void InitializeCoverage() {
101 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG"); 101 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
102 if (file_name != NULL) { 102 if (file_name != NULL) {
103 coverage_log = fopen(file_name, "aw+"); 103 coverage_log = fopen(file_name, "aw+");
104 } 104 }
105 } 105 }
106 106
107 107
108 void Debugger::Stop(Instruction* instr) { 108 void ArmDebugger::Stop(Instruction* instr) {
109 // Get the stop code. 109 // Get the stop code.
110 uint32_t code = instr->SvcValue() & kStopCodeMask; 110 uint32_t code = instr->SvcValue() & kStopCodeMask;
111 // Retrieve the encoded address, which comes just after this stop. 111 // Retrieve the encoded address, which comes just after this stop.
112 char** msg_address = 112 char** msg_address =
113 reinterpret_cast<char**>(sim_->get_pc() + Instruction::kInstrSize); 113 reinterpret_cast<char**>(sim_->get_pc() + Instruction::kInstrSize);
114 char* msg = *msg_address; 114 char* msg = *msg_address;
115 ASSERT(msg != NULL); 115 ASSERT(msg != NULL);
116 116
117 // Update this stop description. 117 // Update this stop description.
118 if (isWatchedStop(code) && !watched_stops[code].desc) { 118 if (isWatchedStop(code) && !watched_stops[code].desc) {
(...skipping 11 matching lines...) Expand all
130 } 130 }
131 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize); 131 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize);
132 } 132 }
133 133
134 #else // ndef GENERATED_CODE_COVERAGE 134 #else // ndef GENERATED_CODE_COVERAGE
135 135
136 static void InitializeCoverage() { 136 static void InitializeCoverage() {
137 } 137 }
138 138
139 139
140 void Debugger::Stop(Instruction* instr) { 140 void ArmDebugger::Stop(Instruction* instr) {
141 // Get the stop code. 141 // Get the stop code.
142 uint32_t code = instr->SvcValue() & kStopCodeMask; 142 uint32_t code = instr->SvcValue() & kStopCodeMask;
143 // Retrieve the encoded address, which comes just after this stop. 143 // Retrieve the encoded address, which comes just after this stop.
144 char* msg = *reinterpret_cast<char**>(sim_->get_pc() 144 char* msg = *reinterpret_cast<char**>(sim_->get_pc()
145 + Instruction::kInstrSize); 145 + Instruction::kInstrSize);
146 // Update this stop description. 146 // Update this stop description.
147 if (sim_->isWatchedStop(code) && !sim_->watched_stops[code].desc) { 147 if (sim_->isWatchedStop(code) && !sim_->watched_stops[code].desc) {
148 sim_->watched_stops[code].desc = msg; 148 sim_->watched_stops[code].desc = msg;
149 } 149 }
150 // Print the stop message and code if it is not the default code. 150 // Print the stop message and code if it is not the default code.
151 if (code != kMaxStopCode) { 151 if (code != kMaxStopCode) {
152 PrintF("Simulator hit stop %u: %s\n", code, msg); 152 PrintF("Simulator hit stop %u: %s\n", code, msg);
153 } else { 153 } else {
154 PrintF("Simulator hit %s\n", msg); 154 PrintF("Simulator hit %s\n", msg);
155 } 155 }
156 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize); 156 sim_->set_pc(sim_->get_pc() + 2 * Instruction::kInstrSize);
157 Debug(); 157 Debug();
158 } 158 }
159 #endif 159 #endif
160 160
161 161
162 int32_t Debugger::GetRegisterValue(int regnum) { 162 int32_t ArmDebugger::GetRegisterValue(int regnum) {
163 if (regnum == kPCRegister) { 163 if (regnum == kPCRegister) {
164 return sim_->get_pc(); 164 return sim_->get_pc();
165 } else { 165 } else {
166 return sim_->get_register(regnum); 166 return sim_->get_register(regnum);
167 } 167 }
168 } 168 }
169 169
170 170
171 double Debugger::GetVFPDoubleRegisterValue(int regnum) { 171 double ArmDebugger::GetVFPDoubleRegisterValue(int regnum) {
172 return sim_->get_double_from_d_register(regnum); 172 return sim_->get_double_from_d_register(regnum);
173 } 173 }
174 174
175 175
176 bool Debugger::GetValue(const char* desc, int32_t* value) { 176 bool ArmDebugger::GetValue(const char* desc, int32_t* value) {
177 int regnum = Registers::Number(desc); 177 int regnum = Registers::Number(desc);
178 if (regnum != kNoRegister) { 178 if (regnum != kNoRegister) {
179 *value = GetRegisterValue(regnum); 179 *value = GetRegisterValue(regnum);
180 return true; 180 return true;
181 } else { 181 } else {
182 if (strncmp(desc, "0x", 2) == 0) { 182 if (strncmp(desc, "0x", 2) == 0) {
183 return SScanF(desc + 2, "%x", reinterpret_cast<uint32_t*>(value)) == 1; 183 return SScanF(desc + 2, "%x", reinterpret_cast<uint32_t*>(value)) == 1;
184 } else { 184 } else {
185 return SScanF(desc, "%u", reinterpret_cast<uint32_t*>(value)) == 1; 185 return SScanF(desc, "%u", reinterpret_cast<uint32_t*>(value)) == 1;
186 } 186 }
187 } 187 }
188 return false; 188 return false;
189 } 189 }
190 190
191 191
192 bool Debugger::GetVFPSingleValue(const char* desc, float* value) { 192 bool ArmDebugger::GetVFPSingleValue(const char* desc, float* value) {
193 bool is_double; 193 bool is_double;
194 int regnum = VFPRegisters::Number(desc, &is_double); 194 int regnum = VFPRegisters::Number(desc, &is_double);
195 if (regnum != kNoRegister && !is_double) { 195 if (regnum != kNoRegister && !is_double) {
196 *value = sim_->get_float_from_s_register(regnum); 196 *value = sim_->get_float_from_s_register(regnum);
197 return true; 197 return true;
198 } 198 }
199 return false; 199 return false;
200 } 200 }
201 201
202 202
203 bool Debugger::GetVFPDoubleValue(const char* desc, double* value) { 203 bool ArmDebugger::GetVFPDoubleValue(const char* desc, double* value) {
204 bool is_double; 204 bool is_double;
205 int regnum = VFPRegisters::Number(desc, &is_double); 205 int regnum = VFPRegisters::Number(desc, &is_double);
206 if (regnum != kNoRegister && is_double) { 206 if (regnum != kNoRegister && is_double) {
207 *value = sim_->get_double_from_d_register(regnum); 207 *value = sim_->get_double_from_d_register(regnum);
208 return true; 208 return true;
209 } 209 }
210 return false; 210 return false;
211 } 211 }
212 212
213 213
214 bool Debugger::SetBreakpoint(Instruction* breakpc) { 214 bool ArmDebugger::SetBreakpoint(Instruction* breakpc) {
215 // Check if a breakpoint can be set. If not return without any side-effects. 215 // Check if a breakpoint can be set. If not return without any side-effects.
216 if (sim_->break_pc_ != NULL) { 216 if (sim_->break_pc_ != NULL) {
217 return false; 217 return false;
218 } 218 }
219 219
220 // Set the breakpoint. 220 // Set the breakpoint.
221 sim_->break_pc_ = breakpc; 221 sim_->break_pc_ = breakpc;
222 sim_->break_instr_ = breakpc->InstructionBits(); 222 sim_->break_instr_ = breakpc->InstructionBits();
223 // Not setting the breakpoint instruction in the code itself. It will be set 223 // Not setting the breakpoint instruction in the code itself. It will be set
224 // when the debugger shell continues. 224 // when the debugger shell continues.
225 return true; 225 return true;
226 } 226 }
227 227
228 228
229 bool Debugger::DeleteBreakpoint(Instruction* breakpc) { 229 bool ArmDebugger::DeleteBreakpoint(Instruction* breakpc) {
230 if (sim_->break_pc_ != NULL) { 230 if (sim_->break_pc_ != NULL) {
231 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); 231 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
232 } 232 }
233 233
234 sim_->break_pc_ = NULL; 234 sim_->break_pc_ = NULL;
235 sim_->break_instr_ = 0; 235 sim_->break_instr_ = 0;
236 return true; 236 return true;
237 } 237 }
238 238
239 239
240 void Debugger::UndoBreakpoints() { 240 void ArmDebugger::UndoBreakpoints() {
241 if (sim_->break_pc_ != NULL) { 241 if (sim_->break_pc_ != NULL) {
242 sim_->break_pc_->SetInstructionBits(sim_->break_instr_); 242 sim_->break_pc_->SetInstructionBits(sim_->break_instr_);
243 } 243 }
244 } 244 }
245 245
246 246
247 void Debugger::RedoBreakpoints() { 247 void ArmDebugger::RedoBreakpoints() {
248 if (sim_->break_pc_ != NULL) { 248 if (sim_->break_pc_ != NULL) {
249 sim_->break_pc_->SetInstructionBits(kBreakpointInstr); 249 sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
250 } 250 }
251 } 251 }
252 252
253 253
254 void Debugger::Debug() { 254 void ArmDebugger::Debug() {
255 intptr_t last_pc = -1; 255 intptr_t last_pc = -1;
256 bool done = false; 256 bool done = false;
257 257
258 #define COMMAND_SIZE 63 258 #define COMMAND_SIZE 63
259 #define ARG_SIZE 255 259 #define ARG_SIZE 255
260 260
261 #define STR(a) #a 261 #define STR(a) #a
262 #define XSTR(a) STR(a) 262 #define XSTR(a) STR(a)
263 263
264 char cmd[COMMAND_SIZE + 1]; 264 char cmd[COMMAND_SIZE + 1];
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after
532 PrintF(" set a break point on the address\n"); 532 PrintF(" set a break point on the address\n");
533 PrintF("del\n"); 533 PrintF("del\n");
534 PrintF(" delete the breakpoint\n"); 534 PrintF(" delete the breakpoint\n");
535 PrintF("trace (alias 't')\n"); 535 PrintF("trace (alias 't')\n");
536 PrintF(" toogle the tracing of all executed statements\n"); 536 PrintF(" toogle the tracing of all executed statements\n");
537 PrintF("stop feature:\n"); 537 PrintF("stop feature:\n");
538 PrintF(" Description:\n"); 538 PrintF(" Description:\n");
539 PrintF(" Stops are debug instructions inserted by\n"); 539 PrintF(" Stops are debug instructions inserted by\n");
540 PrintF(" the Assembler::stop() function.\n"); 540 PrintF(" the Assembler::stop() function.\n");
541 PrintF(" When hitting a stop, the Simulator will\n"); 541 PrintF(" When hitting a stop, the Simulator will\n");
542 PrintF(" stop and and give control to the Debugger.\n"); 542 PrintF(" stop and and give control to the ArmDebugger.\n");
543 PrintF(" The first %d stop codes are watched:\n", 543 PrintF(" The first %d stop codes are watched:\n",
544 Simulator::kNumOfWatchedStops); 544 Simulator::kNumOfWatchedStops);
545 PrintF(" - They can be enabled / disabled: the Simulator\n"); 545 PrintF(" - They can be enabled / disabled: the Simulator\n");
546 PrintF(" will / won't stop when hitting them.\n"); 546 PrintF(" will / won't stop when hitting them.\n");
547 PrintF(" - The Simulator keeps track of how many times they \n"); 547 PrintF(" - The Simulator keeps track of how many times they \n");
548 PrintF(" are met. (See the info command.) Going over a\n"); 548 PrintF(" are met. (See the info command.) Going over a\n");
549 PrintF(" disabled stop still increases its counter. \n"); 549 PrintF(" disabled stop still increases its counter. \n");
550 PrintF(" Commands:\n"); 550 PrintF(" Commands:\n");
551 PrintF(" stop info all/<code> : print infos about number <code>\n"); 551 PrintF(" stop info all/<code> : print infos about number <code>\n");
552 PrintF(" or all stop(s).\n"); 552 PrintF(" or all stop(s).\n");
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
586 } 586 }
587 587
588 588
589 static bool AllOnOnePage(uintptr_t start, int size) { 589 static bool AllOnOnePage(uintptr_t start, int size) {
590 intptr_t start_page = (start & ~CachePage::kPageMask); 590 intptr_t start_page = (start & ~CachePage::kPageMask);
591 intptr_t end_page = ((start + size) & ~CachePage::kPageMask); 591 intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
592 return start_page == end_page; 592 return start_page == end_page;
593 } 593 }
594 594
595 595
596 void Simulator::FlushICache(void* start_addr, size_t size) { 596 void Simulator::FlushICache(v8::internal::HashMap* i_cache,
597 void* start_addr,
598 size_t size) {
597 intptr_t start = reinterpret_cast<intptr_t>(start_addr); 599 intptr_t start = reinterpret_cast<intptr_t>(start_addr);
598 int intra_line = (start & CachePage::kLineMask); 600 int intra_line = (start & CachePage::kLineMask);
599 start -= intra_line; 601 start -= intra_line;
600 size += intra_line; 602 size += intra_line;
601 size = ((size - 1) | CachePage::kLineMask) + 1; 603 size = ((size - 1) | CachePage::kLineMask) + 1;
602 int offset = (start & CachePage::kPageMask); 604 int offset = (start & CachePage::kPageMask);
603 while (!AllOnOnePage(start, size - 1)) { 605 while (!AllOnOnePage(start, size - 1)) {
604 int bytes_to_flush = CachePage::kPageSize - offset; 606 int bytes_to_flush = CachePage::kPageSize - offset;
605 FlushOnePage(start, bytes_to_flush); 607 FlushOnePage(i_cache, start, bytes_to_flush);
606 start += bytes_to_flush; 608 start += bytes_to_flush;
607 size -= bytes_to_flush; 609 size -= bytes_to_flush;
608 ASSERT_EQ(0, start & CachePage::kPageMask); 610 ASSERT_EQ(0, start & CachePage::kPageMask);
609 offset = 0; 611 offset = 0;
610 } 612 }
611 if (size != 0) { 613 if (size != 0) {
612 FlushOnePage(start, size); 614 FlushOnePage(i_cache, start, size);
613 } 615 }
614 } 616 }
615 617
616 618
617 CachePage* Simulator::GetCachePage(void* page) { 619 CachePage* Simulator::GetCachePage(v8::internal::HashMap* i_cache, void* page) {
618 v8::internal::HashMap::Entry* entry = i_cache_->Lookup(page, 620 v8::internal::HashMap::Entry* entry = i_cache->Lookup(page,
619 ICacheHash(page), 621 ICacheHash(page),
620 true); 622 true);
621 if (entry->value == NULL) { 623 if (entry->value == NULL) {
622 CachePage* new_page = new CachePage(); 624 CachePage* new_page = new CachePage();
623 entry->value = new_page; 625 entry->value = new_page;
624 } 626 }
625 return reinterpret_cast<CachePage*>(entry->value); 627 return reinterpret_cast<CachePage*>(entry->value);
626 } 628 }
627 629
628 630
629 // Flush from start up to and not including start + size. 631 // Flush from start up to and not including start + size.
630 void Simulator::FlushOnePage(intptr_t start, int size) { 632 void Simulator::FlushOnePage(v8::internal::HashMap* i_cache,
633 intptr_t start,
634 int size) {
631 ASSERT(size <= CachePage::kPageSize); 635 ASSERT(size <= CachePage::kPageSize);
632 ASSERT(AllOnOnePage(start, size - 1)); 636 ASSERT(AllOnOnePage(start, size - 1));
633 ASSERT((start & CachePage::kLineMask) == 0); 637 ASSERT((start & CachePage::kLineMask) == 0);
634 ASSERT((size & CachePage::kLineMask) == 0); 638 ASSERT((size & CachePage::kLineMask) == 0);
635 void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask)); 639 void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
636 int offset = (start & CachePage::kPageMask); 640 int offset = (start & CachePage::kPageMask);
637 CachePage* cache_page = GetCachePage(page); 641 CachePage* cache_page = GetCachePage(i_cache, page);
638 char* valid_bytemap = cache_page->ValidityByte(offset); 642 char* valid_bytemap = cache_page->ValidityByte(offset);
639 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift); 643 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
640 } 644 }
641 645
642 646
643 void Simulator::CheckICache(Instruction* instr) { 647 void Simulator::CheckICache(v8::internal::HashMap* i_cache,
648 Instruction* instr) {
644 intptr_t address = reinterpret_cast<intptr_t>(instr); 649 intptr_t address = reinterpret_cast<intptr_t>(instr);
645 void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask)); 650 void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
646 void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask)); 651 void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
647 int offset = (address & CachePage::kPageMask); 652 int offset = (address & CachePage::kPageMask);
648 CachePage* cache_page = GetCachePage(page); 653 CachePage* cache_page = GetCachePage(i_cache, page);
649 char* cache_valid_byte = cache_page->ValidityByte(offset); 654 char* cache_valid_byte = cache_page->ValidityByte(offset);
650 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID); 655 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
651 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask); 656 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
652 if (cache_hit) { 657 if (cache_hit) {
653 // Check that the data in memory matches the contents of the I-cache. 658 // Check that the data in memory matches the contents of the I-cache.
654 CHECK(memcmp(reinterpret_cast<void*>(instr), 659 CHECK(memcmp(reinterpret_cast<void*>(instr),
655 cache_page->CachedData(offset), 660 cache_page->CachedData(offset),
656 Instruction::kInstrSize) == 0); 661 Instruction::kInstrSize) == 0);
657 } else { 662 } else {
658 // Cache miss. Load memory into the cache. 663 // Cache miss. Load memory into the cache.
659 memcpy(cached_line, line, CachePage::kLineLength); 664 memcpy(cached_line, line, CachePage::kLineLength);
660 *cache_valid_byte = CachePage::LINE_VALID; 665 *cache_valid_byte = CachePage::LINE_VALID;
661 } 666 }
662 } 667 }
663 668
664 669
665 // Create one simulator per thread and keep it in thread local storage.
666 static v8::internal::Thread::LocalStorageKey simulator_key;
667
668
669 bool Simulator::initialized_ = false;
670
671
672 void Simulator::Initialize() { 670 void Simulator::Initialize() {
673 if (initialized_) return; 671 if (Isolate::Current()->simulator_initialized()) return;
674 simulator_key = v8::internal::Thread::CreateThreadLocalKey(); 672 Isolate::Current()->set_simulator_initialized(true);
675 initialized_ = true;
676 ::v8::internal::ExternalReference::set_redirector(&RedirectExternalReference); 673 ::v8::internal::ExternalReference::set_redirector(&RedirectExternalReference);
677 } 674 }
678 675
679 676
680 v8::internal::HashMap* Simulator::i_cache_ = NULL; 677 Simulator::Simulator() : isolate_(Isolate::Current()) {
681 678 i_cache_ = isolate_->simulator_i_cache();
682
683 Simulator::Simulator() {
684 if (i_cache_ == NULL) { 679 if (i_cache_ == NULL) {
685 i_cache_ = new v8::internal::HashMap(&ICacheMatch); 680 i_cache_ = new v8::internal::HashMap(&ICacheMatch);
681 isolate_->set_simulator_i_cache(i_cache_);
686 } 682 }
687 Initialize(); 683 Initialize();
688 // Setup simulator support first. Some of this information is needed to 684 // Setup simulator support first. Some of this information is needed to
689 // setup the architecture state. 685 // setup the architecture state.
690 size_t stack_size = 1 * 1024*1024; // allocate 1MB for stack 686 size_t stack_size = 1 * 1024*1024; // allocate 1MB for stack
691 stack_ = reinterpret_cast<char*>(malloc(stack_size)); 687 stack_ = reinterpret_cast<char*>(malloc(stack_size));
692 pc_modified_ = false; 688 pc_modified_ = false;
693 icount_ = 0; 689 icount_ = 0;
694 break_pc_ = NULL; 690 break_pc_ = NULL;
695 break_instr_ = 0; 691 break_instr_ = 0;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
741 // execute it with the simulator. We do that by redirecting the external 737 // execute it with the simulator. We do that by redirecting the external
742 // reference to a svc (Supervisor Call) instruction that is handled by 738 // reference to a svc (Supervisor Call) instruction that is handled by
743 // the simulator. We write the original destination of the jump just at a known 739 // the simulator. We write the original destination of the jump just at a known
744 // offset from the svc instruction so the simulator knows what to call. 740 // offset from the svc instruction so the simulator knows what to call.
745 class Redirection { 741 class Redirection {
746 public: 742 public:
747 Redirection(void* external_function, ExternalReference::Type type) 743 Redirection(void* external_function, ExternalReference::Type type)
748 : external_function_(external_function), 744 : external_function_(external_function),
749 swi_instruction_(al | (0xf*B24) | kCallRtRedirected), 745 swi_instruction_(al | (0xf*B24) | kCallRtRedirected),
750 type_(type), 746 type_(type),
751 next_(list_) { 747 next_(NULL) {
752 Simulator::current()-> 748 Isolate* isolate = Isolate::Current();
753 FlushICache(reinterpret_cast<void*>(&swi_instruction_), 749 next_ = isolate->simulator_redirection();
754 Instruction::kInstrSize); 750 Simulator::current(isolate)->
755 list_ = this; 751 FlushICache(isolate->simulator_i_cache(),
752 reinterpret_cast<void*>(&swi_instruction_),
753 Instruction::kInstrSize);
754 isolate->set_simulator_redirection(this);
756 } 755 }
757 756
758 void* address_of_swi_instruction() { 757 void* address_of_swi_instruction() {
759 return reinterpret_cast<void*>(&swi_instruction_); 758 return reinterpret_cast<void*>(&swi_instruction_);
760 } 759 }
761 760
762 void* external_function() { return external_function_; } 761 void* external_function() { return external_function_; }
763 ExternalReference::Type type() { return type_; } 762 ExternalReference::Type type() { return type_; }
764 763
765 static Redirection* Get(void* external_function, 764 static Redirection* Get(void* external_function,
766 ExternalReference::Type type) { 765 ExternalReference::Type type) {
767 Redirection* current; 766 Isolate* isolate = Isolate::Current();
768 for (current = list_; current != NULL; current = current->next_) { 767 Redirection* current = isolate->simulator_redirection();
768 for (; current != NULL; current = current->next_) {
769 if (current->external_function_ == external_function) return current; 769 if (current->external_function_ == external_function) return current;
770 } 770 }
771 return new Redirection(external_function, type); 771 return new Redirection(external_function, type);
772 } 772 }
773 773
774 static Redirection* FromSwiInstruction(Instruction* swi_instruction) { 774 static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
775 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction); 775 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
776 char* addr_of_redirection = 776 char* addr_of_redirection =
777 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_); 777 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_);
778 return reinterpret_cast<Redirection*>(addr_of_redirection); 778 return reinterpret_cast<Redirection*>(addr_of_redirection);
779 } 779 }
780 780
781 private: 781 private:
782 void* external_function_; 782 void* external_function_;
783 uint32_t swi_instruction_; 783 uint32_t swi_instruction_;
784 ExternalReference::Type type_; 784 ExternalReference::Type type_;
785 Redirection* next_; 785 Redirection* next_;
786 static Redirection* list_;
787 }; 786 };
788 787
789 788
790 Redirection* Redirection::list_ = NULL;
791
792
793 void* Simulator::RedirectExternalReference(void* external_function, 789 void* Simulator::RedirectExternalReference(void* external_function,
794 ExternalReference::Type type) { 790 ExternalReference::Type type) {
795 Redirection* redirection = Redirection::Get(external_function, type); 791 Redirection* redirection = Redirection::Get(external_function, type);
796 return redirection->address_of_swi_instruction(); 792 return redirection->address_of_swi_instruction();
797 } 793 }
798 794
799 795
800 // Get the active Simulator for the current thread. 796 // Get the active Simulator for the current thread.
801 Simulator* Simulator::current() { 797 Simulator* Simulator::current(Isolate* isolate) {
802 Initialize(); 798 v8::internal::Isolate::PerIsolateThreadData* isolate_data =
803 Simulator* sim = reinterpret_cast<Simulator*>( 799 Isolate::CurrentPerIsolateThreadData();
804 v8::internal::Thread::GetThreadLocal(simulator_key)); 800 if (isolate_data == NULL) {
801 Isolate::EnterDefaultIsolate();
802 isolate_data = Isolate::CurrentPerIsolateThreadData();
803 }
804 ASSERT(isolate_data != NULL);
805
806 Simulator* sim = isolate_data->simulator();
805 if (sim == NULL) { 807 if (sim == NULL) {
806 // TODO(146): delete the simulator object when a thread goes away. 808 // TODO(146): delete the simulator object when a thread/isolate goes away.
807 sim = new Simulator(); 809 sim = new Simulator();
808 v8::internal::Thread::SetThreadLocal(simulator_key, sim); 810 isolate_data->set_simulator(sim);
809 } 811 }
810 return sim; 812 return sim;
811 } 813 }
812 814
813 815
814 // Sets the register in the architecture state. It will also deal with updating 816 // Sets the register in the architecture state. It will also deal with updating
815 // Simulator internal state for special registers such as PC. 817 // Simulator internal state for special registers such as PC.
816 void Simulator::set_register(int reg, int32_t value) { 818 void Simulator::set_register(int reg, int32_t value) {
817 ASSERT((reg >= 0) && (reg < num_registers)); 819 ASSERT((reg >= 0) && (reg < num_registers));
818 if (reg == pc) { 820 if (reg == pc) {
(...skipping 707 matching lines...) Expand 10 before | Expand all | Expand 10 after
1526 // Calls into the V8 runtime are based on this very simple interface. 1528 // Calls into the V8 runtime are based on this very simple interface.
1527 // Note: To be able to return two values from some calls the code in runtime.cc 1529 // Note: To be able to return two values from some calls the code in runtime.cc
1528 // uses the ObjectPair which is essentially two 32-bit values stuffed into a 1530 // uses the ObjectPair which is essentially two 32-bit values stuffed into a
1529 // 64-bit value. With the code below we assume that all runtime calls return 1531 // 64-bit value. With the code below we assume that all runtime calls return
1530 // 64 bits of result. If they don't, the r1 result register contains a bogus 1532 // 64 bits of result. If they don't, the r1 result register contains a bogus
1531 // value, which is fine because it is caller-saved. 1533 // value, which is fine because it is caller-saved.
1532 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, 1534 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
1533 int32_t arg1, 1535 int32_t arg1,
1534 int32_t arg2, 1536 int32_t arg2,
1535 int32_t arg3, 1537 int32_t arg3,
1536 int32_t arg4); 1538 int32_t arg4,
1539 int32_t arg5);
1537 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0, 1540 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0,
1538 int32_t arg1, 1541 int32_t arg1,
1539 int32_t arg2, 1542 int32_t arg2,
1540 int32_t arg3); 1543 int32_t arg3);
1541 1544
1542 // This signature supports direct call in to API function native callback 1545 // This signature supports direct call in to API function native callback
1543 // (refer to InvocationCallback in v8.h). 1546 // (refer to InvocationCallback in v8.h).
1544 typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectApiCall)(int32_t arg0); 1547 typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectApiCall)(int32_t arg0);
1545 1548
1546 // This signature supports direct call to accessor getter callback. 1549 // This signature supports direct call to accessor getter callback.
(...skipping 10 matching lines...) Expand all
1557 // include information on the function called. 1560 // include information on the function called.
1558 bool stack_aligned = 1561 bool stack_aligned =
1559 (get_register(sp) 1562 (get_register(sp)
1560 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0; 1563 & (::v8::internal::FLAG_sim_stack_alignment - 1)) == 0;
1561 Redirection* redirection = Redirection::FromSwiInstruction(instr); 1564 Redirection* redirection = Redirection::FromSwiInstruction(instr);
1562 int32_t arg0 = get_register(r0); 1565 int32_t arg0 = get_register(r0);
1563 int32_t arg1 = get_register(r1); 1566 int32_t arg1 = get_register(r1);
1564 int32_t arg2 = get_register(r2); 1567 int32_t arg2 = get_register(r2);
1565 int32_t arg3 = get_register(r3); 1568 int32_t arg3 = get_register(r3);
1566 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp)); 1569 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
1567 int32_t arg4 = *stack_pointer; 1570 int32_t arg4 = stack_pointer[0];
1571 int32_t arg5 = stack_pointer[1];
1568 // This is dodgy but it works because the C entry stubs are never moved. 1572 // This is dodgy but it works because the C entry stubs are never moved.
1569 // See comment in codegen-arm.cc and bug 1242173. 1573 // See comment in codegen-arm.cc and bug 1242173.
1570 int32_t saved_lr = get_register(lr); 1574 int32_t saved_lr = get_register(lr);
1571 intptr_t external = 1575 intptr_t external =
1572 reinterpret_cast<intptr_t>(redirection->external_function()); 1576 reinterpret_cast<intptr_t>(redirection->external_function());
1573 if (redirection->type() == ExternalReference::FP_RETURN_CALL) { 1577 if (redirection->type() == ExternalReference::FP_RETURN_CALL) {
1574 SimulatorRuntimeFPCall target = 1578 SimulatorRuntimeFPCall target =
1575 reinterpret_cast<SimulatorRuntimeFPCall>(external); 1579 reinterpret_cast<SimulatorRuntimeFPCall>(external);
1576 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { 1580 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1577 double x, y; 1581 double x, y;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1620 PrintF("Returned %p\n", reinterpret_cast<void *>(*result)); 1624 PrintF("Returned %p\n", reinterpret_cast<void *>(*result));
1621 } 1625 }
1622 set_register(r0, (int32_t) *result); 1626 set_register(r0, (int32_t) *result);
1623 } else { 1627 } else {
1624 // builtin call. 1628 // builtin call.
1625 ASSERT(redirection->type() == ExternalReference::BUILTIN_CALL); 1629 ASSERT(redirection->type() == ExternalReference::BUILTIN_CALL);
1626 SimulatorRuntimeCall target = 1630 SimulatorRuntimeCall target =
1627 reinterpret_cast<SimulatorRuntimeCall>(external); 1631 reinterpret_cast<SimulatorRuntimeCall>(external);
1628 if (::v8::internal::FLAG_trace_sim || !stack_aligned) { 1632 if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
1629 PrintF( 1633 PrintF(
1630 "Call to host function at %p args %08x, %08x, %08x, %08x, %0xc", 1634 "Call to host function at %p"
1635 "args %08x, %08x, %08x, %08x, %08x, %08x",
1631 FUNCTION_ADDR(target), 1636 FUNCTION_ADDR(target),
1632 arg0, 1637 arg0,
1633 arg1, 1638 arg1,
1634 arg2, 1639 arg2,
1635 arg3, 1640 arg3,
1636 arg4); 1641 arg4,
1642 arg5);
1637 if (!stack_aligned) { 1643 if (!stack_aligned) {
1638 PrintF(" with unaligned stack %08x\n", get_register(sp)); 1644 PrintF(" with unaligned stack %08x\n", get_register(sp));
1639 } 1645 }
1640 PrintF("\n"); 1646 PrintF("\n");
1641 } 1647 }
1642 CHECK(stack_aligned); 1648 CHECK(stack_aligned);
1643 int64_t result = target(arg0, arg1, arg2, arg3, arg4); 1649 int64_t result = target(arg0, arg1, arg2, arg3, arg4, arg5);
1644 int32_t lo_res = static_cast<int32_t>(result); 1650 int32_t lo_res = static_cast<int32_t>(result);
1645 int32_t hi_res = static_cast<int32_t>(result >> 32); 1651 int32_t hi_res = static_cast<int32_t>(result >> 32);
1646 if (::v8::internal::FLAG_trace_sim) { 1652 if (::v8::internal::FLAG_trace_sim) {
1647 PrintF("Returned %08x\n", lo_res); 1653 PrintF("Returned %08x\n", lo_res);
1648 } 1654 }
1649 set_register(r0, lo_res); 1655 set_register(r0, lo_res);
1650 set_register(r1, hi_res); 1656 set_register(r1, hi_res);
1651 } 1657 }
1652 set_register(lr, saved_lr); 1658 set_register(lr, saved_lr);
1653 set_pc(get_register(lr)); 1659 set_pc(get_register(lr));
1654 break; 1660 break;
1655 } 1661 }
1656 case kBreakpoint: { 1662 case kBreakpoint: {
1657 Debugger dbg(this); 1663 ArmDebugger dbg(this);
1658 dbg.Debug(); 1664 dbg.Debug();
1659 break; 1665 break;
1660 } 1666 }
1661 // stop uses all codes greater than 1 << 23. 1667 // stop uses all codes greater than 1 << 23.
1662 default: { 1668 default: {
1663 if (svc >= (1 << 23)) { 1669 if (svc >= (1 << 23)) {
1664 uint32_t code = svc & kStopCodeMask; 1670 uint32_t code = svc & kStopCodeMask;
1665 if (isWatchedStop(code)) { 1671 if (isWatchedStop(code)) {
1666 IncreaseStopCounter(code); 1672 IncreaseStopCounter(code);
1667 } 1673 }
1668 // Stop if it is enabled, otherwise go on jumping over the stop 1674 // Stop if it is enabled, otherwise go on jumping over the stop
1669 // and the message address. 1675 // and the message address.
1670 if (isEnabledStop(code)) { 1676 if (isEnabledStop(code)) {
1671 Debugger dbg(this); 1677 ArmDebugger dbg(this);
1672 dbg.Stop(instr); 1678 dbg.Stop(instr);
1673 } else { 1679 } else {
1674 set_pc(get_pc() + 2 * Instruction::kInstrSize); 1680 set_pc(get_pc() + 2 * Instruction::kInstrSize);
1675 } 1681 }
1676 } else { 1682 } else {
1677 // This is not a valid svc code. 1683 // This is not a valid svc code.
1678 UNREACHABLE(); 1684 UNREACHABLE();
1679 break; 1685 break;
1680 } 1686 }
1681 } 1687 }
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after
1969 case BX: 1975 case BX:
1970 set_pc(get_register(rm)); 1976 set_pc(get_register(rm));
1971 break; 1977 break;
1972 case BLX: { 1978 case BLX: {
1973 uint32_t old_pc = get_pc(); 1979 uint32_t old_pc = get_pc();
1974 set_pc(get_register(rm)); 1980 set_pc(get_register(rm));
1975 set_register(lr, old_pc + Instruction::kInstrSize); 1981 set_register(lr, old_pc + Instruction::kInstrSize);
1976 break; 1982 break;
1977 } 1983 }
1978 case BKPT: { 1984 case BKPT: {
1979 Debugger dbg(this); 1985 ArmDebugger dbg(this);
1980 PrintF("Simulator hit BKPT.\n"); 1986 PrintF("Simulator hit BKPT.\n");
1981 dbg.Debug(); 1987 dbg.Debug();
1982 break; 1988 break;
1983 } 1989 }
1984 default: 1990 default:
1985 UNIMPLEMENTED(); 1991 UNIMPLEMENTED();
1986 } 1992 }
1987 } else if (instr->Bits(22, 21) == 3) { 1993 } else if (instr->Bits(22, 21) == 3) {
1988 int rm = instr->RmValue(); 1994 int rm = instr->RmValue();
1989 int rd = instr->RdValue(); 1995 int rd = instr->RdValue();
(...skipping 967 matching lines...) Expand 10 before | Expand all | Expand 10 after
2957 } 2963 }
2958 } else { 2964 } else {
2959 UNIMPLEMENTED(); // Not used by V8. 2965 UNIMPLEMENTED(); // Not used by V8.
2960 } 2966 }
2961 } 2967 }
2962 2968
2963 2969
2964 // Executes the current instruction. 2970 // Executes the current instruction.
2965 void Simulator::InstructionDecode(Instruction* instr) { 2971 void Simulator::InstructionDecode(Instruction* instr) {
2966 if (v8::internal::FLAG_check_icache) { 2972 if (v8::internal::FLAG_check_icache) {
2967 CheckICache(instr); 2973 CheckICache(isolate_->simulator_i_cache(), instr);
2968 } 2974 }
2969 pc_modified_ = false; 2975 pc_modified_ = false;
2970 if (::v8::internal::FLAG_trace_sim) { 2976 if (::v8::internal::FLAG_trace_sim) {
2971 disasm::NameConverter converter; 2977 disasm::NameConverter converter;
2972 disasm::Disassembler dasm(converter); 2978 disasm::Disassembler dasm(converter);
2973 // use a reasonably large buffer 2979 // use a reasonably large buffer
2974 v8::internal::EmbeddedVector<char, 256> buffer; 2980 v8::internal::EmbeddedVector<char, 256> buffer;
2975 dasm.InstructionDecode(buffer, 2981 dasm.InstructionDecode(buffer,
2976 reinterpret_cast<byte*>(instr)); 2982 reinterpret_cast<byte*>(instr));
2977 PrintF(" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr), buffer.start()); 2983 PrintF(" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr), buffer.start());
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
3040 InstructionDecode(instr); 3046 InstructionDecode(instr);
3041 program_counter = get_pc(); 3047 program_counter = get_pc();
3042 } 3048 }
3043 } else { 3049 } else {
3044 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when 3050 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when
3045 // we reach the particular instuction count. 3051 // we reach the particular instuction count.
3046 while (program_counter != end_sim_pc) { 3052 while (program_counter != end_sim_pc) {
3047 Instruction* instr = reinterpret_cast<Instruction*>(program_counter); 3053 Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
3048 icount_++; 3054 icount_++;
3049 if (icount_ == ::v8::internal::FLAG_stop_sim_at) { 3055 if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
3050 Debugger dbg(this); 3056 ArmDebugger dbg(this);
3051 dbg.Debug(); 3057 dbg.Debug();
3052 } else { 3058 } else {
3053 InstructionDecode(instr); 3059 InstructionDecode(instr);
3054 } 3060 }
3055 program_counter = get_pc(); 3061 program_counter = get_pc();
3056 } 3062 }
3057 } 3063 }
3058 } 3064 }
3059 3065
3060 3066
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
3163 uintptr_t address = *stack_slot; 3169 uintptr_t address = *stack_slot;
3164 set_register(sp, current_sp + sizeof(uintptr_t)); 3170 set_register(sp, current_sp + sizeof(uintptr_t));
3165 return address; 3171 return address;
3166 } 3172 }
3167 3173
3168 } } // namespace v8::internal 3174 } } // namespace v8::internal
3169 3175
3170 #endif // USE_SIMULATOR 3176 #endif // USE_SIMULATOR
3171 3177
3172 #endif // V8_TARGET_ARCH_ARM 3178 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/simulator-arm.h ('k') | src/arm/stub-cache-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698