| Index: src/mips64/simulator-mips64.cc
|
| diff --git a/src/mips64/simulator-mips64.cc b/src/mips64/simulator-mips64.cc
|
| index 4b251f2b2fa037cbcbebe72d658bfde9ec66e18e..64e023dc37ed389f5675ac15ae6e8ecd1fae7c0a 100644
|
| --- a/src/mips64/simulator-mips64.cc
|
| +++ b/src/mips64/simulator-mips64.cc
|
| @@ -2206,6 +2206,8 @@ void Simulator::ConfigureTypeRegister(Instruction* instr,
|
| const uint64_t rt_u = static_cast<uint64_t>(rt);
|
| const int64_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();
|
|
|
| @@ -2519,39 +2521,16 @@ void Simulator::ConfigureTypeRegister(Instruction* instr,
|
| *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 +2542,96 @@ void Simulator::ConfigureTypeRegister(Instruction* instr,
|
| 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 {
|
| + uint32_t rt_hi = rt << (8 * bp2);
|
| + uint32_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 +3913,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 +3993,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 +4033,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);
|
| int64_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 +4051,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 +4175,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 +4335,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 +4493,8 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
|
| addr = rs + se_imm16;
|
| WriteD(addr, get_fpu_register_double(ft_reg), instr);
|
| break;
|
| + case PCREL:
|
| + set_register(rs_reg, alu_out);
|
| default:
|
| break;
|
| }
|
|
|