| Index: src/mips64/simulator-mips64.cc
 | 
| diff --git a/src/mips64/simulator-mips64.cc b/src/mips64/simulator-mips64.cc
 | 
| index 200a1bc80b0a4e1be0f585fb58eaa50d8e95ef25..5db9927f8204cde1e888309caee48d3ac24cc67a 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();
 | 
| +  int32_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(rs_reg, alu_out);
 | 
|      default:
 | 
|        break;
 | 
|    }
 | 
| 
 |