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

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

Issue 1538943003: PPC: Fix simulator overflow detection for float -> integer conversions. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years 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 | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/ppc/simulator-ppc.cc
diff --git a/src/ppc/simulator-ppc.cc b/src/ppc/simulator-ppc.cc
index b3c8a176ec922bc30716bafd21f4caf0209bee0e..8de58f31aede7b053fd265894abec6f6a8641bd1 100644
--- a/src/ppc/simulator-ppc.cc
+++ b/src/ppc/simulator-ppc.cc
@@ -2908,119 +2908,91 @@ void Simulator::ExecuteExt4(Instruction* instr) {
set_d_register_from_double(frt, frt_val);
return;
}
- case FCTID: {
+ case FCTID:
+ case FCTIDZ: {
int frt = instr->RTValue();
int frb = instr->RBValue();
double frb_val = get_double_from_d_register(frb);
+ int mode = (opcode == FCTIDZ) ? kRoundToZero
+ : (fp_condition_reg_ & kFPRoundingModeMask);
int64_t frt_val;
int64_t one = 1; // work-around gcc
- int64_t kMinLongLong = (one << 63);
- int64_t kMaxLongLong = kMinLongLong - 1;
+ int64_t kMinVal = (one << 63);
+ int64_t kMaxVal = kMinVal - 1;
bool invalid_convert = false;
- if (std::isnan(frb_val) || frb_val < kMinLongLong) {
- frt_val = kMinLongLong;
- invalid_convert = true;
- } else if (frb_val > kMaxLongLong) {
- frt_val = kMaxLongLong;
+ if (std::isnan(frb_val)) {
+ frt_val = kMinVal;
invalid_convert = true;
} else {
- switch (fp_condition_reg_ & kFPRoundingModeMask) {
+ switch (mode) {
case kRoundToZero:
- frt_val = (int64_t)frb_val;
+ frb_val = std::trunc(frb_val);
break;
case kRoundToPlusInf:
- frt_val = (int64_t)std::ceil(frb_val);
+ frb_val = std::ceil(frb_val);
break;
case kRoundToMinusInf:
- frt_val = (int64_t)std::floor(frb_val);
+ frb_val = std::floor(frb_val);
break;
default:
- frt_val = (int64_t)frb_val;
UNIMPLEMENTED(); // Not used by V8.
break;
}
+ if (frb_val < static_cast<double>(kMinVal)) {
+ frt_val = kMinVal;
+ invalid_convert = true;
+ } else if (frb_val >= static_cast<double>(kMaxVal)) {
+ frt_val = kMaxVal;
+ invalid_convert = true;
+ } else {
+ frt_val = (int64_t)frb_val;
+ }
}
set_d_register(frt, frt_val);
if (invalid_convert) SetFPSCR(VXCVI);
return;
}
- case FCTIDZ: {
- int frt = instr->RTValue();
- int frb = instr->RBValue();
- double frb_val = get_double_from_d_register(frb);
- int64_t frt_val;
- int64_t one = 1; // work-around gcc
- int64_t kMinLongLong = (one << 63);
- int64_t kMaxLongLong = kMinLongLong - 1;
- bool invalid_convert = false;
-
- 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: {
+ case FCTIDU:
+ case FCTIDUZ: {
int frt = instr->RTValue();
int frb = instr->RBValue();
double frb_val = get_double_from_d_register(frb);
+ int mode = (opcode == FCTIDUZ)
+ ? kRoundToZero
+ : (fp_condition_reg_ & kFPRoundingModeMask);
uint64_t frt_val;
- uint64_t kMinLongLong = 0;
- uint64_t kMaxLongLong = kMinLongLong - 1;
+ uint64_t kMinVal = 0;
+ uint64_t kMaxVal = kMinVal - 1;
bool invalid_convert = false;
- if (std::isnan(frb_val) || frb_val < kMinLongLong) {
- frt_val = kMinLongLong;
- invalid_convert = true;
- } else if (frb_val > kMaxLongLong) {
- frt_val = kMaxLongLong;
+ if (std::isnan(frb_val)) {
+ frt_val = kMinVal;
invalid_convert = true;
} else {
- switch (fp_condition_reg_ & kFPRoundingModeMask) {
+ switch (mode) {
case kRoundToZero:
- frt_val = (uint64_t)frb_val;
+ frb_val = std::trunc(frb_val);
break;
case kRoundToPlusInf:
- frt_val = (uint64_t)std::ceil(frb_val);
+ frb_val = std::ceil(frb_val);
break;
case kRoundToMinusInf:
- frt_val = (uint64_t)std::floor(frb_val);
+ frb_val = std::floor(frb_val);
break;
default:
- frt_val = (uint64_t)frb_val;
UNIMPLEMENTED(); // Not used by V8.
break;
}
- }
- set_d_register(frt, frt_val);
- if (invalid_convert) SetFPSCR(VXCVI);
- return;
- }
- case FCTIDUZ: {
- int frt = instr->RTValue();
- int frb = instr->RBValue();
- double frb_val = get_double_from_d_register(frb);
- uint64_t frt_val;
- uint64_t kMinLongLong = 0;
- uint64_t kMaxLongLong = kMinLongLong - 1;
- bool invalid_convert = false;
-
- 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;
+ if (frb_val < static_cast<double>(kMinVal)) {
+ frt_val = kMinVal;
+ invalid_convert = true;
+ } else if (frb_val >= static_cast<double>(kMaxVal)) {
+ frt_val = kMaxVal;
+ invalid_convert = true;
+ } else {
+ frt_val = (uint64_t)frb_val;
+ }
}
set_d_register(frt, frt_val);
if (invalid_convert) SetFPSCR(VXCVI);
@@ -3031,40 +3003,44 @@ void Simulator::ExecuteExt4(Instruction* instr) {
int frt = instr->RTValue();
int frb = instr->RBValue();
double frb_val = get_double_from_d_register(frb);
+ int mode = (opcode == FCTIWZ) ? kRoundToZero
+ : (fp_condition_reg_ & kFPRoundingModeMask);
int64_t frt_val;
- if (frb_val > kMaxInt) {
- frt_val = kMaxInt;
- } else if (frb_val < kMinInt) {
- frt_val = kMinInt;
- } else {
- if (opcode == FCTIWZ) {
- frt_val = (int64_t)frb_val;
- } else {
- switch (fp_condition_reg_ & kFPRoundingModeMask) {
- case kRoundToZero:
- frt_val = (int64_t)frb_val;
- break;
- case kRoundToPlusInf:
- frt_val = (int64_t)std::ceil(frb_val);
- break;
- case kRoundToMinusInf:
- frt_val = (int64_t)std::floor(frb_val);
- break;
- case kRoundToNearest:
- frt_val = (int64_t)lround(frb_val);
-
- // Round to even if exactly halfway. (lround rounds up)
- if (std::fabs(static_cast<double>(frt_val) - frb_val) == 0.5 &&
- (frt_val % 2)) {
- frt_val += ((frt_val > 0) ? -1 : 1);
- }
+ int64_t kMinVal = kMinInt;
+ int64_t kMaxVal = kMaxInt;
- break;
- default:
- DCHECK(false);
- frt_val = (int64_t)frb_val;
- break;
+ if (std::isnan(frb_val)) {
+ frt_val = kMinVal;
+ } else {
+ switch (mode) {
+ case kRoundToZero:
+ frb_val = std::trunc(frb_val);
+ break;
+ case kRoundToPlusInf:
+ frb_val = std::ceil(frb_val);
+ break;
+ case kRoundToMinusInf:
+ frb_val = std::floor(frb_val);
+ break;
+ case kRoundToNearest: {
+ double orig = frb_val;
+ frb_val = lround(frb_val);
+ // Round to even if exactly halfway. (lround rounds up)
+ if (std::fabs(frb_val - orig) == 0.5 && ((int64_t)frb_val % 2)) {
+ frb_val += ((frb_val > 0) ? -1.0 : 1.0);
+ }
+ break;
}
+ default:
+ UNIMPLEMENTED(); // Not used by V8.
+ break;
+ }
+ if (frb_val < kMinVal) {
+ frt_val = kMinVal;
+ } else if (frb_val > kMaxVal) {
+ frt_val = kMaxVal;
+ } else {
+ frt_val = (int64_t)frb_val;
}
}
set_d_register(frt, frt_val);
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698