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