Commit c64448fb by Karl Schimpf

Add VMOV(immediate) instructions to the ARM assembler.

Adds the vmovs/vmovd instructions to the integerated ARM assembler. BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4334 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1624383004 .
parent 40c69b43
...@@ -928,7 +928,8 @@ void Assembler::vmovd(DRegister dd, DRegister dm, Condition cond) { ...@@ -928,7 +928,8 @@ void Assembler::vmovd(DRegister dd, DRegister dm, Condition cond) {
EmitVFPddd(cond, B23 | B21 | B20 | B6, dd, D0, dm); 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) { bool Assembler::vmovs(SRegister sd, float s_imm, Condition cond) {
if (TargetCPUFeatures::arm_version() != ARMv7) { if (TargetCPUFeatures::arm_version() != ARMv7) {
return false; return false;
...@@ -946,7 +947,7 @@ bool Assembler::vmovs(SRegister sd, float s_imm, Condition cond) { ...@@ -946,7 +947,7 @@ bool Assembler::vmovs(SRegister sd, float s_imm, Condition cond) {
return false; return false;
} }
// Moved to Arm32::AssemblerARM32::vmovd()
bool Assembler::vmovd(DRegister dd, double d_imm, Condition cond) { bool Assembler::vmovd(DRegister dd, double d_imm, Condition cond) {
if (TargetCPUFeatures::arm_version() != ARMv7) { if (TargetCPUFeatures::arm_version() != ARMv7) {
return false; return false;
...@@ -964,7 +965,6 @@ bool Assembler::vmovd(DRegister dd, double d_imm, Condition cond) { ...@@ -964,7 +965,6 @@ bool Assembler::vmovd(DRegister dd, double d_imm, Condition cond) {
return false; return false;
} }
#if 0
// Moved to Arm32::AssemblerARM32::vadds() // Moved to Arm32::AssemblerARM32::vadds()
void Assembler::vadds(SRegister sd, SRegister sn, SRegister sm, void Assembler::vadds(SRegister sd, SRegister sn, SRegister sm,
Condition cond) { Condition cond) {
......
...@@ -631,11 +631,13 @@ class Assembler : public ValueObject { ...@@ -631,11 +631,13 @@ class Assembler : public ValueObject {
void vmovd(DRegister dd, DRegister dm, Condition cond = AL); void vmovd(DRegister dd, DRegister dm, Condition cond = AL);
void vmovq(QRegister qd, QRegister qm); void vmovq(QRegister qd, QRegister qm);
#if 0
// Returns false if the immediate cannot be encoded. // Returns false if the immediate cannot be encoded.
// Moved to ARM32::AssemblerARM32::vmovs();
bool vmovs(SRegister sd, float s_imm, Condition cond = AL); 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); bool vmovd(DRegister dd, double d_imm, Condition cond = AL);
#if 0
// Moved to ARM32::AssemblerARM32::vldrs() // Moved to ARM32::AssemblerARM32::vldrs()
void vldrs(SRegister sd, Address ad, Condition cond = AL); void vldrs(SRegister sd, Address ad, Condition cond = AL);
// Moved to Arm32::AssemblerARM32::vstrs() // Moved to Arm32::AssemblerARM32::vstrs()
......
...@@ -2390,6 +2390,40 @@ void AssemblerARM32::vldrs(const Operand *OpSd, const Operand *OpAddress, ...@@ -2390,6 +2390,40 @@ void AssemblerARM32::vldrs(const Operand *OpSd, const Operand *OpAddress,
emitInst(Encoding); 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, void AssemblerARM32::vmovsr(const Operand *OpSn, const Operand *OpRt,
CondARM32::Cond Cond) { CondARM32::Cond Cond) {
// VMOV (between ARM core register and single-precision register) // VMOV (between ARM core register and single-precision register)
......
...@@ -382,6 +382,12 @@ public: ...@@ -382,6 +382,12 @@ public:
vldrs(OpSd, OpAddress, Cond, TInfo); 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); void vmovsr(const Operand *OpSn, const Operand *OpRt, CondARM32::Cond Cond);
// Uses APSR_nzcv as register // Uses APSR_nzcv as register
......
...@@ -1125,6 +1125,32 @@ void InstARM32Mov::emitSingleDestSingleSource(const Cfg *Func) const { ...@@ -1125,6 +1125,32 @@ void InstARM32Mov::emitSingleDestSingleSource(const Cfg *Func) const {
Src0->emit(Func); 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 { void InstARM32Mov::emitIASCoreVFPMove(const Cfg *Func) const {
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>(); auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
Operand *Src0 = getSrc(0); Operand *Src0 = getSrc(0);
...@@ -1150,7 +1176,6 @@ void InstARM32Mov::emitIASCoreVFPMove(const Cfg *Func) const { ...@@ -1150,7 +1176,6 @@ void InstARM32Mov::emitIASCoreVFPMove(const Cfg *Func) const {
} }
void InstARM32Mov::emitIASSingleDestSingleSource(const Cfg *Func) const { void InstARM32Mov::emitIASSingleDestSingleSource(const Cfg *Func) const {
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
Variable *Dest = getDest(); Variable *Dest = getDest();
Operand *Src0 = getSrc(0); Operand *Src0 = getSrc(0);
...@@ -1167,8 +1192,9 @@ void InstARM32Mov::emitIASSingleDestSingleSource(const Cfg *Func) const { ...@@ -1167,8 +1192,9 @@ void InstARM32Mov::emitIASSingleDestSingleSource(const Cfg *Func) const {
const Type DestTy = Dest->getType(); const Type DestTy = Dest->getType();
if (isScalarFloatingType(DestTy)) if (isScalarFloatingType(DestTy))
return Asm->setNeedsTextFixup(); return emitIASScalarVFPMove(Func);
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
if (isVectorType(DestTy)) if (isVectorType(DestTy))
return Asm->setNeedsTextFixup(); return Asm->setNeedsTextFixup();
......
...@@ -266,10 +266,12 @@ public: ...@@ -266,10 +266,12 @@ public:
static bool canHoldImm(Operand *C, uint32_t *ModifiedImm); static bool canHoldImm(Operand *C, uint32_t *ModifiedImm);
uint32_t getModifiedImm() const { return ModifiedImm; }
private: private:
OperandARM32FlexFpImm(Cfg *Func, Type Ty, uint32_t ModifiedImm); 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. /// An operand for representing the 0.0 immediate in vcmp.
...@@ -1340,6 +1342,7 @@ private: ...@@ -1340,6 +1342,7 @@ private:
void emitSingleDestSingleSource(const Cfg *Func) const; void emitSingleDestSingleSource(const Cfg *Func) const;
void emitIASSingleDestSingleSource(const Cfg *Func) const; void emitIASSingleDestSingleSource(const Cfg *Func) const;
void emitIASScalarVFPMove(const Cfg *Func) const;
void emitIASCoreVFPMove(const Cfg *Func) const; void emitIASCoreVFPMove(const Cfg *Func) const;
Variable *DestHi = nullptr; Variable *DestHi = nullptr;
......
; 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
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment