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