}
#endif
+#if 0
void Assembler::vmuls(SRegister sd, SRegister sn, SRegister sm,
Condition cond) {
EmitVFPsss(cond, B21, sd, sn, sm);
Condition cond) {
EmitVFPddd(cond, B21, dd, dn, dm);
}
-
+#endif
void Assembler::vmlas(SRegister sd, SRegister sn, SRegister sm,
Condition cond) {
#endif
void vsubqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm);
void vsubqs(QRegister qd, QRegister qn, QRegister qm);
+#if 0
+ // Moved to Arm32::AssemblerARM32::vmuls()
void vmuls(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
+ // Moved to Arm32::AssemblerARM32::vmuld()
void vmuld(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
+#endif
void vmulqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm);
void vmulqs(QRegister qd, QRegister qn, QRegister qm);
void vshlqi(OperandSize sz, QRegister qd, QRegister qm, QRegister qn);
emitVFPddd(Cond, VdivdOpcode, Dd, Dn, Dm);
}
+void AssemblerARM32::vmuls(const Operand *OpSd, const Operand *OpSn,
+ const Operand *OpSm, CondARM32::Cond Cond) {
+ // VMUL (floating-point) - ARM section A8.8.351, encoding A2:
+ // vmul<c>.f32 <Sd>, <Sn>, <Sm>
+ //
+ // cccc11100D10nnnndddd101sN0M0mmmm where cccc=Cond, s=0, ddddD=Rd, nnnnN=Rn,
+ // and mmmmM=Rm.
+ constexpr const char *Vmuls = "vmuls";
+ IValueT Sd = encodeSRegister(OpSd, "Sd", Vmuls);
+ IValueT Sn = encodeSRegister(OpSn, "Sn", Vmuls);
+ IValueT Sm = encodeSRegister(OpSm, "Sm", Vmuls);
+ constexpr IValueT VmulsOpcode = B21;
+ emitVFPsss(Cond, VmulsOpcode, Sd, Sn, Sm);
+}
+
+void AssemblerARM32::vmuld(const Operand *OpDd, const Operand *OpDn,
+ const Operand *OpDm, CondARM32::Cond Cond) {
+ // VMUL (floating-point) - ARM section A8.8.351, encoding A2:
+ // vmul<c>.f64 <Dd>, <Dn>, <Dm>
+ //
+ // cccc11100D10nnnndddd101sN0M0mmmm where cccc=Cond, s=1, Ddddd=Rd, Nnnnn=Rn,
+ // and Mmmmm=Rm.
+ constexpr const char *Vmuld = "vmuld";
+ IValueT Dd = encodeDRegister(OpDd, "Dd", Vmuld);
+ IValueT Dn = encodeDRegister(OpDn, "Dn", Vmuld);
+ IValueT Dm = encodeDRegister(OpDm, "Dm", Vmuld);
+ constexpr IValueT VmuldOpcode = B21;
+ emitVFPddd(Cond, VmuldOpcode, Dd, Dn, Dm);
+}
+
void AssemblerARM32::vsubs(const Operand *OpSd, const Operand *OpSn,
const Operand *OpSm, CondARM32::Cond Cond) {
// VSUB (floating-point) - ARM section A8.8.415, encoding A2:
void vdivs(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
CondARM32::Cond Cond);
+ void vmuld(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
+ CondARM32::Cond Cond);
+
+ void vmuls(const Operand *OpSd, const Operand *OpSn, const Operand *OpSm,
+ CondARM32::Cond Cond);
+
void vpop(const Variable *OpBaseReg, SizeT NumConsecRegs,
CondARM32::Cond Cond);
assert(!Asm->needsTextFixup());
}
+template <> void InstARM32Vmul::emitIAS(const Cfg *Func) const {
+ auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
+ const Variable *Dest = getDest();
+ switch (Dest->getType()) {
+ default:
+ // TODO(kschimpf) Figure if more cases are needed.
+ Asm->setNeedsTextFixup();
+ break;
+ case IceType_f32:
+ Asm->vmuls(getDest(), getSrc(0), getSrc(1), CondARM32::AL);
+ break;
+ case IceType_f64:
+ Asm->vmuld(getDest(), getSrc(0), getSrc(1), CondARM32::AL);
+ break;
+ }
+ assert(!Asm->needsTextFixup());
+}
+
InstARM32Call::InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget)
: InstARM32(Func, InstARM32::Call, 1, Dest) {
HasSideEffects = true;
--- /dev/null
+; Show that we know how to translate vmul.
+
+; NOTE: We use -O2 to get rid of memory stores.
+
+; REQUIRES: allow_dump
+
+; Compile using standalone assembler.
+; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -O2 \
+; RUN: | FileCheck %s --check-prefix=ASM
+
+; Show bytes in assembled standalone code.
+; RUN: %p2i --filetype=asm -i %s --target=arm32 --assemble --disassemble \
+; RUN: --args -O2 | FileCheck %s --check-prefix=DIS
+
+; Compile using integrated assembler.
+; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -O2 \
+; RUN: | FileCheck %s --check-prefix=IASM
+
+; Show bytes in assembled integrated code.
+; RUN: %p2i --filetype=iasm -i %s --target=arm32 --assemble --disassemble \
+; RUN: --args -O2 | FileCheck %s --check-prefix=DIS
+
+define internal float @testVmulFloat(float %a, float %b) {
+; ASM-LABEL: testVmulFloat:
+; DIS-LABEL: 00000000 <testVmulFloat>:
+; IASM-LABEL: testVmulFloat:
+
+entry:
+; ASM-NEXT: .LtestVmulFloat$entry:
+; IASM-NEXT: .LtestVmulFloat$entry:
+
+ %mul = fmul float %a, %b
+
+; ASM-NEXT: vmul.f32 s0, s0, s1
+; DIS-NEXT: 0: ee200a20
+; IASM-NEXT: .byte 0x20
+; IASM-NEXT: .byte 0xa
+; IASM-NEXT: .byte 0x20
+; IASM-NEXT: .byte 0xee
+
+ ret float %mul
+}
+
+define internal double @testVmulDouble(double %a, double %b) {
+; ASM-LABEL: testVmulDouble:
+; DIS-LABEL: 00000010 <testVmulDouble>:
+; IASM-LABEL: testVmulDouble:
+
+entry:
+; ASM-NEXT: .LtestVmulDouble$entry:
+; IASM-NEXT: .LtestVmulDouble$entry:
+
+ %mul = fmul double %a, %b
+
+; ASM-NEXT: vmul.f64 d0, d0, d1
+; DIS-NEXT: 10: ee200b01
+; IASM-NEXT: .byte 0x1
+; IASM-NEXT: .byte 0xb
+; IASM-NEXT: .byte 0x20
+; IASM-NEXT: .byte 0xee
+
+ ret double %mul
+}