Index: src/ppc/simulator-ppc.cc |
diff --git a/src/ppc/simulator-ppc.cc b/src/ppc/simulator-ppc.cc |
index f23a61816910fb2d373cce1f213358b55ce9325a..b3c8a176ec922bc30716bafd21f4caf0209bee0e 100644 |
--- a/src/ppc/simulator-ppc.cc |
+++ b/src/ppc/simulator-ppc.cc |
@@ -2916,11 +2916,14 @@ void Simulator::ExecuteExt4(Instruction* instr) { |
int64_t one = 1; // work-around gcc |
int64_t kMinLongLong = (one << 63); |
int64_t kMaxLongLong = kMinLongLong - 1; |
+ bool invalid_convert = false; |
- if (frb_val > kMaxLongLong) { |
- frt_val = kMaxLongLong; |
- } else if (frb_val < kMinLongLong) { |
+ if (std::isnan(frb_val) || frb_val < kMinLongLong) { |
frt_val = kMinLongLong; |
+ invalid_convert = true; |
+ } else if (frb_val > kMaxLongLong) { |
+ frt_val = kMaxLongLong; |
+ invalid_convert = true; |
} else { |
switch (fp_condition_reg_ & kFPRoundingModeMask) { |
case kRoundToZero: |
@@ -2939,6 +2942,7 @@ void Simulator::ExecuteExt4(Instruction* instr) { |
} |
} |
set_d_register(frt, frt_val); |
+ if (invalid_convert) SetFPSCR(VXCVI); |
return; |
} |
case FCTIDZ: { |
@@ -2949,15 +2953,19 @@ void Simulator::ExecuteExt4(Instruction* instr) { |
int64_t one = 1; // work-around gcc |
int64_t kMinLongLong = (one << 63); |
int64_t kMaxLongLong = kMinLongLong - 1; |
+ bool invalid_convert = false; |
- if (frb_val > kMaxLongLong) { |
- frt_val = kMaxLongLong; |
- } else if (frb_val < kMinLongLong) { |
+ if (std::isnan(frb_val) || frb_val < kMinLongLong) { |
frt_val = kMinLongLong; |
+ invalid_convert = true; |
+ } else if (frb_val > kMaxLongLong) { |
+ frt_val = kMaxLongLong; |
+ invalid_convert = true; |
} else { |
frt_val = (int64_t)frb_val; |
} |
set_d_register(frt, frt_val); |
+ if (invalid_convert) SetFPSCR(VXCVI); |
return; |
} |
case FCTIDU: { |
@@ -2967,11 +2975,14 @@ void Simulator::ExecuteExt4(Instruction* instr) { |
uint64_t frt_val; |
uint64_t kMinLongLong = 0; |
uint64_t kMaxLongLong = kMinLongLong - 1; |
+ bool invalid_convert = false; |
- if (frb_val > kMaxLongLong) { |
- frt_val = kMaxLongLong; |
- } else if (frb_val < kMinLongLong) { |
+ if (std::isnan(frb_val) || frb_val < kMinLongLong) { |
frt_val = kMinLongLong; |
+ invalid_convert = true; |
+ } else if (frb_val > kMaxLongLong) { |
+ frt_val = kMaxLongLong; |
+ invalid_convert = true; |
} else { |
switch (fp_condition_reg_ & kFPRoundingModeMask) { |
case kRoundToZero: |
@@ -2990,6 +3001,7 @@ void Simulator::ExecuteExt4(Instruction* instr) { |
} |
} |
set_d_register(frt, frt_val); |
+ if (invalid_convert) SetFPSCR(VXCVI); |
return; |
} |
case FCTIDUZ: { |
@@ -2999,15 +3011,19 @@ void Simulator::ExecuteExt4(Instruction* instr) { |
uint64_t frt_val; |
uint64_t kMinLongLong = 0; |
uint64_t kMaxLongLong = kMinLongLong - 1; |
+ bool invalid_convert = false; |
- if (frb_val > kMaxLongLong) { |
- frt_val = kMaxLongLong; |
- } else if (frb_val < kMinLongLong) { |
+ if (std::isnan(frb_val) || frb_val < kMinLongLong) { |
frt_val = kMinLongLong; |
+ invalid_convert = true; |
+ } else if (frb_val > kMaxLongLong) { |
+ frt_val = kMaxLongLong; |
+ invalid_convert = true; |
} else { |
frt_val = (uint64_t)frb_val; |
} |
set_d_register(frt, frt_val); |
+ if (invalid_convert) SetFPSCR(VXCVI); |
return; |
} |
case FCTIW: |
@@ -3104,6 +3120,43 @@ void Simulator::ExecuteExt4(Instruction* instr) { |
set_d_register(frt, lval); |
return; |
} |
+ case MCRFS: { |
+ int bf = instr->Bits(25, 23); |
+ int bfa = instr->Bits(20, 18); |
+ int cr_shift = (7 - bf) * CRWIDTH; |
+ int fp_shift = (7 - bfa) * CRWIDTH; |
+ int field_val = (fp_condition_reg_ >> fp_shift) & 0xf; |
+ condition_reg_ &= ~(0x0f << cr_shift); |
+ condition_reg_ |= (field_val << cr_shift); |
+ // Clear copied exception bits |
+ switch (bfa) { |
+ case 5: |
+ ClearFPSCR(VXSOFT); |
+ ClearFPSCR(VXSQRT); |
+ ClearFPSCR(VXCVI); |
+ break; |
+ default: |
+ UNIMPLEMENTED(); |
+ break; |
+ } |
+ return; |
+ } |
+ case MTFSB0: { |
+ int bt = instr->Bits(25, 21); |
+ ClearFPSCR(bt); |
+ if (instr->Bit(0)) { // RC bit set |
+ UNIMPLEMENTED(); |
+ } |
+ return; |
+ } |
+ case MTFSB1: { |
+ int bt = instr->Bits(25, 21); |
+ SetFPSCR(bt); |
+ if (instr->Bit(0)) { // RC bit set |
+ UNIMPLEMENTED(); |
+ } |
+ return; |
+ } |
case FABS: { |
int frt = instr->RTValue(); |
int frb = instr->RBValue(); |