1; RUN: llc < %s -march=avr | FileCheck %s
2
3@count = global i8 0
4
5define avr_intrcc void @interrupt_handler() {
6; CHECK-LABEL: interrupt_handler:
7; CHECK: sei
8; CHECK-NEXT: push r0
9; CHECK-NEXT: push r1
10; CHECK-NEXT: in r0, 63
11; CHECK-NEXT: push r0
12; CHECK-NEXT: clr r1
13; CHECK: pop r0
14; CHECK-NEXT: out 63, r0
15; CHECK-NEXT: pop r1
16; CHECK-NEXT: pop r0
17; CHECK-NEXT: reti
18  ret void
19}
20
21define void @interrupt_handler_via_ir_attribute() #0 {
22; CHECK-LABEL: interrupt_handler_via_ir_attribute:
23; CHECK: sei
24; CHECK-NEXT: push r0
25; CHECK-NEXT: push r1
26; CHECK-NEXT: in r0, 63
27; CHECK-NEXT: push r0
28; CHECK-NEXT: clr r1
29; CHECK: pop r0
30; CHECK-NEXT: out 63, r0
31; CHECK-NEXT: pop r1
32; CHECK-NEXT: pop r0
33; CHECK-NEXT: reti
34  ret void
35}
36
37define avr_signalcc void @signal_handler() {
38; CHECK-LABEL: signal_handler:
39; CHECK-NOT: sei
40; CHECK: push r0
41; CHECK-NEXT: push r1
42; CHECK-NEXT: in r0, 63
43; CHECK-NEXT: push r0
44; CHECK-NEXT: clr r1
45; CHECK: pop r0
46; CHECK-NEXT: out 63, r0
47; CHECK-NEXT: pop r1
48; CHECK-NEXT: pop r0
49; CHECK-NEXT: reti
50  ret void
51}
52
53define void @signal_handler_via_attribute() #1 {
54; CHECK-LABEL: signal_handler_via_attribute:
55; CHECK-NOT: sei
56; CHECK: push r0
57; CHECK-NEXT: push r1
58; CHECK-NEXT: in r0, 63
59; CHECK-NEXT: push r0
60; CHECK-NEXT: clr r1
61; CHECK: pop r0
62; CHECK-NEXT: out 63, r0
63; CHECK-NEXT: pop r1
64; CHECK-NEXT: pop r0
65; CHECK-NEXT: reti
66  ret void
67}
68
69define avr_intrcc void @interrupt_alloca() {
70; CHECK-LABEL: interrupt_alloca:
71; CHECK: sei
72; CHECK-NEXT: push r0
73; CHECK-NEXT: push r1
74; CHECK-NEXT: in r0, 63
75; CHECK-NEXT: push r0
76; CHECK-NEXT: clr r1
77; CHECK: push r28
78; CHECK-NEXT: push r29
79; CHECK-NEXT: in r28, 61
80; CHECK-NEXT: in r29, 62
81; CHECK-NEXT: sbiw r28, 1
82; CHECK-NEXT: in r0, 63
83; CHECK-NEXT: cli
84; CHECK-NEXT: out 62, r29
85; CHECK-NEXT: out 63, r0
86; CHECK-NEXT: out 61, r28
87; CHECK: adiw r28, 1
88; CHECK-NEXT: in r0, 63
89; CHECK-NEXT: cli
90; CHECK-NEXT: out 62, r29
91; CHECK-NEXT: out 63, r0
92; CHECK-NEXT: out 61, r28
93; CHECK-NEXT: pop r29
94; CHECK-NEXT: pop r28
95; CHECK: pop r0
96; CHECK-NEXT: out 63, r0
97; CHECK-NEXT: pop r1
98; CHECK-NEXT: pop r0
99; CHECK-NEXT: reti
100  alloca i8
101  ret void
102}
103
104define void @signal_handler_with_increment() #1 {
105; CHECK-LABEL: signal_handler_with_increment:
106; CHECK:      push r0
107; CHECK-NEXT: push r1
108; CHECK-NEXT: in r0, 63
109; CHECK-NEXT: push r0
110; CHECK-NEXT: clr r1
111; CHECK-NEXT: push r24
112; CHECK-NEXT: lds r24, count
113; CHECK-NEXT: inc r24
114; CHECK-NEXT: sts count, r24
115; CHECK-NEXT: pop r24
116; CHECK-NEXT: pop r0
117; CHECK-NEXT: out 63, r0
118; CHECK-NEXT: pop r1
119; CHECK-NEXT: pop r0
120; CHECK-NEXT: reti
121  %old = load volatile i8, i8* @count
122  %new = add i8 %old, 1
123  store volatile i8 %new, i8* @count
124  ret void
125}
126
127declare void @foo()
128
129; When a signal handler calls a function, it must push/pop all call clobbered
130; registers.
131define void @signal_handler_with_call() #1 {
132; CHECK-LABEL: signal_handler_with_call:
133; CHECK:      push r0
134; CHECK-NEXT: push r1
135; CHECK-NEXT: in r0, 63
136; CHECK-NEXT: push r0
137; CHECK-NEXT: clr r1
138; CHECK-NEXT: push r18
139; CHECK-NEXT: push r19
140; CHECK-NEXT: push r20
141; CHECK-NEXT: push r21
142; CHECK-NEXT: push r22
143; CHECK-NEXT: push r23
144; CHECK-NEXT: push r24
145; CHECK-NEXT: push r25
146; CHECK-NEXT: push r26
147; CHECK-NEXT: push r27
148; CHECK-NEXT: push r30
149; CHECK-NEXT: push r31
150; CHECK-NEXT: call foo
151; CHECK-NEXT: pop r31
152; CHECK-NEXT: pop r30
153; CHECK-NEXT: pop r27
154; CHECK-NEXT: pop r26
155; CHECK-NEXT: pop r25
156; CHECK-NEXT: pop r24
157; CHECK-NEXT: pop r23
158; CHECK-NEXT: pop r22
159; CHECK-NEXT: pop r21
160; CHECK-NEXT: pop r20
161; CHECK-NEXT: pop r19
162; CHECK-NEXT: pop r18
163; CHECK-NEXT: pop r0
164; CHECK-NEXT: out 63, r0
165; CHECK-NEXT: pop r1
166; CHECK-NEXT: pop r0
167; CHECK-NEXT: reti
168  call void @foo()
169  ret void
170}
171
172attributes #0 = { "interrupt" }
173attributes #1 = { "signal" }
174