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 #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 1308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3754 void Simulator::DecodeTypeRegisterSPECIAL3(Instruction* instr, | 3785 void Simulator::DecodeTypeRegisterSPECIAL3(Instruction* instr, |
| 3755 const int32_t& rt_reg, | 3786 const int32_t& rt_reg, |
| 3756 const int32_t& rd_reg, | 3787 const int32_t& rd_reg, |
| 3757 int32_t& alu_out) { | 3788 int32_t& alu_out) { |
| 3758 switch (instr->FunctionFieldRaw()) { | 3789 switch (instr->FunctionFieldRaw()) { |
| 3759 case INS: | 3790 case INS: |
| 3760 // Ins instr leaves result in Rt, rather than Rd. | 3791 // Ins instr leaves result in Rt, rather than Rd. |
| 3761 set_register(rt_reg, alu_out); | 3792 set_register(rt_reg, alu_out); |
| 3762 break; | 3793 break; |
| 3763 case EXT: | 3794 case EXT: |
| 3764 // Ext instr leaves result in Rt, rather than Rd. | |
| 3765 set_register(rt_reg, alu_out); | 3795 set_register(rt_reg, alu_out); |
| 3766 break; | 3796 break; |
| 3767 case BITSWAP: | 3797 case BSHFL: |
| 3768 set_register(rd_reg, alu_out); | 3798 set_register(rd_reg, alu_out); |
| 3769 break; | 3799 break; |
| 3770 default: | 3800 default: |
| 3771 UNREACHABLE(); | 3801 UNREACHABLE(); |
| 3772 } | 3802 } |
| 3773 } | 3803 } |
| 3774 | 3804 |
| 3775 | 3805 |
| 3776 void Simulator::DecodeTypeRegister(Instruction* instr) { | 3806 void Simulator::DecodeTypeRegister(Instruction* instr) { |
| 3777 // Instruction fields. | 3807 // Instruction fields. |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3842 default: | 3872 default: |
| 3843 set_register(rd_reg, alu_out); | 3873 set_register(rd_reg, alu_out); |
| 3844 } | 3874 } |
| 3845 } | 3875 } |
| 3846 | 3876 |
| 3847 | 3877 |
| 3848 // Type 2: instructions using a 16 bytes immediate. (e.g. addi, beq). | 3878 // Type 2: instructions using a 16 bytes immediate. (e.g. addi, beq). |
| 3849 void Simulator::DecodeTypeImmediate(Instruction* instr) { | 3879 void Simulator::DecodeTypeImmediate(Instruction* instr) { |
| 3850 // Instruction fields. | 3880 // Instruction fields. |
| 3851 Opcode op = instr->OpcodeFieldRaw(); | 3881 Opcode op = instr->OpcodeFieldRaw(); |
| 3882 int32_t rs_reg = instr->RsValue(); | |
| 3852 int32_t rs = get_register(instr->RsValue()); | 3883 int32_t rs = get_register(instr->RsValue()); |
| 3853 uint32_t rs_u = static_cast<uint32_t>(rs); | 3884 uint32_t rs_u = static_cast<uint32_t>(rs); |
| 3854 int32_t rt_reg = instr->RtValue(); // Destination register. | 3885 int32_t rt_reg = instr->RtValue(); // Destination register. |
| 3855 int32_t rt = get_register(rt_reg); | 3886 int32_t rt = get_register(rt_reg); |
| 3856 int16_t imm16 = instr->Imm16Value(); | 3887 int16_t imm16 = instr->Imm16Value(); |
| 3888 int32_t imm19 = instr->Imm19Value(); | |
| 3889 int32_t imm21 = instr->Imm21Value(); | |
| 3890 int32_t imm26 = instr->Imm26Value(); | |
| 3857 | 3891 |
| 3858 int32_t ft_reg = instr->FtValue(); // Destination register. | 3892 int32_t ft_reg = instr->FtValue(); // Destination register. |
| 3859 int64_t ft; | 3893 int64_t ft; |
| 3860 | 3894 |
| 3861 // Zero extended immediate. | 3895 // Zero extended immediate. |
| 3862 uint32_t oe_imm16 = 0xffff & imm16; | 3896 uint32_t oe_imm16 = 0xffff & imm16; |
| 3863 // Sign extended immediate. | 3897 // Sign extended immediate. |
| 3864 int32_t se_imm16 = imm16; | 3898 int32_t se_imm16 = imm16; |
| 3899 int32_t se_imm19 = imm19 | ((imm19 & 0x40000) ? 0xfff80000 : 0); | |
| 3900 int32_t se_imm26 = imm26 | ((imm26 & 0x2000000) ? 0xfc000000 : 0); | |
| 3901 | |
| 3865 | 3902 |
| 3866 // Get current pc. | 3903 // Get current pc. |
| 3867 int32_t current_pc = get_pc(); | 3904 int32_t current_pc = get_pc(); |
| 3868 // Next pc. | 3905 // Next pc. |
| 3869 int32_t next_pc = bad_ra; | 3906 int32_t next_pc = bad_ra; |
| 3907 // pc increment | |
| 3908 int16_t pc_increment; | |
| 3870 | 3909 |
| 3871 // Used for conditional branch instructions. | 3910 // Used for conditional branch instructions. |
| 3872 bool do_branch = false; | 3911 bool do_branch = false; |
| 3873 bool execute_branch_delay_instruction = false; | 3912 bool execute_branch_delay_instruction = false; |
| 3874 | 3913 |
| 3875 // Used for arithmetic instructions. | 3914 // Used for arithmetic instructions. |
| 3876 int32_t alu_out = 0; | 3915 int32_t alu_out = 0; |
| 3877 // Floating point. | 3916 // Floating point. |
| 3878 double fp_out = 0.0; | 3917 double fp_out = 0.0; |
| 3879 uint32_t cc, cc_value, fcsr_cc; | 3918 uint32_t cc, cc_value, fcsr_cc; |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3973 break; | 4012 break; |
| 3974 case BNE: | 4013 case BNE: |
| 3975 do_branch = rs != rt; | 4014 do_branch = rs != rt; |
| 3976 break; | 4015 break; |
| 3977 case BLEZ: | 4016 case BLEZ: |
| 3978 do_branch = rs <= 0; | 4017 do_branch = rs <= 0; |
| 3979 break; | 4018 break; |
| 3980 case BGTZ: | 4019 case BGTZ: |
| 3981 do_branch = rs > 0; | 4020 do_branch = rs > 0; |
| 3982 break; | 4021 break; |
| 4022 case POP66: { | |
| 4023 if (rs_reg) { // BEQZC | |
| 4024 int32_t se_imm21 = | |
| 4025 static_cast<int32_t>(imm21 << (kOpcodeBits + kRsBits)); | |
| 4026 se_imm21 = se_imm21 >> (kOpcodeBits + kRsBits); | |
| 4027 if (rs == 0) | |
| 4028 next_pc = current_pc + 4 + (se_imm21 << 2); | |
| 4029 else | |
| 4030 next_pc = current_pc + 4; | |
| 4031 } else { // JIC | |
| 4032 next_pc = rt + imm16; | |
| 4033 } | |
| 4034 break; | |
| 4035 } | |
| 4036 case BC: { | |
| 4037 next_pc = current_pc + 4 + (se_imm26 << 2); | |
| 4038 set_pc(next_pc); | |
| 4039 pc_modified_ = true; | |
| 4040 break; | |
| 4041 } | |
| 4042 case BALC: { | |
| 4043 set_register(31, current_pc + 4); | |
| 4044 next_pc = current_pc + 4 + (se_imm26 << 2); | |
| 4045 set_pc(next_pc); | |
| 4046 pc_modified_ = true; | |
| 4047 break; | |
| 4048 } | |
| 3983 // ------------- Arithmetic instructions. | 4049 // ------------- Arithmetic instructions. |
| 3984 case ADDI: | 4050 case ADDI: |
| 3985 if (HaveSameSign(rs, se_imm16)) { | 4051 if (HaveSameSign(rs, se_imm16)) { |
| 3986 if (rs > 0) { | 4052 if (rs > 0) { |
| 3987 exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - se_imm16); | 4053 exceptions[kIntegerOverflow] = rs > (Registers::kMaxValue - se_imm16); |
| 3988 } else if (rs < 0) { | 4054 } else if (rs < 0) { |
| 3989 exceptions[kIntegerUnderflow] = | 4055 exceptions[kIntegerUnderflow] = |
| 3990 rs < (Registers::kMinValue - se_imm16); | 4056 rs < (Registers::kMinValue - se_imm16); |
| 3991 } | 4057 } |
| 3992 } | 4058 } |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4087 alu_out = ReadW(addr, instr); | 4153 alu_out = ReadW(addr, instr); |
| 4088 break; | 4154 break; |
| 4089 case LDC1: | 4155 case LDC1: |
| 4090 addr = rs + se_imm16; | 4156 addr = rs + se_imm16; |
| 4091 fp_out = ReadD(addr, instr); | 4157 fp_out = ReadD(addr, instr); |
| 4092 break; | 4158 break; |
| 4093 case SWC1: | 4159 case SWC1: |
| 4094 case SDC1: | 4160 case SDC1: |
| 4095 addr = rs + se_imm16; | 4161 addr = rs + se_imm16; |
| 4096 break; | 4162 break; |
| 4163 // ------------- JIALC and BNEZC instructions. | |
| 4164 case POP76: | |
| 4165 // Next pc. | |
| 4166 next_pc = rt + se_imm16; | |
| 4167 // The instruction after the jump is NOT executed. | |
| 4168 pc_increment = Instruction::kInstrSize; | |
| 4169 if (instr->IsLinkingInstruction()) { | |
| 4170 set_register(31, current_pc + pc_increment); | |
| 4171 } | |
| 4172 set_pc(next_pc); | |
| 4173 pc_modified_ = true; | |
| 4174 break; | |
| 4175 // ---------PC-Relative instructions----------- | |
| 4176 case PCREL: { | |
| 4177 // rt field: checking 5-bits | |
|
paul.l...
2015/06/10 03:49:26
nits: comments end with periods, several places.
ilija.pavlovic
2015/06/12 09:51:33
Done.
| |
| 4178 uint8_t rt = (imm21 >> kImm16Bits); | |
| 4179 switch (rt) { | |
| 4180 case ALUIPC: | |
| 4181 addr = current_pc + (se_imm16 << 16); | |
| 4182 alu_out = static_cast<int64_t>(~0x0FFFF) & addr; | |
| 4183 break; | |
| 4184 case AUIPC: | |
| 4185 alu_out = current_pc + (se_imm16 << 16); | |
| 4186 break; | |
| 4187 default: { | |
| 4188 // rt field: checking the most significant 2-bits | |
| 4189 rt = (imm21 >> kImm19Bits); | |
| 4190 switch (rt) { | |
| 4191 case LWPC: { | |
| 4192 int32_t offset = imm19; | |
| 4193 // set sign | |
| 4194 offset <<= (kOpcodeBits + kRsBits + 2); | |
| 4195 offset >>= (kOpcodeBits + kRsBits + 2); | |
| 4196 addr = current_pc + (offset << 2); | |
| 4197 uint32_t* ptr = reinterpret_cast<uint32_t*>(addr); | |
| 4198 alu_out = *ptr; | |
| 4199 break; | |
| 4200 } | |
| 4201 case ADDIUPC: | |
| 4202 alu_out = current_pc + (se_imm19 << 2); | |
| 4203 break; | |
| 4204 default: | |
| 4205 UNREACHABLE(); | |
| 4206 break; | |
| 4207 } | |
| 4208 } | |
| 4209 } | |
| 4210 break; | |
| 4211 } | |
| 4097 default: | 4212 default: |
| 4098 UNREACHABLE(); | 4213 UNREACHABLE(); |
| 4099 } | 4214 } |
| 4100 | 4215 |
| 4101 // ---------- Raise exceptions triggered. | 4216 // ---------- Raise exceptions triggered. |
| 4102 SignalExceptions(); | 4217 SignalExceptions(); |
| 4103 | 4218 |
| 4104 // ---------- Execution. | 4219 // ---------- Execution. |
| 4105 switch (op) { | 4220 switch (op) { |
| 4106 // ------------- Branch instructions. | 4221 // ------------- Branch instructions. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4164 set_fpu_register_double(ft_reg, fp_out); | 4279 set_fpu_register_double(ft_reg, fp_out); |
| 4165 break; | 4280 break; |
| 4166 case SWC1: | 4281 case SWC1: |
| 4167 addr = rs + se_imm16; | 4282 addr = rs + se_imm16; |
| 4168 WriteW(addr, get_fpu_register_word(ft_reg), instr); | 4283 WriteW(addr, get_fpu_register_word(ft_reg), instr); |
| 4169 break; | 4284 break; |
| 4170 case SDC1: | 4285 case SDC1: |
| 4171 addr = rs + se_imm16; | 4286 addr = rs + se_imm16; |
| 4172 WriteD(addr, get_fpu_register_double(ft_reg), instr); | 4287 WriteD(addr, get_fpu_register_double(ft_reg), instr); |
| 4173 break; | 4288 break; |
| 4289 case PCREL: | |
| 4290 set_register(rs_reg, alu_out); | |
| 4174 default: | 4291 default: |
| 4175 break; | 4292 break; |
| 4176 } | 4293 } |
| 4177 | 4294 |
| 4178 | 4295 |
| 4179 if (execute_branch_delay_instruction) { | 4296 if (execute_branch_delay_instruction) { |
| 4180 // Execute branch delay slot | 4297 // Execute branch delay slot |
| 4181 // We don't check for end_sim_pc. First it should not be met as the current | 4298 // We don't check for end_sim_pc. First it should not be met as the current |
| 4182 // pc is valid. Secondly a jump should always execute its branch delay slot. | 4299 // pc is valid. Secondly a jump should always execute its branch delay slot. |
| 4183 Instruction* branch_delay_instr = | 4300 Instruction* branch_delay_instr = |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4431 } | 4548 } |
| 4432 | 4549 |
| 4433 | 4550 |
| 4434 #undef UNSUPPORTED | 4551 #undef UNSUPPORTED |
| 4435 | 4552 |
| 4436 } } // namespace v8::internal | 4553 } } // namespace v8::internal |
| 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 |