Chromium Code Reviews| 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 |