MIPS64: Optimize simulator.
Port 09f41681ef
Original commit message:
The patch decreases the calls of huge switch instructions making the
DecodeType*() functions to work in one phase and optimizing
Instruction::InstructionType(). Speed gain in release full check is
about 33% (6:13 s -> 4:09 s) and in optdebug full test is about 50%
(12:29 -> 6:17)
BUG=
Review URL: https://codereview.chromium.org/1356693002
Cr-Commit-Position: refs/heads/master@{#30824}
This commit is contained in:
parent
11c45e6d1e
commit
b89eec39a1
@ -219,191 +219,6 @@ bool Instruction::IsTrap() const {
|
||||
}
|
||||
|
||||
|
||||
Instruction::Type Instruction::InstructionType() const {
|
||||
switch (OpcodeFieldRaw()) {
|
||||
case SPECIAL:
|
||||
switch (FunctionFieldRaw()) {
|
||||
case JR:
|
||||
case JALR:
|
||||
case BREAK:
|
||||
case SLL:
|
||||
case DSLL:
|
||||
case DSLL32:
|
||||
case SRL:
|
||||
case DSRL:
|
||||
case DSRL32:
|
||||
case SRA:
|
||||
case DSRA:
|
||||
case DSRA32:
|
||||
case SLLV:
|
||||
case DSLLV:
|
||||
case SRLV:
|
||||
case DSRLV:
|
||||
case SRAV:
|
||||
case DSRAV:
|
||||
case MFHI:
|
||||
case MFLO:
|
||||
case MULT:
|
||||
case DMULT:
|
||||
case MULTU:
|
||||
case DMULTU:
|
||||
case DIV:
|
||||
case DDIV:
|
||||
case DIVU:
|
||||
case DDIVU:
|
||||
case ADD:
|
||||
case DADD:
|
||||
case ADDU:
|
||||
case DADDU:
|
||||
case SUB:
|
||||
case DSUB:
|
||||
case SUBU:
|
||||
case DSUBU:
|
||||
case AND:
|
||||
case OR:
|
||||
case XOR:
|
||||
case NOR:
|
||||
case SLT:
|
||||
case SLTU:
|
||||
case TGE:
|
||||
case TGEU:
|
||||
case TLT:
|
||||
case TLTU:
|
||||
case TEQ:
|
||||
case TNE:
|
||||
case MOVZ:
|
||||
case MOVN:
|
||||
case MOVCI:
|
||||
case SELEQZ_S:
|
||||
case SELNEZ_S:
|
||||
return kRegisterType;
|
||||
default:
|
||||
return kUnsupported;
|
||||
}
|
||||
break;
|
||||
case SPECIAL2:
|
||||
switch (FunctionFieldRaw()) {
|
||||
case MUL:
|
||||
case CLZ:
|
||||
return kRegisterType;
|
||||
default:
|
||||
return kUnsupported;
|
||||
}
|
||||
break;
|
||||
case SPECIAL3:
|
||||
switch (FunctionFieldRaw()) {
|
||||
case INS:
|
||||
case EXT:
|
||||
case DEXT:
|
||||
return kRegisterType;
|
||||
case BSHFL: {
|
||||
int sa = SaFieldRaw() >> kSaShift;
|
||||
switch (sa) {
|
||||
case BITSWAP:
|
||||
return kRegisterType;
|
||||
case WSBH:
|
||||
case SEB:
|
||||
case SEH:
|
||||
return kUnsupported;
|
||||
}
|
||||
sa >>= kBp2Bits;
|
||||
switch (sa) {
|
||||
case ALIGN:
|
||||
return kRegisterType;
|
||||
default:
|
||||
return kUnsupported;
|
||||
}
|
||||
}
|
||||
case DBSHFL: {
|
||||
int sa = SaFieldRaw() >> kSaShift;
|
||||
switch (sa) {
|
||||
case DBITSWAP:
|
||||
return kRegisterType;
|
||||
case DSBH:
|
||||
case DSHD:
|
||||
return kUnsupported;
|
||||
}
|
||||
sa = SaFieldRaw() >> kSaShift;
|
||||
sa >>= kBp3Bits;
|
||||
switch (sa) {
|
||||
case DALIGN:
|
||||
return kRegisterType;
|
||||
default:
|
||||
return kUnsupported;
|
||||
}
|
||||
}
|
||||
default:
|
||||
return kUnsupported;
|
||||
}
|
||||
break;
|
||||
case COP1: // Coprocessor instructions.
|
||||
switch (RsFieldRawNoAssert()) {
|
||||
case BC1: // Branch on coprocessor condition.
|
||||
case BC1EQZ:
|
||||
case BC1NEZ:
|
||||
return kImmediateType;
|
||||
default:
|
||||
return kRegisterType;
|
||||
}
|
||||
break;
|
||||
case COP1X:
|
||||
return kRegisterType;
|
||||
// 16 bits Immediate type instructions. e.g.: addi dest, src, imm16.
|
||||
case REGIMM:
|
||||
case BEQ:
|
||||
case BNE:
|
||||
case BLEZ:
|
||||
case BGTZ:
|
||||
case ADDI:
|
||||
case DADDI:
|
||||
case ADDIU:
|
||||
case DADDIU:
|
||||
case SLTI:
|
||||
case SLTIU:
|
||||
case ANDI:
|
||||
case ORI:
|
||||
case XORI:
|
||||
case LUI:
|
||||
case BEQL:
|
||||
case BNEL:
|
||||
case BLEZL:
|
||||
case BGTZL:
|
||||
case POP66:
|
||||
case POP76:
|
||||
case LB:
|
||||
case LH:
|
||||
case LWL:
|
||||
case LW:
|
||||
case LWU:
|
||||
case LD:
|
||||
case LBU:
|
||||
case LHU:
|
||||
case LWR:
|
||||
case SB:
|
||||
case SH:
|
||||
case SWL:
|
||||
case SW:
|
||||
case SD:
|
||||
case SWR:
|
||||
case LWC1:
|
||||
case LDC1:
|
||||
case SWC1:
|
||||
case SDC1:
|
||||
case PCREL:
|
||||
case BC:
|
||||
case BALC:
|
||||
return kImmediateType;
|
||||
// 26 bits immediate type instructions. e.g.: j imm26.
|
||||
case J:
|
||||
case JAL:
|
||||
return kJumpType;
|
||||
default:
|
||||
return kUnsupported;
|
||||
}
|
||||
return kUnsupported;
|
||||
}
|
||||
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
|
@ -888,8 +888,67 @@ class Instruction {
|
||||
kUnsupported = -1
|
||||
};
|
||||
|
||||
enum TypeChecks { NORMAL, EXTRA };
|
||||
|
||||
|
||||
#define OpcodeToBitNumber(opcode) \
|
||||
(1ULL << (static_cast<uint32_t>(opcode) >> kOpcodeShift))
|
||||
|
||||
static const uint64_t kOpcodeImmediateTypeMask =
|
||||
OpcodeToBitNumber(REGIMM) | OpcodeToBitNumber(BEQ) |
|
||||
OpcodeToBitNumber(BNE) | OpcodeToBitNumber(BLEZ) |
|
||||
OpcodeToBitNumber(BGTZ) | OpcodeToBitNumber(ADDI) |
|
||||
OpcodeToBitNumber(DADDI) | OpcodeToBitNumber(ADDIU) |
|
||||
OpcodeToBitNumber(DADDIU) | OpcodeToBitNumber(SLTI) |
|
||||
OpcodeToBitNumber(SLTIU) | OpcodeToBitNumber(ANDI) |
|
||||
OpcodeToBitNumber(ORI) | OpcodeToBitNumber(XORI) |
|
||||
OpcodeToBitNumber(LUI) | OpcodeToBitNumber(BEQL) |
|
||||
OpcodeToBitNumber(BNEL) | OpcodeToBitNumber(BLEZL) |
|
||||
OpcodeToBitNumber(BGTZL) | OpcodeToBitNumber(POP66) |
|
||||
OpcodeToBitNumber(POP76) | OpcodeToBitNumber(LB) | OpcodeToBitNumber(LH) |
|
||||
OpcodeToBitNumber(LWL) | OpcodeToBitNumber(LW) | OpcodeToBitNumber(LWU) |
|
||||
OpcodeToBitNumber(LD) | OpcodeToBitNumber(LBU) | OpcodeToBitNumber(LHU) |
|
||||
OpcodeToBitNumber(LWR) | OpcodeToBitNumber(SB) | OpcodeToBitNumber(SH) |
|
||||
OpcodeToBitNumber(SWL) | OpcodeToBitNumber(SW) | OpcodeToBitNumber(SD) |
|
||||
OpcodeToBitNumber(SWR) | OpcodeToBitNumber(LWC1) |
|
||||
OpcodeToBitNumber(LDC1) | OpcodeToBitNumber(SWC1) |
|
||||
OpcodeToBitNumber(SDC1) | OpcodeToBitNumber(PCREL) |
|
||||
OpcodeToBitNumber(BC) | OpcodeToBitNumber(BALC);
|
||||
|
||||
#define FunctionFieldToBitNumber(function) (1ULL << function)
|
||||
|
||||
static const uint64_t kFunctionFieldRegisterTypeMask =
|
||||
FunctionFieldToBitNumber(JR) | FunctionFieldToBitNumber(JALR) |
|
||||
FunctionFieldToBitNumber(BREAK) | FunctionFieldToBitNumber(SLL) |
|
||||
FunctionFieldToBitNumber(DSLL) | FunctionFieldToBitNumber(DSLL32) |
|
||||
FunctionFieldToBitNumber(SRL) | FunctionFieldToBitNumber(DSRL) |
|
||||
FunctionFieldToBitNumber(DSRL32) | FunctionFieldToBitNumber(SRA) |
|
||||
FunctionFieldToBitNumber(DSRA) | FunctionFieldToBitNumber(DSRA32) |
|
||||
FunctionFieldToBitNumber(SLLV) | FunctionFieldToBitNumber(DSLLV) |
|
||||
FunctionFieldToBitNumber(SRLV) | FunctionFieldToBitNumber(DSRLV) |
|
||||
FunctionFieldToBitNumber(SRAV) | FunctionFieldToBitNumber(DSRAV) |
|
||||
FunctionFieldToBitNumber(MFHI) | FunctionFieldToBitNumber(MFLO) |
|
||||
FunctionFieldToBitNumber(MULT) | FunctionFieldToBitNumber(DMULT) |
|
||||
FunctionFieldToBitNumber(MULTU) | FunctionFieldToBitNumber(DMULTU) |
|
||||
FunctionFieldToBitNumber(DIV) | FunctionFieldToBitNumber(DDIV) |
|
||||
FunctionFieldToBitNumber(DIVU) | FunctionFieldToBitNumber(DDIVU) |
|
||||
FunctionFieldToBitNumber(ADD) | FunctionFieldToBitNumber(DADD) |
|
||||
FunctionFieldToBitNumber(ADDU) | FunctionFieldToBitNumber(DADDU) |
|
||||
FunctionFieldToBitNumber(SUB) | FunctionFieldToBitNumber(DSUB) |
|
||||
FunctionFieldToBitNumber(SUBU) | FunctionFieldToBitNumber(DSUBU) |
|
||||
FunctionFieldToBitNumber(AND) | FunctionFieldToBitNumber(OR) |
|
||||
FunctionFieldToBitNumber(XOR) | FunctionFieldToBitNumber(NOR) |
|
||||
FunctionFieldToBitNumber(SLT) | FunctionFieldToBitNumber(SLTU) |
|
||||
FunctionFieldToBitNumber(TGE) | FunctionFieldToBitNumber(TGEU) |
|
||||
FunctionFieldToBitNumber(TLT) | FunctionFieldToBitNumber(TLTU) |
|
||||
FunctionFieldToBitNumber(TEQ) | FunctionFieldToBitNumber(TNE) |
|
||||
FunctionFieldToBitNumber(MOVZ) | FunctionFieldToBitNumber(MOVN) |
|
||||
FunctionFieldToBitNumber(MOVCI) | FunctionFieldToBitNumber(SELEQZ_S) |
|
||||
FunctionFieldToBitNumber(SELNEZ_S);
|
||||
|
||||
|
||||
// Get the encoding type of the instruction.
|
||||
Type InstructionType() const;
|
||||
inline Type InstructionType(TypeChecks checks = NORMAL) const;
|
||||
|
||||
|
||||
// Accessors for the different named fields used in the MIPS encoding.
|
||||
@ -1078,6 +1137,111 @@ const int kCArgsSlotsSize = kCArgSlotCount * Instruction::kInstrSize * 2;
|
||||
const int kInvalidStackOffset = -1;
|
||||
const int kBranchReturnOffset = 2 * Instruction::kInstrSize;
|
||||
|
||||
|
||||
Instruction::Type Instruction::InstructionType(TypeChecks checks) const {
|
||||
if (checks == EXTRA) {
|
||||
if (OpcodeToBitNumber(OpcodeFieldRaw()) & kOpcodeImmediateTypeMask) {
|
||||
return kImmediateType;
|
||||
}
|
||||
}
|
||||
switch (OpcodeFieldRaw()) {
|
||||
case SPECIAL:
|
||||
if (checks == EXTRA) {
|
||||
if (FunctionFieldToBitNumber(FunctionFieldRaw()) &
|
||||
kFunctionFieldRegisterTypeMask) {
|
||||
return kRegisterType;
|
||||
} else {
|
||||
return kUnsupported;
|
||||
}
|
||||
} else {
|
||||
return kRegisterType;
|
||||
}
|
||||
break;
|
||||
case SPECIAL2:
|
||||
switch (FunctionFieldRaw()) {
|
||||
case MUL:
|
||||
case CLZ:
|
||||
return kRegisterType;
|
||||
default:
|
||||
return kUnsupported;
|
||||
}
|
||||
break;
|
||||
case SPECIAL3:
|
||||
switch (FunctionFieldRaw()) {
|
||||
case INS:
|
||||
case EXT:
|
||||
case DEXT:
|
||||
return kRegisterType;
|
||||
case BSHFL: {
|
||||
int sa = SaFieldRaw() >> kSaShift;
|
||||
switch (sa) {
|
||||
case BITSWAP:
|
||||
return kRegisterType;
|
||||
case WSBH:
|
||||
case SEB:
|
||||
case SEH:
|
||||
return kUnsupported;
|
||||
}
|
||||
sa >>= kBp2Bits;
|
||||
switch (sa) {
|
||||
case ALIGN:
|
||||
return kRegisterType;
|
||||
default:
|
||||
return kUnsupported;
|
||||
}
|
||||
}
|
||||
case DBSHFL: {
|
||||
int sa = SaFieldRaw() >> kSaShift;
|
||||
switch (sa) {
|
||||
case DBITSWAP:
|
||||
return kRegisterType;
|
||||
case DSBH:
|
||||
case DSHD:
|
||||
return kUnsupported;
|
||||
}
|
||||
sa = SaFieldRaw() >> kSaShift;
|
||||
sa >>= kBp3Bits;
|
||||
switch (sa) {
|
||||
case DALIGN:
|
||||
return kRegisterType;
|
||||
default:
|
||||
return kUnsupported;
|
||||
}
|
||||
}
|
||||
default:
|
||||
return kUnsupported;
|
||||
}
|
||||
break;
|
||||
case COP1: // Coprocessor instructions.
|
||||
switch (RsFieldRawNoAssert()) {
|
||||
case BC1: // Branch on coprocessor condition.
|
||||
case BC1EQZ:
|
||||
case BC1NEZ:
|
||||
return kImmediateType;
|
||||
default:
|
||||
return kRegisterType;
|
||||
}
|
||||
break;
|
||||
case COP1X:
|
||||
return kRegisterType;
|
||||
|
||||
// 26 bits immediate type instructions. e.g.: j imm26.
|
||||
case J:
|
||||
case JAL:
|
||||
return kJumpType;
|
||||
|
||||
default:
|
||||
if (checks == NORMAL) {
|
||||
return kImmediateType;
|
||||
} else {
|
||||
return kUnsupported;
|
||||
}
|
||||
}
|
||||
return kUnsupported;
|
||||
}
|
||||
|
||||
#undef OpcodeToBitNumber
|
||||
#undef FunctionFieldToBitNumber
|
||||
} } // namespace v8::internal
|
||||
|
||||
#endif // #ifndef V8_MIPS_CONSTANTS_H_
|
||||
|
@ -1828,7 +1828,7 @@ int Decoder::InstructionDecode(byte* instr_ptr) {
|
||||
out_buffer_pos_ += SNPrintF(out_buffer_ + out_buffer_pos_,
|
||||
"%08x ",
|
||||
instr->InstructionBits());
|
||||
switch (instr->InstructionType()) {
|
||||
switch (instr->InstructionType(Instruction::TypeChecks::EXTRA)) {
|
||||
case Instruction::kRegisterType: {
|
||||
return DecodeTypeRegister(instr);
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -325,57 +325,54 @@ class Simulator {
|
||||
inline int32_t SetDoubleHIW(double* addr);
|
||||
inline int32_t SetDoubleLOW(double* addr);
|
||||
|
||||
// functions called from DecodeTypeRegister
|
||||
void DecodeTypeRegisterCOP1(Instruction* instr, const int32_t rs_reg,
|
||||
const int64_t rs, const uint64_t rs_u,
|
||||
const int32_t rt_reg, const int64_t rt,
|
||||
const uint64_t rt_u, const int32_t rd_reg,
|
||||
const int32_t fr_reg, const int32_t fs_reg,
|
||||
const int32_t ft_reg, const int32_t fd_reg,
|
||||
int64_t& alu_out);
|
||||
// functions called from DecodeTypeRegister.
|
||||
void DecodeTypeRegisterCOP1();
|
||||
|
||||
void DecodeTypeRegisterCOP1X(Instruction* instr, const int32_t fr_reg,
|
||||
const int32_t fs_reg, const int32_t ft_reg,
|
||||
const int32_t fd_reg);
|
||||
void DecodeTypeRegisterCOP1X();
|
||||
|
||||
void DecodeTypeRegisterSPECIAL(
|
||||
Instruction* instr, const int32_t rs_reg, const int64_t rs,
|
||||
const uint64_t rs_u, const int32_t rt_reg, const int64_t rt,
|
||||
const uint64_t rt_u, const int32_t rd_reg, const int32_t fr_reg,
|
||||
const int32_t fs_reg, const int32_t ft_reg, const int32_t fd_reg,
|
||||
const int64_t i64hilo, const uint64_t u64hilo, const int64_t alu_out,
|
||||
const bool do_interrupt, const int64_t current_pc, const int64_t next_pc,
|
||||
const int32_t return_addr_reg, const int64_t i128resultH,
|
||||
const int64_t i128resultL);
|
||||
void DecodeTypeRegisterSPECIAL();
|
||||
|
||||
|
||||
void DecodeTypeRegisterSPECIAL2(Instruction* instr, const int32_t rd_reg,
|
||||
const int64_t alu_out);
|
||||
void DecodeTypeRegisterSPECIAL2();
|
||||
|
||||
void DecodeTypeRegisterSPECIAL3(Instruction* instr, const int32_t rt_reg,
|
||||
const int32_t rd_reg, const int64_t alu_out);
|
||||
void DecodeTypeRegisterSPECIAL3();
|
||||
|
||||
void DecodeTypeRegisterSRsType(Instruction* instr, const int32_t fs_reg,
|
||||
const int32_t ft_reg, const int32_t fd_reg);
|
||||
void DecodeTypeRegisterSRsType();
|
||||
|
||||
void DecodeTypeRegisterDRsType(Instruction* instr, const int32_t fs_reg,
|
||||
const int32_t ft_reg, const int32_t fd_reg);
|
||||
void DecodeTypeRegisterDRsType();
|
||||
|
||||
void DecodeTypeRegisterWRsType(Instruction* instr, const int32_t fs_reg,
|
||||
const int32_t ft_reg, const int32_t fd_reg,
|
||||
int64_t& alu_out);
|
||||
void DecodeTypeRegisterWRsType();
|
||||
|
||||
void DecodeTypeRegisterLRsType();
|
||||
|
||||
void DecodeTypeRegisterLRsType(Instruction* instr, const int32_t fs_reg,
|
||||
const int32_t fd_reg, const int32_t ft_reg);
|
||||
// Executing is handled based on the instruction type.
|
||||
void DecodeTypeRegister(Instruction* instr);
|
||||
|
||||
// Helper function for DecodeTypeRegister.
|
||||
void ConfigureTypeRegister(Instruction* instr, int64_t* alu_out,
|
||||
int64_t* i64hilo, uint64_t* u64hilo,
|
||||
int64_t* next_pc, int* return_addr_reg,
|
||||
bool* do_interrupt, int64_t* result128H,
|
||||
int64_t* result128L);
|
||||
Instruction* currentInstr_;
|
||||
inline Instruction* get_instr() const { return currentInstr_; }
|
||||
inline void set_instr(Instruction* instr) { currentInstr_ = instr; }
|
||||
|
||||
inline int32_t rs_reg() const { return currentInstr_->RsValue(); }
|
||||
inline int64_t rs() const { return get_register(rs_reg()); }
|
||||
inline uint64_t rs_u() const {
|
||||
return static_cast<uint64_t>(get_register(rs_reg()));
|
||||
}
|
||||
inline int32_t rt_reg() const { return currentInstr_->RtValue(); }
|
||||
inline int64_t rt() const { return get_register(rt_reg()); }
|
||||
inline uint64_t rt_u() const {
|
||||
return static_cast<uint64_t>(get_register(rt_reg()));
|
||||
}
|
||||
inline int32_t rd_reg() const { return currentInstr_->RdValue(); }
|
||||
inline int32_t fr_reg() const { return currentInstr_->FrValue(); }
|
||||
inline int32_t fs_reg() const { return currentInstr_->FsValue(); }
|
||||
inline int32_t ft_reg() const { return currentInstr_->FtValue(); }
|
||||
inline int32_t fd_reg() const { return currentInstr_->FdValue(); }
|
||||
inline int32_t sa() const { return currentInstr_->SaValue(); }
|
||||
|
||||
inline void SetResult(const int32_t rd_reg, const int64_t alu_out) {
|
||||
set_register(rd_reg, alu_out);
|
||||
TraceRegWr(alu_out);
|
||||
}
|
||||
|
||||
void DecodeTypeImmediate(Instruction* instr);
|
||||
void DecodeTypeJump(Instruction* instr);
|
||||
@ -427,10 +424,9 @@ class Simulator {
|
||||
kDivideByZero,
|
||||
kNumExceptions
|
||||
};
|
||||
int16_t exceptions[kNumExceptions];
|
||||
|
||||
// Exceptions.
|
||||
void SignalExceptions();
|
||||
void SignalException(Exception e);
|
||||
|
||||
// Runtime call support.
|
||||
static void* RedirectExternalReference(void* external_function,
|
||||
|
Loading…
Reference in New Issue
Block a user