Encode misc arithmetic instructions.
authorEvan Cheng <evan.cheng@apple.com>
Fri, 7 Nov 2008 01:41:35 +0000 (01:41 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Fri, 7 Nov 2008 01:41:35 +0000 (01:41 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@58828 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 57fde477bc424e14ce7848172e8442d2be55e25f..f786df97b8a5a0252e577f99b89767a8da9bc6eb 100644 (file)
@@ -100,6 +100,8 @@ namespace {
 
     void emitExtendInstruction(const MachineInstr &MI);
 
+    void emitMiscArithInstruction(const MachineInstr &MI);
+
     void emitBranchInstruction(const MachineInstr &MI);
 
     void emitMiscBranchInstruction(const MachineInstr &MI);
@@ -287,6 +289,9 @@ void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) {
   case ARMII::ExtFrm:
     emitExtendInstruction(MI);
     break;
+  case ARMII::ArithMiscFrm:
+    emitMiscArithInstruction(MI);
+    break;
   case ARMII::BrFrm:
     emitBranchInstruction(MI);
     break;
@@ -790,6 +795,44 @@ void ARMCodeEmitter::emitExtendInstruction(const MachineInstr &MI) {
   emitWordLE(Binary);
 }
 
+void ARMCodeEmitter::emitMiscArithInstruction(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;
+
+  unsigned OpIdx = 0;
+
+  // Encode Rd
+  Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRdShift;
+
+  const MachineOperand &MO = MI.getOperand(OpIdx++);
+  if (OpIdx == TID.getNumOperands() ||
+      TID.OpInfo[OpIdx].isPredicate() ||
+      TID.OpInfo[OpIdx].isOptionalDef()) {
+    // Encode Rm and it's done.
+    Binary |= getMachineOpValue(MI, MO);
+    emitWordLE(Binary);
+    return;
+  }
+
+  // Encode Rn.
+  Binary |= getMachineOpValue(MI, MO) << ARMII::RegRnShift;
+
+  // Encode Rm.
+  Binary |= getMachineOpValue(MI, OpIdx++);
+
+  // Encode shift_imm.
+  unsigned ShiftAmt = MI.getOperand(OpIdx).getImm();
+  assert(ShiftAmt < 32 && "shift_imm range is 0 to 31!");
+  Binary |= ShiftAmt << ARMII::ShiftShift;
+  
+  emitWordLE(Binary);
+}
+
 void ARMCodeEmitter::emitBranchInstruction(const MachineInstr &MI) {
   const TargetInstrDesc &TID = MI.getDesc();
 
index d5fca09bafe06bd8c9801543c664ab9822270a86..90e27fa94d81942cfdcb0114febd1530a13e4faf 100644 (file)
@@ -689,6 +689,14 @@ class AExtI<bits<8> opcod, dag oops, dag iops, string opc,
   let Inst{27-20} = opcod;
 }
 
+// Misc Arithmetic instructions.
+class AMiscA1I<bits<8> opcod, dag oops, dag iops, string opc,
+               string asm, list<dag> pattern>
+  : I<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, ArithMiscFrm, opc,
+      asm, "", pattern> {
+  let Inst{27-20} = opcod;
+}
+
 //===----------------------------------------------------------------------===//
 
 // ARMPat - Same as Pat<>, but requires that the compiler be in ARM mode.
index 22fe3796597b879ceba82a5c0048b422142fa929..0a8432ce985656eac81aa50f2ea3e1a07932fd61 100644 (file)
@@ -109,6 +109,7 @@ namespace ARMII {
     //===------------------------------------------------------------------===//
     // Field shifts - such shifts are used to set field while generating
     // machine instructions.
+    ShiftShift     = 7,
     SoRotImmShift  = 8,
     RegRsShift     = 8,
     ExtRotImmShift = 10,
index cb40b1fd233f3bc568049bb09b759b4486b74be0..45cee486d8e67e0fe89f4ecf0aca6bc289978898 100644 (file)
@@ -1101,37 +1101,56 @@ defm SMLA : AI_smla<"smla", BinOpFrag<(mul node:$LHS, node:$RHS)>>;
 //  Misc. Arithmetic Instructions.
 //
 
-def CLZ  : AI<(outs GPR:$dst), (ins GPR:$src), ArithMiscFrm,
+def CLZ  : AMiscA1I<0b000010110, (outs GPR:$dst), (ins GPR:$src),
               "clz", " $dst, $src",
-              [(set GPR:$dst, (ctlz GPR:$src))]>, Requires<[IsARM, HasV5T]>;
+              [(set GPR:$dst, (ctlz GPR:$src))]>, Requires<[IsARM, HasV5T]> {
+  let Inst{7-4}   = 0b0001;
+  let Inst{11-8}  = 0b1111;
+  let Inst{19-16} = 0b1111;
+}
 
-def REV  : AI<(outs GPR:$dst), (ins GPR:$src), ArithMiscFrm,
+def REV  : AMiscA1I<0b01101011, (outs GPR:$dst), (ins GPR:$src),
               "rev", " $dst, $src",
-              [(set GPR:$dst, (bswap GPR:$src))]>, Requires<[IsARM, HasV6]>;
+              [(set GPR:$dst, (bswap GPR:$src))]>, Requires<[IsARM, HasV6]> {
+  let Inst{7-4}   = 0b0011;
+  let Inst{11-8}  = 0b1111;
+  let Inst{19-16} = 0b1111;
+}
 
-def REV16 : AI<(outs GPR:$dst), (ins GPR:$src), ArithMiscFrm,
+def REV16 : AMiscA1I<0b01101011, (outs GPR:$dst), (ins GPR:$src),
                "rev16", " $dst, $src",
                [(set GPR:$dst,
                    (or (and (srl GPR:$src, 8), 0xFF),
                        (or (and (shl GPR:$src, 8), 0xFF00),
                            (or (and (srl GPR:$src, 8), 0xFF0000),
                                (and (shl GPR:$src, 8), 0xFF000000)))))]>,
-               Requires<[IsARM, HasV6]>;
+               Requires<[IsARM, HasV6]> {
+  let Inst{7-4}   = 0b1011;
+  let Inst{11-8}  = 0b1111;
+  let Inst{19-16} = 0b1111;
+}
 
-def REVSH : AI<(outs GPR:$dst), (ins GPR:$src), ArithMiscFrm,
+def REVSH : AMiscA1I<0b01101111, (outs GPR:$dst), (ins GPR:$src),
                "revsh", " $dst, $src",
                [(set GPR:$dst,
                   (sext_inreg
                     (or (srl (and GPR:$src, 0xFF00), 8),
                         (shl GPR:$src, 8)), i16))]>,
-               Requires<[IsARM, HasV6]>;
+               Requires<[IsARM, HasV6]> {
+  let Inst{7-4}   = 0b1011;
+  let Inst{11-8}  = 0b1111;
+  let Inst{19-16} = 0b1111;
+}
 
-def PKHBT : AI<(outs GPR:$dst), (ins GPR:$src1, GPR:$src2, i32imm:$shamt),
-               ArithMiscFrm, "pkhbt", " $dst, $src1, $src2, LSL $shamt",
+def PKHBT : AMiscA1I<0b01101000, (outs GPR:$dst),
+                                 (ins GPR:$src1, GPR:$src2, i32imm:$shamt),
+               "pkhbt", " $dst, $src1, $src2, LSL $shamt",
                [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF),
                                    (and (shl GPR:$src2, (i32 imm:$shamt)),
                                         0xFFFF0000)))]>,
-               Requires<[IsARM, HasV6]>;
+               Requires<[IsARM, HasV6]> {
+  let Inst{6-4} = 0b001;
+}
 
 // Alternate cases for PKHBT where identities eliminate some nodes.
 def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF), (and GPR:$src2, 0xFFFF0000)),
@@ -1140,11 +1159,14 @@ def : ARMV6Pat<(or (and GPR:$src1, 0xFFFF), (shl GPR:$src2, imm16_31:$shamt)),
                (PKHBT GPR:$src1, GPR:$src2, imm16_31:$shamt)>;
 
 
-def PKHTB : AI<(outs GPR:$dst), (ins GPR:$src1, GPR:$src2, i32imm:$shamt),
-               ArithMiscFrm, "pkhtb", " $dst, $src1, $src2, ASR $shamt",
+def PKHTB : AMiscA1I<0b01101000, (outs GPR:$dst),
+                                 (ins GPR:$src1, GPR:$src2, i32imm:$shamt),
+               "pkhtb", " $dst, $src1, $src2, ASR $shamt",
                [(set GPR:$dst, (or (and GPR:$src1, 0xFFFF0000),
                                    (and (sra GPR:$src2, imm16_31:$shamt),
-                                        0xFFFF)))]>, Requires<[IsARM, HasV6]>;
+                                        0xFFFF)))]>, Requires<[IsARM, HasV6]> {
+  let Inst{6-4} = 0b101;
+}
 
 // Alternate cases for PKHTB where identities eliminate some nodes.  Note that
 // a shift amount of 0 is *not legal* here, it is PKHBT instead.