Do not use '&' prefix for globals when register base field is non-zero, otherwise...
[oota-llvm.git] / lib / Target / MSP430 / AsmPrinter / MSP430AsmPrinter.cpp
index 40d9efea26a38e1d9941a87db433efb0a6e3863a..7a35eb092ae32c708bbe2e8bcc4edb6833f05085 100644 (file)
@@ -98,12 +98,19 @@ void MSP430AsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
     bool isMemOp  = Modifier && !strcmp(Modifier, "mem");
     uint64_t Offset = MO.getOffset();
 
-    O << (isMemOp ? '&' : '#');
+    // If the global address expression is a part of displacement field with a
+    // register base, we should not emit any prefix symbol here, e.g.
+    //   mov.w &foo, r1
+    // vs
+    //   mov.w glb(r1), r2
+    // Otherwise (!) msp430-as will silently miscompile the output :(
+    if (!Modifier || strcmp(Modifier, "nohash"))
+      O << (isMemOp ? '&' : '#');
     if (Offset)
       O << '(' << Offset << '+';
 
     O << *GetGlobalValueSymbol(MO.getGlobal());
-    
+
     if (Offset)
       O << ')';
 
@@ -124,15 +131,11 @@ void MSP430AsmPrinter::printSrcMemOperand(const MachineInstr *MI, int OpNum,
   const MachineOperand &Disp = MI->getOperand(OpNum+1);
 
   // Print displacement first
-  if (!Disp.isImm()) {
-    printOperand(MI, OpNum+1, "mem");
-  } else {
-    if (!Base.getReg())
-      O << '&';
-
-    printOperand(MI, OpNum+1, "nohash");
-  }
 
+  // Imm here is in fact global address - print extra modifier.
+  if (Disp.isImm() && !Base.getReg())
+    O << '&';
+  printOperand(MI, OpNum+1, "nohash");
 
   // Print register base field
   if (Base.getReg()) {
@@ -181,28 +184,9 @@ bool MSP430AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
 void MSP430AsmPrinter::EmitInstruction(const MachineInstr *MI) {
   MSP430MCInstLower MCInstLowering(OutContext, *Mang, *this);
 
-  switch (MI->getOpcode()) {
-  case TargetInstrInfo::DBG_LABEL:
-  case TargetInstrInfo::EH_LABEL:
-  case TargetInstrInfo::GC_LABEL:
-    printLabel(MI);
-    return;
-  case TargetInstrInfo::KILL:
-    printKill(MI);
-    return;
-  case TargetInstrInfo::INLINEASM:
-    printInlineAsm(MI);
-    return;
-  case TargetInstrInfo::IMPLICIT_DEF:
-    printImplicitDef(MI);
-    return;
-  default: break;
-  }
-
   MCInst TmpInst;
   MCInstLowering.Lower(MI, TmpInst);
-
-  printMCInst(&TmpInst);
+  OutStreamer.EmitInstruction(TmpInst);
 }
 
 static MCInstPrinter *createMSP430MCInstPrinter(const Target &T,