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], ptr @doubles, i32 0, i32 1 37 store volatile double %a, ptr %0 38 39 %ap = alloca ptr 40 call void @llvm.va_start(ptr %ap) 41 %b = va_arg ptr %ap, double 42 %1 = getelementptr [11 x double], ptr @doubles, i32 0, i32 2 43 store volatile double %b, ptr %1 44 call void @llvm.va_end(ptr %ap) 45 ret void 46} 47 48; ALL-LABEL: double_args: 49; We won't test the way the global address is calculated in this test. This is 50; just to get the register number for the other checks. 51; SYM32-DAG: addiu [[R2:\$[0-9]+]], ${{[0-9]+}}, %lo(doubles) 52; SYM64-DAG: daddiu [[R2:\$[0-9]+]], ${{[0-9]+}}, %lo(doubles) 53 54; O32 forbids using floating point registers for the non-variable portion. 55; N32/N64 allow it. 56; O32BE-DAG: mtc1 $5, [[FTMP1:\$f[0-9]*[02468]+]] 57; O32BE-DAG: mtc1 $4, [[FTMP2:\$f[0-9]*[13579]+]] 58; O32LE-DAG: mtc1 $4, [[FTMP1:\$f[0-9]*[02468]+]] 59; O32LE-DAG: mtc1 $5, [[FTMP2:\$f[0-9]*[13579]+]] 60; O32-DAG: sdc1 [[FTMP1]], 8([[R2]]) 61; NEW-DAG: sdc1 $f12, 8([[R2]]) 62 63; The varargs portion is dumped to stack 64; O32-DAG: sw $6, 16($sp) 65; O32-DAG: sw $7, 20($sp) 66; NEW-DAG: sd $5, 8($sp) 67; NEW-DAG: sd $6, 16($sp) 68; NEW-DAG: sd $7, 24($sp) 69; NEW-DAG: sd $8, 32($sp) 70; NEW-DAG: sd $9, 40($sp) 71; NEW-DAG: sd $10, 48($sp) 72; NEW-DAG: sd $11, 56($sp) 73 74; Get the varargs pointer 75; O32 has 4 bytes padding, 4 bytes for the varargs pointer, and 8 bytes reserved 76; for arguments 1 and 2. 77; N32/N64 has 8 bytes for the varargs pointer, and no reserved area. 78; O32-DAG: addiu [[VAPTR:\$[0-9]+]], $sp, 16 79; O32-DAG: sw [[VAPTR]], 4($sp) 80; N32-DAG: addiu [[VAPTR:\$[0-9]+]], $sp, 8 81; N32-DAG: sw [[VAPTR]], 4($sp) 82; N64-DAG: daddiu [[VAPTR:\$[0-9]+]], $sp, 8 83; N64-DAG: sd [[VAPTR]], 0($sp) 84 85; Increment the pointer then get the varargs arg 86; LLVM will rebind the load to the stack pointer instead of the varargs pointer 87; during lowering. This is fine and doesn't change the behaviour. 88; O32-DAG: addiu [[VAPTR]], [[VAPTR]], 8 89; N32-DAG: addiu [[VAPTR]], [[VAPTR]], 8 90; N64-DAG: daddiu [[VAPTR]], [[VAPTR]], 8 91; O32-DAG: ldc1 [[FTMP1:\$f[0-9]+]], 16($sp) 92; NEW-DAG: ldc1 [[FTMP1:\$f[0-9]+]], 8($sp) 93; ALL-DAG: sdc1 [[FTMP1]], 16([[R2]]) 94 95define void @float_args(float %a, ...) nounwind { 96entry: 97 %0 = getelementptr [11 x float], ptr @floats, i32 0, i32 1 98 store volatile float %a, ptr %0 99 100 %ap = alloca ptr 101 call void @llvm.va_start(ptr %ap) 102 %b = va_arg ptr %ap, float 103 %1 = getelementptr [11 x float], ptr @floats, i32 0, i32 2 104 store volatile float %b, ptr %1 105 call void @llvm.va_end(ptr %ap) 106 ret void 107} 108 109; ALL-LABEL: float_args: 110; We won't test the way the global address is calculated in this test. This is 111; just to get the register number for the other checks. 112; SYM32-DAG: addiu [[R2:\$[0-9]+]], ${{[0-9]+}}, %lo(floats) 113; SYM64-DAG: daddiu [[R2:\$[0-9]+]], ${{[0-9]+}}, %lo(floats) 114 115; The first four arguments are the same in O32/N32/N64. 116; The non-variable portion should be unaffected. 117; O32-DAG: mtc1 $4, $f0 118; O32-DAG: swc1 $f0, 4([[R2]]) 119; NEW-DAG: swc1 $f12, 4([[R2]]) 120 121; The varargs portion is dumped to stack 122; O32-DAG: sw $5, 12($sp) 123; O32-DAG: sw $6, 16($sp) 124; O32-DAG: sw $7, 20($sp) 125; NEW-DAG: sd $5, 8($sp) 126; NEW-DAG: sd $6, 16($sp) 127; NEW-DAG: sd $7, 24($sp) 128; NEW-DAG: sd $8, 32($sp) 129; NEW-DAG: sd $9, 40($sp) 130; NEW-DAG: sd $10, 48($sp) 131; NEW-DAG: sd $11, 56($sp) 132 133; Get the varargs pointer 134; O32 has 4 bytes padding, 4 bytes for the varargs pointer, and should have 8 135; bytes reserved for arguments 1 and 2 (the first float arg) but as discussed in 136; arguments-float.ll, GCC doesn't agree with MD00305 and treats floats as 4 137; bytes so we only have 12 bytes total. 138; N32/N64 has 8 bytes for the varargs pointer, and no reserved area. 139; O32-DAG: addiu [[VAPTR:\$[0-9]+]], $sp, 12 140; O32-DAG: sw [[VAPTR]], 4($sp) 141; N32-DAG: addiu [[VAPTR:\$[0-9]+]], $sp, 8 142; N32-DAG: sw [[VAPTR]], 4($sp) 143; N64-DAG: daddiu [[VAPTR:\$[0-9]+]], $sp, 8 144; N64-DAG: sd [[VAPTR]], 0($sp) 145 146; Increment the pointer then get the varargs arg 147; LLVM will rebind the load to the stack pointer instead of the varargs pointer 148; during lowering. This is fine and doesn't change the behaviour. 149; Also, in big-endian mode the offset must be increased by 4 to retrieve the 150; correct half of the argument slot. 151; 152; O32-DAG: addiu [[VAPTR]], [[VAPTR]], 4 153; N32-DAG: addiu [[VAPTR]], [[VAPTR]], 8 154; N64-DAG: daddiu [[VAPTR]], [[VAPTR]], 8 155; O32-DAG: lwc1 [[FTMP1:\$f[0-9]+]], 12($sp) 156; NEWLE-DAG: lwc1 [[FTMP1:\$f[0-9]+]], 8($sp) 157; NEWBE-DAG: lwc1 [[FTMP1:\$f[0-9]+]], 12($sp) 158; ALL-DAG: swc1 [[FTMP1]], 8([[R2]]) 159 160declare void @llvm.va_start(ptr) 161declare void @llvm.va_copy(ptr, ptr) 162declare void @llvm.va_end(ptr) 163