OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <limits.h> | 5 #include <limits.h> |
6 #include <stdarg.h> | 6 #include <stdarg.h> |
7 #include <stdlib.h> | 7 #include <stdlib.h> |
8 #include <cmath> | 8 #include <cmath> |
9 | 9 |
10 #include "src/v8.h" | 10 #include "src/v8.h" |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 void PrintAllRegsIncludingFPU(); | 60 void PrintAllRegsIncludingFPU(); |
61 | 61 |
62 private: | 62 private: |
63 // We set the breakpoint code to 0xfffff to easily recognize it. | 63 // We set the breakpoint code to 0xfffff to easily recognize it. |
64 static const Instr kBreakpointInstr = SPECIAL | BREAK | 0xfffff << 6; | 64 static const Instr kBreakpointInstr = SPECIAL | BREAK | 0xfffff << 6; |
65 static const Instr kNopInstr = 0x0; | 65 static const Instr kNopInstr = 0x0; |
66 | 66 |
67 Simulator* sim_; | 67 Simulator* sim_; |
68 | 68 |
69 int32_t GetRegisterValue(int regnum); | 69 int32_t GetRegisterValue(int regnum); |
70 int32_t GetFPURegisterValue32(int regnum); | 70 int32_t GetFPURegisterValueInt(int regnum); |
71 int64_t GetFPURegisterValue64(int regnum); | 71 int64_t GetFPURegisterValueLong(int regnum); |
72 float GetFPURegisterValueFloat(int regnum); | 72 float GetFPURegisterValueFloat(int regnum); |
73 double GetFPURegisterValueDouble(int regnum); | 73 double GetFPURegisterValueDouble(int regnum); |
74 bool GetValue(const char* desc, int32_t* value); | 74 bool GetValue(const char* desc, int32_t* value); |
75 bool GetValue(const char* desc, int64_t* value); | |
76 | 75 |
77 // Set or delete a breakpoint. Returns true if successful. | 76 // Set or delete a breakpoint. Returns true if successful. |
78 bool SetBreakpoint(Instruction* breakpc); | 77 bool SetBreakpoint(Instruction* breakpc); |
79 bool DeleteBreakpoint(Instruction* breakpc); | 78 bool DeleteBreakpoint(Instruction* breakpc); |
80 | 79 |
81 // Undo and redo all breakpoints. This is needed to bracket disassembly and | 80 // Undo and redo all breakpoints. This is needed to bracket disassembly and |
82 // execution to skip past breakpoints when run from the debugger. | 81 // execution to skip past breakpoints when run from the debugger. |
83 void UndoBreakpoints(); | 82 void UndoBreakpoints(); |
84 void RedoBreakpoints(); | 83 void RedoBreakpoints(); |
85 }; | 84 }; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
154 | 153 |
155 int32_t MipsDebugger::GetRegisterValue(int regnum) { | 154 int32_t MipsDebugger::GetRegisterValue(int regnum) { |
156 if (regnum == kNumSimuRegisters) { | 155 if (regnum == kNumSimuRegisters) { |
157 return sim_->get_pc(); | 156 return sim_->get_pc(); |
158 } else { | 157 } else { |
159 return sim_->get_register(regnum); | 158 return sim_->get_register(regnum); |
160 } | 159 } |
161 } | 160 } |
162 | 161 |
163 | 162 |
164 int32_t MipsDebugger::GetFPURegisterValue32(int regnum) { | 163 int32_t MipsDebugger::GetFPURegisterValueInt(int regnum) { |
165 if (regnum == kNumFPURegisters) { | |
166 return sim_->get_pc(); | |
167 } else { | |
168 return sim_->get_fpu_register_word(regnum); | |
169 } | |
170 } | |
171 | |
172 | |
173 int64_t MipsDebugger::GetFPURegisterValue64(int regnum) { | |
174 if (regnum == kNumFPURegisters) { | 164 if (regnum == kNumFPURegisters) { |
175 return sim_->get_pc(); | 165 return sim_->get_pc(); |
176 } else { | 166 } else { |
177 return sim_->get_fpu_register(regnum); | 167 return sim_->get_fpu_register(regnum); |
178 } | 168 } |
179 } | 169 } |
180 | 170 |
| 171 |
| 172 int64_t MipsDebugger::GetFPURegisterValueLong(int regnum) { |
| 173 if (regnum == kNumFPURegisters) { |
| 174 return sim_->get_pc(); |
| 175 } else { |
| 176 return sim_->get_fpu_register_long(regnum); |
| 177 } |
| 178 } |
| 179 |
181 | 180 |
182 float MipsDebugger::GetFPURegisterValueFloat(int regnum) { | 181 float MipsDebugger::GetFPURegisterValueFloat(int regnum) { |
183 if (regnum == kNumFPURegisters) { | 182 if (regnum == kNumFPURegisters) { |
184 return sim_->get_pc(); | 183 return sim_->get_pc(); |
185 } else { | 184 } else { |
186 return sim_->get_fpu_register_float(regnum); | 185 return sim_->get_fpu_register_float(regnum); |
187 } | 186 } |
188 } | 187 } |
189 | 188 |
190 | 189 |
191 double MipsDebugger::GetFPURegisterValueDouble(int regnum) { | 190 double MipsDebugger::GetFPURegisterValueDouble(int regnum) { |
192 if (regnum == kNumFPURegisters) { | 191 if (regnum == kNumFPURegisters) { |
193 return sim_->get_pc(); | 192 return sim_->get_pc(); |
194 } else { | 193 } else { |
195 return sim_->get_fpu_register_double(regnum); | 194 return sim_->get_fpu_register_double(regnum); |
196 } | 195 } |
197 } | 196 } |
198 | 197 |
199 | 198 |
200 bool MipsDebugger::GetValue(const char* desc, int32_t* value) { | 199 bool MipsDebugger::GetValue(const char* desc, int32_t* value) { |
201 int regnum = Registers::Number(desc); | 200 int regnum = Registers::Number(desc); |
202 int fpuregnum = FPURegisters::Number(desc); | 201 int fpuregnum = FPURegisters::Number(desc); |
203 | 202 |
204 if (regnum != kInvalidRegister) { | 203 if (regnum != kInvalidRegister) { |
205 *value = GetRegisterValue(regnum); | 204 *value = GetRegisterValue(regnum); |
206 return true; | 205 return true; |
207 } else if (fpuregnum != kInvalidFPURegister) { | 206 } else if (fpuregnum != kInvalidFPURegister) { |
208 *value = GetFPURegisterValue32(fpuregnum); | 207 *value = GetFPURegisterValueInt(fpuregnum); |
209 return true; | 208 return true; |
210 } else if (strncmp(desc, "0x", 2) == 0) { | 209 } else if (strncmp(desc, "0x", 2) == 0) { |
211 return SScanF(desc, "%x", reinterpret_cast<uint32_t*>(value)) == 1; | 210 return SScanF(desc, "%x", reinterpret_cast<uint32_t*>(value)) == 1; |
212 } else { | 211 } else { |
213 return SScanF(desc, "%i", value) == 1; | 212 return SScanF(desc, "%i", value) == 1; |
214 } | 213 } |
215 return false; | 214 return false; |
216 } | 215 } |
217 | 216 |
218 | 217 |
219 bool MipsDebugger::GetValue(const char* desc, int64_t* value) { | |
220 int regnum = Registers::Number(desc); | |
221 int fpuregnum = FPURegisters::Number(desc); | |
222 | |
223 if (regnum != kInvalidRegister) { | |
224 *value = GetRegisterValue(regnum); | |
225 return true; | |
226 } else if (fpuregnum != kInvalidFPURegister) { | |
227 *value = GetFPURegisterValue64(fpuregnum); | |
228 return true; | |
229 } else if (strncmp(desc, "0x", 2) == 0) { | |
230 return SScanF(desc + 2, "%" SCNx64, | |
231 reinterpret_cast<uint64_t*>(value)) == 1; | |
232 } else { | |
233 return SScanF(desc, "%" SCNu64, reinterpret_cast<uint64_t*>(value)) == 1; | |
234 } | |
235 return false; | |
236 } | |
237 | |
238 | |
239 bool MipsDebugger::SetBreakpoint(Instruction* breakpc) { | 218 bool MipsDebugger::SetBreakpoint(Instruction* breakpc) { |
240 // Check if a breakpoint can be set. If not return without any side-effects. | 219 // Check if a breakpoint can be set. If not return without any side-effects. |
241 if (sim_->break_pc_ != NULL) { | 220 if (sim_->break_pc_ != NULL) { |
242 return false; | 221 return false; |
243 } | 222 } |
244 | 223 |
245 // Set the breakpoint. | 224 // Set the breakpoint. |
246 sim_->break_pc_ = breakpc; | 225 sim_->break_pc_ = breakpc; |
247 sim_->break_instr_ = breakpc->InstructionBits(); | 226 sim_->break_instr_ = breakpc->InstructionBits(); |
248 // Not setting the breakpoint instruction in the code itself. It will be set | 227 // Not setting the breakpoint instruction in the code itself. It will be set |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 // pc. | 288 // pc. |
310 PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n", | 289 PrintF("%3s: 0x%08x %10d\t%3s: 0x%08x %10d\n", |
311 REG_INFO(31), REG_INFO(34)); | 290 REG_INFO(31), REG_INFO(34)); |
312 | 291 |
313 #undef REG_INFO | 292 #undef REG_INFO |
314 #undef FPU_REG_INFO | 293 #undef FPU_REG_INFO |
315 } | 294 } |
316 | 295 |
317 | 296 |
318 void MipsDebugger::PrintAllRegsIncludingFPU() { | 297 void MipsDebugger::PrintAllRegsIncludingFPU() { |
319 #define FPU_REG_INFO32(n) FPURegisters::Name(n), FPURegisters::Name(n+1), \ | 298 #define FPU_REG_INFO(n) FPURegisters::Name(n), FPURegisters::Name(n+1), \ |
320 GetFPURegisterValue32(n+1), \ | 299 GetFPURegisterValueInt(n+1), \ |
321 GetFPURegisterValue32(n), \ | 300 GetFPURegisterValueInt(n), \ |
322 GetFPURegisterValueDouble(n) | 301 GetFPURegisterValueDouble(n) |
323 | |
324 #define FPU_REG_INFO64(n) FPURegisters::Name(n), \ | |
325 GetFPURegisterValue64(n), \ | |
326 GetFPURegisterValueDouble(n) | |
327 | 302 |
328 PrintAllRegs(); | 303 PrintAllRegs(); |
329 | 304 |
330 PrintF("\n\n"); | 305 PrintF("\n\n"); |
331 // f0, f1, f2, ... f31. | 306 // f0, f1, f2, ... f31. |
332 // This must be a compile-time switch, | 307 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(0) ); |
333 // compiler will throw out warnings otherwise. | 308 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(2) ); |
334 if (kFpuMode == kFP64) { | 309 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(4) ); |
335 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(0) ); | 310 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(6) ); |
336 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(1) ); | 311 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(8) ); |
337 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(2) ); | 312 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(10)); |
338 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(3) ); | 313 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(12)); |
339 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(4) ); | 314 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(14)); |
340 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(5) ); | 315 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(16)); |
341 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(6) ); | 316 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(18)); |
342 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(7) ); | 317 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(20)); |
343 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(8) ); | 318 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(22)); |
344 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(9) ); | 319 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(24)); |
345 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(10)); | 320 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(26)); |
346 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(11)); | 321 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(28)); |
347 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(12)); | 322 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO(30)); |
348 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(13)); | |
349 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(14)); | |
350 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(15)); | |
351 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(16)); | |
352 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(17)); | |
353 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(18)); | |
354 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(19)); | |
355 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(20)); | |
356 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(21)); | |
357 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(22)); | |
358 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(23)); | |
359 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(24)); | |
360 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(25)); | |
361 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(26)); | |
362 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(27)); | |
363 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(28)); | |
364 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(29)); | |
365 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(30)); | |
366 PrintF("%3s: 0x%016llx %16.4e\n", FPU_REG_INFO64(31)); | |
367 } else { | |
368 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(0) ); | |
369 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(2) ); | |
370 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(4) ); | |
371 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(6) ); | |
372 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(8) ); | |
373 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(10)); | |
374 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(12)); | |
375 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(14)); | |
376 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(16)); | |
377 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(18)); | |
378 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(20)); | |
379 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(22)); | |
380 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(24)); | |
381 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(26)); | |
382 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(28)); | |
383 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", FPU_REG_INFO32(30)); | |
384 } | |
385 | 323 |
386 #undef REG_INFO | 324 #undef REG_INFO |
387 #undef FPU_REG_INFO32 | 325 #undef FPU_REG_INFO |
388 #undef FPU_REG_INFO64 | |
389 } | 326 } |
390 | 327 |
391 | 328 |
392 void MipsDebugger::Debug() { | 329 void MipsDebugger::Debug() { |
393 intptr_t last_pc = -1; | 330 intptr_t last_pc = -1; |
394 bool done = false; | 331 bool done = false; |
395 | 332 |
396 #define COMMAND_SIZE 63 | 333 #define COMMAND_SIZE 63 |
397 #define ARG_SIZE 255 | 334 #define ARG_SIZE 255 |
398 | 335 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 PrintF("/!\\ Jumping over generated breakpoint.\n"); | 390 PrintF("/!\\ Jumping over generated breakpoint.\n"); |
454 sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize); | 391 sim_->set_pc(sim_->get_pc() + Instruction::kInstrSize); |
455 } | 392 } |
456 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { | 393 } else if ((strcmp(cmd, "c") == 0) || (strcmp(cmd, "cont") == 0)) { |
457 // Execute the one instruction we broke at with breakpoints disabled. | 394 // Execute the one instruction we broke at with breakpoints disabled. |
458 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc())); | 395 sim_->InstructionDecode(reinterpret_cast<Instruction*>(sim_->get_pc())); |
459 // Leave the debugger shell. | 396 // Leave the debugger shell. |
460 done = true; | 397 done = true; |
461 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { | 398 } else if ((strcmp(cmd, "p") == 0) || (strcmp(cmd, "print") == 0)) { |
462 if (argc == 2) { | 399 if (argc == 2) { |
| 400 int32_t value; |
| 401 float fvalue; |
463 if (strcmp(arg1, "all") == 0) { | 402 if (strcmp(arg1, "all") == 0) { |
464 PrintAllRegs(); | 403 PrintAllRegs(); |
465 } else if (strcmp(arg1, "allf") == 0) { | 404 } else if (strcmp(arg1, "allf") == 0) { |
466 PrintAllRegsIncludingFPU(); | 405 PrintAllRegsIncludingFPU(); |
467 } else { | 406 } else { |
468 int regnum = Registers::Number(arg1); | 407 int regnum = Registers::Number(arg1); |
469 int fpuregnum = FPURegisters::Number(arg1); | 408 int fpuregnum = FPURegisters::Number(arg1); |
470 | 409 |
471 if (regnum != kInvalidRegister) { | 410 if (regnum != kInvalidRegister) { |
472 int32_t value; | |
473 value = GetRegisterValue(regnum); | 411 value = GetRegisterValue(regnum); |
474 PrintF("%s: 0x%08x %d \n", arg1, value, value); | 412 PrintF("%s: 0x%08x %d \n", arg1, value, value); |
475 } else if (fpuregnum != kInvalidFPURegister) { | 413 } else if (fpuregnum != kInvalidFPURegister) { |
476 if (IsFp64Mode()) { | 414 if (fpuregnum % 2 == 1) { |
477 int64_t value; | 415 value = GetFPURegisterValueInt(fpuregnum); |
478 double dvalue; | 416 fvalue = GetFPURegisterValueFloat(fpuregnum); |
479 value = GetFPURegisterValue64(fpuregnum); | 417 PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue); |
480 dvalue = GetFPURegisterValueDouble(fpuregnum); | |
481 PrintF("%3s: 0x%016llx %16.4e\n", | |
482 FPURegisters::Name(fpuregnum), value, dvalue); | |
483 } else { | 418 } else { |
484 if (fpuregnum % 2 == 1) { | 419 double dfvalue; |
485 int32_t value; | 420 int32_t lvalue1 = GetFPURegisterValueInt(fpuregnum); |
486 float fvalue; | 421 int32_t lvalue2 = GetFPURegisterValueInt(fpuregnum + 1); |
487 value = GetFPURegisterValue32(fpuregnum); | 422 dfvalue = GetFPURegisterValueDouble(fpuregnum); |
488 fvalue = GetFPURegisterValueFloat(fpuregnum); | 423 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", |
489 PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue); | 424 FPURegisters::Name(fpuregnum+1), |
490 } else { | 425 FPURegisters::Name(fpuregnum), |
491 double dfvalue; | 426 lvalue1, |
492 int32_t lvalue1 = GetFPURegisterValue32(fpuregnum); | 427 lvalue2, |
493 int32_t lvalue2 = GetFPURegisterValue32(fpuregnum + 1); | 428 dfvalue); |
494 dfvalue = GetFPURegisterValueDouble(fpuregnum); | |
495 PrintF("%3s,%3s: 0x%08x%08x %16.4e\n", | |
496 FPURegisters::Name(fpuregnum+1), | |
497 FPURegisters::Name(fpuregnum), | |
498 lvalue1, | |
499 lvalue2, | |
500 dfvalue); | |
501 } | |
502 } | 429 } |
503 } else { | 430 } else { |
504 PrintF("%s unrecognized\n", arg1); | 431 PrintF("%s unrecognized\n", arg1); |
505 } | 432 } |
506 } | 433 } |
507 } else { | 434 } else { |
508 if (argc == 3) { | 435 if (argc == 3) { |
509 if (strcmp(arg2, "single") == 0) { | 436 if (strcmp(arg2, "single") == 0) { |
510 int32_t value; | 437 int32_t value; |
511 float fvalue; | 438 float fvalue; |
512 int fpuregnum = FPURegisters::Number(arg1); | 439 int fpuregnum = FPURegisters::Number(arg1); |
513 | 440 |
514 if (fpuregnum != kInvalidFPURegister) { | 441 if (fpuregnum != kInvalidFPURegister) { |
515 value = GetFPURegisterValue32(fpuregnum); | 442 value = GetFPURegisterValueInt(fpuregnum); |
516 fvalue = GetFPURegisterValueFloat(fpuregnum); | 443 fvalue = GetFPURegisterValueFloat(fpuregnum); |
517 PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue); | 444 PrintF("%s: 0x%08x %11.4e\n", arg1, value, fvalue); |
518 } else { | 445 } else { |
519 PrintF("%s unrecognized\n", arg1); | 446 PrintF("%s unrecognized\n", arg1); |
520 } | 447 } |
521 } else { | 448 } else { |
522 PrintF("print <fpu register> single\n"); | 449 PrintF("print <fpu register> single\n"); |
523 } | 450 } |
524 } else { | 451 } else { |
525 PrintF("print <register> or print <fpu register> single\n"); | 452 PrintF("print <register> or print <fpu register> single\n"); |
(...skipping 29 matching lines...) Expand all Loading... |
555 } else { // Command "mem". | 482 } else { // Command "mem". |
556 int32_t value; | 483 int32_t value; |
557 if (!GetValue(arg1, &value)) { | 484 if (!GetValue(arg1, &value)) { |
558 PrintF("%s unrecognized\n", arg1); | 485 PrintF("%s unrecognized\n", arg1); |
559 continue; | 486 continue; |
560 } | 487 } |
561 cur = reinterpret_cast<int32_t*>(value); | 488 cur = reinterpret_cast<int32_t*>(value); |
562 next_arg++; | 489 next_arg++; |
563 } | 490 } |
564 | 491 |
565 // TODO(palfia): optimize this. | 492 int32_t words; |
566 if (IsFp64Mode()) { | 493 if (argc == next_arg) { |
567 int64_t words; | 494 words = 10; |
568 if (argc == next_arg) { | 495 } else { |
| 496 if (!GetValue(argv[next_arg], &words)) { |
569 words = 10; | 497 words = 10; |
570 } else { | |
571 if (!GetValue(argv[next_arg], &words)) { | |
572 words = 10; | |
573 } | |
574 } | 498 } |
575 end = cur + words; | |
576 } else { | |
577 int32_t words; | |
578 if (argc == next_arg) { | |
579 words = 10; | |
580 } else { | |
581 if (!GetValue(argv[next_arg], &words)) { | |
582 words = 10; | |
583 } | |
584 } | |
585 end = cur + words; | |
586 } | 499 } |
| 500 end = cur + words; |
587 | 501 |
588 while (cur < end) { | 502 while (cur < end) { |
589 PrintF(" 0x%08x: 0x%08x %10d", | 503 PrintF(" 0x%08x: 0x%08x %10d", |
590 reinterpret_cast<intptr_t>(cur), *cur, *cur); | 504 reinterpret_cast<intptr_t>(cur), *cur, *cur); |
591 HeapObject* obj = reinterpret_cast<HeapObject*>(*cur); | 505 HeapObject* obj = reinterpret_cast<HeapObject*>(*cur); |
592 int value = *cur; | 506 int value = *cur; |
593 Heap* current_heap = v8::internal::Isolate::Current()->heap(); | 507 Heap* current_heap = v8::internal::Isolate::Current()->heap(); |
594 if (((value & 1) == 0) || current_heap->Contains(obj)) { | 508 if (((value & 1) == 0) || current_heap->Contains(obj)) { |
595 PrintF(" ("); | 509 PrintF(" ("); |
596 if ((value & 1) == 0) { | 510 if ((value & 1) == 0) { |
(...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1091 } | 1005 } |
1092 | 1006 |
1093 | 1007 |
1094 void Simulator::set_dw_register(int reg, const int* dbl) { | 1008 void Simulator::set_dw_register(int reg, const int* dbl) { |
1095 DCHECK((reg >= 0) && (reg < kNumSimuRegisters)); | 1009 DCHECK((reg >= 0) && (reg < kNumSimuRegisters)); |
1096 registers_[reg] = dbl[0]; | 1010 registers_[reg] = dbl[0]; |
1097 registers_[reg + 1] = dbl[1]; | 1011 registers_[reg + 1] = dbl[1]; |
1098 } | 1012 } |
1099 | 1013 |
1100 | 1014 |
1101 void Simulator::set_fpu_register(int fpureg, int64_t value) { | 1015 void Simulator::set_fpu_register(int fpureg, int32_t value) { |
1102 DCHECK(IsFp64Mode()); | |
1103 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); | 1016 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); |
1104 FPUregisters_[fpureg] = value; | 1017 FPUregisters_[fpureg] = value; |
1105 } | 1018 } |
1106 | 1019 |
1107 | 1020 |
1108 void Simulator::set_fpu_register_word(int fpureg, int32_t value) { | |
1109 // Set ONLY lower 32-bits, leaving upper bits untouched. | |
1110 // TODO(plind): big endian issue. | |
1111 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); | |
1112 int32_t *pword = reinterpret_cast<int32_t*>(&FPUregisters_[fpureg]); | |
1113 *pword = value; | |
1114 } | |
1115 | |
1116 | |
1117 void Simulator::set_fpu_register_hi_word(int fpureg, int32_t value) { | |
1118 // Set ONLY upper 32-bits, leaving lower bits untouched. | |
1119 // TODO(plind): big endian issue. | |
1120 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); | |
1121 int32_t *phiword = (reinterpret_cast<int32_t*>(&FPUregisters_[fpureg])) + 1; | |
1122 *phiword = value; | |
1123 } | |
1124 | |
1125 | |
1126 void Simulator::set_fpu_register_float(int fpureg, float value) { | 1021 void Simulator::set_fpu_register_float(int fpureg, float value) { |
1127 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); | 1022 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); |
1128 *BitCast<float*>(&FPUregisters_[fpureg]) = value; | 1023 *BitCast<float*>(&FPUregisters_[fpureg]) = value; |
1129 } | 1024 } |
1130 | 1025 |
1131 | 1026 |
1132 void Simulator::set_fpu_register_double(int fpureg, double value) { | 1027 void Simulator::set_fpu_register_double(int fpureg, double value) { |
1133 if (IsFp64Mode()) { | 1028 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0)); |
1134 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); | 1029 *BitCast<double*>(&FPUregisters_[fpureg]) = value; |
1135 *BitCast<double*>(&FPUregisters_[fpureg]) = value; | |
1136 } else { | |
1137 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0)); | |
1138 int64_t i64 = BitCast<int64_t>(value); | |
1139 set_fpu_register_word(fpureg, i64 & 0xffffffff); | |
1140 set_fpu_register_word(fpureg + 1, i64 >> 32); | |
1141 } | |
1142 } | 1030 } |
1143 | 1031 |
1144 | 1032 |
1145 // Get the register from the architecture state. This function does handle | 1033 // Get the register from the architecture state. This function does handle |
1146 // the special case of accessing the PC register. | 1034 // the special case of accessing the PC register. |
1147 int32_t Simulator::get_register(int reg) const { | 1035 int32_t Simulator::get_register(int reg) const { |
1148 DCHECK((reg >= 0) && (reg < kNumSimuRegisters)); | 1036 DCHECK((reg >= 0) && (reg < kNumSimuRegisters)); |
1149 if (reg == 0) | 1037 if (reg == 0) |
1150 return 0; | 1038 return 0; |
1151 else | 1039 else |
1152 return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0); | 1040 return registers_[reg] + ((reg == pc) ? Instruction::kPCReadOffset : 0); |
1153 } | 1041 } |
1154 | 1042 |
1155 | 1043 |
1156 double Simulator::get_double_from_register_pair(int reg) { | 1044 double Simulator::get_double_from_register_pair(int reg) { |
1157 // TODO(plind): bad ABI stuff, refactor or remove. | |
1158 DCHECK((reg >= 0) && (reg < kNumSimuRegisters) && ((reg % 2) == 0)); | 1045 DCHECK((reg >= 0) && (reg < kNumSimuRegisters) && ((reg % 2) == 0)); |
1159 | 1046 |
1160 double dm_val = 0.0; | 1047 double dm_val = 0.0; |
1161 // Read the bits from the unsigned integer register_[] array | 1048 // Read the bits from the unsigned integer register_[] array |
1162 // into the double precision floating point value and return it. | 1049 // into the double precision floating point value and return it. |
1163 char buffer[2 * sizeof(registers_[0])]; | 1050 char buffer[2 * sizeof(registers_[0])]; |
1164 memcpy(buffer, ®isters_[reg], 2 * sizeof(registers_[0])); | 1051 memcpy(buffer, ®isters_[reg], 2 * sizeof(registers_[0])); |
1165 memcpy(&dm_val, buffer, 2 * sizeof(registers_[0])); | 1052 memcpy(&dm_val, buffer, 2 * sizeof(registers_[0])); |
1166 return(dm_val); | 1053 return(dm_val); |
1167 } | 1054 } |
1168 | 1055 |
1169 | 1056 |
1170 int64_t Simulator::get_fpu_register(int fpureg) const { | 1057 int32_t Simulator::get_fpu_register(int fpureg) const { |
1171 DCHECK(IsFp64Mode()); | |
1172 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); | 1058 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); |
1173 return FPUregisters_[fpureg]; | 1059 return FPUregisters_[fpureg]; |
1174 } | 1060 } |
1175 | 1061 |
1176 | 1062 |
1177 int32_t Simulator::get_fpu_register_word(int fpureg) const { | 1063 int64_t Simulator::get_fpu_register_long(int fpureg) const { |
1178 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); | 1064 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0)); |
1179 return static_cast<int32_t>(FPUregisters_[fpureg] & 0xffffffff); | 1065 return *BitCast<int64_t*>( |
1180 } | 1066 const_cast<int32_t*>(&FPUregisters_[fpureg])); |
1181 | |
1182 | |
1183 int32_t Simulator::get_fpu_register_signed_word(int fpureg) const { | |
1184 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); | |
1185 return static_cast<int32_t>(FPUregisters_[fpureg] & 0xffffffff); | |
1186 } | |
1187 | |
1188 | |
1189 int32_t Simulator::get_fpu_register_hi_word(int fpureg) const { | |
1190 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); | |
1191 return static_cast<int32_t>((FPUregisters_[fpureg] >> 32) & 0xffffffff); | |
1192 } | 1067 } |
1193 | 1068 |
1194 | 1069 |
1195 float Simulator::get_fpu_register_float(int fpureg) const { | 1070 float Simulator::get_fpu_register_float(int fpureg) const { |
1196 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); | 1071 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); |
1197 return *BitCast<float*>( | 1072 return *BitCast<float*>( |
1198 const_cast<int64_t*>(&FPUregisters_[fpureg])); | 1073 const_cast<int32_t*>(&FPUregisters_[fpureg])); |
1199 } | 1074 } |
1200 | 1075 |
1201 | 1076 |
1202 double Simulator::get_fpu_register_double(int fpureg) const { | 1077 double Simulator::get_fpu_register_double(int fpureg) const { |
1203 if (IsFp64Mode()) { | 1078 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0)); |
1204 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters)); | 1079 return *BitCast<double*>(const_cast<int32_t*>(&FPUregisters_[fpureg])); |
1205 return *BitCast<double*>(&FPUregisters_[fpureg]); | |
1206 } else { | |
1207 DCHECK((fpureg >= 0) && (fpureg < kNumFPURegisters) && ((fpureg % 2) == 0)); | |
1208 int64_t i64; | |
1209 i64 = static_cast<uint32_t>(get_fpu_register_word(fpureg)); | |
1210 i64 |= static_cast<uint64_t>(get_fpu_register_word(fpureg + 1)) << 32; | |
1211 return BitCast<double>(i64); | |
1212 } | |
1213 } | 1080 } |
1214 | 1081 |
1215 | 1082 |
1216 // Runtime FP routines take up to two double arguments and zero | 1083 // Runtime FP routines take up to two double arguments and zero |
1217 // or one integer arguments. All are constructed here, | 1084 // or one integer arguments. All are constructed here, |
1218 // from a0-a3 or f12 and f14. | 1085 // from a0-a3 or f12 and f14. |
1219 void Simulator::GetFpArgs(double* x, double* y, int32_t* z) { | 1086 void Simulator::GetFpArgs(double* x, double* y, int32_t* z) { |
1220 if (!IsMipsSoftFloatABI) { | 1087 if (!IsMipsSoftFloatABI) { |
1221 *x = get_fpu_register_double(12); | 1088 *x = get_fpu_register_double(12); |
1222 *y = get_fpu_register_double(14); | 1089 *y = get_fpu_register_double(14); |
1223 *z = get_register(a2); | 1090 *z = get_register(a2); |
1224 } else { | 1091 } else { |
1225 // TODO(plind): bad ABI stuff, refactor or remove. | |
1226 // We use a char buffer to get around the strict-aliasing rules which | 1092 // We use a char buffer to get around the strict-aliasing rules which |
1227 // otherwise allow the compiler to optimize away the copy. | 1093 // otherwise allow the compiler to optimize away the copy. |
1228 char buffer[sizeof(*x)]; | 1094 char buffer[sizeof(*x)]; |
1229 int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer); | 1095 int32_t* reg_buffer = reinterpret_cast<int32_t*>(buffer); |
1230 | 1096 |
1231 // Registers a0 and a1 -> x. | 1097 // Registers a0 and a1 -> x. |
1232 reg_buffer[0] = get_register(a0); | 1098 reg_buffer[0] = get_register(a0); |
1233 reg_buffer[1] = get_register(a1); | 1099 reg_buffer[1] = get_register(a1); |
1234 memcpy(x, buffer, sizeof(buffer)); | 1100 memcpy(x, buffer, sizeof(buffer)); |
1235 // Registers a2 and a3 -> y. | 1101 // Registers a2 and a3 -> y. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1270 | 1136 |
1271 bool Simulator::test_fcsr_bit(uint32_t cc) { | 1137 bool Simulator::test_fcsr_bit(uint32_t cc) { |
1272 return FCSR_ & (1 << cc); | 1138 return FCSR_ & (1 << cc); |
1273 } | 1139 } |
1274 | 1140 |
1275 | 1141 |
1276 // Sets the rounding error codes in FCSR based on the result of the rounding. | 1142 // Sets the rounding error codes in FCSR based on the result of the rounding. |
1277 // Returns true if the operation was invalid. | 1143 // Returns true if the operation was invalid. |
1278 bool Simulator::set_fcsr_round_error(double original, double rounded) { | 1144 bool Simulator::set_fcsr_round_error(double original, double rounded) { |
1279 bool ret = false; | 1145 bool ret = false; |
1280 double max_int32 = std::numeric_limits<int32_t>::max(); | |
1281 double min_int32 = std::numeric_limits<int32_t>::min(); | |
1282 | 1146 |
1283 if (!std::isfinite(original) || !std::isfinite(rounded)) { | 1147 if (!std::isfinite(original) || !std::isfinite(rounded)) { |
1284 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); | 1148 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); |
1285 ret = true; | 1149 ret = true; |
1286 } | 1150 } |
1287 | 1151 |
1288 if (original != rounded) { | 1152 if (original != rounded) { |
1289 set_fcsr_bit(kFCSRInexactFlagBit, true); | 1153 set_fcsr_bit(kFCSRInexactFlagBit, true); |
1290 } | 1154 } |
1291 | 1155 |
1292 if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) { | 1156 if (rounded < DBL_MIN && rounded > -DBL_MIN && rounded != 0) { |
1293 set_fcsr_bit(kFCSRUnderflowFlagBit, true); | 1157 set_fcsr_bit(kFCSRUnderflowFlagBit, true); |
1294 ret = true; | 1158 ret = true; |
1295 } | 1159 } |
1296 | 1160 |
1297 if (rounded > max_int32 || rounded < min_int32) { | 1161 if (rounded > INT_MAX || rounded < INT_MIN) { |
1298 set_fcsr_bit(kFCSROverflowFlagBit, true); | 1162 set_fcsr_bit(kFCSROverflowFlagBit, true); |
1299 // The reference is not really clear but it seems this is required: | 1163 // The reference is not really clear but it seems this is required: |
1300 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); | 1164 set_fcsr_bit(kFCSRInvalidOpFlagBit, true); |
1301 ret = true; | 1165 ret = true; |
1302 } | 1166 } |
1303 | 1167 |
1304 return ret; | 1168 return ret; |
1305 } | 1169 } |
1306 | 1170 |
1307 | 1171 |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1549 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL); | 1413 (redirection->type() == ExternalReference::BUILTIN_FP_INT_CALL); |
1550 | 1414 |
1551 if (!IsMipsSoftFloatABI) { | 1415 if (!IsMipsSoftFloatABI) { |
1552 // With the hard floating point calling convention, double | 1416 // With the hard floating point calling convention, double |
1553 // arguments are passed in FPU registers. Fetch the arguments | 1417 // arguments are passed in FPU registers. Fetch the arguments |
1554 // from there and call the builtin using soft floating point | 1418 // from there and call the builtin using soft floating point |
1555 // convention. | 1419 // convention. |
1556 switch (redirection->type()) { | 1420 switch (redirection->type()) { |
1557 case ExternalReference::BUILTIN_FP_FP_CALL: | 1421 case ExternalReference::BUILTIN_FP_FP_CALL: |
1558 case ExternalReference::BUILTIN_COMPARE_CALL: | 1422 case ExternalReference::BUILTIN_COMPARE_CALL: |
1559 if (IsFp64Mode()) { | 1423 arg0 = get_fpu_register(f12); |
1560 arg0 = get_fpu_register_word(f12); | 1424 arg1 = get_fpu_register(f13); |
1561 arg1 = get_fpu_register_hi_word(f12); | 1425 arg2 = get_fpu_register(f14); |
1562 arg2 = get_fpu_register_word(f14); | 1426 arg3 = get_fpu_register(f15); |
1563 arg3 = get_fpu_register_hi_word(f14); | |
1564 } else { | |
1565 arg0 = get_fpu_register_word(f12); | |
1566 arg1 = get_fpu_register_word(f13); | |
1567 arg2 = get_fpu_register_word(f14); | |
1568 arg3 = get_fpu_register_word(f15); | |
1569 } | |
1570 break; | 1427 break; |
1571 case ExternalReference::BUILTIN_FP_CALL: | 1428 case ExternalReference::BUILTIN_FP_CALL: |
1572 if (IsFp64Mode()) { | 1429 arg0 = get_fpu_register(f12); |
1573 arg0 = get_fpu_register_word(f12); | 1430 arg1 = get_fpu_register(f13); |
1574 arg1 = get_fpu_register_hi_word(f12); | |
1575 } else { | |
1576 arg0 = get_fpu_register_word(f12); | |
1577 arg1 = get_fpu_register_word(f13); | |
1578 } | |
1579 break; | 1431 break; |
1580 case ExternalReference::BUILTIN_FP_INT_CALL: | 1432 case ExternalReference::BUILTIN_FP_INT_CALL: |
1581 if (IsFp64Mode()) { | 1433 arg0 = get_fpu_register(f12); |
1582 arg0 = get_fpu_register_word(f12); | 1434 arg1 = get_fpu_register(f13); |
1583 arg1 = get_fpu_register_hi_word(f12); | |
1584 } else { | |
1585 arg0 = get_fpu_register_word(f12); | |
1586 arg1 = get_fpu_register_word(f13); | |
1587 } | |
1588 arg2 = get_register(a2); | 1435 arg2 = get_register(a2); |
1589 break; | 1436 break; |
1590 default: | 1437 default: |
1591 break; | 1438 break; |
1592 } | 1439 } |
1593 } | 1440 } |
1594 | 1441 |
1595 // This is dodgy but it works because the C entry stubs are never moved. | 1442 // This is dodgy but it works because the C entry stubs are never moved. |
1596 // See comment in codegen-arm.cc and bug 1242173. | 1443 // See comment in codegen-arm.cc and bug 1242173. |
1597 int32_t saved_ra = get_register(ra); | 1444 int32_t saved_ra = get_register(ra); |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1881 const int32_t rd_reg = instr->RdValue(); | 1728 const int32_t rd_reg = instr->RdValue(); |
1882 const uint32_t sa = instr->SaValue(); | 1729 const uint32_t sa = instr->SaValue(); |
1883 | 1730 |
1884 const int32_t fs_reg = instr->FsValue(); | 1731 const int32_t fs_reg = instr->FsValue(); |
1885 | 1732 |
1886 | 1733 |
1887 // ---------- Configuration. | 1734 // ---------- Configuration. |
1888 switch (op) { | 1735 switch (op) { |
1889 case COP1: // Coprocessor instructions. | 1736 case COP1: // Coprocessor instructions. |
1890 switch (instr->RsFieldRaw()) { | 1737 switch (instr->RsFieldRaw()) { |
| 1738 case BC1: // Handled in DecodeTypeImmed, should never come here. |
| 1739 UNREACHABLE(); |
| 1740 break; |
1891 case CFC1: | 1741 case CFC1: |
1892 // At the moment only FCSR is supported. | 1742 // At the moment only FCSR is supported. |
1893 DCHECK(fs_reg == kFCSRRegister); | 1743 DCHECK(fs_reg == kFCSRRegister); |
1894 *alu_out = FCSR_; | 1744 *alu_out = FCSR_; |
1895 break; | 1745 break; |
1896 case MFC1: | 1746 case MFC1: |
1897 *alu_out = get_fpu_register_word(fs_reg); | 1747 *alu_out = get_fpu_register(fs_reg); |
1898 break; | 1748 break; |
1899 case MFHC1: | 1749 case MFHC1: |
1900 *alu_out = get_fpu_register_hi_word(fs_reg); | 1750 UNIMPLEMENTED_MIPS(); |
1901 break; | 1751 break; |
1902 case CTC1: | 1752 case CTC1: |
1903 case MTC1: | 1753 case MTC1: |
1904 case MTHC1: | 1754 case MTHC1: |
| 1755 // Do the store in the execution step. |
| 1756 break; |
1905 case S: | 1757 case S: |
1906 case D: | 1758 case D: |
1907 case W: | 1759 case W: |
1908 case L: | 1760 case L: |
1909 case PS: | 1761 case PS: |
1910 // Do everything in the execution step. | 1762 // Do everything in the execution step. |
1911 break; | 1763 break; |
1912 default: | 1764 default: |
1913 // BC1 BC1EQZ BC1NEZ handled in DecodeTypeImmed, should never come here. | 1765 UNIMPLEMENTED_MIPS(); |
1914 UNREACHABLE(); | |
1915 } | 1766 } |
1916 break; | 1767 break; |
1917 case COP1X: | 1768 case COP1X: |
1918 break; | 1769 break; |
1919 case SPECIAL: | 1770 case SPECIAL: |
1920 switch (instr->FunctionFieldRaw()) { | 1771 switch (instr->FunctionFieldRaw()) { |
1921 case JR: | 1772 case JR: |
1922 case JALR: | 1773 case JALR: |
1923 *next_pc = get_register(instr->RsValue()); | 1774 *next_pc = get_register(instr->RsValue()); |
1924 *return_addr_reg = instr->RdValue(); | 1775 *return_addr_reg = instr->RdValue(); |
(...skipping 27 matching lines...) Expand all Loading... |
1952 } else { | 1803 } else { |
1953 // Logical right-rotate of a word by a variable number of bits. | 1804 // Logical right-rotate of a word by a variable number of bits. |
1954 // This is special case od SRLV instruction, added in MIPS32 | 1805 // This is special case od SRLV instruction, added in MIPS32 |
1955 // Release 2. SA field is equal to 00001. | 1806 // Release 2. SA field is equal to 00001. |
1956 *alu_out = (rt_u >> rs_u) | (rt_u << (32 - rs_u)); | 1807 *alu_out = (rt_u >> rs_u) | (rt_u << (32 - rs_u)); |
1957 } | 1808 } |
1958 break; | 1809 break; |
1959 case SRAV: | 1810 case SRAV: |
1960 *alu_out = rt >> rs; | 1811 *alu_out = rt >> rs; |
1961 break; | 1812 break; |
1962 case MFHI: // MFHI == CLZ on R6. | 1813 case MFHI: |
1963 if (!IsMipsArchVariant(kMips32r6)) { | 1814 *alu_out = get_register(HI); |
1964 DCHECK(instr->SaValue() == 0); | |
1965 *alu_out = get_register(HI); | |
1966 } else { | |
1967 // MIPS spec: If no bits were set in GPR rs, the result written to | |
1968 // GPR rd is 32. | |
1969 // GCC __builtin_clz: If input is 0, the result is undefined. | |
1970 DCHECK(instr->SaValue() == 1); | |
1971 *alu_out = | |
1972 rs_u == 0 ? 32 : CompilerIntrinsics::CountLeadingZeros(rs_u); | |
1973 } | |
1974 break; | 1815 break; |
1975 case MFLO: | 1816 case MFLO: |
1976 *alu_out = get_register(LO); | 1817 *alu_out = get_register(LO); |
1977 break; | 1818 break; |
1978 case MULT: // MULT == MUL_MUH. | 1819 case MULT: |
1979 if (!IsMipsArchVariant(kMips32r6)) { | 1820 *i64hilo = static_cast<int64_t>(rs) * static_cast<int64_t>(rt); |
1980 *i64hilo = static_cast<int64_t>(rs) * static_cast<int64_t>(rt); | |
1981 } else { | |
1982 switch (instr->SaValue()) { | |
1983 case MUL_OP: | |
1984 case MUH_OP: | |
1985 *i64hilo = static_cast<int64_t>(rs) * static_cast<int64_t>(rt); | |
1986 break; | |
1987 default: | |
1988 UNIMPLEMENTED_MIPS(); | |
1989 break; | |
1990 } | |
1991 } | |
1992 break; | 1821 break; |
1993 case MULTU: // MULTU == MUL_MUH_U. | 1822 case MULTU: |
1994 if (!IsMipsArchVariant(kMips32r6)) { | 1823 *u64hilo = static_cast<uint64_t>(rs_u) * static_cast<uint64_t>(rt_u); |
1995 *u64hilo = static_cast<uint64_t>(rs_u) * | |
1996 static_cast<uint64_t>(rt_u); | |
1997 } else { | |
1998 switch (instr->SaValue()) { | |
1999 case MUL_OP: | |
2000 case MUH_OP: | |
2001 *u64hilo = static_cast<uint64_t>(rs_u) * | |
2002 static_cast<uint64_t>(rt_u); | |
2003 break; | |
2004 default: | |
2005 UNIMPLEMENTED_MIPS(); | |
2006 break; | |
2007 } | |
2008 } | |
2009 break; | 1824 break; |
2010 case ADD: | 1825 case ADD: |
2011 if (HaveSameSign(rs, rt)) { | 1826 if (HaveSameSign(rs, rt)) { |
2012 if (rs > 0) { | 1827 if (rs > 0) { |
2013 exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - rt); | 1828 exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - rt); |
2014 } else if (rs < 0) { | 1829 } else if (rs < 0) { |
2015 exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue - rt); | 1830 exceptions[kIntegerUnderflow] = rs < (Registers::kMinValue - rt); |
2016 } | 1831 } |
2017 } | 1832 } |
2018 *alu_out = rs + rt; | 1833 *alu_out = rs + rt; |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2176 &return_addr_reg, | 1991 &return_addr_reg, |
2177 &do_interrupt); | 1992 &do_interrupt); |
2178 | 1993 |
2179 // ---------- Raise exceptions triggered. | 1994 // ---------- Raise exceptions triggered. |
2180 SignalExceptions(); | 1995 SignalExceptions(); |
2181 | 1996 |
2182 // ---------- Execution. | 1997 // ---------- Execution. |
2183 switch (op) { | 1998 switch (op) { |
2184 case COP1: | 1999 case COP1: |
2185 switch (instr->RsFieldRaw()) { | 2000 switch (instr->RsFieldRaw()) { |
| 2001 case BC1: // Branch on coprocessor condition. |
| 2002 UNREACHABLE(); |
| 2003 break; |
2186 case CFC1: | 2004 case CFC1: |
2187 set_register(rt_reg, alu_out); | 2005 set_register(rt_reg, alu_out); |
2188 break; | |
2189 case MFC1: | 2006 case MFC1: |
2190 set_register(rt_reg, alu_out); | 2007 set_register(rt_reg, alu_out); |
2191 break; | 2008 break; |
2192 case MFHC1: | 2009 case MFHC1: |
2193 set_register(rt_reg, alu_out); | 2010 UNIMPLEMENTED_MIPS(); |
2194 break; | 2011 break; |
2195 case CTC1: | 2012 case CTC1: |
2196 // At the moment only FCSR is supported. | 2013 // At the moment only FCSR is supported. |
2197 DCHECK(fs_reg == kFCSRRegister); | 2014 DCHECK(fs_reg == kFCSRRegister); |
2198 FCSR_ = registers_[rt_reg]; | 2015 FCSR_ = registers_[rt_reg]; |
2199 break; | 2016 break; |
2200 case MTC1: | 2017 case MTC1: |
2201 // Hardware writes upper 32-bits to zero on mtc1. | 2018 FPUregisters_[fs_reg] = registers_[rt_reg]; |
2202 set_fpu_register_hi_word(fs_reg, 0); | |
2203 set_fpu_register_word(fs_reg, registers_[rt_reg]); | |
2204 break; | 2019 break; |
2205 case MTHC1: | 2020 case MTHC1: |
2206 set_fpu_register_hi_word(fs_reg, registers_[rt_reg]); | 2021 UNIMPLEMENTED_MIPS(); |
2207 break; | 2022 break; |
2208 case S: | 2023 case S: |
2209 float f; | 2024 float f; |
2210 switch (instr->FunctionFieldRaw()) { | 2025 switch (instr->FunctionFieldRaw()) { |
2211 case CVT_D_S: | 2026 case CVT_D_S: |
2212 f = get_fpu_register_float(fs_reg); | 2027 f = get_fpu_register_float(fs_reg); |
2213 set_fpu_register_double(fd_reg, static_cast<double>(f)); | 2028 set_fpu_register_double(fd_reg, static_cast<double>(f)); |
2214 break; | 2029 break; |
| 2030 case CVT_W_S: |
| 2031 case CVT_L_S: |
| 2032 case TRUNC_W_S: |
| 2033 case TRUNC_L_S: |
| 2034 case ROUND_W_S: |
| 2035 case ROUND_L_S: |
| 2036 case FLOOR_W_S: |
| 2037 case FLOOR_L_S: |
| 2038 case CEIL_W_S: |
| 2039 case CEIL_L_S: |
| 2040 case CVT_PS_S: |
| 2041 UNIMPLEMENTED_MIPS(); |
| 2042 break; |
2215 default: | 2043 default: |
2216 // CVT_W_S CVT_L_S TRUNC_W_S ROUND_W_S ROUND_L_S FLOOR_W_S FLOOR_L_S | |
2217 // CEIL_W_S CEIL_L_S CVT_PS_S are unimplemented. | |
2218 UNREACHABLE(); | 2044 UNREACHABLE(); |
2219 } | 2045 } |
2220 break; | 2046 break; |
2221 case D: | 2047 case D: |
2222 double ft, fs; | 2048 double ft, fs; |
2223 uint32_t cc, fcsr_cc; | 2049 uint32_t cc, fcsr_cc; |
2224 int64_t i64; | 2050 int64_t i64; |
2225 fs = get_fpu_register_double(fs_reg); | 2051 fs = get_fpu_register_double(fs_reg); |
2226 ft = get_fpu_register_double(ft_reg); | 2052 ft = get_fpu_register_double(ft_reg); |
2227 cc = instr->FCccValue(); | 2053 cc = instr->FCccValue(); |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2281 // In rounding mode 0 it should behave like ROUND. | 2107 // In rounding mode 0 it should behave like ROUND. |
2282 case ROUND_W_D: // Round double to word (round half to even). | 2108 case ROUND_W_D: // Round double to word (round half to even). |
2283 { | 2109 { |
2284 double rounded = std::floor(fs + 0.5); | 2110 double rounded = std::floor(fs + 0.5); |
2285 int32_t result = static_cast<int32_t>(rounded); | 2111 int32_t result = static_cast<int32_t>(rounded); |
2286 if ((result & 1) != 0 && result - fs == 0.5) { | 2112 if ((result & 1) != 0 && result - fs == 0.5) { |
2287 // If the number is halfway between two integers, | 2113 // If the number is halfway between two integers, |
2288 // round to the even one. | 2114 // round to the even one. |
2289 result--; | 2115 result--; |
2290 } | 2116 } |
2291 set_fpu_register_word(fd_reg, result); | 2117 set_fpu_register(fd_reg, result); |
2292 if (set_fcsr_round_error(fs, rounded)) { | 2118 if (set_fcsr_round_error(fs, rounded)) { |
2293 set_fpu_register(fd_reg, kFPUInvalidResult); | 2119 set_fpu_register(fd_reg, kFPUInvalidResult); |
2294 } | 2120 } |
2295 } | 2121 } |
2296 break; | 2122 break; |
2297 case TRUNC_W_D: // Truncate double to word (round towards 0). | 2123 case TRUNC_W_D: // Truncate double to word (round towards 0). |
2298 { | 2124 { |
2299 double rounded = trunc(fs); | 2125 double rounded = trunc(fs); |
2300 int32_t result = static_cast<int32_t>(rounded); | 2126 int32_t result = static_cast<int32_t>(rounded); |
2301 set_fpu_register_word(fd_reg, result); | 2127 set_fpu_register(fd_reg, result); |
2302 if (set_fcsr_round_error(fs, rounded)) { | 2128 if (set_fcsr_round_error(fs, rounded)) { |
2303 set_fpu_register(fd_reg, kFPUInvalidResult); | 2129 set_fpu_register(fd_reg, kFPUInvalidResult); |
2304 } | 2130 } |
2305 } | 2131 } |
2306 break; | 2132 break; |
2307 case FLOOR_W_D: // Round double to word towards negative infinity. | 2133 case FLOOR_W_D: // Round double to word towards negative infinity. |
2308 { | 2134 { |
2309 double rounded = std::floor(fs); | 2135 double rounded = std::floor(fs); |
2310 int32_t result = static_cast<int32_t>(rounded); | 2136 int32_t result = static_cast<int32_t>(rounded); |
2311 set_fpu_register_word(fd_reg, result); | 2137 set_fpu_register(fd_reg, result); |
2312 if (set_fcsr_round_error(fs, rounded)) { | 2138 if (set_fcsr_round_error(fs, rounded)) { |
2313 set_fpu_register(fd_reg, kFPUInvalidResult); | 2139 set_fpu_register(fd_reg, kFPUInvalidResult); |
2314 } | 2140 } |
2315 } | 2141 } |
2316 break; | 2142 break; |
2317 case CEIL_W_D: // Round double to word towards positive infinity. | 2143 case CEIL_W_D: // Round double to word towards positive infinity. |
2318 { | 2144 { |
2319 double rounded = std::ceil(fs); | 2145 double rounded = std::ceil(fs); |
2320 int32_t result = static_cast<int32_t>(rounded); | 2146 int32_t result = static_cast<int32_t>(rounded); |
2321 set_fpu_register_word(fd_reg, result); | 2147 set_fpu_register(fd_reg, result); |
2322 if (set_fcsr_round_error(fs, rounded)) { | 2148 if (set_fcsr_round_error(fs, rounded)) { |
2323 set_fpu_register(fd_reg, kFPUInvalidResult); | 2149 set_fpu_register(fd_reg, kFPUInvalidResult); |
2324 } | 2150 } |
2325 } | 2151 } |
2326 break; | 2152 break; |
2327 case CVT_S_D: // Convert double to float (single). | 2153 case CVT_S_D: // Convert double to float (single). |
2328 set_fpu_register_float(fd_reg, static_cast<float>(fs)); | 2154 set_fpu_register_float(fd_reg, static_cast<float>(fs)); |
2329 break; | 2155 break; |
2330 case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word. | 2156 case CVT_L_D: { // Mips32r2: Truncate double to 64-bit long-word. |
2331 double rounded = trunc(fs); | 2157 double rounded = trunc(fs); |
2332 i64 = static_cast<int64_t>(rounded); | 2158 i64 = static_cast<int64_t>(rounded); |
2333 if (IsFp64Mode()) { | 2159 set_fpu_register(fd_reg, i64 & 0xffffffff); |
2334 set_fpu_register(fd_reg, i64); | 2160 set_fpu_register(fd_reg + 1, i64 >> 32); |
2335 } else { | |
2336 set_fpu_register_word(fd_reg, i64 & 0xffffffff); | |
2337 set_fpu_register_word(fd_reg + 1, i64 >> 32); | |
2338 } | |
2339 break; | 2161 break; |
2340 } | 2162 } |
2341 case TRUNC_L_D: { // Mips32r2 instruction. | 2163 case TRUNC_L_D: { // Mips32r2 instruction. |
2342 double rounded = trunc(fs); | 2164 double rounded = trunc(fs); |
2343 i64 = static_cast<int64_t>(rounded); | 2165 i64 = static_cast<int64_t>(rounded); |
2344 if (IsFp64Mode()) { | 2166 set_fpu_register(fd_reg, i64 & 0xffffffff); |
2345 set_fpu_register(fd_reg, i64); | 2167 set_fpu_register(fd_reg + 1, i64 >> 32); |
2346 } else { | |
2347 set_fpu_register_word(fd_reg, i64 & 0xffffffff); | |
2348 set_fpu_register_word(fd_reg + 1, i64 >> 32); | |
2349 } | |
2350 break; | 2168 break; |
2351 } | 2169 } |
2352 case ROUND_L_D: { // Mips32r2 instruction. | 2170 case ROUND_L_D: { // Mips32r2 instruction. |
2353 double rounded = | 2171 double rounded = |
2354 fs > 0 ? std::floor(fs + 0.5) : std::ceil(fs - 0.5); | 2172 fs > 0 ? std::floor(fs + 0.5) : std::ceil(fs - 0.5); |
2355 i64 = static_cast<int64_t>(rounded); | 2173 i64 = static_cast<int64_t>(rounded); |
2356 if (IsFp64Mode()) { | 2174 set_fpu_register(fd_reg, i64 & 0xffffffff); |
2357 set_fpu_register(fd_reg, i64); | 2175 set_fpu_register(fd_reg + 1, i64 >> 32); |
2358 } else { | |
2359 set_fpu_register_word(fd_reg, i64 & 0xffffffff); | |
2360 set_fpu_register_word(fd_reg + 1, i64 >> 32); | |
2361 } | |
2362 break; | 2176 break; |
2363 } | 2177 } |
2364 case FLOOR_L_D: // Mips32r2 instruction. | 2178 case FLOOR_L_D: // Mips32r2 instruction. |
2365 i64 = static_cast<int64_t>(std::floor(fs)); | 2179 i64 = static_cast<int64_t>(std::floor(fs)); |
2366 if (IsFp64Mode()) { | 2180 set_fpu_register(fd_reg, i64 & 0xffffffff); |
2367 set_fpu_register(fd_reg, i64); | 2181 set_fpu_register(fd_reg + 1, i64 >> 32); |
2368 } else { | |
2369 set_fpu_register_word(fd_reg, i64 & 0xffffffff); | |
2370 set_fpu_register_word(fd_reg + 1, i64 >> 32); | |
2371 } | |
2372 break; | 2182 break; |
2373 case CEIL_L_D: // Mips32r2 instruction. | 2183 case CEIL_L_D: // Mips32r2 instruction. |
2374 i64 = static_cast<int64_t>(std::ceil(fs)); | 2184 i64 = static_cast<int64_t>(std::ceil(fs)); |
2375 if (IsFp64Mode()) { | 2185 set_fpu_register(fd_reg, i64 & 0xffffffff); |
2376 set_fpu_register(fd_reg, i64); | 2186 set_fpu_register(fd_reg + 1, i64 >> 32); |
2377 } else { | |
2378 set_fpu_register_word(fd_reg, i64 & 0xffffffff); | |
2379 set_fpu_register_word(fd_reg + 1, i64 >> 32); | |
2380 } | |
2381 break; | 2187 break; |
2382 case C_F_D: | 2188 case C_F_D: |
2383 UNIMPLEMENTED_MIPS(); | 2189 UNIMPLEMENTED_MIPS(); |
2384 break; | 2190 break; |
2385 default: | 2191 default: |
2386 UNREACHABLE(); | 2192 UNREACHABLE(); |
2387 } | 2193 } |
2388 break; | 2194 break; |
2389 case W: | 2195 case W: |
2390 switch (instr->FunctionFieldRaw()) { | 2196 switch (instr->FunctionFieldRaw()) { |
2391 case CVT_S_W: // Convert word to float (single). | 2197 case CVT_S_W: // Convert word to float (single). |
2392 alu_out = get_fpu_register_signed_word(fs_reg); | 2198 alu_out = get_fpu_register(fs_reg); |
2393 set_fpu_register_float(fd_reg, static_cast<float>(alu_out)); | 2199 set_fpu_register_float(fd_reg, static_cast<float>(alu_out)); |
2394 break; | 2200 break; |
2395 case CVT_D_W: // Convert word to double. | 2201 case CVT_D_W: // Convert word to double. |
2396 alu_out = get_fpu_register_signed_word(fs_reg); | 2202 alu_out = get_fpu_register(fs_reg); |
2397 set_fpu_register_double(fd_reg, static_cast<double>(alu_out)); | 2203 set_fpu_register_double(fd_reg, static_cast<double>(alu_out)); |
2398 break; | 2204 break; |
2399 default: // Mips64r6 CMP.S instructions unimplemented. | 2205 default: |
2400 UNREACHABLE(); | 2206 UNREACHABLE(); |
2401 } | 2207 } |
2402 break; | 2208 break; |
2403 case L: | 2209 case L: |
2404 fs = get_fpu_register_double(fs_reg); | |
2405 ft = get_fpu_register_double(ft_reg); | |
2406 switch (instr->FunctionFieldRaw()) { | 2210 switch (instr->FunctionFieldRaw()) { |
2407 case CVT_D_L: // Mips32r2 instruction. | 2211 case CVT_D_L: // Mips32r2 instruction. |
2408 // Watch the signs here, we want 2 32-bit vals | 2212 // Watch the signs here, we want 2 32-bit vals |
2409 // to make a sign-64. | 2213 // to make a sign-64. |
2410 if (IsFp64Mode()) { | 2214 i64 = static_cast<uint32_t>(get_fpu_register(fs_reg)); |
2411 i64 = get_fpu_register(fs_reg); | 2215 i64 |= static_cast<int64_t>(get_fpu_register(fs_reg + 1)) << 32; |
2412 } else { | |
2413 i64 = static_cast<uint32_t>(get_fpu_register_word(fs_reg)); | |
2414 i64 |= static_cast<int64_t>( | |
2415 get_fpu_register_word(fs_reg + 1)) << 32; | |
2416 } | |
2417 set_fpu_register_double(fd_reg, static_cast<double>(i64)); | 2216 set_fpu_register_double(fd_reg, static_cast<double>(i64)); |
2418 break; | 2217 break; |
2419 case CVT_S_L: | 2218 case CVT_S_L: |
2420 UNIMPLEMENTED_MIPS(); | 2219 UNIMPLEMENTED_MIPS(); |
2421 break; | 2220 break; |
2422 case CMP_AF: // Mips64r6 CMP.D instructions. | 2221 default: |
2423 UNIMPLEMENTED_MIPS(); | |
2424 break; | |
2425 case CMP_UN: | |
2426 if (std::isnan(fs) || std::isnan(ft)) { | |
2427 set_fpu_register(fd_reg, -1); | |
2428 } else { | |
2429 set_fpu_register(fd_reg, 0); | |
2430 } | |
2431 break; | |
2432 case CMP_EQ: | |
2433 if (fs == ft) { | |
2434 set_fpu_register(fd_reg, -1); | |
2435 } else { | |
2436 set_fpu_register(fd_reg, 0); | |
2437 } | |
2438 break; | |
2439 case CMP_UEQ: | |
2440 if ((fs == ft) || (std::isnan(fs) || std::isnan(ft))) { | |
2441 set_fpu_register(fd_reg, -1); | |
2442 } else { | |
2443 set_fpu_register(fd_reg, 0); | |
2444 } | |
2445 break; | |
2446 case CMP_LT: | |
2447 if (fs < ft) { | |
2448 set_fpu_register(fd_reg, -1); | |
2449 } else { | |
2450 set_fpu_register(fd_reg, 0); | |
2451 } | |
2452 break; | |
2453 case CMP_ULT: | |
2454 if ((fs < ft) || (std::isnan(fs) || std::isnan(ft))) { | |
2455 set_fpu_register(fd_reg, -1); | |
2456 } else { | |
2457 set_fpu_register(fd_reg, 0); | |
2458 } | |
2459 break; | |
2460 case CMP_LE: | |
2461 if (fs <= ft) { | |
2462 set_fpu_register(fd_reg, -1); | |
2463 } else { | |
2464 set_fpu_register(fd_reg, 0); | |
2465 } | |
2466 break; | |
2467 case CMP_ULE: | |
2468 if ((fs <= ft) || (std::isnan(fs) || std::isnan(ft))) { | |
2469 set_fpu_register(fd_reg, -1); | |
2470 } else { | |
2471 set_fpu_register(fd_reg, 0); | |
2472 } | |
2473 break; | |
2474 default: // CMP_OR CMP_UNE CMP_NE UNIMPLEMENTED. | |
2475 UNREACHABLE(); | 2222 UNREACHABLE(); |
2476 } | 2223 } |
2477 break; | 2224 break; |
| 2225 case PS: |
| 2226 break; |
2478 default: | 2227 default: |
2479 UNREACHABLE(); | 2228 UNREACHABLE(); |
2480 } | 2229 } |
2481 break; | 2230 break; |
2482 case COP1X: | 2231 case COP1X: |
2483 switch (instr->FunctionFieldRaw()) { | 2232 switch (instr->FunctionFieldRaw()) { |
2484 case MADD_D: | 2233 case MADD_D: |
2485 double fr, ft, fs; | 2234 double fr, ft, fs; |
2486 fr = get_fpu_register_double(fr_reg); | 2235 fr = get_fpu_register_double(fr_reg); |
2487 fs = get_fpu_register_double(fs_reg); | 2236 fs = get_fpu_register_double(fs_reg); |
(...skipping 19 matching lines...) Expand all Loading... |
2507 current_pc+Instruction::kInstrSize); | 2256 current_pc+Instruction::kInstrSize); |
2508 BranchDelayInstructionDecode(branch_delay_instr); | 2257 BranchDelayInstructionDecode(branch_delay_instr); |
2509 set_register(return_addr_reg, | 2258 set_register(return_addr_reg, |
2510 current_pc + 2 * Instruction::kInstrSize); | 2259 current_pc + 2 * Instruction::kInstrSize); |
2511 set_pc(next_pc); | 2260 set_pc(next_pc); |
2512 pc_modified_ = true; | 2261 pc_modified_ = true; |
2513 break; | 2262 break; |
2514 } | 2263 } |
2515 // Instructions using HI and LO registers. | 2264 // Instructions using HI and LO registers. |
2516 case MULT: | 2265 case MULT: |
2517 if (!IsMipsArchVariant(kMips32r6)) { | 2266 set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff)); |
2518 set_register(LO, static_cast<int32_t>(i64hilo & 0xffffffff)); | 2267 set_register(HI, static_cast<int32_t>(i64hilo >> 32)); |
2519 set_register(HI, static_cast<int32_t>(i64hilo >> 32)); | |
2520 } else { | |
2521 switch (instr->SaValue()) { | |
2522 case MUL_OP: | |
2523 set_register(rd_reg, | |
2524 static_cast<int32_t>(i64hilo & 0xffffffff)); | |
2525 break; | |
2526 case MUH_OP: | |
2527 set_register(rd_reg, static_cast<int32_t>(i64hilo >> 32)); | |
2528 break; | |
2529 default: | |
2530 UNIMPLEMENTED_MIPS(); | |
2531 break; | |
2532 } | |
2533 } | |
2534 break; | 2268 break; |
2535 case MULTU: | 2269 case MULTU: |
2536 if (!IsMipsArchVariant(kMips32r6)) { | 2270 set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff)); |
2537 set_register(LO, static_cast<int32_t>(u64hilo & 0xffffffff)); | 2271 set_register(HI, static_cast<int32_t>(u64hilo >> 32)); |
2538 set_register(HI, static_cast<int32_t>(u64hilo >> 32)); | |
2539 } else { | |
2540 switch (instr->SaValue()) { | |
2541 case MUL_OP: | |
2542 set_register(rd_reg, | |
2543 static_cast<int32_t>(u64hilo & 0xffffffff)); | |
2544 break; | |
2545 case MUH_OP: | |
2546 set_register(rd_reg, static_cast<int32_t>(u64hilo >> 32)); | |
2547 break; | |
2548 default: | |
2549 UNIMPLEMENTED_MIPS(); | |
2550 break; | |
2551 } | |
2552 } | |
2553 break; | 2272 break; |
2554 case DIV: | 2273 case DIV: |
2555 if (IsMipsArchVariant(kMips32r6)) { | 2274 // Divide by zero and overflow was not checked in the configuration |
2556 switch (instr->SaValue()) { | 2275 // step - div and divu do not raise exceptions. On division by 0 |
2557 case DIV_OP: | 2276 // the result will be UNPREDICTABLE. On overflow (INT_MIN/-1), |
2558 if (rs == INT_MIN && rt == -1) { | 2277 // return INT_MIN which is what the hardware does. |
2559 set_register(rd_reg, INT_MIN); | 2278 if (rs == INT_MIN && rt == -1) { |
2560 } else if (rt != 0) { | 2279 set_register(LO, INT_MIN); |
2561 set_register(rd_reg, rs / rt); | 2280 set_register(HI, 0); |
2562 } | 2281 } else if (rt != 0) { |
2563 break; | 2282 set_register(LO, rs / rt); |
2564 case MOD_OP: | 2283 set_register(HI, rs % rt); |
2565 if (rs == INT_MIN && rt == -1) { | |
2566 set_register(rd_reg, 0); | |
2567 } else if (rt != 0) { | |
2568 set_register(rd_reg, rs % rt); | |
2569 } | |
2570 break; | |
2571 default: | |
2572 UNIMPLEMENTED_MIPS(); | |
2573 break; | |
2574 } | |
2575 } else { | |
2576 // Divide by zero and overflow was not checked in the | |
2577 // configuration step - div and divu do not raise exceptions. On | |
2578 // division by 0 the result will be UNPREDICTABLE. On overflow | |
2579 // (INT_MIN/-1), return INT_MIN which is what the hardware does. | |
2580 if (rs == INT_MIN && rt == -1) { | |
2581 set_register(LO, INT_MIN); | |
2582 set_register(HI, 0); | |
2583 } else if (rt != 0) { | |
2584 set_register(LO, rs / rt); | |
2585 set_register(HI, rs % rt); | |
2586 } | |
2587 } | 2284 } |
2588 break; | 2285 break; |
2589 case DIVU: | 2286 case DIVU: |
2590 if (IsMipsArchVariant(kMips32r6)) { | 2287 if (rt_u != 0) { |
2591 switch (instr->SaValue()) { | 2288 set_register(LO, rs_u / rt_u); |
2592 case DIV_OP: | 2289 set_register(HI, rs_u % rt_u); |
2593 if (rt_u != 0) { | |
2594 set_register(rd_reg, rs_u / rt_u); | |
2595 } | |
2596 break; | |
2597 case MOD_OP: | |
2598 if (rt_u != 0) { | |
2599 set_register(rd_reg, rs_u % rt_u); | |
2600 } | |
2601 break; | |
2602 default: | |
2603 UNIMPLEMENTED_MIPS(); | |
2604 break; | |
2605 } | |
2606 } else { | |
2607 if (rt_u != 0) { | |
2608 set_register(LO, rs_u / rt_u); | |
2609 set_register(HI, rs_u % rt_u); | |
2610 } | |
2611 } | 2290 } |
2612 break; | 2291 break; |
2613 // Break and trap instructions. | 2292 // Break and trap instructions. |
2614 case BREAK: | 2293 case BREAK: |
2615 case TGE: | 2294 case TGE: |
2616 case TGEU: | 2295 case TGEU: |
2617 case TLT: | 2296 case TLT: |
2618 case TLTU: | 2297 case TLTU: |
2619 case TEQ: | 2298 case TEQ: |
2620 case TNE: | 2299 case TNE: |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2682 void Simulator::DecodeTypeImmediate(Instruction* instr) { | 2361 void Simulator::DecodeTypeImmediate(Instruction* instr) { |
2683 // Instruction fields. | 2362 // Instruction fields. |
2684 Opcode op = instr->OpcodeFieldRaw(); | 2363 Opcode op = instr->OpcodeFieldRaw(); |
2685 int32_t rs = get_register(instr->RsValue()); | 2364 int32_t rs = get_register(instr->RsValue()); |
2686 uint32_t rs_u = static_cast<uint32_t>(rs); | 2365 uint32_t rs_u = static_cast<uint32_t>(rs); |
2687 int32_t rt_reg = instr->RtValue(); // Destination register. | 2366 int32_t rt_reg = instr->RtValue(); // Destination register. |
2688 int32_t rt = get_register(rt_reg); | 2367 int32_t rt = get_register(rt_reg); |
2689 int16_t imm16 = instr->Imm16Value(); | 2368 int16_t imm16 = instr->Imm16Value(); |
2690 | 2369 |
2691 int32_t ft_reg = instr->FtValue(); // Destination register. | 2370 int32_t ft_reg = instr->FtValue(); // Destination register. |
2692 int64_t ft; | |
2693 | 2371 |
2694 // Zero extended immediate. | 2372 // Zero extended immediate. |
2695 uint32_t oe_imm16 = 0xffff & imm16; | 2373 uint32_t oe_imm16 = 0xffff & imm16; |
2696 // Sign extended immediate. | 2374 // Sign extended immediate. |
2697 int32_t se_imm16 = imm16; | 2375 int32_t se_imm16 = imm16; |
2698 | 2376 |
2699 // Get current pc. | 2377 // Get current pc. |
2700 int32_t current_pc = get_pc(); | 2378 int32_t current_pc = get_pc(); |
2701 // Next pc. | 2379 // Next pc. |
2702 int32_t next_pc = bad_ra; | 2380 int32_t next_pc = bad_ra; |
(...skipping 24 matching lines...) Expand all Loading... |
2727 cc_value = test_fcsr_bit(fcsr_cc); | 2405 cc_value = test_fcsr_bit(fcsr_cc); |
2728 do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value; | 2406 do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value; |
2729 execute_branch_delay_instruction = true; | 2407 execute_branch_delay_instruction = true; |
2730 // Set next_pc. | 2408 // Set next_pc. |
2731 if (do_branch) { | 2409 if (do_branch) { |
2732 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; | 2410 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; |
2733 } else { | 2411 } else { |
2734 next_pc = current_pc + kBranchReturnOffset; | 2412 next_pc = current_pc + kBranchReturnOffset; |
2735 } | 2413 } |
2736 break; | 2414 break; |
2737 case BC1EQZ: | |
2738 ft = get_fpu_register(ft_reg); | |
2739 do_branch = (ft & 0x1) ? false : true; | |
2740 execute_branch_delay_instruction = true; | |
2741 // Set next_pc. | |
2742 if (do_branch) { | |
2743 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; | |
2744 } else { | |
2745 next_pc = current_pc + kBranchReturnOffset; | |
2746 } | |
2747 break; | |
2748 case BC1NEZ: | |
2749 ft = get_fpu_register(ft_reg); | |
2750 do_branch = (ft & 0x1) ? true : false; | |
2751 execute_branch_delay_instruction = true; | |
2752 // Set next_pc. | |
2753 if (do_branch) { | |
2754 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; | |
2755 } else { | |
2756 next_pc = current_pc + kBranchReturnOffset; | |
2757 } | |
2758 break; | |
2759 default: | 2415 default: |
2760 UNREACHABLE(); | 2416 UNREACHABLE(); |
2761 } | 2417 } |
2762 break; | 2418 break; |
2763 // ------------- REGIMM class. | 2419 // ------------- REGIMM class. |
2764 case REGIMM: | 2420 case REGIMM: |
2765 switch (instr->RtFieldRaw()) { | 2421 switch (instr->RtFieldRaw()) { |
2766 case BLTZ: | 2422 case BLTZ: |
2767 do_branch = (rs < 0); | 2423 do_branch = (rs < 0); |
2768 break; | 2424 break; |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2983 case SWL: | 2639 case SWL: |
2984 WriteW(addr, mem_value, instr); | 2640 WriteW(addr, mem_value, instr); |
2985 break; | 2641 break; |
2986 case SW: | 2642 case SW: |
2987 WriteW(addr, rt, instr); | 2643 WriteW(addr, rt, instr); |
2988 break; | 2644 break; |
2989 case SWR: | 2645 case SWR: |
2990 WriteW(addr, mem_value, instr); | 2646 WriteW(addr, mem_value, instr); |
2991 break; | 2647 break; |
2992 case LWC1: | 2648 case LWC1: |
2993 set_fpu_register_hi_word(ft_reg, 0); | 2649 set_fpu_register(ft_reg, alu_out); |
2994 set_fpu_register_word(ft_reg, alu_out); | |
2995 break; | 2650 break; |
2996 case LDC1: | 2651 case LDC1: |
2997 set_fpu_register_double(ft_reg, fp_out); | 2652 set_fpu_register_double(ft_reg, fp_out); |
2998 break; | 2653 break; |
2999 case SWC1: | 2654 case SWC1: |
3000 addr = rs + se_imm16; | 2655 addr = rs + se_imm16; |
3001 WriteW(addr, get_fpu_register_word(ft_reg), instr); | 2656 WriteW(addr, get_fpu_register(ft_reg), instr); |
3002 break; | 2657 break; |
3003 case SDC1: | 2658 case SDC1: |
3004 addr = rs + se_imm16; | 2659 addr = rs + se_imm16; |
3005 WriteD(addr, get_fpu_register_double(ft_reg), instr); | 2660 WriteD(addr, get_fpu_register_double(ft_reg), instr); |
3006 break; | 2661 break; |
3007 default: | 2662 default: |
3008 break; | 2663 break; |
3009 } | 2664 } |
3010 | 2665 |
3011 | 2666 |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3264 } | 2919 } |
3265 | 2920 |
3266 | 2921 |
3267 #undef UNSUPPORTED | 2922 #undef UNSUPPORTED |
3268 | 2923 |
3269 } } // namespace v8::internal | 2924 } } // namespace v8::internal |
3270 | 2925 |
3271 #endif // USE_SIMULATOR | 2926 #endif // USE_SIMULATOR |
3272 | 2927 |
3273 #endif // V8_TARGET_ARCH_MIPS | 2928 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |