| 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 |