From a0f14afee16ca976fef79c64df9a678e7f26cf43 Mon Sep 17 00:00:00 2001 From: Jack Carter Date: Wed, 18 Jul 2012 06:41:36 +0000 Subject: [PATCH] Mips specific inline asm operand modifier 'M': Print the high order register of a double word register operand. In 32 bit mode, a 64 bit double word integer will be represented by 2 32 bit registers. This modifier causes the high order register to be used in the asm expression. It is useful if you are using doubles in assembler and continue to control register to variable relationships. This patch also fixes a related bug in a previous patch: case 'D': // Second part of a double word register operand case 'L': // Low order register of a double word register operand case 'M': // High order register of a double word register operand I got 'D' and 'M' confused. The second part of a double word operand will only match 'M' for one of the endianesses. I had 'L' and 'D' be the opposite twins when 'L' and 'M' are. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160429 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/MipsAsmPrinter.cpp | 11 +- test/CodeGen/Mips/inlineasm-operand-code.ll | 223 +++++++++++++------- 2 files changed, 150 insertions(+), 84 deletions(-) diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index 914a204fe2e..00ff7545c14 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -355,6 +355,7 @@ bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, } case 'D': // Second part of a double word register operand case 'L': // Low order register of a double word register operand + case 'M': // High order register of a double word register operand { if (OpNum == 0) return true; @@ -377,12 +378,16 @@ bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, unsigned RegOp = OpNum; if (!Subtarget->isGP64bit()){ // Endianess reverses which register holds the high or low value + // between M and L. switch(ExtraCode[0]) { - case 'D': - RegOp = (Subtarget->isLittle()) ? OpNum : OpNum+1; + case 'M': + RegOp = (Subtarget->isLittle()) ? OpNum + 1 : OpNum; break; case 'L': - RegOp = (Subtarget->isLittle()) ? OpNum+1 : OpNum; + RegOp = (Subtarget->isLittle()) ? OpNum : OpNum + 1; + break; + case 'D': // Always the second part + RegOp = OpNum + 1; } if (RegOp >= MI->getNumOperands()) return true; diff --git a/test/CodeGen/Mips/inlineasm-operand-code.ll b/test/CodeGen/Mips/inlineasm-operand-code.ll index 97ec629db20..01978994b2f 100644 --- a/test/CodeGen/Mips/inlineasm-operand-code.ll +++ b/test/CodeGen/Mips/inlineasm-operand-code.ll @@ -1,92 +1,153 @@ ; Positive test for inline register constraints ; -; RUN: llc -march=mipsel < %s | FileCheck %s -check-prefix=LITTLE -; RUN: llc -march=mips < %s | FileCheck %s -check-prefix=BIG +; RUN: llc -march=mipsel < %s | FileCheck -check-prefix=CHECK_LITTLE_32 %s +; RUN: llc -march=mips < %s | FileCheck -check-prefix=CHECK_BIG_32 %s %union.u_tag = type { i64 } %struct.anon = type { i32, i32 } @uval = common global %union.u_tag zeroinitializer, align 8 -define i32 @main() nounwind { -entry: ; X with -3 -;LITTLE: #APP -;LITTLE: addi ${{[0-9]+}},${{[0-9]+}},0xfffffffffffffffd -;LITTLE: #NO_APP - tail call i32 asm sideeffect "addi $0,$1,${2:X}", "=r,r,I"(i32 7, i32 -3) nounwind - -; x with -3 -;LITTLE: #APP -;LITTLE: addi ${{[0-9]+}},${{[0-9]+}},0xfffd -;LITTLE: #NO_APP - tail call i32 asm sideeffect "addi $0,$1,${2:x}", "=r,r,I"(i32 7, i32 -3) nounwind - -; d with -3 -;LITTLE: #APP -;LITTLE: addi ${{[0-9]+}},${{[0-9]+}},-3 -;LITTLE: #NO_APP - tail call i32 asm sideeffect "addi $0,$1,${2:d}", "=r,r,I"(i32 7, i32 -3) nounwind - -; m with -3 -;LITTLE: #APP -;LITTLE: addi ${{[0-9]+}},${{[0-9]+}},-4 -;LITTLE: #NO_APP - tail call i32 asm sideeffect "addi $0,$1,${2:m}", "=r,r,I"(i32 7, i32 -3) nounwind - -; z with -3 -;LITTLE: #APP -;LITTLE: addi ${{[0-9]+}},${{[0-9]+}},-3 -;LITTLE: #NO_APP - tail call i32 asm sideeffect "addi $0,$1,${2:z}", "=r,r,I"(i32 7, i32 -3) nounwind - -; z with 0 -;LITTLE: #APP -;LITTLE: addi ${{[0-9]+}},${{[0-9]+}},$0 -;LITTLE: #NO_APP - tail call i32 asm sideeffect "addi $0,$1,${2:z}", "=r,r,I"(i32 7, i32 0) nounwind - -; a long long in 32 bit mode (use to assert) -;LITTLE: #APP -;LITTLE: addi ${{[0-9]+}},${{[0-9]+}},3 -;LITTLE: #NO_APP - tail call i64 asm sideeffect "addi $0,$1,$2 \0A\09", "=r,r,X"(i64 1229801703532086340, i64 3) nounwind - -; D, in little endian the source reg will be 4 bytes into the long long -;LITTLE: lw ${{[0-9]+}}, %got(uval)(${{[0-9,a-z]+}}) -;LITTLE: lw $[[SECOND:[0-9]+]], 4(${{[0-9]+}}) -;LITTLE-NEXT: lw $[[FIRST:[0-9]+]], 0(${{[0-9]+}}) -;LITTLE: #APP -;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 -;BIG: #APP -;BIG: #APP -;BIG: #APP -;BIG: #APP -;BIG: #APP -;BIG: #APP -;BIG: #APP -;BIG: lw ${{[0-9]+}}, %got(uval)(${{[0-9,a-z]+}}) -;BIG: lw $[[SECOND:[0-9]+]], 4(${{[0-9]+}}) -;BIG-NEXT: lw $[[FIRST:[0-9]+]], 0(${{[0-9]+}}) -;BIG: #APP -;BIG: or ${{[0-9]+}},$[[SECOND]],${{[0-9]+}} -;BIG: #NO_APP - %7 = load i64* getelementptr inbounds (%union.u_tag* @uval, i32 0, i32 0), align 8 - %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 - +define i32 @constraint_X() nounwind { +entry: +;CHECK_LITTLE_32: constraint_X: +;CHECK_LITTLE_32: #APP +;CHECK_LITTLE_32: addi ${{[0-9]+}},${{[0-9]+}},0xfffffffffffffffd +;CHECK_LITTLE_32: #NO_APP + tail call i32 asm sideeffect "addi $0,$1,${2:X}", "=r,r,I"(i32 7, i32 -3) ; ret i32 0 } +; x with -3 +define i32 @constraint_x() nounwind { +entry: +;CHECK_LITTLE_32: constraint_x: +;CHECK_LITTLE_32: #APP +;CHECK_LITTLE_32: addi ${{[0-9]+}},${{[0-9]+}},0xfffd +;CHECK_LITTLE_32: #NO_APP + tail call i32 asm sideeffect "addi $0,$1,${2:x}", "=r,r,I"(i32 7, i32 -3) ; + ret i32 0 +} + +; d with -3 +define i32 @constraint_d() nounwind { +entry: +;CHECK_LITTLE_32: constraint_d: +;CHECK_LITTLE_32: #APP +;CHECK_LITTLE_32: addi ${{[0-9]+}},${{[0-9]+}},-3 +;CHECK_LITTLE_32: #NO_APP + tail call i32 asm sideeffect "addi $0,$1,${2:d}", "=r,r,I"(i32 7, i32 -3) ; + ret i32 0 +} + +; m with -3 +define i32 @constraint_m() nounwind { +entry: +;CHECK_LITTLE_32: constraint_m: +;CHECK_LITTLE_32: #APP +;CHECK_LITTLE_32: addi ${{[0-9]+}},${{[0-9]+}},-4 +;CHECK_LITTLE_32: #NO_APP + tail call i32 asm sideeffect "addi $0,$1,${2:m}", "=r,r,I"(i32 7, i32 -3) ; + ret i32 0 +} + +; z with -3 +define i32 @constraint_z() nounwind { +entry: +;CHECK_LITTLE_32: constraint_z: +;CHECK_LITTLE_32: #APP +;CHECK_LITTLE_32: addi ${{[0-9]+}},${{[0-9]+}},-3 +;CHECK_LITTLE_32: #NO_APP + tail call i32 asm sideeffect "addi $0,$1,${2:z}", "=r,r,I"(i32 7, i32 -3) ; + +; z with 0 +;CHECK_LITTLE_32: #APP +;CHECK_LITTLE_32: addi ${{[0-9]+}},${{[0-9]+}},$0 +;CHECK_LITTLE_32: #NO_APP + tail call i32 asm sideeffect "addi $0,$1,${2:z}", "=r,r,I"(i32 7, i32 0) nounwind + ret i32 0 +} + +; a long long in 32 bit mode (use to assert) +define i32 @constraint_longlong() nounwind { +entry: +;CHECK_LITTLE_32: constraint_longlong: +;CHECK_LITTLE_32: #APP +;CHECK_LITTLE_32: addi ${{[0-9]+}},${{[0-9]+}},3 +;CHECK_LITTLE_32: #NO_APP + tail call i64 asm sideeffect "addi $0,$1,$2 \0A\09", "=r,r,X"(i64 1229801703532086340, i64 3) nounwind + ret i32 0 +} + +; D, in little endian the source reg will be 4 bytes into the long long +define i32 @constraint_D() nounwind { +entry: +;CHECK_LITTLE_32: constraint_D: +;CHECK_LITTLE_32: lw ${{[0-9]+}}, %got(uval)(${{[0-9,a-z]+}}) +;CHECK_LITTLE_32: lw $[[SECOND:[0-9]+]], 4(${{[0-9]+}}) +;CHECK_LITTLE_32: lw $[[FIRST:[0-9]+]], 0(${{[0-9]+}}) +;CHECK_LITTLE_32: #APP +;CHECK_LITTLE_32: or ${{[0-9]+}},$[[SECOND]],${{[0-9]+}} +;CHECK_LITTLE_32: #NO_APP + +; D, in big endian the source reg will also be 4 bytes into the long long +;CHECK_BIG_32: constraint_D: +;CHECK_BIG_32: lw ${{[0-9]+}}, %got(uval)(${{[0-9,a-z]+}}) +;CHECK_BIG_32: lw $[[SECOND:[0-9]+]], 4(${{[0-9]+}}) +;CHECK_BIG_32: lw $[[FIRST:[0-9]+]], 0(${{[0-9]+}}) +;CHECK_BIG_32: #APP +;CHECK_BIG_32: or ${{[0-9]+}},$[[SECOND]],${{[0-9]+}} +;CHECK_BIG_32: #NO_APP + %bosco = load i64* getelementptr inbounds (%union.u_tag* @uval, i32 0, i32 0), align 8 + %trunc1 = trunc i64 %bosco to i32 + tail call i32 asm sideeffect "or $0,${1:D},$2", "=r,r,r"(i64 %bosco, i32 %trunc1) nounwind + ret i32 0 +} + +; L, in little endian the source reg will be 0 bytes into the long long +define i32 @constraint_L() nounwind { +entry: +;CHECK_LITTLE_32: constraint_L: +;CHECK_LITTLE_32: lw ${{[0-9]+}}, %got(uval)(${{[0-9,a-z]+}}) +;CHECK_LITTLE_32: lw $[[SECOND:[0-9]+]], 4(${{[0-9]+}}) +;CHECK_LITTLE_32: lw $[[FIRST:[0-9]+]], 0(${{[0-9]+}}) +;CHECK_LITTLE_32: #APP +;CHECK_LITTLE_32: or ${{[0-9]+}},$[[FIRST]],${{[0-9]+}} +;CHECK_LITTLE_32: #NO_APP +; L, in big endian the source reg will be 4 bytes into the long long +;CHECK_BIG_32: constraint_L: +;CHECK_BIG_32: lw ${{[0-9]+}}, %got(uval)(${{[0-9,a-z]+}}) +;CHECK_BIG_32: lw $[[SECOND:[0-9]+]], 4(${{[0-9]+}}) +;CHECK_BIG_32: lw $[[FIRST:[0-9]+]], 0(${{[0-9]+}}) +;CHECK_BIG_32: #APP +;CHECK_BIG_32: or ${{[0-9]+}},$[[SECOND]],${{[0-9]+}} +;CHECK_BIG_32: #NO_APP + %bosco = load i64* getelementptr inbounds (%union.u_tag* @uval, i32 0, i32 0), align 8 + %trunc1 = trunc i64 %bosco to i32 + tail call i32 asm sideeffect "or $0,${1:L},$2", "=r,r,r"(i64 %bosco, i32 %trunc1) nounwind + ret i32 0 +} + +; M, in little endian the source reg will be 4 bytes into the long long +define i32 @constraint_M() nounwind { +entry: +;CHECK_LITTLE_32: constraint_M: +;CHECK_LITTLE_32: lw ${{[0-9]+}}, %got(uval)(${{[0-9,a-z]+}}) +;CHECK_LITTLE_32: lw $[[SECOND:[0-9]+]], 4(${{[0-9]+}}) +;CHECK_LITTLE_32: lw $[[FIRST:[0-9]+]], 0(${{[0-9]+}}) +;CHECK_LITTLE_32: #APP +;CHECK_LITTLE_32: or ${{[0-9]+}},$[[SECOND]],${{[0-9]+}} +;CHECK_LITTLE_32: #NO_APP +; M, in big endian the source reg will be 0 bytes into the long long +;CHECK_BIG_32: constraint_M: +;CHECK_BIG_32: lw ${{[0-9]+}}, %got(uval)(${{[0-9,a-z]+}}) +;CHECK_BIG_32: lw $[[SECOND:[0-9]+]], 4(${{[0-9]+}}) +;CHECK_BIG_32: lw $[[FIRST:[0-9]+]], 0(${{[0-9]+}}) +;CHECK_BIG_32: #APP +;CHECK_BIG_32: or ${{[0-9]+}},$[[FIRST]],${{[0-9]+}} +;CHECK_BIG_32: #NO_APP + %bosco = load i64* getelementptr inbounds (%union.u_tag* @uval, i32 0, i32 0), align 8 + %trunc1 = trunc i64 %bosco to i32 + tail call i32 asm sideeffect "or $0,${1:M},$2", "=r,r,r"(i64 %bosco, i32 %trunc1) nounwind + ret i32 0 +}