Misc. SSE2 intrinsics: clflush, lfench, mfence
[oota-llvm.git] / lib / Target / PowerPC / PPCAsmPrinter.cpp
index c7218ea62c41f85d8639e9608e302b20b20f893c..b34bf9a8a217813c7962856a2e971d494b1eac28 100644 (file)
@@ -35,6 +35,7 @@
 #include "llvm/Support/Debug.h"
 #include "llvm/Target/MRegisterInfo.h"
 #include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetOptions.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringExtras.h"
 #include <iostream>
@@ -96,11 +97,16 @@ namespace {
     }
     
     bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
-                         unsigned AsmVariant, const char *ExtraCode) {
-       printOperand(MI, OpNo);
-       return false;
-    }
+                         unsigned AsmVariant, const char *ExtraCode);
+    bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
+                               unsigned AsmVariant, const char *ExtraCode);
+    
     
+    void printS5ImmOperand(const MachineInstr *MI, unsigned OpNo) {
+      char value = MI->getOperand(OpNo).getImmedValue();
+      value = (value << (32-5)) >> (32-5);
+      O << (int)value;
+    }
     void printU5ImmOperand(const MachineInstr *MI, unsigned OpNo) {
       unsigned char value = MI->getOperand(OpNo).getImmedValue();
       assert(value <= 31 && "Invalid u5imm argument!");
@@ -131,7 +137,7 @@ namespace {
     }
     void printCallOperand(const MachineInstr *MI, unsigned OpNo) {
       const MachineOperand &MO = MI->getOperand(OpNo);
-      if (!PPCGenerateStaticCode) {
+      if (TM.getRelocationModel() != Reloc::Static) {
         if (MO.getType() == MachineOperand::MO_GlobalAddress) {
           GlobalValue *GV = MO.getGlobal();
           if (((GV->isExternal() || GV->hasWeakLinkage() ||
@@ -166,7 +172,7 @@ namespace {
       } else {
         O << "ha16(";
         printOp(MI->getOperand(OpNo));
-        if (PICEnabled)
+        if (TM.getRelocationModel() == Reloc::PIC)
           O << "-\"L" << getFunctionNumber() << "$pb\")";
         else
           O << ')';
@@ -178,7 +184,7 @@ namespace {
       } else {
         O << "lo16(";
         printOp(MI->getOperand(OpNo));
-        if (PICEnabled)
+        if (TM.getRelocationModel() == Reloc::PIC)
           O << "-\"L" << getFunctionNumber() << "$pb\")";
         else
           O << ')';
@@ -189,13 +195,31 @@ namespace {
       unsigned RegNo = enumRegToMachineReg(CCReg);
       O << (0x80 >> RegNo);
     }
-    // The new addressing mode printers, currently empty
+    // The new addressing mode printers.
     void printMemRegImm(const MachineInstr *MI, unsigned OpNo) {
       printSymbolLo(MI, OpNo);
       O << '(';
-      printOperand(MI, OpNo+1);
+      if (MI->getOperand(OpNo+1).isRegister() && 
+          MI->getOperand(OpNo+1).getReg() == PPC::R0)
+        O << "0";
+      else
+        printOperand(MI, OpNo+1);
       O << ')';
     }
+    void printMemRegImmShifted(const MachineInstr *MI, unsigned OpNo) {
+      if (MI->getOperand(OpNo).isImmediate())
+        printS16X4ImmOperand(MI, OpNo);
+      else 
+        printSymbolLo(MI, OpNo);
+      O << '(';
+      if (MI->getOperand(OpNo+1).isRegister() && 
+          MI->getOperand(OpNo+1).getReg() == PPC::R0)
+        O << "0";
+      else
+        printOperand(MI, OpNo+1);
+      O << ')';
+    }
+    
     void printMemRegReg(const MachineInstr *MI, unsigned OpNo) {
       // When used as the base register, r0 reads constant zero rather than
       // the value contained in the register.  For this reason, the darwin
@@ -222,18 +246,17 @@ namespace {
     : DwarfWriter(o, ap)
     {
       needsSet = true;
-      DwarfAbbrevSection = ".section __DWARF,__debug_abbrev";
-      DwarfInfoSection = ".section __DWARF,__debug_info";
-      DwarfLineSection = ".section __DWARF,__debug_line";
-      DwarfFrameSection =
-          ".section __DWARF,__debug_frame,,coalesced,no_toc+strip_static_syms";
-      DwarfPubNamesSection = ".section __DWARF,__debug_pubnames";
-      DwarfPubTypesSection = ".section __DWARF,__debug_pubtypes";
-      DwarfStrSection = ".section __DWARF,__debug_str";
-      DwarfLocSection = ".section __DWARF,__debug_loc";
-      DwarfARangesSection = ".section __DWARF,__debug_aranges";
-      DwarfRangesSection = ".section __DWARF,__debug_ranges";
-      DwarfMacInfoSection = ".section __DWARF,__debug_macinfo";
+      DwarfAbbrevSection = ".section __DWARFA,__debug_abbrev";
+      DwarfInfoSection = ".section __DWARFA,__debug_info";
+      DwarfLineSection = ".section __DWARFA,__debug_line";
+      DwarfFrameSection = ".section __DWARFA,__debug_frame";
+      DwarfPubNamesSection = ".section __DWARFA,__debug_pubnames";
+      DwarfPubTypesSection = ".section __DWARFA,__debug_pubtypes";
+      DwarfStrSection = ".section __DWARFA,__debug_str";
+      DwarfLocSection = ".section __DWARFA,__debug_loc";
+      DwarfARangesSection = ".section __DWARFA,__debug_aranges";
+      DwarfRangesSection = ".section __DWARFA,__debug_ranges";
+      DwarfMacInfoSection = ".section __DWARFA,__debug_macinfo";
       TextSection = ".text";
       DataSection = ".data";
     }
@@ -246,8 +269,7 @@ namespace {
     DarwinDwarfWriter DW;
 
     DarwinAsmPrinter(std::ostream &O, TargetMachine &TM)
-      : PPCAsmPrinter(O, TM), DW(O, this)      
-      {
+      : PPCAsmPrinter(O, TM), DW(O, this) {
       CommentString = ";";
       GlobalPrefix = "_";
       PrivateGlobalPrefix = "L";     // Marker for constant pool idxs
@@ -258,6 +280,7 @@ namespace {
       LCOMMDirective = "\t.lcomm\t";
       StaticCtorsSection = ".mod_init_func";
       StaticDtorsSection = ".mod_term_func";
+      InlineAsmStart = InlineAsmEnd = "";  // Don't use #APP/#NO_APP
     }
 
     virtual const char *getPassName() const {
@@ -307,7 +330,8 @@ namespace {
 /// code for a MachineFunction to the given output stream, in a format that the
 /// Darwin assembler can deal with.
 ///
-FunctionPass *llvm::createDarwinAsmPrinter(std::ostream &o, TargetMachine &tm) {
+FunctionPass *llvm::createDarwinAsmPrinter(std::ostream &o,
+                                           PPCTargetMachine &tm) {
   return new DarwinAsmPrinter(o, tm);
 }
 
@@ -315,7 +339,7 @@ FunctionPass *llvm::createDarwinAsmPrinter(std::ostream &o, TargetMachine &tm) {
 /// for a MachineFunction to the given output stream, in a format that the
 /// AIX 5L assembler can deal with.
 ///
-FunctionPass *llvm::createAIXAsmPrinter(std::ostream &o, TargetMachine &tm) {
+FunctionPass *llvm::createAIXAsmPrinter(std::ostream &o, PPCTargetMachine &tm) {
   return new AIXAsmPrinter(o, tm);
 }
 
@@ -362,7 +386,7 @@ void PPCAsmPrinter::printOp(const MachineOperand &MO) {
     return;
   case MachineOperand::MO_ExternalSymbol:
     // Computing the address of an external symbol, not calling it.
-    if (!PPCGenerateStaticCode) {
+    if (TM.getRelocationModel() != Reloc::Static) {
       std::string Name(GlobalPrefix); Name += MO.getSymbolName();
       GVStubs.insert(Name);
       O << "L" << Name << "$non_lazy_ptr";
@@ -377,7 +401,7 @@ void PPCAsmPrinter::printOp(const MachineOperand &MO) {
     int offset = MO.getOffset();
 
     // External or weakly linked global variables need non-lazily-resolved stubs
-    if (!PPCGenerateStaticCode) {
+    if (TM.getRelocationModel() != Reloc::Static) {
       if (((GV->isExternal() || GV->hasWeakLinkage() ||
             GV->hasLinkOnceLinkage()))) {
         GVStubs.insert(Name);
@@ -396,6 +420,41 @@ void PPCAsmPrinter::printOp(const MachineOperand &MO) {
   }
 }
 
+/// PrintAsmOperand - Print out an operand for an inline asm expression.
+///
+bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
+                                    unsigned AsmVariant, 
+                                    const char *ExtraCode) {
+  // Does this asm operand have a single letter operand modifier?
+  if (ExtraCode && ExtraCode[0]) {
+    if (ExtraCode[1] != 0) return true; // Unknown modifier.
+    
+    switch (ExtraCode[0]) {
+    default: return true;  // Unknown modifier.
+    case 'L': // Write second word of DImode reference.  
+      // Verify that this operand has two consecutive registers.
+      if (!MI->getOperand(OpNo).isRegister() ||
+          OpNo+1 == MI->getNumOperands() ||
+          !MI->getOperand(OpNo+1).isRegister())
+        return true;
+      ++OpNo;   // Return the high-part.
+      break;
+    }
+  }
+  
+  printOperand(MI, OpNo);
+  return false;
+}
+
+bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
+                                          unsigned AsmVariant, 
+                                          const char *ExtraCode) {
+  if (ExtraCode && ExtraCode[0])
+    return true; // Unknown modifier.
+  printMemRegReg(MI, OpNo);
+  return false;
+}
+
 /// printMachineInstruction -- Print out a single PowerPC MI in Darwin syntax to
 /// the current output stream.
 ///
@@ -452,9 +511,6 @@ bool DarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
   SetupMachineFunction(MF);
   O << "\n\n";
   
-  // Emit pre-function debug information.
-  DW.BeginFunction(MF);
-
   // Print out constants referenced by the function
   EmitConstantPool(MF.getConstantPool());
 
@@ -464,11 +520,9 @@ bool DarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
   default: assert(0 && "Unknown linkage type!");
   case Function::InternalLinkage:  // Symbols default to internal.
     SwitchSection(".text", F);
-    EmitAlignment(4, F);
     break;
   case Function::ExternalLinkage:
     SwitchSection(".text", F);
-    EmitAlignment(4, F);
     O << "\t.globl\t" << CurrentFnName << "\n";
     break;
   case Function::WeakLinkage:
@@ -479,8 +533,12 @@ bool DarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
     O << "\t.weak_definition\t" << CurrentFnName << "\n";
     break;
   }
+  EmitAlignment(4, F);
   O << CurrentFnName << ":\n";
 
+  // Emit pre-function debug information.
+  DW.BeginFunction(&MF);
+
   // Print out code for the function.
   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
        I != E; ++I) {
@@ -501,7 +559,7 @@ bool DarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
   }
 
   // Emit post-function debug information.
-  DW.EndFunction(MF);
+  DW.EndFunction();
 
   // We didn't modify anything.
   return false;
@@ -517,7 +575,7 @@ bool DarwinAsmPrinter::doInitialization(Module &M) {
   Mang->setUseQuotes(true);
   
   // Emit initial debug information.
-  DW.BeginModule(M);
+  DW.BeginModule(&M);
   return false;
 }
 
@@ -530,7 +588,7 @@ bool DarwinAsmPrinter::doFinalization(Module &M) {
     if (!I->hasInitializer()) continue;   // External global require no code
     
     // Check to see if this is a special global used by LLVM, if so, emit it.
-    if (I->hasAppendingLinkage() && EmitSpecialLLVMGlobal(I))
+    if (EmitSpecialLLVMGlobal(I))
       continue;
     
     std::string name = Mang->getValueName(I);
@@ -540,13 +598,20 @@ bool DarwinAsmPrinter::doFinalization(Module &M) {
 
     if (C->isNullValue() && /* FIXME: Verify correct */
         (I->hasInternalLinkage() || I->hasWeakLinkage() ||
-         I->hasLinkOnceLinkage())) {
-      SwitchSection(".data", I);
+         I->hasLinkOnceLinkage() ||
+         (I->hasExternalLinkage() && !I->hasSection()))) {
       if (Size == 0) Size = 1;   // .comm Foo, 0 is undefined, avoid it.
-      if (I->hasInternalLinkage())
+      if (I->hasExternalLinkage()) {
+        O << "\t.globl " << name << '\n';
+        O << "\t.zerofill __DATA, __common, " << name << ", "
+          << Size << ", " << Align;
+      } else if (I->hasInternalLinkage()) {
+        SwitchSection(".data", I);
         O << LCOMMDirective << name << "," << Size << "," << Align;
-      else
+      } else {
+        SwitchSection(".data", I);
         O << ".comm " << name << "," << Size;
+      }
       O << "\t\t; '" << I->getName() << "'\n";
     } else {
       switch (I->getLinkage()) {
@@ -579,7 +644,7 @@ bool DarwinAsmPrinter::doFinalization(Module &M) {
   }
 
   // Output stubs for dynamically-linked functions
-  if (PICEnabled) {
+  if (TM.getRelocationModel() == Reloc::PIC) {
     for (std::set<std::string>::iterator i = FnStubs.begin(), e = FnStubs.end();
          i != e; ++i) {
       SwitchSection(".section __TEXT,__picsymbolstub1,symbol_stubs,"
@@ -634,7 +699,7 @@ bool DarwinAsmPrinter::doFinalization(Module &M) {
   }
 
   // Emit initial debug information.
-  DW.EndModule(M);
+  DW.EndModule();
 
   // Funny Darwin hack: This flag tells the linker that no global symbols
   // contain code that falls through to other global symbols (e.g. the obvious