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"); |
balazs.kilvady
2015/12/18 19:18:05
I just forgot to remove it from the final CL but I
ivica.bogosavljevic
2015/12/22 10:22:40
Ok, I'll remove Sim here as well as for MIPS32
balazs.kilvady
2015/12/22 11:01:56
Please do not remove it. I think it is fine to mak
ivica.bogosavljevic
2015/12/22 12:23:41
Acknowledged.
| |
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 3884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4044 break; | 4044 break; |
4045 // Unimplemented opcodes raised an error in the configuration step before, | 4045 // Unimplemented opcodes raised an error in the configuration step before, |
4046 // so we can use the default here to set the destination register in common | 4046 // so we can use the default here to set the destination register in common |
4047 // cases. | 4047 // cases. |
4048 default: | 4048 default: |
4049 UNREACHABLE(); | 4049 UNREACHABLE(); |
4050 } | 4050 } |
4051 } | 4051 } |
4052 | 4052 |
4053 | 4053 |
4054 // Branch instructions common part. | 4054 // Type 2: instructions using a 16, 21 or 26 bits immediate. (e.g. beq, beqc). |
4055 #define BranchAndLinkHelper(do_branch) \ | |
4056 execute_branch_delay_instruction = true; \ | |
4057 if (do_branch) { \ | |
4058 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; \ | |
4059 set_register(31, current_pc + kBranchReturnOffset); \ | |
4060 } else { \ | |
4061 next_pc = current_pc + kBranchReturnOffset; \ | |
4062 } | |
4063 | |
4064 | |
4065 #define BranchHelper(do_branch) \ | |
4066 execute_branch_delay_instruction = true; \ | |
4067 if (do_branch) { \ | |
4068 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; \ | |
4069 } else { \ | |
4070 next_pc = current_pc + kBranchReturnOffset; \ | |
4071 } | |
4072 | |
4073 | |
4074 // Type 2: instructions using a 16 bytes immediate. (e.g. addi, beq). | |
4075 void Simulator::DecodeTypeImmediate(Instruction* instr) { | 4055 void Simulator::DecodeTypeImmediate(Instruction* instr) { |
4076 // Instruction fields. | 4056 // Instruction fields. |
4077 Opcode op = instr->OpcodeFieldRaw(); | 4057 Opcode op = instr->OpcodeFieldRaw(); |
4078 int32_t rs_reg = instr->RsValue(); | 4058 int32_t rs_reg = instr->RsValue(); |
4079 int64_t rs = get_register(instr->RsValue()); | 4059 int64_t rs = get_register(instr->RsValue()); |
4080 uint64_t rs_u = static_cast<uint64_t>(rs); | 4060 uint64_t rs_u = static_cast<uint64_t>(rs); |
4081 int32_t rt_reg = instr->RtValue(); // Destination register. | 4061 int32_t rt_reg = instr->RtValue(); // Destination register. |
4082 int64_t rt = get_register(rt_reg); | 4062 int64_t rt = get_register(rt_reg); |
4083 int16_t imm16 = instr->Imm16Value(); | 4063 int16_t imm16 = instr->Imm16Value(); |
4084 int32_t imm18 = instr->Imm18Value(); | 4064 int32_t imm18 = instr->Imm18Value(); |
4085 int32_t imm21 = instr->Imm21Value(); | |
4086 int32_t imm26 = instr->Imm26Value(); | |
4087 | 4065 |
4088 int32_t ft_reg = instr->FtValue(); // Destination register. | 4066 int32_t ft_reg = instr->FtValue(); // Destination register. |
4089 int64_t ft = get_fpu_register(ft_reg); | |
4090 | 4067 |
4091 // Zero extended immediate. | 4068 // Zero extended immediate. |
4092 uint64_t oe_imm16 = 0xffff & imm16; | 4069 uint64_t oe_imm16 = 0xffff & imm16; |
4093 // Sign extended immediate. | 4070 // Sign extended immediate. |
4094 int64_t se_imm16 = imm16; | 4071 int64_t se_imm16 = imm16; |
4095 int64_t se_imm18 = imm18 | ((imm18 & 0x20000) ? 0xfffffffffffc0000 : 0); | 4072 int64_t se_imm18 = imm18 | ((imm18 & 0x20000) ? 0xfffffffffffc0000 : 0); |
4096 int64_t se_imm26 = imm26 | ((imm26 & 0x2000000) ? 0xfffffffffc000000 : 0); | |
4097 | 4073 |
4098 // Get current pc. | |
4099 int64_t current_pc = get_pc(); | |
4100 // Next pc. | 4074 // Next pc. |
4101 int64_t next_pc = bad_ra; | 4075 int64_t next_pc = bad_ra; |
4102 | 4076 |
4103 // Used for conditional branch instructions. | 4077 // Used for conditional branch instructions. |
4104 bool execute_branch_delay_instruction = false; | 4078 bool execute_branch_delay_instruction = false; |
4105 | 4079 |
4106 // Used for arithmetic instructions. | 4080 // Used for arithmetic instructions. |
4107 int64_t alu_out = 0; | 4081 int64_t alu_out = 0; |
4108 | 4082 |
4109 // Used for memory instructions. | 4083 // Used for memory instructions. |
4110 int64_t addr = 0x0; | 4084 int64_t addr = 0x0; |
4111 // Alignment for 32-bit integers used in LWL, LWR, etc. | 4085 // Alignment for 32-bit integers used in LWL, LWR, etc. |
4112 const int kInt32AlignmentMask = sizeof(uint32_t) - 1; | 4086 const int kInt32AlignmentMask = sizeof(uint32_t) - 1; |
4113 | 4087 |
4114 // ---------- Configuration (and execution for REGIMM). | 4088 // Branch instructions common part. |
4089 auto BranchAndLinkHelper = [this, instr, &next_pc, | |
4090 &execute_branch_delay_instruction]( | |
4091 bool do_branch) { | |
4092 execute_branch_delay_instruction = true; | |
4093 int64_t current_pc = get_pc(); | |
4094 if (do_branch) { | |
4095 int16_t imm16 = instr->Imm16Value(); | |
4096 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; | |
4097 set_register(31, current_pc + 2 * Instruction::kInstrSize); | |
4098 } else { | |
4099 next_pc = current_pc + 2 * Instruction::kInstrSize; | |
4100 } | |
4101 }; | |
4102 | |
4103 auto BranchHelper = [this, instr, &next_pc, | |
4104 &execute_branch_delay_instruction](bool do_branch) { | |
4105 execute_branch_delay_instruction = true; | |
4106 int64_t current_pc = get_pc(); | |
4107 if (do_branch) { | |
4108 int16_t imm16 = instr->Imm16Value(); | |
4109 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; | |
4110 } else { | |
4111 next_pc = current_pc + 2 * Instruction::kInstrSize; | |
4112 } | |
4113 }; | |
4114 | |
4115 auto BranchAndLinkCompactHelper = [this, instr, &next_pc](bool do_branch, | |
4116 int bits) { | |
4117 int64_t current_pc = get_pc(); | |
4118 CheckForbiddenSlot(current_pc); | |
4119 if (do_branch) { | |
4120 int32_t imm = instr->ImmValue(bits); | |
4121 imm <<= 32 - bits; | |
4122 imm >>= 32 - bits; | |
4123 next_pc = current_pc + (imm << 2) + Instruction::kInstrSize; | |
4124 set_register(31, current_pc + Instruction::kInstrSize); | |
4125 } | |
4126 }; | |
4127 | |
4128 auto BranchCompactHelper = [&next_pc, this, instr](bool do_branch, int bits) { | |
4129 int64_t current_pc = get_pc(); | |
4130 CheckForbiddenSlot(current_pc); | |
4131 if (do_branch) { | |
4132 int32_t imm = instr->ImmValue(bits); | |
4133 imm <<= 32 - bits; | |
4134 imm >>= 32 - bits; | |
4135 next_pc = get_pc() + (imm << 2) + Instruction::kInstrSize; | |
4136 } | |
4137 }; | |
4115 switch (op) { | 4138 switch (op) { |
4116 // ------------- COP1. Coprocessor instructions. | 4139 // ------------- COP1. Coprocessor instructions. |
4117 case COP1: | 4140 case COP1: |
4118 switch (instr->RsFieldRaw()) { | 4141 switch (instr->RsFieldRaw()) { |
4119 case BC1: { // Branch on coprocessor condition. | 4142 case BC1: { // Branch on coprocessor condition. |
4120 uint32_t cc = instr->FBccValue(); | 4143 uint32_t cc = instr->FBccValue(); |
4121 uint32_t fcsr_cc = get_fcsr_condition_bit(cc); | 4144 uint32_t fcsr_cc = get_fcsr_condition_bit(cc); |
4122 uint32_t cc_value = test_fcsr_bit(fcsr_cc); | 4145 uint32_t cc_value = test_fcsr_bit(fcsr_cc); |
4123 bool do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value; | 4146 bool do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value; |
4124 execute_branch_delay_instruction = true; | 4147 BranchHelper(do_branch); |
4125 // Set next_pc. | |
4126 if (do_branch) { | |
4127 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; | |
4128 } else { | |
4129 next_pc = current_pc + kBranchReturnOffset; | |
4130 } | |
4131 break; | 4148 break; |
4132 } | 4149 } |
4133 case BC1EQZ: | 4150 case BC1EQZ: |
4134 execute_branch_delay_instruction = true; | 4151 BranchHelper(!(get_fpu_register(ft_reg) & 0x1)); |
4135 // Set next_pc. | |
4136 if (!(ft & 0x1)) { | |
4137 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; | |
4138 } else { | |
4139 next_pc = current_pc + kBranchReturnOffset; | |
4140 } | |
4141 break; | 4152 break; |
4142 case BC1NEZ: | 4153 case BC1NEZ: |
4143 execute_branch_delay_instruction = true; | 4154 BranchHelper(get_fpu_register(ft_reg) & 0x1); |
4144 // Set next_pc. | |
4145 if (ft & 0x1) { | |
4146 next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; | |
4147 } else { | |
4148 next_pc = current_pc + kBranchReturnOffset; | |
4149 } | |
4150 break; | 4155 break; |
4151 default: | 4156 default: |
4152 UNREACHABLE(); | 4157 UNREACHABLE(); |
4153 } | 4158 } |
4154 break; | 4159 break; |
4155 // ------------- REGIMM class. | 4160 // ------------- REGIMM class. |
4156 case REGIMM: | 4161 case REGIMM: |
4157 switch (instr->RtFieldRaw()) { | 4162 switch (instr->RtFieldRaw()) { |
4158 case BLTZ: | 4163 case BLTZ: |
4159 BranchHelper(rs < 0); | 4164 BranchHelper(rs < 0); |
(...skipping 19 matching lines...) Expand all Loading... | |
4179 break; // case REGIMM. | 4184 break; // case REGIMM. |
4180 // ------------- Branch instructions. | 4185 // ------------- Branch instructions. |
4181 // When comparing to zero, the encoding of rt field is always 0, so we don't | 4186 // When comparing to zero, the encoding of rt field is always 0, so we don't |
4182 // need to replace rt with zero. | 4187 // need to replace rt with zero. |
4183 case BEQ: | 4188 case BEQ: |
4184 BranchHelper(rs == rt); | 4189 BranchHelper(rs == rt); |
4185 break; | 4190 break; |
4186 case BNE: | 4191 case BNE: |
4187 BranchHelper(rs != rt); | 4192 BranchHelper(rs != rt); |
4188 break; | 4193 break; |
4189 case BLEZ: | 4194 case POP06: // BLEZALC, BGEZALC, BGEUC, BLEZ (pre-r6) |
4190 BranchHelper(rs <= 0); | 4195 if (kArchVariant == kMips64r6) { |
4196 if (rt_reg != 0) { | |
4197 if (rs_reg == 0) { // BLEZALC | |
4198 BranchAndLinkCompactHelper(rt <= 0, 16); | |
4199 } else { | |
4200 if (rs_reg == rt_reg) { // BGEZALC | |
4201 BranchAndLinkCompactHelper(rt >= 0, 16); | |
4202 } else { // BGEUC | |
4203 BranchCompactHelper( | |
4204 static_cast<uint64_t>(rs) >= static_cast<uint64_t>(rt), 16); | |
4205 } | |
4206 } | |
4207 } else { // BLEZ | |
4208 BranchHelper(rs <= 0); | |
4209 } | |
4210 } else { // BLEZ | |
4211 BranchHelper(rs <= 0); | |
4212 } | |
4191 break; | 4213 break; |
4192 case BGTZ: | 4214 case POP07: // BGTZALC, BLTZALC, BLTUC, BGTZ (pre-r6) |
4193 BranchHelper(rs > 0); | 4215 if (kArchVariant == kMips64r6) { |
4216 if (rt_reg != 0) { | |
4217 if (rs_reg == 0) { // BGTZALC | |
4218 BranchAndLinkCompactHelper(rt > 0, 16); | |
4219 } else { | |
4220 if (rt_reg == rs_reg) { // BLTZALC | |
4221 BranchAndLinkCompactHelper(rt < 0, 16); | |
4222 } else { // BLTUC | |
4223 BranchCompactHelper( | |
4224 static_cast<uint64_t>(rs) < static_cast<uint64_t>(rt), 16); | |
4225 } | |
4226 } | |
4227 } else { // BGTZ | |
4228 BranchHelper(rs > 0); | |
4229 } | |
4230 } else { // BGTZ | |
4231 BranchHelper(rs > 0); | |
4232 } | |
4194 break; | 4233 break; |
4195 case POP66: { | 4234 case POP26: // BLEZC, BGEZC, BGEC/BLEC / BLEZL (pre-r6) |
4196 if (rs_reg) { // BEQZC | 4235 if (kArchVariant == kMips64r6) { |
4197 int32_t se_imm21 = | 4236 if (rt_reg != 0) { |
4198 static_cast<int32_t>(imm21 << (kOpcodeBits + kRsBits)); | 4237 if (rs_reg == 0) { // BLEZC |
4199 se_imm21 = se_imm21 >> (kOpcodeBits + kRsBits); | 4238 BranchCompactHelper(rt <= 0, 16); |
4200 if (rs == 0) | 4239 } else { |
4201 next_pc = current_pc + 4 + (se_imm21 << 2); | 4240 if (rs_reg == rt_reg) { // BGEZC |
4202 else | 4241 BranchCompactHelper(rt >= 0, 16); |
4203 next_pc = current_pc + 4; | 4242 } else { // BGEC/BLEC |
4243 BranchCompactHelper(rs >= rt, 16); | |
4244 } | |
4245 } | |
4246 } | |
4247 } else { // BLEZL | |
4248 BranchAndLinkHelper(rs <= 0); | |
4249 } | |
4250 break; | |
4251 case POP27: // BGTZC, BLTZC, BLTC/BGTC / BGTZL (pre-r6) | |
4252 if (kArchVariant == kMips64r6) { | |
4253 if (rt_reg != 0) { | |
4254 if (rs_reg == 0) { // BGTZC | |
4255 BranchCompactHelper(rt > 0, 16); | |
4256 } else { | |
4257 if (rs_reg == rt_reg) { // BLTZC | |
4258 BranchCompactHelper(rt < 0, 16); | |
4259 } else { // BLTC/BGTC | |
4260 BranchCompactHelper(rs < rt, 16); | |
4261 } | |
4262 } | |
4263 } | |
4264 } else { // BGTZL | |
4265 BranchAndLinkHelper(rs > 0); | |
4266 } | |
4267 break; | |
4268 case POP66: // BEQZC, JIC | |
4269 if (rs_reg != 0) { // BEQZC | |
4270 BranchCompactHelper(rs == 0, 21); | |
4204 } else { // JIC | 4271 } else { // JIC |
4272 CheckForbiddenSlot(get_pc()); | |
4205 next_pc = rt + imm16; | 4273 next_pc = rt + imm16; |
4206 } | 4274 } |
4207 break; | 4275 break; |
4208 } | 4276 case POP76: // BNEZC, JIALC |
4209 case BC: { | 4277 if (rs_reg != 0) { // BNEZC |
4210 next_pc = current_pc + 4 + (se_imm26 << 2); | 4278 BranchCompactHelper(rs != 0, 21); |
4211 set_pc(next_pc); | 4279 } else { // JIALC |
4212 pc_modified_ = true; | 4280 int64_t current_pc = get_pc(); |
4281 CheckForbiddenSlot(current_pc); | |
4282 set_register(31, current_pc + Instruction::kInstrSize); | |
4283 next_pc = rt + imm16; | |
4284 } | |
4213 break; | 4285 break; |
4214 } | 4286 case BC: |
4215 case BALC: { | 4287 BranchCompactHelper(true, 26); |
4216 set_register(31, current_pc + 4); | |
4217 next_pc = current_pc + 4 + (se_imm26 << 2); | |
4218 set_pc(next_pc); | |
4219 pc_modified_ = true; | |
4220 break; | 4288 break; |
4221 } | 4289 case BALC: |
4222 // ------------- Arithmetic instructions. | 4290 BranchAndLinkCompactHelper(true, 26); |
4223 case ADDI: | 4291 break; |
4224 case DADDI: | 4292 case POP10: // BOVC, BEQZALC, BEQC / ADDI (pre-r6) |
4225 if (HaveSameSign(rs, se_imm16)) { | 4293 if (kArchVariant == kMips64r6) { |
4226 if (rs > 0) { | 4294 if (rs_reg >= rt_reg) { // BOVC |
4227 if (rs > Registers::kMaxValue - se_imm16) { | 4295 if (HaveSameSign(rs, rt)) { |
4228 SignalException(kIntegerOverflow); | 4296 if (rs > 0) { |
4297 BranchCompactHelper(rs > Registers::kMaxValue - rt, 16); | |
4298 } else if (rs < 0) { | |
4299 BranchCompactHelper(rs < Registers::kMinValue - rt, 16); | |
4300 } | |
4229 } | 4301 } |
4230 } else if (rs < 0) { | 4302 } else { |
4231 if (rs < Registers::kMinValue - se_imm16) { | 4303 if (rs_reg == 0) { // BEQZALC |
4232 SignalException(kIntegerUnderflow); | 4304 BranchAndLinkCompactHelper(rt == 0, 16); |
4305 } else { // BEQC | |
4306 BranchCompactHelper(rt == rs, 16); | |
4307 } | |
4308 } | |
4309 } else { // ADDI | |
4310 if (HaveSameSign(rs, se_imm16)) { | |
4311 if (rs > 0) { | |
4312 if (rs <= Registers::kMaxValue - se_imm16) { | |
4313 SignalException(kIntegerOverflow); | |
4314 } | |
4315 } else if (rs < 0) { | |
4316 if (rs >= Registers::kMinValue - se_imm16) { | |
4317 SignalException(kIntegerUnderflow); | |
4318 } | |
4319 } | |
4320 } | |
4321 SetResult(rt_reg, rs + se_imm16); | |
4322 } | |
4323 break; | |
4324 case POP30: // BNVC, BNEZALC, BNEC / DADDI (pre-r6) | |
4325 if (kArchVariant == kMips64r6) { | |
4326 if (rs_reg >= rt_reg) { // BNVC | |
4327 if (!HaveSameSign(rs, rt) || rs == 0 || rt == 0) { | |
4328 BranchCompactHelper(true, 16); | |
4329 } else { | |
4330 if (rs > 0) { | |
4331 BranchCompactHelper(rs <= Registers::kMaxValue - rt, 16); | |
4332 } else if (rs < 0) { | |
4333 BranchCompactHelper(rs >= Registers::kMinValue - rt, 16); | |
4334 } | |
4335 } | |
4336 } else { | |
4337 if (rs_reg == 0) { // BNEZALC | |
4338 BranchAndLinkCompactHelper(rt != 0, 16); | |
4339 } else { // BNEC | |
4340 BranchCompactHelper(rt != rs, 16); | |
4233 } | 4341 } |
4234 } | 4342 } |
4235 } | 4343 } |
4236 SetResult(rt_reg, rs + se_imm16); | |
4237 break; | 4344 break; |
4345 // ------------- Arithmetic instructions. | |
4238 case ADDIU: { | 4346 case ADDIU: { |
4239 int32_t alu32_out = static_cast<int32_t>(rs + se_imm16); | 4347 int32_t alu32_out = static_cast<int32_t>(rs + se_imm16); |
4240 // Sign-extend result of 32bit operation into 64bit register. | 4348 // Sign-extend result of 32bit operation into 64bit register. |
4241 SetResult(rt_reg, static_cast<int64_t>(alu32_out)); | 4349 SetResult(rt_reg, static_cast<int64_t>(alu32_out)); |
4242 break; | 4350 break; |
4243 } | 4351 } |
4244 case DADDIU: | 4352 case DADDIU: |
4245 SetResult(rt_reg, rs + se_imm16); | 4353 SetResult(rt_reg, rs + se_imm16); |
4246 break; | 4354 break; |
4247 case SLTI: | 4355 case SLTI: |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4362 set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr)); | 4470 set_fpu_register_double(ft_reg, ReadD(rs + se_imm16, instr)); |
4363 break; | 4471 break; |
4364 case SWC1: { | 4472 case SWC1: { |
4365 int32_t alu_out_32 = static_cast<int32_t>(get_fpu_register(ft_reg)); | 4473 int32_t alu_out_32 = static_cast<int32_t>(get_fpu_register(ft_reg)); |
4366 WriteW(rs + se_imm16, alu_out_32, instr); | 4474 WriteW(rs + se_imm16, alu_out_32, instr); |
4367 break; | 4475 break; |
4368 } | 4476 } |
4369 case SDC1: | 4477 case SDC1: |
4370 WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr); | 4478 WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr); |
4371 break; | 4479 break; |
4372 // ------------- JIALC and BNEZC instructions. | |
4373 case POP76: { | |
4374 // Next pc. | |
4375 next_pc = rt + se_imm16; | |
4376 // The instruction after the jump is NOT executed. | |
4377 uint16_t pc_increment = Instruction::kInstrSize; | |
4378 if (instr->IsLinkingInstruction()) { | |
4379 set_register(31, current_pc + pc_increment); | |
4380 } | |
4381 set_pc(next_pc); | |
4382 pc_modified_ = true; | |
4383 break; | |
4384 } | |
4385 // ------------- PC-Relative instructions. | 4480 // ------------- PC-Relative instructions. |
4386 case PCREL: { | 4481 case PCREL: { |
4387 // rt field: checking 5-bits. | 4482 // rt field: checking 5-bits. |
4483 int32_t imm21 = instr->Imm21Value(); | |
4484 int64_t current_pc = get_pc(); | |
4388 uint8_t rt = (imm21 >> kImm16Bits); | 4485 uint8_t rt = (imm21 >> kImm16Bits); |
4389 switch (rt) { | 4486 switch (rt) { |
4390 case ALUIPC: | 4487 case ALUIPC: |
4391 addr = current_pc + (se_imm16 << 16); | 4488 addr = current_pc + (se_imm16 << 16); |
4392 alu_out = static_cast<int64_t>(~0x0FFFF) & addr; | 4489 alu_out = static_cast<int64_t>(~0x0FFFF) & addr; |
4393 break; | 4490 break; |
4394 case AUIPC: | 4491 case AUIPC: |
4395 alu_out = current_pc + (se_imm16 << 16); | 4492 alu_out = current_pc + (se_imm16 << 16); |
4396 break; | 4493 break; |
4397 default: { | 4494 default: { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4447 } | 4544 } |
4448 default: | 4545 default: |
4449 UNREACHABLE(); | 4546 UNREACHABLE(); |
4450 } | 4547 } |
4451 | 4548 |
4452 if (execute_branch_delay_instruction) { | 4549 if (execute_branch_delay_instruction) { |
4453 // Execute branch delay slot | 4550 // Execute branch delay slot |
4454 // We don't check for end_sim_pc. First it should not be met as the current | 4551 // We don't check for end_sim_pc. First it should not be met as the current |
4455 // pc is valid. Secondly a jump should always execute its branch delay slot. | 4552 // pc is valid. Secondly a jump should always execute its branch delay slot. |
4456 Instruction* branch_delay_instr = | 4553 Instruction* branch_delay_instr = |
4457 reinterpret_cast<Instruction*>(current_pc+Instruction::kInstrSize); | 4554 reinterpret_cast<Instruction*>(get_pc() + Instruction::kInstrSize); |
4458 BranchDelayInstructionDecode(branch_delay_instr); | 4555 BranchDelayInstructionDecode(branch_delay_instr); |
4459 } | 4556 } |
4460 | 4557 |
4461 // If needed update pc after the branch delay execution. | 4558 // If needed update pc after the branch delay execution. |
4462 if (next_pc != bad_ra) { | 4559 if (next_pc != bad_ra) { |
4463 set_pc(next_pc); | 4560 set_pc(next_pc); |
4464 } | 4561 } |
4465 } | 4562 } |
4466 | 4563 |
4467 #undef BranchHelper | |
4468 #undef BranchAndLinkHelper | |
4469 | |
4470 | 4564 |
4471 // Type 3: instructions using a 26 bytes immediate. (e.g. j, jal). | 4565 // Type 3: instructions using a 26 bytes immediate. (e.g. j, jal). |
4472 void Simulator::DecodeTypeJump(Instruction* instr) { | 4566 void Simulator::DecodeTypeJump(Instruction* instr) { |
4473 // Get current pc. | 4567 // Get current pc. |
4474 int64_t current_pc = get_pc(); | 4568 int64_t current_pc = get_pc(); |
4475 // Get unchanged bits of pc. | 4569 // Get unchanged bits of pc. |
4476 int64_t pc_high_bits = current_pc & 0xfffffffff0000000; | 4570 int64_t pc_high_bits = current_pc & 0xfffffffff0000000; |
4477 // Next pc. | 4571 // Next pc. |
4478 int64_t next_pc = pc_high_bits | (instr->Imm26Value() << 2); | 4572 int64_t next_pc = pc_high_bits | (instr->Imm26Value() << 2); |
4479 | 4573 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4550 icount_++; | 4644 icount_++; |
4551 InstructionDecode(instr); | 4645 InstructionDecode(instr); |
4552 program_counter = get_pc(); | 4646 program_counter = get_pc(); |
4553 } | 4647 } |
4554 } else { | 4648 } else { |
4555 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when | 4649 // FLAG_stop_sim_at is at the non-default value. Stop in the debugger when |
4556 // we reach the particular instuction count. | 4650 // we reach the particular instuction count. |
4557 while (program_counter != end_sim_pc) { | 4651 while (program_counter != end_sim_pc) { |
4558 Instruction* instr = reinterpret_cast<Instruction*>(program_counter); | 4652 Instruction* instr = reinterpret_cast<Instruction*>(program_counter); |
4559 icount_++; | 4653 icount_++; |
4560 if (icount_ == static_cast<int64_t>(::v8::internal::FLAG_stop_sim_at)) { | 4654 if (icount_ == static_cast<uint64_t>(::v8::internal::FLAG_stop_sim_at)) { |
4561 MipsDebugger dbg(this); | 4655 MipsDebugger dbg(this); |
4562 dbg.Debug(); | 4656 dbg.Debug(); |
4563 } else { | 4657 } else { |
4564 InstructionDecode(instr); | 4658 InstructionDecode(instr); |
4565 } | 4659 } |
4566 program_counter = get_pc(); | 4660 program_counter = get_pc(); |
4567 } | 4661 } |
4568 } | 4662 } |
4569 } | 4663 } |
4570 | 4664 |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4732 } | 4826 } |
4733 | 4827 |
4734 | 4828 |
4735 #undef UNSUPPORTED | 4829 #undef UNSUPPORTED |
4736 } // namespace internal | 4830 } // namespace internal |
4737 } // namespace v8 | 4831 } // namespace v8 |
4738 | 4832 |
4739 #endif // USE_SIMULATOR | 4833 #endif // USE_SIMULATOR |
4740 | 4834 |
4741 #endif // V8_TARGET_ARCH_MIPS64 | 4835 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |