[llvm-commits] [llvm] r160028 - in /llvm/trunk: lib/Target/Mips/MipsAsmPrinter.cpp test/CodeGen/Mips/inlineasm-operand-code.ll

Jack Carter jcarter at mips.com
Tue Jul 10 15:41:20 PDT 2012


Author: jacksprat
Date: Tue Jul 10 17:41:20 2012
New Revision: 160028

URL: http://llvm.org/viewvc/llvm-project?rev=160028&view=rev
Log:
   Mips specific inline asm operand modifier 'L'.
   
   Low order register of a double word register operand. Operands 
   are defined by the name of the variable they are marked with in
   the inline assembler code. This is a way to specify that the 
   operand just refers to the low order register for that variable.
   
   It is the opposite of modifier 'D' which specifies the high order
   register.
   
   Example:
   
 main()
{

    long long ll_input = 0x1111222233334444LL;
    long long ll_val = 3;
    int i_result = 0;

    __asm__ __volatile__( 
		   "or	%0, %L1, %2"
	     : "=r" (i_result) 
	     : "r" (ll_input), "r" (ll_val)); 
}

   Which results in:
   
   	lui	$2, %hi(_gp_disp)
	addiu	$2, $2, %lo(_gp_disp)
	addiu	$sp, $sp, -8
	addu	$2, $2, $25
	sw	$2, 0($sp)
	lui	$2, 13107
	ori	$3, $2, 17476     <-- Low 32 bits of ll_input
	lui	$2, 4369
	ori	$4, $2, 8738      <-- High 32 bits of ll_input
	addiu	$5, $zero, 3  <-- Low 32 bits of ll_val
	addiu	$2, $zero, 0  <-- High 32 bits of ll_val
	#APP
	or	$3, $4, $5        <-- or i_result, high 32 ll_input, low 32 of ll_val
	#NO_APP
	addiu	$sp, $sp, 8
	jr	$ra

If not direction is done for the long long for 32 bit variables results
in using the low 32 bits as ll_val shows.

There is an existing bug if 'L' or 'D' is used for the destination register
for 32 bit long longs in that the target value will be updated incorrectly
for the non-specified part unless explicitly set within the inline asm code.



Modified:
    llvm/trunk/lib/Target/Mips/MipsAsmPrinter.cpp
    llvm/trunk/test/CodeGen/Mips/inlineasm-operand-code.ll

Modified: llvm/trunk/lib/Target/Mips/MipsAsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsAsmPrinter.cpp?rev=160028&r1=160027&r2=160028&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsAsmPrinter.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsAsmPrinter.cpp Tue Jul 10 17:41:20 2012
@@ -333,8 +333,9 @@
         O << "$0";
       return false;
     }
-    case 'D': {
-      // Second part of a double word register operand
+    case 'D': // Second part of a double word register operand
+    case 'L': // Low order register of a double word register operand
+    {
       if (OpNum == 0)
         return true;
       const MachineOperand &FlagsOP = MI->getOperand(OpNum - 1);
@@ -353,19 +354,26 @@
         return true;
       }
       unsigned RegOp;
-      switch(ExtraCode[0]) {
-      case 'D':
-        RegOp = (!Subtarget->isGP32bit()) ? OpNum : OpNum + 1;
-        break;
+      if (Subtarget->isGP64bit())
+        RegOp = OpNum;
+      else {
+        // Endianess reverses which register holds the high or low value
+        switch(ExtraCode[0]) {
+        case 'D':
+          RegOp = (Subtarget->isLittle()) ? OpNum : OpNum+1;
+          break;
+        case 'L':
+          RegOp = (Subtarget->isLittle()) ? OpNum+1 : OpNum;
+        }
+        if (RegOp >= MI->getNumOperands())
+          return true;
+        const MachineOperand &MO = MI->getOperand(RegOp);
+        if (!MO.isReg())
+          return true;
+        unsigned Reg = MO.getReg();
+        O << '$' << MipsInstPrinter::getRegisterName(Reg);
+        return false;
       }
-      if (RegOp >= MI->getNumOperands())
-        return true;
-      const MachineOperand &MO = MI->getOperand(RegOp);
-      if (!MO.isReg())
-        return true;
-      unsigned Reg = MO.getReg();
-      O << '$' << MipsInstPrinter::getRegisterName(Reg);
-      return false;
     }
     }
   }

Modified: llvm/trunk/test/CodeGen/Mips/inlineasm-operand-code.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/inlineasm-operand-code.ll?rev=160028&r1=160027&r2=160028&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/inlineasm-operand-code.ll (original)
+++ llvm/trunk/test/CodeGen/Mips/inlineasm-operand-code.ll Tue Jul 10 17:41:20 2012
@@ -56,7 +56,7 @@
 ;LITTLE:    lw $[[SECOND:[0-9]+]], 4(${{[0-9]+}})
 ;LITTLE-NEXT: lw $[[FIRST:[0-9]+]], 0(${{[0-9]+}})
 ;LITTLE:	#APP
-;LITTLE:    or	${{[0-9]+}},$[[SECOND]],${{[0-9]+}}
+;LITTLE:    or	${{[0-9]+}},$[[FIRST]],${{[0-9]+}}
 ;LITTLE:    #NO_APP
 
 ; D, in big endian the source reg will also be 4 bytes into the long long
@@ -77,6 +77,16 @@
   %trunc1 = trunc i64 %7 to i32
   tail call i32 asm sideeffect "or $0,${1:D},$2", "=r,r,r"(i64 %7, i32 %trunc1) nounwind
 
+; L, in little endian the source reg will be 4 bytes into the long long
+;LITTLE:	#APP
+;LITTLE:	     or	${{[0-9]+}},$[[SECOND]],${{[0-9]+}}
+;LITTLE:	#NO_APP
+; L, in big endian the source reg will be 0 bytes into the long long
+;BIG:	#APP
+;BIG:	     or	${{[0-9]+}},$[[FIRST]],${{[0-9]+}}
+;BIG:	#NO_APP
+  tail call i32 asm sideeffect "or $0,${1:L},$2", "=r,r,r"(i64 %7, i32 %trunc1) nounwind
+
   ret i32 0
 }
 





More information about the llvm-commits mailing list