summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2008-11-11 22:46:12 +0000
committerEvan Cheng <evan.cheng@apple.com>2008-11-11 22:46:12 +0000
commit0a0ab1387a3923769990e91cce8e098366c4a920 (patch)
tree77a6568b1a5241caa75c86e187a101d0b84d32f7
parentcb5201f3b2d7147471d33cb2ddd94c5e011055e2 (diff)
downloadllvm-0a0ab1387a3923769990e91cce8e098366c4a920.tar.gz
llvm-0a0ab1387a3923769990e91cce8e098366c4a920.tar.bz2
llvm-0a0ab1387a3923769990e91cce8e098366c4a920.tar.xz
Fix FMDRR encoding.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59088 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/ARM/ARMCodeEmitter.cpp29
-rw-r--r--lib/Target/ARM/ARMInstrFormats.td21
-rw-r--r--lib/Target/ARM/ARMInstrInfo.h9
-rw-r--r--lib/Target/ARM/ARMInstrVFP.td18
4 files changed, 51 insertions, 26 deletions
diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp
index 08372cefd6..7e1e8046fa 100644
--- a/lib/Target/ARM/ARMCodeEmitter.cpp
+++ b/lib/Target/ARM/ARMCodeEmitter.cpp
@@ -342,6 +342,7 @@ void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) {
break;
case ARMII::VFPConv1Frm:
case ARMII::VFPConv2Frm:
+ case ARMII::VFPConv3Frm:
emitVFPConversionInstruction(MI);
break;
case ARMII::VFPLdStFrm:
@@ -1080,27 +1081,41 @@ void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) {
// Set the conditional execution predicate
Binary |= II->getPredicate(&MI) << ARMII::CondShift;
- unsigned OpIdx = 0;
+ // FMDRR encodes registers in reverse order.
+ unsigned Form = TID.TSFlags & ARMII::FormMask;
+ unsigned OpIdx = (Form == ARMII::VFPConv2Frm) ? 2 : 0;
// Encode Dd / Sd.
- unsigned RegD = getMachineOpValue(MI, OpIdx++);
+ unsigned RegD = getMachineOpValue(MI, OpIdx);
Binary |= (RegD & 0x0f) << ARMII::RegRdShift;
Binary |= (RegD & 0x10) << ARMII::D_BitShift;
+ if (Form == ARMII::VFPConv2Frm)
+ --OpIdx;
+ else
+ ++OpIdx;
// Encode Dn / Sn.
- if ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPConv1Frm) {
- unsigned RegN = getMachineOpValue(MI, OpIdx++);
+ if (Form == ARMII::VFPConv1Frm || Form == ARMII::VFPConv2Frm) {
+ unsigned RegN = getMachineOpValue(MI, OpIdx);
Binary |= (RegN & 0x0f) << ARMII::RegRnShift;
Binary |= (RegN & 0x10) << ARMII::N_BitShift;
+ if (Form == ARMII::VFPConv2Frm)
+ --OpIdx;
+ else
+ ++OpIdx;
// FMRS / FMSR do not have Rm.
- if (!TID.OpInfo[2].isPredicate()) {
- unsigned RegM = getMachineOpValue(MI, OpIdx++);
+ if (TID.getNumOperands() > OpIdx && MI.getOperand(OpIdx).isReg()) {
+ unsigned RegM = getMachineOpValue(MI, OpIdx);
Binary |= (RegM & 0x0f);
Binary |= (RegM & 0x10) << ARMII::M_BitShift;
+ } else if (Form == ARMII::VFPConv2Frm) {
+ // FMDRR encodes definition register in Dm field.
+ Binary |= getMachineOpValue(MI, 0);
}
} else {
- unsigned RegM = getMachineOpValue(MI, OpIdx++);
+ assert(Form == ARMII::VFPConv3Frm && "Unsupported format!");
+ unsigned RegM = getMachineOpValue(MI, OpIdx);
Binary |= (RegM & 0x0f);
Binary |= (RegM & 0x10) << ARMII::M_BitShift;
}
diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td
index b59af13cd9..1db0838d07 100644
--- a/lib/Target/ARM/ARMInstrFormats.td
+++ b/lib/Target/ARM/ARMInstrFormats.td
@@ -41,11 +41,12 @@ def VFPUnaryFrm : Format<15>;
def VFPBinaryFrm : Format<16>;
def VFPConv1Frm : Format<17>;
def VFPConv2Frm : Format<18>;
-def VFPLdStFrm : Format<19>;
-def VFPLdStMulFrm : Format<20>;
-def VFPMiscFrm : Format<21>;
+def VFPConv3Frm : Format<19>;
+def VFPLdStFrm : Format<20>;
+def VFPLdStMulFrm : Format<21>;
+def VFPMiscFrm : Format<22>;
-def ThumbFrm : Format<22>;
+def ThumbFrm : Format<23>;
// Misc flag for data processing instructions that indicates whether
// the instruction has a Rn register operand.
@@ -827,9 +828,17 @@ class AVConv1I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops, string opc,
let Inst{4} = 1;
}
-class AVConv2I<bits<8> opcod1, bits<4> opcod2, bits<4> opcod3,
+class AVConv2I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops, string opc,
+ string asm, list<dag> pattern>
+ : AI<oops, iops, VFPConv2Frm, opc, asm, pattern> {
+ let Inst{27-20} = opcod1;
+ let Inst{11-8} = opcod2;
+ let Inst{4} = 1;
+}
+
+class AVConv3I<bits<8> opcod1, bits<4> opcod2, bits<4> opcod3,
dag oops, dag iops, string opc, string asm, list<dag> pattern>
- : AI<oops, iops, VFPConv1Frm, opc, asm, pattern> {
+ : AI<oops, iops, VFPConv3Frm, opc, asm, pattern> {
let Inst{27-20} = opcod1;
let Inst{19-16} = opcod2;
let Inst{11-8} = opcod3;
diff --git a/lib/Target/ARM/ARMInstrInfo.h b/lib/Target/ARM/ARMInstrInfo.h
index c77a6288f6..1da9678c03 100644
--- a/lib/Target/ARM/ARMInstrInfo.h
+++ b/lib/Target/ARM/ARMInstrInfo.h
@@ -105,12 +105,13 @@ namespace ARMII {
VFPBinaryFrm = 16 << FormShift,
VFPConv1Frm = 17 << FormShift,
VFPConv2Frm = 18 << FormShift,
- VFPLdStFrm = 19 << FormShift,
- VFPLdStMulFrm = 20 << FormShift,
- VFPMiscFrm = 21 << FormShift,
+ VFPConv3Frm = 19 << FormShift,
+ VFPLdStFrm = 20 << FormShift,
+ VFPLdStMulFrm = 21 << FormShift,
+ VFPMiscFrm = 22 << FormShift,
// Thumb format
- ThumbFrm = 22 << FormShift,
+ ThumbFrm = 23 << FormShift,
//===------------------------------------------------------------------===//
// Field shifts - such shifts are used to set field while generating
diff --git a/lib/Target/ARM/ARMInstrVFP.td b/lib/Target/ARM/ARMInstrVFP.td
index 442c12abcb..7409eb0dec 100644
--- a/lib/Target/ARM/ARMInstrVFP.td
+++ b/lib/Target/ARM/ARMInstrVFP.td
@@ -235,7 +235,7 @@ def FMRRD : AVConv1I<0b11000101, 0b1011,
// FMDHR: GPR -> SPR
// FMDLR: GPR -> SPR
-def FMDRR : AVConv1I<0b11000100, 0b1011, (outs DPR:$dst), (ins GPR:$src1, GPR:$src2),
+def FMDRR : AVConv2I<0b11000100, 0b1011, (outs DPR:$dst), (ins GPR:$src1, GPR:$src2),
"fmdrr", " $dst, $src1, $src2",
[(set DPR:$dst, (arm_fmdrr GPR:$src1, GPR:$src2))]>;
@@ -251,25 +251,25 @@ def FMDRR : AVConv1I<0b11000100, 0b1011, (outs DPR:$dst), (ins GPR:$src1, GPR:$s
// Int to FP:
-def FSITOD : AVConv2I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a),
+def FSITOD : AVConv3I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a),
"fsitod", " $dst, $a",
[(set DPR:$dst, (arm_sitof SPR:$a))]> {
let Inst{7} = 1; // Z bit
}
-def FSITOS : AVConv2I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a),
+def FSITOS : AVConv3I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a),
"fsitos", " $dst, $a",
[(set SPR:$dst, (arm_sitof SPR:$a))]> {
let Inst{7} = 1; // Z bit
}
-def FUITOD : AVConv2I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a),
+def FUITOD : AVConv3I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a),
"fuitod", " $dst, $a",
[(set DPR:$dst, (arm_uitof SPR:$a))]> {
let Inst{7} = 0; // Z bit
}
-def FUITOS : AVConv2I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a),
+def FUITOS : AVConv3I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a),
"fuitos", " $dst, $a",
[(set SPR:$dst, (arm_uitof SPR:$a))]> {
let Inst{7} = 1; // Z bit
@@ -278,28 +278,28 @@ def FUITOS : AVConv2I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a),
// FP to Int:
// Always set Z bit in the instruction, i.e. "round towards zero" variants.
-def FTOSIZD : AVConv2I<0b11101011, 0b1101, 0b1011,
+def FTOSIZD : AVConv3I<0b11101011, 0b1101, 0b1011,
(outs SPR:$dst), (ins DPR:$a),
"ftosizd", " $dst, $a",
[(set SPR:$dst, (arm_ftosi DPR:$a))]> {
let Inst{7} = 1; // Z bit
}
-def FTOSIZS : AVConv2I<0b11101011, 0b1101, 0b1010,
+def FTOSIZS : AVConv3I<0b11101011, 0b1101, 0b1010,
(outs SPR:$dst), (ins SPR:$a),
"ftosizs", " $dst, $a",
[(set SPR:$dst, (arm_ftosi SPR:$a))]> {
let Inst{7} = 1; // Z bit
}
-def FTOUIZD : AVConv2I<0b11101011, 0b1100, 0b1011,
+def FTOUIZD : AVConv3I<0b11101011, 0b1100, 0b1011,
(outs SPR:$dst), (ins DPR:$a),
"ftouizd", " $dst, $a",
[(set SPR:$dst, (arm_ftoui DPR:$a))]> {
let Inst{7} = 1; // Z bit
}
-def FTOUIZS : AVConv2I<0b11101011, 0b1100, 0b1010,
+def FTOUIZS : AVConv3I<0b11101011, 0b1100, 0b1010,
(outs SPR:$dst), (ins SPR:$a),
"ftouizs", " $dst, $a",
[(set SPR:$dst, (arm_ftoui SPR:$a))]> {