EmitVFPddd(cond, B23 | B21 | B20 | B6, dd, D0, dm);
}
-
+#if 0
+// Moved to Arm32::AssemblerARM32::vmovs()
bool Assembler::vmovs(SRegister sd, float s_imm, Condition cond) {
if (TargetCPUFeatures::arm_version() != ARMv7) {
return false;
return false;
}
-
+// Moved to Arm32::AssemblerARM32::vmovd()
bool Assembler::vmovd(DRegister dd, double d_imm, Condition cond) {
if (TargetCPUFeatures::arm_version() != ARMv7) {
return false;
return false;
}
-#if 0
// Moved to Arm32::AssemblerARM32::vadds()
void Assembler::vadds(SRegister sd, SRegister sn, SRegister sm,
Condition cond) {
void vmovd(DRegister dd, DRegister dm, Condition cond = AL);
void vmovq(QRegister qd, QRegister qm);
+#if 0
// Returns false if the immediate cannot be encoded.
+ // Moved to ARM32::AssemblerARM32::vmovs();
bool vmovs(SRegister sd, float s_imm, Condition cond = AL);
+ // Moved to ARM32::AssemblerARM32::vmovs();
bool vmovd(DRegister dd, double d_imm, Condition cond = AL);
-#if 0
// Moved to ARM32::AssemblerARM32::vldrs()
void vldrs(SRegister sd, Address ad, Condition cond = AL);
// Moved to Arm32::AssemblerARM32::vstrs()
emitInst(Encoding);
}
+void AssemblerARM32::vmovd(const Operand *OpDd,
+ const OperandARM32FlexFpImm *OpFpImm,
+ CondARM32::Cond Cond) {
+ // VMOV (immediate) - ARM section A8.8.339, encoding A2:
+ // vmov<c>.f64 <Dd>, #<imm>
+ //
+ // cccc11101D11xxxxdddd10110000yyyy where cccc=Cond, ddddD=Sn, xxxxyyyy=imm.
+ constexpr const char *Vmovd = "vmovd";
+ IValueT Dd = encodeSRegister(OpDd, "Dd", Vmovd);
+ IValueT Imm8 = OpFpImm->getModifiedImm();
+ assert(Imm8 < (1 << 8));
+ constexpr IValueT VmovsOpcode = B23 | B21 | B20 | B8;
+ IValueT OpcodePlusImm8 = VmovsOpcode | ((Imm8 >> 4) << 16) | (Imm8 & 0xf);
+ constexpr IValueT D0 = 0;
+ emitVFPddd(Cond, OpcodePlusImm8, Dd, D0, D0);
+}
+
+void AssemblerARM32::vmovs(const Operand *OpSd,
+ const OperandARM32FlexFpImm *OpFpImm,
+ CondARM32::Cond Cond) {
+ // VMOV (immediate) - ARM section A8.8.339, encoding A2:
+ // vmov<c>.f32 <Sd>, #<imm>
+ //
+ // cccc11101D11xxxxdddd10100000yyyy where cccc=Cond, ddddD=Sn, xxxxyyyy=imm.
+ constexpr const char *Vmovs = "vmovs";
+ IValueT Sd = encodeSRegister(OpSd, "Sd", Vmovs);
+ IValueT Imm8 = OpFpImm->getModifiedImm();
+ assert(Imm8 < (1 << 8));
+ constexpr IValueT VmovsOpcode = B23 | B21 | B20;
+ IValueT OpcodePlusImm8 = VmovsOpcode | ((Imm8 >> 4) << 16) | (Imm8 & 0xf);
+ constexpr IValueT S0 = 0;
+ emitVFPsss(Cond, OpcodePlusImm8, Sd, S0, S0);
+}
+
void AssemblerARM32::vmovsr(const Operand *OpSn, const Operand *OpRt,
CondARM32::Cond Cond) {
// VMOV (between ARM core register and single-precision register)
vldrs(OpSd, OpAddress, Cond, TInfo);
}
+ void vmovd(const Operand *OpDn, const OperandARM32FlexFpImm *OpFpImm,
+ CondARM32::Cond Cond);
+
+ void vmovs(const Operand *OpSn, const OperandARM32FlexFpImm *OpFpImm,
+ CondARM32::Cond Cond);
+
void vmovsr(const Operand *OpSn, const Operand *OpRt, CondARM32::Cond Cond);
// Uses APSR_nzcv as register
Src0->emit(Func);
}
+void InstARM32Mov::emitIASScalarVFPMove(const Cfg *Func) const {
+ auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
+ Operand *Src0 = getSrc(0);
+ Variable *Dest = getDest();
+ switch (Dest->getType()) {
+ default:
+ assert(false && "Do not know how to emit scalar FP move for type.");
+ return;
+ case IceType_f32:
+ if (const auto *FpImm = llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) {
+ Asm->vmovs(Dest, FpImm, getPredicate());
+ return;
+ }
+ break;
+ case IceType_f64:
+ if (const auto *FpImm = llvm::dyn_cast<OperandARM32FlexFpImm>(Src0)) {
+ Asm->vmovd(Dest, FpImm, getPredicate());
+ return;
+ }
+ break;
+ }
+ // TODO(kschimpf) Handle register to register move.
+ Asm->setNeedsTextFixup();
+ return;
+}
+
void InstARM32Mov::emitIASCoreVFPMove(const Cfg *Func) const {
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
Operand *Src0 = getSrc(0);
}
void InstARM32Mov::emitIASSingleDestSingleSource(const Cfg *Func) const {
- auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
Variable *Dest = getDest();
Operand *Src0 = getSrc(0);
const Type DestTy = Dest->getType();
if (isScalarFloatingType(DestTy))
- return Asm->setNeedsTextFixup();
+ return emitIASScalarVFPMove(Func);
+ auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
if (isVectorType(DestTy))
return Asm->setNeedsTextFixup();
static bool canHoldImm(Operand *C, uint32_t *ModifiedImm);
+ uint32_t getModifiedImm() const { return ModifiedImm; }
+
private:
OperandARM32FlexFpImm(Cfg *Func, Type Ty, uint32_t ModifiedImm);
- uint32_t ModifiedImm;
+ const uint32_t ModifiedImm;
};
/// An operand for representing the 0.0 immediate in vcmp.
void emitSingleDestSingleSource(const Cfg *Func) const;
void emitIASSingleDestSingleSource(const Cfg *Func) const;
+ void emitIASScalarVFPMove(const Cfg *Func) const;
void emitIASCoreVFPMove(const Cfg *Func) const;
Variable *DestHi = nullptr;
--- /dev/null
+; Test moving constants into VPF registers.
+
+; REQUIRES: allow_dump
+
+; Compile using standalone assembler.
+; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -Om1 -reg-use=d21,s20 \
+; RUN: | FileCheck %s --check-prefix=ASM
+
+; Show bytes in assembled standalone code.
+; RUN: %p2i --filetype=asm -i %s --target=arm32 --assemble --disassemble \
+; RUN: --args -Om1 -reg-use=d21,s20 \
+; RUN: | FileCheck %s --check-prefix=DIS
+
+; Compile using integrated assembler.
+; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -Om1 -reg-use=d21,s20 \
+; RUN: | FileCheck %s --check-prefix=IASM
+
+; Show bytes in assembled integrated code.
+; RUN: %p2i --filetype=iasm -i %s --target=arm32 --assemble --disassemble \
+; RUN: --args -Om1 -reg-use=d21,s20 \
+; RUN: | FileCheck %s --check-prefix=DIS
+
+define internal void @testMoveDouble() {
+; ASM-LABEL: testMoveDouble:
+; DIS-LABEL: 00000000 <testMoveDouble>:
+
+entry:
+ store double 1.5, double* undef, align 8
+
+; ASM: vmov.f64 d21, #1.500000e+00
+; DIS: 4: eef75b08
+; IASM-NOT: vmov.f64
+
+ ret void
+}
+
+define internal void @testMoveFloat() {
+; ASM-LABEL: testMoveFloat:
+; DIS-LABEL: 00000010 <testMoveFloat>:
+
+entry:
+ %addr = inttoptr i32 0 to float*
+ store float 1.5, float* %addr, align 4
+
+; ASM: vmov.f32 s20, #1.500000e+00
+; DIS: 18: eeb7aa08
+; IASM-NOT: vmov.f32
+
+ ret void
+}