1; RUN: llc -mtriple=mips -relocation-model=static < %s \ 2; RUN: | FileCheck --check-prefixes=ALL,SYM32,O32,O32BE %s 3; RUN: llc -mtriple=mipsel -relocation-model=static < %s \ 4; RUN: | FileCheck --check-prefixes=ALL,SYM32,O32,O32LE %s 5 6; RUN-TODO: llc -mtriple=mips64 -relocation-model=static -target-abi o32 < %s \ 7; RUN-TODO: | FileCheck --check-prefixes=ALL,SYM32,O32 %s 8; RUN-TODO: llc -mtriple=mips64el -relocation-model=static -target-abi o32 < %s \ 9; RUN-TODO: | FileCheck --check-prefixes=ALL,SYM32,O32 %s 10 11; RUN: llc -mtriple=mips64 -relocation-model=static -target-abi n32 < %s \ 12; RUN: | FileCheck --check-prefixes=ALL,SYM32,N32,NEW,NEWBE %s 13; RUN: llc -mtriple=mips64el -relocation-model=static -target-abi n32 < %s \ 14; RUN: | FileCheck --check-prefixes=ALL,SYM32,N32,NEW,NEWLE %s 15 16; RUN: llc -mtriple=mips64 -relocation-model=static -target-abi n64 < %s \ 17; RUN: | FileCheck --check-prefixes=ALL,SYM64,N64,NEW,NEWBE %s 18; RUN: llc -mtriple=mips64el -relocation-model=static -target-abi n64 < %s \ 19; RUN: | FileCheck --check-prefixes=ALL,SYM64,N64,NEW,NEWLE %s 20 21; Test the effect of varargs on floating point types in the non-variable part 22; of the argument list as specified by section 2 of the MIPSpro N32 Handbook. 23; 24; N32/N64 are almost identical in this area so many of their checks have been 25; combined into the 'NEW' prefix (the N stands for New). 26; 27; On O32, varargs prevents all FPU argument register usage. This contradicts 28; the N32 handbook, but agrees with the SYSV ABI and GCC's behaviour. 29 30@floats = global [11 x float] zeroinitializer 31@doubles = global [11 x double] zeroinitializer 32 33define void @double_args(double %a, ...) 34 nounwind { 35entry: 36 %0 = getelementptr [11 x double], [11 x double]* @doubles, i32 0, i32 1 37 store volatile double %a, double* %0 38 39 %ap = alloca i8* 40 %ap2 = bitcast i8** %ap to i8* 41 call void @llvm.va_start(i8* %ap2) 42 %b = va_arg i8** %ap, double 43 %1 = getelementptr [11 x double], [11 x double]* @doubles, i32 0, i32 2 44 store volatile double %b, double* %1 45 call void @llvm.va_end(i8* %ap2) 46 ret void 47} 48 49; ALL-LABEL: double_args: 50; We won't test the way the global address is calculated in this test. This is 51; just to get the register number for the other checks. 52; SYM32-DAG: addiu [[R2:\$[0-9]+]], ${{[0-9]+}}, %lo(doubles) 53; SYM64-DAG: daddiu [[R2:\$[0-9]+]], ${{[0-9]+}}, %lo(doubles) 54 55; O32 forbids using floating point registers for the non-variable portion. 56; N32/N64 allow it. 57; O32BE-DAG: mtc1 $5, [[FTMP1:\$f[0-9]*[02468]+]] 58; O32BE-DAG: mtc1 $4, [[FTMP2:\$f[0-9]*[13579]+]] 59; O32LE-DAG: mtc1 $4, [[FTMP1:\$f[0-9]*[02468]+]] 60; O32LE-DAG: mtc1 $5, [[FTMP2:\$f[0-9]*[13579]+]] 61; O32-DAG: sdc1 [[FTMP1]], 8([[R2]]) 62; NEW-DAG: sdc1 $f12, 8([[R2]]) 63 64; The varargs portion is dumped to stack 65; O32-DAG: sw $6, 16($sp) 66; O32-DAG: sw $7, 20($sp) 67; NEW-DAG: sd $5, 8($sp) 68; NEW-DAG: sd $6, 16($sp) 69; NEW-DAG: sd $7, 24($sp) 70; NEW-DAG: sd $8, 32($sp) 71; NEW-DAG: sd $9, 40($sp) 72; NEW-DAG: sd $10, 48($sp) 73; NEW-DAG: sd $11, 56($sp) 74 75; Get the varargs pointer 76; O32 has 4 bytes padding, 4 bytes for the varargs pointer, and 8 bytes reserved 77; for arguments 1 and 2. 78; N32/N64 has 8 bytes for the varargs pointer, and no reserved area. 79; O32-DAG: addiu [[VAPTR:\$[0-9]+]], $sp, 16 80; O32-DAG: sw [[VAPTR]], 4($sp) 81; N32-DAG: addiu [[VAPTR:\$[0-9]+]], $sp, 8 82; N32-DAG: sw [[VAPTR]], 4($sp) 83; N64-DAG: daddiu [[VAPTR:\$[0-9]+]], $sp, 8 84; N64-DAG: sd [[VAPTR]], 0($sp) 85 86; Increment the pointer then get the varargs arg 87; LLVM will rebind the load to the stack pointer instead of the varargs pointer 88; during lowering. This is fine and doesn't change the behaviour. 89; O32-DAG: addiu [[VAPTR]], [[VAPTR]], 8 90; N32-DAG: addiu [[VAPTR]], [[VAPTR]], 8 91; N64-DAG: daddiu [[VAPTR]], [[VAPTR]], 8 92; O32-DAG: ldc1 [[FTMP1:\$f[0-9]+]], 16($sp) 93; NEW-DAG: ldc1 [[FTMP1:\$f[0-9]+]], 8($sp) 94; ALL-DAG: sdc1 [[FTMP1]], 16([[R2]]) 95 96define void @float_args(float %a, ...) nounwind { 97entry: 98 %0 = getelementptr [11 x float], [11 x float]* @floats, i32 0, i32 1 99 store volatile float %a, float* %0 100 101 %ap = alloca i8* 102 %ap2 = bitcast i8** %ap to i8* 103 call void @llvm.va_start(i8* %ap2) 104 %b = va_arg i8** %ap, float 105 %1 = getelementptr [11 x float], [11 x float]* @floats, i32 0, i32 2 106 store volatile float %b, float* %1 107 call void @llvm.va_end(i8* %ap2) 108 ret void 109} 110 111; ALL-LABEL: float_args: 112; We won't test the way the global address is calculated in this test. This is 113; just to get the register number for the other checks. 114; SYM32-DAG: addiu [[R2:\$[0-9]+]], ${{[0-9]+}}, %lo(floats) 115; SYM64-DAG: daddiu [[R2:\$[0-9]+]], ${{[0-9]+}}, %lo(floats) 116 117; The first four arguments are the same in O32/N32/N64. 118; The non-variable portion should be unaffected. 119; O32-DAG: mtc1 $4, $f0 120; O32-DAG: swc1 $f0, 4([[R2]]) 121; NEW-DAG: swc1 $f12, 4([[R2]]) 122 123; The varargs portion is dumped to stack 124; O32-DAG: sw $5, 12($sp) 125; O32-DAG: sw $6, 16($sp) 126; O32-DAG: sw $7, 20($sp) 127; NEW-DAG: sd $5, 8($sp) 128; NEW-DAG: sd $6, 16($sp) 129; NEW-DAG: sd $7, 24($sp) 130; NEW-DAG: sd $8, 32($sp) 131; NEW-DAG: sd $9, 40($sp) 132; NEW-DAG: sd $10, 48($sp) 133; NEW-DAG: sd $11, 56($sp) 134 135; Get the varargs pointer 136; O32 has 4 bytes padding, 4 bytes for the varargs pointer, and should have 8 137; bytes reserved for arguments 1 and 2 (the first float arg) but as discussed in 138; arguments-float.ll, GCC doesn't agree with MD00305 and treats floats as 4 139; bytes so we only have 12 bytes total. 140; N32/N64 has 8 bytes for the varargs pointer, and no reserved area. 141; O32-DAG: addiu [[VAPTR:\$[0-9]+]], $sp, 12 142; O32-DAG: sw [[VAPTR]], 4($sp) 143; N32-DAG: addiu [[VAPTR:\$[0-9]+]], $sp, 8 144; N32-DAG: sw [[VAPTR]], 4($sp) 145; N64-DAG: daddiu [[VAPTR:\$[0-9]+]], $sp, 8 146; N64-DAG: sd [[VAPTR]], 0($sp) 147 148; Increment the pointer then get the varargs arg 149; LLVM will rebind the load to the stack pointer instead of the varargs pointer 150; during lowering. This is fine and doesn't change the behaviour. 151; Also, in big-endian mode the offset must be increased by 4 to retrieve the 152; correct half of the argument slot. 153; 154; O32-DAG: addiu [[VAPTR]], [[VAPTR]], 4 155; N32-DAG: addiu [[VAPTR]], [[VAPTR]], 8 156; N64-DAG: daddiu [[VAPTR]], [[VAPTR]], 8 157; O32-DAG: lwc1 [[FTMP1:\$f[0-9]+]], 12($sp) 158; NEWLE-DAG: lwc1 [[FTMP1:\$f[0-9]+]], 8($sp) 159; NEWBE-DAG: lwc1 [[FTMP1:\$f[0-9]+]], 12($sp) 160; ALL-DAG: swc1 [[FTMP1]], 8([[R2]]) 161 162declare void @llvm.va_start(i8*) 163declare void @llvm.va_copy(i8*, i8*) 164declare void @llvm.va_end(i8*) 165