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