Index: src/ppc/simulator-ppc.cc |
diff --git a/src/ppc/simulator-ppc.cc b/src/ppc/simulator-ppc.cc |
index 261982c0b3f0abdb17468710b1a107815bb8c6f9..770d3ec634a669d0d5cf67ba0df7ed2c9750963b 100644 |
--- a/src/ppc/simulator-ppc.cc |
+++ b/src/ppc/simulator-ppc.cc |
@@ -1562,9 +1562,8 @@ void Simulator::SetCR0(intptr_t result, bool setSO) { |
} |
-void Simulator::ExecuteBranchConditional(Instruction* instr) { |
+void Simulator::ExecuteBranchConditional(Instruction* instr, BCType type) { |
int bo = instr->Bits(25, 21) << 21; |
- int offset = (instr->Bits(15, 2) << 18) >> 16; |
int condition_bit = instr->Bits(20, 16); |
int condition_mask = 0x80000000 >> condition_bit; |
switch (bo) { |
@@ -1572,46 +1571,47 @@ void Simulator::ExecuteBranchConditional(Instruction* instr) { |
case DCBEZF: // Decrement CTR; branch if CTR == 0 and condition false |
UNIMPLEMENTED(); |
case BF: { // Branch if condition false |
- if (!(condition_reg_ & condition_mask)) { |
- if (instr->Bit(0) == 1) { // LK flag set |
- special_reg_lr_ = get_pc() + 4; |
- } |
- set_pc(get_pc() + offset); |
- } |
+ if (condition_reg_ & condition_mask) return; |
break; |
} |
case DCBNZT: // Decrement CTR; branch if CTR != 0 and condition true |
case DCBEZT: // Decrement CTR; branch if CTR == 0 and condition true |
UNIMPLEMENTED(); |
case BT: { // Branch if condition true |
- if (condition_reg_ & condition_mask) { |
- if (instr->Bit(0) == 1) { // LK flag set |
- special_reg_lr_ = get_pc() + 4; |
- } |
- set_pc(get_pc() + offset); |
- } |
+ if (!(condition_reg_ & condition_mask)) return; |
break; |
} |
case DCBNZ: // Decrement CTR; branch if CTR != 0 |
case DCBEZ: // Decrement CTR; branch if CTR == 0 |
special_reg_ctr_ -= 1; |
- if ((special_reg_ctr_ == 0) == (bo == DCBEZ)) { |
- if (instr->Bit(0) == 1) { // LK flag set |
- special_reg_lr_ = get_pc() + 4; |
- } |
- set_pc(get_pc() + offset); |
- } |
+ if ((special_reg_ctr_ == 0) != (bo == DCBEZ)) return; |
break; |
case BA: { // Branch always |
- if (instr->Bit(0) == 1) { // LK flag set |
- special_reg_lr_ = get_pc() + 4; |
- } |
- set_pc(get_pc() + offset); |
break; |
} |
default: |
UNIMPLEMENTED(); // Invalid encoding |
} |
+ |
+ intptr_t old_pc = get_pc(); |
+ |
+ switch (type) { |
+ case BC_OFFSET: { |
+ int offset = (instr->Bits(15, 2) << 18) >> 16; |
+ set_pc(old_pc + offset); |
+ break; |
+ } |
+ case BC_LINK_REG: |
+ set_pc(special_reg_lr_); |
+ break; |
+ case BC_CTR_REG: |
+ set_pc(special_reg_ctr_); |
+ break; |
+ } |
+ |
+ if (instr->Bit(0) == 1) { // LK flag set |
+ special_reg_lr_ = old_pc + 4; |
+ } |
} |
@@ -1620,24 +1620,12 @@ void Simulator::ExecuteExt1(Instruction* instr) { |
switch (instr->Bits(10, 1) << 1) { |
case MCRF: |
UNIMPLEMENTED(); // Not used by V8. |
- case BCLRX: { |
- // need to check BO flag |
- intptr_t old_pc = get_pc(); |
- set_pc(special_reg_lr_); |
- if (instr->Bit(0) == 1) { // LK flag set |
- special_reg_lr_ = old_pc + 4; |
- } |
+ case BCLRX: |
+ ExecuteBranchConditional(instr, BC_LINK_REG); |
break; |
- } |
- case BCCTRX: { |
- // need to check BO flag |
- intptr_t old_pc = get_pc(); |
- set_pc(special_reg_ctr_); |
- if (instr->Bit(0) == 1) { // LK flag set |
- special_reg_lr_ = old_pc + 4; |
- } |
+ case BCCTRX: |
+ ExecuteBranchConditional(instr, BC_CTR_REG); |
break; |
- } |
case CRNOR: |
case RFI: |
case CRANDC: |
@@ -3262,7 +3250,7 @@ void Simulator::ExecuteGeneric(Instruction* instr) { |
break; |
} |
case BCX: { |
- ExecuteBranchConditional(instr); |
+ ExecuteBranchConditional(instr, BC_OFFSET); |
break; |
} |
case BX: { |