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:
balazs.kilvady 2015-09-18 04:08:17 -07:00 committed by Commit bot
parent 11c45e6d1e
commit b89eec39a1
5 changed files with 974 additions and 1300 deletions

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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,