Commit 09f41681 authored by balazs.kilvady's avatar balazs.kilvady Committed by Commit bot

MIPS: Optimize simulator.

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/1310883005

Cr-Commit-Position: refs/heads/master@{#30596}
parent 2fe2258c
...@@ -219,151 +219,6 @@ bool Instruction::IsTrap() const { ...@@ -219,151 +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 SRL:
case SRA:
case SLLV:
case SRLV:
case SRAV:
case MFHI:
case MFLO:
case MULT:
case MULTU:
case DIV:
case DIVU:
case ADD:
case ADDU:
case SUB:
case SUBU:
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:
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;
}
}
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 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 LBU:
case LHU:
case LWR:
case SB:
case SH:
case SWL:
case SW:
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 internal
} // namespace v8 } // namespace v8
......
...@@ -820,6 +820,7 @@ const Instr rtCallRedirInstr = SPECIAL | BREAK | call_rt_redirected << 6; ...@@ -820,6 +820,7 @@ const Instr rtCallRedirInstr = SPECIAL | BREAK | call_rt_redirected << 6;
// A nop instruction. (Encoding of sll 0 0 0). // A nop instruction. (Encoding of sll 0 0 0).
const Instr nopInstr = 0; const Instr nopInstr = 0;
class Instruction { class Instruction {
public: public:
enum { enum {
...@@ -858,9 +859,57 @@ class Instruction { ...@@ -858,9 +859,57 @@ class Instruction {
kUnsupported = -1 kUnsupported = -1
}; };
// Get the encoding type of the instruction. enum TypeChecks { NORMAL, EXTRA };
Type InstructionType() const;
#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(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(LBU) | OpcodeToBitNumber(LHU) |
OpcodeToBitNumber(LWR) | OpcodeToBitNumber(SB) | OpcodeToBitNumber(SH) |
OpcodeToBitNumber(SWL) | OpcodeToBitNumber(SW) | 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(SRL) | FunctionFieldToBitNumber(SRA) |
FunctionFieldToBitNumber(SLLV) | FunctionFieldToBitNumber(SRLV) |
FunctionFieldToBitNumber(SRAV) | FunctionFieldToBitNumber(MFHI) |
FunctionFieldToBitNumber(MFLO) | FunctionFieldToBitNumber(MULT) |
FunctionFieldToBitNumber(MULTU) | FunctionFieldToBitNumber(DIV) |
FunctionFieldToBitNumber(DIVU) | FunctionFieldToBitNumber(ADD) |
FunctionFieldToBitNumber(ADDU) | FunctionFieldToBitNumber(SUB) |
FunctionFieldToBitNumber(SUBU) | 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.
inline Type InstructionType(TypeChecks checks = NORMAL) const;
// Accessors for the different named fields used in the MIPS encoding. // Accessors for the different named fields used in the MIPS encoding.
inline Opcode OpcodeValue() const { inline Opcode OpcodeValue() const {
...@@ -1044,6 +1093,91 @@ const int kBArgsSlotsSize = 0 * Instruction::kInstrSize; ...@@ -1044,6 +1093,91 @@ const int kBArgsSlotsSize = 0 * Instruction::kInstrSize;
const int kBranchReturnOffset = 2 * Instruction::kInstrSize; 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:
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;
}
}
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;
}
}
}
#undef OpcodeToBitNumber
#undef FunctionFieldToBitNumber
} } // namespace v8::internal } } // namespace v8::internal
#endif // #ifndef V8_MIPS_CONSTANTS_H_ #endif // #ifndef V8_MIPS_CONSTANTS_H_
This diff is collapsed.
...@@ -293,56 +293,51 @@ class Simulator { ...@@ -293,56 +293,51 @@ class Simulator {
// Executing is handled based on the instruction type. // Executing is handled based on the instruction type.
void DecodeTypeRegister(Instruction* instr); void DecodeTypeRegister(Instruction* instr);
// Called from DecodeTypeRegisterCOP1 // Functions called from DecodeTypeRegister.
void DecodeTypeRegisterDRsType(Instruction* instr, const int32_t& fr_reg, void DecodeTypeRegisterCOP1();
const int32_t& fs_reg, const int32_t& ft_reg,
const int32_t& fd_reg); void DecodeTypeRegisterCOP1X();
void DecodeTypeRegisterWRsType(Instruction* instr, int32_t& alu_out,
const int32_t& fd_reg, const int32_t& fs_reg, void DecodeTypeRegisterSPECIAL();
const int32_t& ft_reg);
void DecodeTypeRegisterSRsType(Instruction* instr, const int32_t& ft_reg, void DecodeTypeRegisterSPECIAL2();
const int32_t& fs_reg, const int32_t& fd_reg);
void DecodeTypeRegisterLRsType(Instruction* instr, const int32_t& ft_reg, void DecodeTypeRegisterSPECIAL3();
const int32_t& fs_reg, const int32_t& fd_reg);
// Called from DecodeTypeRegisterCOP1.
// Functions called from DeocodeTypeRegister void DecodeTypeRegisterSRsType();
void DecodeTypeRegisterCOP1(
Instruction* instr, const int32_t& rs_reg, const int32_t& rs, void DecodeTypeRegisterDRsType();
const uint32_t& rs_u, const int32_t& rt_reg, const int32_t& rt,
const uint32_t& rt_u, const int32_t& rd_reg, const int32_t& fr_reg, void DecodeTypeRegisterWRsType();
const int32_t& fs_reg, const int32_t& ft_reg, const int32_t& fd_reg,
int64_t& i64hilo, uint64_t& u64hilo, int32_t& alu_out, bool& do_interrupt, void DecodeTypeRegisterLRsType();
int32_t& current_pc, int32_t& next_pc, int32_t& return_addr_reg);
Instruction* currentInstr_;
inline Instruction* get_instr() const { return currentInstr_; }
void DecodeTypeRegisterCOP1X(Instruction* instr, const int32_t& fr_reg, inline void set_instr(Instruction* instr) { currentInstr_ = instr; }
const int32_t& fs_reg, const int32_t& ft_reg,
const int32_t& fd_reg); inline int32_t rs_reg() const { return currentInstr_->RsValue(); }
inline int32_t rs() const { return get_register(rs_reg()); }
inline uint32_t rs_u() const {
void DecodeTypeRegisterSPECIAL( return static_cast<uint32_t>(get_register(rs_reg()));
Instruction* instr, const int32_t& rs_reg, const int32_t& rs, }
const uint32_t& rs_u, const int32_t& rt_reg, const int32_t& rt, inline int32_t rt_reg() const { return currentInstr_->RtValue(); }
const uint32_t& rt_u, const int32_t& rd_reg, const int32_t& fr_reg, inline int32_t rt() const { return get_register(rt_reg()); }
const int32_t& fs_reg, const int32_t& ft_reg, const int32_t& fd_reg, inline uint32_t rt_u() const {
int64_t& i64hilo, uint64_t& u64hilo, int32_t& alu_out, bool& do_interrupt, return static_cast<uint32_t>(get_register(rt_reg()));
int32_t& current_pc, int32_t& next_pc, int32_t& return_addr_reg); }
inline int32_t rd_reg() const { return currentInstr_->RdValue(); }
inline int32_t fr_reg() const { return currentInstr_->FrValue(); }
void DecodeTypeRegisterSPECIAL2(Instruction* instr, const int32_t& rd_reg, inline int32_t fs_reg() const { return currentInstr_->FsValue(); }
int32_t& alu_out); inline int32_t ft_reg() const { return currentInstr_->FtValue(); }
inline int32_t fd_reg() const { return currentInstr_->FdValue(); }
void DecodeTypeRegisterSPECIAL3(Instruction* instr, const int32_t& rt_reg, inline int32_t sa() const { return currentInstr_->SaValue(); }
const int32_t& rd_reg, int32_t& alu_out);
inline void SetResult(int32_t rd_reg, int32_t alu_out) {
// Helper function for DecodeTypeRegister. set_register(rd_reg, alu_out);
void ConfigureTypeRegister(Instruction* instr, TraceRegWr(alu_out);
int32_t* alu_out, }
int64_t* i64hilo,
uint64_t* u64hilo,
int32_t* next_pc,
int32_t* return_addr_reg,
bool* do_interrupt);
void DecodeTypeImmediate(Instruction* instr); void DecodeTypeImmediate(Instruction* instr);
void DecodeTypeJump(Instruction* instr); void DecodeTypeJump(Instruction* instr);
...@@ -394,10 +389,9 @@ class Simulator { ...@@ -394,10 +389,9 @@ class Simulator {
kDivideByZero, kDivideByZero,
kNumExceptions kNumExceptions
}; };
int16_t exceptions[kNumExceptions];
// Exceptions. // Exceptions.
void SignalExceptions(); void SignalException(Exception e);
// Runtime call support. // Runtime call support.
static void* RedirectExternalReference(void* external_function, static void* RedirectExternalReference(void* external_function,
...@@ -424,7 +418,7 @@ class Simulator { ...@@ -424,7 +418,7 @@ class Simulator {
static const size_t stack_size_ = 1 * 1024*1024; static const size_t stack_size_ = 1 * 1024*1024;
char* stack_; char* stack_;
bool pc_modified_; bool pc_modified_;
int icount_; uint64_t icount_;
int break_count_; int break_count_;
// Debugger input. // Debugger input.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment