1 ; RUN: llc -mtriple=mips-linux -relocation-model=static < %s | FileCheck --check-prefix=ALL --check-prefix=O32 --check-prefix=O32-BE %s
2 ; RUN: llc -mtriple=mipsel-linux -relocation-model=static < %s | FileCheck --check-prefix=ALL --check-prefix=O32 --check-prefix=O32-LE %s
4 ; RUN-TODO: llc -march=mips64 -relocation-model=static -target-abi o32 < %s | FileCheck --check-prefix=ALL --check-prefix=O32 %s
5 ; RUN-TODO: llc -march=mips64el -relocation-model=static -target-abi o32 < %s | FileCheck --check-prefix=ALL --check-prefix=O32 %s
7 ; RUN: llc -mtriple=mips64-linux -relocation-model=static -target-abi n32 < %s | FileCheck --check-prefix=ALL --check-prefix=NEW --check-prefix=N32 --check-prefix=NEW-BE %s
8 ; RUN: llc -mtriple=mips64el-linux -relocation-model=static -target-abi n32 < %s | FileCheck --check-prefix=ALL --check-prefix=NEW --check-prefix=N32 --check-prefix=NEW-LE %s
10 ; RUN: llc -march=mips64 -relocation-model=static -target-abi n64 < %s | FileCheck --check-prefix=ALL --check-prefix=NEW --check-prefix=N64 --check-prefix=NEW-BE %s
11 ; RUN: llc -march=mips64el -relocation-model=static -target-abi n64 < %s | FileCheck --check-prefix=ALL --check-prefix=NEW --check-prefix=N64 --check-prefix=NEW-LE %s
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
17 define void @fn_i16_dotdotdot_i16(i16 %a, ...) {
19 ; ALL-LABEL: fn_i16_dotdotdot_i16:
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
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]])
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]])
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
44 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack
46 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12
47 ; O32-DAG: sw [[VA]], 0([[SP]])
49 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8
50 ; N32-DAG: sw [[VA]], 0([[SP]])
52 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8
53 ; N64-DAG: sd [[VA]], 0([[SP]])
56 ; O32-DAG: sw [[VA]], 0([[SP]])
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]])
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]])
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]])
73 ; Load the first argument from the variable portion.
74 ; This has used the stack pointer directly rather than the [[VA]] we just set
76 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
78 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
80 ; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
81 ; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]])
83 ; Copy the arg to the global
84 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords)
86 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords)
88 ; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(hwords)(
90 ; ALL-DAG: sh [[ARG1]], 2([[GV]])
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]])
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]])
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]])
107 ; Load the second argument from the variable portion.
108 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]])
110 ; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]])
111 ; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]])
113 ; Copy the arg to the global
114 ; ALL-DAG: sh [[ARG2]], 4([[GV]])
116 %ap = alloca i8*, align 8
117 %ap2 = bitcast i8** %ap to i8*
118 call void @llvm.va_start(i8* %ap2)
120 call void asm sideeffect "# ANCHOR1", ""()
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
125 call void asm sideeffect "# ANCHOR2", ""()
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
130 call void @llvm.va_end(i8* %ap2)
135 define void @fn_i16_dotdotdot_i32(i16 %a, ...) {
137 ; ALL-LABEL: fn_i16_dotdotdot_i32:
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
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]])
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]])
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
162 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack
164 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12
165 ; O32-DAG: sw [[VA]], 0([[SP]])
167 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8
168 ; N32-DAG: sw [[VA]], 0([[SP]])
170 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8
171 ; N64-DAG: sd [[VA]], 0([[SP]])
174 ; O32-DAG: sw [[VA]], 0([[SP]])
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]])
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]])
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]])
191 ; Load the first argument from the variable portion.
192 ; This has used the stack pointer directly rather than the [[VA]] we just set
194 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
196 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
198 ; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
199 ; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]])
201 ; Copy the arg to the global
202 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words)
204 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words)
206 ; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(words)(
208 ; ALL-DAG: sw [[ARG1]], 4([[GV]])
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]])
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]])
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]])
225 ; Load the second argument from the variable portion.
226 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]])
228 ; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]])
229 ; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]])
231 ; Copy the arg to the global
232 ; ALL-DAG: sw [[ARG2]], 8([[GV]])
234 %ap = alloca i8*, align 8
235 %ap2 = bitcast i8** %ap to i8*
236 call void @llvm.va_start(i8* %ap2)
238 call void asm sideeffect "# ANCHOR1", ""()
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
243 call void asm sideeffect "# ANCHOR2", ""()
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
248 call void @llvm.va_end(i8* %ap2)
253 define void @fn_i16_dotdotdot_i64(i16 %a, ...) {
255 ; ALL-LABEL: fn_i16_dotdotdot_i64:
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
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]])
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]])
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
280 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack
282 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12
283 ; O32-DAG: sw [[VA]], 0([[SP]])
285 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8
286 ; N32-DAG: sw [[VA]], 0([[SP]])
288 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8
289 ; N64-DAG: sd [[VA]], 0([[SP]])
292 ; O32-DAG: sw [[VA]], 0([[SP]])
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]])
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]])
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]])
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
315 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
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]])
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]])
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]])
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]])
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]])
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]])
358 ; NEW-DAG: ld [[ARG2:\$[0-9]+]], 0([[VA2]])
359 ; NEW-DAG: sd [[ARG2]], 16([[GV]])
361 %ap = alloca i8*, align 8
362 %ap2 = bitcast i8** %ap to i8*
363 call void @llvm.va_start(i8* %ap2)
365 call void asm sideeffect "# ANCHOR1", ""()
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
370 call void asm sideeffect "# ANCHOR2", ""()
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
375 call void @llvm.va_end(i8* %ap2)
380 define void @fn_i32_dotdotdot_i16(i32 %a, ...) {
382 ; ALL-LABEL: fn_i32_dotdotdot_i16:
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
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]])
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]])
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
407 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack
409 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12
410 ; O32-DAG: sw [[VA]], 0([[SP]])
412 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8
413 ; N32-DAG: sw [[VA]], 0([[SP]])
415 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8
416 ; N64-DAG: sd [[VA]], 0([[SP]])
419 ; O32-DAG: sw [[VA]], 0([[SP]])
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]])
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]])
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]])
436 ; Load the first argument from the variable portion.
437 ; This has used the stack pointer directly rather than the [[VA]] we just set
439 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
441 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
443 ; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
444 ; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]])
446 ; Copy the arg to the global
447 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords)
449 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords)
451 ; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(hwords)(
453 ; ALL-DAG: sh [[ARG1]], 2([[GV]])
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]])
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]])
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]])
470 ; Load the second argument from the variable portion.
471 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]])
473 ; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]])
474 ; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]])
476 ; Copy the arg to the global
477 ; ALL-DAG: sh [[ARG2]], 4([[GV]])
479 %ap = alloca i8*, align 8
480 %ap2 = bitcast i8** %ap to i8*
481 call void @llvm.va_start(i8* %ap2)
483 call void asm sideeffect "# ANCHOR1", ""()
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
488 call void asm sideeffect "# ANCHOR2", ""()
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
493 call void @llvm.va_end(i8* %ap2)
498 define void @fn_i32_dotdotdot_i32(i32 %a, ...) {
500 ; ALL-LABEL: fn_i32_dotdotdot_i32:
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
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]])
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]])
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
525 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack
527 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12
528 ; O32-DAG: sw [[VA]], 0([[SP]])
530 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8
531 ; N32-DAG: sw [[VA]], 0([[SP]])
533 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8
534 ; N64-DAG: sd [[VA]], 0([[SP]])
537 ; O32-DAG: sw [[VA]], 0([[SP]])
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]])
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]])
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]])
554 ; Load the first argument from the variable portion.
555 ; This has used the stack pointer directly rather than the [[VA]] we just set
557 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
559 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
561 ; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
562 ; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]])
564 ; Copy the arg to the global
565 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words)
567 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words)
569 ; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(words)(
571 ; ALL-DAG: sw [[ARG1]], 4([[GV]])
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]])
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]])
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]])
588 ; Load the second argument from the variable portion.
589 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]])
591 ; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]])
592 ; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]])
594 ; Copy the arg to the global
595 ; ALL-DAG: sw [[ARG2]], 8([[GV]])
597 %ap = alloca i8*, align 8
598 %ap2 = bitcast i8** %ap to i8*
599 call void @llvm.va_start(i8* %ap2)
601 call void asm sideeffect "# ANCHOR1", ""()
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
606 call void asm sideeffect "# ANCHOR2", ""()
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
611 call void @llvm.va_end(i8* %ap2)
616 define void @fn_i32_dotdotdot_i64(i32 %a, ...) {
618 ; ALL-LABEL: fn_i32_dotdotdot_i64:
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
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]])
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]])
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
643 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack
645 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12
646 ; O32-DAG: sw [[VA]], 0([[SP]])
648 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8
649 ; N32-DAG: sw [[VA]], 0([[SP]])
651 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8
652 ; N64-DAG: sd [[VA]], 0([[SP]])
655 ; O32-DAG: sw [[VA]], 0([[SP]])
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]])
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]])
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]])
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
678 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
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]])
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]])
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]])
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]])
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]])
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]])
721 ; NEW-DAG: ld [[ARG2:\$[0-9]+]], 0([[VA2]])
722 ; NEW-DAG: sd [[ARG2]], 16([[GV]])
724 %ap = alloca i8*, align 8
725 %ap2 = bitcast i8** %ap to i8*
726 call void @llvm.va_start(i8* %ap2)
728 call void asm sideeffect "# ANCHOR1", ""()
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
733 call void asm sideeffect "# ANCHOR2", ""()
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
738 call void @llvm.va_end(i8* %ap2)
743 define void @fn_i64_dotdotdot_i16(i64 %a, ...) {
745 ; ALL-LABEL: fn_i64_dotdotdot_i16:
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
753 ; Save variable argument portion on the stack
754 ; O32-DAG: sw $7, 20([[SP]])
755 ; O32-DAG: sw $6, 16([[SP]])
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]])
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
771 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 16
772 ; O32-DAG: sw [[VA]], 0([[SP]])
774 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8
775 ; N32-DAG: sw [[VA]], 0([[SP]])
777 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8
778 ; N64-DAG: sd [[VA]], 0([[SP]])
781 ; O32-DAG: sw [[VA]], 0([[SP]])
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]])
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]])
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]])
798 ; Load the first argument from the variable portion.
799 ; This has used the stack pointer directly rather than the [[VA]] we just set
801 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
803 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
805 ; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
806 ; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]])
808 ; Copy the arg to the global
809 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords)
811 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords)
813 ; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(hwords)(
815 ; ALL-DAG: sh [[ARG1]], 2([[GV]])
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]])
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]])
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]])
832 ; Load the second argument from the variable portion.
833 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]])
835 ; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]])
836 ; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]])
838 ; Copy the arg to the global
839 ; ALL-DAG: sh [[ARG2]], 4([[GV]])
841 %ap = alloca i8*, align 8
842 %ap2 = bitcast i8** %ap to i8*
843 call void @llvm.va_start(i8* %ap2)
845 call void asm sideeffect "# ANCHOR1", ""()
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
850 call void asm sideeffect "# ANCHOR2", ""()
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
855 call void @llvm.va_end(i8* %ap2)
860 define void @fn_i64_dotdotdot_i32(i64 %a, ...) {
862 ; ALL-LABEL: fn_i64_dotdotdot_i32:
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
870 ; Save variable argument portion on the stack
871 ; O32-DAG: sw $7, 20([[SP]])
872 ; O32-DAG: sw $6, 16([[SP]])
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]])
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
888 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 16
889 ; O32-DAG: sw [[VA]], 0([[SP]])
891 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8
892 ; N32-DAG: sw [[VA]], 0([[SP]])
894 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8
895 ; N64-DAG: sd [[VA]], 0([[SP]])
898 ; O32-DAG: sw [[VA]], 0([[SP]])
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]])
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]])
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]])
915 ; Load the first argument from the variable portion.
916 ; This has used the stack pointer directly rather than the [[VA]] we just set
918 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
920 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
922 ; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
923 ; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]])
925 ; Copy the arg to the global
926 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words)
928 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words)
930 ; N64-DAG: ld [[GV:\$[0-9]+]], %got_disp(words)(
932 ; ALL-DAG: sw [[ARG1]], 4([[GV]])
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]])
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]])
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]])
949 ; Load the second argument from the variable portion.
950 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]])
952 ; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]])
953 ; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]])
955 ; Copy the arg to the global
956 ; ALL-DAG: sw [[ARG2]], 8([[GV]])
958 %ap = alloca i8*, align 8
959 %ap2 = bitcast i8** %ap to i8*
960 call void @llvm.va_start(i8* %ap2)
962 call void asm sideeffect "# ANCHOR1", ""()
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
967 call void asm sideeffect "# ANCHOR2", ""()
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
972 call void @llvm.va_end(i8* %ap2)
977 define void @fn_i64_dotdotdot_i64(i64 %a, ...) {
979 ; ALL-LABEL: fn_i64_dotdotdot_i64:
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
987 ; Save variable argument portion on the stack
988 ; O32-DAG: sw $7, 20([[SP]])
989 ; O32-DAG: sw $6, 16([[SP]])
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]])
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
1005 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 16
1006 ; O32-DAG: sw [[VA]], 0([[SP]])
1008 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8
1009 ; N32-DAG: sw [[VA]], 0([[SP]])
1011 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8
1012 ; N64-DAG: sd [[VA]], 0([[SP]])
1015 ; O32-DAG: sw [[VA]], 0([[SP]])
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]])
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]])
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]])
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
1038 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
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]])
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]])
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]])
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]])
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]])
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]])
1081 ; NEW-DAG: ld [[ARG2:\$[0-9]+]], 0([[VA2]])
1082 ; NEW-DAG: sd [[ARG2]], 16([[GV]])
1084 %ap = alloca i8*, align 8
1085 %ap2 = bitcast i8** %ap to i8*
1086 call void @llvm.va_start(i8* %ap2)
1088 call void asm sideeffect "# ANCHOR1", ""()
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
1093 call void asm sideeffect "# ANCHOR2", ""()
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
1098 call void @llvm.va_end(i8* %ap2)
1103 declare void @llvm.va_start(i8*)
1104 declare void @llvm.va_end(i8*)