1 ; RUN: llc -mtriple=mips-linux -relocation-model=static < %s \
2 ; RUN: | FileCheck --check-prefixes=ALL,O32 %s
3 ; RUN: llc -mtriple=mipsel-linux -relocation-model=static < %s \
4 ; RUN: | FileCheck --check-prefixes=ALL,O32 %s
6 ; RUN-TODO: llc -mtriple=mips64 -relocation-model=static -target-abi o32 < %s \
7 ; RUN-TODO: | FileCheck --check-prefixes=ALL,O32 %s
8 ; RUN-TODO: llc -mtriple=mips64el -relocation-model=static -target-abi o32 < %s \
9 ; RUN-TODO: | FileCheck --check-prefixes=ALL,O32 %s
11 ; RUN: llc -mtriple=mips64-linux -relocation-model=static -target-abi n32 < %s \
12 ; RUN: | FileCheck --check-prefixes=ALL,NEW,N32,NEW-BE %s
13 ; RUN: llc -mtriple=mips64el-linux -relocation-model=static -target-abi n32 < %s \
14 ; RUN: | FileCheck --check-prefixes=ALL,NEW,N32,NEW-LE %s
16 ; RUN: llc -mtriple=mips64 -relocation-model=static -target-abi n64 < %s \
17 ; RUN: | FileCheck --check-prefixes=ALL,NEW,N64,NEW-BE %s
18 ; RUN: llc -mtriple=mips64el -relocation-model=static -target-abi n64 < %s \
19 ; RUN: | FileCheck --check-prefixes=ALL,NEW,N64,NEW-LE %s
21 @hwords = global [3 x i16] zeroinitializer, align 1
22 @words = global [3 x i32] zeroinitializer, align 1
23 @dwords = global [3 x i64] zeroinitializer, align 1
25 define void @fn_i16_dotdotdot_i16(i16 %a, ...) {
27 ; ALL-LABEL: fn_i16_dotdotdot_i16:
29 ; Set up the stack with an 8-byte local area. N32/N64 must also make room for
30 ; the argument save area (56 bytes).
31 ; O32: addiu [[SP:\$sp]], $sp, -8
32 ; N32: addiu [[SP:\$sp]], $sp, -64
33 ; N64: daddiu [[SP:\$sp]], $sp, -64
35 ; Save variable argument portion on the stack
36 ; O32-DAG: sw $7, 20([[SP]])
37 ; O32-DAG: sw $6, 16([[SP]])
38 ; O32-DAG: sw $5, 12([[SP]])
40 ; NEW-DAG: sd $11, 56([[SP]])
41 ; NEW-DAG: sd $10, 48([[SP]])
42 ; NEW-DAG: sd $9, 40([[SP]])
43 ; NEW-DAG: sd $8, 32([[SP]])
44 ; NEW-DAG: sd $7, 24([[SP]])
45 ; NEW-DAG: sd $6, 16([[SP]])
46 ; NEW-DAG: sd $5, 8([[SP]])
48 ; Initialize variable argument pointer.
49 ; For O32, the offset is 12 due to the 4 bytes used to store local variables,
50 ; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first
52 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack
54 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12
55 ; O32-DAG: sw [[VA]], 0([[SP]])
57 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8
58 ; N32-DAG: sw [[VA]], 0([[SP]])
60 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8
61 ; N64-DAG: sd [[VA]], 0([[SP]])
66 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]])
67 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4
68 ; O32-DAG: sw [[VA2]], 0([[SP]])
70 ; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]])
71 ; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8
72 ; N32-DAG: sw [[VA2]], 0([[SP]])
74 ; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]])
75 ; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8
76 ; N64-DAG: sd [[VA2]], 0([[SP]])
78 ; Load the first argument from the variable portion.
79 ; This has used the stack pointer directly rather than the [[VA]] we just set
81 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
83 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
85 ; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
86 ; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]])
88 ; Copy the arg to the global
89 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords)
91 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords)
93 ; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords)
95 ; ALL-DAG: sh [[ARG1]], 2([[GV]])
99 ; Increment [[VA]] again.
100 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]])
101 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4
102 ; O32-DAG: sw [[VA2]], 0([[SP]])
104 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]])
105 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8
106 ; N32-DAG: sw [[VA3]], 0([[SP]])
108 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]])
109 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8
110 ; N64-DAG: sd [[VA3]], 0([[SP]])
112 ; Load the second argument from the variable portion.
113 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]])
115 ; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]])
116 ; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]])
118 ; Copy the arg to the global
119 ; ALL-DAG: sh [[ARG2]], 4([[GV]])
121 %ap = alloca ptr, align 8
122 call void @llvm.va_start(ptr %ap)
124 call void asm sideeffect "teqi $$zero, 1", ""()
125 %arg1 = va_arg ptr %ap, i16
126 %e1 = getelementptr [3 x i16], ptr @hwords, i32 0, i32 1
127 store volatile i16 %arg1, ptr %e1, align 2
129 call void asm sideeffect "teqi $$zero, 2", ""()
130 %arg2 = va_arg ptr %ap, i16
131 %e2 = getelementptr [3 x i16], ptr @hwords, i32 0, i32 2
132 store volatile i16 %arg2, ptr %e2, align 2
134 call void @llvm.va_end(ptr %ap)
139 define void @fn_i16_dotdotdot_i32(i16 %a, ...) {
141 ; ALL-LABEL: fn_i16_dotdotdot_i32:
143 ; Set up the stack with an 8-byte local area. N32/N64 must also make room for
144 ; the argument save area (56 bytes).
145 ; O32: addiu [[SP:\$sp]], $sp, -8
146 ; N32: addiu [[SP:\$sp]], $sp, -64
147 ; N64: daddiu [[SP:\$sp]], $sp, -64
149 ; Save variable argument portion on the stack
150 ; O32-DAG: sw $7, 20([[SP]])
151 ; O32-DAG: sw $6, 16([[SP]])
152 ; O32-DAG: sw $5, 12([[SP]])
154 ; NEW-DAG: sd $11, 56([[SP]])
155 ; NEW-DAG: sd $10, 48([[SP]])
156 ; NEW-DAG: sd $9, 40([[SP]])
157 ; NEW-DAG: sd $8, 32([[SP]])
158 ; NEW-DAG: sd $7, 24([[SP]])
159 ; NEW-DAG: sd $6, 16([[SP]])
160 ; NEW-DAG: sd $5, 8([[SP]])
162 ; Initialize variable argument pointer.
163 ; For O32, the offset is 12 due to the 4 bytes used to store local variables,
164 ; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first
166 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack
168 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12
169 ; O32-DAG: sw [[VA]], 0([[SP]])
171 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8
172 ; N32-DAG: sw [[VA]], 0([[SP]])
174 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8
175 ; N64-DAG: sd [[VA]], 0([[SP]])
180 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]])
181 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4
182 ; O32-DAG: sw [[VA2]], 0([[SP]])
184 ; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]])
185 ; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8
186 ; N32-DAG: sw [[VA2]], 0([[SP]])
188 ; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]])
189 ; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8
190 ; N64-DAG: sd [[VA2]], 0([[SP]])
192 ; Load the first argument from the variable portion.
193 ; This has used the stack pointer directly rather than the [[VA]] we just set
195 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
197 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
199 ; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
200 ; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]])
202 ; Copy the arg to the global
203 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words)
205 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words)
207 ; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words)
209 ; ALL-DAG: sw [[ARG1]], 4([[GV]])
213 ; Increment [[VA]] again.
214 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]])
215 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4
216 ; O32-DAG: sw [[VA2]], 0([[SP]])
218 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]])
219 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8
220 ; N32-DAG: sw [[VA3]], 0([[SP]])
222 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]])
223 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8
224 ; N64-DAG: sd [[VA3]], 0([[SP]])
226 ; Load the second argument from the variable portion.
227 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]])
229 ; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]])
230 ; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]])
232 ; Copy the arg to the global
233 ; ALL-DAG: sw [[ARG2]], 8([[GV]])
235 %ap = alloca ptr, align 8
236 call void @llvm.va_start(ptr %ap)
238 call void asm sideeffect "teqi $$zero, 1", ""()
239 %arg1 = va_arg ptr %ap, i32
240 %e1 = getelementptr [3 x i32], ptr @words, i32 0, i32 1
241 store volatile i32 %arg1, ptr %e1, align 4
243 call void asm sideeffect "teqi $$zero, 2", ""()
244 %arg2 = va_arg ptr %ap, i32
245 %e2 = getelementptr [3 x i32], ptr @words, i32 0, i32 2
246 store volatile i32 %arg2, ptr %e2, align 4
248 call void @llvm.va_end(ptr %ap)
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]])
293 ; Increment [[VA]] (and realign pointer for O32)
294 ; O32: lw [[VA:\$[0-9]+]], 0([[SP]])
295 ; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7
296 ; O32-DAG: addiu [[VA_TMP1:\$[0-9]+]], $zero, -8
297 ; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]]
298 ; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4
299 ; O32-DAG: sw [[VA2]], 0([[SP]])
301 ; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]])
302 ; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8
303 ; N32-DAG: sw [[VA2]], 0([[SP]])
305 ; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]])
306 ; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8
307 ; N64-DAG: sd [[VA2]], 0([[SP]])
309 ; Load the first argument from the variable portion and copy it to the global.
310 ; This has used the stack pointer directly rather than the [[VA]] we just set
312 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
314 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords)
315 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA_TMP2]])
316 ; O32-DAG: sw [[ARG1]], 8([[GV]])
317 ; O32-DAG: addiu [[VA3:\$[0-9]+]], [[VA_TMP2]], 8
318 ; O32-DAG: sw [[VA3]], 0([[SP]])
319 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA_TMP2]])
320 ; O32-DAG: sw [[ARG1]], 12([[GV]])
322 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords)
323 ; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords)
324 ; NEW-DAG: ld [[ARG1:\$[0-9]+]], 0([[VA]])
325 ; NEW-DAG: sd [[ARG1]], 8([[GV]])
329 ; Increment [[VA]] again.
330 ; FIXME: We're still aligned from the last one but CodeGen doesn't spot that.
331 ; O32: lw [[VA:\$[0-9]+]], 0([[SP]])
332 ; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7
333 ; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]]
334 ; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4
335 ; O32-DAG: sw [[VA2]], 0([[SP]])
337 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]])
338 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8
339 ; N32-DAG: sw [[VA3]], 0([[SP]])
341 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]])
342 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8
343 ; N64-DAG: sd [[VA3]], 0([[SP]])
345 ; Load the second argument from the variable portion and copy it to the global.
346 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]])
347 ; O32-DAG: sw [[ARG2]], 16([[GV]])
348 ; O32-DAG: addiu [[VA3:\$[0-9]+]], [[VA_TMP2]], 8
349 ; O32-DAG: sw [[VA3]], 0([[SP]])
350 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA_TMP2]])
351 ; O32-DAG: sw [[ARG2]], 20([[GV]])
353 ; NEW-DAG: ld [[ARG2:\$[0-9]+]], 0([[VA2]])
354 ; NEW-DAG: sd [[ARG2]], 16([[GV]])
356 %ap = alloca ptr, align 8
357 call void @llvm.va_start(ptr %ap)
359 call void asm sideeffect "teqi $$zero, 1", ""()
360 %arg1 = va_arg ptr %ap, i64
361 %e1 = getelementptr [3 x i64], ptr @dwords, i32 0, i32 1
362 store volatile i64 %arg1, ptr %e1, align 8
364 call void asm sideeffect "teqi $$zero, 2", ""()
365 %arg2 = va_arg ptr %ap, i64
366 %e2 = getelementptr [3 x i64], ptr @dwords, i32 0, i32 2
367 store volatile i64 %arg2, ptr %e2, align 8
369 call void @llvm.va_end(ptr %ap)
374 define void @fn_i32_dotdotdot_i16(i32 %a, ...) {
376 ; ALL-LABEL: fn_i32_dotdotdot_i16:
378 ; Set up the stack with an 8-byte local area. N32/N64 must also make room for
379 ; the argument save area (56 bytes).
380 ; O32: addiu [[SP:\$sp]], $sp, -8
381 ; N32: addiu [[SP:\$sp]], $sp, -64
382 ; N64: daddiu [[SP:\$sp]], $sp, -64
384 ; Save variable argument portion on the stack
385 ; O32-DAG: sw $7, 20([[SP]])
386 ; O32-DAG: sw $6, 16([[SP]])
387 ; O32-DAG: sw $5, 12([[SP]])
389 ; NEW-DAG: sd $11, 56([[SP]])
390 ; NEW-DAG: sd $10, 48([[SP]])
391 ; NEW-DAG: sd $9, 40([[SP]])
392 ; NEW-DAG: sd $8, 32([[SP]])
393 ; NEW-DAG: sd $7, 24([[SP]])
394 ; NEW-DAG: sd $6, 16([[SP]])
395 ; NEW-DAG: sd $5, 8([[SP]])
397 ; Initialize variable argument pointer.
398 ; For O32, the offset is 12 due to the 4 bytes used to store local variables,
399 ; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first
401 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack
403 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12
404 ; O32-DAG: sw [[VA]], 0([[SP]])
406 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8
407 ; N32-DAG: sw [[VA]], 0([[SP]])
409 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8
410 ; N64-DAG: sd [[VA]], 0([[SP]])
415 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]])
416 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4
417 ; O32-DAG: sw [[VA2]], 0([[SP]])
419 ; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]])
420 ; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8
421 ; N32-DAG: sw [[VA2]], 0([[SP]])
423 ; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]])
424 ; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8
425 ; N64-DAG: sd [[VA2]], 0([[SP]])
427 ; Load the first argument from the variable portion.
428 ; This has used the stack pointer directly rather than the [[VA]] we just set
430 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
432 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
434 ; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
435 ; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]])
437 ; Copy the arg to the global
438 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords)
440 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords)
442 ; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords)
444 ; ALL-DAG: sh [[ARG1]], 2([[GV]])
448 ; Increment [[VA]] again.
449 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]])
450 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4
451 ; O32-DAG: sw [[VA2]], 0([[SP]])
453 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]])
454 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8
455 ; N32-DAG: sw [[VA3]], 0([[SP]])
457 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]])
458 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8
459 ; N64-DAG: sd [[VA3]], 0([[SP]])
461 ; Load the second argument from the variable portion.
462 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]])
464 ; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]])
465 ; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]])
467 ; Copy the arg to the global
468 ; ALL-DAG: sh [[ARG2]], 4([[GV]])
470 %ap = alloca ptr, align 8
471 call void @llvm.va_start(ptr %ap)
473 call void asm sideeffect "teqi $$zero, 1", ""()
474 %arg1 = va_arg ptr %ap, i16
475 %e1 = getelementptr [3 x i16], ptr @hwords, i32 0, i32 1
476 store volatile i16 %arg1, ptr %e1, align 2
478 call void asm sideeffect "teqi $$zero, 2", ""()
479 %arg2 = va_arg ptr %ap, i16
480 %e2 = getelementptr [3 x i16], ptr @hwords, i32 0, i32 2
481 store volatile i16 %arg2, ptr %e2, align 2
483 call void @llvm.va_end(ptr %ap)
488 define void @fn_i32_dotdotdot_i32(i32 %a, ...) {
490 ; ALL-LABEL: fn_i32_dotdotdot_i32:
492 ; Set up the stack with an 8-byte local area. N32/N64 must also make room for
493 ; the argument save area (56 bytes).
494 ; O32: addiu [[SP:\$sp]], $sp, -8
495 ; N32: addiu [[SP:\$sp]], $sp, -64
496 ; N64: daddiu [[SP:\$sp]], $sp, -64
498 ; Save variable argument portion on the stack
499 ; O32-DAG: sw $7, 20([[SP]])
500 ; O32-DAG: sw $6, 16([[SP]])
501 ; O32-DAG: sw $5, 12([[SP]])
503 ; NEW-DAG: sd $11, 56([[SP]])
504 ; NEW-DAG: sd $10, 48([[SP]])
505 ; NEW-DAG: sd $9, 40([[SP]])
506 ; NEW-DAG: sd $8, 32([[SP]])
507 ; NEW-DAG: sd $7, 24([[SP]])
508 ; NEW-DAG: sd $6, 16([[SP]])
509 ; NEW-DAG: sd $5, 8([[SP]])
511 ; Initialize variable argument pointer.
512 ; For O32, the offset is 12 due to the 4 bytes used to store local variables,
513 ; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first
515 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack
517 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12
518 ; O32-DAG: sw [[VA]], 0([[SP]])
520 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8
521 ; N32-DAG: sw [[VA]], 0([[SP]])
523 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8
524 ; N64-DAG: sd [[VA]], 0([[SP]])
529 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]])
530 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4
531 ; O32-DAG: sw [[VA2]], 0([[SP]])
533 ; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]])
534 ; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8
535 ; N32-DAG: sw [[VA2]], 0([[SP]])
537 ; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]])
538 ; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8
539 ; N64-DAG: sd [[VA2]], 0([[SP]])
541 ; Load the first argument from the variable portion.
542 ; This has used the stack pointer directly rather than the [[VA]] we just set
544 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
546 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
548 ; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
549 ; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]])
551 ; Copy the arg to the global
552 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words)
554 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words)
556 ; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words)
558 ; ALL-DAG: sw [[ARG1]], 4([[GV]])
562 ; Increment [[VA]] again.
563 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]])
564 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4
565 ; O32-DAG: sw [[VA2]], 0([[SP]])
567 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]])
568 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8
569 ; N32-DAG: sw [[VA3]], 0([[SP]])
571 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]])
572 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8
573 ; N64-DAG: sd [[VA3]], 0([[SP]])
575 ; Load the second argument from the variable portion.
576 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]])
578 ; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]])
579 ; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]])
581 ; Copy the arg to the global
582 ; ALL-DAG: sw [[ARG2]], 8([[GV]])
584 %ap = alloca ptr, align 8
585 call void @llvm.va_start(ptr %ap)
587 call void asm sideeffect "teqi $$zero, 1", ""()
588 %arg1 = va_arg ptr %ap, i32
589 %e1 = getelementptr [3 x i32], ptr @words, i32 0, i32 1
590 store volatile i32 %arg1, ptr %e1, align 4
592 call void asm sideeffect "teqi $$zero, 2", ""()
593 %arg2 = va_arg ptr %ap, i32
594 %e2 = getelementptr [3 x i32], ptr @words, i32 0, i32 2
595 store volatile i32 %arg2, ptr %e2, align 4
597 call void @llvm.va_end(ptr %ap)
602 define void @fn_i32_dotdotdot_i64(i32 %a, ...) {
604 ; ALL-LABEL: fn_i32_dotdotdot_i64:
606 ; Set up the stack with an 8-byte local area. N32/N64 must also make room for
607 ; the argument save area (56 bytes).
608 ; O32: addiu [[SP:\$sp]], $sp, -8
609 ; N32: addiu [[SP:\$sp]], $sp, -64
610 ; N64: daddiu [[SP:\$sp]], $sp, -64
612 ; Save variable argument portion on the stack
613 ; O32-DAG: sw $7, 20([[SP]])
614 ; O32-DAG: sw $6, 16([[SP]])
615 ; O32-DAG: sw $5, 12([[SP]])
617 ; NEW-DAG: sd $11, 56([[SP]])
618 ; NEW-DAG: sd $10, 48([[SP]])
619 ; NEW-DAG: sd $9, 40([[SP]])
620 ; NEW-DAG: sd $8, 32([[SP]])
621 ; NEW-DAG: sd $7, 24([[SP]])
622 ; NEW-DAG: sd $6, 16([[SP]])
623 ; NEW-DAG: sd $5, 8([[SP]])
625 ; Initialize variable argument pointer.
626 ; For O32, the offset is 12 due to the 4 bytes used to store local variables,
627 ; 4 bytes padding to maintain stack alignment, and the 4 byte slot for the first
629 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack
631 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 12
632 ; O32-DAG: sw [[VA]], 0([[SP]])
634 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8
635 ; N32-DAG: sw [[VA]], 0([[SP]])
637 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8
638 ; N64-DAG: sd [[VA]], 0([[SP]])
642 ; Increment [[VA]] (and realign pointer for O32)
643 ; O32: lw [[VA:\$[0-9]+]], 0([[SP]])
644 ; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7
645 ; O32-DAG: addiu [[VA_TMP1:\$[0-9]+]], $zero, -8
646 ; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]]
647 ; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4
648 ; O32-DAG: sw [[VA2]], 0([[SP]])
650 ; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]])
651 ; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8
652 ; N32-DAG: sw [[VA2]], 0([[SP]])
654 ; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]])
655 ; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8
656 ; N64-DAG: sd [[VA2]], 0([[SP]])
658 ; Load the first argument from the variable portion and copy it to the global.
659 ; This has used the stack pointer directly rather than the [[VA]] we just set
661 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
663 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords)
664 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA_TMP2]])
665 ; O32-DAG: sw [[ARG1]], 8([[GV]])
666 ; O32-DAG: addiu [[VA3:\$[0-9]+]], [[VA_TMP2]], 8
667 ; O32-DAG: sw [[VA3]], 0([[SP]])
668 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA_TMP2]])
669 ; O32-DAG: sw [[ARG1]], 12([[GV]])
671 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords)
672 ; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords)
673 ; NEW-DAG: ld [[ARG1:\$[0-9]+]], 0([[VA]])
674 ; NEW-DAG: sd [[ARG1]], 8([[GV]])
678 ; Increment [[VA]] again.
679 ; FIXME: We're still aligned from the last one but CodeGen doesn't spot that.
680 ; O32: lw [[VA:\$[0-9]+]], 0([[SP]])
681 ; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7
682 ; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]]
683 ; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4
684 ; O32-DAG: sw [[VA2]], 0([[SP]])
686 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]])
687 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8
688 ; N32-DAG: sw [[VA3]], 0([[SP]])
690 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]])
691 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8
692 ; N64-DAG: sd [[VA3]], 0([[SP]])
694 ; Load the second argument from the variable portion and copy it to the global.
695 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]])
696 ; O32-DAG: sw [[ARG2]], 16([[GV]])
697 ; O32-DAG: addiu [[VA3:\$[0-9]+]], [[VA_TMP2]], 8
698 ; O32-DAG: sw [[VA3]], 0([[SP]])
699 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA_TMP2]])
700 ; O32-DAG: sw [[ARG2]], 20([[GV]])
702 ; NEW-DAG: ld [[ARG2:\$[0-9]+]], 0([[VA2]])
703 ; NEW-DAG: sd [[ARG2]], 16([[GV]])
705 %ap = alloca ptr, align 8
706 call void @llvm.va_start(ptr %ap)
708 call void asm sideeffect "teqi $$zero, 1", ""()
709 %arg1 = va_arg ptr %ap, i64
710 %e1 = getelementptr [3 x i64], ptr @dwords, i32 0, i32 1
711 store volatile i64 %arg1, ptr %e1, align 8
713 call void asm sideeffect "teqi $$zero, 2", ""()
714 %arg2 = va_arg ptr %ap, i64
715 %e2 = getelementptr [3 x i64], ptr @dwords, i32 0, i32 2
716 store volatile i64 %arg2, ptr %e2, align 8
718 call void @llvm.va_end(ptr %ap)
723 define void @fn_i64_dotdotdot_i16(i64 %a, ...) {
725 ; ALL-LABEL: fn_i64_dotdotdot_i16:
727 ; Set up the stack with an 8-byte local area. N32/N64 must also make room for
728 ; the argument save area (56 bytes).
729 ; O32: addiu [[SP:\$sp]], $sp, -8
730 ; N32: addiu [[SP:\$sp]], $sp, -64
731 ; N64: daddiu [[SP:\$sp]], $sp, -64
733 ; Save variable argument portion on the stack
734 ; O32-DAG: sw $7, 20([[SP]])
735 ; O32-DAG: sw $6, 16([[SP]])
737 ; NEW-DAG: sd $11, 56([[SP]])
738 ; NEW-DAG: sd $10, 48([[SP]])
739 ; NEW-DAG: sd $9, 40([[SP]])
740 ; NEW-DAG: sd $8, 32([[SP]])
741 ; NEW-DAG: sd $7, 24([[SP]])
742 ; NEW-DAG: sd $6, 16([[SP]])
743 ; NEW-DAG: sd $5, 8([[SP]])
745 ; Initialize variable argument pointer.
746 ; For O32, the offset is 16 due to the 4 bytes used to store local variables,
747 ; 4 bytes padding to maintain stack alignment, and the two 4 byte slots for the
748 ; first fixed argument.
749 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack
751 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 16
752 ; O32-DAG: sw [[VA]], 0([[SP]])
754 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8
755 ; N32-DAG: sw [[VA]], 0([[SP]])
757 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8
758 ; N64-DAG: sd [[VA]], 0([[SP]])
763 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]])
764 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4
765 ; O32-DAG: sw [[VA2]], 0([[SP]])
767 ; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]])
768 ; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8
769 ; N32-DAG: sw [[VA2]], 0([[SP]])
771 ; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]])
772 ; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8
773 ; N64-DAG: sd [[VA2]], 0([[SP]])
775 ; Load the first argument from the variable portion.
776 ; This has used the stack pointer directly rather than the [[VA]] we just set
778 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
780 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
782 ; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
783 ; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]])
785 ; Copy the arg to the global
786 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords)
788 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords)
790 ; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords)
792 ; ALL-DAG: sh [[ARG1]], 2([[GV]])
796 ; Increment [[VA]] again.
797 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]])
798 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4
799 ; O32-DAG: sw [[VA2]], 0([[SP]])
801 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]])
802 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8
803 ; N32-DAG: sw [[VA3]], 0([[SP]])
805 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]])
806 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8
807 ; N64-DAG: sd [[VA3]], 0([[SP]])
809 ; Load the second argument from the variable portion.
810 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]])
812 ; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]])
813 ; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]])
815 ; Copy the arg to the global
816 ; ALL-DAG: sh [[ARG2]], 4([[GV]])
818 %ap = alloca ptr, align 8
819 call void @llvm.va_start(ptr %ap)
821 call void asm sideeffect "teqi $$zero, 1", ""()
822 %arg1 = va_arg ptr %ap, i16
823 %e1 = getelementptr [3 x i16], ptr @hwords, i32 0, i32 1
824 store volatile i16 %arg1, ptr %e1, align 2
826 call void asm sideeffect "teqi $$zero, 2", ""()
827 %arg2 = va_arg ptr %ap, i16
828 %e2 = getelementptr [3 x i16], ptr @hwords, i32 0, i32 2
829 store volatile i16 %arg2, ptr %e2, align 2
831 call void @llvm.va_end(ptr %ap)
836 define void @fn_i64_dotdotdot_i32(i64 %a, ...) {
838 ; ALL-LABEL: fn_i64_dotdotdot_i32:
840 ; Set up the stack with an 8-byte local area. N32/N64 must also make room for
841 ; the argument save area (56 bytes).
842 ; O32: addiu [[SP:\$sp]], $sp, -8
843 ; N32: addiu [[SP:\$sp]], $sp, -64
844 ; N64: daddiu [[SP:\$sp]], $sp, -64
846 ; Save variable argument portion on the stack
847 ; O32-DAG: sw $7, 20([[SP]])
848 ; O32-DAG: sw $6, 16([[SP]])
850 ; NEW-DAG: sd $11, 56([[SP]])
851 ; NEW-DAG: sd $10, 48([[SP]])
852 ; NEW-DAG: sd $9, 40([[SP]])
853 ; NEW-DAG: sd $8, 32([[SP]])
854 ; NEW-DAG: sd $7, 24([[SP]])
855 ; NEW-DAG: sd $6, 16([[SP]])
856 ; NEW-DAG: sd $5, 8([[SP]])
858 ; Initialize variable argument pointer.
859 ; For O32, the offset is 16 due to the 4 bytes used to store local variables,
860 ; 4 bytes padding to maintain stack alignment, and the two 4 byte slots for the
861 ; first fixed argument.
862 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack
864 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 16
865 ; O32-DAG: sw [[VA]], 0([[SP]])
867 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8
868 ; N32-DAG: sw [[VA]], 0([[SP]])
870 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8
871 ; N64-DAG: sd [[VA]], 0([[SP]])
876 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]])
877 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4
878 ; O32-DAG: sw [[VA2]], 0([[SP]])
880 ; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]])
881 ; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8
882 ; N32-DAG: sw [[VA2]], 0([[SP]])
884 ; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]])
885 ; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8
886 ; N64-DAG: sd [[VA2]], 0([[SP]])
888 ; Load the first argument from the variable portion.
889 ; This has used the stack pointer directly rather than the [[VA]] we just set
891 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
893 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
895 ; NEW-LE-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
896 ; NEW-BE-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA]])
898 ; Copy the arg to the global
899 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words)
901 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words)
903 ; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words)
905 ; ALL-DAG: sw [[ARG1]], 4([[GV]])
909 ; Increment [[VA]] again.
910 ; O32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]])
911 ; O32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 4
912 ; O32-DAG: sw [[VA2]], 0([[SP]])
914 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]])
915 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8
916 ; N32-DAG: sw [[VA3]], 0([[SP]])
918 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]])
919 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8
920 ; N64-DAG: sd [[VA3]], 0([[SP]])
922 ; Load the second argument from the variable portion.
923 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]])
925 ; NEW-LE-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA2]])
926 ; NEW-BE-DAG: lw [[ARG2:\$[0-9]+]], 4([[VA2]])
928 ; Copy the arg to the global
929 ; ALL-DAG: sw [[ARG2]], 8([[GV]])
931 %ap = alloca ptr, align 8
932 call void @llvm.va_start(ptr %ap)
934 call void asm sideeffect "teqi $$zero, 1", ""()
935 %arg1 = va_arg ptr %ap, i32
936 %e1 = getelementptr [3 x i32], ptr @words, i32 0, i32 1
937 store volatile i32 %arg1, ptr %e1, align 4
939 call void asm sideeffect "teqi $$zero, 2", ""()
940 %arg2 = va_arg ptr %ap, i32
941 %e2 = getelementptr [3 x i32], ptr @words, i32 0, i32 2
942 store volatile i32 %arg2, ptr %e2, align 4
944 call void @llvm.va_end(ptr %ap)
949 define void @fn_i64_dotdotdot_i64(i64 %a, ...) {
951 ; ALL-LABEL: fn_i64_dotdotdot_i64:
953 ; Set up the stack with an 8-byte local area. N32/N64 must also make room for
954 ; the argument save area (56 bytes).
955 ; O32: addiu [[SP:\$sp]], $sp, -8
956 ; N32: addiu [[SP:\$sp]], $sp, -64
957 ; N64: daddiu [[SP:\$sp]], $sp, -64
959 ; Save variable argument portion on the stack
960 ; O32-DAG: sw $7, 20([[SP]])
961 ; O32-DAG: sw $6, 16([[SP]])
963 ; NEW-DAG: sd $11, 56([[SP]])
964 ; NEW-DAG: sd $10, 48([[SP]])
965 ; NEW-DAG: sd $9, 40([[SP]])
966 ; NEW-DAG: sd $8, 32([[SP]])
967 ; NEW-DAG: sd $7, 24([[SP]])
968 ; NEW-DAG: sd $6, 16([[SP]])
969 ; NEW-DAG: sd $5, 8([[SP]])
971 ; Initialize variable argument pointer.
972 ; For O32, the offset is 16 due to the 4 bytes used to store local variables,
973 ; 4 bytes padding to maintain stack alignment, and the two 4 byte slots for the
974 ; first fixed argument.
975 ; For N32/N64, it is only 8 since the fixed arguments do not reserve stack
977 ; O32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 16
978 ; O32-DAG: sw [[VA]], 0([[SP]])
980 ; N32-DAG: addiu [[VA:\$[0-9]+]], [[SP]], 8
981 ; N32-DAG: sw [[VA]], 0([[SP]])
983 ; N64-DAG: daddiu [[VA:\$[0-9]+]], [[SP]], 8
984 ; N64-DAG: sd [[VA]], 0([[SP]])
988 ; Increment [[VA]] (and realign pointer for O32)
989 ; O32: lw [[VA:\$[0-9]+]], 0([[SP]])
990 ; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7
991 ; O32-DAG: addiu [[VA_TMP1:\$[0-9]+]], $zero, -8
992 ; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]]
993 ; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4
994 ; O32-DAG: sw [[VA2]], 0([[SP]])
996 ; N32-DAG: lw [[VA:\$[0-9]+]], 0([[SP]])
997 ; N32-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8
998 ; N32-DAG: sw [[VA2]], 0([[SP]])
1000 ; N64-DAG: ld [[VA:\$[0-9]+]], 0([[SP]])
1001 ; N64-DAG: addiu [[VA2:\$[0-9]+]], [[VA]], 8
1002 ; N64-DAG: sd [[VA2]], 0([[SP]])
1004 ; Load the first argument from the variable portion and copy it to the global.
1005 ; This has used the stack pointer directly rather than the [[VA]] we just set
1007 ; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
1009 ; O32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords)
1010 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 0([[VA]])
1011 ; O32-DAG: sw [[ARG1]], 8([[GV]])
1012 ; O32-DAG: addiu [[VA3:\$[0-9]+]], [[VA_TMP2]], 8
1013 ; O32-DAG: sw [[VA3]], 0([[SP]])
1014 ; O32-DAG: lw [[ARG1:\$[0-9]+]], 4([[VA_TMP2]])
1015 ; O32-DAG: sw [[ARG1]], 12([[GV]])
1017 ; N32-DAG: addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords)
1018 ; N64-DAG: daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(dwords)
1019 ; NEW-DAG: ld [[ARG1:\$[0-9]+]], 0([[VA]])
1020 ; NEW-DAG: sd [[ARG1]], 8([[GV]])
1022 ; ALL: teqi $zero, 2
1024 ; Increment [[VA]] again.
1025 ; FIXME: We're still aligned from the last one but CodeGen doesn't spot that.
1026 ; O32: lw [[VA:\$[0-9]+]], 0([[SP]])
1027 ; O32-DAG: addiu [[VA_TMP0:\$[0-9]+]], [[VA]], 7
1028 ; O32-DAG: and [[VA_TMP2:\$[0-9]+]], [[VA_TMP0]], [[VA_TMP1]]
1029 ; O32-DAG: ori [[VA2:\$[0-9]+]], [[VA_TMP2]], 4
1030 ; O32-DAG: sw [[VA2]], 0([[SP]])
1032 ; N32-DAG: lw [[VA2:\$[0-9]+]], 0([[SP]])
1033 ; N32-DAG: addiu [[VA3:\$[0-9]+]], [[VA2]], 8
1034 ; N32-DAG: sw [[VA3]], 0([[SP]])
1036 ; N64-DAG: ld [[VA2:\$[0-9]+]], 0([[SP]])
1037 ; N64-DAG: daddiu [[VA3:\$[0-9]+]], [[VA2]], 8
1038 ; N64-DAG: sd [[VA3]], 0([[SP]])
1040 ; Load the second argument from the variable portion and copy it to the global.
1041 ; O32-DAG: lw [[ARG2:\$[0-9]+]], 0([[VA]])
1042 ; O32-DAG: addiu [[VA3:\$[0-9]+]], [[VA_TMP2]], 8
1043 ; O32-DAG: sw [[VA3]], 0([[SP]])
1044 ; O32-DAG: lw [[ARG3:\$[0-9]+]], 4([[VA_TMP2]])
1045 ; O32-DAG: sw [[ARG3]], 20([[GV]])
1046 ; O32-DAG: sw [[ARG2]], 16([[GV]])
1048 ; NEW-DAG: ld [[ARG2:\$[0-9]+]], 0([[VA2]])
1049 ; NEW-DAG: sd [[ARG2]], 16([[GV]])
1051 %ap = alloca ptr, align 8
1052 call void @llvm.va_start(ptr %ap)
1054 call void asm sideeffect "teqi $$zero, 1", ""()
1055 %arg1 = va_arg ptr %ap, i64
1056 %e1 = getelementptr [3 x i64], ptr @dwords, i32 0, i32 1
1057 store volatile i64 %arg1, ptr %e1, align 8
1059 call void asm sideeffect "teqi $$zero, 2", ""()
1060 %arg2 = va_arg ptr %ap, i64
1061 %e2 = getelementptr [3 x i64], ptr @dwords, i32 0, i32 2
1062 store volatile i64 %arg2, ptr %e2, align 8
1064 call void @llvm.va_end(ptr %ap)
1069 declare void @llvm.va_start(ptr)
1070 declare void @llvm.va_end(ptr)