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 {
}
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 v8
......
......@@ -820,6 +820,7 @@ const Instr rtCallRedirInstr = SPECIAL | BREAK | call_rt_redirected << 6;
// A nop instruction. (Encoding of sll 0 0 0).
const Instr nopInstr = 0;
class Instruction {
public:
enum {
......@@ -858,9 +859,57 @@ class Instruction {
kUnsupported = -1
};
// Get the encoding type of the instruction.
Type InstructionType() const;
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(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.
inline Opcode OpcodeValue() const {
......@@ -1044,6 +1093,91 @@ const int kBArgsSlotsSize = 0 * 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
#endif // #ifndef V8_MIPS_CONSTANTS_H_
This diff is collapsed.
......@@ -293,56 +293,51 @@ class Simulator {
// Executing is handled based on the instruction type.
void DecodeTypeRegister(Instruction* instr);
// Called from DecodeTypeRegisterCOP1
void DecodeTypeRegisterDRsType(Instruction* instr, const int32_t& fr_reg,
const int32_t& fs_reg, const int32_t& ft_reg,
const int32_t& fd_reg);
void DecodeTypeRegisterWRsType(Instruction* instr, int32_t& alu_out,
const int32_t& fd_reg, const int32_t& fs_reg,
const int32_t& ft_reg);
void DecodeTypeRegisterSRsType(Instruction* instr, const int32_t& ft_reg,
const int32_t& fs_reg, const int32_t& fd_reg);
void DecodeTypeRegisterLRsType(Instruction* instr, const int32_t& ft_reg,
const int32_t& fs_reg, const int32_t& fd_reg);
// Functions called from DeocodeTypeRegister
void DecodeTypeRegisterCOP1(
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,
const uint32_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& i64hilo, uint64_t& u64hilo, int32_t& alu_out, bool& do_interrupt,
int32_t& current_pc, int32_t& next_pc, int32_t& return_addr_reg);
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 DecodeTypeRegisterSPECIAL(
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,
const uint32_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& i64hilo, uint64_t& u64hilo, int32_t& alu_out, bool& do_interrupt,
int32_t& current_pc, int32_t& next_pc, int32_t& return_addr_reg);
void DecodeTypeRegisterSPECIAL2(Instruction* instr, const int32_t& rd_reg,
int32_t& alu_out);
void DecodeTypeRegisterSPECIAL3(Instruction* instr, const int32_t& rt_reg,
const int32_t& rd_reg, int32_t& alu_out);
// Helper function for DecodeTypeRegister.
void ConfigureTypeRegister(Instruction* instr,
int32_t* alu_out,
int64_t* i64hilo,
uint64_t* u64hilo,
int32_t* next_pc,
int32_t* return_addr_reg,
bool* do_interrupt);
// Functions called from DecodeTypeRegister.
void DecodeTypeRegisterCOP1();
void DecodeTypeRegisterCOP1X();
void DecodeTypeRegisterSPECIAL();
void DecodeTypeRegisterSPECIAL2();
void DecodeTypeRegisterSPECIAL3();
// Called from DecodeTypeRegisterCOP1.
void DecodeTypeRegisterSRsType();
void DecodeTypeRegisterDRsType();
void DecodeTypeRegisterWRsType();
void DecodeTypeRegisterLRsType();
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 int32_t rs() const { return get_register(rs_reg()); }
inline uint32_t rs_u() const {
return static_cast<uint32_t>(get_register(rs_reg()));
}
inline int32_t rt_reg() const { return currentInstr_->RtValue(); }
inline int32_t rt() const { return get_register(rt_reg()); }
inline uint32_t rt_u() const {
return static_cast<uint32_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(int32_t rd_reg, int32_t alu_out) {
set_register(rd_reg, alu_out);
TraceRegWr(alu_out);
}
void DecodeTypeImmediate(Instruction* instr);
void DecodeTypeJump(Instruction* instr);
......@@ -394,10 +389,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,
......@@ -424,7 +418,7 @@ class Simulator {
static const size_t stack_size_ = 1 * 1024*1024;
char* stack_;
bool pc_modified_;
int icount_;
uint64_t icount_;
int break_count_;
// 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