Restructure ARM code emitter to use instruction formats instead of addressing modes to determine how to encode instructions.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@58764 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/ARM/ARMCodeEmitter.cpp b/lib/Target/ARM/ARMCodeEmitter.cpp
index 47aa22b..193df98 100644
--- a/lib/Target/ARM/ARMCodeEmitter.cpp
+++ b/lib/Target/ARM/ARMCodeEmitter.cpp
@@ -69,10 +69,6 @@
 
     void emitPseudoInstruction(const MachineInstr &MI);
 
-    unsigned getAddrModeNoneInstrBinary(const MachineInstr &MI,
-                                        const TargetInstrDesc &TID,
-                                        unsigned Binary);
-
     unsigned getMachineSoRegOpValue(const MachineInstr &MI,
                                     const TargetInstrDesc &TID,
                                     const MachineOperand &MO,
@@ -85,25 +81,19 @@
     unsigned getAddrModeSBit(const MachineInstr &MI,
                              const TargetInstrDesc &TID) const;
 
-    unsigned getAddrMode1InstrBinary(const MachineInstr &MI,
-                                     const TargetInstrDesc &TID,
-                                     unsigned Binary);
-    unsigned getAddrMode2InstrBinary(const MachineInstr &MI,
-                                     const TargetInstrDesc &TID,
-                                     unsigned Binary);
-    unsigned getAddrMode3InstrBinary(const MachineInstr &MI,
-                                     const TargetInstrDesc &TID,
-                                     unsigned Binary);
-    unsigned getAddrMode4InstrBinary(const MachineInstr &MI,
-                                     const TargetInstrDesc &TID,
-                                     unsigned Binary);
-    unsigned getAddrMode6InstrBinary(const MachineInstr &MI,
-                                     const TargetInstrDesc &TID,
-                                     unsigned Binary);
+    void emitDataProcessingInstruction(const MachineInstr &MI);
 
-    /// getInstrBinary - Return binary encoding for the specified
-    /// machine instruction.
-    unsigned getInstrBinary(const MachineInstr &MI);
+    void emitLoadStoreInstruction(const MachineInstr &MI);
+
+    void emitMiscLoadStoreInstruction(const MachineInstr &MI);
+
+    void emitLoadStoreMultipleInstruction(const MachineInstr &MI);
+
+    void emitMulFrm1Instruction(const MachineInstr &MI);
+
+    void emitBranchInstruction(const MachineInstr &MI);
+
+    void emitMiscBranchInstruction(const MachineInstr &MI);
 
     /// getBinaryCodeForInstr - This function, generated by the
     /// CodeEmitterGenerator using TableGen, produces the binary encoding for
@@ -260,10 +250,39 @@
   DOUT << "JIT: " << (void*)MCE.getCurrentPCValue() << ":\t" << MI;
 
   NumEmitted++;  // Keep track of the # of mi's emitted
-  if ((MI.getDesc().TSFlags & ARMII::FormMask) == ARMII::Pseudo)
+  switch (MI.getDesc().TSFlags & ARMII::FormMask) {
+  default:
+    assert(0 && "Unhandled instruction encoding format!");
+    break;
+  case ARMII::Pseudo:
     emitPseudoInstruction(MI);
-  else
-    MCE.emitWordLE(getInstrBinary(MI));
+    break;
+  case ARMII::DPFrm:
+  case ARMII::DPSoRegFrm:
+    emitDataProcessingInstruction(MI);
+    break;
+  case ARMII::LdFrm:
+  case ARMII::StFrm:
+    emitLoadStoreInstruction(MI);
+    break;
+  case ARMII::LdMiscFrm:
+  case ARMII::StMiscFrm:
+    emitMiscLoadStoreInstruction(MI);
+    break;
+  case ARMII::LdMulFrm:
+  case ARMII::StMulFrm:
+    emitLoadStoreMultipleInstruction(MI);
+    break;
+  case ARMII::MulFrm1:
+    emitMulFrm1Instruction(MI);
+    break;
+  case ARMII::Branch:
+    emitBranchInstruction(MI);
+    break;
+  case ARMII::BranchMisc:
+    emitMiscBranchInstruction(MI);
+    break;
+  }
 }
 
 void ARMCodeEmitter::emitConstPoolInstruction(const MachineInstr &MI) {
@@ -329,51 +348,13 @@
     JTI->addPCLabelAddr(MO2.getImm(), MCE.getCurrentPCValue());
 
     // PICADD is just an add instruction that implicitly read pc.
-    unsigned Binary = getBinaryCodeForInstr(MI);
-    const TargetInstrDesc &TID = MI.getDesc();
-    MCE.emitWordLE(getAddrMode1InstrBinary(MI, TID, Binary));
+    emitDataProcessingInstruction(MI);
     break;
   }
   }
 }
 
 
-unsigned ARMCodeEmitter::getAddrModeNoneInstrBinary(const MachineInstr &MI,
-                                                    const TargetInstrDesc &TID,
-                                                    unsigned Binary) {
-  // Set the conditional execution predicate
-  Binary |= II->getPredicate(&MI) << 28;
-
-  switch (TID.TSFlags & ARMII::FormMask) {
-  default:
-    assert(0 && "Unknown instruction subtype!");
-    break;
-  case ARMII::Branch: {
-    // Set signed_immed_24 field
-    Binary |= getMachineOpValue(MI, 0);
-
-    // if it is a conditional branch, set cond field
-    if (TID.Opcode == ARM::Bcc) {
-      Binary &= 0x0FFFFFFF;                      // clear conditional field
-      Binary |= getMachineOpValue(MI, 1) << 28;  // set conditional field
-    }
-    break;
-  }
-  case ARMII::BranchMisc: {
-    if (TID.Opcode == ARM::BX)
-      abort(); // FIXME
-    if (TID.Opcode == ARM::BX_RET)
-      Binary |= 0xe; // the return register is LR
-    else 
-      // otherwise, set the return register
-      Binary |= getMachineOpValue(MI, 0);
-    break;
-  }
-  }
-
-  return Binary;
-}
-
 unsigned ARMCodeEmitter::getMachineSoRegOpValue(const MachineInstr &MI,
                                                 const TargetInstrDesc &TID,
                                                 const MachineOperand &MO,
@@ -453,9 +434,14 @@
   return 0;
 }
 
-unsigned ARMCodeEmitter::getAddrMode1InstrBinary(const MachineInstr &MI,
-                                                 const TargetInstrDesc &TID,
-                                                 unsigned Binary) {
+void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI) {
+  const TargetInstrDesc &TID = MI.getDesc();
+  if (TID.getOpcode() == ARM::MOVi2pieces)
+    abort(); // FIXME
+
+  // Part of binary is determined by TableGn.
+  unsigned Binary = getBinaryCodeForInstr(MI);
+
   // Set the conditional execution predicate
   Binary |= II->getPredicate(&MI) << 28;
 
@@ -471,16 +457,12 @@
   }
 
   // Encode first non-shifter register operand if there is one.
-  unsigned Format = TID.TSFlags & ARMII::FormMask;
-  bool HasRnReg = !(Format == ARMII::DPRdMisc  ||
-                    Format == ARMII::DPRdIm    ||
-                    Format == ARMII::DPRdReg   ||
-                    Format == ARMII::DPRdSoReg);
-  if (HasRnReg) {
+  bool isUnary = TID.TSFlags & ARMII::UnaryDP;
+  if (!isUnary) {
     if (TID.getOpcode() == ARM::PICADD)
-      // Special handling for PICADD. It implicitly use add.
-      Binary |=
-        ARMRegisterInfo::getRegisterNumbering(ARM::PC) << ARMII::RegRnShift;
+      // Special handling for PICADD. It implicitly uses PC register.
+      Binary |= (ARMRegisterInfo::getRegisterNumbering(ARM::PC)
+                 << ARMII::RegRnShift);
     else {
       Binary |= getMachineOpValue(MI, OpIdx) << ARMII::RegRnShift;
       ++OpIdx;
@@ -488,30 +470,33 @@
   }
 
   // Encode shifter operand.
-  bool HasSoReg = (Format == ARMII::DPRdSoReg ||
-                   Format == ARMII::DPRnSoReg ||
-                   Format == ARMII::DPRSoReg  ||
-                   Format == ARMII::DPRSoRegS);
-
   const MachineOperand &MO = MI.getOperand(OpIdx);
-  if (HasSoReg)
+  if ((TID.TSFlags & ARMII::FormMask) == ARMII::DPSoRegFrm) {
     // Encode SoReg.
-    return Binary | getMachineSoRegOpValue(MI, TID, MO, OpIdx);
+    MCE.emitWordLE(Binary | getMachineSoRegOpValue(MI, TID, MO, OpIdx));
+    return;
+  }
 
-  if (MO.isReg())
+  if (MO.isReg()) {
     // Encode register Rm.
-    return Binary | ARMRegisterInfo::getRegisterNumbering(MO.getReg());
+    MCE.emitWordLE(Binary | ARMRegisterInfo::getRegisterNumbering(MO.getReg()));
+    return;
+  }
 
   // Encode so_imm.
   // Set bit I(25) to identify this is the immediate form of <shifter_op>
   Binary |= 1 << ARMII::I_BitShift;
   Binary |= getMachineSoImmOpValue(MI, TID, MO);
-  return Binary;
+
+  MCE.emitWordLE(Binary);
 }
 
-unsigned ARMCodeEmitter::getAddrMode2InstrBinary(const MachineInstr &MI,
-                                                 const TargetInstrDesc &TID,
-                                                 unsigned Binary) {
+void ARMCodeEmitter::emitLoadStoreInstruction(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) << 28;
 
@@ -531,7 +516,8 @@
     if (ARM_AM::getAM2Offset(MO3.getImm()))
       // Set the value of offset_12 field
       Binary |= ARM_AM::getAM2Offset(MO3.getImm());
-    return Binary;
+    MCE.emitWordLE(Binary);
+    return;
   }
 
   // Set bit I(25), because this is not in immediate enconding.
@@ -547,12 +533,15 @@
     Binary |= ShImm           << 7;  // shift_immed
   }
 
-  return Binary;
+  MCE.emitWordLE(Binary);
 }
 
-unsigned ARMCodeEmitter::getAddrMode3InstrBinary(const MachineInstr &MI,
-                                                 const TargetInstrDesc &TID,
-                                                 unsigned Binary) {
+void ARMCodeEmitter::emitMiscLoadStoreInstruction(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) << 28;
 
@@ -573,7 +562,8 @@
   // to the corresponding Rm register.
   if (MO2.getReg()) {
     Binary |= ARMRegisterInfo::getRegisterNumbering(MO2.getReg());
-    return Binary;
+    MCE.emitWordLE(Binary);
+    return;
   }
 
   // if this instr is in immediate offset/index encoding, set bit 22 to 1
@@ -584,12 +574,15 @@
     Binary |= (ImmOffs & ~0xF);     // immedL
   }
 
-  return Binary;
+  MCE.emitWordLE(Binary);
 }
 
-unsigned ARMCodeEmitter::getAddrMode4InstrBinary(const MachineInstr &MI,
-                                                 const TargetInstrDesc &TID,
-                                                 unsigned Binary) {
+void ARMCodeEmitter::emitLoadStoreMultipleInstruction(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) << 28;
 
@@ -626,12 +619,15 @@
     Binary |= 0x1 << RegNum;
   }
 
-  return Binary;
+  MCE.emitWordLE(Binary);
 }
 
-unsigned ARMCodeEmitter::getAddrMode6InstrBinary(const MachineInstr &MI,
-                                                 const TargetInstrDesc &TID,
-                                                 unsigned Binary) {
+void ARMCodeEmitter::emitMulFrm1Instruction(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) << 28;
 
@@ -653,33 +649,49 @@
   // Encode Rs
   Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRsShift;
 
-  return Binary;
+  MCE.emitWordLE(Binary);
 }
 
-/// getInstrBinary - Return binary encoding for the specified
-/// machine instruction.
-unsigned ARMCodeEmitter::getInstrBinary(const MachineInstr &MI) {
+void ARMCodeEmitter::emitBranchInstruction(const MachineInstr &MI) {
+  const TargetInstrDesc &TID = MI.getDesc();
+
   // Part of binary is determined by TableGn.
   unsigned Binary = getBinaryCodeForInstr(MI);
 
-  const TargetInstrDesc &TID = MI.getDesc();
-  switch (TID.TSFlags & ARMII::AddrModeMask) {
-  case ARMII::AddrModeNone:
-    return getAddrModeNoneInstrBinary(MI, TID, Binary);
-  case ARMII::AddrMode1:
-    return getAddrMode1InstrBinary(MI, TID, Binary);
-  case ARMII::AddrMode2:
-    return getAddrMode2InstrBinary(MI, TID, Binary);
-  case ARMII::AddrMode3:
-    return getAddrMode3InstrBinary(MI, TID, Binary);
-  case ARMII::AddrMode4:
-    return getAddrMode4InstrBinary(MI, TID, Binary);
-  case ARMII::AddrMode6:
-    return getAddrMode6InstrBinary(MI, TID, Binary);
+  // Set the conditional execution predicate
+  Binary |= II->getPredicate(&MI) << 28;
+
+  // Set signed_immed_24 field
+  Binary |= getMachineOpValue(MI, 0);
+
+  // if it is a conditional branch, set cond field
+  if (TID.Opcode == ARM::Bcc) {
+    Binary &= 0x0FFFFFFF;                      // clear conditional field
+    Binary |= getMachineOpValue(MI, 1) << 28;  // set conditional field
   }
 
-  abort();
-  return 0;
+  MCE.emitWordLE(Binary);
+}
+
+void ARMCodeEmitter::emitMiscBranchInstruction(const MachineInstr &MI) {
+  const TargetInstrDesc &TID = MI.getDesc();
+  if (TID.Opcode == ARM::BX)
+    abort(); // FIXME
+
+  // Part of binary is determined by TableGn.
+  unsigned Binary = getBinaryCodeForInstr(MI);
+
+  // Set the conditional execution predicate
+  Binary |= II->getPredicate(&MI) << 28;
+
+  if (TID.Opcode == ARM::BX_RET)
+    // The return register is LR.
+    Binary |= ARMRegisterInfo::getRegisterNumbering(ARM::LR);
+  else 
+    // otherwise, set the return register
+    Binary |= getMachineOpValue(MI, 0);
+
+  MCE.emitWordLE(Binary);
 }
 
 #include "ARMGenCodeEmitter.inc"