2012-05-11 05:48:22 +08:00
|
|
|
; Positive test for inline register constraints
|
|
|
|
;
|
2016-04-11 23:24:23 +08:00
|
|
|
; RUN: llc -no-integrated-as -march=mipsel -relocation-model=pic < %s | \
|
2016-06-24 20:23:17 +08:00
|
|
|
; RUN: FileCheck -check-prefixes=ALL,LE32,GAS %s
|
2016-04-11 23:24:23 +08:00
|
|
|
; RUN: llc -no-integrated-as -march=mips -relocation-model=pic < %s | \
|
2016-06-24 20:23:17 +08:00
|
|
|
; RUN: FileCheck -check-prefixes=ALL,BE32,GAS %s
|
2012-05-11 05:48:22 +08:00
|
|
|
|
2016-05-14 20:43:08 +08:00
|
|
|
; IAS might not print in the same way since it parses the assembly.
|
|
|
|
; RUN: llc -march=mipsel -relocation-model=pic < %s | \
|
2016-06-24 20:23:17 +08:00
|
|
|
; RUN: FileCheck -check-prefixes=ALL,LE32,IAS %s
|
2016-05-14 20:43:08 +08:00
|
|
|
; RUN: llc -march=mips -relocation-model=pic < %s | \
|
2016-06-24 20:23:17 +08:00
|
|
|
; RUN: FileCheck -check-prefixes=ALL,BE32,IAS %s
|
2016-05-14 20:43:08 +08:00
|
|
|
|
2012-07-06 07:58:21 +08:00
|
|
|
%union.u_tag = type { i64 }
|
|
|
|
%struct.anon = type { i32, i32 }
|
|
|
|
@uval = common global %union.u_tag zeroinitializer, align 8
|
2012-05-11 05:48:22 +08:00
|
|
|
|
|
|
|
; X with -3
|
2012-07-18 14:41:36 +08:00
|
|
|
define i32 @constraint_X() nounwind {
|
|
|
|
entry:
|
2015-11-26 19:23:03 +08:00
|
|
|
; ALL-LABEL: constraint_X:
|
|
|
|
; ALL: #APP
|
|
|
|
; GAS: addiu ${{[0-9]+}}, ${{[0-9]+}}, 0xfffffffffffffffd
|
2016-05-14 20:43:08 +08:00
|
|
|
; IAS: addiu ${{[0-9]+}}, ${{[0-9]+}}, -3
|
2015-11-26 19:23:03 +08:00
|
|
|
; ALL: #NO_APP
|
2015-11-16 22:14:59 +08:00
|
|
|
tail call i32 asm sideeffect "addiu $0, $1, ${2:X}", "=r,r,I"(i32 7, i32 -3) ;
|
2012-07-18 14:41:36 +08:00
|
|
|
ret i32 0
|
|
|
|
}
|
2012-05-11 05:48:22 +08:00
|
|
|
|
2012-05-19 01:39:35 +08:00
|
|
|
; x with -3
|
2012-07-18 14:41:36 +08:00
|
|
|
define i32 @constraint_x() nounwind {
|
|
|
|
entry:
|
2015-11-26 19:23:03 +08:00
|
|
|
; ALL-LABEL: constraint_x:
|
|
|
|
; ALL: #APP
|
|
|
|
; GAS: addiu ${{[0-9]+}}, ${{[0-9]+}}, 0xfffd
|
2016-05-14 20:43:08 +08:00
|
|
|
; This is _also_ -3 because uimm16 values are silently coerced to simm16 when
|
|
|
|
; it would otherwise fail to match.
|
|
|
|
; IAS: addiu ${{[0-9]+}}, ${{[0-9]+}}, -3
|
2015-11-26 19:23:03 +08:00
|
|
|
; ALL: #NO_APP
|
2015-11-16 22:14:59 +08:00
|
|
|
tail call i32 asm sideeffect "addiu $0, $1, ${2:x}", "=r,r,I"(i32 7, i32 -3) ;
|
2012-07-18 14:41:36 +08:00
|
|
|
ret i32 0
|
|
|
|
}
|
2012-05-19 01:39:35 +08:00
|
|
|
|
2012-05-19 08:51:56 +08:00
|
|
|
; d with -3
|
2012-07-18 14:41:36 +08:00
|
|
|
define i32 @constraint_d() nounwind {
|
|
|
|
entry:
|
2015-11-26 19:23:03 +08:00
|
|
|
; ALL-LABEL: constraint_d:
|
|
|
|
; ALL: #APP
|
|
|
|
; ALL: addiu ${{[0-9]+}}, ${{[0-9]+}}, -3
|
|
|
|
; ALL: #NO_APP
|
2015-11-16 22:14:59 +08:00
|
|
|
tail call i32 asm sideeffect "addiu $0, $1, ${2:d}", "=r,r,I"(i32 7, i32 -3) ;
|
2012-07-18 14:41:36 +08:00
|
|
|
ret i32 0
|
|
|
|
}
|
2012-05-19 08:51:56 +08:00
|
|
|
|
2012-05-31 03:05:19 +08:00
|
|
|
; m with -3
|
2012-07-18 14:41:36 +08:00
|
|
|
define i32 @constraint_m() nounwind {
|
|
|
|
entry:
|
2015-11-26 19:23:03 +08:00
|
|
|
; ALL-LABEL: constraint_m:
|
|
|
|
; ALL: #APP
|
|
|
|
; ALL: addiu ${{[0-9]+}}, ${{[0-9]+}}, -4
|
|
|
|
; ALL: #NO_APP
|
2015-11-16 22:14:59 +08:00
|
|
|
tail call i32 asm sideeffect "addiu $0, $1, ${2:m}", "=r,r,I"(i32 7, i32 -3) ;
|
2012-07-18 14:41:36 +08:00
|
|
|
ret i32 0
|
|
|
|
}
|
2012-05-31 03:05:19 +08:00
|
|
|
|
2012-06-28 09:33:40 +08:00
|
|
|
; z with -3
|
2016-05-14 20:43:08 +08:00
|
|
|
define void @constraint_z_0() nounwind {
|
2012-07-18 14:41:36 +08:00
|
|
|
entry:
|
2016-05-14 20:43:08 +08:00
|
|
|
; ALL-LABEL: constraint_z_0:
|
2015-11-26 19:23:03 +08:00
|
|
|
; ALL: #APP
|
|
|
|
; ALL: addiu ${{[0-9]+}}, ${{[0-9]+}}, -3
|
|
|
|
; ALL: #NO_APP
|
2015-11-16 22:14:59 +08:00
|
|
|
tail call i32 asm sideeffect "addiu $0, $1, ${2:z}", "=r,r,I"(i32 7, i32 -3) ;
|
2016-05-14 20:43:08 +08:00
|
|
|
ret void
|
|
|
|
}
|
2012-06-28 09:33:40 +08:00
|
|
|
|
|
|
|
; z with 0
|
2016-05-14 20:43:08 +08:00
|
|
|
define void @constraint_z_1() nounwind {
|
|
|
|
entry:
|
|
|
|
; ALL-LABEL: constraint_z_1:
|
2015-11-26 19:23:03 +08:00
|
|
|
; ALL: #APP
|
2016-05-14 20:43:08 +08:00
|
|
|
; GAS: addu ${{[0-9]+}}, ${{[0-9]+}}, $0
|
|
|
|
; IAS: move ${{[0-9]+}}, ${{[0-9]+}}
|
2015-11-26 19:23:03 +08:00
|
|
|
; ALL: #NO_APP
|
2016-05-14 20:43:08 +08:00
|
|
|
tail call i32 asm sideeffect "addu $0, $1, ${2:z}", "=r,r,I"(i32 7, i32 0) nounwind
|
|
|
|
ret void
|
|
|
|
}
|
2014-11-06 22:25:42 +08:00
|
|
|
|
|
|
|
; z with non-zero and the "r"(register) and "J"(integer zero) constraints
|
2016-05-14 20:43:08 +08:00
|
|
|
define void @constraint_z_2() nounwind {
|
|
|
|
entry:
|
|
|
|
; ALL-LABEL: constraint_z_2:
|
2015-11-26 19:23:03 +08:00
|
|
|
; ALL: #APP
|
|
|
|
; ALL: mtc0 ${{[1-9][0-9]?}}, ${{[0-9]+}}
|
|
|
|
; ALL: #NO_APP
|
2014-11-06 22:25:42 +08:00
|
|
|
call void asm sideeffect "mtc0 ${0:z}, $$12", "Jr"(i32 7) nounwind
|
2016-05-14 20:43:08 +08:00
|
|
|
ret void
|
|
|
|
}
|
2014-11-06 22:25:42 +08:00
|
|
|
|
|
|
|
; z with zero and the "r"(register) and "J"(integer zero) constraints
|
2016-05-14 20:43:08 +08:00
|
|
|
define void @constraint_z_3() nounwind {
|
|
|
|
entry:
|
|
|
|
; ALL-LABEL: constraint_z_3:
|
2015-11-26 19:23:03 +08:00
|
|
|
; ALL: #APP
|
2016-05-14 20:43:08 +08:00
|
|
|
; GAS: mtc0 $0, ${{[0-9]+}}
|
|
|
|
; IAS: mtc0 $zero, ${{[0-9]+}}, 0
|
2015-11-26 19:23:03 +08:00
|
|
|
; ALL: #NO_APP
|
2014-11-06 22:25:42 +08:00
|
|
|
call void asm sideeffect "mtc0 ${0:z}, $$12", "Jr"(i32 0) nounwind
|
2016-05-14 20:43:08 +08:00
|
|
|
ret void
|
|
|
|
}
|
2014-11-06 22:25:42 +08:00
|
|
|
|
|
|
|
; z with non-zero and just the "r"(register) constraint
|
2016-05-14 20:43:08 +08:00
|
|
|
define void @constraint_z_4() nounwind {
|
|
|
|
entry:
|
|
|
|
; ALL-LABEL: constraint_z_4:
|
2015-11-26 19:23:03 +08:00
|
|
|
; ALL: #APP
|
|
|
|
; ALL: mtc0 ${{[1-9][0-9]?}}, ${{[0-9]+}}
|
|
|
|
; ALL: #NO_APP
|
2014-11-06 22:25:42 +08:00
|
|
|
call void asm sideeffect "mtc0 ${0:z}, $$12", "r"(i32 7) nounwind
|
2016-05-14 20:43:08 +08:00
|
|
|
ret void
|
|
|
|
}
|
2014-11-06 22:25:42 +08:00
|
|
|
|
|
|
|
; z with zero and just the "r"(register) constraint
|
2016-05-14 20:43:08 +08:00
|
|
|
define void @constraint_z_5() nounwind {
|
|
|
|
entry:
|
|
|
|
; ALL-LABEL: constraint_z_5:
|
2014-11-06 22:25:42 +08:00
|
|
|
; FIXME: Check for $0, instead of other registers.
|
|
|
|
; We should be using $0 directly in this case, not real registers.
|
|
|
|
; When the materialization of 0 gets fixed, this test will fail.
|
2015-11-26 19:23:03 +08:00
|
|
|
; ALL: #APP
|
|
|
|
; ALL: mtc0 ${{[1-9][0-9]?}}, ${{[0-9]+}}
|
|
|
|
; ALL: #NO_APP
|
2014-11-06 22:25:42 +08:00
|
|
|
call void asm sideeffect "mtc0 ${0:z}, $$12", "r"(i32 0) nounwind
|
2016-05-14 20:43:08 +08:00
|
|
|
ret void
|
2012-07-18 14:41:36 +08:00
|
|
|
}
|
2012-06-28 09:33:40 +08:00
|
|
|
|
2015-11-26 19:23:03 +08:00
|
|
|
; A long long in 32 bit mode (use to assert)
|
2012-07-18 14:41:36 +08:00
|
|
|
define i32 @constraint_longlong() nounwind {
|
|
|
|
entry:
|
2015-11-26 19:23:03 +08:00
|
|
|
; ALL-LABEL: constraint_longlong:
|
|
|
|
; ALL: #APP
|
|
|
|
; ALL: addiu ${{[0-9]+}}, ${{[0-9]+}}, 3
|
|
|
|
; ALL: #NO_APP
|
2015-11-16 22:14:59 +08:00
|
|
|
tail call i64 asm sideeffect "addiu $0, $1, $2 \0A\09", "=r,r,X"(i64 1229801703532086340, i64 3) nounwind
|
2012-07-18 14:41:36 +08:00
|
|
|
ret i32 0
|
|
|
|
}
|
2012-07-03 07:35:23 +08:00
|
|
|
|
2015-11-26 19:23:03 +08:00
|
|
|
; In little endian the source reg will be 4 bytes into the long long
|
|
|
|
; In big endian the source reg will also be 4 bytes into the long long
|
2012-07-18 14:41:36 +08:00
|
|
|
define i32 @constraint_D() nounwind {
|
|
|
|
entry:
|
2015-11-26 19:23:03 +08:00
|
|
|
; ALL-LABEL: constraint_D:
|
|
|
|
; ALL: lw ${{[0-9]+}}, %got(uval)(${{[0-9,a-z]+}})
|
|
|
|
; ALL: lw $[[SECOND:[0-9]+]], 4(${{[0-9]+}})
|
|
|
|
; ALL: lw $[[FIRST:[0-9]+]], 0(${{[0-9]+}})
|
|
|
|
; ALL: #APP
|
|
|
|
; LE32: or ${{[0-9]+}}, $[[SECOND]], ${{[0-9]+}}
|
|
|
|
; BE32: or ${{[0-9]+}}, $[[SECOND]], ${{[0-9]+}}
|
|
|
|
; ALL: #NO_APP
|
2015-03-14 02:20:45 +08:00
|
|
|
%bosco = load i64, i64* getelementptr inbounds (%union.u_tag, %union.u_tag* @uval, i32 0, i32 0), align 8
|
2012-07-18 14:41:36 +08:00
|
|
|
%trunc1 = trunc i64 %bosco to i32
|
2015-11-16 22:14:59 +08:00
|
|
|
tail call i32 asm sideeffect "or $0, ${1:D}, $2", "=r,r,r"(i64 %bosco, i32 %trunc1) nounwind
|
2012-07-18 14:41:36 +08:00
|
|
|
ret i32 0
|
|
|
|
}
|
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.
llvm-svn: 160028
2012-07-11 06:41:20 +08:00
|
|
|
|
2015-11-26 19:23:03 +08:00
|
|
|
; In little endian the source reg will be 0 bytes into the long long
|
|
|
|
; In big endian the source reg will be 4 bytes into the long long
|
2012-07-18 14:41:36 +08:00
|
|
|
define i32 @constraint_L() nounwind {
|
|
|
|
entry:
|
2015-11-26 19:23:03 +08:00
|
|
|
; ALL-LABEL: constraint_L:
|
|
|
|
; ALL: lw ${{[0-9]+}}, %got(uval)(${{[0-9,a-z]+}})
|
|
|
|
; ALL: lw $[[SECOND:[0-9]+]], 4(${{[0-9]+}})
|
|
|
|
; ALL: lw $[[FIRST:[0-9]+]], 0(${{[0-9]+}})
|
|
|
|
; ALL: #APP
|
|
|
|
; LE32: or ${{[0-9]+}}, $[[FIRST]], ${{[0-9]+}}
|
|
|
|
; BE32: or ${{[0-9]+}}, $[[SECOND]], ${{[0-9]+}}
|
|
|
|
; ALL: #NO_APP
|
2015-03-14 02:20:45 +08:00
|
|
|
%bosco = load i64, i64* getelementptr inbounds (%union.u_tag, %union.u_tag* @uval, i32 0, i32 0), align 8
|
2012-07-18 14:41:36 +08:00
|
|
|
%trunc1 = trunc i64 %bosco to i32
|
2015-11-16 22:14:59 +08:00
|
|
|
tail call i32 asm sideeffect "or $0, ${1:L}, $2", "=r,r,r"(i64 %bosco, i32 %trunc1) nounwind
|
2012-05-11 05:48:22 +08:00
|
|
|
ret i32 0
|
|
|
|
}
|
2012-07-06 07:58:21 +08:00
|
|
|
|
2015-11-26 19:23:03 +08:00
|
|
|
; In little endian the source reg will be 4 bytes into the long long
|
|
|
|
; In big endian the source reg will be 0 bytes into the long long
|
2012-07-18 14:41:36 +08:00
|
|
|
define i32 @constraint_M() nounwind {
|
|
|
|
entry:
|
2015-11-26 19:23:03 +08:00
|
|
|
; ALL-LABEL: constraint_M:
|
|
|
|
; ALL: lw ${{[0-9]+}}, %got(uval)(${{[0-9,a-z]+}})
|
|
|
|
; ALL: lw $[[SECOND:[0-9]+]], 4(${{[0-9]+}})
|
|
|
|
; ALL: lw $[[FIRST:[0-9]+]], 0(${{[0-9]+}})
|
|
|
|
; ALL: #APP
|
|
|
|
; LE32: or ${{[0-9]+}}, $[[SECOND]], ${{[0-9]+}}
|
|
|
|
; BE32: or ${{[0-9]+}}, $[[FIRST]], ${{[0-9]+}}
|
|
|
|
; ALL: #NO_APP
|
2015-03-14 02:20:45 +08:00
|
|
|
%bosco = load i64, i64* getelementptr inbounds (%union.u_tag, %union.u_tag* @uval, i32 0, i32 0), align 8
|
2012-07-18 14:41:36 +08:00
|
|
|
%trunc1 = trunc i64 %bosco to i32
|
2015-11-16 22:14:59 +08:00
|
|
|
tail call i32 asm sideeffect "or $0, ${1:M}, $2", "=r,r,r"(i64 %bosco, i32 %trunc1) nounwind
|
2012-07-18 14:41:36 +08:00
|
|
|
ret i32 0
|
|
|
|
}
|