Fix FMDRR encoding.
authorEvan Cheng <evan.cheng@apple.com>
Tue, 11 Nov 2008 22:46:12 +0000 (22:46 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Tue, 11 Nov 2008 22:46:12 +0000 (22:46 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59088 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMCodeEmitter.cpp
lib/Target/ARM/ARMInstrFormats.td
lib/Target/ARM/ARMInstrInfo.h
lib/Target/ARM/ARMInstrVFP.td

index 08372cefd616891ddf4135e9c6486982aacd1896..7e1e8046faf213f3e1a77b4ed6facfdd6b00dc6f 100644 (file)
@@ -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;
   }
index b59af13cd9e8d02f023e3e2ef110dcdf343c41cd..1db0838d07b8288863017963f36761fca6786f9e 100644 (file)
@@ -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;
index c77a6288f6f6dc5a1cc55e7832bb0bcf3b2b63bd..1da9678c03ec9429d9b5c6b3f2ea5d28556446de 100644 (file)
@@ -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
index 442c12abcb93035f17df97ce61cab73eb8281277..7409eb0decda8f7d58c7194610000c8a46e35fbe 100644 (file)
@@ -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))]> {