29#ifndef __BITS_LPM_ELPM_H_
30#define __BITS_LPM_ELPM_H_
42#define __LPM_VOLATILE __volatile__
45#ifndef __ELPM_VOLATILE
46#define __ELPM_VOLATILE __volatile__
49#if defined(__AVR_TINY__)
54#define __LPM__1(res, addr) res = *addr
55#define __LPM__2(res, addr) res = *addr
56#define __LPM__3(res, addr) res = *addr
57#define __LPM__4(res, addr) res = *addr
58#define __LPM__8(res, addr) res = *addr
60#elif defined(__AVR_HAVE_LPMX__)
61#define __LPM__1(res, addr) \
62 __asm __LPM_VOLATILE ("lpm %0,%a1" \
63 : "=r" (res) : "z" (addr))
65#define __LPM__2(res, addr) \
66 __asm __LPM_VOLATILE ("lpm %A0,%a1+" "\n\t" \
68 : "=r" (res), "+z" (addr))
70#define __LPM__3(res, addr) \
71 __asm __LPM_VOLATILE ("lpm %A0,%a1+" "\n\t" \
72 "lpm %B0,%a1+" "\n\t" \
74 : "=r" (res), "+z" (addr))
76#define __LPM__4(res, addr) \
77 __asm __LPM_VOLATILE ("lpm %A0,%a1+" "\n\t" \
78 "lpm %B0,%a1+" "\n\t" \
79 "lpm %C0,%a1+" "\n\t" \
81 : "=r" (res), "+z" (addr))
83#define __LPM__8(res, addr) \
84 __asm __LPM_VOLATILE ("lpm %r0+0,%a1+" "\n\t" \
85 "lpm %r0+1,%a1+" "\n\t" \
86 "lpm %r0+2,%a1+" "\n\t" \
87 "lpm %r0+3,%a1+" "\n\t" \
88 "lpm %r0+4,%a1+" "\n\t" \
89 "lpm %r0+5,%a1+" "\n\t" \
90 "lpm %r0+6,%a1+" "\n\t" \
92 : "=r" (res), "+z" (addr))
94#define __LPM__1(res, addr) \
95 __asm __LPM_VOLATILE ("lpm $ mov %A0,r0" \
96 : "=r" (res) : "z" (addr) : "r0")
98#define __LPM__2(res, addr) \
99 __asm __LPM_VOLATILE ("lpm $ mov %A0,r0 $ adiw %1,1" "\n\t" \
101 : "=r" (res), "+z" (addr) :: "r0")
103#define __LPM__3(res, addr) \
104 __asm __LPM_VOLATILE ("lpm $ mov %A0,r0 $ adiw %1,1" "\n\t" \
105 "lpm $ mov %B0,r0 $ adiw %1,1" "\n\t" \
107 : "=r" (res), "+z" (addr) :: "r0")
109#define __LPM__4(res, addr) \
110 __asm __LPM_VOLATILE ("lpm $ mov %A0,r0 $ adiw %1,1" "\n\t" \
111 "lpm $ mov %B0,r0 $ adiw %1,1" "\n\t" \
112 "lpm $ mov %C0,r0 $ adiw %1,1" "\n\t" \
114 : "=r" (res), "+z" (addr) :: "r0")
116#define __LPM__8(res, addr) \
117 __asm __LPM_VOLATILE ("lpm $ mov %r0+0,r0 $ adiw %1,1" "\n\t" \
118 "lpm $ mov %r0+1,r0 $ adiw %1,1" "\n\t" \
119 "lpm $ mov %r0+2,r0 $ adiw %1,1" "\n\t" \
120 "lpm $ mov %r0+3,r0 $ adiw %1,1" "\n\t" \
121 "lpm $ mov %r0+4,r0 $ adiw %1,1" "\n\t" \
122 "lpm $ mov %r0+5,r0 $ adiw %1,1" "\n\t" \
123 "lpm $ mov %r0+6,r0 $ adiw %1,1" "\n\t" \
124 "lpm $ mov %r0+7,r0" \
125 : "=r" (res), "+z" (addr) :: "r0")
129#if defined(__AVR_HAVE_ELPMX__)
131#ifdef __AVR_HAVE_RAMPD__
133#define __pgm_clr_RAMPZ_ "\n\t" "out __RAMPZ__,__zero_reg__"
136#define __pgm_clr_RAMPZ_
139#define __ELPM__1(res, addr, T) \
140 __asm __ELPM_VOLATILE ("movw r30,%1" "\n\t" \
141 "out __RAMPZ__,%C1" "\n\t" \
148#define __ELPM__2(res, addr, T) \
149 __asm __ELPM_VOLATILE ("movw r30,%1" "\n\t" \
150 "out __RAMPZ__,%C1" "\n\t" \
151 "elpm %A0,Z+" "\n\t" \
158#define __ELPM__3(res, addr, T) \
159 __asm __ELPM_VOLATILE ("movw r30,%1" "\n\t" \
160 "out __RAMPZ__,%C1" "\n\t" \
161 "elpm %A0,Z+" "\n\t" \
162 "elpm %B0,Z+" "\n\t" \
169#define __ELPM__4(res, addr, T) \
170 __asm __ELPM_VOLATILE ("movw r30,%1" "\n\t" \
171 "out __RAMPZ__,%C1" "\n\t" \
172 "elpm %A0,Z+" "\n\t" \
173 "elpm %B0,Z+" "\n\t" \
174 "elpm %C0,Z+" "\n\t" \
181#define __ELPM__8(res, addr, T) \
182 __asm __ELPM_VOLATILE ("movw r30,%1" "\n\t" \
183 "out __RAMPZ__,%C1" "\n\t" \
184 "elpm %r0+0,Z+" "\n\t" \
185 "elpm %r0+1,Z+" "\n\t" \
186 "elpm %r0+2,Z+" "\n\t" \
187 "elpm %r0+3,Z+" "\n\t" \
188 "elpm %r0+4,Z+" "\n\t" \
189 "elpm %r0+5,Z+" "\n\t" \
190 "elpm %r0+6,Z+" "\n\t" \
204#elif defined(__AVR_HAVE_ELPM__) \
205 && !defined(__AVR_AT43USB320__)
207#define __ELPM__1(res, addr, T) \
208 __asm __ELPM_VOLATILE ("mov r30,%A1" "\n\t" \
209 "mov r31,%B1" "\n\t" \
210 "out __RAMPZ__,%C1 $ elpm $ mov %A0,r0" \
213 : "r30", "r31", "r0")
215#define __ELPM__2(res, addr, T) \
216 __asm __ELPM_VOLATILE \
217 ("mov r30,%A1" "\n\t" \
218 "mov r31,%B1" "\n\t" \
219 "mov %B0,%C1" "\n\t" \
220 "out __RAMPZ__,%B0 $ elpm $ mov %A0,r0 $ adiw r30,1 $ adc %B0,r1\n\t"\
221 "out __RAMPZ__,%B0 $ elpm $ mov %B0,r0" \
224 : "r30", "r31", "r0")
226#define __ELPM__3(res, addr, T) \
227 __asm __ELPM_VOLATILE \
228 ("mov r30,%A1" "\n\t" \
229 "mov r31,%B1" "\n\t" \
230 "mov %C0,%C1" "\n\t" \
231 "out __RAMPZ__,%C0 $ elpm $ mov %A0,r0 $ adiw r30,1 $ adc %C0,r1\n\t"\
232 "out __RAMPZ__,%C0 $ elpm $ mov %B0,r0 $ adiw r30,1 $ adc %C0,r1\n\t"\
233 "out __RAMPZ__,%C0 $ elpm $ mov %C0,r0" \
236 : "r30", "r31", "r0")
238#define __ELPM__4(res, addr, T) \
239 __asm __ELPM_VOLATILE \
240 ("mov r30,%A1" "\n\t" \
241 "mov r31,%B1" "\n\t" \
242 "mov %D0,%C1" "\n\t" \
243 "out __RAMPZ__,%D0 $ elpm $ mov %A0,r0 $ adiw r30,1 $ adc %D0,r1\n\t"\
244 "out __RAMPZ__,%D0 $ elpm $ mov %B0,r0 $ adiw r30,1 $ adc %D0,r1\n\t"\
245 "out __RAMPZ__,%D0 $ elpm $ mov %C0,r0 $ adiw r30,1 $ adc %D0,r1\n\t"\
246 "out __RAMPZ__,%D0 $ elpm $ mov %D0,r0" \
249 : "r30", "r31", "r0")
251#define __ELPM__8(res, addr, T) \
252 __asm __ELPM_VOLATILE \
253 ("mov r30,%A1" "\n\t" \
254 "mov r31,%B1" "\n\t" \
255 "mov %r0+7,%C1" "\n\t" \
256 "out __RAMPZ__,%r0+7 $ elpm $ mov %r0+0,0 $ adiw 30,1 $ adc %r0+7,1\n\t"\
257 "out __RAMPZ__,%r0+7 $ elpm $ mov %r0+1,0 $ adiw 30,1 $ adc %r0+7,1\n\t"\
258 "out __RAMPZ__,%r0+7 $ elpm $ mov %r0+2,0 $ adiw 30,1 $ adc %r0+7,1\n\t"\
259 "out __RAMPZ__,%r0+7 $ elpm $ mov %r0+3,0 $ adiw 30,1 $ adc %r0+7,1\n\t"\
260 "out __RAMPZ__,%r0+7 $ elpm $ mov %r0+4,0 $ adiw 30,1 $ adc %r0+7,1\n\t"\
261 "out __RAMPZ__,%r0+7 $ elpm $ mov %r0+5,0 $ adiw 30,1 $ adc %r0+7,1\n\t"\
262 "out __RAMPZ__,%r0+7 $ elpm $ mov %r0+6,0 $ adiw 30,1 $ adc %r0+7,1\n\t"\
263 "out __RAMPZ__,%r0+7 $ elpm $ mov %r0+7,0" \
266 : "r30", "r31", "r0")
269#define __ELPM__1(r,a,T) const T *__a = (const T*)(uint16_t) a; __LPM__1(r,__a)
270#define __ELPM__2(r,a,T) const T *__a = (const T*)(uint16_t) a; __LPM__2(r,__a)
271#define __ELPM__3(r,a,T) const T *__a = (const T*)(uint16_t) a; __LPM__3(r,__a)
272#define __ELPM__4(r,a,T) const T *__a = (const T*)(uint16_t) a; __LPM__4(r,__a)
273#define __ELPM__8(r,a,T) const T *__a = (const T*)(uint16_t) a; __LPM__8(r,__a)