Commit 4ff90be3 by Karl Schimpf

Clean up handling of ARM IR instruction "mov".

Also adds VMOVSR instruction to the integrated ARM assembler. BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4334 R=jpp@chromium.org, stichnot@chromium.org Review URL: https://codereview.chromium.org/1596613002 .
parent ab389f22
......@@ -604,9 +604,8 @@ void Assembler::nop(Condition cond) {
B25 | B24 | B21 | (0xf << 12);
Emit(encoding);
}
#endif
// Moved to ARM32::AssemblerARM32::vmovsr().
void Assembler::vmovsr(SRegister sn, Register rt, Condition cond) {
ASSERT(TargetCPUFeatures::vfp_supported());
ASSERT(sn != kNoSRegister);
......@@ -621,7 +620,7 @@ void Assembler::vmovsr(SRegister sn, Register rt, Condition cond) {
((static_cast<int32_t>(sn) & 1)*B7) | B4;
Emit(encoding);
}
#endif
void Assembler::vmovrs(Register rt, SRegister sn, Condition cond) {
ASSERT(TargetCPUFeatures::vfp_supported());
......
......@@ -617,7 +617,10 @@ class Assembler : public ValueObject {
}
// Floating point instructions (VFPv3-D16 and VFPv3-D32 profiles).
#if 0
// Moved to ARM32::AssemblerARM32::vmovsr().
void vmovsr(SRegister sn, Register rt, Condition cond = AL);
#endif
void vmovrs(Register rt, SRegister sn, Condition cond = AL);
void vmovsrr(SRegister sm, Register rt, Register rt2, Condition cond = AL);
void vmovrrs(Register rt, Register rt2, SRegister sm, Condition cond = AL);
......
......@@ -199,6 +199,7 @@ IValueT getEncodedGPRegNum(const Variable *Var) {
}
IValueT getEncodedSRegNum(const Variable *Var) {
assert(Var->hasReg());
return RegARM32::getEncodedSReg(Var->getRegNum());
}
......@@ -2378,6 +2379,27 @@ void AssemblerARM32::vldrs(const Operand *OpSd, const Operand *OpAddress,
emitInst(Encoding);
}
void AssemblerARM32::vmovsr(const Operand *OpSn, const Operand *OpRt,
CondARM32::Cond Cond) {
// VMOV (between ARM core register and single-precision register)
// ARM seciont A8.8.343, encoding A1.
//
// vmov<c> <Sn>, <Rt>
//
// cccc1110000onnnntttt1010N0010000 where cccc=Cond, nnnnN = Sn, and tttt=Rt.
constexpr const char *Vmovsr = "vmovsr";
IValueT Sn = encodeSRegister(OpSn, "Sn", Vmovsr);
IValueT Rt = encodeGPRegister(OpRt, "Rt", Vmovsr);
assert(Sn < RegARM32::getNumSRegs());
assert(Rt < RegARM32::getNumGPRegs());
assert(CondARM32::isDefined(Cond));
AssemblerBuffer::EnsureCapacity ensured(&Buffer);
IValueT Encoding = (encodeCondition(Cond) << kConditionShift) | B27 | B26 |
B25 | B11 | B9 | B4 | (getXXXXInRegXXXXY(Sn) << 16) |
(Rt << kRdShift) | (getYInRegXXXXY(Sn) << 7);
emitInst(Encoding);
}
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:
......
......@@ -382,6 +382,8 @@ public:
vldrs(OpSd, OpAddress, Cond, TInfo);
}
void vmovsr(const Operand *OpSn, const Operand *OpRt, CondARM32::Cond Cond);
void vmuld(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
CondARM32::Cond Cond);
......
......@@ -1124,6 +1124,30 @@ void InstARM32Mov::emitSingleDestSingleSource(const Cfg *Func) const {
Src0->emit(Func);
}
void InstARM32Mov::emitIASCoreVFPMove(const Cfg *Func) const {
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
Operand *Src0 = getSrc(0);
if (!llvm::isa<Variable>(Src0))
// TODO(kschimpf) Handle moving constants into registers.
return Asm->setNeedsTextFixup();
// Move register to register.
Variable *Dest = getDest();
switch (Dest->getType()) {
default:
// TODO(kschimpf): Fill this out more.
return Asm->setNeedsTextFixup();
case IceType_f32:
switch (Src0->getType()) {
default:
// TODO(kschimpf): Fill this out more?
return Asm->setNeedsTextFixup();
case IceType_i32:
return Asm->vmovsr(Dest, Src0, getPredicate());
}
}
}
void InstARM32Mov::emitIASSingleDestSingleSource(const Cfg *Func) const {
auto *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
Variable *Dest = getDest();
......@@ -1137,12 +1161,16 @@ void InstARM32Mov::emitIASSingleDestSingleSource(const Cfg *Func) const {
llvm::report_fatal_error("mov can't load.");
}
if (isMoveBetweenCoreAndVFPRegisters(Dest, Src0))
return emitIASCoreVFPMove(Func);
const Type DestTy = Dest->getType();
const bool DestIsVector = isVectorType(DestTy);
const bool DestIsScalarFP = isScalarFloatingType(DestTy);
const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0);
if (DestIsVector || DestIsScalarFP || CoreVFPMove)
if (isScalarFloatingType(DestTy))
return Asm->setNeedsTextFixup();
if (isVectorType(DestTy))
return Asm->setNeedsTextFixup();
return Asm->mov(Dest, Src0, getPredicate());
}
......
......@@ -1340,6 +1340,7 @@ private:
void emitSingleDestSingleSource(const Cfg *Func) const;
void emitIASSingleDestSingleSource(const Cfg *Func) const;
void emitIASCoreVFPMove(const Cfg *Func) const;
Variable *DestHi = nullptr;
};
......
; Show that we know how to translate vmov for casts.
; NOTE: Restricts S register to one that will better test S register encodings.
; REQUIRES: allow_dump
; Compile using standalone assembler.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -Om1 \
; RUN: -reg-use s20,s22,d20,d22 \
; 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 \
; RUN: -reg-use s20,s22,d20,d22 \
; RUN: | FileCheck %s --check-prefix=DIS
; Compile using integrated assembler.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -Om1 \
; RUN: -reg-use s20,s22,d20,d22 \
; 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 \
; RUN: -reg-use s20,s22,d20,d22 \
; RUN: | FileCheck %s --check-prefix=DIS
define internal float @castToFloat(i32 %a) {
; ASM-LABEL: castToFloat:
; DIS-LABEL: 00000000 <castToFloat>:
; IASM-LABEL: castToFloat:
entry:
; ASM: .LcastToFloat$entry:
; IASM: .LcastToFloat$entry:
%0 = bitcast i32 %a to float
; ASM: vmov s20, r0
; DIS: 10: ee0a0a10
; IASM-NOT: vmov
ret float %0
}
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