Copy some AVX support from MCJIT to JIT. Maybe will fix PR12748.
authorCraig Topper <craig.topper@gmail.com>
Sat, 19 May 2012 08:28:17 +0000 (08:28 +0000)
committerCraig Topper <craig.topper@gmail.com>
Sat, 19 May 2012 08:28:17 +0000 (08:28 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@157109 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86CodeEmitter.cpp

index 57af7bb43f682af8d7b96e7b3c46f305db627e8f..6757043bc064ae908fe1ffc799be96a676f8eeed 100644 (file)
@@ -749,10 +749,6 @@ void Emitter<CodeEmitter>::emitOpcodePrefix(uint64_t TSFlags,
   }
 }
 
-static unsigned GetX86RegNum(const MachineOperand &MO) {
-  return X86_MC::getX86RegNum(MO.getReg());
-}
-
 // On regular x86, both XMM0-XMM7 and XMM8-XMM15 are encoded in the range
 // 0-7 and the difference between the 2 groups is given by the REX prefix.
 // In the VEX prefix, registers are seen sequencially from 0-15 and encoded
@@ -765,7 +761,7 @@ static unsigned GetX86RegNum(const MachineOperand &MO) {
 static unsigned char getVEXRegisterEncoding(const MachineInstr &MI,
                                             unsigned OpNum) {
   unsigned SrcReg = MI.getOperand(OpNum).getReg();
-  unsigned SrcRegNum = GetX86RegNum(MI.getOperand(OpNum));
+  unsigned SrcRegNum = X86_MC::getX86RegNum(MI.getOperand(OpNum).getReg());
   if (X86II::isX86_64ExtendedReg(SrcReg))
     SrcRegNum |= 8;
 
@@ -1132,6 +1128,7 @@ void Emitter<CodeEmitter>::emitInstruction(MachineInstr &MI,
   bool HasVEX_4V = (TSFlags >> X86II::VEXShift) & X86II::VEX_4V;
   bool HasVEX_4VOp3 = (TSFlags >> X86II::VEXShift) & X86II::VEX_4VOp3;
   bool HasMemOp4 = (TSFlags >> X86II::VEXShift) & X86II::MemOp4;
+  const unsigned MemOp4_I8IMMOperand = 2;
 
   // Determine where the memory operand starts, if present.
   int MemoryOperand = X86II::getMemoryOperandNo(TSFlags, Opcode);
@@ -1273,9 +1270,6 @@ void Emitter<CodeEmitter>::emitInstruction(MachineInstr &MI,
     emitRegModRMByte(MI.getOperand(CurOp).getReg(),
                      X86_MC::getX86RegNum(MI.getOperand(CurOp+1).getReg()));
     CurOp += 2;
-    if (CurOp != NumOps)
-      emitConstant(MI.getOperand(CurOp++).getImm(),
-                   X86II::getSizeOfImm(Desc->TSFlags));
     break;
   }
   case X86II::MRMDestMem: {
@@ -1287,9 +1281,6 @@ void Emitter<CodeEmitter>::emitInstruction(MachineInstr &MI,
     emitMemModRMByte(MI, CurOp,
                 X86_MC::getX86RegNum(MI.getOperand(SrcRegNum).getReg()));
     CurOp = SrcRegNum + 1;
-    if (CurOp != NumOps)
-      emitConstant(MI.getOperand(CurOp++).getImm(),
-                   X86II::getSizeOfImm(Desc->TSFlags));
     break;
   }
 
@@ -1309,9 +1300,6 @@ void Emitter<CodeEmitter>::emitInstruction(MachineInstr &MI,
     CurOp = HasMemOp4 ? SrcRegNum : SrcRegNum + 1;
     if (HasVEX_4VOp3)
       ++CurOp;
-    if (CurOp != NumOps)
-      emitConstant(MI.getOperand(CurOp++).getImm(),
-                   X86II::getSizeOfImm(Desc->TSFlags));
     break;
   }
   case X86II::MRMSrcMem: {
@@ -1333,9 +1321,6 @@ void Emitter<CodeEmitter>::emitInstruction(MachineInstr &MI,
     CurOp += AddrOperands + 1;
     if (HasVEX_4VOp3)
       ++CurOp;
-    if (CurOp != NumOps)
-      emitConstant(MI.getOperand(CurOp++).getImm(),
-                   X86II::getSizeOfImm(Desc->TSFlags));
     break;
   }
 
@@ -1448,6 +1433,33 @@ void Emitter<CodeEmitter>::emitInstruction(MachineInstr &MI,
     break;
   }
 
+  if (CurOp != NumOps) {
+    // The last source register of a 4 operand instruction in AVX is encoded
+    // in bits[7:4] of a immediate byte.
+    if ((TSFlags >> X86II::VEXShift) & X86II::VEX_I8IMM) {
+      const MachineOperand &MO = MI.getOperand(HasMemOp4 ? MemOp4_I8IMMOperand
+                                                         : CurOp);
+      CurOp++;
+      bool IsExtReg = X86II::isX86_64ExtendedReg(MO.getReg());
+      unsigned RegNum = (IsExtReg ? (1 << 7) : 0);
+      RegNum |= X86_MC::getX86RegNum(MO.getReg()) << 4;
+      // If there is an additional 5th operand it must be an immediate, which
+      // is encoded in bits[3:0]
+      if(CurOp != NumOps) {
+        const MachineOperand &MIMM = MI.getOperand(CurOp++);
+        if(MIMM.isImm()) {
+          unsigned Val = MIMM.getImm();
+          assert(Val < 16 && "Immediate operand value out of range");
+          RegNum |= Val;
+        }
+      }
+      emitConstant(RegNum, 1);
+    } else {
+      emitConstant(MI.getOperand(CurOp++).getImm(),
+                   X86II::getSizeOfImm(Desc->TSFlags));
+    }
+  }
+
   if (!MI.isVariadic() && CurOp != NumOps) {
 #ifndef NDEBUG
     dbgs() << "Cannot encode all operands of: " << MI << "\n";