| Index: src/arm/assembler-arm.cc
 | 
| ===================================================================
 | 
| --- src/arm/assembler-arm.cc	(revision 4136)
 | 
| +++ src/arm/assembler-arm.cc	(working copy)
 | 
| @@ -1313,11 +1313,28 @@
 | 
|    // Vdst(15-12) | 1011(11-8) | offset
 | 
|    ASSERT(CpuFeatures::IsEnabled(VFP3));
 | 
|    ASSERT(offset % 4 == 0);
 | 
| +  ASSERT((offset / 4) < 256);
 | 
|    emit(cond | 0xD9*B20 | base.code()*B16 | dst.code()*B12 |
 | 
|         0xB*B8 | ((offset / 4) & 255));
 | 
|  }
 | 
|  
 | 
|  
 | 
| +void Assembler::vldr(const SwVfpRegister dst,
 | 
| +                     const Register base,
 | 
| +                     int offset,
 | 
| +                     const Condition cond) {
 | 
| +  // Sdst = MEM(Rbase + offset).
 | 
| +  // Instruction details available in ARM DDI 0406A, A8-628.
 | 
| +  // cond(31-28) | 1101(27-24)| 1001(23-20) | Rbase(19-16) |
 | 
| +  // Vdst(15-12) | 1010(11-8) | offset
 | 
| +  ASSERT(CpuFeatures::IsEnabled(VFP3));
 | 
| +  ASSERT(offset % 4 == 0);
 | 
| +  ASSERT((offset / 4) < 256);
 | 
| +  emit(cond | 0xD9*B20 | base.code()*B16 | dst.code()*B12 |
 | 
| +       0xA*B8 | ((offset / 4) & 255));
 | 
| +}
 | 
| +
 | 
| +
 | 
|  void Assembler::vstr(const DwVfpRegister src,
 | 
|                       const Register base,
 | 
|                       int offset,
 | 
| @@ -1328,6 +1345,7 @@
 | 
|    // Vsrc(15-12) | 1011(11-8) | (offset/4)
 | 
|    ASSERT(CpuFeatures::IsEnabled(VFP3));
 | 
|    ASSERT(offset % 4 == 0);
 | 
| +  ASSERT((offset / 4) < 256);
 | 
|    emit(cond | 0xD8*B20 | base.code()*B16 | src.code()*B12 |
 | 
|         0xB*B8 | ((offset / 4) & 255));
 | 
|  }
 | 
| @@ -1391,34 +1409,175 @@
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void Assembler::vcvt(const DwVfpRegister dst,
 | 
| -                     const SwVfpRegister src,
 | 
| -                     const Condition cond) {
 | 
| -  // Dd = Sm (integer in Sm converted to IEEE 64-bit doubles in Dd).
 | 
| -  // Instruction details available in ARM DDI 0406A, A8-576.
 | 
| -  // cond(31-28) | 11101(27-23)| D=?(22) | 11(21-20) | 1(19) | opc2=000(18-16) |
 | 
| -  // Vd(15-12) | 101(11-9) | sz(8)=1 | op(7)=1 | 1(6) | M=?(5) | 0(4) | Vm(3-0)
 | 
| +// Type of data to read from or write to VFP register.
 | 
| +// Used as specifier in generic vcvt instruction.
 | 
| +enum VFPType { S32, U32, F32, F64 };
 | 
| +
 | 
| +
 | 
| +static bool IsSignedVFPType(VFPType type) {
 | 
| +  switch (type) {
 | 
| +    case S32:
 | 
| +      return true;
 | 
| +    case U32:
 | 
| +      return false;
 | 
| +    default:
 | 
| +      UNREACHABLE();
 | 
| +      return false;
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +static bool IsIntegerVFPType(VFPType type) {
 | 
| +  switch (type) {
 | 
| +    case S32:
 | 
| +    case U32:
 | 
| +      return true;
 | 
| +    case F32:
 | 
| +    case F64:
 | 
| +      return false;
 | 
| +    default:
 | 
| +      UNREACHABLE();
 | 
| +      return false;
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +static bool IsDoubleVFPType(VFPType type) {
 | 
| +  switch (type) {
 | 
| +    case F32:
 | 
| +      return false;
 | 
| +    case F64:
 | 
| +      return true;
 | 
| +    default:
 | 
| +      UNREACHABLE();
 | 
| +      return false;
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +// Depending on split_last_bit split binary representation of reg_code into Vm:M
 | 
| +// or M:Vm form (where M is single bit).
 | 
| +static void SplitRegCode(bool split_last_bit,
 | 
| +                         int reg_code,
 | 
| +                         int* vm,
 | 
| +                         int* m) {
 | 
| +  if (split_last_bit) {
 | 
| +    *m  = reg_code & 0x1;
 | 
| +    *vm = reg_code >> 1;
 | 
| +  } else {
 | 
| +    *m  = (reg_code & 0x10) >> 4;
 | 
| +    *vm = reg_code & 0x0F;
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +// Encode vcvt.src_type.dst_type instruction.
 | 
| +static Instr EncodeVCVT(const VFPType dst_type,
 | 
| +                        const int dst_code,
 | 
| +                        const VFPType src_type,
 | 
| +                        const int src_code,
 | 
| +                        const Condition cond) {
 | 
| +  if (IsIntegerVFPType(dst_type) || IsIntegerVFPType(src_type)) {
 | 
| +    // Conversion between IEEE floating point and 32-bit integer.
 | 
| +    // Instruction details available in ARM DDI 0406B, A8.6.295.
 | 
| +    // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 1(19) | opc2(18-16) |
 | 
| +    // Vd(15-12) | 101(11-9) | sz(8) | op(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
 | 
| +    ASSERT(!IsIntegerVFPType(dst_type) || !IsIntegerVFPType(src_type));
 | 
| +
 | 
| +    int sz, opc2, D, Vd, M, Vm, op;
 | 
| +
 | 
| +    if (IsIntegerVFPType(dst_type)) {
 | 
| +      opc2 = IsSignedVFPType(dst_type) ? 0x5 : 0x4;
 | 
| +      sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
 | 
| +      op = 1;  // round towards zero
 | 
| +      SplitRegCode(!IsDoubleVFPType(src_type), src_code, &Vm, &M);
 | 
| +      SplitRegCode(true, dst_code, &Vd, &D);
 | 
| +    } else {
 | 
| +      ASSERT(IsIntegerVFPType(src_type));
 | 
| +
 | 
| +      opc2 = 0x0;
 | 
| +      sz = IsDoubleVFPType(dst_type) ? 0x1 : 0x0;
 | 
| +      op = IsSignedVFPType(src_type) ? 0x1 : 0x0;
 | 
| +      SplitRegCode(true, src_code, &Vm, &M);
 | 
| +      SplitRegCode(!IsDoubleVFPType(dst_type), dst_code, &Vd, &D);
 | 
| +    }
 | 
| +
 | 
| +    return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | B19 | opc2*B16 |
 | 
| +            Vd*B12 | 0x5*B9 | sz*B8 | op*B7 | B6 | M*B5 | Vm);
 | 
| +  } else {
 | 
| +    // Conversion between IEEE double and single precision.
 | 
| +    // Instruction details available in ARM DDI 0406B, A8.6.298.
 | 
| +    // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0111(19-16) |
 | 
| +    // Vd(15-12) | 101(11-9) | sz(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0)
 | 
| +    int sz, D, Vd, M, Vm;
 | 
| +
 | 
| +    ASSERT(IsDoubleVFPType(dst_type) != IsDoubleVFPType(src_type));
 | 
| +    sz = IsDoubleVFPType(src_type) ? 0x1 : 0x0;
 | 
| +    SplitRegCode(IsDoubleVFPType(src_type), dst_code, &Vd, &D);
 | 
| +    SplitRegCode(!IsDoubleVFPType(src_type), src_code, &Vm, &M);
 | 
| +
 | 
| +    return (cond | 0xE*B24 | B23 | D*B22 | 0x3*B20 | 0x7*B16 |
 | 
| +            Vd*B12 | 0x5*B9 | sz*B8 | B7 | B6 | M*B5 | Vm);
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void Assembler::vcvt_f64_s32(const DwVfpRegister dst,
 | 
| +                             const SwVfpRegister src,
 | 
| +                             const Condition cond) {
 | 
|    ASSERT(CpuFeatures::IsEnabled(VFP3));
 | 
| -  emit(cond | 0xE*B24 | B23 | 0x3*B20 | B19 |
 | 
| -       dst.code()*B12 | 0x5*B9 | B8 | B7 | B6 |
 | 
| -       (0x1 & src.code())*B5 | (src.code() >> 1));
 | 
| +  emit(EncodeVCVT(F64, dst.code(), S32, src.code(), cond));
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void Assembler::vcvt(const SwVfpRegister dst,
 | 
| -                     const DwVfpRegister src,
 | 
| -                     const Condition cond) {
 | 
| -  // Sd = Dm (IEEE 64-bit doubles in Dm converted to 32 bit integer in Sd).
 | 
| -  // Instruction details available in ARM DDI 0406A, A8-576.
 | 
| -  // cond(31-28) | 11101(27-23)| D=?(22) | 11(21-20) | 1(19) | opc2=101(18-16)|
 | 
| -  // Vd(15-12) | 101(11-9) | sz(8)=1 | op(7)=? | 1(6) | M=?(5) | 0(4) | Vm(3-0)
 | 
| +void Assembler::vcvt_f32_s32(const SwVfpRegister dst,
 | 
| +                             const SwVfpRegister src,
 | 
| +                             const Condition cond) {
 | 
|    ASSERT(CpuFeatures::IsEnabled(VFP3));
 | 
| -  emit(cond | 0xE*B24 | B23 |(0x1 & dst.code())*B22 |
 | 
| -       0x3*B20 | B19 | 0x5*B16 | (dst.code() >> 1)*B12 |
 | 
| -       0x5*B9 | B8 | B7 | B6 | src.code());
 | 
| +  emit(EncodeVCVT(F32, dst.code(), S32, src.code(), cond));
 | 
|  }
 | 
|  
 | 
|  
 | 
| +void Assembler::vcvt_f64_u32(const DwVfpRegister dst,
 | 
| +                             const SwVfpRegister src,
 | 
| +                             const Condition cond) {
 | 
| +  ASSERT(CpuFeatures::IsEnabled(VFP3));
 | 
| +  emit(EncodeVCVT(F64, dst.code(), U32, src.code(), cond));
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void Assembler::vcvt_s32_f64(const SwVfpRegister dst,
 | 
| +                             const DwVfpRegister src,
 | 
| +                             const Condition cond) {
 | 
| +  ASSERT(CpuFeatures::IsEnabled(VFP3));
 | 
| +  emit(EncodeVCVT(S32, dst.code(), F64, src.code(), cond));
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void Assembler::vcvt_u32_f64(const SwVfpRegister dst,
 | 
| +                             const DwVfpRegister src,
 | 
| +                             const Condition cond) {
 | 
| +  ASSERT(CpuFeatures::IsEnabled(VFP3));
 | 
| +  emit(EncodeVCVT(U32, dst.code(), F64, src.code(), cond));
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void Assembler::vcvt_f64_f32(const DwVfpRegister dst,
 | 
| +                             const SwVfpRegister src,
 | 
| +                             const Condition cond) {
 | 
| +  ASSERT(CpuFeatures::IsEnabled(VFP3));
 | 
| +  emit(EncodeVCVT(F64, dst.code(), F32, src.code(), cond));
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void Assembler::vcvt_f32_f64(const SwVfpRegister dst,
 | 
| +                             const DwVfpRegister src,
 | 
| +                             const Condition cond) {
 | 
| +  ASSERT(CpuFeatures::IsEnabled(VFP3));
 | 
| +  emit(EncodeVCVT(F32, dst.code(), F64, src.code(), cond));
 | 
| +}
 | 
| +
 | 
| +
 | 
|  void Assembler::vadd(const DwVfpRegister dst,
 | 
|                       const DwVfpRegister src1,
 | 
|                       const DwVfpRegister src2,
 | 
| 
 |