aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2008-11-12 06:41:41 +0000
committerEvan Cheng <evan.cheng@apple.com>2008-11-12 06:41:41 +0000
commit7427338c3da0cf35ecd0ea845ea41e3939eab608 (patch)
treedb6709385ba9106fd60de2c990610c0479e31698 /lib/Target
parent8a0454bb13f2db05517e70aae31e0f15f5d252fe (diff)
downloadexternal_llvm-7427338c3da0cf35ecd0ea845ea41e3939eab608.zip
external_llvm-7427338c3da0cf35ecd0ea845ea41e3939eab608.tar.gz
external_llvm-7427338c3da0cf35ecd0ea845ea41e3939eab608.tar.bz2
Fix VFP conversion instruction encodings.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59104 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target')
-rw-r--r--lib/Target/ARM/ARMCodeEmitter.cpp126
-rw-r--r--lib/Target/ARM/ARMInstrFormats.td49
-rw-r--r--lib/Target/ARM/ARMInstrInfo.h10
-rw-r--r--lib/Target/ARM/ARMInstrVFP.td24
4 files changed, 123 insertions, 86 deletions
diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp
index d6d9814..e36f0e1 100644
--- a/lib/Target/ARM/ARMCodeEmitter.cpp
+++ b/lib/Target/ARM/ARMCodeEmitter.cpp
@@ -347,6 +347,8 @@ void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) {
case ARMII::VFPConv1Frm:
case ARMII::VFPConv2Frm:
case ARMII::VFPConv3Frm:
+ case ARMII::VFPConv4Frm:
+ case ARMII::VFPConv5Frm:
emitVFPConversionInstruction(MI);
break;
case ARMII::VFPLdStFrm:
@@ -1095,22 +1097,9 @@ void ARMCodeEmitter::emitVFPArithInstruction(const MachineInstr &MI) {
emitWordLE(Binary);
}
-void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) {
- const TargetInstrDesc &TID = MI.getDesc();
-
- // Part of binary is determined by TableGn.
- unsigned Binary = getBinaryCodeForInstr(MI);
-
- // Set the conditional execution predicate
- Binary |= II->getPredicate(&MI) << ARMII::CondShift;
-
- // FMDRR encodes registers in reverse order.
- unsigned Form = TID.TSFlags & ARMII::FormMask;
- unsigned OpIdx = (Form == ARMII::VFPConv2Frm)
- ? MI.findFirstPredOperandIdx()-1 : 0;
-
- // Encode Dd / Sd.
+static unsigned encodeVFPRd(const MachineInstr &MI, unsigned OpIdx) {
unsigned RegD = MI.getOperand(OpIdx).getReg();
+ unsigned Binary = 0;
bool isSPVFP = false;
RegD = ARMRegisterInfo::getRegisterNumbering(RegD, isSPVFP);
if (!isSPVFP)
@@ -1119,29 +1108,13 @@ void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) {
Binary |= ((RegD & 0x1E) >> 1) << ARMII::RegRdShift;
Binary |= (RegD & 0x01) << ARMII::D_BitShift;
}
- if (Form == ARMII::VFPConv2Frm)
- --OpIdx;
- else
- ++OpIdx;
-
- if (Form == ARMII::VFPConv3Frm) {
- unsigned RegM = MI.getOperand(OpIdx).getReg();
- isSPVFP = false;
- RegM = ARMRegisterInfo::getRegisterNumbering(RegM, isSPVFP);
- if (!isSPVFP)
- Binary |= RegM;
- else {
- Binary |= ((RegM & 0x1E) >> 1);
- Binary |= (RegM & 0x01) << ARMII::M_BitShift;
- }
-
- emitWordLE(Binary);
- return;
- }
+ return Binary;
+}
- // Encode Dn / Sn.
+static unsigned encodeVFPRn(const MachineInstr &MI, unsigned OpIdx) {
unsigned RegN = MI.getOperand(OpIdx).getReg();
- isSPVFP = false;
+ unsigned Binary = 0;
+ bool isSPVFP = false;
RegN = ARMRegisterInfo::getRegisterNumbering(RegN, isSPVFP);
if (!isSPVFP)
Binary |= RegN << ARMII::RegRnShift;
@@ -1149,23 +1122,74 @@ void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) {
Binary |= ((RegN & 0x1E) >> 1) << ARMII::RegRnShift;
Binary |= (RegN & 0x01) << ARMII::N_BitShift;
}
- if (Form == ARMII::VFPConv2Frm)
- --OpIdx;
- else
- ++OpIdx;
+ return Binary;
+}
- // FMRS / FMSR do not have Rm.
- if (TID.getNumOperands() > OpIdx && MI.getOperand(OpIdx).isReg()) {
- unsigned RegM = MI.getOperand(OpIdx).getReg();
- isSPVFP = false;
- RegM = ARMRegisterInfo::getRegisterNumbering(RegM, isSPVFP);
- if (!isSPVFP)
- Binary |= RegM;
- else {
- Binary |= ((RegM & 0x1E) >> 1);
- Binary |= (RegM & 0x01) << ARMII::M_BitShift;
- }
+static unsigned encodeVFPRm(const MachineInstr &MI, unsigned OpIdx) {
+ unsigned RegM = MI.getOperand(OpIdx).getReg();
+ unsigned Binary = 0;
+ bool isSPVFP = false;
+ RegM = ARMRegisterInfo::getRegisterNumbering(RegM, isSPVFP);
+ if (!isSPVFP)
+ Binary |= RegM;
+ else {
+ Binary |= ((RegM & 0x1E) >> 1);
+ Binary |= (RegM & 0x01) << ARMII::M_BitShift;
}
+ return Binary;
+}
+
+void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) {
+ const TargetInstrDesc &TID = MI.getDesc();
+ unsigned Form = TID.TSFlags & ARMII::FormMask;
+
+ // Part of binary is determined by TableGn.
+ unsigned Binary = getBinaryCodeForInstr(MI);
+
+ // Set the conditional execution predicate
+ Binary |= II->getPredicate(&MI) << ARMII::CondShift;
+
+ switch (Form) {
+ default: break;
+ case ARMII::VFPConv1Frm:
+ case ARMII::VFPConv2Frm:
+ case ARMII::VFPConv3Frm:
+ // Encode Dd / Sd.
+ Binary |= encodeVFPRd(MI, 0);
+ break;
+ case ARMII::VFPConv4Frm:
+ // Encode Dn / Sn.
+ Binary |= encodeVFPRn(MI, 0);
+ break;
+ case ARMII::VFPConv5Frm:
+ // Encode Dm / Sm.
+ Binary |= encodeVFPRm(MI, 0);
+ break;
+ }
+
+ switch (Form) {
+ default: break;
+ case ARMII::VFPConv1Frm:
+ // Encode Dm / Sm.
+ Binary |= encodeVFPRm(MI, 1);
+ case ARMII::VFPConv2Frm:
+ case ARMII::VFPConv3Frm:
+ // Encode Dn / Sn.
+ Binary |= encodeVFPRn(MI, 1);
+ break;
+ case ARMII::VFPConv4Frm:
+ case ARMII::VFPConv5Frm:
+ // Encode Dd / Sd.
+ Binary |= encodeVFPRd(MI, 1);
+ break;
+ }
+
+ if (Form == ARMII::VFPConv5Frm)
+ // Encode Dn / Sn.
+ Binary |= encodeVFPRn(MI, 2);
+ else if (Form == ARMII::VFPConv3Frm)
+ // Encode Dm / Sm.
+ Binary |= encodeVFPRm(MI, 2);
emitWordLE(Binary);
}
diff --git a/lib/Target/ARM/ARMInstrFormats.td b/lib/Target/ARM/ARMInstrFormats.td
index 1db0838..6ca931d 100644
--- a/lib/Target/ARM/ARMInstrFormats.td
+++ b/lib/Target/ARM/ARMInstrFormats.td
@@ -42,11 +42,13 @@ def VFPBinaryFrm : Format<16>;
def VFPConv1Frm : Format<17>;
def VFPConv2Frm : Format<18>;
def VFPConv3Frm : Format<19>;
-def VFPLdStFrm : Format<20>;
-def VFPLdStMulFrm : Format<21>;
-def VFPMiscFrm : Format<22>;
+def VFPConv4Frm : Format<20>;
+def VFPConv5Frm : Format<21>;
+def VFPLdStFrm : Format<22>;
+def VFPLdStMulFrm : Format<23>;
+def VFPMiscFrm : Format<24>;
-def ThumbFrm : Format<23>;
+def ThumbFrm : Format<25>;
// Misc flag for data processing instructions that indicates whether
// the instruction has a Rn register operand.
@@ -820,30 +822,39 @@ class ASbI<bits<8> opcod, dag oops, dag iops, string opc,
let Inst{11-8} = 0b1010;
}
-class AVConv1I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops, string opc,
- string asm, list<dag> pattern>
+// VFP conversion instructions
+class AVConv1I<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> {
let Inst{27-20} = opcod1;
- let Inst{11-8} = opcod2;
- let Inst{4} = 1;
+ let Inst{19-16} = opcod2;
+ let Inst{11-8} = opcod3;
+ let Inst{6} = 1;
}
-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> {
+class AVConvXI<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops, Format f,
+ string opc, string asm, list<dag> pattern>
+ : AI<oops, iops, f, 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, VFPConv3Frm, opc, asm, pattern> {
- let Inst{27-20} = opcod1;
- let Inst{19-16} = opcod2;
- let Inst{11-8} = opcod3;
- let Inst{6} = 1;
-}
+class AVConv2I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops, string opc,
+ string asm, list<dag> pattern>
+ : AVConvXI<opcod1, opcod2, oops, iops, VFPConv2Frm, opc, asm, pattern>;
+
+class AVConv3I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops, string opc,
+ string asm, list<dag> pattern>
+ : AVConvXI<opcod1, opcod2, oops, iops, VFPConv3Frm, opc, asm, pattern>;
+
+class AVConv4I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops, string opc,
+ string asm, list<dag> pattern>
+ : AVConvXI<opcod1, opcod2, oops, iops, VFPConv4Frm, opc, asm, pattern>;
+
+class AVConv5I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops, string opc,
+ string asm, list<dag> pattern>
+ : AVConvXI<opcod1, opcod2, oops, iops, VFPConv5Frm, opc, asm, pattern>;
//===----------------------------------------------------------------------===//
diff --git a/lib/Target/ARM/ARMInstrInfo.h b/lib/Target/ARM/ARMInstrInfo.h
index 1da9678..d9ee5fc 100644
--- a/lib/Target/ARM/ARMInstrInfo.h
+++ b/lib/Target/ARM/ARMInstrInfo.h
@@ -106,12 +106,14 @@ namespace ARMII {
VFPConv1Frm = 17 << FormShift,
VFPConv2Frm = 18 << FormShift,
VFPConv3Frm = 19 << FormShift,
- VFPLdStFrm = 20 << FormShift,
- VFPLdStMulFrm = 21 << FormShift,
- VFPMiscFrm = 22 << FormShift,
+ VFPConv4Frm = 20 << FormShift,
+ VFPConv5Frm = 21 << FormShift,
+ VFPLdStFrm = 22 << FormShift,
+ VFPLdStMulFrm = 23 << FormShift,
+ VFPMiscFrm = 24 << FormShift,
// Thumb format
- ThumbFrm = 23 << FormShift,
+ ThumbFrm = 25 << 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 b4e665c..5c5b9e2 100644
--- a/lib/Target/ARM/ARMInstrVFP.td
+++ b/lib/Target/ARM/ARMInstrVFP.td
@@ -219,15 +219,15 @@ def FSQRTS : ASuI<0b11101011, 0b0001, 0b1100, (outs SPR:$dst), (ins SPR:$a),
// FP <-> GPR Copies. Int <-> FP Conversions.
//
-def FMRS : AVConv1I<0b11100001, 0b1010, (outs GPR:$dst), (ins SPR:$src),
+def FMRS : AVConv2I<0b11100001, 0b1010, (outs GPR:$dst), (ins SPR:$src),
"fmrs", " $dst, $src",
[(set GPR:$dst, (bitconvert SPR:$src))]>;
-def FMSR : AVConv2I<0b11100000, 0b1010, (outs SPR:$dst), (ins GPR:$src),
+def FMSR : AVConv4I<0b11100000, 0b1010, (outs SPR:$dst), (ins GPR:$src),
"fmsr", " $dst, $src",
[(set SPR:$dst, (bitconvert GPR:$src))]>;
-def FMRRD : AVConv1I<0b11000101, 0b1011,
+def FMRRD : AVConv3I<0b11000101, 0b1011,
(outs GPR:$dst1, GPR:$dst2), (ins DPR:$src),
"fmrrd", " $dst1, $dst2, $src",
[/* FIXME: Can't write pattern for multiple result instr*/]>;
@@ -235,7 +235,7 @@ def FMRRD : AVConv1I<0b11000101, 0b1011,
// FMDHR: GPR -> SPR
// FMDLR: GPR -> SPR
-def FMDRR : AVConv2I<0b11000100, 0b1011, (outs DPR:$dst), (ins GPR:$src1, GPR:$src2),
+def FMDRR : AVConv5I<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 : AVConv2I<0b11000100, 0b1011, (outs DPR:$dst), (ins GPR:$src1, GPR:$s
// Int to FP:
-def FSITOD : AVConv3I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a),
+def FSITOD : AVConv1I<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 : AVConv3I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a),
+def FSITOS : AVConv1I<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 : AVConv3I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a),
+def FUITOD : AVConv1I<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 : AVConv3I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a),
+def FUITOS : AVConv1I<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 : AVConv3I<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 : AVConv3I<0b11101011, 0b1101, 0b1011,
+def FTOSIZD : AVConv1I<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 : AVConv3I<0b11101011, 0b1101, 0b1010,
+def FTOSIZS : AVConv1I<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 : AVConv3I<0b11101011, 0b1100, 0b1011,
+def FTOUIZD : AVConv1I<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 : AVConv3I<0b11101011, 0b1100, 0b1010,
+def FTOUIZS : AVConv1I<0b11101011, 0b1100, 0b1010,
(outs SPR:$dst), (ins SPR:$a),
"ftouizs", " $dst, $a",
[(set SPR:$dst, (arm_ftoui SPR:$a))]> {