1; RUN: llc -mtriple=mips-linux -relocation-model=static < %s | FileCheck --check-prefixes=ALL,O32,O32-BE %s 2; RUN: llc -mtriple=mipsel-linux -relocation-model=static < %s | FileCheck --check-prefixes=ALL,O32,O32-LE %s 3 4; RUN-TODO: llc -march=mips64 -relocation-model=static -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s 5; RUN-TODO: llc -march=mips64el -relocation-model=static -target-abi o32 < %s | FileCheck --check-prefixes=ALL,O32 %s 6 7; RUN: llc -mtriple=mips64-linux -relocation-model=static -target-abi n32 < %s | FileCheck --check-prefixes=ALL,NEW,N32,NEW-BE %s 8; RUN: llc -mtriple=mips64el-linux -relocation-model=static -target-abi n32 < %s | FileCheck --check-prefixes=ALL,NEW,N32,NEW-LE %s 9 10; RUN: llc -march=mips64 -relocation-model=static -target-abi n64 < %s | FileCheck --check-prefixes=ALL,NEW,N64,NEW-BE %s 11; RUN: llc -march=mips64el -relocation-model=static -target-abi n64 < %s | FileCheck --check-prefixes=ALL,NEW,N64,NEW-LE %s 12 13@hwords = global [3 x i16] zeroinitializer, align 1 14@words = global [3 x i32] zeroinitializer, align 1 15@dwords = global [3 x i64] zeroinitializer, align 1 16 17define void @fn_i16_dotdotdot_i16(i16 %a, ...) { 18entry: 19; ALL-LABEL: fn_i16_dotdotdot_i16: 20 21; Set up the stack with an 8-byte local area. N32/N64 must also make room for 22; the argument save area (56 bytes). 23; O32: addiu [[SP:\$sp]], $sp, -8 24; N32: addiu [[SP:\$sp]], $sp, -64 25; N64: daddiu [[SP:\$sp]], $sp, -64 26 27; Save variable argument portion on the stack 28; O32-DAG: sw $7, 20([[SP]]) 29; O32-DAG: sw $6, 16([[SP]]) 30; O32-DAG: sw $5, 12([[SP]]) 31 32; NEW-DAG: sd $11, 56([[SP]]) 33; NEW-DAG: sd $10, 48([[SP]]) 34; NEW-DAG: sd $9, 40([[SP]]) 35; NEW-DAG: sd $8, 32([[SP]]) 36; NEW-DAG: sd $7, 24([[SP]]) 37; NEW-DAG: sd $6, 16([[SP]]) 38; NEW-DAG: sd $5, 8([[SP]]) 39 40; Initialize variable argument pointer. 41; For O32, the offset is 12 due to the 4 bytes used to store local variables, 42; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first 43; fixed argument. 44; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 45; space. 46; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 47; O32-DAG: sw [[VA]], 0([[SP]]) 48 49; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 50; N32-DAG: sw [[VA]], 0([[SP]]) 51 52; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 53; N64-DAG: sd [[VA]], 0([[SP]]) 54 55; Store [[VA]] 56; O32-DAG: sw [[VA]], 0([[SP]]) 57 58; ALL: teqi $zero, 1 59 60; Increment [[VA]] 61; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 62; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 63; O32-DAG: sw [[VA2]], 0([[SP]]) 64 65; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 66; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 67; N32-DAG: sw [[VA2]], 0([[SP]]) 68 69; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 70; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 71; N64-DAG: sd [[VA2]], 0([[SP]]) 72 73; Load the first argument from the variable portion. 74; This has used the stack pointer directly rather than the [[VA]] we just set 75; up. 76; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 77; order. 78; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 79 80; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 81; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) 82 83; Copy the arg to the global 84; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 85 86; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 87 88; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(hwords)( 89 90; ALL-DAG: sh [[ARG1]], 2([[GV]]) 91 92; ALL: teqi $zero, 2 93 94; Increment [[VA]] again. 95; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 96; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 97; O32-DAG: sw [[VA2]], 0([[SP]]) 98 99; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 100; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 101; N32-DAG: sw [[VA3]], 0([[SP]]) 102 103; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 104; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 105; N64-DAG: sd [[VA3]], 0([[SP]]) 106 107; Load the second argument from the variable portion. 108; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 109 110; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) 111; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) 112 113; Copy the arg to the global 114; ALL-DAG: sh [[ARG2]], 4([[GV]]) 115 116 %ap = alloca i8*, align 8 117 %ap2 = bitcast i8** %ap to i8* 118 call void @llvm.va_start(i8* %ap2) 119 120 call void asm sideeffect "teqi $$zero, 1", ""() 121 %arg1 = va_arg i8** %ap, i16 122 %e1 = getelementptr [3 x i16], [3 x i16]* @hwords, i32 0, i32 1 123 store volatile i16 %arg1, i16* %e1, align 2 124 125 call void asm sideeffect "teqi $$zero, 2", ""() 126 %arg2 = va_arg i8** %ap, i16 127 %e2 = getelementptr [3 x i16], [3 x i16]* @hwords, i32 0, i32 2 128 store volatile i16 %arg2, i16* %e2, align 2 129 130 call void @llvm.va_end(i8* %ap2) 131 132 ret void 133} 134 135define void @fn_i16_dotdotdot_i32(i16 %a, ...) { 136entry: 137; ALL-LABEL: fn_i16_dotdotdot_i32: 138 139; Set up the stack with an 8-byte local area. N32/N64 must also make room for 140; the argument save area (56 bytes). 141; O32: addiu [[SP:\$sp]], $sp, -8 142; N32: addiu [[SP:\$sp]], $sp, -64 143; N64: daddiu [[SP:\$sp]], $sp, -64 144 145; Save variable argument portion on the stack 146; O32-DAG: sw $7, 20([[SP]]) 147; O32-DAG: sw $6, 16([[SP]]) 148; O32-DAG: sw $5, 12([[SP]]) 149 150; NEW-DAG: sd $11, 56([[SP]]) 151; NEW-DAG: sd $10, 48([[SP]]) 152; NEW-DAG: sd $9, 40([[SP]]) 153; NEW-DAG: sd $8, 32([[SP]]) 154; NEW-DAG: sd $7, 24([[SP]]) 155; NEW-DAG: sd $6, 16([[SP]]) 156; NEW-DAG: sd $5, 8([[SP]]) 157 158; Initialize variable argument pointer. 159; For O32, the offset is 12 due to the 4 bytes used to store local variables, 160; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first 161; fixed argument. 162; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 163; space. 164; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 165; O32-DAG: sw [[VA]], 0([[SP]]) 166 167; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 168; N32-DAG: sw [[VA]], 0([[SP]]) 169 170; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 171; N64-DAG: sd [[VA]], 0([[SP]]) 172 173; Store [[VA]] 174; O32-DAG: sw [[VA]], 0([[SP]]) 175 176; ALL: teqi $zero, 1 177 178; Increment [[VA]] 179; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 180; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 181; O32-DAG: sw [[VA2]], 0([[SP]]) 182 183; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 184; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 185; N32-DAG: sw [[VA2]], 0([[SP]]) 186 187; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 188; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 189; N64-DAG: sd [[VA2]], 0([[SP]]) 190 191; Load the first argument from the variable portion. 192; This has used the stack pointer directly rather than the [[VA]] we just set 193; up. 194; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 195; order. 196; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 197 198; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 199; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) 200 201; Copy the arg to the global 202; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 203 204; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 205 206; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(words)( 207 208; ALL-DAG: sw [[ARG1]], 4([[GV]]) 209 210; ALL: teqi $zero, 2 211 212; Increment [[VA]] again. 213; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 214; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 215; O32-DAG: sw [[VA2]], 0([[SP]]) 216 217; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 218; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 219; N32-DAG: sw [[VA3]], 0([[SP]]) 220 221; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 222; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 223; N64-DAG: sd [[VA3]], 0([[SP]]) 224 225; Load the second argument from the variable portion. 226; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 227 228; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) 229; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) 230 231; Copy the arg to the global 232; ALL-DAG: sw [[ARG2]], 8([[GV]]) 233 234 %ap = alloca i8*, align 8 235 %ap2 = bitcast i8** %ap to i8* 236 call void @llvm.va_start(i8* %ap2) 237 238 call void asm sideeffect "teqi $$zero, 1", ""() 239 %arg1 = va_arg i8** %ap, i32 240 %e1 = getelementptr [3 x i32], [3 x i32]* @words, i32 0, i32 1 241 store volatile i32 %arg1, i32* %e1, align 4 242 243 call void asm sideeffect "teqi $$zero, 2", ""() 244 %arg2 = va_arg i8** %ap, i32 245 %e2 = getelementptr [3 x i32], [3 x i32]* @words, i32 0, i32 2 246 store volatile i32 %arg2, i32* %e2, align 4 247 248 call void @llvm.va_end(i8* %ap2) 249 250 ret void 251} 252 253define void @fn_i16_dotdotdot_i64(i16 %a, ...) { 254entry: 255; ALL-LABEL: fn_i16_dotdotdot_i64: 256 257; Set up the stack with an 8-byte local area. N32/N64 must also make room for 258; the argument save area (56 bytes). 259; O32: addiu [[SP:\$sp]], $sp, -8 260; N32: addiu [[SP:\$sp]], $sp, -64 261; N64: daddiu [[SP:\$sp]], $sp, -64 262 263; Save variable argument portion on the stack 264; O32-DAG: sw $7, 20([[SP]]) 265; O32-DAG: sw $6, 16([[SP]]) 266; O32-DAG: sw $5, 12([[SP]]) 267 268; NEW-DAG: sd $11, 56([[SP]]) 269; NEW-DAG: sd $10, 48([[SP]]) 270; NEW-DAG: sd $9, 40([[SP]]) 271; NEW-DAG: sd $8, 32([[SP]]) 272; NEW-DAG: sd $7, 24([[SP]]) 273; NEW-DAG: sd $6, 16([[SP]]) 274; NEW-DAG: sd $5, 8([[SP]]) 275 276; Initialize variable argument pointer. 277; For O32, the offset is 12 due to the 4 bytes used to store local variables, 278; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first 279; fixed argument. 280; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 281; space. 282; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 283; O32-DAG: sw [[VA]], 0([[SP]]) 284 285; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 286; N32-DAG: sw [[VA]], 0([[SP]]) 287 288; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 289; N64-DAG: sd [[VA]], 0([[SP]]) 290 291; Store [[VA]] 292; O32-DAG: sw [[VA]], 0([[SP]]) 293 294; ALL: teqi $zero, 1 295 296; Increment [[VA]] (and realign pointer for O32) 297; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) 298; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 299; O32-DAG: addiu [[VA_TMP1:\$[0-9]+]], $zero, -8 300; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] 301; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 302; O32-DAG: sw [[VA2]], 0([[SP]]) 303 304; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 305; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 306; N32-DAG: sw [[VA2]], 0([[SP]]) 307 308; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 309; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 310; N64-DAG: sd [[VA2]], 0([[SP]]) 311 312; Load the first argument from the variable portion and copy it to the global. 313; This has used the stack pointer directly rather than the [[VA]] we just set 314; up. 315; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 316; order. 317; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 318; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 319; O32-DAG: sw [[ARG1]], 8([[GV]]) 320; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 321; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 322; O32-DAG: sw [[VA2]], 0([[SP]]) 323; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 324; O32-DAG: sw [[ARG1]], 12([[GV]]) 325 326; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 327; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(dwords)( 328; NEW-DAG: ld [[ARG1:\$[0-9]+]], 0([[VA]]) 329; NEW-DAG: sd [[ARG1]], 8([[GV]]) 330 331; ALL: teqi $zero, 2 332 333; Increment [[VA]] again. 334; FIXME: We're still aligned from the last one but CodeGen doesn't spot that. 335; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) 336; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 337; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] 338; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 339; O32-DAG: sw [[VA2]], 0([[SP]]) 340 341; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 342; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 343; N32-DAG: sw [[VA3]], 0([[SP]]) 344 345; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 346; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 347; N64-DAG: sd [[VA3]], 0([[SP]]) 348 349; Load the second argument from the variable portion and copy it to the global. 350; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 351; O32-DAG: sw [[ARG2]], 16([[GV]]) 352; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 353; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 354; O32-DAG: sw [[VA2]], 0([[SP]]) 355; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 356; O32-DAG: sw [[ARG2]], 20([[GV]]) 357 358; NEW-DAG: ld [[ARG2:\$[0-9]+]], 0([[VA2]]) 359; NEW-DAG: sd [[ARG2]], 16([[GV]]) 360 361 %ap = alloca i8*, align 8 362 %ap2 = bitcast i8** %ap to i8* 363 call void @llvm.va_start(i8* %ap2) 364 365 call void asm sideeffect "teqi $$zero, 1", ""() 366 %arg1 = va_arg i8** %ap, i64 367 %e1 = getelementptr [3 x i64], [3 x i64]* @dwords, i32 0, i32 1 368 store volatile i64 %arg1, i64* %e1, align 8 369 370 call void asm sideeffect "teqi $$zero, 2", ""() 371 %arg2 = va_arg i8** %ap, i64 372 %e2 = getelementptr [3 x i64], [3 x i64]* @dwords, i32 0, i32 2 373 store volatile i64 %arg2, i64* %e2, align 8 374 375 call void @llvm.va_end(i8* %ap2) 376 377 ret void 378} 379 380define void @fn_i32_dotdotdot_i16(i32 %a, ...) { 381entry: 382; ALL-LABEL: fn_i32_dotdotdot_i16: 383 384; Set up the stack with an 8-byte local area. N32/N64 must also make room for 385; the argument save area (56 bytes). 386; O32: addiu [[SP:\$sp]], $sp, -8 387; N32: addiu [[SP:\$sp]], $sp, -64 388; N64: daddiu [[SP:\$sp]], $sp, -64 389 390; Save variable argument portion on the stack 391; O32-DAG: sw $7, 20([[SP]]) 392; O32-DAG: sw $6, 16([[SP]]) 393; O32-DAG: sw $5, 12([[SP]]) 394 395; NEW-DAG: sd $11, 56([[SP]]) 396; NEW-DAG: sd $10, 48([[SP]]) 397; NEW-DAG: sd $9, 40([[SP]]) 398; NEW-DAG: sd $8, 32([[SP]]) 399; NEW-DAG: sd $7, 24([[SP]]) 400; NEW-DAG: sd $6, 16([[SP]]) 401; NEW-DAG: sd $5, 8([[SP]]) 402 403; Initialize variable argument pointer. 404; For O32, the offset is 12 due to the 4 bytes used to store local variables, 405; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first 406; fixed argument. 407; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 408; space. 409; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 410; O32-DAG: sw [[VA]], 0([[SP]]) 411 412; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 413; N32-DAG: sw [[VA]], 0([[SP]]) 414 415; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 416; N64-DAG: sd [[VA]], 0([[SP]]) 417 418; Store [[VA]] 419; O32-DAG: sw [[VA]], 0([[SP]]) 420 421; ALL: teqi $zero, 1 422 423; Increment [[VA]] 424; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 425; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 426; O32-DAG: sw [[VA2]], 0([[SP]]) 427 428; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 429; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 430; N32-DAG: sw [[VA2]], 0([[SP]]) 431 432; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 433; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 434; N64-DAG: sd [[VA2]], 0([[SP]]) 435 436; Load the first argument from the variable portion. 437; This has used the stack pointer directly rather than the [[VA]] we just set 438; up. 439; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 440; order. 441; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 442 443; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 444; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) 445 446; Copy the arg to the global 447; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 448 449; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 450 451; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(hwords)( 452 453; ALL-DAG: sh [[ARG1]], 2([[GV]]) 454 455; ALL: teqi $zero, 2 456 457; Increment [[VA]] again. 458; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 459; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 460; O32-DAG: sw [[VA2]], 0([[SP]]) 461 462; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 463; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 464; N32-DAG: sw [[VA3]], 0([[SP]]) 465 466; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 467; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 468; N64-DAG: sd [[VA3]], 0([[SP]]) 469 470; Load the second argument from the variable portion. 471; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 472 473; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) 474; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) 475 476; Copy the arg to the global 477; ALL-DAG: sh [[ARG2]], 4([[GV]]) 478 479 %ap = alloca i8*, align 8 480 %ap2 = bitcast i8** %ap to i8* 481 call void @llvm.va_start(i8* %ap2) 482 483 call void asm sideeffect "teqi $$zero, 1", ""() 484 %arg1 = va_arg i8** %ap, i16 485 %e1 = getelementptr [3 x i16], [3 x i16]* @hwords, i32 0, i32 1 486 store volatile i16 %arg1, i16* %e1, align 2 487 488 call void asm sideeffect "teqi $$zero, 2", ""() 489 %arg2 = va_arg i8** %ap, i16 490 %e2 = getelementptr [3 x i16], [3 x i16]* @hwords, i32 0, i32 2 491 store volatile i16 %arg2, i16* %e2, align 2 492 493 call void @llvm.va_end(i8* %ap2) 494 495 ret void 496} 497 498define void @fn_i32_dotdotdot_i32(i32 %a, ...) { 499entry: 500; ALL-LABEL: fn_i32_dotdotdot_i32: 501 502; Set up the stack with an 8-byte local area. N32/N64 must also make room for 503; the argument save area (56 bytes). 504; O32: addiu [[SP:\$sp]], $sp, -8 505; N32: addiu [[SP:\$sp]], $sp, -64 506; N64: daddiu [[SP:\$sp]], $sp, -64 507 508; Save variable argument portion on the stack 509; O32-DAG: sw $7, 20([[SP]]) 510; O32-DAG: sw $6, 16([[SP]]) 511; O32-DAG: sw $5, 12([[SP]]) 512 513; NEW-DAG: sd $11, 56([[SP]]) 514; NEW-DAG: sd $10, 48([[SP]]) 515; NEW-DAG: sd $9, 40([[SP]]) 516; NEW-DAG: sd $8, 32([[SP]]) 517; NEW-DAG: sd $7, 24([[SP]]) 518; NEW-DAG: sd $6, 16([[SP]]) 519; NEW-DAG: sd $5, 8([[SP]]) 520 521; Initialize variable argument pointer. 522; For O32, the offset is 12 due to the 4 bytes used to store local variables, 523; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first 524; fixed argument. 525; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 526; space. 527; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 528; O32-DAG: sw [[VA]], 0([[SP]]) 529 530; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 531; N32-DAG: sw [[VA]], 0([[SP]]) 532 533; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 534; N64-DAG: sd [[VA]], 0([[SP]]) 535 536; Store [[VA]] 537; O32-DAG: sw [[VA]], 0([[SP]]) 538 539; ALL: teqi $zero, 1 540 541; Increment [[VA]] 542; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 543; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 544; O32-DAG: sw [[VA2]], 0([[SP]]) 545 546; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 547; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 548; N32-DAG: sw [[VA2]], 0([[SP]]) 549 550; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 551; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 552; N64-DAG: sd [[VA2]], 0([[SP]]) 553 554; Load the first argument from the variable portion. 555; This has used the stack pointer directly rather than the [[VA]] we just set 556; up. 557; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 558; order. 559; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 560 561; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 562; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) 563 564; Copy the arg to the global 565; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 566 567; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 568 569; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(words)( 570 571; ALL-DAG: sw [[ARG1]], 4([[GV]]) 572 573; ALL: teqi $zero, 2 574 575; Increment [[VA]] again. 576; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 577; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 578; O32-DAG: sw [[VA2]], 0([[SP]]) 579 580; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 581; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 582; N32-DAG: sw [[VA3]], 0([[SP]]) 583 584; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 585; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 586; N64-DAG: sd [[VA3]], 0([[SP]]) 587 588; Load the second argument from the variable portion. 589; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 590 591; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) 592; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) 593 594; Copy the arg to the global 595; ALL-DAG: sw [[ARG2]], 8([[GV]]) 596 597 %ap = alloca i8*, align 8 598 %ap2 = bitcast i8** %ap to i8* 599 call void @llvm.va_start(i8* %ap2) 600 601 call void asm sideeffect "teqi $$zero, 1", ""() 602 %arg1 = va_arg i8** %ap, i32 603 %e1 = getelementptr [3 x i32], [3 x i32]* @words, i32 0, i32 1 604 store volatile i32 %arg1, i32* %e1, align 4 605 606 call void asm sideeffect "teqi $$zero, 2", ""() 607 %arg2 = va_arg i8** %ap, i32 608 %e2 = getelementptr [3 x i32], [3 x i32]* @words, i32 0, i32 2 609 store volatile i32 %arg2, i32* %e2, align 4 610 611 call void @llvm.va_end(i8* %ap2) 612 613 ret void 614} 615 616define void @fn_i32_dotdotdot_i64(i32 %a, ...) { 617entry: 618; ALL-LABEL: fn_i32_dotdotdot_i64: 619 620; Set up the stack with an 8-byte local area. N32/N64 must also make room for 621; the argument save area (56 bytes). 622; O32: addiu [[SP:\$sp]], $sp, -8 623; N32: addiu [[SP:\$sp]], $sp, -64 624; N64: daddiu [[SP:\$sp]], $sp, -64 625 626; Save variable argument portion on the stack 627; O32-DAG: sw $7, 20([[SP]]) 628; O32-DAG: sw $6, 16([[SP]]) 629; O32-DAG: sw $5, 12([[SP]]) 630 631; NEW-DAG: sd $11, 56([[SP]]) 632; NEW-DAG: sd $10, 48([[SP]]) 633; NEW-DAG: sd $9, 40([[SP]]) 634; NEW-DAG: sd $8, 32([[SP]]) 635; NEW-DAG: sd $7, 24([[SP]]) 636; NEW-DAG: sd $6, 16([[SP]]) 637; NEW-DAG: sd $5, 8([[SP]]) 638 639; Initialize variable argument pointer. 640; For O32, the offset is 12 due to the 4 bytes used to store local variables, 641; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first 642; fixed argument. 643; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 644; space. 645; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12 646; O32-DAG: sw [[VA]], 0([[SP]]) 647 648; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 649; N32-DAG: sw [[VA]], 0([[SP]]) 650 651; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 652; N64-DAG: sd [[VA]], 0([[SP]]) 653 654; Store [[VA]] 655; O32-DAG: sw [[VA]], 0([[SP]]) 656 657; ALL: teqi $zero, 1 658 659; Increment [[VA]] (and realign pointer for O32) 660; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) 661; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 662; O32-DAG: addiu [[VA_TMP1:\$[0-9]+]], $zero, -8 663; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] 664; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 665; O32-DAG: sw [[VA2]], 0([[SP]]) 666 667; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 668; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 669; N32-DAG: sw [[VA2]], 0([[SP]]) 670 671; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 672; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 673; N64-DAG: sd [[VA2]], 0([[SP]]) 674 675; Load the first argument from the variable portion and copy it to the global. 676; This has used the stack pointer directly rather than the [[VA]] we just set 677; up. 678; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 679; order. 680; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 681; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 682; O32-DAG: sw [[ARG1]], 8([[GV]]) 683; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 684; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 685; O32-DAG: sw [[VA2]], 0([[SP]]) 686; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 687; O32-DAG: sw [[ARG1]], 12([[GV]]) 688 689; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 690; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(dwords)( 691; NEW-DAG: ld [[ARG1:\$[0-9]+]], 0([[VA]]) 692; NEW-DAG: sd [[ARG1]], 8([[GV]]) 693 694; ALL: teqi $zero, 2 695 696; Increment [[VA]] again. 697; FIXME: We're still aligned from the last one but CodeGen doesn't spot that. 698; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) 699; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 700; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] 701; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 702; O32-DAG: sw [[VA2]], 0([[SP]]) 703 704; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 705; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 706; N32-DAG: sw [[VA3]], 0([[SP]]) 707 708; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 709; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 710; N64-DAG: sd [[VA3]], 0([[SP]]) 711 712; Load the second argument from the variable portion and copy it to the global. 713; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 714; O32-DAG: sw [[ARG2]], 16([[GV]]) 715; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 716; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 717; O32-DAG: sw [[VA2]], 0([[SP]]) 718; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 719; O32-DAG: sw [[ARG2]], 20([[GV]]) 720 721; NEW-DAG: ld [[ARG2:\$[0-9]+]], 0([[VA2]]) 722; NEW-DAG: sd [[ARG2]], 16([[GV]]) 723 724 %ap = alloca i8*, align 8 725 %ap2 = bitcast i8** %ap to i8* 726 call void @llvm.va_start(i8* %ap2) 727 728 call void asm sideeffect "teqi $$zero, 1", ""() 729 %arg1 = va_arg i8** %ap, i64 730 %e1 = getelementptr [3 x i64], [3 x i64]* @dwords, i32 0, i32 1 731 store volatile i64 %arg1, i64* %e1, align 8 732 733 call void asm sideeffect "teqi $$zero, 2", ""() 734 %arg2 = va_arg i8** %ap, i64 735 %e2 = getelementptr [3 x i64], [3 x i64]* @dwords, i32 0, i32 2 736 store volatile i64 %arg2, i64* %e2, align 8 737 738 call void @llvm.va_end(i8* %ap2) 739 740 ret void 741} 742 743define void @fn_i64_dotdotdot_i16(i64 %a, ...) { 744entry: 745; ALL-LABEL: fn_i64_dotdotdot_i16: 746 747; Set up the stack with an 8-byte local area. N32/N64 must also make room for 748; the argument save area (56 bytes). 749; O32: addiu [[SP:\$sp]], $sp, -8 750; N32: addiu [[SP:\$sp]], $sp, -64 751; N64: daddiu [[SP:\$sp]], $sp, -64 752 753; Save variable argument portion on the stack 754; O32-DAG: sw $7, 20([[SP]]) 755; O32-DAG: sw $6, 16([[SP]]) 756 757; NEW-DAG: sd $11, 56([[SP]]) 758; NEW-DAG: sd $10, 48([[SP]]) 759; NEW-DAG: sd $9, 40([[SP]]) 760; NEW-DAG: sd $8, 32([[SP]]) 761; NEW-DAG: sd $7, 24([[SP]]) 762; NEW-DAG: sd $6, 16([[SP]]) 763; NEW-DAG: sd $5, 8([[SP]]) 764 765; Initialize variable argument pointer. 766; For O32, the offset is 16 due to the 4 bytes used to store local variables, 767; 4 bytes padding to maintain stack alignment, and the two 4 byte slots for the 768; first fixed argument. 769; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 770; space. 771; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 16 772; O32-DAG: sw [[VA]], 0([[SP]]) 773 774; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 775; N32-DAG: sw [[VA]], 0([[SP]]) 776 777; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 778; N64-DAG: sd [[VA]], 0([[SP]]) 779 780; Store [[VA]] 781; O32-DAG: sw [[VA]], 0([[SP]]) 782 783; ALL: teqi $zero, 1 784 785; Increment [[VA]] 786; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 787; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 788; O32-DAG: sw [[VA2]], 0([[SP]]) 789 790; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 791; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 792; N32-DAG: sw [[VA2]], 0([[SP]]) 793 794; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 795; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 796; N64-DAG: sd [[VA2]], 0([[SP]]) 797 798; Load the first argument from the variable portion. 799; This has used the stack pointer directly rather than the [[VA]] we just set 800; up. 801; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 802; order. 803; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 804 805; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 806; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) 807 808; Copy the arg to the global 809; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 810 811; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords) 812 813; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(hwords)( 814 815; ALL-DAG: sh [[ARG1]], 2([[GV]]) 816 817; ALL: teqi $zero, 2 818 819; Increment [[VA]] again. 820; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 821; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 822; O32-DAG: sw [[VA2]], 0([[SP]]) 823 824; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 825; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 826; N32-DAG: sw [[VA3]], 0([[SP]]) 827 828; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 829; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 830; N64-DAG: sd [[VA3]], 0([[SP]]) 831 832; Load the second argument from the variable portion. 833; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 834 835; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) 836; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) 837 838; Copy the arg to the global 839; ALL-DAG: sh [[ARG2]], 4([[GV]]) 840 841 %ap = alloca i8*, align 8 842 %ap2 = bitcast i8** %ap to i8* 843 call void @llvm.va_start(i8* %ap2) 844 845 call void asm sideeffect "teqi $$zero, 1", ""() 846 %arg1 = va_arg i8** %ap, i16 847 %e1 = getelementptr [3 x i16], [3 x i16]* @hwords, i32 0, i32 1 848 store volatile i16 %arg1, i16* %e1, align 2 849 850 call void asm sideeffect "teqi $$zero, 2", ""() 851 %arg2 = va_arg i8** %ap, i16 852 %e2 = getelementptr [3 x i16], [3 x i16]* @hwords, i32 0, i32 2 853 store volatile i16 %arg2, i16* %e2, align 2 854 855 call void @llvm.va_end(i8* %ap2) 856 857 ret void 858} 859 860define void @fn_i64_dotdotdot_i32(i64 %a, ...) { 861entry: 862; ALL-LABEL: fn_i64_dotdotdot_i32: 863 864; Set up the stack with an 8-byte local area. N32/N64 must also make room for 865; the argument save area (56 bytes). 866; O32: addiu [[SP:\$sp]], $sp, -8 867; N32: addiu [[SP:\$sp]], $sp, -64 868; N64: daddiu [[SP:\$sp]], $sp, -64 869 870; Save variable argument portion on the stack 871; O32-DAG: sw $7, 20([[SP]]) 872; O32-DAG: sw $6, 16([[SP]]) 873 874; NEW-DAG: sd $11, 56([[SP]]) 875; NEW-DAG: sd $10, 48([[SP]]) 876; NEW-DAG: sd $9, 40([[SP]]) 877; NEW-DAG: sd $8, 32([[SP]]) 878; NEW-DAG: sd $7, 24([[SP]]) 879; NEW-DAG: sd $6, 16([[SP]]) 880; NEW-DAG: sd $5, 8([[SP]]) 881 882; Initialize variable argument pointer. 883; For O32, the offset is 16 due to the 4 bytes used to store local variables, 884; 4 bytes padding to maintain stack alignment, and the two 4 byte slots for the 885; first fixed argument. 886; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 887; space. 888; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 16 889; O32-DAG: sw [[VA]], 0([[SP]]) 890 891; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 892; N32-DAG: sw [[VA]], 0([[SP]]) 893 894; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 895; N64-DAG: sd [[VA]], 0([[SP]]) 896 897; Store [[VA]] 898; O32-DAG: sw [[VA]], 0([[SP]]) 899 900; ALL: teqi $zero, 1 901 902; Increment [[VA]] 903; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 904; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 905; O32-DAG: sw [[VA2]], 0([[SP]]) 906 907; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 908; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 909; N32-DAG: sw [[VA2]], 0([[SP]]) 910 911; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 912; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 913; N64-DAG: sd [[VA2]], 0([[SP]]) 914 915; Load the first argument from the variable portion. 916; This has used the stack pointer directly rather than the [[VA]] we just set 917; up. 918; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 919; order. 920; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 921 922; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 923; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]]) 924 925; Copy the arg to the global 926; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 927 928; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words) 929 930; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(words)( 931 932; ALL-DAG: sw [[ARG1]], 4([[GV]]) 933 934; ALL: teqi $zero, 2 935 936; Increment [[VA]] again. 937; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 938; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 939; O32-DAG: sw [[VA2]], 0([[SP]]) 940 941; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 942; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 943; N32-DAG: sw [[VA3]], 0([[SP]]) 944 945; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 946; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 947; N64-DAG: sd [[VA3]], 0([[SP]]) 948 949; Load the second argument from the variable portion. 950; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 951 952; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]]) 953; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]]) 954 955; Copy the arg to the global 956; ALL-DAG: sw [[ARG2]], 8([[GV]]) 957 958 %ap = alloca i8*, align 8 959 %ap2 = bitcast i8** %ap to i8* 960 call void @llvm.va_start(i8* %ap2) 961 962 call void asm sideeffect "teqi $$zero, 1", ""() 963 %arg1 = va_arg i8** %ap, i32 964 %e1 = getelementptr [3 x i32], [3 x i32]* @words, i32 0, i32 1 965 store volatile i32 %arg1, i32* %e1, align 4 966 967 call void asm sideeffect "teqi $$zero, 2", ""() 968 %arg2 = va_arg i8** %ap, i32 969 %e2 = getelementptr [3 x i32], [3 x i32]* @words, i32 0, i32 2 970 store volatile i32 %arg2, i32* %e2, align 4 971 972 call void @llvm.va_end(i8* %ap2) 973 974 ret void 975} 976 977define void @fn_i64_dotdotdot_i64(i64 %a, ...) { 978entry: 979; ALL-LABEL: fn_i64_dotdotdot_i64: 980 981; Set up the stack with an 8-byte local area. N32/N64 must also make room for 982; the argument save area (56 bytes). 983; O32: addiu [[SP:\$sp]], $sp, -8 984; N32: addiu [[SP:\$sp]], $sp, -64 985; N64: daddiu [[SP:\$sp]], $sp, -64 986 987; Save variable argument portion on the stack 988; O32-DAG: sw $7, 20([[SP]]) 989; O32-DAG: sw $6, 16([[SP]]) 990 991; NEW-DAG: sd $11, 56([[SP]]) 992; NEW-DAG: sd $10, 48([[SP]]) 993; NEW-DAG: sd $9, 40([[SP]]) 994; NEW-DAG: sd $8, 32([[SP]]) 995; NEW-DAG: sd $7, 24([[SP]]) 996; NEW-DAG: sd $6, 16([[SP]]) 997; NEW-DAG: sd $5, 8([[SP]]) 998 999; Initialize variable argument pointer. 1000; For O32, the offset is 16 due to the 4 bytes used to store local variables, 1001; 4 bytes padding to maintain stack alignment, and the two 4 byte slots for the 1002; first fixed argument. 1003; For N32/N64, it is only 8 since the fixed arguments do not reserve stack 1004; space. 1005; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 16 1006; O32-DAG: sw [[VA]], 0([[SP]]) 1007 1008; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8 1009; N32-DAG: sw [[VA]], 0([[SP]]) 1010 1011; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8 1012; N64-DAG: sd [[VA]], 0([[SP]]) 1013 1014; Store [[VA]] 1015; O32-DAG: sw [[VA]], 0([[SP]]) 1016 1017; ALL: teqi $zero, 1 1018 1019; Increment [[VA]] (and realign pointer for O32) 1020; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) 1021; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 1022; O32-DAG: addiu [[VA_TMP1:\$[0-9]+]], $zero, -8 1023; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] 1024; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 1025; O32-DAG: sw [[VA2]], 0([[SP]]) 1026 1027; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 1028; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 1029; N32-DAG: sw [[VA2]], 0([[SP]]) 1030 1031; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]]) 1032; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8 1033; N64-DAG: sd [[VA2]], 0([[SP]]) 1034 1035; Load the first argument from the variable portion and copy it to the global. 1036; This has used the stack pointer directly rather than the [[VA]] we just set 1037; up. 1038; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte 1039; order. 1040; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 1041; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 1042; O32-DAG: sw [[ARG1]], 8([[GV]]) 1043; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 1044; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 1045; O32-DAG: sw [[VA2]], 0([[SP]]) 1046; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]]) 1047; O32-DAG: sw [[ARG1]], 12([[GV]]) 1048 1049; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords) 1050; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(dwords)( 1051; NEW-DAG: ld [[ARG1:\$[0-9]+]], 0([[VA]]) 1052; NEW-DAG: sd [[ARG1]], 8([[GV]]) 1053 1054; ALL: teqi $zero, 2 1055 1056; Increment [[VA]] again. 1057; FIXME: We're still aligned from the last one but CodeGen doesn't spot that. 1058; O32: lw [[VA:\$[0-9]+]], 0([[SP]]) 1059; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7 1060; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]] 1061; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4 1062; O32-DAG: sw [[VA2]], 0([[SP]]) 1063 1064; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]]) 1065; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8 1066; N32-DAG: sw [[VA3]], 0([[SP]]) 1067 1068; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]]) 1069; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8 1070; N64-DAG: sd [[VA3]], 0([[SP]]) 1071 1072; Load the second argument from the variable portion and copy it to the global. 1073; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 1074; O32-DAG: sw [[ARG2]], 16([[GV]]) 1075; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]]) 1076; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4 1077; O32-DAG: sw [[VA2]], 0([[SP]]) 1078; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]]) 1079; O32-DAG: sw [[ARG2]], 20([[GV]]) 1080 1081; NEW-DAG: ld [[ARG2:\$[0-9]+]], 0([[VA2]]) 1082; NEW-DAG: sd [[ARG2]], 16([[GV]]) 1083 1084 %ap = alloca i8*, align 8 1085 %ap2 = bitcast i8** %ap to i8* 1086 call void @llvm.va_start(i8* %ap2) 1087 1088 call void asm sideeffect "teqi $$zero, 1", ""() 1089 %arg1 = va_arg i8** %ap, i64 1090 %e1 = getelementptr [3 x i64], [3 x i64]* @dwords, i32 0, i32 1 1091 store volatile i64 %arg1, i64* %e1, align 8 1092 1093 call void asm sideeffect "teqi $$zero, 2", ""() 1094 %arg2 = va_arg i8** %ap, i64 1095 %e2 = getelementptr [3 x i64], [3 x i64]* @dwords, i32 0, i32 2 1096 store volatile i64 %arg2, i64* %e2, align 8 1097 1098 call void @llvm.va_end(i8* %ap2) 1099 1100 ret void 1101} 1102 1103declare void @llvm.va_start(i8*) 1104declare void @llvm.va_end(i8*) 1105