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

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

Issue 6709022: Re-establish mips basic infrastructure. (Closed) Base URL: git://github.com/v8/v8.git@master
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
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
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include <stdlib.h> 28 #include <stdlib.h>
29 #include <math.h>
30 #include <limits.h>
29 #include <cstdarg> 31 #include <cstdarg>
30 #include "v8.h" 32 #include "v8.h"
31 33
32 #if defined(V8_TARGET_ARCH_MIPS) 34 #if defined(V8_TARGET_ARCH_MIPS)
33 35
34 #include "disasm.h" 36 #include "disasm.h"
35 #include "assembler.h" 37 #include "assembler.h"
36 #include "globals.h" // Need the BitCast 38 #include "globals.h" // Need the BitCast
37 #include "mips/constants-mips.h" 39 #include "mips/constants-mips.h"
38 #include "mips/simulator-mips.h" 40 #include "mips/simulator-mips.h"
39 41
40 namespace v8i = v8::internal;
41
42 #if !defined(__mips) || defined(USE_SIMULATOR)
43 42
44 // Only build the simulator if not compiling for real MIPS hardware. 43 // Only build the simulator if not compiling for real MIPS hardware.
45 namespace assembler { 44 #if defined(USE_SIMULATOR)
46 namespace mips {
47 45
48 using ::v8::internal::Object; 46 // This can be defined by the build system, even for Simulator builds.
49 using ::v8::internal::PrintF; 47 #ifdef _MIPS_ARCH_MIPS32R2
50 using ::v8::internal::OS; 48 #define mips32r2 1
51 using ::v8::internal::ReadLine; 49 #else
52 using ::v8::internal::DeleteArray; 50 #define mips32r2 0
51 #endif
52
53 namespace v8 {
54 namespace internal {
53 55
54 // Utils functions 56 // Utils functions
55 bool HaveSameSign(int32_t a, int32_t b) { 57 bool HaveSameSign(int32_t a, int32_t b) {
56 return ((a ^ b) > 0); 58 return ((a ^ b) >= 0);
57 } 59 }
58 60
59 61
62 uint32_t get_fcsr_condition_bit(uint32_t cc) {
63 if (cc == 0) {
64 return 23;
65 } else {
66 return 24 + cc;
67 }
68 }
69
70
60 // This macro provides a platform independent use of sscanf. The reason for 71 // This macro provides a platform independent use of sscanf. The reason for
61 // SScanF not being implemented in a platform independent was through 72 // SScanF not being implemented in a platform independent was through
62 // ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time 73 // ::v8::internal::OS in the same way as SNPrintF is that the Windows C Run-Time
63 // Library does not provide vsscanf. 74 // Library does not provide vsscanf.
64 #define SScanF sscanf // NOLINT 75 #define SScanF sscanf // NOLINT
65 76
66 // The Debugger class is used by the simulator while debugging simulated MIPS 77 // The Debugger class is used by the simulator while debugging simulated MIPS
67 // code. 78 // code.
68 class Debugger { 79 class Debugger {
69 public: 80 public:
70 explicit Debugger(Simulator* sim); 81 explicit Debugger(Simulator* sim);
71 ~Debugger(); 82 ~Debugger();
72 83
73 void Stop(Instruction* instr); 84 void Stop(Instruction* instr);
74 void Debug(); 85 void Debug();
86 // Print all registers with a nice formatting.
87 void PrintAllRegs();
88 void PrintAllRegsIncludingFPU();
75 89
76 private: 90 private:
77 // We set the breakpoint code to 0xfffff to easily recognize it. 91 // We set the breakpoint code to 0xfffff to easily recognize it.
78 static const Instr kBreakpointInstr = SPECIAL | BREAK | 0xfffff << 6; 92 static const Instr kBreakpointInstr = SPECIAL | BREAK | 0xfffff << 6;
79 static const Instr kNopInstr = 0x0; 93 static const Instr kNopInstr = 0x0;
80 94
81 Simulator* sim_; 95 Simulator* sim_;
82 96
83 int32_t GetRegisterValue(int regnum); 97 int32_t GetRegisterValue(int regnum);
98 int32_t GetFPURegisterValueInt(int regnum);
99 int64_t GetFPURegisterValueLong(int regnum);
100 float GetFPURegisterValueFloat(int regnum);
101 double GetFPURegisterValueDouble(int regnum);
84 bool GetValue(const char* desc, int32_t* value); 102 bool GetValue(const char* desc, int32_t* value);
85 103
86 // Set or delete a breakpoint. Returns true if successful. 104 // Set or delete a breakpoint. Returns true if successful.
87 bool SetBreakpoint(Instruction* breakpc); 105 bool SetBreakpoint(Instruction* breakpc);
88 bool DeleteBreakpoint(Instruction* breakpc); 106 bool DeleteBreakpoint(Instruction* breakpc);
89 107
90 // Undo and redo all breakpoints. This is needed to bracket disassembly and 108 // Undo and redo all breakpoints. This is needed to bracket disassembly and
91 // execution to skip past breakpoints when run from the debugger. 109 // execution to skip past breakpoints when run from the debugger.
92 void UndoBreakpoints(); 110 void UndoBreakpoints();
93 void RedoBreakpoints(); 111 void RedoBreakpoints();
94
95 // Print all registers with a nice formatting.
96 void PrintAllRegs();
97 }; 112 };
98 113
99 Debugger::Debugger(Simulator* sim) { 114 Debugger::Debugger(Simulator* sim) {
100 sim_ = sim; 115 sim_ = sim;
101 } 116 }
102 117
118
103 Debugger::~Debugger() { 119 Debugger::~Debugger() {
104 } 120 }
105 121
122
106 #ifdef GENERATED_CODE_COVERAGE 123 #ifdef GENERATED_CODE_COVERAGE
107 static FILE* coverage_log = NULL; 124 static FILE* coverage_log = NULL;
108 125
109 126
110 static void InitializeCoverage() { 127 static void InitializeCoverage() {
111 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG"); 128 char* file_name = getenv("V8_GENERATED_CODE_COVERAGE_LOG");
112 if (file_name != NULL) { 129 if (file_name != NULL) {
113 coverage_log = fopen(file_name, "aw+"); 130 coverage_log = fopen(file_name, "aw+");
114 } 131 }
115 } 132 }
116 133
117 134
118 void Debugger::Stop(Instruction* instr) { 135 void Debugger::Stop(Instruction* instr) {
119 UNIMPLEMENTED_MIPS(); 136 UNIMPLEMENTED_MIPS();
120 char* str = reinterpret_cast<char*>(instr->InstructionBits()); 137 char* str = reinterpret_cast<char*>(instr->InstructionBits());
121 if (strlen(str) > 0) { 138 if (strlen(str) > 0) {
122 if (coverage_log != NULL) { 139 if (coverage_log != NULL) {
123 fprintf(coverage_log, "%s\n", str); 140 fprintf(coverage_log, "%s\n", str);
124 fflush(coverage_log); 141 fflush(coverage_log);
125 } 142 }
126 instr->SetInstructionBits(0x0); // Overwrite with nop. 143 instr->SetInstructionBits(0x0); // Overwrite with nop.
127 } 144 }
128 sim_->set_pc(sim_->get_pc() + Instruction::kInstructionSize); 145 sim_->set_pc(sim_->get_pc() + Instruction::kInstructionSize);
129 } 146 }
130 147
148
131 #else // ndef GENERATED_CODE_COVERAGE 149 #else // ndef GENERATED_CODE_COVERAGE
132 150
133 #define UNSUPPORTED() printf("Unsupported instruction.\n"); 151 #define UNSUPPORTED() printf("Unsupported instruction.\n");
134 152
135 static void InitializeCoverage() {} 153 static void InitializeCoverage() {}
136 154
137 155
138 void Debugger::Stop(Instruction* instr) { 156 void Debugger::Stop(Instruction* instr) {
139 const char* str = reinterpret_cast<char*>(instr->InstructionBits()); 157 const char* str = reinterpret_cast<char*>(instr->InstructionBits());
140 PrintF("Simulator hit %s\n", str); 158 PrintF("Simulator hit %s\n", str);
141 sim_->set_pc(sim_->get_pc() + Instruction::kInstructionSize); 159 sim_->set_pc(sim_->get_pc() + Instruction::kInstructionSize);
142 Debug(); 160 Debug();
143 } 161 }
144 #endif // GENERATED_CODE_COVERAGE 162 #endif // GENERATED_CODE_COVERAGE
145 163
146 164
147 int32_t Debugger::GetRegisterValue(int regnum) { 165 int32_t Debugger::GetRegisterValue(int regnum) {
148 if (regnum == kNumSimuRegisters) { 166 if (regnum == kNumSimuRegisters) {
149 return sim_->get_pc(); 167 return sim_->get_pc();
150 } else { 168 } else {
151 return sim_->get_register(regnum); 169 return sim_->get_register(regnum);
152 } 170 }
153 } 171 }
154 172
155 173
174 int32_t Debugger::GetFPURegisterValueInt(int regnum) {
175 if (regnum == kNumFPURegisters) {
176 return sim_->get_pc();
177 } else {
178 return sim_->get_fpu_register(regnum);
179 }
180 }
181
182
183 int64_t Debugger::GetFPURegisterValueLong(int regnum) {
184 if (regnum == kNumFPURegisters) {
185 return sim_->get_pc();
186 } else {
187 return sim_->get_fpu_register_long(regnum);
188 }
189 }
190
191
192 float Debugger::GetFPURegisterValueFloat(int regnum) {
193 if (regnum == kNumFPURegisters) {
194 return sim_->get_pc();
195 } else {
196 return sim_->get_fpu_register_float(regnum);
197 }
198 }
199
200
201 double Debugger::GetFPURegisterValueDouble(int regnum) {
202 if (regnum == kNumFPURegisters) {
203 return sim_->get_pc();
204 } else {
205 return sim_->get_fpu_register_double(regnum);
206 }
207 }
208
209
156 bool Debugger::GetValue(const char* desc, int32_t* value) { 210 bool Debugger::GetValue(const char* desc, int32_t* value) {
157 int regnum = Registers::Number(desc); 211 int regnum = Registers::Number(desc);
212 int fpuregnum = FPURegisters::Number(desc);
213
158 if (regnum != kInvalidRegister) { 214 if (regnum != kInvalidRegister) {
159 *value = GetRegisterValue(regnum); 215 *value = GetRegisterValue(regnum);
160 return true; 216 return true;
217 } else if (fpuregnum != kInvalidFPURegister) {
218 *value = GetFPURegisterValueInt(fpuregnum);
219 return true;
220 } else if (strncmp(desc, "0x", 2) == 0) {
221 return SScanF(desc, "%x", reinterpret_cast<uint32_t*>(value)) == 1;
161 } else { 222 } else {
162 return SScanF(desc, "%i", value) == 1; 223 return SScanF(desc, "%i", value) == 1;
163 } 224 }
164 return false; 225 return false;
165 } 226 }
166 227
167 228
168 bool Debugger::SetBreakpoint(Instruction* breakpc) { 229 bool Debugger::SetBreakpoint(Instruction* breakpc) {
169 // Check if a breakpoint can be set. If not return without any side-effects. 230 // Check if a breakpoint can be set. If not return without any side-effects.
170 if (sim_->break_pc_ != NULL) { 231 if (sim_->break_pc_ != NULL) {
(...skipping 26 matching lines...) Expand all
197 } 258 }
198 } 259 }
199 260
200 261
201 void Debugger::RedoBreakpoints() { 262 void Debugger::RedoBreakpoints() {
202 if (sim_->break_pc_ != NULL) { 263 if (sim_->break_pc_ != NULL) {
203 sim_->break_pc_->SetInstructionBits(kBreakpointInstr); 264 sim_->break_pc_->SetInstructionBits(kBreakpointInstr);
204 } 265 }
205 } 266 }
206 267
268
207 void Debugger::PrintAllRegs() { 269 void Debugger::PrintAllRegs() {
208 #define REG_INFO(n) Registers::Name(n), GetRegisterValue(n), GetRegisterValue(n) 270 #define REG_INFO(n) Registers::Name(n), GetRegisterValue(n), GetRegisterValue(n)
209 271
210 PrintF("\n"); 272 PrintF("\n");
211 // at, v0, a0 273 // at, v0, a0
212 PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n", 274 PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
213 REG_INFO(1), REG_INFO(2), REG_INFO(4)); 275 REG_INFO(1), REG_INFO(2), REG_INFO(4));
214 // v1, a1 276 // v1, a1
215 PrintF("%26s\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n", 277 PrintF("%26s\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
216 "", REG_INFO(3), REG_INFO(5)); 278 "", REG_INFO(3), REG_INFO(5));
(...skipping 13 matching lines...) Expand all
230 REG_INFO(24), REG_INFO(26), REG_INFO(32)); 292 REG_INFO(24), REG_INFO(26), REG_INFO(32));
231 // t9, k1, HI 293 // t9, k1, HI
232 PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n", 294 PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
233 REG_INFO(25), REG_INFO(27), REG_INFO(33)); 295 REG_INFO(25), REG_INFO(27), REG_INFO(33));
234 // sp, fp, gp 296 // sp, fp, gp
235 PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n", 297 PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
236 REG_INFO(29), REG_INFO(30), REG_INFO(28)); 298 REG_INFO(29), REG_INFO(30), REG_INFO(28));
237 // pc 299 // pc
238 PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n", 300 PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n",
239 REG_INFO(31), REG_INFO(34)); 301 REG_INFO(31), REG_INFO(34));
302
240 #undef REG_INFO 303 #undef REG_INFO
304 #undef FPU_REG_INFO
241 } 305 }
242 306
307
308 void Debugger::PrintAllRegsIncludingFPU() {
309 #define FPU_REG_INFO(n) FPURegisters::Name(n), FPURegisters::Name(n+1), \
310 GetFPURegisterValueInt(n+1), \
311 GetFPURegisterValueInt(n), \
312 GetFPURegisterValueDouble(n)
313
314 PrintAllRegs();
315
316 PrintF("\n\n");
317 // f0, f1, f2, ... f31
318 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(0) );
319 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(2) );
320 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(4) );
321 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(6) );
322 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(8) );
323 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(10));
324 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(12));
325 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(14));
326 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(16));
327 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(18));
328 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(20));
329 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(22));
330 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(24));
331 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(26));
332 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(28));
333 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(30));
334
335 #undef REG_INFO
336 #undef FPU_REG_INFO
337 }
338
339
243 void Debugger::Debug() { 340 void Debugger::Debug() {
244 intptr_t last_pc = -1; 341 intptr_t last_pc = -1;
245 bool done = false; 342 bool done = false;
246 343
247 #define COMMAND_SIZE 63 344 #define COMMAND_SIZE 63
248 #define ARG_SIZE 255 345 #define ARG_SIZE 255
249 346
250 #define STR(a) #a 347 #define STR(a) #a
251 #define XSTR(a) STR(a) 348 #define XSTR(a) STR(a)
252 349
253 char cmd[COMMAND_SIZE + 1]; 350 char cmd[COMMAND_SIZE + 1];
254 char arg1[ARG_SIZE + 1]; 351 char arg1[ARG_SIZE + 1];
255 char arg2[ARG_SIZE + 1]; 352 char arg2[ARG_SIZE + 1];
353 char* argv[3] = { cmd, arg1, arg2 };
256 354
257 // make sure to have a proper terminating character if reaching the limit 355 // make sure to have a proper terminating character if reaching the limit
258 cmd[COMMAND_SIZE] = 0; 356 cmd[COMMAND_SIZE] = 0;
259 arg1[ARG_SIZE] = 0; 357 arg1[ARG_SIZE] = 0;
260 arg2[ARG_SIZE] = 0; 358 arg2[ARG_SIZE] = 0;
261 359
262 // Undo all set breakpoints while running in the debugger shell. This will 360 // Undo all set breakpoints while running in the debugger shell. This will
263 // make them invisible to all commands. 361 // make them invisible to all commands.
264 UndoBreakpoints(); 362 UndoBreakpoints();
265 363
266 while (!done && (sim_->get_pc() != Simulator::end_sim_pc)) { 364 while (!done && (sim_->get_pc() != Simulator::end_sim_pc)) {
267 if (last_pc != sim_->get_pc()) { 365 if (last_pc != sim_->get_pc()) {
268 disasm::NameConverter converter; 366 disasm::NameConverter converter;
269 disasm::Disassembler dasm(converter); 367 disasm::Disassembler dasm(converter);
270 // use a reasonably large buffer 368 // use a reasonably large buffer
271 v8::internal::EmbeddedVector<char, 256> buffer; 369 v8::internal::EmbeddedVector<char, 256> buffer;
272 dasm.InstructionDecode(buffer, 370 dasm.InstructionDecode(buffer,
273 reinterpret_cast<byte_*>(sim_->get_pc())); 371 reinterpret_cast<byte_*>(sim_->get_pc()));
274 PrintF(" 0x%08x %s\n", sim_->get_pc(), buffer.start()); 372 PrintF(" 0x%08x %s\n", sim_->get_pc(), buffer.start());
275 last_pc = sim_->get_pc(); 373 last_pc = sim_->get_pc();
276 } 374 }
277 char* line = ReadLine("sim> "); 375 char* line = ReadLine("sim> ");
278 if (line == NULL) { 376 if (line == NULL) {
279 break; 377 break;
280 } else { 378 } else {
281 // Use sscanf to parse the individual parts of the command line. At the 379 // Use sscanf to parse the individual parts of the command line. At the
282 // moment no command expects more than two parameters. 380 // moment no command expects more than two parameters.
283 int args = SScanF(line, 381 int argc = SScanF(line,
284 "%" XSTR(COMMAND_SIZE) "s " 382 "%" XSTR(COMMAND_SIZE) "s "
285 "%" XSTR(ARG_SIZE) "s " 383 "%" XSTR(ARG_SIZE) "s "
286 "%" XSTR(ARG_SIZE) "s", 384 "%" XSTR(ARG_SIZE) "s",
287 cmd, arg1, arg2); 385 cmd, arg1, arg2);
288 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) { 386 if ((strcmp(cmd, "si") == 0) || (strcmp(cmd, "stepi") == 0)) {
289 if (!(reinterpret_cast<Instruction*>(sim_->get_pc())->IsTrap())) { 387 Instruction* instr = reinterpret_cast<Instruction*>(sim_->get_pc());
388 if (!(instr->IsTrap()) ||
389 instr->InstructionBits() == rtCallRedirInstr) {
290 sim_->InstructionDecode( 390 sim_->InstructionDecode(
291 reinterpret_cast<Instruction*>(sim_->get_pc())); 391 reinterpret_cast<Instruction*>(sim_->get_pc()));
292 } else { 392 } else {
293 // Allow si to jump over generated breakpoints. 393 // Allow si to jump over generated breakpoints.
294 PrintF("/!\\ Jumping over generated breakpoint.\n"); 394 PrintF("/!\\ Jumping over generated breakpoint.\n");
295 sim_->set_pc(sim_->get_pc() + Instruction::kInstructionSize); 395 sim_->set_pc(sim_->get_pc() + Instruction::kInstructionSize);
296 } 396 }
297 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { 397 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) {
298 // Execute the one instruction we broke at with breakpoints disabled. 398 // Execute the one instruction we broke at with breakpoints disabled.
299 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc())); 399 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc()));
300 // Leave the debugger shell. 400 // Leave the debugger shell.
301 done = true; 401 done = true;
302 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { 402 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) {
303 if (args == 2) { 403 if (argc == 2) {
304 int32_t value; 404 int32_t value;
405 float fvalue;
305 if (strcmp(arg1, "all") == 0) { 406 if (strcmp(arg1, "all") == 0) {
306 PrintAllRegs(); 407 PrintAllRegs();
408 } else if (strcmp(arg1, "allf") == 0) {
409 PrintAllRegsIncludingFPU();
307 } else { 410 } else {
308 if (GetValue(arg1, &value)) { 411 int regnum = Registers::Number(arg1);
412 int fpuregnum = FPURegisters::Number(arg1);
413
414 if (regnum != kInvalidRegister) {
415 value = GetRegisterValue(regnum);
309 PrintF("%s: 0x%08x %d \n", arg1, value, value); 416 PrintF("%s: 0x%08x %d \n", arg1, value, value);
417 } else if (fpuregnum != kInvalidFPURegister) {
418 if (fpuregnum % 2 == 1) {
419 value = GetFPURegisterValueInt(fpuregnum);
420 fvalue = GetFPURegisterValueFloat(fpuregnum);
421 PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue);
422 } else {
423 double dfvalue;
424 int32_t lvalue1 = GetFPURegisterValueInt(fpuregnum);
425 int32_t lvalue2 = GetFPURegisterValueInt(fpuregnum + 1);
426 dfvalue = GetFPURegisterValueDouble(fpuregnum);
427 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n",
428 FPURegisters::Name(fpuregnum+1),
429 FPURegisters::Name(fpuregnum),
430 lvalue1,
431 lvalue2,
432 dfvalue);
433 }
310 } else { 434 } else {
311 PrintF("%s unrecognized\n", arg1); 435 PrintF("%s unrecognized\n", arg1);
312 } 436 }
313 } 437 }
314 } else { 438 } else {
315 PrintF("print <register>\n"); 439 if (argc == 3) {
440 if (strcmp(arg2, "single") == 0) {
441 int32_t value;
442 float fvalue;
443 int fpuregnum = FPURegisters::Number(arg1);
444
445 if (fpuregnum != kInvalidFPURegister) {
446 value = GetFPURegisterValueInt(fpuregnum);
447 fvalue = GetFPURegisterValueFloat(fpuregnum);
448 PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue);
449 } else {
450 PrintF("%s unrecognized\n", arg1);
451 }
452 } else {
453 PrintF("print <fpu register> single\n");
454 }
455 } else {
456 PrintF("print <register> or print <fpu register> single\n");
457 }
316 } 458 }
317 } else if ((strcmp(cmd, "po") == 0) 459 } else if ((strcmp(cmd, "po") == 0)
318 || (strcmp(cmd, "printobject") == 0)) { 460 || (strcmp(cmd, "printobject") == 0)) {
319 if (args == 2) { 461 if (argc == 2) {
320 int32_t value; 462 int32_t value;
321 if (GetValue(arg1, &value)) { 463 if (GetValue(arg1, &value)) {
322 Object* obj = reinterpret_cast<Object*>(value); 464 Object* obj = reinterpret_cast<Object*>(value);
323 PrintF("%s: \n", arg1); 465 PrintF("%s: \n", arg1);
324 #ifdef DEBUG 466 #ifdef DEBUG
325 obj->PrintLn(); 467 obj->PrintLn();
326 #else 468 #else
327 obj->ShortPrint(); 469 obj->ShortPrint();
328 PrintF("\n"); 470 PrintF("\n");
329 #endif 471 #endif
330 } else { 472 } else {
331 PrintF("%s unrecognized\n", arg1); 473 PrintF("%s unrecognized\n", arg1);
332 } 474 }
333 } else { 475 } else {
334 PrintF("printobject <value>\n"); 476 PrintF("printobject <value>\n");
335 } 477 }
478 } else if (strcmp(cmd, "stack") == 0 || strcmp(cmd, "mem") == 0) {
479 int32_t* cur = NULL;
480 int32_t* end = NULL;
481 int next_arg = 1;
482
483 if (strcmp(cmd, "stack") == 0) {
484 cur = reinterpret_cast<int32_t*>(sim_->get_register(Simulator::sp));
485 } else { // "mem"
486 int32_t value;
487 if (!GetValue(arg1, &value)) {
488 PrintF("%s unrecognized\n", arg1);
489 continue;
490 }
491 cur = reinterpret_cast<int32_t*>(value);
492 next_arg++;
493 }
494
495 int32_t words;
496 if (argc == next_arg) {
497 words = 10;
498 } else if (argc == next_arg + 1) {
499 if (!GetValue(argv[next_arg], &words)) {
500 words = 10;
501 }
502 }
503 end = cur + words;
504
505 while (cur < end) {
506 PrintF(" 0x%08x: 0x%08x %10d\n",
507 reinterpret_cast<intptr_t>(cur), *cur, *cur);
508 cur++;
509 }
510
336 } else if ((strcmp(cmd, "disasm") == 0) || (strcmp(cmd, "dpc") == 0)) { 511 } else if ((strcmp(cmd, "disasm") == 0) || (strcmp(cmd, "dpc") == 0)) {
337 disasm::NameConverter converter; 512 disasm::NameConverter converter;
338 disasm::Disassembler dasm(converter); 513 disasm::Disassembler dasm(converter);
339 // use a reasonably large buffer 514 // use a reasonably large buffer
340 v8::internal::EmbeddedVector<char, 256> buffer; 515 v8::internal::EmbeddedVector<char, 256> buffer;
341 516
342 byte_* cur = NULL; 517 byte_* cur = NULL;
343 byte_* end = NULL; 518 byte_* end = NULL;
344 519
345 if (args == 1) { 520 if (argc == 1) {
346 cur = reinterpret_cast<byte_*>(sim_->get_pc()); 521 cur = reinterpret_cast<byte_*>(sim_->get_pc());
347 end = cur + (10 * Instruction::kInstructionSize); 522 end = cur + (10 * Instruction::kInstructionSize);
348 } else if (args == 2) { 523 } else if (argc == 2) {
349 int32_t value; 524 int32_t value;
350 if (GetValue(arg1, &value)) { 525 if (GetValue(arg1, &value)) {
351 cur = reinterpret_cast<byte_*>(value); 526 cur = reinterpret_cast<byte_*>(value);
352 // no length parameter passed, assume 10 instructions 527 // no length parameter passed, assume 10 instructions
353 end = cur + (10 * Instruction::kInstructionSize); 528 end = cur + (10 * Instruction::kInstructionSize);
354 } 529 }
355 } else { 530 } else {
356 int32_t value1; 531 int32_t value1;
357 int32_t value2; 532 int32_t value2;
358 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) { 533 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
359 cur = reinterpret_cast<byte_*>(value1); 534 cur = reinterpret_cast<byte_*>(value1);
360 end = cur + (value2 * Instruction::kInstructionSize); 535 end = cur + (value2 * Instruction::kInstructionSize);
361 } 536 }
362 } 537 }
363 538
364 while (cur < end) { 539 while (cur < end) {
365 dasm.InstructionDecode(buffer, cur); 540 dasm.InstructionDecode(buffer, cur);
366 PrintF(" 0x%08x %s\n", cur, buffer.start()); 541 PrintF(" 0x%08x %s\n",
542 reinterpret_cast<intptr_t>(cur), buffer.start());
367 cur += Instruction::kInstructionSize; 543 cur += Instruction::kInstructionSize;
368 } 544 }
369 } else if (strcmp(cmd, "gdb") == 0) { 545 } else if (strcmp(cmd, "gdb") == 0) {
370 PrintF("relinquishing control to gdb\n"); 546 PrintF("relinquishing control to gdb\n");
371 v8::internal::OS::DebugBreak(); 547 v8::internal::OS::DebugBreak();
372 PrintF("regaining control from gdb\n"); 548 PrintF("regaining control from gdb\n");
373 } else if (strcmp(cmd, "break") == 0) { 549 } else if (strcmp(cmd, "break") == 0) {
374 if (args == 2) { 550 if (argc == 2) {
375 int32_t value; 551 int32_t value;
376 if (GetValue(arg1, &value)) { 552 if (GetValue(arg1, &value)) {
377 if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) { 553 if (!SetBreakpoint(reinterpret_cast<Instruction*>(value))) {
378 PrintF("setting breakpoint failed\n"); 554 PrintF("setting breakpoint failed\n");
379 } 555 }
380 } else { 556 } else {
381 PrintF("%s unrecognized\n", arg1); 557 PrintF("%s unrecognized\n", arg1);
382 } 558 }
383 } else { 559 } else {
384 PrintF("break <address>\n"); 560 PrintF("break <address>\n");
(...skipping 12 matching lines...) Expand all
397 PrintF("\n"); 573 PrintF("\n");
398 574
399 disasm::NameConverter converter; 575 disasm::NameConverter converter;
400 disasm::Disassembler dasm(converter); 576 disasm::Disassembler dasm(converter);
401 // use a reasonably large buffer 577 // use a reasonably large buffer
402 v8::internal::EmbeddedVector<char, 256> buffer; 578 v8::internal::EmbeddedVector<char, 256> buffer;
403 579
404 byte_* cur = NULL; 580 byte_* cur = NULL;
405 byte_* end = NULL; 581 byte_* end = NULL;
406 582
407 if (args == 1) { 583 if (argc == 1) {
408 cur = reinterpret_cast<byte_*>(sim_->get_pc()); 584 cur = reinterpret_cast<byte_*>(sim_->get_pc());
409 end = cur + (10 * Instruction::kInstructionSize); 585 end = cur + (10 * Instruction::kInstructionSize);
410 } else if (args == 2) { 586 } else if (argc == 2) {
411 int32_t value; 587 int32_t value;
412 if (GetValue(arg1, &value)) { 588 if (GetValue(arg1, &value)) {
413 cur = reinterpret_cast<byte_*>(value); 589 cur = reinterpret_cast<byte_*>(value);
414 // no length parameter passed, assume 10 instructions 590 // no length parameter passed, assume 10 instructions
415 end = cur + (10 * Instruction::kInstructionSize); 591 end = cur + (10 * Instruction::kInstructionSize);
416 } 592 }
417 } else { 593 } else {
418 int32_t value1; 594 int32_t value1;
419 int32_t value2; 595 int32_t value2;
420 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) { 596 if (GetValue(arg1, &value1) && GetValue(arg2, &value2)) {
421 cur = reinterpret_cast<byte_*>(value1); 597 cur = reinterpret_cast<byte_*>(value1);
422 end = cur + (value2 * Instruction::kInstructionSize); 598 end = cur + (value2 * Instruction::kInstructionSize);
423 } 599 }
424 } 600 }
425 601
426 while (cur < end) { 602 while (cur < end) {
427 dasm.InstructionDecode(buffer, cur); 603 dasm.InstructionDecode(buffer, cur);
428 PrintF(" 0x%08x %s\n", cur, buffer.start()); 604 PrintF(" 0x%08x %s\n",
605 reinterpret_cast<intptr_t>(cur), buffer.start());
429 cur += Instruction::kInstructionSize; 606 cur += Instruction::kInstructionSize;
430 } 607 }
431 } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) { 608 } else if ((strcmp(cmd, "h") == 0) || (strcmp(cmd, "help") == 0)) {
432 PrintF("cont\n"); 609 PrintF("cont\n");
433 PrintF(" continue execution (alias 'c')\n"); 610 PrintF(" continue execution (alias 'c')\n");
434 PrintF("stepi\n"); 611 PrintF("stepi\n");
435 PrintF(" step one instruction (alias 'si')\n"); 612 PrintF(" step one instruction (alias 'si')\n");
436 PrintF("print <register>\n"); 613 PrintF("print <register>\n");
437 PrintF(" print register content (alias 'p')\n"); 614 PrintF(" print register content (alias 'p')\n");
438 PrintF(" use register name 'all' to print all registers\n"); 615 PrintF(" use register name 'all' to print all registers\n");
439 PrintF("printobject <register>\n"); 616 PrintF("printobject <register>\n");
440 PrintF(" print an object from a register (alias 'po')\n"); 617 PrintF(" print an object from a register (alias 'po')\n");
618 PrintF("stack [<words>]\n");
619 PrintF(" dump stack content, default dump 10 words)\n");
620 PrintF("mem <address> [<words>]\n");
621 PrintF(" dump memory content, default dump 10 words)\n");
441 PrintF("flags\n"); 622 PrintF("flags\n");
442 PrintF(" print flags\n"); 623 PrintF(" print flags\n");
443 PrintF("disasm [<instructions>]\n"); 624 PrintF("disasm [<instructions>]\n");
444 PrintF("disasm [[<address>] <instructions>]\n"); 625 PrintF("disasm [[<address>] <instructions>]\n");
445 PrintF(" disassemble code, default is 10 instructions from pc\n"); 626 PrintF(" disassemble code, default is 10 instructions from pc\n");
446 PrintF("gdb\n"); 627 PrintF("gdb\n");
447 PrintF(" enter gdb\n"); 628 PrintF(" enter gdb\n");
448 PrintF("break <address>\n"); 629 PrintF("break <address>\n");
449 PrintF(" set a break point on the address\n"); 630 PrintF(" set a break point on the address\n");
450 PrintF("del\n"); 631 PrintF("del\n");
(...skipping 13 matching lines...) Expand all
464 RedoBreakpoints(); 645 RedoBreakpoints();
465 646
466 #undef COMMAND_SIZE 647 #undef COMMAND_SIZE
467 #undef ARG_SIZE 648 #undef ARG_SIZE
468 649
469 #undef STR 650 #undef STR
470 #undef XSTR 651 #undef XSTR
471 } 652 }
472 653
473 654
655 static bool ICacheMatch(void* one, void* two) {
656 ASSERT((reinterpret_cast<intptr_t>(one) & CachePage::kPageMask) == 0);
657 ASSERT((reinterpret_cast<intptr_t>(two) & CachePage::kPageMask) == 0);
658 return one == two;
659 }
660
661
662 static uint32_t ICacheHash(void* key) {
663 return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(key)) >> 2;
664 }
665
666
667 static bool AllOnOnePage(uintptr_t start, int size) {
668 intptr_t start_page = (start & ~CachePage::kPageMask);
669 intptr_t end_page = ((start + size) & ~CachePage::kPageMask);
670 return start_page == end_page;
671 }
672
673
674 void Simulator::FlushICache(void* start_addr, size_t size) {
675 intptr_t start = reinterpret_cast<intptr_t>(start_addr);
676 int intra_line = (start & CachePage::kLineMask);
677 start -= intra_line;
678 size += intra_line;
679 size = ((size - 1) | CachePage::kLineMask) + 1;
680 int offset = (start & CachePage::kPageMask);
681 while (!AllOnOnePage(start, size - 1)) {
682 int bytes_to_flush = CachePage::kPageSize - offset;
683 FlushOnePage(start, bytes_to_flush);
684 start += bytes_to_flush;
685 size -= bytes_to_flush;
686 ASSERT_EQ(0, start & CachePage::kPageMask);
687 offset = 0;
688 }
689 if (size != 0) {
690 FlushOnePage(start, size);
691 }
692 }
693
694
695 CachePage* Simulator::GetCachePage(void* page) {
696 v8::internal::HashMap::Entry* entry = i_cache_->Lookup(page,
697 ICacheHash(page),
698 true);
699 if (entry->value == NULL) {
700 CachePage* new_page = new CachePage();
701 entry->value = new_page;
702 }
703 return reinterpret_cast<CachePage*>(entry->value);
704 }
705
706
707 // Flush from start up to and not including start + size.
708 void Simulator::FlushOnePage(intptr_t start, int size) {
709 ASSERT(size <= CachePage::kPageSize);
710 ASSERT(AllOnOnePage(start, size - 1));
711 ASSERT((start & CachePage::kLineMask) == 0);
712 ASSERT((size & CachePage::kLineMask) == 0);
713 void* page = reinterpret_cast<void*>(start & (~CachePage::kPageMask));
714 int offset = (start & CachePage::kPageMask);
715 CachePage* cache_page = GetCachePage(page);
716 char* valid_bytemap = cache_page->ValidityByte(offset);
717 memset(valid_bytemap, CachePage::LINE_INVALID, size >> CachePage::kLineShift);
718 }
719
720
721 void Simulator::CheckICache(Instruction* instr) {
722 intptr_t address = reinterpret_cast<intptr_t>(instr);
723 void* page = reinterpret_cast<void*>(address & (~CachePage::kPageMask));
724 void* line = reinterpret_cast<void*>(address & (~CachePage::kLineMask));
725 int offset = (address & CachePage::kPageMask);
726 CachePage* cache_page = GetCachePage(page);
727 char* cache_valid_byte = cache_page->ValidityByte(offset);
728 bool cache_hit = (*cache_valid_byte == CachePage::LINE_VALID);
729 char* cached_line = cache_page->CachedData(offset & ~CachePage::kLineMask);
730 if (cache_hit) {
731 // Check that the data in memory matches the contents of the I-cache.
732 CHECK(memcmp(reinterpret_cast<void*>(instr),
733 cache_page->CachedData(offset),
734 Instruction::kInstructionSize) == 0);
735 } else {
736 // Cache miss. Load memory into the cache.
737 memcpy(cached_line, line, CachePage::kLineLength);
738 *cache_valid_byte = CachePage::LINE_VALID;
739 }
740 }
741
742
474 // Create one simulator per thread and keep it in thread local storage. 743 // Create one simulator per thread and keep it in thread local storage.
475 static v8::internal::Thread::LocalStorageKey simulator_key; 744 static v8::internal::Thread::LocalStorageKey simulator_key;
476 745
477 746
478 bool Simulator::initialized_ = false; 747 bool Simulator::initialized_ = false;
479 748
480 749
481 void Simulator::Initialize() { 750 void Simulator::Initialize() {
482 if (initialized_) return; 751 if (initialized_) return;
483 simulator_key = v8::internal::Thread::CreateThreadLocalKey(); 752 simulator_key = v8::internal::Thread::CreateThreadLocalKey();
484 initialized_ = true; 753 initialized_ = true;
485 ::v8::internal::ExternalReference::set_redirector(&RedirectExternalReference); 754 ::v8::internal::ExternalReference::set_redirector(&RedirectExternalReference);
486 } 755 }
487 756
488 757
758 v8::internal::HashMap* Simulator::i_cache_ = NULL;
759
489 Simulator::Simulator() { 760 Simulator::Simulator() {
761 if (i_cache_ == NULL) {
762 i_cache_ = new v8::internal::HashMap(&ICacheMatch);
763 }
490 Initialize(); 764 Initialize();
491 // Setup simulator support first. Some of this information is needed to 765 // Setup simulator support first. Some of this information is needed to
492 // setup the architecture state. 766 // setup the architecture state.
493 size_t stack_size = 1 * 1024*1024; // allocate 1MB for stack 767 stack_ = reinterpret_cast<char*>(malloc(stack_size_));
494 stack_ = reinterpret_cast<char*>(malloc(stack_size));
495 pc_modified_ = false; 768 pc_modified_ = false;
496 icount_ = 0; 769 icount_ = 0;
770 break_count_ = 0;
497 break_pc_ = NULL; 771 break_pc_ = NULL;
498 break_instr_ = 0; 772 break_instr_ = 0;
499 773
500 // Setup architecture state. 774 // Setup architecture state.
501 // All registers are initialized to zero to start with. 775 // All registers are initialized to zero to start with.
502 for (int i = 0; i < kNumSimuRegisters; i++) { 776 for (int i = 0; i < kNumSimuRegisters; i++) {
503 registers_[i] = 0; 777 registers_[i] = 0;
504 } 778 }
779 for (int i = 0; i < kNumFPURegisters; i++) {
780 FPUregisters_[i] = 0;
781 }
782 FCSR_ = 0;
505 783
506 // The sp is initialized to point to the bottom (high address) of the 784 // The sp is initialized to point to the bottom (high address) of the
507 // allocated stack area. To be safe in potential stack underflows we leave 785 // allocated stack area. To be safe in potential stack underflows we leave
508 // some buffer below. 786 // some buffer below.
509 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size - 64; 787 registers_[sp] = reinterpret_cast<int32_t>(stack_) + stack_size_ - 64;
510 // The ra and pc are initialized to a known bad value that will cause an 788 // The ra and pc are initialized to a known bad value that will cause an
511 // access violation if the simulator ever tries to execute it. 789 // access violation if the simulator ever tries to execute it.
512 registers_[pc] = bad_ra; 790 registers_[pc] = bad_ra;
513 registers_[ra] = bad_ra; 791 registers_[ra] = bad_ra;
514 InitializeCoverage(); 792 InitializeCoverage();
793 for (int i = 0; i < kNumExceptions; i++) {
794 exceptions[i] = 0;
795 }
515 } 796 }
516 797
517 798
518 // When the generated code calls an external reference we need to catch that in 799 // When the generated code calls an external reference we need to catch that in
519 // the simulator. The external reference will be a function compiled for the 800 // the simulator. The external reference will be a function compiled for the
520 // host architecture. We need to call that function instead of trying to 801 // host architecture. We need to call that function instead of trying to
521 // execute it with the simulator. We do that by redirecting the external 802 // execute it with the simulator. We do that by redirecting the external
522 // reference to a swi (software-interrupt) instruction that is handled by 803 // reference to a swi (software-interrupt) instruction that is handled by
523 // the simulator. We write the original destination of the jump just at a known 804 // the simulator. We write the original destination of the jump just at a known
524 // offset from the swi instruction so the simulator knows what to call. 805 // offset from the swi instruction so the simulator knows what to call.
525 class Redirection { 806 class Redirection {
526 public: 807 public:
527 Redirection(void* external_function, bool fp_return) 808 Redirection(void* external_function, ExternalReference::Type type)
528 : external_function_(external_function), 809 : external_function_(external_function),
529 swi_instruction_(rtCallRedirInstr), 810 swi_instruction_(rtCallRedirInstr),
530 fp_return_(fp_return), 811 type_(type),
531 next_(list_) { 812 next_(list_) {
813 Simulator::current()->
814 FlushICache(reinterpret_cast<void*>(&swi_instruction_),
815 Instruction::kInstructionSize);
532 list_ = this; 816 list_ = this;
533 } 817 }
534 818
535 void* address_of_swi_instruction() { 819 void* address_of_swi_instruction() {
536 return reinterpret_cast<void*>(&swi_instruction_); 820 return reinterpret_cast<void*>(&swi_instruction_);
537 } 821 }
538 822
539 void* external_function() { return external_function_; } 823 void* external_function() { return external_function_; }
540 bool fp_return() { return fp_return_; } 824 ExternalReference::Type type() { return type_; }
541 825
542 static Redirection* Get(void* external_function, bool fp_return) { 826 static Redirection* Get(void* external_function,
827 ExternalReference::Type type) {
543 Redirection* current; 828 Redirection* current;
544 for (current = list_; current != NULL; current = current->next_) { 829 for (current = list_; current != NULL; current = current->next_) {
545 if (current->external_function_ == external_function) return current; 830 if (current->external_function_ == external_function) return current;
546 } 831 }
547 return new Redirection(external_function, fp_return); 832 return new Redirection(external_function, type);
548 } 833 }
549 834
550 static Redirection* FromSwiInstruction(Instruction* swi_instruction) { 835 static Redirection* FromSwiInstruction(Instruction* swi_instruction) {
551 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction); 836 char* addr_of_swi = reinterpret_cast<char*>(swi_instruction);
552 char* addr_of_redirection = 837 char* addr_of_redirection =
553 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_); 838 addr_of_swi - OFFSET_OF(Redirection, swi_instruction_);
554 return reinterpret_cast<Redirection*>(addr_of_redirection); 839 return reinterpret_cast<Redirection*>(addr_of_redirection);
555 } 840 }
556 841
557 private: 842 private:
558 void* external_function_; 843 void* external_function_;
559 uint32_t swi_instruction_; 844 uint32_t swi_instruction_;
560 bool fp_return_; 845 ExternalReference::Type type_;
561 Redirection* next_; 846 Redirection* next_;
562 static Redirection* list_; 847 static Redirection* list_;
563 }; 848 };
564 849
565 850
566 Redirection* Redirection::list_ = NULL; 851 Redirection* Redirection::list_ = NULL;
567 852
568 853
569 void* Simulator::RedirectExternalReference(void* external_function, 854 void* Simulator::RedirectExternalReference(void* external_function,
570 bool fp_return) { 855 ExternalReference::Type type) {
571 Redirection* redirection = Redirection::Get(external_function, fp_return); 856 Redirection* redirection = Redirection::Get(external_function, type);
572 return redirection->address_of_swi_instruction(); 857 return redirection->address_of_swi_instruction();
573 } 858 }
574 859
575 860
576 // Get the active Simulator for the current thread. 861 // Get the active Simulator for the current thread.
577 Simulator* Simulator::current() { 862 Simulator* Simulator::current() {
578 Initialize(); 863 Initialize();
579 Simulator* sim = reinterpret_cast<Simulator*>( 864 Simulator* sim = reinterpret_cast<Simulator*>(
580 v8::internal::Thread::GetThreadLocal(simulator_key)); 865 v8::internal::Thread::GetThreadLocal(simulator_key));
581 if (sim == NULL) { 866 if (sim == NULL) {
(...skipping 10 matching lines...) Expand all
592 void Simulator::set_register(int reg, int32_t value) { 877 void Simulator::set_register(int reg, int32_t value) {
593 ASSERT((reg >= 0) && (reg < kNumSimuRegisters)); 878 ASSERT((reg >= 0) && (reg < kNumSimuRegisters));
594 if (reg == pc) { 879 if (reg == pc) {
595 pc_modified_ = true; 880 pc_modified_ = true;
596 } 881 }
597 882
598 // zero register always hold 0. 883 // zero register always hold 0.
599 registers_[reg] = (reg == 0) ? 0 : value; 884 registers_[reg] = (reg == 0) ? 0 : value;
600 } 885 }
601 886
887
602 void Simulator::set_fpu_register(int fpureg, int32_t value) { 888 void Simulator::set_fpu_register(int fpureg, int32_t value) {
603 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters)); 889 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
604 FPUregisters_[fpureg] = value; 890 FPUregisters_[fpureg] = value;
605 } 891 }
606 892
607 void Simulator::set_fpu_register_double(int fpureg, double value) { 893
608 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0)); 894 void Simulator::set_fpu_register_float(int fpureg, float value) {
609 *v8i::BitCast<double*>(&FPUregisters_[fpureg]) = value; 895 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
896 *BitCast<float*>(&FPUregisters_[fpureg]) = value;
610 } 897 }
611 898
612 899
900 void Simulator::set_fpu_register_double(int fpureg, double value) {
901 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
902 *BitCast<double*>(&FPUregisters_[fpureg]) = value;
903 }
904
905
613 // Get the register from the architecture state. This function does handle 906 // Get the register from the architecture state. This function does handle
614 // the special case of accessing the PC register. 907 // the special case of accessing the PC register.
615 int32_t Simulator::get_register(int reg) const { 908 int32_t Simulator::get_register(int reg) const {
616 ASSERT((reg >= 0) && (reg < kNumSimuRegisters)); 909 ASSERT((reg >= 0) && (reg < kNumSimuRegisters));
617 if (reg == 0) 910 if (reg == 0)
618 return 0; 911 return 0;
619 else 912 else
620 return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0); 913 return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0);
621 } 914 }
622 915
916
623 int32_t Simulator::get_fpu_register(int fpureg) const { 917 int32_t Simulator::get_fpu_register(int fpureg) const {
624 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters)); 918 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
625 return FPUregisters_[fpureg]; 919 return FPUregisters_[fpureg];
626 } 920 }
627 921
922
923 int64_t Simulator::get_fpu_register_long(int fpureg) const {
924 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
925 return *BitCast<int64_t*>(
926 const_cast<int32_t*>(&FPUregisters_[fpureg]));
927 }
928
929
930 float Simulator::get_fpu_register_float(int fpureg) const {
931 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters));
932 return *BitCast<float*>(
933 const_cast<int32_t*>(&FPUregisters_[fpureg]));
934 }
935
936
628 double Simulator::get_fpu_register_double(int fpureg) const { 937 double Simulator::get_fpu_register_double(int fpureg) const {
629 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0)); 938 ASSERT((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0));
630 return *v8i::BitCast<double*>(const_cast<int32_t*>(&FPUregisters_[fpureg])); 939 return *BitCast<double*>(const_cast<int32_t*>(&FPUregisters_[fpureg]));
631 } 940 }
632 941
942
943 // Helper functions for setting and testing the FCSR register's bits.
944 void Simulator::set_fcsr_bit(uint32_t cc, bool value) {
945 if (value) {
946 FCSR_ |= (1 << cc);
947 } else {
948 FCSR_ &= ~(1 << cc);
949 }
950 }
951
952
953 bool Simulator::test_fcsr_bit(uint32_t cc) {
954 return FCSR_ & (1 << cc);
955 }
956
957
958 // Sets the rounding error codes in FCSR based on the result of the rounding.
959 // Returns true if the operation was invalid.
960 bool Simulator::set_fcsr_round_error(double original, double rounded) {
961 if (!isfinite(original) ||
962 rounded > LONG_MAX ||
963 rounded < LONG_MIN) {
964 set_fcsr_bit(6, true); // Invalid operation.
965 return true;
966 } else if (original != static_cast<double>(rounded)) {
967 set_fcsr_bit(2, true); // Inexact.
968 }
969 return false;
970 }
971
972
633 // Raw access to the PC register. 973 // Raw access to the PC register.
634 void Simulator::set_pc(int32_t value) { 974 void Simulator::set_pc(int32_t value) {
635 pc_modified_ = true; 975 pc_modified_ = true;
636 registers_[pc] = value; 976 registers_[pc] = value;
637 } 977 }
638 978
979
980 bool Simulator::has_bad_pc() const {
981 return ((registers_[pc] == bad_ra) || (registers_[pc] == end_sim_pc));
982 }
983
984
639 // Raw access to the PC register without the special adjustment when reading. 985 // Raw access to the PC register without the special adjustment when reading.
640 int32_t Simulator::get_pc() const { 986 int32_t Simulator::get_pc() const {
641 return registers_[pc]; 987 return registers_[pc];
642 } 988 }
643 989
644 990
645 // The MIPS cannot do unaligned reads and writes. On some MIPS platforms an 991 // The MIPS cannot do unaligned reads and writes. On some MIPS platforms an
646 // interrupt is caused. On others it does a funky rotation thing. For now we 992 // interrupt is caused. On others it does a funky rotation thing. For now we
647 // simply disallow unaligned reads, but at some point we may want to move to 993 // simply disallow unaligned reads, but at some point we may want to move to
648 // emulating the rotate behaviour. Note that simulator runs have the runtime 994 // emulating the rotate behaviour. Note that simulator runs have the runtime
649 // system running directly on the host system and only generated code is 995 // system running directly on the host system and only generated code is
650 // executed in the simulator. Since the host is typically IA32 we will not 996 // executed in the simulator. Since the host is typically IA32 we will not
651 // get the correct MIPS-like behaviour on unaligned accesses. 997 // get the correct MIPS-like behaviour on unaligned accesses.
652 998
653 int Simulator::ReadW(int32_t addr, Instruction* instr) { 999 int Simulator::ReadW(int32_t addr, Instruction* instr) {
654 if ((addr & v8i::kPointerAlignmentMask) == 0) { 1000 if (addr >=0 && addr < 0x400) {
1001 // this has to be a NULL-dereference
1002 Debugger dbg(this);
1003 dbg.Debug();
1004 }
1005 if ((addr & kPointerAlignmentMask) == 0) {
655 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); 1006 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
656 return *ptr; 1007 return *ptr;
657 } 1008 }
658 PrintF("Unaligned read at 0x%08x, pc=%p\n", addr, instr); 1009 PrintF("Unaligned read at 0x%08x, pc=%p\n", addr,
659 OS::Abort(); 1010 reinterpret_cast<void*>(instr));
1011 Debugger dbg(this);
1012 dbg.Debug();
660 return 0; 1013 return 0;
661 } 1014 }
662 1015
663 1016
664 void Simulator::WriteW(int32_t addr, int value, Instruction* instr) { 1017 void Simulator::WriteW(int32_t addr, int value, Instruction* instr) {
665 if ((addr & v8i::kPointerAlignmentMask) == 0) { 1018 if (addr >= 0 && addr < 0x400) {
1019 // this has to be a NULL-dereference
1020 Debugger dbg(this);
1021 dbg.Debug();
1022 }
1023 if ((addr & kPointerAlignmentMask) == 0) {
666 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr); 1024 intptr_t* ptr = reinterpret_cast<intptr_t*>(addr);
667 *ptr = value; 1025 *ptr = value;
668 return; 1026 return;
669 } 1027 }
670 PrintF("Unaligned write at 0x%08x, pc=%p\n", addr, instr); 1028 PrintF("Unaligned write at 0x%08x, pc=%p\n", addr,
671 OS::Abort(); 1029 reinterpret_cast<void*>(instr));
1030 Debugger dbg(this);
1031 dbg.Debug();
672 } 1032 }
673 1033
674 1034
675 double Simulator::ReadD(int32_t addr, Instruction* instr) { 1035 double Simulator::ReadD(int32_t addr, Instruction* instr) {
676 if ((addr & kDoubleAlignmentMask) == 0) { 1036 if ((addr & kDoubleAlignmentMask) == 0) {
677 double* ptr = reinterpret_cast<double*>(addr); 1037 double* ptr = reinterpret_cast<double*>(addr);
678 return *ptr; 1038 return *ptr;
679 } 1039 }
680 PrintF("Unaligned read at 0x%08x, pc=%p\n", addr, instr); 1040 PrintF("Unaligned (double) read at 0x%08x, pc=%p\n", addr,
1041 reinterpret_cast<void*>(instr));
681 OS::Abort(); 1042 OS::Abort();
682 return 0; 1043 return 0;
683 } 1044 }
684 1045
685 1046
686 void Simulator::WriteD(int32_t addr, double value, Instruction* instr) { 1047 void Simulator::WriteD(int32_t addr, double value, Instruction* instr) {
687 if ((addr & kDoubleAlignmentMask) == 0) { 1048 if ((addr & kDoubleAlignmentMask) == 0) {
688 double* ptr = reinterpret_cast<double*>(addr); 1049 double* ptr = reinterpret_cast<double*>(addr);
689 *ptr = value; 1050 *ptr = value;
690 return; 1051 return;
691 } 1052 }
692 PrintF("Unaligned write at 0x%08x, pc=%p\n", addr, instr); 1053 PrintF("Unaligned (double) write at 0x%08x, pc=%p\n", addr,
1054 reinterpret_cast<void*>(instr));
693 OS::Abort(); 1055 OS::Abort();
694 } 1056 }
695 1057
696 1058
697 uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) { 1059 uint16_t Simulator::ReadHU(int32_t addr, Instruction* instr) {
698 if ((addr & 1) == 0) { 1060 if ((addr & 1) == 0) {
699 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 1061 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
700 return *ptr; 1062 return *ptr;
701 } 1063 }
702 PrintF("Unaligned unsigned halfword read at 0x%08x, pc=%p\n", addr, instr); 1064 PrintF("Unaligned unsigned halfword read at 0x%08x, pc=%p\n", addr,
1065 reinterpret_cast<void*>(instr));
703 OS::Abort(); 1066 OS::Abort();
704 return 0; 1067 return 0;
705 } 1068 }
706 1069
707 1070
708 int16_t Simulator::ReadH(int32_t addr, Instruction* instr) { 1071 int16_t Simulator::ReadH(int32_t addr, Instruction* instr) {
709 if ((addr & 1) == 0) { 1072 if ((addr & 1) == 0) {
710 int16_t* ptr = reinterpret_cast<int16_t*>(addr); 1073 int16_t* ptr = reinterpret_cast<int16_t*>(addr);
711 return *ptr; 1074 return *ptr;
712 } 1075 }
713 PrintF("Unaligned signed halfword read at 0x%08x, pc=%p\n", addr, instr); 1076 PrintF("Unaligned signed halfword read at 0x%08x, pc=%p\n", addr,
1077 reinterpret_cast<void*>(instr));
714 OS::Abort(); 1078 OS::Abort();
715 return 0; 1079 return 0;
716 } 1080 }
717 1081
718 1082
719 void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) { 1083 void Simulator::WriteH(int32_t addr, uint16_t value, Instruction* instr) {
720 if ((addr & 1) == 0) { 1084 if ((addr & 1) == 0) {
721 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr); 1085 uint16_t* ptr = reinterpret_cast<uint16_t*>(addr);
722 *ptr = value; 1086 *ptr = value;
723 return; 1087 return;
724 } 1088 }
725 PrintF("Unaligned unsigned halfword write at 0x%08x, pc=%p\n", addr, instr); 1089 PrintF("Unaligned unsigned halfword write at 0x%08x, pc=%p\n", addr,
1090 reinterpret_cast<void*>(instr));
726 OS::Abort(); 1091 OS::Abort();
727 } 1092 }
728 1093
729 1094
730 void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) { 1095 void Simulator::WriteH(int32_t addr, int16_t value, Instruction* instr) {
731 if ((addr & 1) == 0) { 1096 if ((addr & 1) == 0) {
732 int16_t* ptr = reinterpret_cast<int16_t*>(addr); 1097 int16_t* ptr = reinterpret_cast<int16_t*>(addr);
733 *ptr = value; 1098 *ptr = value;
734 return; 1099 return;
735 } 1100 }
736 PrintF("Unaligned halfword write at 0x%08x, pc=%p\n", addr, instr); 1101 PrintF("Unaligned halfword write at 0x%08x, pc=%p\n", addr,
1102 reinterpret_cast<void*>(instr));
737 OS::Abort(); 1103 OS::Abort();
738 } 1104 }
739 1105
740 1106
741 uint32_t Simulator::ReadBU(int32_t addr) { 1107 uint32_t Simulator::ReadBU(int32_t addr) {
742 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 1108 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
743 return *ptr & 0xff; 1109 return *ptr & 0xff;
744 } 1110 }
745 1111
746 1112
747 int32_t Simulator::ReadB(int32_t addr) { 1113 int32_t Simulator::ReadB(int32_t addr) {
748 int8_t* ptr = reinterpret_cast<int8_t*>(addr); 1114 int8_t* ptr = reinterpret_cast<int8_t*>(addr);
749 return ((*ptr << 24) >> 24) & 0xff; 1115 return *ptr;
750 } 1116 }
751 1117
752 1118
753 void Simulator::WriteB(int32_t addr, uint8_t value) { 1119 void Simulator::WriteB(int32_t addr, uint8_t value) {
754 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr); 1120 uint8_t* ptr = reinterpret_cast<uint8_t*>(addr);
755 *ptr = value; 1121 *ptr = value;
756 } 1122 }
757 1123
758 1124
759 void Simulator::WriteB(int32_t addr, int8_t value) { 1125 void Simulator::WriteB(int32_t addr, int8_t value) {
760 int8_t* ptr = reinterpret_cast<int8_t*>(addr); 1126 int8_t* ptr = reinterpret_cast<int8_t*>(addr);
761 *ptr = value; 1127 *ptr = value;
762 } 1128 }
763 1129
764 1130
765 // Returns the limit of the stack area to enable checking for stack overflows. 1131 // Returns the limit of the stack area to enable checking for stack overflows.
766 uintptr_t Simulator::StackLimit() const { 1132 uintptr_t Simulator::StackLimit() const {
767 // Leave a safety margin of 256 bytes to prevent overrunning the stack when 1133 // Leave a safety margin of 256 bytes to prevent overrunning the stack when
768 // pushing values. 1134 // pushing values.
769 return reinterpret_cast<uintptr_t>(stack_) + 256; 1135 return reinterpret_cast<uintptr_t>(stack_) + 256;
770 } 1136 }
771 1137
772 1138
773 // Unsupported instructions use Format to print an error and stop execution. 1139 // Unsupported instructions use Format to print an error and stop execution.
774 void Simulator::Format(Instruction* instr, const char* format) { 1140 void Simulator::Format(Instruction* instr, const char* format) {
775 PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n", 1141 PrintF("Simulator found unsupported instruction:\n 0x%08x: %s\n",
776 instr, format); 1142 reinterpret_cast<intptr_t>(instr), format);
777 UNIMPLEMENTED_MIPS(); 1143 UNIMPLEMENTED_MIPS();
778 } 1144 }
779 1145
780 1146
781 // Calls into the V8 runtime are based on this very simple interface. 1147 // Calls into the V8 runtime are based on this very simple interface.
782 // Note: To be able to return two values from some calls the code in runtime.cc 1148 // Note: To be able to return two values from some calls the code in runtime.cc
783 // uses the ObjectPair which is essentially two 32-bit values stuffed into a 1149 // uses the ObjectPair which is essentially two 32-bit values stuffed into a
784 // 64-bit value. With the code below we assume that all runtime calls return 1150 // 64-bit value. With the code below we assume that all runtime calls return
785 // 64 bits of result. If they don't, the r1 result register contains a bogus 1151 // 64 bits of result. If they don't, the v1 result register contains a bogus
786 // value, which is fine because it is caller-saved. 1152 // value, which is fine because it is caller-saved.
787 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0, 1153 typedef int64_t (*SimulatorRuntimeCall)(int32_t arg0,
788 int32_t arg1, 1154 int32_t arg1,
789 int32_t arg2, 1155 int32_t arg2,
790 int32_t arg3); 1156 int32_t arg3,
791 typedef double (*SimulatorRuntimeFPCall)(double fparg0, 1157 int32_t arg4);
792 double fparg1); 1158 typedef double (*SimulatorRuntimeFPCall)(int32_t arg0,
793 1159 int32_t arg1,
1160 int32_t arg2,
1161 int32_t arg3);
794 1162
795 // Software interrupt instructions are used by the simulator to call into the 1163 // Software interrupt instructions are used by the simulator to call into the
796 // C-based V8 runtime. 1164 // C-based V8 runtime. They are also used for debugging with simulator.
797 void Simulator::SoftwareInterrupt(Instruction* instr) { 1165 void Simulator::SoftwareInterrupt(Instruction* instr) {
1166 // There are several instructions that could get us here,
1167 // the break_ instruction, or several variants of traps. All
1168 // Are "SPECIAL" class opcode, and are distinuished by function.
1169 int32_t func = instr->FunctionFieldRaw();
1170 int32_t code = (func == BREAK) ? instr->Bits(25, 6) : -1;
1171
798 // We first check if we met a call_rt_redirected. 1172 // We first check if we met a call_rt_redirected.
799 if (instr->InstructionBits() == rtCallRedirInstr) { 1173 if (instr->InstructionBits() == rtCallRedirInstr) {
800 Redirection* redirection = Redirection::FromSwiInstruction(instr); 1174 Redirection* redirection = Redirection::FromSwiInstruction(instr);
801 int32_t arg0 = get_register(a0); 1175 int32_t arg0 = get_register(a0);
802 int32_t arg1 = get_register(a1); 1176 int32_t arg1 = get_register(a1);
803 int32_t arg2 = get_register(a2); 1177 int32_t arg2 = get_register(a2);
804 int32_t arg3 = get_register(a3); 1178 int32_t arg3 = get_register(a3);
805 // fp args are (not always) in f12 and f14. 1179 int32_t arg4 = 0;
806 // See MIPS conventions for more details. 1180
807 double fparg0 = get_fpu_register_double(f12); 1181 // We try to make arg4 = *sp, but need to check if sp is valid first.
808 double fparg1 = get_fpu_register_double(f14); 1182 // This is basically a fix for cctest test-api/CatchStackOverflow which
1183 // causes the stack to overflow. For some reason arm doesn't need this
1184 // stack check here.
1185 int32_t* stack_pointer = reinterpret_cast<int32_t*>(get_register(sp));
1186 int32_t* stack = reinterpret_cast<int32_t*>(stack_);
1187 if (stack_pointer >= stack && stack_pointer < stack + stack_size_) {
1188 arg4 = *stack_pointer;
1189 }
809 // This is dodgy but it works because the C entry stubs are never moved. 1190 // This is dodgy but it works because the C entry stubs are never moved.
810 // See comment in codegen-arm.cc and bug 1242173. 1191 // See comment in codegen-arm.cc and bug 1242173.
811 int32_t saved_ra = get_register(ra); 1192 int32_t saved_ra = get_register(ra);
812 if (redirection->fp_return()) { 1193
813 intptr_t external = 1194 intptr_t external =
814 reinterpret_cast<intptr_t>(redirection->external_function()); 1195 reinterpret_cast<int32_t>(redirection->external_function());
1196 SimulatorRuntimeCall target =
1197 reinterpret_cast<SimulatorRuntimeCall>(external);
1198
1199 if (::v8::internal::FLAG_trace_sim) {
1200 PrintF(
1201 "Call to host function at %p args %08x, %08x, %08x, %08x, %0xc",
1202 FUNCTION_ADDR(target),
1203 arg0,
1204 arg1,
1205 arg2,
1206 arg3,
1207 arg4);
1208 }
1209
1210 // Based on CpuFeatures::IsSupported(FPU), Mips will use either hardware
1211 // FPU, or gcc soft-float routines. Hardware FPU is simulated in this
1212 // simulator. Soft-float has additional abstraction of ExternalReference,
1213 // to support serialization. Finally, when simulated on x86 host, the
1214 // x86 softfloat routines are used, and this Redirection infrastructure
1215 // lets simulated-mips make calls into x86 C code.
1216 // When doing that, the 'double' return type must be handled differently
1217 // than the usual int64_t return. The data is returned in different
1218 // registers and cannot be cast from one type to the other. However, the
1219 // calling arguments are passed the same way in both cases.
1220 if (redirection->type() == ExternalReference::FP_RETURN_CALL) {
815 SimulatorRuntimeFPCall target = 1221 SimulatorRuntimeFPCall target =
816 reinterpret_cast<SimulatorRuntimeFPCall>(external); 1222 reinterpret_cast<SimulatorRuntimeFPCall>(external);
817 if (::v8::internal::FLAG_trace_sim) { 1223 double result = target(arg0, arg1, arg2, arg3);
818 PrintF("Call to host function at %p with args %f, %f\n", 1224 // fp result -> registers v0 and v1.
819 FUNCTION_ADDR(target), fparg0, fparg1); 1225 int32_t gpreg_pair[2];
820 } 1226 memcpy(&gpreg_pair[0], &result, 2 * sizeof(int32_t));
821 double result = target(fparg0, fparg1); 1227 set_register(v0, gpreg_pair[0]);
822 set_fpu_register_double(f0, result); 1228 set_register(v1, gpreg_pair[1]);
1229 } else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
1230 PrintF("Mips does not yet support ExternalReference::DIRECT_API_CALL\n");
1231 ASSERT(redirection->type() != ExternalReference::DIRECT_API_CALL);
1232 } else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
1233 PrintF("Mips does not support ExternalReference::DIRECT_GETTER_CALL\n");
1234 ASSERT(redirection->type() != ExternalReference::DIRECT_GETTER_CALL);
823 } else { 1235 } else {
824 intptr_t external = 1236 int64_t result = target(arg0, arg1, arg2, arg3, arg4);
825 reinterpret_cast<int32_t>(redirection->external_function()); 1237 set_register(v0, static_cast<int32_t>(result));
826 SimulatorRuntimeCall target = 1238 set_register(v1, static_cast<int32_t>(result >> 32));
827 reinterpret_cast<SimulatorRuntimeCall>(external); 1239 }
828 if (::v8::internal::FLAG_trace_sim) { 1240 if (::v8::internal::FLAG_trace_sim) {
829 PrintF( 1241 PrintF("Returned %08x : %08x\n", get_register(v1), get_register(v0));
830 "Call to host function at %p with args %08x, %08x, %08x, %08x\n",
831 FUNCTION_ADDR(target),
832 arg0,
833 arg1,
834 arg2,
835 arg3);
836 }
837 int64_t result = target(arg0, arg1, arg2, arg3);
838 int32_t lo_res = static_cast<int32_t>(result);
839 int32_t hi_res = static_cast<int32_t>(result >> 32);
840 if (::v8::internal::FLAG_trace_sim) {
841 PrintF("Returned %08x\n", lo_res);
842 }
843 set_register(v0, lo_res);
844 set_register(v1, hi_res);
845 } 1242 }
846 set_register(ra, saved_ra); 1243 set_register(ra, saved_ra);
847 set_pc(get_register(ra)); 1244 set_pc(get_register(ra));
1245
1246 } else if (func == BREAK && code >= 0 && code < 16) {
1247 // First 16 break_ codes interpreted as debug markers.
1248 Debugger dbg(this);
1249 ++break_count_;
1250 PrintF("\n---- break %d marker: %3d (instr count: %8d) ----------"
1251 "----------------------------------",
1252 code, break_count_, icount_);
1253 dbg.PrintAllRegs(); // Print registers and continue running.
848 } else { 1254 } else {
1255 // All remaining break_ codes, and all traps are handled here.
849 Debugger dbg(this); 1256 Debugger dbg(this);
850 dbg.Debug(); 1257 dbg.Debug();
851 } 1258 }
852 } 1259 }
853 1260
1261
854 void Simulator::SignalExceptions() { 1262 void Simulator::SignalExceptions() {
855 for (int i = 1; i < kNumExceptions; i++) { 1263 for (int i = 1; i < kNumExceptions; i++) {
856 if (exceptions[i] != 0) { 1264 if (exceptions[i] != 0) {
857 V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", i); 1265 V8_Fatal(__FILE__, __LINE__, "Error: Exception %i raised.", i);
858 } 1266 }
859 } 1267 }
860 } 1268 }
861 1269
1270
862 // Handle execution based on instruction types. 1271 // Handle execution based on instruction types.
863 void Simulator::DecodeTypeRegister(Instruction* instr) {
864 // Instruction fields
865 Opcode op = instr->OpcodeFieldRaw();
866 int32_t rs_reg = instr->RsField();
867 int32_t rs = get_register(rs_reg);
868 uint32_t rs_u = static_cast<uint32_t>(rs);
869 int32_t rt_reg = instr->RtField();
870 int32_t rt = get_register(rt_reg);
871 uint32_t rt_u = static_cast<uint32_t>(rt);
872 int32_t rd_reg = instr->RdField();
873 uint32_t sa = instr->SaField();
874 1272
875 int32_t fs_reg= instr->FsField(); 1273 void Simulator::ConfigureTypeRegister(Instruction* instr,
1274 int32_t& alu_out,
1275 int64_t& i64hilo,
1276 uint64_t& u64hilo,
1277 int32_t& next_pc,
1278 bool& do_interrupt) {
1279 // Every local variable declared here needs to be const.
1280 // This is to make sure that changed values are sent back to
1281 // DecodeTypeRegister correctly.
876 1282
877 // ALU output 1283 // Instruction fields.
878 // It should not be used as is. Instructions using it should always initialize 1284 const Opcode op = instr->OpcodeFieldRaw();
879 // it first. 1285 const int32_t rs_reg = instr->RsValue();
880 int32_t alu_out = 0x12345678; 1286 const int32_t rs = get_register(rs_reg);
881 // Output or temporary for floating point. 1287 const uint32_t rs_u = static_cast<uint32_t>(rs);
882 double fp_out = 0.0; 1288 const int32_t rt_reg = instr->RtValue();
1289 const int32_t rt = get_register(rt_reg);
1290 const uint32_t rt_u = static_cast<uint32_t>(rt);
1291 const int32_t rd_reg = instr->RdValue();
1292 const uint32_t sa = instr->SaValue();
883 1293
884 // For break and trap instructions. 1294 const int32_t fs_reg = instr->FsValue();
885 bool do_interrupt = false;
886 1295
887 // For jr and jalr
888 // Get current pc.
889 int32_t current_pc = get_pc();
890 // Next pc
891 int32_t next_pc = 0;
892 1296
893 // ---------- Configuration 1297 // ---------- Configuration
894 switch (op) { 1298 switch (op) {
895 case COP1: // Coprocessor instructions 1299 case COP1: // Coprocessor instructions
896 switch (instr->RsFieldRaw()) { 1300 switch (instr->RsFieldRaw()) {
897 case BC1: // branch on coprocessor condition 1301 case BC1: // Handled in DecodeTypeImmed, should never come here.
898 UNREACHABLE(); 1302 UNREACHABLE();
899 break; 1303 break;
1304 case CFC1:
1305 // At the moment only FCSR is supported.
1306 ASSERT(fs_reg == kFCSRRegister);
1307 alu_out = FCSR_;
1308 break;
900 case MFC1: 1309 case MFC1:
901 alu_out = get_fpu_register(fs_reg); 1310 alu_out = get_fpu_register(fs_reg);
902 break; 1311 break;
903 case MFHC1: 1312 case MFHC1:
904 fp_out = get_fpu_register_double(fs_reg); 1313 UNIMPLEMENTED_MIPS();
905 alu_out = *v8i::BitCast<int32_t*>(&fp_out);
906 break; 1314 break;
1315 case CTC1:
907 case MTC1: 1316 case MTC1:
908 case MTHC1: 1317 case MTHC1:
909 // Do the store in the execution step. 1318 // Do the store in the execution step.
910 break; 1319 break;
911 case S: 1320 case S:
912 case D: 1321 case D:
913 case W: 1322 case W:
914 case L: 1323 case L:
915 case PS: 1324 case PS:
916 // Do everything in the execution step. 1325 // Do everything in the execution step.
917 break; 1326 break;
918 default: 1327 default:
919 UNIMPLEMENTED_MIPS(); 1328 UNIMPLEMENTED_MIPS();
920 }; 1329 };
921 break; 1330 break;
922 case SPECIAL: 1331 case SPECIAL:
923 switch (instr->FunctionFieldRaw()) { 1332 switch (instr->FunctionFieldRaw()) {
924 case JR: 1333 case JR:
925 case JALR: 1334 case JALR:
926 next_pc = get_register(instr->RsField()); 1335 next_pc = get_register(instr->RsValue());
927 break; 1336 break;
928 case SLL: 1337 case SLL:
929 alu_out = rt << sa; 1338 alu_out = rt << sa;
930 break; 1339 break;
931 case SRL: 1340 case SRL:
932 alu_out = rt_u >> sa; 1341 if (rs_reg == 0) {
1342 // Regular logical right shift of a word by a fixed number of
1343 // bits instruction. RS field is always equal to 0.
1344 alu_out = rt_u >> sa;
1345 } else {
1346 // Logical right-rotate of a word by a fixed number of bits. This
1347 // is special case of SRL instruction, added in MIPS32 Release 2.
1348 // RS field is equal to 00001
1349 if (mips32r2) {
1350 alu_out = (rt_u >> sa) | (rt_u << (32 - sa));
1351 } else {
1352 Format(instr, "SRL");
1353 }
1354 }
933 break; 1355 break;
934 case SRA: 1356 case SRA:
935 alu_out = rt >> sa; 1357 alu_out = rt >> sa;
936 break; 1358 break;
937 case SLLV: 1359 case SLLV:
938 alu_out = rt << rs; 1360 alu_out = rt << rs;
939 break; 1361 break;
940 case SRLV: 1362 case SRLV:
941 alu_out = rt_u >> rs; 1363 if (sa == 0) {
1364 // Regular logical right-shift of a word by a variable number of
1365 // bits instruction. SA field is always equal to 0.
1366 alu_out = rt_u >> rs;
1367 } else {
1368 // Logical right-rotate of a word by a variable number of bits.
1369 // This is special case od SRLV instruction, added in MIPS32
1370 // Release 2. SA field is equal to 00001
1371 if (mips32r2) {
1372 alu_out = (rt_u >> rs_u) | (rt_u << (32 - rs_u));
1373 } else {
1374 Format(instr, "SRLV");
1375 }
1376 }
942 break; 1377 break;
943 case SRAV: 1378 case SRAV:
944 alu_out = rt >> rs; 1379 alu_out = rt >> rs;
945 break; 1380 break;
946 case MFHI: 1381 case MFHI:
947 alu_out = get_register(HI); 1382 alu_out = get_register(HI);
948 break; 1383 break;
949 case MFLO: 1384 case MFLO:
950 alu_out = get_register(LO); 1385 alu_out = get_register(LO);
951 break; 1386 break;
952 case MULT: 1387 case MULT:
953 UNIMPLEMENTED_MIPS(); 1388 i64hilo = static_cast<int64_t>(rs) * static_cast<int64_t>(rt);
954 break; 1389 break;
955 case MULTU: 1390 case MULTU:
956 UNIMPLEMENTED_MIPS(); 1391 u64hilo = static_cast<uint64_t>(rs_u) * static_cast<uint64_t>(rt_u);
957 break; 1392 break;
958 case DIV: 1393 case DIV:
959 case DIVU: 1394 case DIVU:
960 exceptions[kDivideByZero] = rt == 0; 1395 exceptions[kDivideByZero] = rt == 0;
961 break; 1396 break;
962 case ADD: 1397 case ADD:
963 if (HaveSameSign(rs, rt)) { 1398 if (HaveSameSign(rs, rt)) {
964 if (rs > 0) { 1399 if (rs > 0) {
965 exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - rt); 1400 exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - rt);
966 } else if (rs < 0) { 1401 } else if (rs < 0) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
998 alu_out = ~(rs | rt); 1433 alu_out = ~(rs | rt);
999 break; 1434 break;
1000 case SLT: 1435 case SLT:
1001 alu_out = rs < rt ? 1 : 0; 1436 alu_out = rs < rt ? 1 : 0;
1002 break; 1437 break;
1003 case SLTU: 1438 case SLTU:
1004 alu_out = rs_u < rt_u ? 1 : 0; 1439 alu_out = rs_u < rt_u ? 1 : 0;
1005 break; 1440 break;
1006 // Break and trap instructions 1441 // Break and trap instructions
1007 case BREAK: 1442 case BREAK:
1443
1008 do_interrupt = true; 1444 do_interrupt = true;
1009 break; 1445 break;
1010 case TGE: 1446 case TGE:
1011 do_interrupt = rs >= rt; 1447 do_interrupt = rs >= rt;
1012 break; 1448 break;
1013 case TGEU: 1449 case TGEU:
1014 do_interrupt = rs_u >= rt_u; 1450 do_interrupt = rs_u >= rt_u;
1015 break; 1451 break;
1016 case TLT: 1452 case TLT:
1017 do_interrupt = rs < rt; 1453 do_interrupt = rs < rt;
1018 break; 1454 break;
1019 case TLTU: 1455 case TLTU:
1020 do_interrupt = rs_u < rt_u; 1456 do_interrupt = rs_u < rt_u;
1021 break; 1457 break;
1022 case TEQ: 1458 case TEQ:
1023 do_interrupt = rs == rt; 1459 do_interrupt = rs == rt;
1024 break; 1460 break;
1025 case TNE: 1461 case TNE:
1026 do_interrupt = rs != rt; 1462 do_interrupt = rs != rt;
1027 break; 1463 break;
1464 case MOVN:
1465 case MOVZ:
1466 case MOVCI:
1467 // No action taken on decode.
1468 break;
1028 default: 1469 default:
1029 UNREACHABLE(); 1470 UNREACHABLE();
1030 }; 1471 };
1031 break; 1472 break;
1032 case SPECIAL2: 1473 case SPECIAL2:
1033 switch (instr->FunctionFieldRaw()) { 1474 switch (instr->FunctionFieldRaw()) {
1034 case MUL: 1475 case MUL:
1035 alu_out = rs_u * rt_u; // Only the lower 32 bits are kept. 1476 alu_out = rs_u * rt_u; // Only the lower 32 bits are kept.
1036 break; 1477 break;
1478 case CLZ:
1479 alu_out = __builtin_clz(rs_u);
1480 break;
1037 default: 1481 default:
1038 UNREACHABLE(); 1482 UNREACHABLE();
1039 } 1483 };
1484 break;
1485 case SPECIAL3:
1486 switch (instr->FunctionFieldRaw()) {
1487 case INS: { // mips32r2 instruction.
1488 if (mips32r2) {
1489 // Interpret Rd field as 5-bit msb of insert.
1490 uint16_t msb = rd_reg;
1491 // Interpret sa field as 5-bit lsb of insert.
1492 uint16_t lsb = sa;
1493 uint16_t size = msb - lsb + 1;
1494 uint32_t mask = (1 << size) - 1;
1495 alu_out = (rt_u & ~(mask << lsb)) | ((rs_u & mask) << lsb);
1496 } else {
1497 Format(instr, "INS");
1498 }
1499 }
1500 break;
1501 case EXT: { // mips32r2 instruction.
1502 if (mips32r2) {
1503 // Interpret Rd field as 5-bit msb of extract.
1504 uint16_t msb = rd_reg;
1505 // Interpret sa field as 5-bit lsb of extract.
1506 uint16_t lsb = sa;
1507 uint16_t size = msb + 1;
1508 uint32_t mask = (1 << size) - 1;
1509 alu_out = (rs_u & (mask << lsb)) >> lsb;
1510 } else {
1511 Format(instr, "EXT");
1512 }
1513 }
1514 break;
1515 default:
1516 UNREACHABLE();
1517 };
1040 break; 1518 break;
1041 default: 1519 default:
1042 UNREACHABLE(); 1520 UNREACHABLE();
1043 }; 1521 };
1522 }
1523
1524
1525 void Simulator::DecodeTypeRegister(Instruction* instr) {
1526 // Instruction fields.
1527 const Opcode op = instr->OpcodeFieldRaw();
1528 const int32_t rs_reg = instr->RsValue();
1529 const int32_t rs = get_register(rs_reg);
1530 const uint32_t rs_u = static_cast<uint32_t>(rs);
1531 const int32_t rt_reg = instr->RtValue();
1532 const int32_t rt = get_register(rt_reg);
1533 const uint32_t rt_u = static_cast<uint32_t>(rt);
1534 const int32_t rd_reg = instr->RdValue();
1535
1536 const int32_t fs_reg = instr->FsValue();
1537 const int32_t ft_reg = instr->FtValue();
1538 const int32_t fd_reg = instr->FdValue();
1539 int64_t i64hilo = 0;
1540 uint64_t u64hilo = 0;
1541
1542 // ALU output
1543 // It should not be used as is. Instructions using it should always
1544 // initialize it first.
1545 int32_t alu_out = 0x12345678;
1546
1547 // For break and trap instructions.
1548 bool do_interrupt = false;
1549
1550 // For jr and jalr
1551 // Get current pc.
1552 int32_t current_pc = get_pc();
1553 // Next pc
1554 int32_t next_pc = 0;
1555
1556 // Setup the variables if needed before executing the instruction.
1557 ConfigureTypeRegister(instr,
1558 alu_out,
1559 i64hilo,
1560 u64hilo,
1561 next_pc,
1562 do_interrupt);
1044 1563
1045 // ---------- Raise exceptions triggered. 1564 // ---------- Raise exceptions triggered.
1046 SignalExceptions(); 1565 SignalExceptions();
1047 1566
1048 // ---------- Execution 1567 // ---------- Execution
1049 switch (op) { 1568 switch (op) {
1050 case COP1: 1569 case COP1:
1051 switch (instr->RsFieldRaw()) { 1570 switch (instr->RsFieldRaw()) {
1052 case BC1: // branch on coprocessor condition 1571 case BC1: // branch on coprocessor condition
1053 UNREACHABLE(); 1572 UNREACHABLE();
1054 break; 1573 break;
1574 case CFC1:
1575 set_register(rt_reg, alu_out);
1055 case MFC1: 1576 case MFC1:
1056 case MFHC1:
1057 set_register(rt_reg, alu_out); 1577 set_register(rt_reg, alu_out);
1058 break; 1578 break;
1579 case MFHC1:
1580 UNIMPLEMENTED_MIPS();
1581 break;
1582 case CTC1:
1583 // At the moment only FCSR is supported.
1584 ASSERT(fs_reg == kFCSRRegister);
1585 FCSR_ = registers_[rt_reg];
1586 break;
1059 case MTC1: 1587 case MTC1:
1060 // We don't need to set the higher bits to 0, because MIPS ISA says
1061 // they are in an unpredictable state after executing MTC1.
1062 FPUregisters_[fs_reg] = registers_[rt_reg]; 1588 FPUregisters_[fs_reg] = registers_[rt_reg];
1063 FPUregisters_[fs_reg+1] = Unpredictable;
1064 break; 1589 break;
1065 case MTHC1: 1590 case MTHC1:
1066 // Here we need to keep the lower bits unchanged. 1591 UNIMPLEMENTED_MIPS();
1067 FPUregisters_[fs_reg+1] = registers_[rt_reg];
1068 break; 1592 break;
1069 case S: 1593 case S:
1594 float f;
1070 switch (instr->FunctionFieldRaw()) { 1595 switch (instr->FunctionFieldRaw()) {
1071 case CVT_D_S: 1596 case CVT_D_S:
1597 f = get_fpu_register_float(fs_reg);
1598 set_fpu_register_double(fd_reg, static_cast<double>(f));
1599 break;
1072 case CVT_W_S: 1600 case CVT_W_S:
1073 case CVT_L_S: 1601 case CVT_L_S:
1602 case TRUNC_W_S:
1603 case TRUNC_L_S:
1604 case ROUND_W_S:
1605 case ROUND_L_S:
1606 case FLOOR_W_S:
1607 case FLOOR_L_S:
1608 case CEIL_W_S:
1609 case CEIL_L_S:
1074 case CVT_PS_S: 1610 case CVT_PS_S:
1075 UNIMPLEMENTED_MIPS(); 1611 UNIMPLEMENTED_MIPS();
1076 break; 1612 break;
1077 default: 1613 default:
1078 UNREACHABLE(); 1614 UNREACHABLE();
1079 } 1615 }
1080 break; 1616 break;
1081 case D: 1617 case D:
1618 double ft, fs;
1619 uint32_t cc, fcsr_cc;
1620 int64_t i64;
1621 fs = get_fpu_register_double(fs_reg);
1622 ft = get_fpu_register_double(ft_reg);
1623 cc = instr->FCccValue();
1624 fcsr_cc = get_fcsr_condition_bit(cc);
1082 switch (instr->FunctionFieldRaw()) { 1625 switch (instr->FunctionFieldRaw()) {
1083 case CVT_S_D: 1626 case ADD_D:
1084 case CVT_W_D: 1627 set_fpu_register_double(fd_reg, fs + ft);
1085 case CVT_L_D: 1628 break;
1629 case SUB_D:
1630 set_fpu_register_double(fd_reg, fs - ft);
1631 break;
1632 case MUL_D:
1633 set_fpu_register_double(fd_reg, fs * ft);
1634 break;
1635 case DIV_D:
1636 set_fpu_register_double(fd_reg, fs / ft);
1637 break;
1638 case ABS_D:
1639 set_fpu_register_double(fd_reg, fs < 0 ? -fs : fs);
1640 break;
1641 case MOV_D:
1642 set_fpu_register_double(fd_reg, fs);
1643 break;
1644 case NEG_D:
1645 set_fpu_register_double(fd_reg, -fs);
1646 break;
1647 case SQRT_D:
1648 set_fpu_register_double(fd_reg, sqrt(fs));
1649 break;
1650 case C_UN_D:
1651 set_fcsr_bit(fcsr_cc, isnan(fs) || isnan(ft));
1652 break;
1653 case C_EQ_D:
1654 set_fcsr_bit(fcsr_cc, (fs == ft));
1655 break;
1656 case C_UEQ_D:
1657 set_fcsr_bit(fcsr_cc, (fs == ft) || (isnan(fs) || isnan(ft)));
1658 break;
1659 case C_OLT_D:
1660 set_fcsr_bit(fcsr_cc, (fs < ft));
1661 break;
1662 case C_ULT_D:
1663 set_fcsr_bit(fcsr_cc, (fs < ft) || (isnan(fs) || isnan(ft)));
1664 break;
1665 case C_OLE_D:
1666 set_fcsr_bit(fcsr_cc, (fs <= ft));
1667 break;
1668 case C_ULE_D:
1669 set_fcsr_bit(fcsr_cc, (fs <= ft) || (isnan(fs) || isnan(ft)));
1670 break;
1671 case CVT_W_D: // Convert double to word.
1672 // Rounding modes are not yet supported.
1673 ASSERT((FCSR_ & 3) == 0);
1674 // In rounding mode 0 it should behave like ROUND.
1675 case ROUND_W_D: // Round double to word.
1676 {
1677 double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
1678 int32_t result = static_cast<int32_t>(rounded);
1679 set_fpu_register(fd_reg, result);
1680 if (set_fcsr_round_error(fs, rounded)) {
1681 set_fpu_register(fd_reg, kFPUInvalidResult);
1682 }
1683 }
1684 break;
1685 case TRUNC_W_D: // Truncate double to word (round towards 0).
1686 {
1687 int32_t result = static_cast<int32_t>(fs);
1688 set_fpu_register(fd_reg, result);
1689 if (set_fcsr_round_error(fs, static_cast<double>(result))) {
1690 set_fpu_register(fd_reg, kFPUInvalidResult);
1691 }
1692 }
1693 break;
1694 case FLOOR_W_D: // Round double to word towards negative infinity.
1695 {
1696 double rounded = floor(fs);
1697 int32_t result = static_cast<int32_t>(rounded);
1698 set_fpu_register(fd_reg, result);
1699 if (set_fcsr_round_error(fs, rounded)) {
1700 set_fpu_register(fd_reg, kFPUInvalidResult);
1701 }
1702 }
1703 break;
1704 case CEIL_W_D: // Round double to word towards positive infinity.
1705 {
1706 double rounded = ceil(fs);
1707 int32_t result = static_cast<int32_t>(rounded);
1708 set_fpu_register(fd_reg, result);
1709 if (set_fcsr_round_error(fs, rounded)) {
1710 set_fpu_register(fd_reg, kFPUInvalidResult);
1711 }
1712 }
1713 break;
1714 case CVT_S_D: // Convert double to float (single).
1715 set_fpu_register_float(fd_reg, static_cast<float>(fs));
1716 break;
1717 case CVT_L_D: // Truncate double to 64-bit long-word.
1718 if (mips32r2) {
1719 i64 = static_cast<int64_t>(fs);
1720 set_fpu_register(fd_reg, i64 & 0xffffffff);
1721 set_fpu_register(fd_reg + 1, i64 >> 32);
1722 } else {
1723 // Not allowed on MIPS32 Release 1
1724 UNIMPLEMENTED_MIPS();
1725 }
1726 break;
1727 case TRUNC_L_D:
1728 if (mips32r2) {
1729 i64 = static_cast<int64_t>(fs);
1730 set_fpu_register(fd_reg, i64 & 0xffffffff);
1731 set_fpu_register(fd_reg + 1, i64 >> 32);
1732 } else {
1733 // Not allowed on MIPS32 Release 1
1734 UNIMPLEMENTED_MIPS();
1735 }
1736 break;
1737 case ROUND_L_D:
1738 if (mips32r2) {
1739 double rounded = fs > 0 ? floor(fs + 0.5) : ceil(fs - 0.5);
1740 i64 = static_cast<int64_t>(rounded);
1741 set_fpu_register(fd_reg, i64 & 0xffffffff);
1742 set_fpu_register(fd_reg + 1, i64 >> 32);
1743 } else {
1744 // Not allowed on MIPS32 Release 1
1745 UNIMPLEMENTED_MIPS();
1746 }
1747 break;
1748 case FLOOR_L_D:
1749 if (mips32r2) {
1750 i64 = static_cast<int64_t>(floor(fs));
1751 set_fpu_register(fd_reg, i64 & 0xffffffff);
1752 set_fpu_register(fd_reg + 1, i64 >> 32);
1753 } else {
1754 // Not allowed on MIPS32 Release 1
1755 UNIMPLEMENTED_MIPS();
1756 }
1757 break;
1758 case CEIL_L_D:
1759 if (mips32r2) {
1760 i64 = static_cast<int64_t>(ceil(fs));
1761 set_fpu_register(fd_reg, i64 & 0xffffffff);
1762 set_fpu_register(fd_reg + 1, i64 >> 32);
1763 } else {
1764 // Not allowed on MIPS32 Release 1
1765 UNIMPLEMENTED_MIPS();
1766 }
1767 break;
1768 case C_F_D:
1086 UNIMPLEMENTED_MIPS(); 1769 UNIMPLEMENTED_MIPS();
1087 break; 1770 break;
1088 default: 1771 default:
1089 UNREACHABLE(); 1772 UNREACHABLE();
1090 } 1773 }
1091 break; 1774 break;
1092 case W: 1775 case W:
1093 switch (instr->FunctionFieldRaw()) { 1776 switch (instr->FunctionFieldRaw()) {
1094 case CVT_S_W: 1777 case CVT_S_W: // Convert word to float (single).
1095 UNIMPLEMENTED_MIPS(); 1778 alu_out = get_fpu_register(fs_reg);
1779 set_fpu_register_float(fd_reg, static_cast<float>(alu_out));
1096 break; 1780 break;
1097 case CVT_D_W: // Convert word to double. 1781 case CVT_D_W: // Convert word to double.
1098 set_fpu_register(rd_reg, static_cast<double>(rs)); 1782 alu_out = get_fpu_register(fs_reg);
1783 set_fpu_register_double(fd_reg, static_cast<double>(alu_out));
1099 break; 1784 break;
1100 default: 1785 default:
1101 UNREACHABLE(); 1786 UNREACHABLE();
1102 }; 1787 };
1103 break; 1788 break;
1104 case L: 1789 case L:
1105 switch (instr->FunctionFieldRaw()) { 1790 switch (instr->FunctionFieldRaw()) {
1791 case CVT_D_L:
1792 if (mips32r2) {
1793 // Watch the signs here, we want 2 32-bit vals
1794 // to make a sign-64.
1795 i64 = (uint32_t) get_fpu_register(fs_reg);
1796 i64 |= ((int64_t) get_fpu_register(fs_reg + 1) << 32);
1797 set_fpu_register_double(fd_reg, static_cast<double>(i64));
1798 } else {
1799 // Not allowed on MIPS32 Release 1
1800 UNIMPLEMENTED_MIPS();
1801 }
1802 break;
1106 case CVT_S_L: 1803 case CVT_S_L:
1107 case CVT_D_L:
1108 UNIMPLEMENTED_MIPS(); 1804 UNIMPLEMENTED_MIPS();
1109 break; 1805 break;
1110 default: 1806 default:
1111 UNREACHABLE(); 1807 UNREACHABLE();
1112 } 1808 }
1113 break; 1809 break;
1114 case PS: 1810 case PS:
1115 break; 1811 break;
1116 default: 1812 default:
1117 UNREACHABLE(); 1813 UNREACHABLE();
(...skipping 13 matching lines...) Expand all
1131 Instruction* branch_delay_instr = reinterpret_cast<Instruction*>( 1827 Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
1132 current_pc+Instruction::kInstructionSize); 1828 current_pc+Instruction::kInstructionSize);
1133 BranchDelayInstructionDecode(branch_delay_instr); 1829 BranchDelayInstructionDecode(branch_delay_instr);
1134 set_register(31, current_pc + 2* Instruction::kInstructionSize); 1830 set_register(31, current_pc + 2* Instruction::kInstructionSize);
1135 set_pc(next_pc); 1831 set_pc(next_pc);
1136 pc_modified_ = true; 1832 pc_modified_ = true;
1137 break; 1833 break;
1138 } 1834 }
1139 // Instructions using HI and LO registers. 1835 // Instructions using HI and LO registers.
1140 case MULT: 1836 case MULT:
1837 set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff));
1838 set_register(HI, static_cast<int32_t>(i64hilo >> 32));
1839 break;
1141 case MULTU: 1840 case MULTU:
1841 set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff));
1842 set_register(HI, static_cast<int32_t>(u64hilo >> 32));
1142 break; 1843 break;
1143 case DIV: 1844 case DIV:
1144 // Divide by zero was checked in the configuration step. 1845 // Divide by zero was checked in the configuration step.
1145 set_register(LO, rs / rt); 1846 set_register(LO, rs / rt);
1146 set_register(HI, rs % rt); 1847 set_register(HI, rs % rt);
1147 break; 1848 break;
1148 case DIVU: 1849 case DIVU:
1149 set_register(LO, rs_u / rt_u); 1850 set_register(LO, rs_u / rt_u);
1150 set_register(HI, rs_u % rt_u); 1851 set_register(HI, rs_u % rt_u);
1151 break; 1852 break;
1152 // Break and trap instructions 1853 // Break and trap instructions.
1153 case BREAK: 1854 case BREAK:
1154 case TGE: 1855 case TGE:
1155 case TGEU: 1856 case TGEU:
1156 case TLT: 1857 case TLT:
1157 case TLTU: 1858 case TLTU:
1158 case TEQ: 1859 case TEQ:
1159 case TNE: 1860 case TNE:
1160 if (do_interrupt) { 1861 if (do_interrupt) {
1161 SoftwareInterrupt(instr); 1862 SoftwareInterrupt(instr);
1162 } 1863 }
1163 break; 1864 break;
1865 // Conditional moves.
1866 case MOVN:
1867 if (rt) set_register(rd_reg, rs);
1868 break;
1869 case MOVCI: {
1870 uint32_t cc = instr->FCccValue();
1871 uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
1872 if (instr->Bit(16)) { // Read Tf bit
1873 if (test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
1874 } else {
1875 if (!test_fcsr_bit(fcsr_cc)) set_register(rd_reg, rs);
1876 }
1877 break;
1878 }
1879 case MOVZ:
1880 if (!rt) set_register(rd_reg, rs);
1881 break;
1164 default: // For other special opcodes we do the default operation. 1882 default: // For other special opcodes we do the default operation.
1165 set_register(rd_reg, alu_out); 1883 set_register(rd_reg, alu_out);
1166 }; 1884 };
1167 break; 1885 break;
1168 case SPECIAL2: 1886 case SPECIAL2:
1169 switch (instr->FunctionFieldRaw()) { 1887 switch (instr->FunctionFieldRaw()) {
1170 case MUL: 1888 case MUL:
1171 set_register(rd_reg, alu_out); 1889 set_register(rd_reg, alu_out);
1172 // HI and LO are UNPREDICTABLE after the operation. 1890 // HI and LO are UNPREDICTABLE after the operation.
1173 set_register(LO, Unpredictable); 1891 set_register(LO, Unpredictable);
1174 set_register(HI, Unpredictable); 1892 set_register(HI, Unpredictable);
1175 break; 1893 break;
1894 default: // For other special2 opcodes we do the default operation.
1895 set_register(rd_reg, alu_out);
1896 }
1897 break;
1898 case SPECIAL3:
1899 switch (instr->FunctionFieldRaw()) {
1900 case INS:
1901 // Ins instr leaves result in Rt, rather than Rd.
1902 set_register(rt_reg, alu_out);
1903 break;
1904 case EXT:
1905 // Ext instr leaves result in Rt, rather than Rd.
1906 set_register(rt_reg, alu_out);
1907 break;
1176 default: 1908 default:
1177 UNREACHABLE(); 1909 UNREACHABLE();
1178 } 1910 };
1179 break; 1911 break;
1180 // Unimplemented opcodes raised an error in the configuration step before, 1912 // Unimplemented opcodes raised an error in the configuration step before,
1181 // so we can use the default here to set the destination register in common 1913 // so we can use the default here to set the destination register in common
1182 // cases. 1914 // cases.
1183 default: 1915 default:
1184 set_register(rd_reg, alu_out); 1916 set_register(rd_reg, alu_out);
1185 }; 1917 };
1186 } 1918 }
1187 1919
1920
1188 // Type 2: instructions using a 16 bytes immediate. (eg: addi, beq) 1921 // Type 2: instructions using a 16 bytes immediate. (eg: addi, beq)
1189 void Simulator::DecodeTypeImmediate(Instruction* instr) { 1922 void Simulator::DecodeTypeImmediate(Instruction* instr) {
1190 // Instruction fields 1923 // Instruction fields.
1191 Opcode op = instr->OpcodeFieldRaw(); 1924 Opcode op = instr->OpcodeFieldRaw();
1192 int32_t rs = get_register(instr->RsField()); 1925 int32_t rs = get_register(instr->RsValue());
1193 uint32_t rs_u = static_cast<uint32_t>(rs); 1926 uint32_t rs_u = static_cast<uint32_t>(rs);
1194 int32_t rt_reg = instr->RtField(); // destination register 1927 int32_t rt_reg = instr->RtValue(); // destination register
1195 int32_t rt = get_register(rt_reg); 1928 int32_t rt = get_register(rt_reg);
1196 int16_t imm16 = instr->Imm16Field(); 1929 int16_t imm16 = instr->Imm16Value();
1197 1930
1198 int32_t ft_reg = instr->FtField(); // destination register 1931 int32_t ft_reg = instr->FtValue(); // destination register
1199 int32_t ft = get_register(ft_reg);
1200 1932
1201 // zero extended immediate 1933 // Zero extended immediate.
1202 uint32_t oe_imm16 = 0xffff & imm16; 1934 uint32_t oe_imm16 = 0xffff & imm16;
1203 // sign extended immediate 1935 // Sign extended immediate.
1204 int32_t se_imm16 = imm16; 1936 int32_t se_imm16 = imm16;
1205 1937
1206 // Get current pc. 1938 // Get current pc.
1207 int32_t current_pc = get_pc(); 1939 int32_t current_pc = get_pc();
1208 // Next pc. 1940 // Next pc.
1209 int32_t next_pc = bad_ra; 1941 int32_t next_pc = bad_ra;
1210 1942
1211 // Used for conditional branch instructions 1943 // Used for conditional branch instructions.
1212 bool do_branch = false; 1944 bool do_branch = false;
1213 bool execute_branch_delay_instruction = false; 1945 bool execute_branch_delay_instruction = false;
1214 1946
1215 // Used for arithmetic instructions 1947 // Used for arithmetic instructions.
1216 int32_t alu_out = 0; 1948 int32_t alu_out = 0;
1217 // Floating point 1949 // Floating point.
1218 double fp_out = 0.0; 1950 double fp_out = 0.0;
1951 uint32_t cc, cc_value, fcsr_cc;
1219 1952
1220 // Used for memory instructions 1953 // Used for memory instructions.
1221 int32_t addr = 0x0; 1954 int32_t addr = 0x0;
1955 // Value to be written in memory
1956 uint32_t mem_value = 0x0;
1222 1957
1223 // ---------- Configuration (and execution for REGIMM) 1958 // ---------- Configuration (and execution for REGIMM)
1224 switch (op) { 1959 switch (op) {
1225 // ------------- COP1. Coprocessor instructions 1960 // ------------- COP1. Coprocessor instructions.
1226 case COP1: 1961 case COP1:
1227 switch (instr->RsFieldRaw()) { 1962 switch (instr->RsFieldRaw()) {
1228 case BC1: // branch on coprocessor condition 1963 case BC1: // Branch on coprocessor condition.
1229 UNIMPLEMENTED_MIPS(); 1964 cc = instr->FBccValue();
1965 fcsr_cc = get_fcsr_condition_bit(cc);
1966 cc_value = test_fcsr_bit(fcsr_cc);
1967 do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value;
1968 execute_branch_delay_instruction = true;
1969 // Set next_pc
1970 if (do_branch) {
1971 next_pc = current_pc + (imm16 << 2) + Instruction::kInstructionSize;
1972 } else {
1973 next_pc = current_pc + kBranchReturnOffset;
1974 }
1230 break; 1975 break;
1231 default: 1976 default:
1232 UNREACHABLE(); 1977 UNREACHABLE();
1233 }; 1978 };
1234 break; 1979 break;
1235 // ------------- REGIMM class 1980 // ------------- REGIMM class
1236 case REGIMM: 1981 case REGIMM:
1237 switch (instr->RtFieldRaw()) { 1982 switch (instr->RtFieldRaw()) {
1238 case BLTZ: 1983 case BLTZ:
1239 do_branch = (rs < 0); 1984 do_branch = (rs < 0);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
1316 alu_out = rs ^ oe_imm16; 2061 alu_out = rs ^ oe_imm16;
1317 break; 2062 break;
1318 case LUI: 2063 case LUI:
1319 alu_out = (oe_imm16 << 16); 2064 alu_out = (oe_imm16 << 16);
1320 break; 2065 break;
1321 // ------------- Memory instructions 2066 // ------------- Memory instructions
1322 case LB: 2067 case LB:
1323 addr = rs + se_imm16; 2068 addr = rs + se_imm16;
1324 alu_out = ReadB(addr); 2069 alu_out = ReadB(addr);
1325 break; 2070 break;
2071 case LH:
2072 addr = rs + se_imm16;
2073 alu_out = ReadH(addr, instr);
2074 break;
2075 case LWL: {
2076 // al_offset is an offset of the effective address within an aligned word
2077 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2078 uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2079 uint32_t mask = (1 << byte_shift * 8) - 1;
2080 addr = rs + se_imm16 - al_offset;
2081 alu_out = ReadW(addr, instr);
2082 alu_out <<= byte_shift * 8;
2083 alu_out |= rt & mask;
2084 }
2085 break;
1326 case LW: 2086 case LW:
1327 addr = rs + se_imm16; 2087 addr = rs + se_imm16;
1328 alu_out = ReadW(addr, instr); 2088 alu_out = ReadW(addr, instr);
1329 break; 2089 break;
1330 case LBU: 2090 case LBU:
1331 addr = rs + se_imm16; 2091 addr = rs + se_imm16;
1332 alu_out = ReadBU(addr); 2092 alu_out = ReadBU(addr);
1333 break; 2093 break;
2094 case LHU:
2095 addr = rs + se_imm16;
2096 alu_out = ReadHU(addr, instr);
2097 break;
2098 case LWR: {
2099 // al_offset is an offset of the effective address within an aligned word
2100 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2101 uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2102 uint32_t mask = al_offset ? (~0 << (byte_shift + 1) * 8) : 0;
2103 addr = rs + se_imm16 - al_offset;
2104 alu_out = ReadW(addr, instr);
2105 alu_out = static_cast<uint32_t> (alu_out) >> al_offset * 8;
2106 alu_out |= rt & mask;
2107 }
2108 break;
1334 case SB: 2109 case SB:
1335 addr = rs + se_imm16; 2110 addr = rs + se_imm16;
1336 break; 2111 break;
2112 case SH:
2113 addr = rs + se_imm16;
2114 break;
2115 case SWL: {
2116 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2117 uint8_t byte_shift = kPointerAlignmentMask - al_offset;
2118 uint32_t mask = byte_shift ? (~0 << (al_offset + 1) * 8) : 0;
2119 addr = rs + se_imm16 - al_offset;
2120 mem_value = ReadW(addr, instr) & mask;
2121 mem_value |= static_cast<uint32_t>(rt) >> byte_shift * 8;
2122 }
2123 break;
1337 case SW: 2124 case SW:
1338 addr = rs + se_imm16; 2125 addr = rs + se_imm16;
1339 break; 2126 break;
2127 case SWR: {
2128 uint8_t al_offset = (rs + se_imm16) & kPointerAlignmentMask;
2129 uint32_t mask = (1 << al_offset * 8) - 1;
2130 addr = rs + se_imm16 - al_offset;
2131 mem_value = ReadW(addr, instr);
2132 mem_value = (rt << al_offset * 8) | (mem_value & mask);
2133 }
2134 break;
1340 case LWC1: 2135 case LWC1:
1341 addr = rs + se_imm16; 2136 addr = rs + se_imm16;
1342 alu_out = ReadW(addr, instr); 2137 alu_out = ReadW(addr, instr);
1343 break; 2138 break;
1344 case LDC1: 2139 case LDC1:
1345 addr = rs + se_imm16; 2140 addr = rs + se_imm16;
1346 fp_out = ReadD(addr, instr); 2141 fp_out = ReadD(addr, instr);
1347 break; 2142 break;
1348 case SWC1: 2143 case SWC1:
1349 case SDC1: 2144 case SDC1:
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1381 case SLTI: 2176 case SLTI:
1382 case SLTIU: 2177 case SLTIU:
1383 case ANDI: 2178 case ANDI:
1384 case ORI: 2179 case ORI:
1385 case XORI: 2180 case XORI:
1386 case LUI: 2181 case LUI:
1387 set_register(rt_reg, alu_out); 2182 set_register(rt_reg, alu_out);
1388 break; 2183 break;
1389 // ------------- Memory instructions 2184 // ------------- Memory instructions
1390 case LB: 2185 case LB:
2186 case LH:
2187 case LWL:
1391 case LW: 2188 case LW:
1392 case LBU: 2189 case LBU:
2190 case LHU:
2191 case LWR:
1393 set_register(rt_reg, alu_out); 2192 set_register(rt_reg, alu_out);
1394 break; 2193 break;
1395 case SB: 2194 case SB:
1396 WriteB(addr, static_cast<int8_t>(rt)); 2195 WriteB(addr, static_cast<int8_t>(rt));
1397 break; 2196 break;
2197 case SH:
2198 WriteH(addr, static_cast<uint16_t>(rt), instr);
2199 break;
2200 case SWL:
2201 WriteW(addr, mem_value, instr);
2202 break;
1398 case SW: 2203 case SW:
1399 WriteW(addr, rt, instr); 2204 WriteW(addr, rt, instr);
1400 break; 2205 break;
2206 case SWR:
2207 WriteW(addr, mem_value, instr);
2208 break;
1401 case LWC1: 2209 case LWC1:
1402 set_fpu_register(ft_reg, alu_out); 2210 set_fpu_register(ft_reg, alu_out);
1403 break; 2211 break;
1404 case LDC1: 2212 case LDC1:
1405 set_fpu_register_double(ft_reg, fp_out); 2213 set_fpu_register_double(ft_reg, fp_out);
1406 break; 2214 break;
1407 case SWC1: 2215 case SWC1:
1408 addr = rs + se_imm16; 2216 addr = rs + se_imm16;
1409 WriteW(addr, get_fpu_register(ft_reg), instr); 2217 WriteW(addr, get_fpu_register(ft_reg), instr);
1410 break; 2218 break;
1411 case SDC1: 2219 case SDC1:
1412 addr = rs + se_imm16; 2220 addr = rs + se_imm16;
1413 WriteD(addr, ft, instr); 2221 WriteD(addr, get_fpu_register_double(ft_reg), instr);
1414 break; 2222 break;
1415 default: 2223 default:
1416 break; 2224 break;
1417 }; 2225 };
1418 2226
1419 2227
1420 if (execute_branch_delay_instruction) { 2228 if (execute_branch_delay_instruction) {
1421 // Execute branch delay slot 2229 // Execute branch delay slot
1422 // We don't check for end_sim_pc. First it should not be met as the current 2230 // We don't check for end_sim_pc. First it should not be met as the current
1423 // pc is valid. Secondly a jump should always execute its branch delay slot. 2231 // pc is valid. Secondly a jump should always execute its branch delay slot.
1424 Instruction* branch_delay_instr = 2232 Instruction* branch_delay_instr =
1425 reinterpret_cast<Instruction*>(current_pc+Instruction::kInstructionSize); 2233 reinterpret_cast<Instruction*>(current_pc+Instruction::kInstructionSize);
1426 BranchDelayInstructionDecode(branch_delay_instr); 2234 BranchDelayInstructionDecode(branch_delay_instr);
1427 } 2235 }
1428 2236
1429 // If needed update pc after the branch delay execution. 2237 // If needed update pc after the branch delay execution.
1430 if (next_pc != bad_ra) { 2238 if (next_pc != bad_ra) {
1431 set_pc(next_pc); 2239 set_pc(next_pc);
1432 } 2240 }
1433 } 2241 }
1434 2242
2243
1435 // Type 3: instructions using a 26 bytes immediate. (eg: j, jal) 2244 // Type 3: instructions using a 26 bytes immediate. (eg: j, jal)
1436 void Simulator::DecodeTypeJump(Instruction* instr) { 2245 void Simulator::DecodeTypeJump(Instruction* instr) {
1437 // Get current pc. 2246 // Get current pc.
1438 int32_t current_pc = get_pc(); 2247 int32_t current_pc = get_pc();
1439 // Get unchanged bits of pc. 2248 // Get unchanged bits of pc.
1440 int32_t pc_high_bits = current_pc & 0xf0000000; 2249 int32_t pc_high_bits = current_pc & 0xf0000000;
1441 // Next pc 2250 // Next pc
1442 int32_t next_pc = pc_high_bits | (instr->Imm26Field() << 2); 2251 int32_t next_pc = pc_high_bits | (instr->Imm26Value() << 2);
1443 2252
1444 // Execute branch delay slot 2253 // Execute branch delay slot
1445 // We don't check for end_sim_pc. First it should not be met as the current pc 2254 // We don't check for end_sim_pc. First it should not be met as the current pc
1446 // is valid. Secondly a jump should always execute its branch delay slot. 2255 // is valid. Secondly a jump should always execute its branch delay slot.
1447 Instruction* branch_delay_instr = 2256 Instruction* branch_delay_instr =
1448 reinterpret_cast<Instruction*>(current_pc+Instruction::kInstructionSize); 2257 reinterpret_cast<Instruction*>(current_pc+Instruction::kInstructionSize);
1449 BranchDelayInstructionDecode(branch_delay_instr); 2258 BranchDelayInstructionDecode(branch_delay_instr);
1450 2259
1451 // Update pc and ra if necessary. 2260 // Update pc and ra if necessary.
1452 // Do this after the branch delay execution. 2261 // Do this after the branch delay execution.
1453 if (instr->IsLinkingInstruction()) { 2262 if (instr->IsLinkingInstruction()) {
1454 set_register(31, current_pc + 2* Instruction::kInstructionSize); 2263 set_register(31, current_pc + 2* Instruction::kInstructionSize);
1455 } 2264 }
1456 set_pc(next_pc); 2265 set_pc(next_pc);
1457 pc_modified_ = true; 2266 pc_modified_ = true;
1458 } 2267 }
1459 2268
2269
1460 // Executes the current instruction. 2270 // Executes the current instruction.
1461 void Simulator::InstructionDecode(Instruction* instr) { 2271 void Simulator::InstructionDecode(Instruction* instr) {
2272 if (v8::internal::FLAG_check_icache) {
2273 CheckICache(instr);
2274 }
1462 pc_modified_ = false; 2275 pc_modified_ = false;
1463 if (::v8::internal::FLAG_trace_sim) { 2276 if (::v8::internal::FLAG_trace_sim) {
1464 disasm::NameConverter converter; 2277 disasm::NameConverter converter;
1465 disasm::Disassembler dasm(converter); 2278 disasm::Disassembler dasm(converter);
1466 // use a reasonably large buffer 2279 // use a reasonably large buffer
1467 v8::internal::EmbeddedVector<char, 256> buffer; 2280 v8::internal::EmbeddedVector<char, 256> buffer;
1468 dasm.InstructionDecode(buffer, 2281 dasm.InstructionDecode(buffer,
1469 reinterpret_cast<byte_*>(instr)); 2282 reinterpret_cast<byte_*>(instr));
1470 PrintF(" 0x%08x %s\n", instr, buffer.start()); 2283 PrintF(" 0x%08x %s\n", reinterpret_cast<intptr_t>(instr),
2284 buffer.start());
1471 } 2285 }
1472 2286
1473 switch (instr->InstructionType()) { 2287 switch (instr->InstructionType()) {
1474 case Instruction::kRegisterType: 2288 case Instruction::kRegisterType:
1475 DecodeTypeRegister(instr); 2289 DecodeTypeRegister(instr);
1476 break; 2290 break;
1477 case Instruction::kImmediateType: 2291 case Instruction::kImmediateType:
1478 DecodeTypeImmediate(instr); 2292 DecodeTypeImmediate(instr);
1479 break; 2293 break;
1480 case Instruction::kJumpType: 2294 case Instruction::kJumpType:
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1531 ASSERT(argument_count >= 4); 2345 ASSERT(argument_count >= 4);
1532 set_register(a0, va_arg(parameters, int32_t)); 2346 set_register(a0, va_arg(parameters, int32_t));
1533 set_register(a1, va_arg(parameters, int32_t)); 2347 set_register(a1, va_arg(parameters, int32_t));
1534 set_register(a2, va_arg(parameters, int32_t)); 2348 set_register(a2, va_arg(parameters, int32_t));
1535 set_register(a3, va_arg(parameters, int32_t)); 2349 set_register(a3, va_arg(parameters, int32_t));
1536 2350
1537 // Remaining arguments passed on stack. 2351 // Remaining arguments passed on stack.
1538 int original_stack = get_register(sp); 2352 int original_stack = get_register(sp);
1539 // Compute position of stack on entry to generated code. 2353 // Compute position of stack on entry to generated code.
1540 int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t) 2354 int entry_stack = (original_stack - (argument_count - 4) * sizeof(int32_t)
1541 - kArgsSlotsSize); 2355 - kCArgsSlotsSize);
1542 if (OS::ActivationFrameAlignment() != 0) { 2356 if (OS::ActivationFrameAlignment() != 0) {
1543 entry_stack &= -OS::ActivationFrameAlignment(); 2357 entry_stack &= -OS::ActivationFrameAlignment();
1544 } 2358 }
1545 // Store remaining arguments on stack, from low to high memory. 2359 // Store remaining arguments on stack, from low to high memory.
1546 intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack); 2360 intptr_t* stack_argument = reinterpret_cast<intptr_t*>(entry_stack);
1547 for (int i = 4; i < argument_count; i++) { 2361 for (int i = 4; i < argument_count; i++) {
1548 stack_argument[i - 4 + kArgsSlotsNum] = va_arg(parameters, int32_t); 2362 stack_argument[i - 4 + kArgsSlotsNum] = va_arg(parameters, int32_t);
1549 } 2363 }
1550 va_end(parameters); 2364 va_end(parameters);
1551 set_register(sp, entry_stack); 2365 set_register(sp, entry_stack);
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
1636 int current_sp = get_register(sp); 2450 int current_sp = get_register(sp);
1637 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp); 2451 uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
1638 uintptr_t address = *stack_slot; 2452 uintptr_t address = *stack_slot;
1639 set_register(sp, current_sp + sizeof(uintptr_t)); 2453 set_register(sp, current_sp + sizeof(uintptr_t));
1640 return address; 2454 return address;
1641 } 2455 }
1642 2456
1643 2457
1644 #undef UNSUPPORTED 2458 #undef UNSUPPORTED
1645 2459
1646 } } // namespace assembler::mips 2460 } } // namespace v8::internal
1647 2461
1648 #endif // !__mips || USE_SIMULATOR 2462 #endif // USE_SIMULATOR
1649 2463
1650 #endif // V8_TARGET_ARCH_MIPS 2464 #endif // V8_TARGET_ARCH_MIPS
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698