OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <limits.h> | 5 #include <limits.h> |
6 #include <stdarg.h> | 6 #include <stdarg.h> |
7 #include <stdlib.h> | 7 #include <stdlib.h> |
8 #include <cmath> | 8 #include <cmath> |
9 | 9 |
10 #include "src/v8.h" | 10 #include "src/v8.h" |
(...skipping 2151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2162 // Instruction fields. | 2162 // Instruction fields. |
2163 const Opcode op = instr->OpcodeFieldRaw(); | 2163 const Opcode op = instr->OpcodeFieldRaw(); |
2164 const int32_t rs_reg = instr->RsValue(); | 2164 const int32_t rs_reg = instr->RsValue(); |
2165 const int32_t rs = get_register(rs_reg); | 2165 const int32_t rs = get_register(rs_reg); |
2166 const uint32_t rs_u = static_cast<uint32_t>(rs); | 2166 const uint32_t rs_u = static_cast<uint32_t>(rs); |
2167 const int32_t rt_reg = instr->RtValue(); | 2167 const int32_t rt_reg = instr->RtValue(); |
2168 const int32_t rt = get_register(rt_reg); | 2168 const int32_t rt = get_register(rt_reg); |
2169 const uint32_t rt_u = static_cast<uint32_t>(rt); | 2169 const uint32_t rt_u = static_cast<uint32_t>(rt); |
2170 const int32_t rd_reg = instr->RdValue(); | 2170 const int32_t rd_reg = instr->RdValue(); |
2171 const uint32_t sa = instr->SaValue(); | 2171 const uint32_t sa = instr->SaValue(); |
| 2172 const uint8_t bp = instr->Bp2Value(); |
2172 | 2173 |
2173 const int32_t fs_reg = instr->FsValue(); | 2174 const int32_t fs_reg = instr->FsValue(); |
2174 | 2175 |
2175 | 2176 |
2176 // ---------- Configuration. | 2177 // ---------- Configuration. |
2177 switch (op) { | 2178 switch (op) { |
2178 case COP1: // Coprocessor instructions. | 2179 case COP1: // Coprocessor instructions. |
2179 switch (instr->RsFieldRaw()) { | 2180 switch (instr->RsFieldRaw()) { |
2180 case CFC1: | 2181 case CFC1: |
2181 // At the moment only FCSR is supported. | 2182 // At the moment only FCSR is supported. |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2404 case EXT: { // Mips32r2 instruction. | 2405 case EXT: { // Mips32r2 instruction. |
2405 // Interpret rd field as 5-bit msb of extract. | 2406 // Interpret rd field as 5-bit msb of extract. |
2406 uint16_t msb = rd_reg; | 2407 uint16_t msb = rd_reg; |
2407 // Interpret sa field as 5-bit lsb of extract. | 2408 // Interpret sa field as 5-bit lsb of extract. |
2408 uint16_t lsb = sa; | 2409 uint16_t lsb = sa; |
2409 uint16_t size = msb + 1; | 2410 uint16_t size = msb + 1; |
2410 uint32_t mask = (1 << size) - 1; | 2411 uint32_t mask = (1 << size) - 1; |
2411 *alu_out = (rs_u & (mask << lsb)) >> lsb; | 2412 *alu_out = (rs_u & (mask << lsb)) >> lsb; |
2412 break; | 2413 break; |
2413 } | 2414 } |
2414 case BITSWAP: { // Mips32r6 instruction | 2415 case BSHFL: { |
2415 uint32_t input = static_cast<uint32_t>(rt); | 2416 int sa = instr->SaFieldRaw() >> kSaShift; |
2416 uint32_t output = 0; | 2417 switch (sa) { |
2417 uint8_t i_byte, o_byte; | 2418 case BITSWAP: { |
| 2419 uint32_t input = static_cast<uint32_t>(rt); |
| 2420 uint32_t output = 0; |
| 2421 uint8_t i_byte, o_byte; |
2418 | 2422 |
2419 // Reverse the bit in byte for each individual byte | 2423 // Reverse the bit in byte for each individual byte |
2420 for (int i = 0; i < 4; i++) { | 2424 for (int i = 0; i < 4; i++) { |
2421 output = output >> 8; | 2425 output = output >> 8; |
2422 i_byte = input & 0xff; | 2426 i_byte = input & 0xff; |
2423 | 2427 |
2424 // Fast way to reverse bits in byte | 2428 // Fast way to reverse bits in byte |
2425 // Devised by Sean Anderson, July 13, 2001 | 2429 // Devised by Sean Anderson, July 13, 2001 |
2426 o_byte = static_cast<uint8_t>(((i_byte * 0x0802LU & 0x22110LU) | | 2430 o_byte = |
2427 (i_byte * 0x8020LU & 0x88440LU)) * | 2431 static_cast<uint8_t>(((i_byte * 0x0802LU & 0x22110LU) | |
2428 0x10101LU >> | 2432 (i_byte * 0x8020LU & 0x88440LU)) * |
2429 16); | 2433 0x10101LU >> |
| 2434 16); |
2430 | 2435 |
2431 output = output | (static_cast<uint32_t>(o_byte << 24)); | 2436 output = output | (static_cast<uint32_t>(o_byte << 24)); |
2432 input = input >> 8; | 2437 input = input >> 8; |
| 2438 } |
| 2439 |
| 2440 *alu_out = static_cast<int32_t>(output); |
| 2441 break; |
| 2442 } |
| 2443 case SEB: |
| 2444 case SEH: |
| 2445 case WSBH: |
| 2446 UNREACHABLE(); |
| 2447 break; |
| 2448 default: { |
| 2449 sa >>= kBp2Bits; |
| 2450 switch (sa) { |
| 2451 case ALIGN: { |
| 2452 if (bp == 0) { |
| 2453 *alu_out = static_cast<int32_t>(rt); |
| 2454 } else { |
| 2455 uint32_t rt_hi = rt << (8 * bp); |
| 2456 uint32_t rs_lo = rs >> (8 * (4 - bp)); |
| 2457 *alu_out = static_cast<int32_t>(rt_hi | rs_lo); |
| 2458 } |
| 2459 break; |
| 2460 } |
| 2461 default: |
| 2462 UNREACHABLE(); |
| 2463 break; |
| 2464 } |
| 2465 } |
2433 } | 2466 } |
2434 | |
2435 *alu_out = static_cast<int32_t>(output); | |
2436 break; | 2467 break; |
2437 } | 2468 } |
2438 default: | 2469 default: |
2439 UNREACHABLE(); | 2470 UNREACHABLE(); |
2440 } | 2471 } |
2441 break; | 2472 break; |
2442 default: | 2473 default: |
2443 UNREACHABLE(); | 2474 UNREACHABLE(); |
2444 } | 2475 } |
2445 } | 2476 } |
(...skipping 1307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3753 void Simulator::DecodeTypeRegisterSPECIAL3(Instruction* instr, | 3784 void Simulator::DecodeTypeRegisterSPECIAL3(Instruction* instr, |
3754 const int32_t& rt_reg, | 3785 const int32_t& rt_reg, |
3755 const int32_t& rd_reg, | 3786 const int32_t& rd_reg, |
3756 int32_t& alu_out) { | 3787 int32_t& alu_out) { |
3757 switch (instr->FunctionFieldRaw()) { | 3788 switch (instr->FunctionFieldRaw()) { |
3758 case INS: | 3789 case INS: |
3759 // Ins instr leaves result in Rt, rather than Rd. | 3790 // Ins instr leaves result in Rt, rather than Rd. |
3760 set_register(rt_reg, alu_out); | 3791 set_register(rt_reg, alu_out); |
3761 break; | 3792 break; |
3762 case EXT: | 3793 case EXT: |
3763 // Ext instr leaves result in Rt, rather than Rd. | |
3764 set_register(rt_reg, alu_out); | 3794 set_register(rt_reg, alu_out); |
3765 break; | 3795 break; |
3766 case BITSWAP: | 3796 case BSHFL: |
3767 set_register(rd_reg, alu_out); | 3797 set_register(rd_reg, alu_out); |
3768 break; | 3798 break; |
3769 default: | 3799 default: |
3770 UNREACHABLE(); | 3800 UNREACHABLE(); |
3771 } | 3801 } |
3772 } | 3802 } |
3773 | 3803 |
3774 | 3804 |
3775 void Simulator::DecodeTypeRegister(Instruction* instr) { | 3805 void Simulator::DecodeTypeRegister(Instruction* instr) { |
3776 // Instruction fields. | 3806 // Instruction fields. |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3841 default: | 3871 default: |
3842 set_register(rd_reg, alu_out); | 3872 set_register(rd_reg, alu_out); |
3843 } | 3873 } |
3844 } | 3874 } |
3845 | 3875 |
3846 | 3876 |
3847 // Type 2: instructions using a 16 bytes immediate. (e.g. addi, beq). | 3877 // Type 2: instructions using a 16 bytes immediate. (e.g. addi, beq). |
3848 void Simulator::DecodeTypeImmediate(Instruction* instr) { | 3878 void Simulator::DecodeTypeImmediate(Instruction* instr) { |
3849 // Instruction fields. | 3879 // Instruction fields. |
3850 Opcode op = instr->OpcodeFieldRaw(); | 3880 Opcode op = instr->OpcodeFieldRaw(); |
| 3881 int32_t rs_reg = instr->RsValue(); |
3851 int32_t rs = get_register(instr->RsValue()); | 3882 int32_t rs = get_register(instr->RsValue()); |
3852 uint32_t rs_u = static_cast<uint32_t>(rs); | 3883 uint32_t rs_u = static_cast<uint32_t>(rs); |
3853 int32_t rt_reg = instr->RtValue(); // Destination register. | 3884 int32_t rt_reg = instr->RtValue(); // Destination register. |
3854 int32_t rt = get_register(rt_reg); | 3885 int32_t rt = get_register(rt_reg); |
3855 int16_t imm16 = instr->Imm16Value(); | 3886 int16_t imm16 = instr->Imm16Value(); |
| 3887 int32_t imm19 = instr->Imm19Value(); |
| 3888 int32_t imm21 = instr->Imm21Value(); |
| 3889 int32_t imm26 = instr->Imm26Value(); |
3856 | 3890 |
3857 int32_t ft_reg = instr->FtValue(); // Destination register. | 3891 int32_t ft_reg = instr->FtValue(); // Destination register. |
3858 int64_t ft; | 3892 int64_t ft; |
3859 | 3893 |
3860 // Zero extended immediate. | 3894 // Zero extended immediate. |
3861 uint32_t oe_imm16 = 0xffff & imm16; | 3895 uint32_t oe_imm16 = 0xffff & imm16; |
3862 // Sign extended immediate. | 3896 // Sign extended immediate. |
3863 int32_t se_imm16 = imm16; | 3897 int32_t se_imm16 = imm16; |
| 3898 int32_t se_imm19 = imm19 | ((imm19 & 0x40000) ? 0xfff80000 : 0); |
| 3899 int32_t se_imm26 = imm26 | ((imm26 & 0x2000000) ? 0xfc000000 : 0); |
| 3900 |
3864 | 3901 |
3865 // Get current pc. | 3902 // Get current pc. |
3866 int32_t current_pc = get_pc(); | 3903 int32_t current_pc = get_pc(); |
3867 // Next pc. | 3904 // Next pc. |
3868 int32_t next_pc = bad_ra; | 3905 int32_t next_pc = bad_ra; |
| 3906 // pc increment |
| 3907 int16_t pc_increment; |
3869 | 3908 |
3870 // Used for conditional branch instructions. | 3909 // Used for conditional branch instructions. |
3871 bool do_branch = false; | 3910 bool do_branch = false; |
3872 bool execute_branch_delay_instruction = false; | 3911 bool execute_branch_delay_instruction = false; |
3873 | 3912 |
3874 // Used for arithmetic instructions. | 3913 // Used for arithmetic instructions. |
3875 int32_t alu_out = 0; | 3914 int32_t alu_out = 0; |
3876 // Floating point. | 3915 // Floating point. |
3877 double fp_out = 0.0; | 3916 double fp_out = 0.0; |
3878 uint32_t cc, cc_value, fcsr_cc; | 3917 uint32_t cc, cc_value, fcsr_cc; |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3972 break; | 4011 break; |
3973 case BNE: | 4012 case BNE: |
3974 do_branch = rs != rt; | 4013 do_branch = rs != rt; |
3975 break; | 4014 break; |
3976 case BLEZ: | 4015 case BLEZ: |
3977 do_branch = rs <= 0; | 4016 do_branch = rs <= 0; |
3978 break; | 4017 break; |
3979 case BGTZ: | 4018 case BGTZ: |
3980 do_branch = rs > 0; | 4019 do_branch = rs > 0; |
3981 break; | 4020 break; |
| 4021 case POP66: { |
| 4022 if (rs_reg) { // BEQZC |
| 4023 int32_t se_imm21 = |
| 4024 static_cast<int32_t>(imm21 << (kOpcodeBits + kRsBits)); |
| 4025 se_imm21 = se_imm21 >> (kOpcodeBits + kRsBits); |
| 4026 if (rs == 0) |
| 4027 next_pc = current_pc + 4 + (se_imm21 << 2); |
| 4028 else |
| 4029 next_pc = current_pc + 4; |
| 4030 } else { // JIC |
| 4031 next_pc = rt + imm16; |
| 4032 } |
| 4033 break; |
| 4034 } |
| 4035 case BC: { |
| 4036 next_pc = current_pc + 4 + (se_imm26 << 2); |
| 4037 set_pc(next_pc); |
| 4038 pc_modified_ = true; |
| 4039 break; |
| 4040 } |
| 4041 case BALC: { |
| 4042 set_register(31, current_pc + 4); |
| 4043 next_pc = current_pc + 4 + (se_imm26 << 2); |
| 4044 set_pc(next_pc); |
| 4045 pc_modified_ = true; |
| 4046 break; |
| 4047 } |
3982 // ------------- Arithmetic instructions. | 4048 // ------------- Arithmetic instructions. |
3983 case ADDI: | 4049 case ADDI: |
3984 if (HaveSameSign(rs, se_imm16)) { | 4050 if (HaveSameSign(rs, se_imm16)) { |
3985 if (rs > 0) { | 4051 if (rs > 0) { |
3986 exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - se_imm16); | 4052 exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - se_imm16); |
3987 } else if (rs < 0) { | 4053 } else if (rs < 0) { |
3988 exceptions[kIntegerUnderflow] = | 4054 exceptions[kIntegerUnderflow] = |
3989 rs < (Registers::kMinValue - se_imm16); | 4055 rs < (Registers::kMinValue - se_imm16); |
3990 } | 4056 } |
3991 } | 4057 } |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4086 alu_out = ReadW(addr, instr); | 4152 alu_out = ReadW(addr, instr); |
4087 break; | 4153 break; |
4088 case LDC1: | 4154 case LDC1: |
4089 addr = rs + se_imm16; | 4155 addr = rs + se_imm16; |
4090 fp_out = ReadD(addr, instr); | 4156 fp_out = ReadD(addr, instr); |
4091 break; | 4157 break; |
4092 case SWC1: | 4158 case SWC1: |
4093 case SDC1: | 4159 case SDC1: |
4094 addr = rs + se_imm16; | 4160 addr = rs + se_imm16; |
4095 break; | 4161 break; |
| 4162 // ------------- JIALC and BNEZC instructions. |
| 4163 case POP76: |
| 4164 // Next pc. |
| 4165 next_pc = rt + se_imm16; |
| 4166 // The instruction after the jump is NOT executed. |
| 4167 pc_increment = Instruction::kInstrSize; |
| 4168 if (instr->IsLinkingInstruction()) { |
| 4169 set_register(31, current_pc + pc_increment); |
| 4170 } |
| 4171 set_pc(next_pc); |
| 4172 pc_modified_ = true; |
| 4173 break; |
| 4174 // ------------- PC-Relative instructions. |
| 4175 case PCREL: { |
| 4176 // rt field: checking 5-bits. |
| 4177 uint8_t rt = (imm21 >> kImm16Bits); |
| 4178 switch (rt) { |
| 4179 case ALUIPC: |
| 4180 addr = current_pc + (se_imm16 << 16); |
| 4181 alu_out = static_cast<int64_t>(~0x0FFFF) & addr; |
| 4182 break; |
| 4183 case AUIPC: |
| 4184 alu_out = current_pc + (se_imm16 << 16); |
| 4185 break; |
| 4186 default: { |
| 4187 // rt field: checking the most significant 2-bits. |
| 4188 rt = (imm21 >> kImm19Bits); |
| 4189 switch (rt) { |
| 4190 case LWPC: { |
| 4191 int32_t offset = imm19; |
| 4192 // Set sign. |
| 4193 offset <<= (kOpcodeBits + kRsBits + 2); |
| 4194 offset >>= (kOpcodeBits + kRsBits + 2); |
| 4195 addr = current_pc + (offset << 2); |
| 4196 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr); |
| 4197 alu_out = *ptr; |
| 4198 break; |
| 4199 } |
| 4200 case ADDIUPC: |
| 4201 alu_out = current_pc + (se_imm19 << 2); |
| 4202 break; |
| 4203 default: |
| 4204 UNREACHABLE(); |
| 4205 break; |
| 4206 } |
| 4207 } |
| 4208 } |
| 4209 break; |
| 4210 } |
4096 default: | 4211 default: |
4097 UNREACHABLE(); | 4212 UNREACHABLE(); |
4098 } | 4213 } |
4099 | 4214 |
4100 // ---------- Raise exceptions triggered. | 4215 // ---------- Raise exceptions triggered. |
4101 SignalExceptions(); | 4216 SignalExceptions(); |
4102 | 4217 |
4103 // ---------- Execution. | 4218 // ---------- Execution. |
4104 switch (op) { | 4219 switch (op) { |
4105 // ------------- Branch instructions. | 4220 // ------------- Branch instructions. |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4163 set_fpu_register_double(ft_reg, fp_out); | 4278 set_fpu_register_double(ft_reg, fp_out); |
4164 break; | 4279 break; |
4165 case SWC1: | 4280 case SWC1: |
4166 addr = rs + se_imm16; | 4281 addr = rs + se_imm16; |
4167 WriteW(addr, get_fpu_register_word(ft_reg), instr); | 4282 WriteW(addr, get_fpu_register_word(ft_reg), instr); |
4168 break; | 4283 break; |
4169 case SDC1: | 4284 case SDC1: |
4170 addr = rs + se_imm16; | 4285 addr = rs + se_imm16; |
4171 WriteD(addr, get_fpu_register_double(ft_reg), instr); | 4286 WriteD(addr, get_fpu_register_double(ft_reg), instr); |
4172 break; | 4287 break; |
| 4288 case PCREL: |
| 4289 set_register(rs_reg, alu_out); |
4173 default: | 4290 default: |
4174 break; | 4291 break; |
4175 } | 4292 } |
4176 | 4293 |
4177 | 4294 |
4178 if (execute_branch_delay_instruction) { | 4295 if (execute_branch_delay_instruction) { |
4179 // Execute branch delay slot | 4296 // Execute branch delay slot |
4180 // We don't check for end_sim_pc. First it should not be met as the current | 4297 // We don't check for end_sim_pc. First it should not be met as the current |
4181 // pc is valid. Secondly a jump should always execute its branch delay slot. | 4298 // pc is valid. Secondly a jump should always execute its branch delay slot. |
4182 Instruction* branch_delay_instr = | 4299 Instruction* branch_delay_instr = |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4431 | 4548 |
4432 | 4549 |
4433 #undef UNSUPPORTED | 4550 #undef UNSUPPORTED |
4434 | 4551 |
4435 } // namespace internal | 4552 } // namespace internal |
4436 } // namespace v8 | 4553 } // namespace v8 |
4437 | 4554 |
4438 #endif // USE_SIMULATOR | 4555 #endif // USE_SIMULATOR |
4439 | 4556 |
4440 #endif // V8_TARGET_ARCH_MIPS | 4557 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |