Chromium Code Reviews| Index: src/mips64/simulator-mips64.cc |
| diff --git a/src/mips64/simulator-mips64.cc b/src/mips64/simulator-mips64.cc |
| index 200a1bc80b0a4e1be0f585fb58eaa50d8e95ef25..7ef7428a8a585b0a23711eac2cc3bedd16c9eb1a 100644 |
| --- a/src/mips64/simulator-mips64.cc |
| +++ b/src/mips64/simulator-mips64.cc |
| @@ -2201,6 +2201,8 @@ void Simulator::ConfigureTypeRegister(Instruction* instr, int64_t* alu_out, |
| const uint64_t rt_u = static_cast<uint64_t>(rt); |
| const int32_t rd_reg = instr->RdValue(); |
| const uint64_t sa = instr->SaValue(); |
| + const uint8_t bp2 = instr->Bp2Value(); |
| + const uint8_t bp3 = instr->Bp3Value(); |
| const int32_t fs_reg = instr->FsValue(); |
| @@ -2335,7 +2337,8 @@ void Simulator::ConfigureTypeRegister(Instruction* instr, int64_t* alu_out, |
| // MIPS spec: If no bits were set in GPR rs, the result written to |
| // GPR rd is 32. |
| DCHECK(instr->SaValue() == 1); |
| - *alu_out = base::bits::CountLeadingZeros32(rs_u); |
| + *alu_out = |
| + base::bits::CountLeadingZeros32(static_cast<int32_t>(rs_u)); |
| } |
| break; |
| case MFLO: |
| @@ -2519,39 +2522,16 @@ void Simulator::ConfigureTypeRegister(Instruction* instr, int64_t* alu_out, |
| *alu_out = static_cast<int64_t>((rs_u & (mask << lsb)) >> lsb); |
| break; |
| } |
| - case BITSWAP: { // Mips32r6 instruction |
| - uint32_t input = static_cast<uint32_t>(rt); |
| - uint32_t output = 0; |
| - uint8_t i_byte, o_byte; |
| - |
| - // Reverse the bit in byte for each individual byte |
| - for (int i = 0; i < 4; i++) { |
| - output = output >> 8; |
| - i_byte = input & 0xff; |
| - |
| - // Fast way to reverse bits in byte |
| - // Devised by Sean Anderson, July 13, 2001 |
| - o_byte = static_cast<uint8_t>(((i_byte * 0x0802LU & 0x22110LU) | |
| - (i_byte * 0x8020LU & 0x88440LU)) * |
| - 0x10101LU >> |
| - 16); |
| - |
| - output = output | (static_cast<uint32_t>(o_byte << 24)); |
| - input = input >> 8; |
| - } |
| - |
| - *alu_out = static_cast<int64_t>(static_cast<int32_t>(output)); |
| - break; |
| - } |
| - case DBITSWAP: { |
| - switch (instr->SaFieldRaw()) { |
| - case DBITSWAP_SA: { // Mips64r6 |
| - uint64_t input = static_cast<uint64_t>(rt); |
| - uint64_t output = 0; |
| + case BSHFL: { |
| + int sa = instr->SaFieldRaw() >> kSaShift; |
| + switch (sa) { |
| + case BITSWAP: { |
| + uint32_t input = static_cast<uint32_t>(rt); |
| + uint32_t output = 0; |
| uint8_t i_byte, o_byte; |
| // Reverse the bit in byte for each individual byte |
| - for (int i = 0; i < 8; i++) { |
| + for (int i = 0; i < 4; i++) { |
| output = output >> 8; |
| i_byte = input & 0xff; |
| @@ -2563,15 +2543,96 @@ void Simulator::ConfigureTypeRegister(Instruction* instr, int64_t* alu_out, |
| 0x10101LU >> |
| 16); |
| - output = output | ((static_cast<uint64_t>(o_byte) << 56)); |
| + output = output | (static_cast<uint32_t>(o_byte << 24)); |
| input = input >> 8; |
| } |
| - *alu_out = static_cast<int64_t>(output); |
| + *alu_out = static_cast<int64_t>(static_cast<int32_t>(output)); |
| break; |
| } |
| - default: |
| + case SEB: |
| + case SEH: |
| + case WSBH: |
| UNREACHABLE(); |
| + break; |
| + default: { |
| + sa >>= kBp2Bits; |
| + switch (sa) { |
| + case ALIGN: { |
| + if (bp2 == 0) { |
| + *alu_out = static_cast<int32_t>(rt); |
| + } else { |
| + uint64_t rt_hi = rt << (8 * bp2); |
| + uint64_t rs_lo = rs >> (8 * (4 - bp2)); |
| + *alu_out = static_cast<int32_t>(rt_hi | rs_lo); |
| + } |
| + break; |
| + } |
| + default: |
| + UNREACHABLE(); |
| + break; |
| + } |
| + break; |
| + } |
| + } |
| + break; |
| + } |
| + case DBSHFL: { |
| + int sa = instr->SaFieldRaw() >> kSaShift; |
| + switch (sa) { |
| + case DBITSWAP: { |
| + switch (instr->SaFieldRaw() >> kSaShift) { |
| + case DBITSWAP_SA: { // Mips64r6 |
| + uint64_t input = static_cast<uint64_t>(rt); |
| + uint64_t output = 0; |
| + uint8_t i_byte, o_byte; |
| + |
| + // Reverse the bit in byte for each individual byte |
| + for (int i = 0; i < 8; i++) { |
| + output = output >> 8; |
| + i_byte = input & 0xff; |
| + |
| + // Fast way to reverse bits in byte |
| + // Devised by Sean Anderson, July 13, 2001 |
| + o_byte = |
| + static_cast<uint8_t>(((i_byte * 0x0802LU & 0x22110LU) | |
| + (i_byte * 0x8020LU & 0x88440LU)) * |
| + 0x10101LU >> |
| + 16); |
| + |
| + output = output | ((static_cast<uint64_t>(o_byte) << 56)); |
| + input = input >> 8; |
| + } |
| + |
| + *alu_out = static_cast<int64_t>(output); |
| + break; |
| + } |
| + } |
| + break; |
| + } |
| + case DSBH: |
| + case DSHD: |
| + UNREACHABLE(); |
| + break; |
| + default: { |
| + sa >>= kBp3Bits; |
| + switch (sa) { |
| + case DALIGN: { |
| + if (bp3 == 0) { |
| + *alu_out = static_cast<int64_t>(rt); |
| + } else { |
| + uint64_t rt_hi = rt << (8 * bp3); |
| + uint64_t rs_lo = rs >> (8 * (8 - bp3)); |
| + *alu_out = static_cast<int64_t>(rt_hi | rs_lo); |
| + } |
| + break; |
| + } |
| + default: |
| + UNREACHABLE(); |
| + break; |
| + } |
| + break; |
| + } |
| } |
| break; |
| } |
| @@ -3853,8 +3914,8 @@ void Simulator::DecodeTypeRegisterSPECIAL3(Instruction* instr, |
| set_register(rt_reg, alu_out); |
| TraceRegWr(alu_out); |
| break; |
| - case BITSWAP: |
| - case DBITSWAP: |
| + case BSHFL: |
| + case DBSHFL: |
| set_register(rd_reg, alu_out); |
| TraceRegWr(alu_out); |
| break; |
| @@ -3933,7 +3994,31 @@ void Simulator::DecodeTypeRegister(Instruction* instr) { |
| DecodeTypeRegisterSPECIAL2(instr, rd_reg, alu_out); |
| break; |
| case SPECIAL3: |
| - DecodeTypeRegisterSPECIAL3(instr, rt_reg, rd_reg, alu_out); |
| + switch (instr->FunctionFieldRaw()) { |
| + case BSHFL: { |
| + int sa = instr->SaValue(); |
| + sa >>= kBp2Bits; |
| + switch (sa) { |
| + case ALIGN: { |
| + DecodeTypeRegisterSPECIAL3(instr, rt_reg, rd_reg, alu_out); |
| + break; |
| + } |
| + } |
| + } |
| + case DBSHFL: { |
| + int sa = instr->SaValue(); |
| + sa >>= kBp3Bits; |
| + switch (sa) { |
| + case DALIGN: { |
| + DecodeTypeRegisterSPECIAL3(instr, rt_reg, rd_reg, alu_out); |
| + break; |
| + } |
| + } |
| + } |
| + default: |
| + DecodeTypeRegisterSPECIAL3(instr, rt_reg, rd_reg, alu_out); |
| + break; |
| + } |
| break; |
| // Unimplemented opcodes raised an error in the configuration step before, |
| // so we can use the default here to set the destination register in common |
| @@ -3949,11 +4034,16 @@ void Simulator::DecodeTypeRegister(Instruction* instr) { |
| void Simulator::DecodeTypeImmediate(Instruction* instr) { |
| // Instruction fields. |
| Opcode op = instr->OpcodeFieldRaw(); |
| + int64_t rs_reg = instr->RsValue(); |
| int64_t rs = get_register(instr->RsValue()); |
| uint64_t rs_u = static_cast<uint64_t>(rs); |
| int32_t rt_reg = instr->RtValue(); // Destination register. |
| int64_t rt = get_register(rt_reg); |
| int16_t imm16 = instr->Imm16Value(); |
| + int32_t imm18 = instr->Imm18Value(); |
| + int32_t imm19 = instr->Imm19Value(); |
| + int32_t imm21 = instr->Imm21Value(); |
| + int32_t imm26 = instr->Imm26Value(); |
| int32_t ft_reg = instr->FtValue(); // Destination register. |
| int64_t ft = get_fpu_register(ft_reg); |
| @@ -3962,11 +4052,17 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) { |
| uint64_t oe_imm16 = 0xffff & imm16; |
| // Sign extended immediate. |
| int64_t se_imm16 = imm16; |
| + int64_t se_imm18 = imm18 | ((imm18 & 0x20000) ? 0xfffffffffffc0000 : 0); |
| + int64_t se_imm19 = imm19 | ((imm19 & 0x40000) ? 0xfffffffffff80000 : 0); |
| + int64_t se_imm26 = imm26 | ((imm26 & 0x2000000) ? 0xfffffffffc000000 : 0); |
| + |
| // Get current pc. |
| int64_t current_pc = get_pc(); |
| // Next pc. |
| int64_t next_pc = bad_ra; |
| + // pc increment |
| + int16_t pc_increment; |
| // Used for conditional branch instructions. |
| bool do_branch = false; |
| @@ -4080,6 +4176,33 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) { |
| case BGTZ: |
| do_branch = rs > 0; |
| break; |
| + case POP66: { |
| + if (rs_reg) { // BEQZC |
| + int32_t se_imm21 = |
| + static_cast<int32_t>(imm21 << (kOpcodeBits + kRsBits)); |
| + se_imm21 = se_imm21 >> (kOpcodeBits + kRsBits); |
| + if (rs == 0) |
| + next_pc = current_pc + 4 + (se_imm21 << 2); |
| + else |
| + next_pc = current_pc + 4; |
| + } else { // JIC |
| + next_pc = rt + imm16; |
| + } |
| + break; |
| + } |
| + case BC: { |
| + next_pc = current_pc + 4 + (se_imm26 << 2); |
| + set_pc(next_pc); |
| + pc_modified_ = true; |
| + break; |
| + } |
| + case BALC: { |
| + set_register(31, current_pc + 4); |
| + next_pc = current_pc + 4 + (se_imm26 << 2); |
| + set_pc(next_pc); |
| + pc_modified_ = true; |
| + break; |
| + } |
| // ------------- Arithmetic instructions. |
| case ADDI: |
| case DADDI: |
| @@ -4213,10 +4336,83 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) { |
| case SDC1: |
| addr = rs + se_imm16; |
| break; |
| + // ------------- JIALC and BNEZC instructions. |
| + case POP76: |
| + // Next pc. |
| + next_pc = rt + se_imm16; |
| + // The instruction after the jump is NOT executed. |
| + pc_increment = Instruction::kInstrSize; |
| + if (instr->IsLinkingInstruction()) { |
| + set_register(31, current_pc + pc_increment); |
| + } |
| + set_pc(next_pc); |
| + pc_modified_ = true; |
| + break; |
| + // ------------- PC-Relative instructions. |
| + case PCREL: { |
| + // rt field: checking 5-bits. |
| + uint8_t rt = (imm21 >> kImm16Bits); |
| + switch (rt) { |
| + case ALUIPC: |
| + addr = current_pc + (se_imm16 << 16); |
| + alu_out = static_cast<int64_t>(~0x0FFFF) & addr; |
| + break; |
| + case AUIPC: |
| + alu_out = current_pc + (se_imm16 << 16); |
| + break; |
| + default: { |
| + // rt field: checking the most significant 3-bits. |
| + rt = (imm21 >> kImm18Bits); |
| + switch (rt) { |
| + case LDPC: |
| + addr = |
| + (current_pc & static_cast<int64_t>(~0x7)) + (se_imm18 << 3); |
| + alu_out = Read2W(addr, instr); |
| + break; |
| + default: { |
| + // rt field: checking the most significant 2-bits. |
| + rt = (imm21 >> kImm19Bits); |
| + switch (rt) { |
| + case LWUPC: { |
| + int32_t offset = imm19; |
| + // Set sign. |
| + offset <<= (kOpcodeBits + kRsBits + 2); |
| + offset >>= (kOpcodeBits + kRsBits + 2); |
| + addr = current_pc + (offset << 2); |
| + uint32_t* ptr = reinterpret_cast<uint32_t*>(addr); |
| + alu_out = *ptr; |
| + break; |
| + } |
| + case LWPC: { |
| + int32_t offset = imm19; |
| + // Set sign. |
| + offset <<= (kOpcodeBits + kRsBits + 2); |
| + offset >>= (kOpcodeBits + kRsBits + 2); |
| + addr = current_pc + (offset << 2); |
| + int32_t* ptr = reinterpret_cast<int32_t*>(addr); |
| + alu_out = *ptr; |
| + break; |
| + } |
| + case ADDIUPC: |
| + alu_out = current_pc + (se_imm19 << 2); |
| + break; |
| + default: |
| + UNREACHABLE(); |
| + break; |
| + } |
| + break; |
| + } |
| + } |
| + break; |
| + } |
| + } |
| + break; |
| + } |
| default: |
| UNREACHABLE(); |
| } |
| + |
| // ---------- Raise exceptions triggered. |
| SignalExceptions(); |
| @@ -4298,6 +4494,8 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) { |
| addr = rs + se_imm16; |
| WriteD(addr, get_fpu_register_double(ft_reg), instr); |
| break; |
| + case PCREL: |
| + set_register(static_cast<int32_t>(rs_reg), alu_out); |
|
dusmil.imgtec
2015/06/17 14:24:13
Instead of cast, change rs_reg type to be int32_t.
ilija.pavlovic
2015/06/18 05:32:51
Done.
|
| default: |
| break; |
| } |