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