Move the ARM SSAT and USAT optional shift amount operand out of the
authorBob Wilson <bob.wilson@apple.com>
Wed, 11 Aug 2010 23:10:46 +0000 (23:10 +0000)
committerBob Wilson <bob.wilson@apple.com>
Wed, 11 Aug 2010 23:10:46 +0000 (23:10 +0000)
instruction opcode.  This also fixes part of PR7792.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@110875 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/ARM/ARMAsmPrinter.cpp
lib/Target/ARM/ARMCodeEmitter.cpp
lib/Target/ARM/ARMInstrInfo.td
lib/Target/ARM/AsmPrinter/ARMInstPrinter.cpp
lib/Target/ARM/AsmPrinter/ARMInstPrinter.h
lib/Target/ARM/Disassembler/ARMDisassembler.cpp
lib/Target/ARM/Disassembler/ARMDisassemblerCore.cpp
test/MC/Disassembler/arm-tests.txt
utils/TableGen/EDEmitter.cpp

index 12baca6242e45fb2a8a8b685bfd682f754a9b7ee..b09cd73176df169bd1ff47a4121a58bd42d5eb9a 100644 (file)
@@ -120,8 +120,10 @@ namespace {
     void printAddrModePCOperand(const MachineInstr *MI, int OpNum,
                                 raw_ostream &O,
                                 const char *Modifier = 0);
-    void printBitfieldInvMaskImmOperand (const MachineInstr *MI, int OpNum,
-                                         raw_ostream &O);
+    void printBitfieldInvMaskImmOperand(const MachineInstr *MI, int OpNum,
+                                        raw_ostream &O);
+    void printSatShiftOperand(const MachineInstr *MI, int OpNum,
+                              raw_ostream &O);
 
     void printThumbS4ImmOperand(const MachineInstr *MI, int OpNum,
                                 raw_ostream &O);
@@ -669,6 +671,25 @@ ARMAsmPrinter::printBitfieldInvMaskImmOperand(const MachineInstr *MI, int Op,
   O << "#" << lsb << ", #" << width;
 }
 
+void ARMAsmPrinter::printSatShiftOperand(const MachineInstr *MI, int OpNum,
+                                         raw_ostream &O) {
+  unsigned ShiftOp = MI->getOperand(OpNum).getImm();
+  ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp);
+  switch (Opc) {
+  case ARM_AM::no_shift:
+    return;
+  case ARM_AM::lsl:
+    O << ", lsl #";
+    break;
+  case ARM_AM::asr:
+    O << ", asr #";
+    break;
+  default:
+    assert(0 && "unexpected shift opcode for saturate shift operand");
+  }
+  O << ARM_AM::getSORegOffset(ShiftOp);
+}
+
 //===--------------------------------------------------------------------===//
 
 void ARMAsmPrinter::printThumbS4ImmOperand(const MachineInstr *MI, int Op,
index d323a32975aea7618435f2cf44b44fd552b92e5e..5ccba1cedb98659df92be65cfdf26bb14747bb7d 100644 (file)
@@ -1247,9 +1247,7 @@ void ARMCodeEmitter::emitSaturateInstruction(const MachineInstr &MI) {
 
   // Encode saturate bit position.
   unsigned Pos = MI.getOperand(1).getImm();
-  if (TID.Opcode == ARM::SSATlsl ||
-      TID.Opcode == ARM::SSATasr ||
-      TID.Opcode == ARM::SSAT16)
+  if (TID.Opcode == ARM::SSAT || TID.Opcode == ARM::SSAT16)
     Pos -= 1;
   assert((Pos < 16 || (Pos < 32 &&
                        TID.Opcode != ARM::SSAT16 &&
@@ -1262,9 +1260,12 @@ void ARMCodeEmitter::emitSaturateInstruction(const MachineInstr &MI) {
 
   // Encode shift_imm.
   if (TID.getNumOperands() == 4) {
+    unsigned ShiftOp = MI.getOperand(3).getImm();
+    ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp);
+    if (Opc == ARM_AM::asr)
+      Binary |= (1 << 6);
     unsigned ShiftAmt = MI.getOperand(3).getImm();
-    if (ShiftAmt == 32 &&
-        (TID.Opcode == ARM::SSATasr || TID.Opcode == ARM::USATasr))
+    if (ShiftAmt == 32 && Opc == ARM_AM::asr)
       ShiftAmt = 0;
     assert(ShiftAmt < 32 && "shift_imm range is 0 to 31!");
     Binary |= ShiftAmt << ARMII::ShiftShift;
index 4a47b8c9a97615b3a2c04cb56ab5f24411188065..827b743e10f31a39e6732e1a152f7289c6dd0d84 100644 (file)
@@ -1810,20 +1810,15 @@ def USADA8 : AI<(outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$acc),
 
 // Signed/Unsigned saturate -- for disassembly only
 
-def SSATlsl : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a, i32imm:$shamt),
-                 SatFrm, NoItinerary,
-                 "ssat", "\t$dst, $bit_pos, $a, lsl $shamt",
-                 [/* For disassembly only; pattern left blank */]> {
-  let Inst{27-21} = 0b0110101;
-  let Inst{6-4} = 0b001;
+def sat_shift : Operand<i32> {
+  let PrintMethod = "printSatShiftOperand";
 }
 
-def SSATasr : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a, i32imm:$shamt),
-                 SatFrm, NoItinerary,
-                 "ssat", "\t$dst, $bit_pos, $a, asr $shamt",
-                 [/* For disassembly only; pattern left blank */]> {
+def SSAT : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a, sat_shift:$sh),
+              SatFrm, NoItinerary, "ssat", "\t$dst, $bit_pos, $a$sh",
+              [/* For disassembly only; pattern left blank */]> {
   let Inst{27-21} = 0b0110101;
-  let Inst{6-4} = 0b101;
+  let Inst{5-4} = 0b01;
 }
 
 def SSAT16 : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a), SatFrm,
@@ -1833,20 +1828,11 @@ def SSAT16 : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a), SatFrm,
   let Inst{7-4} = 0b0011;
 }
 
-def USATlsl : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a, i32imm:$shamt),
-                 SatFrm, NoItinerary,
-                 "usat", "\t$dst, $bit_pos, $a, lsl $shamt",
-                 [/* For disassembly only; pattern left blank */]> {
-  let Inst{27-21} = 0b0110111;
-  let Inst{6-4} = 0b001;
-}
-
-def USATasr : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a, i32imm:$shamt),
-                 SatFrm, NoItinerary,
-                 "usat", "\t$dst, $bit_pos, $a, asr $shamt",
-                 [/* For disassembly only; pattern left blank */]> {
+def USAT : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a, sat_shift:$sh),
+              SatFrm, NoItinerary, "usat", "\t$dst, $bit_pos, $a$sh",
+              [/* For disassembly only; pattern left blank */]> {
   let Inst{27-21} = 0b0110111;
-  let Inst{6-4} = 0b101;
+  let Inst{5-4} = 0b01;
 }
 
 def USAT16 : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a), SatFrm,
@@ -1856,8 +1842,8 @@ def USAT16 : AI<(outs GPR:$dst), (ins i32imm:$bit_pos, GPR:$a), SatFrm,
   let Inst{7-4} = 0b0011;
 }
 
-def : ARMV6Pat<(int_arm_ssat GPR:$a, imm:$pos), (SSATlsl imm:$pos, GPR:$a, 0)>;
-def : ARMV6Pat<(int_arm_usat GPR:$a, imm:$pos), (USATlsl imm:$pos, GPR:$a, 0)>;
+def : ARMV6Pat<(int_arm_ssat GPR:$a, imm:$pos), (SSAT imm:$pos, GPR:$a, 0)>;
+def : ARMV6Pat<(int_arm_usat GPR:$a, imm:$pos), (USAT imm:$pos, GPR:$a, 0)>;
 
 //===----------------------------------------------------------------------===//
 //  Bitwise Instructions.
index d1d28521610407cfaadb9a2d54f4794bcc8cab18..f40da955041d6efaa45cdbb613d01def34585c90 100644 (file)
@@ -461,9 +461,9 @@ void ARMInstPrinter::printAddrModePCOperand(const MCInst *MI, unsigned OpNum,
   assert(0 && "FIXME: Implement printAddrModePCOperand");
 }
 
-void ARMInstPrinter::printBitfieldInvMaskImmOperand (const MCInst *MI,
-                                                     unsigned OpNum,
-                                                     raw_ostream &O) {
+void ARMInstPrinter::printBitfieldInvMaskImmOperand(const MCInst *MI,
+                                                    unsigned OpNum,
+                                                    raw_ostream &O) {
   const MCOperand &MO = MI->getOperand(OpNum);
   uint32_t v = ~MO.getImm();
   int32_t lsb = CountTrailingZeros_32(v);
@@ -472,6 +472,25 @@ void ARMInstPrinter::printBitfieldInvMaskImmOperand (const MCInst *MI,
   O << '#' << lsb << ", #" << width;
 }
 
+void ARMInstPrinter::printSatShiftOperand(const MCInst *MI, unsigned OpNum,
+                                          raw_ostream &O) {
+  unsigned ShiftOp = MI->getOperand(OpNum).getImm();
+  ARM_AM::ShiftOpc Opc = ARM_AM::getSORegShOp(ShiftOp);
+  switch (Opc) {
+  case ARM_AM::no_shift:
+    return;
+  case ARM_AM::lsl:
+    O << ", lsl #";
+    break;
+  case ARM_AM::asr:
+    O << ", asr #";
+    break;
+  default:
+    assert(0 && "unexpected shift opcode for saturate shift operand");
+  }
+  O << ARM_AM::getSORegOffset(ShiftOp);
+}
+
 void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum,
                                        raw_ostream &O) {
   O << "{";
index ddf5047793d299dc3ce55d880f22874122eb638d..14d7ec9308780b03d5b6bc9bb5ec5580ac241716 100644 (file)
@@ -57,6 +57,7 @@ public:
 
   void printBitfieldInvMaskImmOperand(const MCInst *MI, unsigned OpNum,
                                       raw_ostream &O);
+  void printSatShiftOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
 
   void printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum, raw_ostream &O);
   void printThumbITMask(const MCInst *MI, unsigned OpNum, raw_ostream &O);
index 4de697e8bf67649817fc66ab4bdde352fb2053a2..f9eecb8acb2738dd5b57e9bc1dfa2ba5fe7f0241 100644 (file)
@@ -106,7 +106,7 @@ static unsigned decodeARMInstruction(uint32_t &insn) {
   // Ditto for STRT, which is a super-instruction for A8.6.210 Encoding A1 & A2.
   // As a result, the decoder fails to deocode SSAT properly.
   if (slice(insn, 27, 21) == 0x35 && slice(insn, 5, 4) == 1)
-    return slice(insn, 6, 6) == 0 ? ARM::SSATlsl : ARM::SSATasr;
+    return ARM::SSAT;
 
   // Ditto for RSCrs, which is a super-instruction for A8.6.146 & A8.6.147.
   // As a result, the decoder fails to decode STRHT/LDRHT/LDRSHT/LDRSBT.
index 99d9f01c0484fe1e3b6db41ef11540affaa93756..57dc3471b9570959bb98284533b3419244fee1ac 100644 (file)
@@ -1466,9 +1466,7 @@ static bool DisassembleSatFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
                                                      decodeRd(insn))));
 
   unsigned Pos = slice(insn, 20, 16);
-  if (Opcode == ARM::SSATlsl ||
-      Opcode == ARM::SSATasr ||
-      Opcode == ARM::SSAT16)
+  if (Opcode == ARM::SSAT || Opcode == ARM::SSAT16)
     Pos += 1;
   MI.addOperand(MCOperand::CreateImm(Pos));
 
@@ -1476,12 +1474,17 @@ static bool DisassembleSatFrm(MCInst &MI, unsigned Opcode, uint32_t insn,
                                                      decodeRm(insn))));
 
   if (NumOpsAdded == 4) {
+    ARM_AM::ShiftOpc Opc = (slice(insn, 6, 6) != 0 ? ARM_AM::asr : ARM_AM::lsl);
     // Inst{11-7} encodes the imm5 shift amount.
     unsigned ShAmt = slice(insn, 11, 7);
-    // A8.6.183.  Possible ASR shift amount of 32...
-    if ((Opcode == ARM::SSATasr || Opcode == ARM::USATasr) && ShAmt == 0)
-      ShAmt = 32;
-    MI.addOperand(MCOperand::CreateImm(ShAmt));
+    if (ShAmt == 0) {
+      // A8.6.183.  Possible ASR shift amount of 32...
+      if (Opc == ARM_AM::asr)
+        ShAmt = 32;
+      else
+        Opc = ARM_AM::no_shift;
+    }
+    MI.addOperand(MCOperand::CreateImm(ARM_AM::getSORegOpc(Opc, ShAmt)));
   }
   return true;
 }
index 52161a6ec16f72fd42be88e90d870032dbd43bab..d6df56b827689b45db73290f48d96ccbbd8b2b17 100644 (file)
 # CHECK:       ssat    r8, #1, r10, lsl #8
 0x1a 0x84 0xa0 0xe6
 
+# CHECK-NOT:   ssatmi  r0, #17, r12, lsl #0
+# CHECK:       ssatmi  r0, #17, r12
+0x1c 0x00 0xb0 0x46
+
 # CHECK:       stmdb   r10!, {r4, r5, r6, r7, lr}
 0xf0 0x40 0x2a 0xe9
 
index 50ff9ea070a0ec365abe36322147de6db6636090..a640a74d21621bc067908bf04d09cfd7dd6a4e5a 100644 (file)
@@ -607,6 +607,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type,
   IMM("jt2block_operand");
   IMM("t_imm_s4");
   IMM("pclabel");
+  IMM("sat_shift");
   
   MISC("brtarget", "kOperandTypeARMBranchTarget");                // ?
   MISC("so_reg", "kOperandTypeARMSoReg");                         // R, R, I