Index: src/arm/assembler-arm.cc |
diff --git a/src/arm/assembler-arm.cc b/src/arm/assembler-arm.cc |
index b80e23d1498b0cb50b177f308bfdfe4f3e296935..ead66741a1bc736d203b50e343c13417609fe4d9 100644 |
--- a/src/arm/assembler-arm.cc |
+++ b/src/arm/assembler-arm.cc |
@@ -51,6 +51,11 @@ unsigned CpuFeatures::supported_ = 0; |
unsigned CpuFeatures::found_by_runtime_probing_ = 0; |
+ExternalReference ExternalReference::cpu_features() { |
+ ASSERT(CpuFeatures::initialized_); |
+ return ExternalReference(&CpuFeatures::supported_); |
+} |
+ |
// Get the CPU features enabled by the build. For cross compilation the |
// preprocessor symbols CAN_USE_ARMV7_INSTRUCTIONS and CAN_USE_VFP3_INSTRUCTIONS |
// can be defined to enable ARMv7 and VFPv3 instructions when building the |
@@ -66,6 +71,9 @@ static unsigned CpuFeaturesImpliedByCompiler() { |
#ifdef CAN_USE_VFP2_INSTRUCTIONS |
answer |= 1u << VFP2; |
#endif // CAN_USE_VFP2_INSTRUCTIONS |
+#ifdef CAN_USE_VFP32DREGS |
+ answer |= 1u << VFP32DREGS; |
+#endif // CAN_USE_VFP32DREGS |
#ifdef __arm__ |
// If the compiler is allowed to use VFP then we can use VFP too in our code |
@@ -87,7 +95,13 @@ static unsigned CpuFeaturesImpliedByCompiler() { |
const char* DwVfpRegister::AllocationIndexToString(int index) { |
if (CpuFeatures::IsSupported(VFP2)) { |
- ASSERT(index >= 0 && index < kMaxNumAllocatableRegisters); |
+ ASSERT(index >= 0 && index < NumAllocatableRegisters()); |
+ ASSERT(kScratchDoubleReg.code() - kDoubleRegZero.code() == |
+ kNumReservedRegisters - 1); |
+ if (index >= kDoubleRegZero.code()) |
+ index += kNumReservedRegisters; |
+ |
+ // TODO(hans): Maybe this could just use VFPRegisters::Name()? |
const char* const names[] = { |
"d0", |
"d1", |
@@ -103,6 +117,24 @@ const char* DwVfpRegister::AllocationIndexToString(int index) { |
"d11", |
"d12", |
"d13" |
+ "d14", |
+ "d15", |
+ "d16", |
+ "d17", |
+ "d18", |
+ "d19", |
+ "d20", |
+ "d21", |
+ "d22", |
+ "d23", |
+ "d24", |
+ "d25", |
+ "d26", |
+ "d27", |
+ "d28", |
+ "d29", |
+ "d30", |
+ "d31" |
}; |
return names[index]; |
} else { |
@@ -148,6 +180,11 @@ void CpuFeatures::Probe() { |
if (FLAG_enable_movw_movt) { |
supported_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS; |
} |
+ |
+ if (FLAG_enable_32dregs) { |
+ supported_ |= 1u << VFP32DREGS; |
+ } |
+ |
#else // __arm__ |
// Probe for additional features not already known to be available. |
if (!IsSupported(VFP3) && OS::ArmCpuHasFeature(VFP3)) { |
@@ -176,6 +213,10 @@ void CpuFeatures::Probe() { |
found_by_runtime_probing_ |= 1u << MOVW_MOVT_IMMEDIATE_LOADS; |
} |
+ if (!IsSupported(VFP32DREGS) && OS::ArmCpuHasFeature(VFP32DREGS)) { |
+ found_by_runtime_probing_ |= 1u << VFP32DREGS; |
+ } |
+ |
supported_ |= found_by_runtime_probing_; |
#endif |
@@ -1746,19 +1787,21 @@ void Assembler::vldr(const DwVfpRegister dst, |
int offset, |
const Condition cond) { |
// Ddst = MEM(Rbase + offset). |
- // Instruction details available in ARM DDI 0406A, A8-628. |
- // cond(31-28) | 1101(27-24)| U001(23-20) | Rbase(19-16) | |
- // Vdst(15-12) | 1011(11-8) | offset |
+ // Instruction details available in ARM DDI 0406C.b, A8-924. |
+ // cond(31-28) | 1101(27-24)| U(23) | D(22) | 01(21-20) | Rbase(19-16) | |
+ // Vd(15-12) | 1011(11-8) | offset |
ASSERT(CpuFeatures::IsEnabled(VFP2)); |
int u = 1; |
if (offset < 0) { |
offset = -offset; |
u = 0; |
} |
+ int vd, d; |
+ dst.split_code(&vd, &d); |
ASSERT(offset >= 0); |
if ((offset % 4) == 0 && (offset / 4) < 256) { |
- emit(cond | u*B23 | 0xD1*B20 | base.code()*B16 | dst.code()*B12 | |
+ emit(cond | 0xD*B24 | u*B23 | d*B22 | B20 | base.code()*B16 | vd*B12 | |
0xB*B8 | ((offset / 4) & 255)); |
} else { |
// Larger offsets must be handled by computing the correct address |
@@ -1769,7 +1812,7 @@ void Assembler::vldr(const DwVfpRegister dst, |
} else { |
sub(ip, base, Operand(offset)); |
} |
- emit(cond | 0xD1*B20 | ip.code()*B16 | dst.code()*B12 | 0xB*B8); |
+ emit(cond | 0xD*B24 | d*B22 | B20 | ip.code()*B16 | vd*B12 | 0xB*B8); |
} |
} |
@@ -1832,9 +1875,9 @@ void Assembler::vstr(const DwVfpRegister src, |
int offset, |
const Condition cond) { |
// MEM(Rbase + offset) = Dsrc. |
- // Instruction details available in ARM DDI 0406A, A8-786. |
- // cond(31-28) | 1101(27-24)| U000(23-20) | | Rbase(19-16) | |
- // Vsrc(15-12) | 1011(11-8) | (offset/4) |
+ // Instruction details available in ARM DDI 0406C.b, A8-1082. |
+ // cond(31-28) | 1101(27-24)| U(23) | D(22) | 00(21-20) | Rbase(19-16) | |
+ // Vd(15-12) | 1011(11-8) | (offset/4) |
ASSERT(CpuFeatures::IsEnabled(VFP2)); |
int u = 1; |
if (offset < 0) { |
@@ -1842,9 +1885,12 @@ void Assembler::vstr(const DwVfpRegister src, |
u = 0; |
} |
ASSERT(offset >= 0); |
+ int vd, d; |
+ src.split_code(&vd, &d); |
+ |
if ((offset % 4) == 0 && (offset / 4) < 256) { |
- emit(cond | u*B23 | 0xD0*B20 | base.code()*B16 | src.code()*B12 | |
- 0xB*B8 | ((offset / 4) & 255)); |
+ emit(cond | 0xD*B24 | u*B23 | d*B22 | base.code()*B16 | vd*B12 | 0xB*B8 | |
+ ((offset / 4) & 255)); |
} else { |
// Larger offsets must be handled by computing the correct address |
// in the ip register. |
@@ -1854,7 +1900,7 @@ void Assembler::vstr(const DwVfpRegister src, |
} else { |
sub(ip, base, Operand(offset)); |
} |
- emit(cond | 0xD0*B20 | ip.code()*B16 | src.code()*B12 | 0xB*B8); |
+ emit(cond | 0xD*B24 | d*B22 | ip.code()*B16 | vd*B12 | 0xB*B8); |
} |
} |
@@ -1916,9 +1962,9 @@ void Assembler::vldm(BlockAddrMode am, |
DwVfpRegister first, |
DwVfpRegister last, |
Condition cond) { |
- // Instruction details available in ARM DDI 0406A, A8-626. |
+ // Instruction details available in ARM DDI 0406C.b, A8-922. |
// cond(31-28) | 110(27-25)| PUDW1(24-20) | Rbase(19-16) | |
- // first(15-12) | 1010(11-8) | (count * 2) |
+ // first(15-12) | 1011(11-8) | (count * 2) |
ASSERT(CpuFeatures::IsEnabled(VFP2)); |
ASSERT_LE(first.code(), last.code()); |
ASSERT(am == ia || am == ia_w || am == db_w); |
@@ -1938,7 +1984,7 @@ void Assembler::vstm(BlockAddrMode am, |
DwVfpRegister first, |
DwVfpRegister last, |
Condition cond) { |
- // Instruction details available in ARM DDI 0406A, A8-784. |
+ // Instruction details available in ARM DDI 0406C.b, A8-1080. |
// cond(31-28) | 110(27-25)| PUDW0(24-20) | Rbase(19-16) | |
// first(15-12) | 1011(11-8) | (count * 2) |
ASSERT(CpuFeatures::IsEnabled(VFP2)); |
@@ -2058,14 +2104,19 @@ void Assembler::vmov(const DwVfpRegister dst, |
double imm, |
const Register scratch, |
const Condition cond) { |
- // Dd = immediate |
- // Instruction details available in ARM DDI 0406B, A8-640. |
ASSERT(CpuFeatures::IsEnabled(VFP2)); |
uint32_t enc; |
if (CpuFeatures::IsSupported(VFP3) && FitsVMOVDoubleImmediate(imm, &enc)) { |
// The double can be encoded in the instruction. |
- emit(cond | 0xE*B24 | 0xB*B20 | dst.code()*B12 | 0xB*B8 | enc); |
+ // |
+ // Dd = immediate |
+ // Instruction details available in ARM DDI 0406C.b, A8-936. |
+ // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | imm4H(19-16) | |
+ // Vd(15-12) | 101(11-9) | sz=1(8) | imm4L(3-0) |
+ int vd, d; |
+ dst.split_code(&vd, &d); |
+ emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | enc); |
} else if (FLAG_enable_vldr_imm) { |
// TODO(jfb) Temporarily turned off until we have constant blinding or |
// some equivalent mitigation: an attacker can otherwise control |
@@ -2088,20 +2139,31 @@ void Assembler::vmov(const DwVfpRegister dst, |
// Synthesise the double from ARM immediates. |
uint32_t lo, hi; |
DoubleAsTwoUInt32(imm, &lo, &hi); |
- mov(ip, Operand(lo)); |
if (scratch.is(no_reg)) { |
- // Move the low part of the double into the lower of the corresponsing S |
- // registers of D register dst. |
- vmov(dst.low(), ip, cond); |
- |
- // Move the high part of the double into the higher of the corresponsing S |
- // registers of D register dst. |
- mov(ip, Operand(hi)); |
- vmov(dst.high(), ip, cond); |
+ if (dst.code() < 16) { |
+ // Move the low part of the double into the lower of the corresponsing S |
+ // registers of D register dst. |
+ mov(ip, Operand(lo)); |
+ vmov(dst.low(), ip, cond); |
+ |
+ // Move the high part of the double into the higher of the |
+ // corresponsing S registers of D register dst. |
+ mov(ip, Operand(hi)); |
+ vmov(dst.high(), ip, cond); |
+ } else { |
+ // D16-D31 does not have S registers, so move the low and high parts |
+ // directly to the D register using vmov.32. |
+ // Note: This may be slower, so we only do this when we have to. |
+ mov(ip, Operand(lo)); |
+ vmov(dst, 0, ip, cond); |
+ mov(ip, Operand(hi)); |
+ vmov(dst, 1, ip, cond); |
+ } |
} else { |
// Move the low and high parts of the double to a D register in one |
// instruction. |
+ mov(ip, Operand(lo)); |
mov(scratch, Operand(hi)); |
vmov(dst, ip, scratch, cond); |
} |
@@ -2126,10 +2188,33 @@ void Assembler::vmov(const DwVfpRegister dst, |
const DwVfpRegister src, |
const Condition cond) { |
// Dd = Dm |
- // Instruction details available in ARM DDI 0406B, A8-642. |
+ // Instruction details available in ARM DDI 0406C.b, A8-938. |
+ // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) | |
+ // 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0) |
ASSERT(CpuFeatures::IsEnabled(VFP2)); |
- emit(cond | 0xE*B24 | 0xB*B20 | |
- dst.code()*B12 | 0x5*B9 | B8 | B6 | src.code()); |
+ int vd, d; |
+ dst.split_code(&vd, &d); |
+ int vm, m; |
+ src.split_code(&vm, &m); |
+ emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | B6 | m*B5 | |
+ vm); |
+} |
+ |
+ |
+void Assembler::vmov(const DwVfpRegister dst, |
+ int index, |
+ const Register src, |
+ const Condition cond) { |
+ // Dd[index] = Rt |
+ // Instruction details available in ARM DDI 0406C.b, A8-940. |
+ // cond(31-28) | 1110(27-24) | 0(23) | opc1=0index(22-21) | 0(20) | |
+ // Vd(19-16) | Rt(15-12) | 1011(11-8) | D(7) | opc2=00(6-5) | 1(4) | 0000(3-0) |
+ ASSERT(CpuFeatures::IsEnabled(VFP2)); |
+ ASSERT(index == 0 || index == 1); |
+ int vd, d; |
+ dst.split_code(&vd, &d); |
+ emit(cond | 0xE*B24 | index*B21 | vd*B16 | src.code()*B12 | 0xB*B8 | d*B7 | |
+ B4); |
} |
@@ -2138,13 +2223,15 @@ void Assembler::vmov(const DwVfpRegister dst, |
const Register src2, |
const Condition cond) { |
// Dm = <Rt,Rt2>. |
- // Instruction details available in ARM DDI 0406A, A8-646. |
+ // Instruction details available in ARM DDI 0406C.b, A8-948. |
// cond(31-28) | 1100(27-24)| 010(23-21) | op=0(20) | Rt2(19-16) | |
// Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm |
ASSERT(CpuFeatures::IsEnabled(VFP2)); |
ASSERT(!src1.is(pc) && !src2.is(pc)); |
+ int vm, m; |
+ dst.split_code(&vm, &m); |
emit(cond | 0xC*B24 | B22 | src2.code()*B16 | |
- src1.code()*B12 | 0xB*B8 | B4 | dst.code()); |
+ src1.code()*B12 | 0xB*B8 | m*B5 | B4 | vm); |
} |
@@ -2153,13 +2240,15 @@ void Assembler::vmov(const Register dst1, |
const DwVfpRegister src, |
const Condition cond) { |
// <Rt,Rt2> = Dm. |
- // Instruction details available in ARM DDI 0406A, A8-646. |
+ // Instruction details available in ARM DDI 0406C.b, A8-948. |
// cond(31-28) | 1100(27-24)| 010(23-21) | op=1(20) | Rt2(19-16) | |
// Rt(15-12) | 1011(11-8) | 00(7-6) | M(5) | 1(4) | Vm |
ASSERT(CpuFeatures::IsEnabled(VFP2)); |
ASSERT(!dst1.is(pc) && !dst2.is(pc)); |
+ int vm, m; |
+ src.split_code(&vm, &m); |
emit(cond | 0xC*B24 | B22 | B20 | dst2.code()*B16 | |
- dst1.code()*B12 | 0xB*B8 | B4 | src.code()); |
+ dst1.code()*B12 | 0xB*B8 | m*B5 | B4 | vm); |
} |
@@ -2372,18 +2461,33 @@ void Assembler::vcvt_f32_f64(const SwVfpRegister dst, |
void Assembler::vneg(const DwVfpRegister dst, |
const DwVfpRegister src, |
const Condition cond) { |
+ // Instruction details available in ARM DDI 0406C.b, A8-968. |
+ // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0001(19-16) | Vd(15-12) | |
+ // 101(11-9) | sz=1(8) | 0(7) | 1(6) | M(5) | 0(4) | Vm(3-0) |
ASSERT(CpuFeatures::IsEnabled(VFP2)); |
- emit(cond | 0xE*B24 | 0xB*B20 | B16 | dst.code()*B12 | |
- 0x5*B9 | B8 | B6 | src.code()); |
+ int vd, d; |
+ dst.split_code(&vd, &d); |
+ int vm, m; |
+ src.split_code(&vm, &m); |
+ |
+ emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | B6 | |
+ m*B5 | vm); |
} |
void Assembler::vabs(const DwVfpRegister dst, |
const DwVfpRegister src, |
const Condition cond) { |
+ // Instruction details available in ARM DDI 0406C.b, A8-524. |
+ // cond(31-28) | 11101(27-23) | D(22) | 11(21-20) | 0000(19-16) | Vd(15-12) | |
+ // 101(11-9) | sz=1(8) | 1(7) | 1(6) | M(5) | 0(4) | Vm(3-0) |
ASSERT(CpuFeatures::IsEnabled(VFP2)); |
- emit(cond | 0xE*B24 | 0xB*B20 | dst.code()*B12 | |
- 0x5*B9 | B8 | 0x3*B6 | src.code()); |
+ int vd, d; |
+ dst.split_code(&vd, &d); |
+ int vm, m; |
+ src.split_code(&vm, &m); |
+ emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | vd*B12 | 0x5*B9 | B8 | B7 | B6 | |
+ m*B5 | vm); |
} |
@@ -2393,12 +2497,18 @@ void Assembler::vadd(const DwVfpRegister dst, |
const Condition cond) { |
// Dd = vadd(Dn, Dm) double precision floating point addition. |
// Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. |
- // Instruction details available in ARM DDI 0406A, A8-536. |
- // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) | |
- // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0) |
+ // Instruction details available in ARM DDI 0406C.b, A8-830. |
+ // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) | |
+ // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0) |
ASSERT(CpuFeatures::IsEnabled(VFP2)); |
- emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 | |
- dst.code()*B12 | 0x5*B9 | B8 | src2.code()); |
+ int vd, d; |
+ dst.split_code(&vd, &d); |
+ int vn, n; |
+ src1.split_code(&vn, &n); |
+ int vm, m; |
+ src2.split_code(&vm, &m); |
+ emit(cond | 0x1C*B23 | d*B22 | 0x3*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 | |
+ n*B7 | m*B5 | vm); |
} |
@@ -2408,12 +2518,18 @@ void Assembler::vsub(const DwVfpRegister dst, |
const Condition cond) { |
// Dd = vsub(Dn, Dm) double precision floating point subtraction. |
// Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. |
- // Instruction details available in ARM DDI 0406A, A8-784. |
- // cond(31-28) | 11100(27-23)| D=?(22) | 11(21-20) | Vn(19-16) | |
- // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 1(6) | M=?(5) | 0(4) | Vm(3-0) |
+ // Instruction details available in ARM DDI 0406C.b, A8-1086. |
+ // cond(31-28) | 11100(27-23)| D(22) | 11(21-20) | Vn(19-16) | |
+ // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 1(6) | M(5) | 0(4) | Vm(3-0) |
ASSERT(CpuFeatures::IsEnabled(VFP2)); |
- emit(cond | 0xE*B24 | 0x3*B20 | src1.code()*B16 | |
- dst.code()*B12 | 0x5*B9 | B8 | B6 | src2.code()); |
+ int vd, d; |
+ dst.split_code(&vd, &d); |
+ int vn, n; |
+ src1.split_code(&vn, &n); |
+ int vm, m; |
+ src2.split_code(&vm, &m); |
+ emit(cond | 0x1C*B23 | d*B22 | 0x3*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 | |
+ n*B7 | B6 | m*B5 | vm); |
} |
@@ -2423,12 +2539,18 @@ void Assembler::vmul(const DwVfpRegister dst, |
const Condition cond) { |
// Dd = vmul(Dn, Dm) double precision floating point multiplication. |
// Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. |
- // Instruction details available in ARM DDI 0406A, A8-784. |
- // cond(31-28) | 11100(27-23)| D=?(22) | 10(21-20) | Vn(19-16) | |
- // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=0 | 0(6) | M=?(5) | 0(4) | Vm(3-0) |
+ // Instruction details available in ARM DDI 0406C.b, A8-960. |
+ // cond(31-28) | 11100(27-23)| D(22) | 10(21-20) | Vn(19-16) | |
+ // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0) |
ASSERT(CpuFeatures::IsEnabled(VFP2)); |
- emit(cond | 0xE*B24 | 0x2*B20 | src1.code()*B16 | |
- dst.code()*B12 | 0x5*B9 | B8 | src2.code()); |
+ int vd, d; |
+ dst.split_code(&vd, &d); |
+ int vn, n; |
+ src1.split_code(&vn, &n); |
+ int vm, m; |
+ src2.split_code(&vm, &m); |
+ emit(cond | 0x1C*B23 | d*B22 | 0x2*B20 | vn*B16 | vd*B12 | 0x5*B9 | B8 | |
+ n*B7 | m*B5 | vm); |
} |
@@ -2436,13 +2558,17 @@ void Assembler::vmla(const DwVfpRegister dst, |
const DwVfpRegister src1, |
const DwVfpRegister src2, |
const Condition cond) { |
- // Instruction details available in ARM DDI 0406C.b, A8-892. |
- // cond(31-28) | 11100(27-23) | D=?(22) | 00(21-20) | Vn(19-16) | |
- // Vd(15-12) | 101(11-9) | sz(8)=1 | N=?(7) | op(6)=0 | M=?(5) | 0(4) | |
- // Vm(3-0) |
- unsigned x = (cond | 0x1C*B23 | src1.code()*B16 | |
- dst.code()*B12 | 0x5*B9 | B8 | src2.code()); |
- emit(x); |
+ // Instruction details available in ARM DDI 0406C.b, A8-932. |
+ // cond(31-28) | 11100(27-23) | D(22) | 00(21-20) | Vn(19-16) | |
+ // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | op=0(6) | M(5) | 0(4) | Vm(3-0) |
+ int vd, d; |
+ dst.split_code(&vd, &d); |
+ int vn, n; |
+ src1.split_code(&vn, &n); |
+ int vm, m; |
+ src2.split_code(&vm, &m); |
+ emit(cond | 0x1C*B23 | d*B22 | vn*B16 | vd*B12 | 0x5*B9 | B8 | n*B7 | m*B5 | |
+ vm); |
} |
@@ -2452,12 +2578,18 @@ void Assembler::vdiv(const DwVfpRegister dst, |
const Condition cond) { |
// Dd = vdiv(Dn, Dm) double precision floating point division. |
// Dd = D:Vd; Dm=M:Vm; Dn=N:Vm. |
- // Instruction details available in ARM DDI 0406A, A8-584. |
- // cond(31-28) | 11101(27-23)| D=?(22) | 00(21-20) | Vn(19-16) | |
- // Vd(15-12) | 101(11-9) | sz(8)=1 | N(7)=? | 0(6) | M=?(5) | 0(4) | Vm(3-0) |
+ // Instruction details available in ARM DDI 0406C.b, A8-882. |
+ // cond(31-28) | 11101(27-23)| D(22) | 00(21-20) | Vn(19-16) | |
+ // Vd(15-12) | 101(11-9) | sz=1(8) | N(7) | 0(6) | M(5) | 0(4) | Vm(3-0) |
ASSERT(CpuFeatures::IsEnabled(VFP2)); |
- emit(cond | 0xE*B24 | B23 | src1.code()*B16 | |
- dst.code()*B12 | 0x5*B9 | B8 | src2.code()); |
+ int vd, d; |
+ dst.split_code(&vd, &d); |
+ int vn, n; |
+ src1.split_code(&vn, &n); |
+ int vm, m; |
+ src2.split_code(&vm, &m); |
+ emit(cond | 0x1D*B23 | d*B22 | vn*B16 | vd*B12 | 0x5*B9 | B8 | n*B7 | m*B5 | |
+ vm); |
} |
@@ -2465,26 +2597,31 @@ void Assembler::vcmp(const DwVfpRegister src1, |
const DwVfpRegister src2, |
const Condition cond) { |
// vcmp(Dd, Dm) double precision floating point comparison. |
- // Instruction details available in ARM DDI 0406A, A8-570. |
- // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0100 (19-16) | |
- // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=0 | 1(6) | M(5)=? | 0(4) | Vm(3-0) |
+ // Instruction details available in ARM DDI 0406C.b, A8-864. |
+ // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0100(19-16) | |
+ // Vd(15-12) | 101(11-9) | sz=1(8) | E=0(7) | 1(6) | M(5) | 0(4) | Vm(3-0) |
ASSERT(CpuFeatures::IsEnabled(VFP2)); |
- emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 | |
- src1.code()*B12 | 0x5*B9 | B8 | B6 | src2.code()); |
+ int vd, d; |
+ src1.split_code(&vd, &d); |
+ int vm, m; |
+ src2.split_code(&vm, &m); |
+ emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | 0x4*B16 | vd*B12 | 0x5*B9 | B8 | B6 | |
+ m*B5 | vm); |
} |
void Assembler::vcmp(const DwVfpRegister src1, |
const double src2, |
const Condition cond) { |
- // vcmp(Dd, Dm) double precision floating point comparison. |
- // Instruction details available in ARM DDI 0406A, A8-570. |
- // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0101 (19-16) | |
- // Vd(15-12) | 101(11-9) | sz(8)=1 | E(7)=0 | 1(6) | M(5)=? | 0(4) | 0000(3-0) |
+ // vcmp(Dd, #0.0) double precision floating point comparison. |
+ // Instruction details available in ARM DDI 0406C.b, A8-864. |
+ // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0101(19-16) | |
+ // Vd(15-12) | 101(11-9) | sz=1(8) | E=0(7) | 1(6) | 0(5) | 0(4) | 0000(3-0) |
ASSERT(CpuFeatures::IsEnabled(VFP2)); |
ASSERT(src2 == 0.0); |
- emit(cond | 0xE*B24 |B23 | 0x3*B20 | B18 | B16 | |
- src1.code()*B12 | 0x5*B9 | B8 | B6); |
+ int vd, d; |
+ src1.split_code(&vd, &d); |
+ emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | 0x5*B16 | vd*B12 | 0x5*B9 | B8 | B6); |
} |
@@ -2511,11 +2648,16 @@ void Assembler::vmrs(Register dst, Condition cond) { |
void Assembler::vsqrt(const DwVfpRegister dst, |
const DwVfpRegister src, |
const Condition cond) { |
- // cond(31-28) | 11101 (27-23)| D=?(22) | 11 (21-20) | 0001 (19-16) | |
- // Vd(15-12) | 101(11-9) | sz(8)=1 | 11 (7-6) | M(5)=? | 0(4) | Vm(3-0) |
+ // Instruction details available in ARM DDI 0406C.b, A8-1058. |
+ // cond(31-28) | 11101(27-23)| D(22) | 11(21-20) | 0001(19-16) | |
+ // Vd(15-12) | 101(11-9) | sz=1(8) | 11(7-6) | M(5) | 0(4) | Vm(3-0) |
ASSERT(CpuFeatures::IsEnabled(VFP2)); |
- emit(cond | 0xE*B24 | B23 | 0x3*B20 | B16 | |
- dst.code()*B12 | 0x5*B9 | B8 | 3*B6 | src.code()); |
+ int vd, d; |
+ dst.split_code(&vd, &d); |
+ int vm, m; |
+ src.split_code(&vm, &m); |
+ emit(cond | 0x1D*B23 | d*B22 | 0x3*B20 | B16 | vd*B12 | 0x5*B9 | B8 | 0x3*B6 | |
+ m*B5 | vm); |
} |