| 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 #if V8_TARGET_ARCH_MIPS64 | 10 #if V8_TARGET_ARCH_MIPS64 |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 instr->SetInstructionBits(kNopInstr); | 139 instr->SetInstructionBits(kNopInstr); |
| 140 reinterpret_cast<Instr*>(msg_address)->SetInstructionBits(kNopInstr); | 140 reinterpret_cast<Instr*>(msg_address)->SetInstructionBits(kNopInstr); |
| 141 } | 141 } |
| 142 // TODO(yuyin): 2 -> 3? | 142 // TODO(yuyin): 2 -> 3? |
| 143 sim_->set_pc(sim_->get_pc() + 3 * Instruction::kInstructionSize); | 143 sim_->set_pc(sim_->get_pc() + 3 * Instruction::kInstructionSize); |
| 144 } | 144 } |
| 145 | 145 |
| 146 | 146 |
| 147 #else // GENERATED_CODE_COVERAGE | 147 #else // GENERATED_CODE_COVERAGE |
| 148 | 148 |
| 149 #define UNSUPPORTED() printf("Unsupported instruction.\n"); | 149 #define UNSUPPORTED() printf("Sim: Unsupported instruction.\n"); |
| 150 | 150 |
| 151 static void InitializeCoverage() {} | 151 static void InitializeCoverage() {} |
| 152 | 152 |
| 153 | 153 |
| 154 void MipsDebugger::Stop(Instruction* instr) { | 154 void MipsDebugger::Stop(Instruction* instr) { |
| 155 // Get the stop code. | 155 // Get the stop code. |
| 156 uint32_t code = instr->Bits(25, 6); | 156 uint32_t code = instr->Bits(25, 6); |
| 157 // Retrieve the encoded address, which comes just after this stop. | 157 // Retrieve the encoded address, which comes just after this stop. |
| 158 char* msg = *reinterpret_cast<char**>(sim_->get_pc() + | 158 char* msg = *reinterpret_cast<char**>(sim_->get_pc() + |
| 159 Instruction::kInstrSize); | 159 Instruction::kInstrSize); |
| (...skipping 3906 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4066 break; | 4066 break; |
| 4067 // Unimplemented opcodes raised an error in the configuration step before, | 4067 // Unimplemented opcodes raised an error in the configuration step before, |
| 4068 // so we can use the default here to set the destination register in common | 4068 // so we can use the default here to set the destination register in common |
| 4069 // cases. | 4069 // cases. |
| 4070 default: | 4070 default: |
| 4071 UNREACHABLE(); | 4071 UNREACHABLE(); |
| 4072 } | 4072 } |
| 4073 } | 4073 } |
| 4074 | 4074 |
| 4075 | 4075 |
| 4076 // Branch instructions common part. | 4076 // Type 2: instructions using a 16, 21 or 26 bits immediate. (e.g. beq, beqc). |
| 4077 #define BranchAndLinkHelper(do_branch) \ | |
| 4078 execute_branch_delay_instruction = true; \ | |
| 4079 if (do_branch) { \ | |
| 4080 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; \ | |
| 4081 set_register(31, current_pc + kBranchReturnOffset); \ | |
| 4082 } else { \ | |
| 4083 next_pc = current_pc + kBranchReturnOffset; \ | |
| 4084 } | |
| 4085 | |
| 4086 | |
| 4087 #define BranchHelper(do_branch) \ | |
| 4088 execute_branch_delay_instruction = true; \ | |
| 4089 if (do_branch) { \ | |
| 4090 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; \ | |
| 4091 } else { \ | |
| 4092 next_pc = current_pc + kBranchReturnOffset; \ | |
| 4093 } | |
| 4094 | |
| 4095 | |
| 4096 // Type 2: instructions using a 16 bytes immediate. (e.g. addi, beq). | |
| 4097 void Simulator::DecodeTypeImmediate(Instruction* instr) { | 4077 void Simulator::DecodeTypeImmediate(Instruction* instr) { |
| 4098 // Instruction fields. | 4078 // Instruction fields. |
| 4099 Opcode op = instr->OpcodeFieldRaw(); | 4079 Opcode op = instr->OpcodeFieldRaw(); |
| 4100 int32_t rs_reg = instr->RsValue(); | 4080 int32_t rs_reg = instr->RsValue(); |
| 4101 int64_t rs = get_register(instr->RsValue()); | 4081 int64_t rs = get_register(instr->RsValue()); |
| 4102 uint64_t rs_u = static_cast<uint64_t>(rs); | 4082 uint64_t rs_u = static_cast<uint64_t>(rs); |
| 4103 int32_t rt_reg = instr->RtValue(); // Destination register. | 4083 int32_t rt_reg = instr->RtValue(); // Destination register. |
| 4104 int64_t rt = get_register(rt_reg); | 4084 int64_t rt = get_register(rt_reg); |
| 4105 int16_t imm16 = instr->Imm16Value(); | 4085 int16_t imm16 = instr->Imm16Value(); |
| 4106 int32_t imm18 = instr->Imm18Value(); | 4086 int32_t imm18 = instr->Imm18Value(); |
| 4107 int32_t imm21 = instr->Imm21Value(); | |
| 4108 int32_t imm26 = instr->Imm26Value(); | |
| 4109 | 4087 |
| 4110 int32_t ft_reg = instr->FtValue(); // Destination register. | 4088 int32_t ft_reg = instr->FtValue(); // Destination register. |
| 4111 int64_t ft = get_fpu_register(ft_reg); | |
| 4112 | 4089 |
| 4113 // Zero extended immediate. | 4090 // Zero extended immediate. |
| 4114 uint64_t oe_imm16 = 0xffff & imm16; | 4091 uint64_t oe_imm16 = 0xffff & imm16; |
| 4115 // Sign extended immediate. | 4092 // Sign extended immediate. |
| 4116 int64_t se_imm16 = imm16; | 4093 int64_t se_imm16 = imm16; |
| 4117 int64_t se_imm18 = imm18 | ((imm18 & 0x20000) ? 0xfffffffffffc0000 : 0); | 4094 int64_t se_imm18 = imm18 | ((imm18 & 0x20000) ? 0xfffffffffffc0000 : 0); |
| 4118 int64_t se_imm26 = imm26 | ((imm26 & 0x2000000) ? 0xfffffffffc000000 : 0); | |
| 4119 | 4095 |
| 4120 // Get current pc. | |
| 4121 int64_t current_pc = get_pc(); | |
| 4122 // Next pc. | 4096 // Next pc. |
| 4123 int64_t next_pc = bad_ra; | 4097 int64_t next_pc = bad_ra; |
| 4124 | 4098 |
| 4125 // Used for conditional branch instructions. | 4099 // Used for conditional branch instructions. |
| 4126 bool execute_branch_delay_instruction = false; | 4100 bool execute_branch_delay_instruction = false; |
| 4127 | 4101 |
| 4128 // Used for arithmetic instructions. | 4102 // Used for arithmetic instructions. |
| 4129 int64_t alu_out = 0; | 4103 int64_t alu_out = 0; |
| 4130 | 4104 |
| 4131 // Used for memory instructions. | 4105 // Used for memory instructions. |
| 4132 int64_t addr = 0x0; | 4106 int64_t addr = 0x0; |
| 4133 // Alignment for 32-bit integers used in LWL, LWR, etc. | 4107 // Alignment for 32-bit integers used in LWL, LWR, etc. |
| 4134 const int kInt32AlignmentMask = sizeof(uint32_t) - 1; | 4108 const int kInt32AlignmentMask = sizeof(uint32_t) - 1; |
| 4135 | 4109 |
| 4136 // ---------- Configuration (and execution for REGIMM). | 4110 // Branch instructions common part. |
| 4111 auto BranchAndLinkHelper = [this, instr, &next_pc, |
| 4112 &execute_branch_delay_instruction]( |
| 4113 bool do_branch) { |
| 4114 execute_branch_delay_instruction = true; |
| 4115 int64_t current_pc = get_pc(); |
| 4116 if (do_branch) { |
| 4117 int16_t imm16 = instr->Imm16Value(); |
| 4118 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; |
| 4119 set_register(31, current_pc + 2 * Instruction::kInstrSize); |
| 4120 } else { |
| 4121 next_pc = current_pc + 2 * Instruction::kInstrSize; |
| 4122 } |
| 4123 }; |
| 4124 |
| 4125 auto BranchHelper = [this, instr, &next_pc, |
| 4126 &execute_branch_delay_instruction](bool do_branch) { |
| 4127 execute_branch_delay_instruction = true; |
| 4128 int64_t current_pc = get_pc(); |
| 4129 if (do_branch) { |
| 4130 int16_t imm16 = instr->Imm16Value(); |
| 4131 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; |
| 4132 } else { |
| 4133 next_pc = current_pc + 2 * Instruction::kInstrSize; |
| 4134 } |
| 4135 }; |
| 4136 |
| 4137 auto BranchAndLinkCompactHelper = [this, instr, &next_pc](bool do_branch, |
| 4138 int bits) { |
| 4139 int64_t current_pc = get_pc(); |
| 4140 CheckForbiddenSlot(current_pc); |
| 4141 if (do_branch) { |
| 4142 int32_t imm = instr->ImmValue(bits); |
| 4143 imm <<= 32 - bits; |
| 4144 imm >>= 32 - bits; |
| 4145 next_pc = current_pc + (imm << 2) + Instruction::kInstrSize; |
| 4146 set_register(31, current_pc + Instruction::kInstrSize); |
| 4147 } |
| 4148 }; |
| 4149 |
| 4150 auto BranchCompactHelper = [&next_pc, this, instr](bool do_branch, int bits) { |
| 4151 int64_t current_pc = get_pc(); |
| 4152 CheckForbiddenSlot(current_pc); |
| 4153 if (do_branch) { |
| 4154 int32_t imm = instr->ImmValue(bits); |
| 4155 imm <<= 32 - bits; |
| 4156 imm >>= 32 - bits; |
| 4157 next_pc = get_pc() + (imm << 2) + Instruction::kInstrSize; |
| 4158 } |
| 4159 }; |
| 4160 |
| 4137 switch (op) { | 4161 switch (op) { |
| 4138 // ------------- COP1. Coprocessor instructions. | 4162 // ------------- COP1. Coprocessor instructions. |
| 4139 case COP1: | 4163 case COP1: |
| 4140 switch (instr->RsFieldRaw()) { | 4164 switch (instr->RsFieldRaw()) { |
| 4141 case BC1: { // Branch on coprocessor condition. | 4165 case BC1: { // Branch on coprocessor condition. |
| 4142 uint32_t cc = instr->FBccValue(); | 4166 uint32_t cc = instr->FBccValue(); |
| 4143 uint32_t fcsr_cc = get_fcsr_condition_bit(cc); | 4167 uint32_t fcsr_cc = get_fcsr_condition_bit(cc); |
| 4144 uint32_t cc_value = test_fcsr_bit(fcsr_cc); | 4168 uint32_t cc_value = test_fcsr_bit(fcsr_cc); |
| 4145 bool do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value; | 4169 bool do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value; |
| 4146 execute_branch_delay_instruction = true; | 4170 BranchHelper(do_branch); |
| 4147 // Set next_pc. | |
| 4148 if (do_branch) { | |
| 4149 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; | |
| 4150 } else { | |
| 4151 next_pc = current_pc + kBranchReturnOffset; | |
| 4152 } | |
| 4153 break; | 4171 break; |
| 4154 } | 4172 } |
| 4155 case BC1EQZ: | 4173 case BC1EQZ: |
| 4156 execute_branch_delay_instruction = true; | 4174 BranchHelper(!(get_fpu_register(ft_reg) & 0x1)); |
| 4157 // Set next_pc. | |
| 4158 if (!(ft & 0x1)) { | |
| 4159 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; | |
| 4160 } else { | |
| 4161 next_pc = current_pc + kBranchReturnOffset; | |
| 4162 } | |
| 4163 break; | 4175 break; |
| 4164 case BC1NEZ: | 4176 case BC1NEZ: |
| 4165 execute_branch_delay_instruction = true; | 4177 BranchHelper(get_fpu_register(ft_reg) & 0x1); |
| 4166 // Set next_pc. | |
| 4167 if (ft & 0x1) { | |
| 4168 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; | |
| 4169 } else { | |
| 4170 next_pc = current_pc + kBranchReturnOffset; | |
| 4171 } | |
| 4172 break; | 4178 break; |
| 4173 default: | 4179 default: |
| 4174 UNREACHABLE(); | 4180 UNREACHABLE(); |
| 4175 } | 4181 } |
| 4176 break; | 4182 break; |
| 4177 // ------------- REGIMM class. | 4183 // ------------- REGIMM class. |
| 4178 case REGIMM: | 4184 case REGIMM: |
| 4179 switch (instr->RtFieldRaw()) { | 4185 switch (instr->RtFieldRaw()) { |
| 4180 case BLTZ: | 4186 case BLTZ: |
| 4181 BranchHelper(rs < 0); | 4187 BranchHelper(rs < 0); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 4201 break; // case REGIMM. | 4207 break; // case REGIMM. |
| 4202 // ------------- Branch instructions. | 4208 // ------------- Branch instructions. |
| 4203 // When comparing to zero, the encoding of rt field is always 0, so we don't | 4209 // When comparing to zero, the encoding of rt field is always 0, so we don't |
| 4204 // need to replace rt with zero. | 4210 // need to replace rt with zero. |
| 4205 case BEQ: | 4211 case BEQ: |
| 4206 BranchHelper(rs == rt); | 4212 BranchHelper(rs == rt); |
| 4207 break; | 4213 break; |
| 4208 case BNE: | 4214 case BNE: |
| 4209 BranchHelper(rs != rt); | 4215 BranchHelper(rs != rt); |
| 4210 break; | 4216 break; |
| 4211 case BLEZ: | 4217 case POP06: // BLEZALC, BGEZALC, BGEUC, BLEZ (pre-r6) |
| 4212 BranchHelper(rs <= 0); | 4218 if (kArchVariant == kMips64r6) { |
| 4219 if (rt_reg != 0) { |
| 4220 if (rs_reg == 0) { // BLEZALC |
| 4221 BranchAndLinkCompactHelper(rt <= 0, 16); |
| 4222 } else { |
| 4223 if (rs_reg == rt_reg) { // BGEZALC |
| 4224 BranchAndLinkCompactHelper(rt >= 0, 16); |
| 4225 } else { // BGEUC |
| 4226 BranchCompactHelper( |
| 4227 static_cast<uint64_t>(rs) >= static_cast<uint64_t>(rt), 16); |
| 4228 } |
| 4229 } |
| 4230 } else { // BLEZ |
| 4231 BranchHelper(rs <= 0); |
| 4232 } |
| 4233 } else { // BLEZ |
| 4234 BranchHelper(rs <= 0); |
| 4235 } |
| 4213 break; | 4236 break; |
| 4214 case BGTZ: | 4237 case POP07: // BGTZALC, BLTZALC, BLTUC, BGTZ (pre-r6) |
| 4215 BranchHelper(rs > 0); | 4238 if (kArchVariant == kMips64r6) { |
| 4239 if (rt_reg != 0) { |
| 4240 if (rs_reg == 0) { // BGTZALC |
| 4241 BranchAndLinkCompactHelper(rt > 0, 16); |
| 4242 } else { |
| 4243 if (rt_reg == rs_reg) { // BLTZALC |
| 4244 BranchAndLinkCompactHelper(rt < 0, 16); |
| 4245 } else { // BLTUC |
| 4246 BranchCompactHelper( |
| 4247 static_cast<uint64_t>(rs) < static_cast<uint64_t>(rt), 16); |
| 4248 } |
| 4249 } |
| 4250 } else { // BGTZ |
| 4251 BranchHelper(rs > 0); |
| 4252 } |
| 4253 } else { // BGTZ |
| 4254 BranchHelper(rs > 0); |
| 4255 } |
| 4216 break; | 4256 break; |
| 4217 case POP66: { | 4257 case POP26: // BLEZC, BGEZC, BGEC/BLEC / BLEZL (pre-r6) |
| 4218 if (rs_reg) { // BEQZC | 4258 if (kArchVariant == kMips64r6) { |
| 4219 int32_t se_imm21 = | 4259 if (rt_reg != 0) { |
| 4220 static_cast<int32_t>(imm21 << (kOpcodeBits + kRsBits)); | 4260 if (rs_reg == 0) { // BLEZC |
| 4221 se_imm21 = se_imm21 >> (kOpcodeBits + kRsBits); | 4261 BranchCompactHelper(rt <= 0, 16); |
| 4222 if (rs == 0) | 4262 } else { |
| 4223 next_pc = current_pc + 4 + (se_imm21 << 2); | 4263 if (rs_reg == rt_reg) { // BGEZC |
| 4224 else | 4264 BranchCompactHelper(rt >= 0, 16); |
| 4225 next_pc = current_pc + 4; | 4265 } else { // BGEC/BLEC |
| 4266 BranchCompactHelper(rs >= rt, 16); |
| 4267 } |
| 4268 } |
| 4269 } |
| 4270 } else { // BLEZL |
| 4271 BranchAndLinkHelper(rs <= 0); |
| 4272 } |
| 4273 break; |
| 4274 case POP27: // BGTZC, BLTZC, BLTC/BGTC / BGTZL (pre-r6) |
| 4275 if (kArchVariant == kMips64r6) { |
| 4276 if (rt_reg != 0) { |
| 4277 if (rs_reg == 0) { // BGTZC |
| 4278 BranchCompactHelper(rt > 0, 16); |
| 4279 } else { |
| 4280 if (rs_reg == rt_reg) { // BLTZC |
| 4281 BranchCompactHelper(rt < 0, 16); |
| 4282 } else { // BLTC/BGTC |
| 4283 BranchCompactHelper(rs < rt, 16); |
| 4284 } |
| 4285 } |
| 4286 } |
| 4287 } else { // BGTZL |
| 4288 BranchAndLinkHelper(rs > 0); |
| 4289 } |
| 4290 break; |
| 4291 case POP66: // BEQZC, JIC |
| 4292 if (rs_reg != 0) { // BEQZC |
| 4293 BranchCompactHelper(rs == 0, 21); |
| 4226 } else { // JIC | 4294 } else { // JIC |
| 4227 next_pc = rt + imm16; | 4295 next_pc = rt + imm16; |
| 4228 } | 4296 } |
| 4229 break; | 4297 break; |
| 4230 } | 4298 case POP76: // BNEZC, JIALC |
| 4231 case BC: { | 4299 if (rs_reg != 0) { // BNEZC |
| 4232 next_pc = current_pc + 4 + (se_imm26 << 2); | 4300 BranchCompactHelper(rs != 0, 21); |
| 4233 set_pc(next_pc); | 4301 } else { // JIALC |
| 4234 pc_modified_ = true; | 4302 int64_t current_pc = get_pc(); |
| 4303 set_register(31, current_pc + Instruction::kInstrSize); |
| 4304 next_pc = rt + imm16; |
| 4305 } |
| 4235 break; | 4306 break; |
| 4236 } | 4307 case BC: |
| 4237 case BALC: { | 4308 BranchCompactHelper(true, 26); |
| 4238 set_register(31, current_pc + 4); | |
| 4239 next_pc = current_pc + 4 + (se_imm26 << 2); | |
| 4240 set_pc(next_pc); | |
| 4241 pc_modified_ = true; | |
| 4242 break; | 4309 break; |
| 4243 } | 4310 case BALC: |
| 4244 // ------------- Arithmetic instructions. | 4311 BranchAndLinkCompactHelper(true, 26); |
| 4245 case ADDI: | 4312 break; |
| 4246 case DADDI: | 4313 case POP10: // BOVC, BEQZALC, BEQC / ADDI (pre-r6) |
| 4247 if (HaveSameSign(rs, se_imm16)) { | 4314 if (kArchVariant == kMips64r6) { |
| 4248 if (rs > 0) { | 4315 if (rs_reg >= rt_reg) { // BOVC |
| 4249 if (rs > Registers::kMaxValue - se_imm16) { | 4316 if (HaveSameSign(rs, rt)) { |
| 4250 SignalException(kIntegerOverflow); | 4317 if (rs > 0) { |
| 4318 BranchCompactHelper(rs > Registers::kMaxValue - rt, 16); |
| 4319 } else if (rs < 0) { |
| 4320 BranchCompactHelper(rs < Registers::kMinValue - rt, 16); |
| 4321 } |
| 4251 } | 4322 } |
| 4252 } else if (rs < 0) { | 4323 } else { |
| 4253 if (rs < Registers::kMinValue - se_imm16) { | 4324 if (rs_reg == 0) { // BEQZALC |
| 4254 SignalException(kIntegerUnderflow); | 4325 BranchAndLinkCompactHelper(rt == 0, 16); |
| 4326 } else { // BEQC |
| 4327 BranchCompactHelper(rt == rs, 16); |
| 4328 } |
| 4329 } |
| 4330 } else { // ADDI |
| 4331 if (HaveSameSign(rs, se_imm16)) { |
| 4332 if (rs > 0) { |
| 4333 if (rs <= Registers::kMaxValue - se_imm16) { |
| 4334 SignalException(kIntegerOverflow); |
| 4335 } |
| 4336 } else if (rs < 0) { |
| 4337 if (rs >= Registers::kMinValue - se_imm16) { |
| 4338 SignalException(kIntegerUnderflow); |
| 4339 } |
| 4340 } |
| 4341 } |
| 4342 SetResult(rt_reg, rs + se_imm16); |
| 4343 } |
| 4344 break; |
| 4345 case POP30: // BNVC, BNEZALC, BNEC / DADDI (pre-r6) |
| 4346 if (kArchVariant == kMips64r6) { |
| 4347 if (rs_reg >= rt_reg) { // BNVC |
| 4348 if (!HaveSameSign(rs, rt) || rs == 0 || rt == 0) { |
| 4349 BranchCompactHelper(true, 16); |
| 4350 } else { |
| 4351 if (rs > 0) { |
| 4352 BranchCompactHelper(rs <= Registers::kMaxValue - rt, 16); |
| 4353 } else if (rs < 0) { |
| 4354 BranchCompactHelper(rs >= Registers::kMinValue - rt, 16); |
| 4355 } |
| 4356 } |
| 4357 } else { |
| 4358 if (rs_reg == 0) { // BNEZALC |
| 4359 BranchAndLinkCompactHelper(rt != 0, 16); |
| 4360 } else { // BNEC |
| 4361 BranchCompactHelper(rt != rs, 16); |
| 4255 } | 4362 } |
| 4256 } | 4363 } |
| 4257 } | 4364 } |
| 4258 SetResult(rt_reg, rs + se_imm16); | |
| 4259 break; | 4365 break; |
| 4366 // ------------- Arithmetic instructions. |
| 4260 case ADDIU: { | 4367 case ADDIU: { |
| 4261 int32_t alu32_out = static_cast<int32_t>(rs + se_imm16); | 4368 int32_t alu32_out = static_cast<int32_t>(rs + se_imm16); |
| 4262 // Sign-extend result of 32bit operation into 64bit register. | 4369 // Sign-extend result of 32bit operation into 64bit register. |
| 4263 SetResult(rt_reg, static_cast<int64_t>(alu32_out)); | 4370 SetResult(rt_reg, static_cast<int64_t>(alu32_out)); |
| 4264 break; | 4371 break; |
| 4265 } | 4372 } |
| 4266 case DADDIU: | 4373 case DADDIU: |
| 4267 SetResult(rt_reg, rs + se_imm16); | 4374 SetResult(rt_reg, rs + se_imm16); |
| 4268 break; | 4375 break; |
| 4269 case SLTI: | 4376 case SLTI: |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4384 set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr)); | 4491 set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr)); |
| 4385 break; | 4492 break; |
| 4386 case SWC1: { | 4493 case SWC1: { |
| 4387 int32_t alu_out_32 = static_cast<int32_t>(get_fpu_register(ft_reg)); | 4494 int32_t alu_out_32 = static_cast<int32_t>(get_fpu_register(ft_reg)); |
| 4388 WriteW(rs + se_imm16, alu_out_32, instr); | 4495 WriteW(rs + se_imm16, alu_out_32, instr); |
| 4389 break; | 4496 break; |
| 4390 } | 4497 } |
| 4391 case SDC1: | 4498 case SDC1: |
| 4392 WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr); | 4499 WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr); |
| 4393 break; | 4500 break; |
| 4394 // ------------- JIALC and BNEZC instructions. | |
| 4395 case POP76: { | |
| 4396 // Next pc. | |
| 4397 next_pc = rt + se_imm16; | |
| 4398 // The instruction after the jump is NOT executed. | |
| 4399 uint16_t pc_increment = Instruction::kInstrSize; | |
| 4400 if (instr->IsLinkingInstruction()) { | |
| 4401 set_register(31, current_pc + pc_increment); | |
| 4402 } | |
| 4403 set_pc(next_pc); | |
| 4404 pc_modified_ = true; | |
| 4405 break; | |
| 4406 } | |
| 4407 // ------------- PC-Relative instructions. | 4501 // ------------- PC-Relative instructions. |
| 4408 case PCREL: { | 4502 case PCREL: { |
| 4409 // rt field: checking 5-bits. | 4503 // rt field: checking 5-bits. |
| 4504 int32_t imm21 = instr->Imm21Value(); |
| 4505 int64_t current_pc = get_pc(); |
| 4410 uint8_t rt = (imm21 >> kImm16Bits); | 4506 uint8_t rt = (imm21 >> kImm16Bits); |
| 4411 switch (rt) { | 4507 switch (rt) { |
| 4412 case ALUIPC: | 4508 case ALUIPC: |
| 4413 addr = current_pc + (se_imm16 << 16); | 4509 addr = current_pc + (se_imm16 << 16); |
| 4414 alu_out = static_cast<int64_t>(~0x0FFFF) & addr; | 4510 alu_out = static_cast<int64_t>(~0x0FFFF) & addr; |
| 4415 break; | 4511 break; |
| 4416 case AUIPC: | 4512 case AUIPC: |
| 4417 alu_out = current_pc + (se_imm16 << 16); | 4513 alu_out = current_pc + (se_imm16 << 16); |
| 4418 break; | 4514 break; |
| 4419 default: { | 4515 default: { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4469 } | 4565 } |
| 4470 default: | 4566 default: |
| 4471 UNREACHABLE(); | 4567 UNREACHABLE(); |
| 4472 } | 4568 } |
| 4473 | 4569 |
| 4474 if (execute_branch_delay_instruction) { | 4570 if (execute_branch_delay_instruction) { |
| 4475 // Execute branch delay slot | 4571 // Execute branch delay slot |
| 4476 // We don't check for end_sim_pc. First it should not be met as the current | 4572 // We don't check for end_sim_pc. First it should not be met as the current |
| 4477 // pc is valid. Secondly a jump should always execute its branch delay slot. | 4573 // pc is valid. Secondly a jump should always execute its branch delay slot. |
| 4478 Instruction* branch_delay_instr = | 4574 Instruction* branch_delay_instr = |
| 4479 reinterpret_cast<Instruction*>(current_pc+Instruction::kInstrSize); | 4575 reinterpret_cast<Instruction*>(get_pc() + Instruction::kInstrSize); |
| 4480 BranchDelayInstructionDecode(branch_delay_instr); | 4576 BranchDelayInstructionDecode(branch_delay_instr); |
| 4481 } | 4577 } |
| 4482 | 4578 |
| 4483 // If needed update pc after the branch delay execution. | 4579 // If needed update pc after the branch delay execution. |
| 4484 if (next_pc != bad_ra) { | 4580 if (next_pc != bad_ra) { |
| 4485 set_pc(next_pc); | 4581 set_pc(next_pc); |
| 4486 } | 4582 } |
| 4487 } | 4583 } |
| 4488 | 4584 |
| 4489 #undef BranchHelper | |
| 4490 #undef BranchAndLinkHelper | |
| 4491 | |
| 4492 | 4585 |
| 4493 // Type 3: instructions using a 26 bytes immediate. (e.g. j, jal). | 4586 // Type 3: instructions using a 26 bytes immediate. (e.g. j, jal). |
| 4494 void Simulator::DecodeTypeJump(Instruction* instr) { | 4587 void Simulator::DecodeTypeJump(Instruction* instr) { |
| 4495 // Get current pc. | 4588 // Get current pc. |
| 4496 int64_t current_pc = get_pc(); | 4589 int64_t current_pc = get_pc(); |
| 4497 // Get unchanged bits of pc. | 4590 // Get unchanged bits of pc. |
| 4498 int64_t pc_high_bits = current_pc & 0xfffffffff0000000; | 4591 int64_t pc_high_bits = current_pc & 0xfffffffff0000000; |
| 4499 // Next pc. | 4592 // Next pc. |
| 4500 int64_t next_pc = pc_high_bits | (instr->Imm26Value() << 2); | 4593 int64_t next_pc = pc_high_bits | (instr->Imm26Value() << 2); |
| 4501 | 4594 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4572 icount_++; | 4665 icount_++; |
| 4573 InstructionDecode(instr); | 4666 InstructionDecode(instr); |
| 4574 program_counter = get_pc(); | 4667 program_counter = get_pc(); |
| 4575 } | 4668 } |
| 4576 } else { | 4669 } else { |
| 4577 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when | 4670 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when |
| 4578 // we reach the particular instuction count. | 4671 // we reach the particular instuction count. |
| 4579 while (program_counter != end_sim_pc) { | 4672 while (program_counter != end_sim_pc) { |
| 4580 Instruction* instr = reinterpret_cast<Instruction*>(program_counter); | 4673 Instruction* instr = reinterpret_cast<Instruction*>(program_counter); |
| 4581 icount_++; | 4674 icount_++; |
| 4582 if (icount_ == static_cast<int64_t>(::v8::internal::FLAG_stop_sim_at)) { | 4675 if (icount_ == static_cast<uint64_t>(::v8::internal::FLAG_stop_sim_at)) { |
| 4583 MipsDebugger dbg(this); | 4676 MipsDebugger dbg(this); |
| 4584 dbg.Debug(); | 4677 dbg.Debug(); |
| 4585 } else { | 4678 } else { |
| 4586 InstructionDecode(instr); | 4679 InstructionDecode(instr); |
| 4587 } | 4680 } |
| 4588 program_counter = get_pc(); | 4681 program_counter = get_pc(); |
| 4589 } | 4682 } |
| 4590 } | 4683 } |
| 4591 } | 4684 } |
| 4592 | 4685 |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4754 } | 4847 } |
| 4755 | 4848 |
| 4756 | 4849 |
| 4757 #undef UNSUPPORTED | 4850 #undef UNSUPPORTED |
| 4758 } // namespace internal | 4851 } // namespace internal |
| 4759 } // namespace v8 | 4852 } // namespace v8 |
| 4760 | 4853 |
| 4761 #endif // USE_SIMULATOR | 4854 #endif // USE_SIMULATOR |
| 4762 | 4855 |
| 4763 #endif // V8_TARGET_ARCH_MIPS64 | 4856 #endif // V8_TARGET_ARCH_MIPS64 |
| OLD | NEW |