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, |