| Index: src/arm/simulator-arm.cc
|
| diff --git a/src/arm/simulator-arm.cc b/src/arm/simulator-arm.cc
|
| index 8f7c1e8bb2b740e7884c6ae52c6b867681c9e125..1f64d2bfa9f7e33eadd6940dce456e8bb9b40817 100644
|
| --- a/src/arm/simulator-arm.cc
|
| +++ b/src/arm/simulator-arm.cc
|
| @@ -2885,6 +2885,7 @@ void Simulator::DecodeType7(Instruction* instr) {
|
| // vcvt: Dd = Sm
|
| // vcvt: Sd = Dm
|
| // vcvt.f64.s32 Dd, Dd, #<fbits>
|
| +// vcvt.u32.f64 Dd, Dd, #<fbits>
|
| // Dd = vabs(Dm)
|
| // Dd = vneg(Dm)
|
| // Dd = vadd(Dn, Dm)
|
| @@ -2933,13 +2934,10 @@ void Simulator::DecodeTypeVFP(Instruction* instr) {
|
| DecodeVCVTBetweenDoubleAndSingle(instr);
|
| } else if ((instr->Opc2Value() == 0x8) && (instr->Opc3Value() & 0x1)) {
|
| DecodeVCVTBetweenFloatingPointAndInteger(instr);
|
| - } else if ((instr->Opc2Value() == 0xA) && (instr->Opc3Value() == 0x3) &&
|
| - (instr->Bit(8) == 1)) {
|
| - // vcvt.f64.s32 Dd, Dd, #<fbits>
|
| - int fraction_bits = 32 - ((instr->Bit(5) << 4) | instr->Bits(3, 0));
|
| - int fixed_value = get_sinteger_from_s_register(vd * 2);
|
| - double divide = 1 << fraction_bits;
|
| - set_d_register_from_double(vd, fixed_value / divide);
|
| + } else if ((instr->Opc2Value() & 0x2) && (instr->Opc2Value() & 0x8) &&
|
| + (instr->Opc3Value() == 0x3) &&
|
| + (instr->Bit(5) || instr->Bits(3, 0))) {
|
| + DecodeVCVTBetweenFloatingPointAndFixedPoint(instr);
|
| } else if (((instr->Opc2Value() >> 1) == 0x6) &&
|
| (instr->Opc3Value() & 0x1)) {
|
| DecodeVCVTBetweenFloatingPointAndInteger(instr);
|
| @@ -3348,6 +3346,78 @@ void Simulator::DecodeVCVTBetweenFloatingPointAndInteger(Instruction* instr) {
|
| }
|
|
|
|
|
| +void Simulator::DecodeVCVTBetweenFloatingPointAndFixedPoint(
|
| + Instruction* instr) {
|
| + ASSERT((instr->Bit(4) == 0) && (instr->Opc1Value() == 0x7));
|
| + ASSERT((instr->Opc2Value() & 0x2) && (instr->Opc2Value() & 0x8));
|
| + ASSERT(instr->Opc3Value() == 0x3);
|
| + ASSERT(instr->Bit(5) || instr->Bits(3, 0));
|
| +
|
| + bool to_integer = (instr->Bit(18) == 1);
|
| + bool unsigned_integer = (instr->Bit(16) == 1);
|
| +
|
| + VFPRegPrecision f_precision = (instr->SzValue() == 1) ? kDoublePrecision
|
| + : kSinglePrecision;
|
| + int fd = instr->VFPDRegValue(f_precision);
|
| + int sd = instr->VFPDRegValue(kSinglePrecision);
|
| +
|
| + int sx = instr->Bit(7);
|
| + int fraction_bits = (sx ? 32 : 16) -
|
| + ((instr->Bits(3, 0) << 1) | instr->Bit(5));
|
| + double mult = 1 << fraction_bits;
|
| +
|
| + if (to_integer) {
|
| + bool double_precision = (f_precision == kDoublePrecision);
|
| + double val = double_precision ? get_double_from_d_register(fd)
|
| + : get_float_from_s_register(fd);
|
| +
|
| + // First check if the value overflows the integer range without
|
| + // multiplication.
|
| + inv_op_vfp_flag_ = get_inv_op_vfp_flag(RZ, val, unsigned_integer);
|
| +
|
| + if (!inv_op_vfp_flag_) {
|
| + // The original value did not overflow the integer range, so we can
|
| + // safely multiply it without fear of double overflow.
|
| + val *= mult;
|
| + // ARM specifies rounding towards zero for float to fixed conversion.
|
| + inv_op_vfp_flag_ = get_inv_op_vfp_flag(RZ, val, unsigned_integer);
|
| + }
|
| +
|
| + int temp = unsigned_integer ? static_cast<uint32_t>(val)
|
| + : static_cast<int32_t>(val);
|
| + if (inv_op_vfp_flag_) {
|
| + temp = VFPConversionSaturate(val, unsigned_integer);
|
| + }
|
| +
|
| + // FIXME: inexact_vfp_flag_ does not model ARM behavior exactly if
|
| + // inv_op_vfp_flag_ is set.
|
| + double abs_diff =
|
| + unsigned_integer ? std::fabs(val - static_cast<uint32_t>(temp))
|
| + : std::fabs(val - temp);
|
| + inexact_vfp_flag_ = (abs_diff != 0);
|
| +
|
| + set_s_register_from_sinteger(sd, temp);
|
| +
|
| + } else {
|
| + int val = get_sinteger_from_s_register(sd);
|
| + if (f_precision == kDoublePrecision) {
|
| + if (unsigned_integer) {
|
| + set_d_register_from_double(fd, static_cast<uint32_t>(val) / mult);
|
| + } else {
|
| + set_d_register_from_double(fd, val / mult);
|
| + }
|
| + } else {
|
| + if (unsigned_integer) {
|
| + set_s_register_from_float(
|
| + fd, static_cast<float>(static_cast<uint32_t>(val) / mult));
|
| + } else {
|
| + set_s_register_from_float(fd, static_cast<float>(val / mult));
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +
|
| // void Simulator::DecodeType6CoprocessorIns(Instruction* instr)
|
| // Decode Type 6 coprocessor instructions.
|
| // Dm = vmov(Rt, Rt2)
|
|
|