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 |