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