Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(186)

Unified Diff: src/mips/simulator-mips.cc

Issue 1396133002: MIPS: r6 compact branch optimization. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/mips/simulator-mips.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/mips/simulator-mips.cc
diff --git a/src/mips/simulator-mips.cc b/src/mips/simulator-mips.cc
index e945b0ca5fa1741c58368a348e90f25ad81c899d..e9dd0d32dca5c69b0d8ae19419a580f14a9ec33f 100644
--- a/src/mips/simulator-mips.cc
+++ b/src/mips/simulator-mips.cc
@@ -129,7 +129,7 @@ void MipsDebugger::Stop(Instruction* instr) {
#else // GENERATED_CODE_COVERAGE
-#define UNSUPPORTED() printf("Unsupported instruction.\n");
+#define UNSUPPORTED() printf("Sim: Unsupported instruction.\n");
static void InitializeCoverage() {}
@@ -3736,26 +3736,7 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
}
-// Branch instructions common part.
-#define BranchAndLinkHelper(do_branch) \
- execute_branch_delay_instruction = true; \
- if (do_branch) { \
- next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; \
- set_register(31, current_pc + 2 * Instruction::kInstrSize); \
- } else { \
- next_pc = current_pc + 2 * Instruction::kInstrSize; \
- }
-
-#define BranchHelper(do_branch) \
- execute_branch_delay_instruction = true; \
- if (do_branch) { \
- next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize; \
- } else { \
- next_pc = current_pc + 2 * Instruction::kInstrSize; \
- }
-
-
-// Type 2: instructions using a 16 bytes immediate. (e.g. addi, beq).
+// Type 2: instructions using a 16, 21 or 26 bits immediate. (e.g. beq, beqc).
void Simulator::DecodeTypeImmediate(Instruction* instr) {
// Instruction fields.
Opcode op = instr->OpcodeFieldRaw();
@@ -3765,20 +3746,14 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
int32_t rt_reg = instr->RtValue(); // Destination register.
int32_t rt = get_register(rt_reg);
int16_t imm16 = instr->Imm16Value();
- int32_t imm21 = instr->Imm21Value();
- int32_t imm26 = instr->Imm26Value();
int32_t ft_reg = instr->FtValue(); // Destination register.
- int64_t ft;
// Zero extended immediate.
uint32_t oe_imm16 = 0xffff & imm16;
// Sign extended immediate.
int32_t se_imm16 = imm16;
- int32_t se_imm26 = imm26 | ((imm26 & 0x2000000) ? 0xfc000000 : 0);
- // Get current pc.
- int32_t current_pc = get_pc();
// Next pc.
int32_t next_pc = bad_ra;
@@ -3791,7 +3766,58 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
// Used for memory instructions.
int32_t addr = 0x0;
- // ---------- Configuration (and execution for REGIMM).
+ // Branch instructions common part.
+ auto BranchAndLinkHelper = [this, instr, &next_pc,
+ &execute_branch_delay_instruction](
+ bool do_branch) {
+ execute_branch_delay_instruction = true;
+ int32_t current_pc = get_pc();
+ if (do_branch) {
+ int16_t imm16 = instr->Imm16Value();
+ next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
+ set_register(31, current_pc + 2 * Instruction::kInstrSize);
+ } else {
+ next_pc = current_pc + 2 * Instruction::kInstrSize;
+ }
+ };
+
+ auto BranchHelper = [this, instr, &next_pc,
+ &execute_branch_delay_instruction](bool do_branch) {
+ execute_branch_delay_instruction = true;
+ int32_t current_pc = get_pc();
+ if (do_branch) {
+ int16_t imm16 = instr->Imm16Value();
+ next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
+ } else {
+ next_pc = current_pc + 2 * Instruction::kInstrSize;
+ }
+ };
+
+ auto BranchAndLinkCompactHelper = [this, instr, &next_pc](bool do_branch,
+ int bits) {
+ int32_t current_pc = get_pc();
+ CheckForbiddenSlot(current_pc);
+ if (do_branch) {
+ int32_t imm = instr->ImmValue(bits);
+ imm <<= 32 - bits;
+ imm >>= 32 - bits;
+ next_pc = current_pc + (imm << 2) + Instruction::kInstrSize;
+ set_register(31, current_pc + Instruction::kInstrSize);
+ }
+ };
+
+ auto BranchCompactHelper = [&next_pc, this, instr](bool do_branch, int bits) {
+ int32_t current_pc = get_pc();
+ CheckForbiddenSlot(current_pc);
+ if (do_branch) {
+ int32_t imm = instr->ImmValue(bits);
+ imm <<= 32 - bits;
+ imm >>= 32 - bits;
+ next_pc = get_pc() + (imm << 2) + Instruction::kInstrSize;
+ }
+ };
+
+
switch (op) {
// ------------- COP1. Coprocessor instructions.
case COP1:
@@ -3802,34 +3828,14 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
uint32_t fcsr_cc = get_fcsr_condition_bit(cc);
uint32_t cc_value = test_fcsr_bit(fcsr_cc);
bool do_branch = (instr->FBtrueValue()) ? cc_value : !cc_value;
- execute_branch_delay_instruction = true;
- // Set next_pc.
- if (do_branch) {
- next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
- } else {
- next_pc = current_pc + kBranchReturnOffset;
- }
+ BranchHelper(do_branch);
break;
}
case BC1EQZ:
- ft = get_fpu_register(ft_reg);
- execute_branch_delay_instruction = true;
- // Set next_pc.
- if (!(ft & 0x1)) {
- next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
- } else {
- next_pc = current_pc + kBranchReturnOffset;
- }
+ BranchHelper(!(get_fpu_register(ft_reg) & 0x1));
break;
case BC1NEZ:
- ft = get_fpu_register(ft_reg);
- execute_branch_delay_instruction = true;
- // Set next_pc.
- if (ft & 0x1) {
- next_pc = current_pc + (imm16 << 2) + Instruction::kInstrSize;
- } else {
- next_pc = current_pc + kBranchReturnOffset;
- }
+ BranchHelper(get_fpu_register(ft_reg) & 0x1);
break;
default:
UNREACHABLE();
@@ -3863,54 +3869,158 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
case BNE:
BranchHelper(rs != rt);
break;
- case BLEZ:
- BranchHelper(rs <= 0);
- break;
- case BGTZ:
- BranchHelper(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;
+ case POP06: // BLEZALC, BGEZALC, BGEUC, BLEZ (pre-r6)
+ if (IsMipsArchVariant(kMips32r6)) {
+ if (rt_reg != 0) {
+ if (rs_reg == 0) { // BLEZALC
+ BranchAndLinkCompactHelper(rt <= 0, 16);
+ } else {
+ if (rs_reg == rt_reg) { // BGEZALC
+ BranchAndLinkCompactHelper(rt >= 0, 16);
+ } else { // BGEUC
+ BranchCompactHelper(
+ static_cast<uint32_t>(rs) >= static_cast<uint32_t>(rt), 16);
+ }
+ }
+ } else { // BLEZ
+ BranchHelper(rs <= 0);
+ }
+ } else { // BLEZ
+ BranchHelper(rs <= 0);
+ }
+ break;
+ case POP07: // BGTZALC, BLTZALC, BLTUC, BGTZ (pre-r6)
+ if (IsMipsArchVariant(kMips32r6)) {
+ if (rt_reg != 0) {
+ if (rs_reg == 0) { // BGTZALC
+ BranchAndLinkCompactHelper(rt > 0, 16);
+ } else {
+ if (rt_reg == rs_reg) { // BLTZALC
+ BranchAndLinkCompactHelper(rt < 0, 16);
+ } else { // BLTUC
+ BranchCompactHelper(
+ static_cast<uint32_t>(rs) < static_cast<uint32_t>(rt), 16);
+ }
+ }
+ } else { // BGTZ
+ BranchHelper(rs > 0);
+ }
+ } else { // BGTZ
+ BranchHelper(rs > 0);
+ }
+ break;
+ case POP26: // BLEZC, BGEZC, BGEC/BLEC / BLEZL (pre-r6)
+ if (IsMipsArchVariant(kMips32r6)) {
+ if (rt_reg != 0) {
+ if (rs_reg == 0) { // BLEZC
+ BranchCompactHelper(rt <= 0, 16);
+ } else {
+ if (rs_reg == rt_reg) { // BGEZC
+ BranchCompactHelper(rt >= 0, 16);
+ } else { // BGEC/BLEC
+ BranchCompactHelper(rs >= rt, 16);
+ }
+ }
+ }
+ } else { // BLEZL
+ BranchAndLinkHelper(rs <= 0);
+ }
+ break;
+ case POP27: // BGTZC, BLTZC, BLTC/BGTC / BGTZL (pre-r6)
+ if (IsMipsArchVariant(kMips32r6)) {
+ if (rt_reg != 0) {
+ if (rs_reg == 0) { // BGTZC
+ BranchCompactHelper(rt > 0, 16);
+ } else {
+ if (rs_reg == rt_reg) { // BLTZC
+ BranchCompactHelper(rt < 0, 16);
+ } else { // BLTC/BGTC
+ BranchCompactHelper(rs < rt, 16);
+ }
+ }
+ }
+ } else { // BGTZL
+ BranchAndLinkHelper(rs > 0);
+ }
+ break;
+ case POP66: // BEQZC, JIC
+ if (rs_reg != 0) { // BEQZC
+ BranchCompactHelper(rs == 0, 21);
} else { // JIC
+ CheckForbiddenSlot(get_pc());
next_pc = rt + imm16;
}
break;
- }
- case BC: {
- next_pc = current_pc + 4 + (se_imm26 << 2);
- set_pc(next_pc);
- pc_modified_ = true;
+ case POP76: // BNEZC, JIALC
+ if (rs_reg != 0) { // BNEZC
+ BranchCompactHelper(rs != 0, 21);
+ } else { // JIALC
+ int32_t current_pc = get_pc();
+ CheckForbiddenSlot(current_pc);
+ set_register(31, current_pc + Instruction::kInstrSize);
+ next_pc = rt + imm16;
+ }
break;
- }
- case BALC: {
- set_register(31, current_pc + 4);
- next_pc = current_pc + 4 + (se_imm26 << 2);
- set_pc(next_pc);
- pc_modified_ = true;
+ case BC:
+ BranchCompactHelper(true, 26);
break;
- }
- // ------------- Arithmetic instructions.
- case ADDI:
- if (HaveSameSign(rs, se_imm16)) {
- if (rs > 0) {
- if (rs <= (Registers::kMaxValue - se_imm16)) {
- SignalException(kIntegerOverflow);
+ case BALC:
+ BranchAndLinkCompactHelper(true, 26);
+ break;
+ case POP10: // BOVC, BEQZALC, BEQC / ADDI (pre-r6)
+ if (IsMipsArchVariant(kMips32r6)) {
+ if (rs_reg >= rt_reg) { // BOVC
+ if (HaveSameSign(rs, rt)) {
+ if (rs > 0) {
+ BranchCompactHelper(rs > Registers::kMaxValue - rt, 16);
+ } else if (rs < 0) {
+ BranchCompactHelper(rs < Registers::kMinValue - rt, 16);
+ }
}
- } else if (rs < 0) {
- if (rs >= (Registers::kMinValue - se_imm16)) {
- SignalException(kIntegerUnderflow);
+ } else {
+ if (rs_reg == 0) { // BEQZALC
+ BranchAndLinkCompactHelper(rt == 0, 16);
+ } else { // BEQC
+ BranchCompactHelper(rt == rs, 16);
}
}
+ } else { // ADDI
+ if (HaveSameSign(rs, se_imm16)) {
+ if (rs > 0) {
+ if (rs <= Registers::kMaxValue - se_imm16) {
+ SignalException(kIntegerOverflow);
+ }
+ } else if (rs < 0) {
+ if (rs >= Registers::kMinValue - se_imm16) {
+ SignalException(kIntegerUnderflow);
+ }
+ }
+ }
+ SetResult(rt_reg, rs + se_imm16);
}
- SetResult(rt_reg, rs + se_imm16);
break;
+ case POP30: // BNVC, BNEZALC, BNEC / DADDI (pre-r6)
+ if (IsMipsArchVariant(kMips32r6)) {
+ if (rs_reg >= rt_reg) { // BNVC
+ if (!HaveSameSign(rs, rt) || rs == 0 || rt == 0) {
+ BranchCompactHelper(true, 16);
+ } else {
+ if (rs > 0) {
+ BranchCompactHelper(rs <= Registers::kMaxValue - rt, 16);
+ } else if (rs < 0) {
+ BranchCompactHelper(rs >= Registers::kMinValue - rt, 16);
+ }
+ }
+ } else {
+ if (rs_reg == 0) { // BNEZALC
+ BranchAndLinkCompactHelper(rt != 0, 16);
+ } else { // BNEC
+ BranchCompactHelper(rt != rs, 16);
+ }
+ }
+ }
+ break;
+ // ------------- Arithmetic instructions.
case ADDIU:
SetResult(rt_reg, rs + se_imm16);
break;
@@ -4014,22 +4124,11 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
case SDC1:
WriteD(rs + se_imm16, get_fpu_register_double(ft_reg), instr);
break;
- // ------------- JIALC and BNEZC instructions.
- case POP76: {
- // Next pc.
- next_pc = rt + se_imm16;
- // The instruction after the jump is NOT executed.
- int16_t 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.
+ int32_t imm21 = instr->Imm21Value();
+ int32_t current_pc = get_pc();
uint8_t rt = (imm21 >> kImm16Bits);
switch (rt) {
case ALUIPC:
@@ -4076,7 +4175,7 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
// We don't check for end_sim_pc. First it should not be met as the current
// pc is valid. Secondly a jump should always execute its branch delay slot.
Instruction* branch_delay_instr =
- reinterpret_cast<Instruction*>(current_pc+Instruction::kInstrSize);
+ reinterpret_cast<Instruction*>(get_pc() + Instruction::kInstrSize);
BranchDelayInstructionDecode(branch_delay_instr);
}
@@ -4086,9 +4185,6 @@ void Simulator::DecodeTypeImmediate(Instruction* instr) {
}
}
-#undef BranchHelper
-#undef BranchAndLinkHelper
-
// Type 3: instructions using a 26 bytes immediate. (e.g. j, jal).
void Simulator::DecodeTypeJump(Instruction* instr) {
@@ -4174,7 +4270,7 @@ void Simulator::Execute() {
while (program_counter != end_sim_pc) {
Instruction* instr = reinterpret_cast<Instruction*>(program_counter);
icount_++;
- if (icount_ == ::v8::internal::FLAG_stop_sim_at) {
+ if (icount_ == static_cast<uint64_t>(::v8::internal::FLAG_stop_sim_at)) {
MipsDebugger dbg(this);
dbg.Debug();
} else {
« no previous file with comments | « src/mips/simulator-mips.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698