xref: /llvm-project/llvm/test/CodeGen/Mips/cconv/arguments-varargs.ll (revision 8663926a544602932d299dda435ed1ef70a05f48)
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
5
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
10
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
15
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
20
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
24
25define void @fn_i16_dotdotdot_i16(i16 %a, ...) {
26entry:
27; ALL-LABEL: fn_i16_dotdotdot_i16:
28
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
34
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]])
39
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]])
47
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
51; fixed argument.
52; For N32/N64, it is only 8 since the fixed arguments do not reserve stack
53; space.
54; O32-DAG:       addiu [[VA:\$[0-9]+]], [[SP]], 12
55; O32-DAG:       sw [[VA]], 0([[SP]])
56
57; N32-DAG:       addiu [[VA:\$[0-9]+]], [[SP]], 8
58; N32-DAG:       sw [[VA]], 0([[SP]])
59
60; N64-DAG:       daddiu [[VA:\$[0-9]+]], [[SP]], 8
61; N64-DAG:       sd [[VA]], 0([[SP]])
62
63; ALL: teqi $zero, 1
64
65; Increment [[VA]]
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]])
69
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]])
73
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]])
77
78; Load the first argument from the variable portion.
79; This has used the stack pointer directly rather than the [[VA]] we just set
80; up.
81; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
82; order.
83; O32-DAG:       lw [[ARG1:\$[0-9]+]], 0([[VA]])
84
85; NEW-LE-DAG:    lw [[ARG1:\$[0-9]+]], 0([[VA]])
86; NEW-BE-DAG:    lw [[ARG1:\$[0-9]+]], 4([[VA]])
87
88; Copy the arg to the global
89; O32-DAG:       addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords)
90
91; N32-DAG:       addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords)
92
93; N64-DAG:       daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords)
94
95; ALL-DAG:       sh [[ARG1]], 2([[GV]])
96
97; ALL: teqi $zero, 2
98
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]])
103
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]])
107
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]])
111
112; Load the second argument from the variable portion.
113; O32-DAG:       lw [[ARG2:\$[0-9]+]], 0([[VA]])
114
115; NEW-LE-DAG:    lw [[ARG2:\$[0-9]+]], 0([[VA2]])
116; NEW-BE-DAG:    lw [[ARG2:\$[0-9]+]], 4([[VA2]])
117
118; Copy the arg to the global
119; ALL-DAG:       sh [[ARG2]], 4([[GV]])
120
121  %ap = alloca ptr, align 8
122  call void @llvm.va_start(ptr %ap)
123
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
128
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
133
134  call void @llvm.va_end(ptr %ap)
135
136  ret void
137}
138
139define void @fn_i16_dotdotdot_i32(i16 %a, ...) {
140entry:
141; ALL-LABEL: fn_i16_dotdotdot_i32:
142
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
148
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]])
153
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]])
161
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
165; fixed argument.
166; For N32/N64, it is only 8 since the fixed arguments do not reserve stack
167; space.
168; O32-DAG:       addiu [[VA:\$[0-9]+]], [[SP]], 12
169; O32-DAG:       sw [[VA]], 0([[SP]])
170
171; N32-DAG:       addiu [[VA:\$[0-9]+]], [[SP]], 8
172; N32-DAG:       sw [[VA]], 0([[SP]])
173
174; N64-DAG:       daddiu [[VA:\$[0-9]+]], [[SP]], 8
175; N64-DAG:       sd [[VA]], 0([[SP]])
176
177; ALL: teqi $zero, 1
178
179; Increment [[VA]]
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]])
183
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]])
187
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]])
191
192; Load the first argument from the variable portion.
193; This has used the stack pointer directly rather than the [[VA]] we just set
194; up.
195; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
196; order.
197; O32-DAG:       lw [[ARG1:\$[0-9]+]], 0([[VA]])
198
199; NEW-LE-DAG:    lw [[ARG1:\$[0-9]+]], 0([[VA]])
200; NEW-BE-DAG:    lw [[ARG1:\$[0-9]+]], 4([[VA]])
201
202; Copy the arg to the global
203; O32-DAG:       addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words)
204
205; N32-DAG:       addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words)
206
207; N64-DAG:       daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words)
208
209; ALL-DAG:       sw [[ARG1]], 4([[GV]])
210
211; ALL: teqi $zero, 2
212
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]])
217
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]])
221
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]])
225
226; Load the second argument from the variable portion.
227; O32-DAG:       lw [[ARG2:\$[0-9]+]], 0([[VA]])
228
229; NEW-LE-DAG:    lw [[ARG2:\$[0-9]+]], 0([[VA2]])
230; NEW-BE-DAG:    lw [[ARG2:\$[0-9]+]], 4([[VA2]])
231
232; Copy the arg to the global
233; ALL-DAG:       sw [[ARG2]], 8([[GV]])
234
235  %ap = alloca ptr, align 8
236  call void @llvm.va_start(ptr %ap)
237
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
242
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
247
248  call void @llvm.va_end(ptr %ap)
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; ALL: teqi $zero, 1
292
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]])
300
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]])
304
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]])
308
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
311; up.
312; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
313; order.
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]])
321
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]])
326
327; ALL: teqi $zero, 2
328
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]])
336
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]])
340
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]])
344
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]])
352
353; NEW-DAG:       ld [[ARG2:\$[0-9]+]], 0([[VA2]])
354; NEW-DAG:       sd [[ARG2]], 16([[GV]])
355
356  %ap = alloca ptr, align 8
357  call void @llvm.va_start(ptr %ap)
358
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
363
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
368
369  call void @llvm.va_end(ptr %ap)
370
371  ret void
372}
373
374define void @fn_i32_dotdotdot_i16(i32 %a, ...) {
375entry:
376; ALL-LABEL: fn_i32_dotdotdot_i16:
377
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
383
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]])
388
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]])
396
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
400; fixed argument.
401; For N32/N64, it is only 8 since the fixed arguments do not reserve stack
402; space.
403; O32-DAG:       addiu [[VA:\$[0-9]+]], [[SP]], 12
404; O32-DAG:       sw [[VA]], 0([[SP]])
405
406; N32-DAG:       addiu [[VA:\$[0-9]+]], [[SP]], 8
407; N32-DAG:       sw [[VA]], 0([[SP]])
408
409; N64-DAG:       daddiu [[VA:\$[0-9]+]], [[SP]], 8
410; N64-DAG:       sd [[VA]], 0([[SP]])
411
412; ALL: teqi $zero, 1
413
414; Increment [[VA]]
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]])
418
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]])
422
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]])
426
427; Load the first argument from the variable portion.
428; This has used the stack pointer directly rather than the [[VA]] we just set
429; up.
430; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
431; order.
432; O32-DAG:       lw [[ARG1:\$[0-9]+]], 0([[VA]])
433
434; NEW-LE-DAG:    lw [[ARG1:\$[0-9]+]], 0([[VA]])
435; NEW-BE-DAG:    lw [[ARG1:\$[0-9]+]], 4([[VA]])
436
437; Copy the arg to the global
438; O32-DAG:       addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords)
439
440; N32-DAG:       addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords)
441
442; N64-DAG:       daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords)
443
444; ALL-DAG:       sh [[ARG1]], 2([[GV]])
445
446; ALL: teqi $zero, 2
447
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]])
452
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]])
456
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]])
460
461; Load the second argument from the variable portion.
462; O32-DAG:       lw [[ARG2:\$[0-9]+]], 0([[VA]])
463
464; NEW-LE-DAG:    lw [[ARG2:\$[0-9]+]], 0([[VA2]])
465; NEW-BE-DAG:    lw [[ARG2:\$[0-9]+]], 4([[VA2]])
466
467; Copy the arg to the global
468; ALL-DAG:       sh [[ARG2]], 4([[GV]])
469
470  %ap = alloca ptr, align 8
471  call void @llvm.va_start(ptr %ap)
472
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
477
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
482
483  call void @llvm.va_end(ptr %ap)
484
485  ret void
486}
487
488define void @fn_i32_dotdotdot_i32(i32 %a, ...) {
489entry:
490; ALL-LABEL: fn_i32_dotdotdot_i32:
491
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
497
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]])
502
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]])
510
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
514; fixed argument.
515; For N32/N64, it is only 8 since the fixed arguments do not reserve stack
516; space.
517; O32-DAG:       addiu [[VA:\$[0-9]+]], [[SP]], 12
518; O32-DAG:       sw [[VA]], 0([[SP]])
519
520; N32-DAG:       addiu [[VA:\$[0-9]+]], [[SP]], 8
521; N32-DAG:       sw [[VA]], 0([[SP]])
522
523; N64-DAG:       daddiu [[VA:\$[0-9]+]], [[SP]], 8
524; N64-DAG:       sd [[VA]], 0([[SP]])
525
526; ALL: teqi $zero, 1
527
528; Increment [[VA]]
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]])
532
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]])
536
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]])
540
541; Load the first argument from the variable portion.
542; This has used the stack pointer directly rather than the [[VA]] we just set
543; up.
544; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
545; order.
546; O32-DAG:       lw [[ARG1:\$[0-9]+]], 0([[VA]])
547
548; NEW-LE-DAG:    lw [[ARG1:\$[0-9]+]], 0([[VA]])
549; NEW-BE-DAG:    lw [[ARG1:\$[0-9]+]], 4([[VA]])
550
551; Copy the arg to the global
552; O32-DAG:       addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words)
553
554; N32-DAG:       addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words)
555
556; N64-DAG:       daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words)
557
558; ALL-DAG:       sw [[ARG1]], 4([[GV]])
559
560; ALL: teqi $zero, 2
561
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]])
566
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]])
570
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]])
574
575; Load the second argument from the variable portion.
576; O32-DAG:       lw [[ARG2:\$[0-9]+]], 0([[VA]])
577
578; NEW-LE-DAG:    lw [[ARG2:\$[0-9]+]], 0([[VA2]])
579; NEW-BE-DAG:    lw [[ARG2:\$[0-9]+]], 4([[VA2]])
580
581; Copy the arg to the global
582; ALL-DAG:       sw [[ARG2]], 8([[GV]])
583
584  %ap = alloca ptr, align 8
585  call void @llvm.va_start(ptr %ap)
586
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
591
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
596
597  call void @llvm.va_end(ptr %ap)
598
599  ret void
600}
601
602define void @fn_i32_dotdotdot_i64(i32 %a, ...) {
603entry:
604; ALL-LABEL: fn_i32_dotdotdot_i64:
605
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
611
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]])
616
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]])
624
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
628; fixed argument.
629; For N32/N64, it is only 8 since the fixed arguments do not reserve stack
630; space.
631; O32-DAG:       addiu [[VA:\$[0-9]+]], [[SP]], 12
632; O32-DAG:       sw [[VA]], 0([[SP]])
633
634; N32-DAG:       addiu [[VA:\$[0-9]+]], [[SP]], 8
635; N32-DAG:       sw [[VA]], 0([[SP]])
636
637; N64-DAG:       daddiu [[VA:\$[0-9]+]], [[SP]], 8
638; N64-DAG:       sd [[VA]], 0([[SP]])
639
640; ALL: teqi $zero, 1
641
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]])
649
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]])
653
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]])
657
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
660; up.
661; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
662; order.
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]])
670
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]])
675
676; ALL: teqi $zero, 2
677
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]])
685
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]])
689
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]])
693
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]])
701
702; NEW-DAG:       ld [[ARG2:\$[0-9]+]], 0([[VA2]])
703; NEW-DAG:       sd [[ARG2]], 16([[GV]])
704
705  %ap = alloca ptr, align 8
706  call void @llvm.va_start(ptr %ap)
707
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
712
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
717
718  call void @llvm.va_end(ptr %ap)
719
720  ret void
721}
722
723define void @fn_i64_dotdotdot_i16(i64 %a, ...) {
724entry:
725; ALL-LABEL: fn_i64_dotdotdot_i16:
726
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
732
733; Save variable argument portion on the stack
734; O32-DAG:       sw $7, 20([[SP]])
735; O32-DAG:       sw $6, 16([[SP]])
736
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]])
744
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
750; space.
751; O32-DAG:       addiu [[VA:\$[0-9]+]], [[SP]], 16
752; O32-DAG:       sw [[VA]], 0([[SP]])
753
754; N32-DAG:       addiu [[VA:\$[0-9]+]], [[SP]], 8
755; N32-DAG:       sw [[VA]], 0([[SP]])
756
757; N64-DAG:       daddiu [[VA:\$[0-9]+]], [[SP]], 8
758; N64-DAG:       sd [[VA]], 0([[SP]])
759
760; ALL: teqi $zero, 1
761
762; Increment [[VA]]
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]])
766
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]])
770
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]])
774
775; Load the first argument from the variable portion.
776; This has used the stack pointer directly rather than the [[VA]] we just set
777; up.
778; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
779; order.
780; O32-DAG:       lw [[ARG1:\$[0-9]+]], 0([[VA]])
781
782; NEW-LE-DAG:    lw [[ARG1:\$[0-9]+]], 0([[VA]])
783; NEW-BE-DAG:    lw [[ARG1:\$[0-9]+]], 4([[VA]])
784
785; Copy the arg to the global
786; O32-DAG:       addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords)
787
788; N32-DAG:       addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords)
789
790; N64-DAG:       daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(hwords)
791
792; ALL-DAG:       sh [[ARG1]], 2([[GV]])
793
794; ALL: teqi $zero, 2
795
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]])
800
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]])
804
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]])
808
809; Load the second argument from the variable portion.
810; O32-DAG:       lw [[ARG2:\$[0-9]+]], 0([[VA]])
811
812; NEW-LE-DAG:    lw [[ARG2:\$[0-9]+]], 0([[VA2]])
813; NEW-BE-DAG:    lw [[ARG2:\$[0-9]+]], 4([[VA2]])
814
815; Copy the arg to the global
816; ALL-DAG:       sh [[ARG2]], 4([[GV]])
817
818  %ap = alloca ptr, align 8
819  call void @llvm.va_start(ptr %ap)
820
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
825
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
830
831  call void @llvm.va_end(ptr %ap)
832
833  ret void
834}
835
836define void @fn_i64_dotdotdot_i32(i64 %a, ...) {
837entry:
838; ALL-LABEL: fn_i64_dotdotdot_i32:
839
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
845
846; Save variable argument portion on the stack
847; O32-DAG:       sw $7, 20([[SP]])
848; O32-DAG:       sw $6, 16([[SP]])
849
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]])
857
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
863; space.
864; O32-DAG:       addiu [[VA:\$[0-9]+]], [[SP]], 16
865; O32-DAG:       sw [[VA]], 0([[SP]])
866
867; N32-DAG:       addiu [[VA:\$[0-9]+]], [[SP]], 8
868; N32-DAG:       sw [[VA]], 0([[SP]])
869
870; N64-DAG:       daddiu [[VA:\$[0-9]+]], [[SP]], 8
871; N64-DAG:       sd [[VA]], 0([[SP]])
872
873; ALL: teqi $zero, 1
874
875; Increment [[VA]]
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]])
879
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]])
883
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]])
887
888; Load the first argument from the variable portion.
889; This has used the stack pointer directly rather than the [[VA]] we just set
890; up.
891; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
892; order.
893; O32-DAG:       lw [[ARG1:\$[0-9]+]], 0([[VA]])
894
895; NEW-LE-DAG:    lw [[ARG1:\$[0-9]+]], 0([[VA]])
896; NEW-BE-DAG:    lw [[ARG1:\$[0-9]+]], 4([[VA]])
897
898; Copy the arg to the global
899; O32-DAG:       addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words)
900
901; N32-DAG:       addiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words)
902
903; N64-DAG:       daddiu [[GV:\$[0-9]+]], ${{[0-9]+}}, %lo(words)
904
905; ALL-DAG:       sw [[ARG1]], 4([[GV]])
906
907; ALL: teqi $zero, 2
908
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]])
913
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]])
917
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]])
921
922; Load the second argument from the variable portion.
923; O32-DAG:       lw [[ARG2:\$[0-9]+]], 0([[VA]])
924
925; NEW-LE-DAG:    lw [[ARG2:\$[0-9]+]], 0([[VA2]])
926; NEW-BE-DAG:    lw [[ARG2:\$[0-9]+]], 4([[VA2]])
927
928; Copy the arg to the global
929; ALL-DAG:       sw [[ARG2]], 8([[GV]])
930
931  %ap = alloca ptr, align 8
932  call void @llvm.va_start(ptr %ap)
933
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
938
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
943
944  call void @llvm.va_end(ptr %ap)
945
946  ret void
947}
948
949define void @fn_i64_dotdotdot_i64(i64 %a, ...) {
950entry:
951; ALL-LABEL: fn_i64_dotdotdot_i64:
952
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
958
959; Save variable argument portion on the stack
960; O32-DAG:       sw $7, 20([[SP]])
961; O32-DAG:       sw $6, 16([[SP]])
962
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]])
970
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
976; space.
977; O32-DAG:       addiu [[VA:\$[0-9]+]], [[SP]], 16
978; O32-DAG:       sw [[VA]], 0([[SP]])
979
980; N32-DAG:       addiu [[VA:\$[0-9]+]], [[SP]], 8
981; N32-DAG:       sw [[VA]], 0([[SP]])
982
983; N64-DAG:       daddiu [[VA:\$[0-9]+]], [[SP]], 8
984; N64-DAG:       sd [[VA]], 0([[SP]])
985
986; ALL: teqi $zero, 1
987
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]])
995
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]])
999
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]])
1003
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
1006; up.
1007; Big-endian mode for N32/N64 must add an additional 4 to the offset due to byte
1008; order.
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]])
1016
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]])
1021
1022; ALL: teqi $zero, 2
1023
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]])
1031
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]])
1035
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]])
1039
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]])
1047
1048; NEW-DAG:       ld [[ARG2:\$[0-9]+]], 0([[VA2]])
1049; NEW-DAG:       sd [[ARG2]], 16([[GV]])
1050
1051  %ap = alloca ptr, align 8
1052  call void @llvm.va_start(ptr %ap)
1053
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
1058
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
1063
1064  call void @llvm.va_end(ptr %ap)
1065
1066  ret void
1067}
1068
1069declare void @llvm.va_start(ptr)
1070declare void @llvm.va_end(ptr)
1071