| 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 |