1 #ifndef ISR_TEST_H
2 #define ISR_TEST_H
3
4 #include <string.h>
5
6 #define ISR(N,...) \
7 __attribute__ ((used, externally_visible , ## __VA_ARGS__)) \
8 void __vector_##N (void); \
9 void __vector_##N (void)
10
11 #define SFR(ADDR) (*(unsigned char volatile*) (__AVR_SFR_OFFSET__ + (ADDR)))
12 #define CORE_SFRS SFR (0x38)
13 #define SREG SFR (0x3F)
14 #define SPL SFR (0x3D)
15 #define EIND SFR (0x3C)
16 #define RAMPZ SFR (0x3B)
17 #define RAMPY SFR (0x3A)
18 #define RAMPX SFR (0x39)
19 #define RAMPD SFR (0x38)
20
21 #ifdef __AVR_HAVE_JMP_CALL__
22 #define VEC_SIZE 4
23 #else
24 #define VEC_SIZE 2
25 #endif
26
27 #ifdef __AVR_TINY__
28 #define FIRST_REG 16
29 #else
30 #define FIRST_REG 0
31 #endif
32
33 #define CR "\n\t"
34
35 typedef struct
36 {
37 unsigned char sfrs[8];
38 unsigned char gprs[32 - FIRST_REG];
39 } regs_t;
40
41 regs_t reginfo1, reginfo2;
42
43 __attribute__((noinline,unused))
clear_reginfo(void)44 static void clear_reginfo (void)
45 {
46 memset (reginfo1.sfrs, 0, sizeof (reginfo1.sfrs));
47 memset (reginfo2.sfrs, 0, sizeof (reginfo2.sfrs));
48 }
49
50 __attribute__((noinline,unused))
compare_reginfo(unsigned long gpr_ignore)51 static void compare_reginfo (unsigned long gpr_ignore)
52 {
53 signed char regno;
54 const unsigned char *preg1 = ®info1.gprs[0];
55 const unsigned char *preg2 = ®info2.gprs[0];
56
57 if (memcmp (®info1, ®info2, 8))
58 __builtin_abort();
59
60 gpr_ignore >>= FIRST_REG;
61
62 for (regno = FIRST_REG; regno < 32;
63 regno++, preg1++, preg2++, gpr_ignore >>= 1)
64 {
65 if (gpr_ignore & 1)
66 continue;
67
68 if (*preg1 != *preg2)
69 {
70 static signed char volatile failed_regno;
71 (void) failed_regno;
72 failed_regno = regno;
73 __builtin_abort();
74 }
75 }
76 }
77
78 /* STore GPR */
79 #define ST(regno,M) \
80 CR "sts %[" #M "]+8-%[first]+" #regno ", r" #regno
81
82 /* STore SFR */
83 #define ST_SFR(sfr, n_sfr, M) \
84 CR "in __tmp_reg__,%i[s_" #sfr "]" \
85 CR "sts %[" #M "]+" #n_sfr ", __tmp_reg__"
86
87 /* Named asm OPerand for SFR */
88 #define OP_SFR(sfr) \
89 , [s_ ## sfr] "n" (&(sfr))
90
91 /* Write funny value to SFR */
92 #define XX_SFR(sfr) \
93 CR "dec r31 $ out %i[s_" #sfr "], r31"
94
95 /* Write 0 to SFR */
96 #define OO_SFR(sfr) \
97 CR "out %i[s_" #sfr "], __zero_reg__"
98
99 /* Macros for SREG */
100 #define ST_SREG(M) ST_SFR (SREG,0,M)
101 #define OP_SREG OP_SFR (SREG)
102 #define XX_SREG XX_SFR (SREG)
103
104 /* Macros for EIND */
105 #if defined __AVR_HAVE_EIJMP_EICALL__
106 #define ST_EIND(M) ST_SFR (EIND,1,M)
107 #define OP_EIND OP_SFR (EIND)
108 #else
109 #define ST_EIND(M) /* empty */
110 #define OP_EIND /* empty */
111 #endif
112
113 /* Macros for RAMPX */
114 #if defined (__AVR_HAVE_RAMPX__)
115 #define ST_RAMPX(M) ST_SFR (RAMPX,2,M)
116 #define OP_RAMPX OP_SFR (RAMPX)
117 #define XX_RAMPX XX_SFR (RAMPX)
118 #define OO_RAMPX OO_SFR (RAMPX)
119 #else
120 #define ST_RAMPX(M) /* empty */
121 #define OP_RAMPX /* empty */
122 #define XX_RAMPX /* empty */
123 #define OO_RAMPX /* empty */
124 #endif
125
126 /* Macros for RAMPY */
127 #if defined (__AVR_HAVE_RAMPY__)
128 #define ST_RAMPY(M) ST_SFR (RAMPY,3,M)
129 #define OP_RAMPY OP_SFR (RAMPY)
130 #define XX_RAMPY XX_SFR (RAMPY)
131 #define OO_RAMPY OO_SFR (RAMPY)
132 #else
133 #define ST_RAMPY(M) /* empty */
134 #define OP_RAMPY /* empty */
135 #define XX_RAMPY /* empty */
136 #define OO_RAMPY /* empty */
137 #endif
138
139 /* Macros for RAMPZ */
140 #if defined (__AVR_HAVE_RAMPZ__)
141 #define ST_RAMPZ(M) ST_SFR (RAMPZ,4,M)
142 #define OP_RAMPZ OP_SFR (RAMPZ)
143 #define XX_RAMPZ XX_SFR (RAMPZ)
144 #define OO_RAMPZ OO_SFR (RAMPZ)
145 #else
146 #define ST_RAMPZ(M) /* empty */
147 #define OP_RAMPZ /* empty */
148 #define XX_RAMPZ /* empty */
149 #define OO_RAMPZ /* empty */
150 #endif
151
152 /* Macros for RAMPD */
153 #if defined (__AVR_HAVE_RAMPD__)
154 #define ST_RAMPD(M) ST_SFR (RAMPD,5,M)
155 #define OP_RAMPD OP_SFR (RAMPD)
156 #else
157 #define ST_RAMPD(M) /* empty */
158 #define OP_RAMPD /* empty */
159 #endif
160
161 /* Macros for all GPRs */
162 #if defined __AVR_TINY__
163 #define ST_REGS_LO(M) /* empty */
164 #else
165 #define ST_REGS_LO(M) \
166 ST(0,M) ST(1,M) ST(2,M) ST(3,M) \
167 ST(4,M) ST(5,M) ST(6,M) ST(7,M) \
168 ST(8,M) ST(9,M) ST(10,M) ST(11,M) \
169 ST(12,M) ST(13,M) ST(14,M) ST(15,M)
170 #endif /* AVR_TINY */
171
172 #define ST_REGS_HI(M) \
173 ST(16,M) ST(17,M) ST(18,M) ST(19,M) \
174 ST(20,M) ST(21,M) ST(22,M) ST(23,M) \
175 ST(24,M) ST(25,M) ST(26,M) ST(27,M) \
176 ST(28,M) ST(29,M) ST(30,M) ST(31,M)
177
178 __attribute__((unused,naked,noinline,noclone))
host_store1(void)179 static void host_store1 (void)
180 {
181 __asm __volatile__
182 ("nop"
183 CR ".global do_stores_before"
184 CR ".type do_stores_before,@function"
185 CR "do_stores_before:"
186 /* Funny values to some SFRs */
187 CR "ldi r31, 1 + 'Z'"
188 XX_RAMPZ
189 XX_RAMPY
190 XX_RAMPX
191 CR "dec __zero_reg__"
192 CR "clr r31"
193 XX_SREG
194 /* Must set I-flag due to RETI of ISR */
195 CR "sei"
196 /* Store core regs before ISR */
197 ST_RAMPX (mem1)
198 ST_RAMPY (mem1)
199 ST_RAMPZ (mem1)
200 ST_RAMPD (mem1)
201 ST_EIND (mem1)
202 ST_SREG (mem1)
203 CR "ldi r31, 0xaa"
204 CR "mov __tmp_reg__, r31"
205 CR "ldi r31, 31"
206 ST_REGS_LO (mem1)
207 ST_REGS_HI (mem1)
208 CR "ret"
209 : /* No outputs */
210 : [mem1] "i" (®info1), [first] "n" (FIRST_REG)
211 OP_RAMPX
212 OP_RAMPY
213 OP_RAMPZ
214 OP_RAMPD
215 OP_EIND
216 OP_SREG
217 : "memory", "r31");
218 }
219
220 __attribute__((unused,naked,noinline,noclone))
host_store2(void)221 static void host_store2 (void)
222 {
223 __asm __volatile__
224 ("nop"
225 CR ".global do_stores_after"
226 CR ".type do_stores_after,@function"
227 CR "do_stores_after:"
228 /* Store core regs after ISR */
229 ST_REGS_LO (mem2)
230 ST_REGS_HI (mem2)
231 ST_RAMPX (mem2)
232 ST_RAMPY (mem2)
233 ST_RAMPZ (mem2)
234 ST_RAMPD (mem2)
235 ST_EIND (mem2)
236 ST_SREG (mem2)
237 /* Undo funny values */
238 CR "clr __zero_reg__"
239 OO_RAMPX
240 OO_RAMPY
241 OO_RAMPZ
242 CR "ret"
243 : /* No outputs */
244 : [mem2] "i" (®info2), [first] "n" (FIRST_REG)
245 OP_RAMPX
246 OP_RAMPY
247 OP_RAMPZ
248 OP_RAMPD
249 OP_EIND
250 OP_SREG
251 : "memory");
252 }
253
254 #define MK_CALL_ISR(vecno) \
255 __asm __volatile__ \
256 (/* Funny values to some SFRs */ \
257 /* Must set I-flag due to RETI of ISR */ \
258 /* Store core regs before ISR */ \
259 CR "%~call do_stores_before" \
260 /* Execute ISR */ \
261 CR "%~call __vectors + %[vect]" \
262 /* Store core regs after ISR */ \
263 /* Undo funny values */ \
264 CR "%~call do_stores_after" \
265 : /* No outputs */ \
266 : [vect] "i" (VEC_SIZE * (vecno)) \
267 , "i" (host_store1) \
268 , "i" (host_store2) \
269 : "memory", "r31")
270
271
272 #define MK_RUN_ISR(N, IGMSK) \
273 \
274 __attribute__((noinline,noclone)) \
275 void run_isr_ ## N (void) \
276 { \
277 clear_reginfo(); \
278 MK_CALL_ISR (N); \
279 compare_reginfo (IGMSK); \
280 }
281
282 #endif /* ISR_TEST_H */
283
284