Encode VFP load / store instructions.
authorEvan Cheng <evan.cheng@apple.com>
Tue, 11 Nov 2008 21:48:44 +0000 (21:48 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Tue, 11 Nov 2008 21:48:44 +0000 (21:48 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59084 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 29a8f31a5148a980b25793553ba9c94c03ffdbed..2288ad1d37cf1e9df2860179a23a3ef524696131 100644 (file)
@@ -124,6 +124,12 @@ namespace {
 
     void emitVFPConversionInstruction(const MachineInstr &MI);
 
+    void emitVFPLoadStoreInstruction(const MachineInstr &MI);
+
+    void emitVFPLoadStoreMultipleInstruction(const MachineInstr &MI);
+
+    void emitMiscInstruction(const MachineInstr &MI);
+
     /// getBinaryCodeForInstr - This function, generated by the
     /// CodeEmitterGenerator using TableGen, produces the binary encoding for
     /// machine instructions.
@@ -326,6 +332,15 @@ void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) {
   case ARMII::VFPConv2Frm:
     emitVFPConversionInstruction(MI);
     break;
+  case ARMII::VFPLdStFrm:
+    emitVFPLoadStoreInstruction(MI);
+    break;
+  case ARMII::VFPLdStMulFrm:
+    emitVFPLoadStoreMultipleInstruction(MI);
+    break;
+  case ARMII::VFPMiscFrm:
+    emitMiscInstruction(MI);
+    break;
   }
 }
 
@@ -759,23 +774,14 @@ void ARMCodeEmitter::emitMiscLoadStoreInstruction(const MachineInstr &MI,
   emitWordLE(Binary);
 }
 
-void ARMCodeEmitter::emitLoadStoreMultipleInstruction(const MachineInstr &MI) {
-  // Part of binary is determined by TableGn.
-  unsigned Binary = getBinaryCodeForInstr(MI);
-
-  // Set the conditional execution predicate
-  Binary |= II->getPredicate(&MI) << ARMII::CondShift;
-
-  // Set first operand
-  Binary |= getMachineOpValue(MI, 0) << ARMII::RegRnShift;
+static unsigned getAddrModeUPBits(unsigned Mode) {
+  unsigned Binary = 0;
 
   // Set addressing mode by modifying bits U(23) and P(24)
   // IA - Increment after  - bit U = 1 and bit P = 0
   // IB - Increment before - bit U = 1 and bit P = 1
   // DA - Decrement after  - bit U = 0 and bit P = 0
   // DB - Decrement before - bit U = 0 and bit P = 1
-  const MachineOperand &MO = MI.getOperand(1);
-  ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO.getImm());
   switch (Mode) {
   default: assert(0 && "Unknown addressing sub-mode!");
   case ARM_AM::da:                      break;
@@ -784,6 +790,23 @@ void ARMCodeEmitter::emitLoadStoreMultipleInstruction(const MachineInstr &MI) {
   case ARM_AM::ib: Binary |= 0x3 << ARMII::U_BitShift; break;
   }
 
+  return Binary;
+}
+
+void ARMCodeEmitter::emitLoadStoreMultipleInstruction(const MachineInstr &MI) {
+  // Part of binary is determined by TableGn.
+  unsigned Binary = getBinaryCodeForInstr(MI);
+
+  // Set the conditional execution predicate
+  Binary |= II->getPredicate(&MI) << ARMII::CondShift;
+
+  // Set base address operand
+  Binary |= getMachineOpValue(MI, 0) << ARMII::RegRnShift;
+
+  // Set addressing mode by modifying bits U(23) and P(24)
+  const MachineOperand &MO = MI.getOperand(1);
+  Binary |= getAddrModeUPBits(ARM_AM::getAM4SubMode(MO.getImm()));
+
   // Set bit W(21)
   if (ARM_AM::getAM4WBFlag(MO.getImm()))
     Binary |= 0x1 << ARMII::W_BitShift;
@@ -791,8 +814,8 @@ void ARMCodeEmitter::emitLoadStoreMultipleInstruction(const MachineInstr &MI) {
   // Set registers
   for (unsigned i = 4, e = MI.getNumOperands(); i != e; ++i) {
     const MachineOperand &MO = MI.getOperand(i);
-    if (MO.isReg() && MO.isImplicit())
-      continue;
+    if (!MO.isReg() || MO.isImplicit())
+      break;
     unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(MO.getReg());
     assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) &&
            RegNum < 16);
@@ -1064,4 +1087,87 @@ void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) {
   emitWordLE(Binary);
 }
 
+void ARMCodeEmitter::emitVFPLoadStoreInstruction(const MachineInstr &MI) {
+  // Part of binary is determined by TableGn.
+  unsigned Binary = getBinaryCodeForInstr(MI);
+
+  // Set the conditional execution predicate
+  Binary |= II->getPredicate(&MI) << ARMII::CondShift;
+
+  unsigned OpIdx = 0;
+
+  // Encode Dd / Sd.
+  unsigned RegD = getMachineOpValue(MI, OpIdx++);
+  Binary |= (RegD & 0x0f) << ARMII::RegRdShift;
+  Binary |= (RegD & 0x10) << ARMII::D_BitShift;
+
+  // Encode address base.
+  const MachineOperand &Base = MI.getOperand(OpIdx++);
+  Binary |= getMachineOpValue(MI, Base) << ARMII::RegRnShift;
+
+  // If there is a non-zero immediate offset, encode it.
+  if (Base.isReg()) {
+    const MachineOperand &Offset = MI.getOperand(OpIdx);
+    if (unsigned ImmOffs = ARM_AM::getAM5Offset(Offset.getImm())) {
+      if (ARM_AM::getAM5Op(Offset.getImm()) == ARM_AM::add)
+        Binary |= 1 << ARMII::U_BitShift;
+      // Immediate offset is multiplied by 4.
+      Binary |= ImmOffs >> 2;
+      emitWordLE(Binary);
+      return;
+    }
+  }
+
+  // If immediate offset is omitted, default to +0.
+  Binary |= 1 << ARMII::U_BitShift;
+
+  emitWordLE(Binary);
+}
+
+void
+ARMCodeEmitter::emitVFPLoadStoreMultipleInstruction(const MachineInstr &MI) {
+  // Part of binary is determined by TableGn.
+  unsigned Binary = getBinaryCodeForInstr(MI);
+
+  // Set the conditional execution predicate
+  Binary |= II->getPredicate(&MI) << ARMII::CondShift;
+
+  // Set base address operand
+  Binary |= getMachineOpValue(MI, 0) << ARMII::RegRnShift;
+
+  // Set addressing mode by modifying bits U(23) and P(24)
+  const MachineOperand &MO = MI.getOperand(1);
+  Binary |= getAddrModeUPBits(ARM_AM::getAM5SubMode(MO.getImm()));
+
+  // Set bit W(21)
+  if (ARM_AM::getAM5WBFlag(MO.getImm()))
+    Binary |= 0x1 << ARMII::W_BitShift;
+
+  // First register is encoded in Dd.
+  unsigned FirstReg = MI.getOperand(4).getReg();
+  Binary |= ARMRegisterInfo::getRegisterNumbering(FirstReg)<< ARMII::RegRdShift;
+
+  // Number of registers are encoded in offset field.
+  unsigned NumRegs = 1;
+  for (unsigned i = 5, e = MI.getNumOperands(); i != e; ++i) {
+    const MachineOperand &MO = MI.getOperand(i);
+    if (!MO.isReg() || MO.isImplicit())
+      break;
+    ++NumRegs;
+  }
+  Binary |= NumRegs * 2;
+
+  emitWordLE(Binary);
+}
+
+void ARMCodeEmitter::emitMiscInstruction(const MachineInstr &MI) {
+  // Part of binary is determined by TableGn.
+  unsigned Binary = getBinaryCodeForInstr(MI);
+
+  // Set the conditional execution predicate
+  Binary |= II->getPredicate(&MI) << ARMII::CondShift;
+
+  emitWordLE(Binary);
+}
+
 #include "ARMGenCodeEmitter.inc"
index 5efa76db8e143591e74f6000952a4777647e11b0..b59af13cd9e8d02f023e3e2ef110dcdf343c41cd 100644 (file)
@@ -19,29 +19,33 @@ class Format<bits<5> val> {
   bits<5> Value = val;
 }
 
-def Pseudo      : Format<1>;
-def MulFrm      : Format<2>;
-def BrFrm       : Format<3>;
-def BrMiscFrm   : Format<4>;
-
-def DPFrm       : Format<5>;
-def DPSoRegFrm  : Format<6>;
-
-def LdFrm       : Format<7>;
-def StFrm       : Format<8>;
-def LdMiscFrm   : Format<9>;
-def StMiscFrm   : Format<10>;
-def LdMulFrm    : Format<11>;
-def StMulFrm    : Format<12>;
-
-def ArithMiscFrm: Format<13>;
-def ExtFrm      : Format<14>;
-def VFPFrm      : Format<15>;
-def VFPUnaryFrm : Format<16>;
-def VFPBinaryFrm: Format<17>;
-def VFPConv1Frm : Format<18>;
-def VFPConv2Frm : Format<19>;
-def ThumbFrm    : Format<20>;
+def Pseudo        : Format<1>;
+def MulFrm        : Format<2>;
+def BrFrm         : Format<3>;
+def BrMiscFrm     : Format<4>;
+
+def DPFrm         : Format<5>;
+def DPSoRegFrm    : Format<6>;
+
+def LdFrm         : Format<7>;
+def StFrm         : Format<8>;
+def LdMiscFrm     : Format<9>;
+def StMiscFrm     : Format<10>;
+def LdMulFrm      : Format<11>;
+def StMulFrm      : Format<12>;
+
+def ArithMiscFrm  : Format<13>;
+def ExtFrm        : Format<14>;
+
+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 ThumbFrm      : Format<22>;
 
 // Misc flag for data processing instructions that indicates whether
 // the instruction has a Rn register operand.
@@ -738,30 +742,45 @@ class TJTI<dag outs, dag ins, string asm, list<dag> pattern>
 // ARM VFP Instruction templates.
 //
 
-// ARM Float Instruction
-class ASI<dag oops, dag iops, string opc, string asm, list<dag> pattern>
-  : AI<oops, iops, VFPFrm, opc, asm, pattern> {
+// ARM VFP addrmode5 loads and stores
+class ADI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops,
+           string opc, string asm, list<dag> pattern>
+  : I<oops, iops, AddrMode5, Size4Bytes, IndexModeNone,
+      VFPLdStFrm, opc, asm, "", pattern> {
   // TODO: Mark the instructions with the appropriate subtarget info.
+  let Inst{27-24} = opcod1;
+  let Inst{21-20} = opcod2;
+  let Inst{11-8}  = 0b1011;
 }
 
-class ASI5<dag oops, dag iops, string opc, string asm, list<dag> pattern>
+class ASI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops,
+           string opc, string asm, list<dag> pattern>
   : I<oops, iops, AddrMode5, Size4Bytes, IndexModeNone,
-      VFPFrm, opc, asm, "", pattern> {
+      VFPLdStFrm, opc, asm, "", pattern> {
   // TODO: Mark the instructions with the appropriate subtarget info.
+  let Inst{27-24} = opcod1;
+  let Inst{21-20} = opcod2;
+  let Inst{11-8}  = 0b1010;
 }
 
-// ARM Double Instruction
-class ADI<dag oops, dag iops, string opc, string asm, list<dag> pattern>
-  : AI<oops, iops, VFPFrm, opc, asm, pattern> {
+// Load / store multiple
+class AXSI5<dag oops, dag iops, string asm, list<dag> pattern>
+  : XI<oops, iops, AddrMode5, Size4Bytes, IndexModeNone,
+       VFPLdStMulFrm, asm, "", pattern> {
   // TODO: Mark the instructions with the appropriate subtarget info.
+  let Inst{27-25} = 0b110;
+  let Inst{11-8}  = 0b1011;
 }
 
-class ADI5<dag oops, dag iops, string opc, string asm, list<dag> pattern>
-  : I<oops, iops, AddrMode5, Size4Bytes, IndexModeNone,
-      VFPFrm, opc, asm, "", pattern> {
+class AXDI5<dag oops, dag iops, string asm, list<dag> pattern>
+  : XI<oops, iops, AddrMode5, Size4Bytes, IndexModeNone,
+       VFPLdStMulFrm, asm, "", pattern> {
   // TODO: Mark the instructions with the appropriate subtarget info.
+  let Inst{27-25} = 0b110;
+  let Inst{11-8}  = 0b1010;
 }
 
+
 // Double precision, unary
 class ADuI<bits<8> opcod1, bits<4> opcod2, bits<4> opcod3, dag oops, dag iops,
            string opc, string asm, list<dag> pattern>
@@ -817,32 +836,6 @@ class AVConv2I<bits<8> opcod1, bits<4> opcod2, bits<4> opcod3,
   let Inst{6}     = 1;
 }
 
-// Special cases.
-class AXSI<dag oops, dag iops, string asm, list<dag> pattern>
-  : XI<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone,
-       VFPFrm, asm, "", pattern> {
-  // TODO: Mark the instructions with the appropriate subtarget info.
-}
-
-class AXSI5<dag oops, dag iops, string asm, list<dag> pattern>
-  : XI<oops, iops, AddrMode5, Size4Bytes, IndexModeNone,
-       VFPFrm, asm, "", pattern> {
-  // TODO: Mark the instructions with the appropriate subtarget info.
-}
-
-class AXDI<dag oops, dag iops, string asm, list<dag> pattern>
-  : XI<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone,
-       VFPFrm, asm, "", pattern> {
-  // TODO: Mark the instructions with the appropriate subtarget info.
-}
-
-class AXDI5<dag oops, dag iops, string asm, list<dag> pattern>
-  : XI<oops, iops, AddrMode5, Size4Bytes, IndexModeNone,
-       VFPFrm, asm, "", pattern> {
-  // TODO: Mark the instructions with the appropriate subtarget info.
-}
-
-
 //===----------------------------------------------------------------------===//
 
 
index ccaeac56a122370a5ff970ba074761752383359d..c77a6288f6f6dc5a1cc55e7832bb0bcf3b2b63bd 100644 (file)
@@ -69,46 +69,48 @@ namespace ARMII {
     //===------------------------------------------------------------------===//
     // Instruction encoding formats.
     //
-    FormShift   = 10,
-    FormMask    = 0x1f << FormShift,
+    FormShift     = 10,
+    FormMask      = 0x1f << FormShift,
 
     // Pseudo instructions
-    Pseudo      = 1 << FormShift,
+    Pseudo        = 1 << FormShift,
 
     // Multiply instructions
-    MulFrm      = 2 << FormShift,
+    MulFrm        = 2 << FormShift,
 
     // Branch instructions
-    BrFrm       = 3 << FormShift,
-    BrMiscFrm   = 4 << FormShift,
+    BrFrm         = 3 << FormShift,
+    BrMiscFrm     = 4 << FormShift,
 
     // Data Processing instructions
-    DPFrm       = 5 << FormShift,
-    DPSoRegFrm  = 6 << FormShift,
+    DPFrm         = 5 << FormShift,
+    DPSoRegFrm    = 6 << FormShift,
 
     // Load and Store
-    LdFrm       = 7  << FormShift,
-    StFrm       = 8  << FormShift,
-    LdMiscFrm   = 9  << FormShift,
-    StMiscFrm   = 10 << FormShift,
-    LdMulFrm    = 11 << FormShift,
-    StMulFrm    = 12 << FormShift,
+    LdFrm         = 7  << FormShift,
+    StFrm         = 8  << FormShift,
+    LdMiscFrm     = 9  << FormShift,
+    StMiscFrm     = 10 << FormShift,
+    LdMulFrm      = 11 << FormShift,
+    StMulFrm      = 12 << FormShift,
 
     // Miscellaneous arithmetic instructions
-    ArithMiscFrm= 13 << FormShift,
+    ArithMiscFrm  = 13 << FormShift,
 
     // Extend instructions
-    ExtFrm      = 14 << FormShift,
+    ExtFrm        = 14 << FormShift,
 
     // VFP formats
-    VPFFrm       = 15 << FormShift,
-    VFPUnaryFrm  = 16 << FormShift,
-    VFPBinaryFrm = 17 << FormShift,
-    VFPConv1Frm  = 18 << FormShift,
-    VFPConv2Frm  = 19 << FormShift,
+    VFPUnaryFrm   = 15 << FormShift,
+    VFPBinaryFrm  = 16 << FormShift,
+    VFPConv1Frm   = 17 << FormShift,
+    VFPConv2Frm   = 18 << FormShift,
+    VFPLdStFrm    = 19 << FormShift,
+    VFPLdStMulFrm = 20 << FormShift,
+    VFPMiscFrm    = 21 << FormShift,
 
     // Thumb format
-    ThumbFrm     = 20 << FormShift,
+    ThumbFrm      = 22 << FormShift,
 
     //===------------------------------------------------------------------===//
     // Field shifts - such shifts are used to set field while generating
index 2dc3f0bacf885b29470cbd0fe6f2a09cd58977bd..442c12abcb93035f17df97ce61cab73eb8281277 100644 (file)
@@ -35,20 +35,20 @@ def arm_fmdrr  : SDNode<"ARMISD::FMDRR",  SDT_FMDRR>;
 //
 
 let isSimpleLoad = 1 in {
-def FLDD  : ADI5<(outs DPR:$dst), (ins addrmode5:$addr),
+def FLDD  : ADI5<0b1101, 0b01, (outs DPR:$dst), (ins addrmode5:$addr),
                  "fldd", " $dst, $addr",
                  [(set DPR:$dst, (load addrmode5:$addr))]>;
 
-def FLDS  : ASI5<(outs SPR:$dst), (ins addrmode5:$addr),
+def FLDS  : ASI5<0b1101, 0b01, (outs SPR:$dst), (ins addrmode5:$addr),
                  "flds", " $dst, $addr",
                  [(set SPR:$dst, (load addrmode5:$addr))]>;
 } // isSimpleLoad
 
-def FSTD  : ADI5<(outs), (ins DPR:$src, addrmode5:$addr),
+def FSTD  : ADI5<0b1101, 0b00, (outs), (ins DPR:$src, addrmode5:$addr),
                  "fstd", " $src, $addr",
                  [(store DPR:$src, addrmode5:$addr)]>;
 
-def FSTS  : ASI5<(outs), (ins SPR:$src, addrmode5:$addr),
+def FSTS  : ASI5<0b1101, 0b00, (outs), (ins SPR:$src, addrmode5:$addr),
                  "fsts", " $src, $addr",
                  [(store SPR:$src, addrmode5:$addr)]>;
 
@@ -60,24 +60,32 @@ let mayLoad = 1 in {
 def FLDMD : AXDI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$dst1,
                            variable_ops),
                   "fldm${addr:submode}d${p} ${addr:base}, $dst1",
-                  []>;
+                  []> {
+  let Inst{20} = 1;
+}
 
 def FLDMS : AXSI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$dst1,
                            variable_ops),
                   "fldm${addr:submode}s${p} ${addr:base}, $dst1",
-                  []>;
+                  []> {
+  let Inst{20} = 1;
+}
 }
 
 let mayStore = 1 in {
 def FSTMD : AXDI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$src1,
                            variable_ops),
                  "fstm${addr:submode}d${p} ${addr:base}, $src1",
-                 []>;
+                 []> {
+  let Inst{20} = 0;
+}
 
 def FSTMS : AXSI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$src1,
                            variable_ops),
                  "fstm${addr:submode}s${p} ${addr:base}, $src1",
-                 []>;
+                 []> {
+  let Inst{20} = 0;
+}
 } // mayStore
 
 // FLDMX, FSTMX - mixing S/D registers for pre-armv6 cores
@@ -384,4 +392,11 @@ def FNEGScc  : ASuI<0b11101011, 0b0001, 0b0100,
 //
 
 let Defs = [CPSR] in
-def FMSTAT : ASI<(outs), (ins), "fmstat", "", [(arm_fmstat)]>;
+def FMSTAT : AI<(outs), (ins), VFPMiscFrm, "fmstat", "", [(arm_fmstat)]> {
+  let Inst{27-20} = 0b11101111;
+  let Inst{19-16} = 0b0001;
+  let Inst{15-12} = 0b1111;
+  let Inst{11-8}  = 0b1010;
+  let Inst{7}     = 0;
+  let Inst{4}     = 1;
+}