aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2010-10-14 02:33:26 +0000
committerBill Wendling <isanbard@gmail.com>2010-10-14 02:33:26 +0000
commitbbbdcd453d22258cb4dd217eddf016668fcebf84 (patch)
treeea56c8202a8f47594ca62fb4d655f01927163a42
parent946a2740a54fe2cd57509999384239101bf5b9df (diff)
downloadexternal_llvm-bbbdcd453d22258cb4dd217eddf016668fcebf84.zip
external_llvm-bbbdcd453d22258cb4dd217eddf016668fcebf84.tar.gz
external_llvm-bbbdcd453d22258cb4dd217eddf016668fcebf84.tar.bz2
Add support for vmov.f64/.f32 encoding. There's a bit of a hack going on
here. The f32 in FCONSTS is handled as a double instead of a float in the code. So the encoding of the immediate into the instruction isn't exactly in line with the documentation in that regard. But given that we know it's handled as a double, it doesn't cause any harm. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@116471 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/ARM/ARMInstrVFP.td46
-rw-r--r--lib/Target/ARM/ARMMCCodeEmitter.cpp8
-rw-r--r--test/MC/ARM/simple-fp-encoding.ll16
3 files changed, 56 insertions, 14 deletions
diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td
index c7f3f85..4766205 100644
--- a/lib/Target/ARM/ARMInstrVFP.td
+++ b/lib/Target/ARM/ARMInstrVFP.td
@@ -921,7 +921,7 @@ def VNEGScc : ASuI<0b11101, 0b11, 0b0001, 0b01, 0,
let Defs = [CPSR], Uses = [FPSCR] in
def FMSTAT : VFPAI<(outs), (ins), VFPMiscFrm, IIC_fpSTAT, "vmrs",
"\tapsr_nzcv, fpscr",
- [(arm_fmstat)]> {
+ [(arm_fmstat)]> {
let Inst{27-20} = 0b11101111;
let Inst{19-16} = 0b0001;
let Inst{15-12} = 0b1111;
@@ -932,7 +932,7 @@ def FMSTAT : VFPAI<(outs), (ins), VFPMiscFrm, IIC_fpSTAT, "vmrs",
let Inst{3-0} = 0b0000;
}
-// FPSCR <-> GPR (for disassembly only)
+// FPSCR <-> GPR
let hasSideEffects = 1, Uses = [FPSCR] in
def VMRS : VFPAI<(outs GPR:$Rt), (ins), VFPMiscFrm, IIC_fpSTAT,
"vmrs", "\t$Rt, fpscr",
@@ -971,25 +971,49 @@ def VMSR : VFPAI<(outs), (ins GPR:$src), VFPMiscFrm, IIC_fpSTAT,
// Materialize FP immediates. VFP3 only.
let isReMaterializable = 1 in {
-def FCONSTD : VFPAI<(outs DPR:$dst), (ins vfp_f64imm:$imm),
+def FCONSTD : VFPAI<(outs DPR:$Dd), (ins vfp_f64imm:$imm),
VFPMiscFrm, IIC_fpUNA64,
- "vmov", ".f64\t$dst, $imm",
- [(set DPR:$dst, vfp_f64imm:$imm)]>, Requires<[HasVFP3]> {
+ "vmov", ".f64\t$Dd, $imm",
+ [(set DPR:$Dd, vfp_f64imm:$imm)]>, Requires<[HasVFP3]> {
+ // Instruction operands.
+ bits<5> Dd;
+ bits<32> imm;
+
+ // Encode instruction operands.
+ let Inst{15-12} = Dd{3-0};
+ let Inst{22} = Dd{4};
+ let Inst{19} = imm{31};
+ let Inst{18-16} = imm{22-20};
+ let Inst{3-0} = imm{19-16};
+
+ // Encode remaining instruction bits.
let Inst{27-23} = 0b11101;
let Inst{21-20} = 0b11;
let Inst{11-9} = 0b101;
- let Inst{8} = 1;
+ let Inst{8} = 1; // Double precision.
let Inst{7-4} = 0b0000;
}
-def FCONSTS : VFPAI<(outs SPR:$dst), (ins vfp_f32imm:$imm),
- VFPMiscFrm, IIC_fpUNA32,
- "vmov", ".f32\t$dst, $imm",
- [(set SPR:$dst, vfp_f32imm:$imm)]>, Requires<[HasVFP3]> {
+def FCONSTS : VFPAI<(outs SPR:$Sd), (ins vfp_f32imm:$imm),
+ VFPMiscFrm, IIC_fpUNA32,
+ "vmov", ".f32\t$Sd, $imm",
+ [(set SPR:$Sd, vfp_f32imm:$imm)]>, Requires<[HasVFP3]> {
+ // Instruction operands.
+ bits<5> Sd;
+ bits<32> imm;
+
+ // Encode instruction operands.
+ let Inst{15-12} = Sd{4-1};
+ let Inst{22} = Sd{0};
+ let Inst{19} = imm{31}; // The immediate is handled as a double.
+ let Inst{18-16} = imm{22-20};
+ let Inst{3-0} = imm{19-16};
+
+ // Encode remaining instruction bits.
let Inst{27-23} = 0b11101;
let Inst{21-20} = 0b11;
let Inst{11-9} = 0b101;
- let Inst{8} = 0;
+ let Inst{8} = 0; // Single precision.
let Inst{7-4} = 0b0000;
}
}
diff --git a/lib/Target/ARM/ARMMCCodeEmitter.cpp b/lib/Target/ARM/ARMMCCodeEmitter.cpp
index 5b20676..cafd3f2 100644
--- a/lib/Target/ARM/ARMMCCodeEmitter.cpp
+++ b/lib/Target/ARM/ARMMCCodeEmitter.cpp
@@ -138,10 +138,13 @@ EmitImmediate(const MCOperand &DispOp, unsigned Size, MCFixupKind FixupKind,
/// operand requires relocation, record the relocation and return zero.
unsigned ARMMCCodeEmitter::getMachineOpValue(const MCInst &MI,
const MCOperand &MO) const {
- if (MO.isReg())
+ if (MO.isReg()) {
return getARMRegisterNumbering(MO.getReg());
- else if (MO.isImm()) {
+ } else if (MO.isImm()) {
return static_cast<unsigned>(MO.getImm());
+ } else if (MO.isFPImm()) {
+ return static_cast<unsigned>(APFloat(MO.getFPImm())
+ .bitcastToAPInt().getHiBits(32).getLimitedValue());
} else {
#ifndef NDEBUG
errs() << MO;
@@ -151,7 +154,6 @@ unsigned ARMMCCodeEmitter::getMachineOpValue(const MCInst &MI,
return 0;
}
-
unsigned ARMMCCodeEmitter::getSORegOpValue(const MCInst &MI,
unsigned OpIdx) const {
// Sub-operands are [reg, reg, imm]. The first register is Rm, the reg
diff --git a/test/MC/ARM/simple-fp-encoding.ll b/test/MC/ARM/simple-fp-encoding.ll
index 84ccb6d..99b479b 100644
--- a/test/MC/ARM/simple-fp-encoding.ll
+++ b/test/MC/ARM/simple-fp-encoding.ll
@@ -352,3 +352,19 @@ entry:
}
declare void @llvm.arm.set.fpscr(i32) nounwind
+
+
+define double @f102() nounwind readnone {
+entry:
+; CHECK: f102
+; CHECK: vmov.f64 d16, #3.000000e+00 @ encoding: [0x08,0x0b,0xf0,0xee]
+ ret double 3.000000e+00
+}
+
+define float @f103(float %a) nounwind readnone {
+entry:
+; CHECK: f103
+; CHECK: vmov.f32 s0, #3.000000e+00 @ encoding: [0x08,0x0a,0xb0,0xee]
+ %add = fadd float %a, 3.000000e+00
+ ret float %add
+}