1 | #ifndef LIBMP_H
|
2 | #define LIBMP_H
|
3 |
|
4 | #include <stdint.h>
|
5 | #include <avr/pgmspace.h>
|
6 |
|
7 | #define R_NUM "r24"
|
8 | #define R_CARRY "r25"
|
9 |
|
10 | #define mp_add(N, A, B) mp_adc (N, A, B, 0)
|
11 | #define mp_lsl(N, A) mp_rol (N, A, 0)
|
12 | #define mp_lsr(N, A) mp_ror (N, A, 0)
|
13 |
|
14 | #define MP_INLINE __inline__ __attribute__((__always_inline__))
|
15 |
|
16 | typedef struct
|
17 | {
|
18 | uint8_t mask;
|
19 | uint8_t offset;
|
20 | } mp_msb_t;
|
21 |
|
22 | extern void mp_adc_asm (void);
|
23 | extern void mp_ror_asm (void);
|
24 | extern void mp_rol_asm (void);
|
25 | extern void mp_rol8_asm (void);
|
26 | extern void mp_sub_asm (void);
|
27 | extern void mp_cmp_asm (void);
|
28 | extern void mp_add0_asm (void);
|
29 | extern void mp_sub0_asm (void);
|
30 | extern void mp_set0_asm (void);
|
31 | extern void mp_and_asm (void);
|
32 | extern void mp_com_asm (void);
|
33 | extern void mp_msb_asm (void);
|
34 | extern void mp_copy_asm (void);
|
35 | extern void mp_push_digit_asm (void);
|
36 |
|
37 | extern void mp_out_hex (uint8_t, uint8_t*);
|
38 | extern void mp_out_bin (uint8_t, const uint8_t*);
|
39 | extern void mp_out_dec (uint8_t, const uint8_t*, uint8_t);
|
40 | extern void mp_from_string (uint8_t, uint8_t*, const char*);
|
41 | extern uint8_t mp_pop_digit (uint8_t, uint8_t*, uint8_t);
|
42 | extern void mp_udivmod (uint8_t, uint8_t*, uint8_t*);
|
43 | extern void mp_udivmod_1 (uint8_t, uint8_t*, uint8_t*, uint8_t);
|
44 | extern void mp_mod (uint8_t, uint8_t*, const uint8_t*);
|
45 | extern void mp_add_m (uint8_t, uint8_t*, const uint8_t*, const uint8_t*);
|
46 | extern void mp_mul_m (uint8_t, uint8_t*, const uint8_t*, const uint8_t*);
|
47 | extern void mp_mul2_m (uint8_t, uint8_t*, const uint8_t*);
|
48 | extern void mp_exp_m (uint8_t, uint8_t*, const uint8_t*, const uint8_t*);
|
49 |
|
50 | static MP_INLINE
|
51 | uint8_t mp_udivmod0 (uint8_t n, uint8_t *a, uint8_t divisor)
|
52 | {
|
53 | return mp_pop_digit (n, a, divisor);
|
54 | }
|
55 |
|
56 | extern uint8_t mp_zero_p;
|
57 |
|
58 | static MP_INLINE
|
59 | void mp_copy_P (uint8_t n, uint8_t *a, const __flash uint8_t *b)
|
60 | {
|
61 | struct S { uint8_t a[n]; };
|
62 | * (struct S*) a = * (const __flash struct S*) b;
|
63 | }
|
64 |
|
65 | static MP_INLINE
|
66 | uint8_t mp_getbit (uint8_t *a, unsigned bit)
|
67 | {
|
68 | uint8_t val = a[bit >> 3];
|
69 | uint8_t bit8 = bit & 7;
|
70 | val >>= bit8;
|
71 | val &= 1;
|
72 | return val;
|
73 | }
|
74 |
|
75 |
|
76 | static MP_INLINE
|
77 | uint8_t mp_adc (uint8_t n, uint8_t *a, const uint8_t *b, uint8_t carry)
|
78 | {
|
79 | register uint8_t rn asm (R_NUM) = n;
|
80 | register uint8_t *ra asm ("r26") = a;
|
81 | register const uint8_t *rb asm ("r30") = b;
|
82 | register uint8_t rcarry asm (R_CARRY) = carry;
|
83 | asm volatile ("%~call %x[f]"
|
84 | : "+r" (rcarry)
|
85 | : [f] "s" (mp_adc_asm), "r" (rn), "r" (ra), "r" (rb)
|
86 | : "memory");
|
87 |
|
88 | return rcarry;
|
89 | }
|
90 |
|
91 | static MP_INLINE
|
92 | uint8_t mp_add0 (uint8_t n, uint8_t *a, int8_t val)
|
93 | {
|
94 | register uint8_t rn asm (R_NUM) = n;
|
95 | register uint8_t *ra asm ("r26") = a;
|
96 | register int8_t rcarry asm ("r25") = val;
|
97 | asm volatile ("%~call %x[f]"
|
98 | : "+r" (rcarry)
|
99 | : [f] "s" (mp_add0_asm), "r" (rn), "r" (ra)
|
100 | : "memory");
|
101 | if (val < 0)
|
102 | rcarry ^= 1;
|
103 | return rcarry;
|
104 | }
|
105 |
|
106 |
|
107 | static MP_INLINE
|
108 | uint8_t mp_rol8 (uint8_t n, uint8_t *a, uint8_t val)
|
109 | {
|
110 | register uint8_t rn asm (R_NUM) = n;
|
111 | register uint8_t *ra asm ("r26") = a;
|
112 | register uint8_t rval asm ("r25") = val;
|
113 | asm volatile ("%~call %x[f]"
|
114 | : "+r" (rval)
|
115 | : [f] "s" (mp_rol8_asm), "r" (rn), "r" (ra)
|
116 | : "memory");
|
117 |
|
118 | return rval;
|
119 | }
|
120 |
|
121 | static MP_INLINE
|
122 | uint8_t mp_and (uint8_t n, uint8_t *a, const uint8_t *b)
|
123 | {
|
124 | register uint8_t rn asm (R_NUM) = n;
|
125 | register uint8_t *ra asm ("r26") = a;
|
126 | register const uint8_t *rb asm ("r30") = b;
|
127 | register uint8_t rnonzero_p asm ("r25");
|
128 | asm volatile ("%~call %x[f]"
|
129 | : "=r" (rnonzero_p)
|
130 | : [f] "s" (mp_and_asm), "r" (rn), "r" (ra), "r" (rb)
|
131 | : "memory");
|
132 |
|
133 | return rnonzero_p;
|
134 | }
|
135 |
|
136 | static MP_INLINE
|
137 | void mp_com (uint8_t n, uint8_t *a)
|
138 | {
|
139 | register uint8_t rn asm (R_NUM) = n;
|
140 | register uint8_t *ra asm ("r26") = a;
|
141 | asm volatile ("%~call %x[f]"
|
142 | :
|
143 | : [f] "s" (mp_com_asm), "r" (rn), "r" (ra)
|
144 | : "memory");
|
145 | }
|
146 |
|
147 | static MP_INLINE
|
148 | void mp_neg (uint8_t n, uint8_t *a)
|
149 | {
|
150 | mp_add0 (n, a, -1);
|
151 | mp_com (n, a);
|
152 | }
|
153 |
|
154 | static MP_INLINE
|
155 | void mp_set0 (uint8_t n, uint8_t *a, int8_t val)
|
156 | {
|
157 | register uint8_t rn asm (R_NUM) = n;
|
158 | register uint8_t *ra asm ("r26") = a;
|
159 | register uint8_t rval asm ("r25") = val;
|
160 | asm volatile ("%~call %x[f]"
|
161 | : "+r" (rval)
|
162 | : [f] "s" (mp_set0_asm), "r" (rn), "r" (ra)
|
163 | : "memory");
|
164 | }
|
165 |
|
166 | static MP_INLINE
|
167 | uint8_t mp_ror (uint8_t n, uint8_t *a, uint8_t carry)
|
168 | {
|
169 | register uint8_t rn asm (R_NUM) = n;
|
170 | register uint8_t *ra asm ("r26") = a;
|
171 | register uint8_t rcarry asm (R_CARRY) = carry;
|
172 | asm volatile ("%~call %x[f]"
|
173 | : "+r" (rcarry)
|
174 | : [f] "s" (mp_ror_asm), "r" (rn), "r" (ra)
|
175 | : "memory");
|
176 |
|
177 | return rcarry;
|
178 | }
|
179 |
|
180 | static MP_INLINE
|
181 | uint8_t mp_rol (uint8_t n, uint8_t *a, uint8_t carry)
|
182 | {
|
183 | register uint8_t rn asm (R_NUM) = n;
|
184 | register uint8_t *ra asm ("r26") = a;
|
185 | register uint8_t rcarry asm (R_CARRY) = carry;
|
186 | asm volatile ("%~call %x[f]"
|
187 | : "+r" (rcarry)
|
188 | : [f] "s" (mp_rol_asm), "r" (rn), "r" (ra)
|
189 | : "memory");
|
190 |
|
191 | return rcarry;
|
192 | }
|
193 |
|
194 | static MP_INLINE
|
195 | void mp_sub (uint8_t n, uint8_t *a, const uint8_t *b)
|
196 | {
|
197 | register uint8_t rn asm (R_NUM) = n;
|
198 | register uint8_t *ra asm ("r26") = a;
|
199 | register const uint8_t *rb asm ("r30") = b;
|
200 | asm volatile ("%~call %x[f]"
|
201 | :
|
202 | : [f] "s" (mp_sub_asm), "r" (rn), "r" (ra), "r" (rb)
|
203 | : "25", "memory");
|
204 | }
|
205 |
|
206 | static MP_INLINE
|
207 | int8_t mp_cmp (uint8_t n, const uint8_t *a, const uint8_t *b, uint8_t signed_p)
|
208 | {
|
209 | register uint8_t rn asm (R_NUM) = n;
|
210 | register const uint8_t *ra asm ("r26") = a;
|
211 | register const uint8_t *rb asm ("r30") = b;
|
212 | register uint8_t rs asm ("r25") = signed_p;
|
213 | asm volatile ("%~call %x[f]"
|
214 | : "+r" (rs), "+r" (ra), "+r" (rb)
|
215 | : [f] "s" (mp_cmp_asm), "r" (rn)
|
216 | );
|
217 | return rs;
|
218 | }
|
219 |
|
220 | static MP_INLINE
|
221 | mp_msb_t mp_msb (uint8_t n, const uint8_t *a)
|
222 | {
|
223 | register uint8_t rn asm (R_NUM) = n;
|
224 | register const uint8_t *ra asm ("r26") = a;
|
225 | register mp_msb_t rmsb asm ("r22");
|
226 | asm volatile ("%~call %x[f]"
|
227 | : "=r" (rmsb)
|
228 | : [f] "s" (mp_msb_asm), "r" (rn), "r" (ra)
|
229 | );
|
230 | return rmsb;
|
231 | }
|
232 |
|
233 |
|
234 | static MP_INLINE
|
235 | uint8_t mp_push_digit (uint8_t n, uint8_t *a, uint8_t b, uint8_t d)
|
236 | {
|
237 | register uint8_t rn asm (R_NUM) = n;
|
238 | register uint8_t *ra asm ("r26") = a;
|
239 | register uint8_t rb asm ("r22") = b;
|
240 | register uint8_t rd asm ("r25") = d;
|
241 | asm volatile ("%~call %x[f]"
|
242 | : "+r" (rd)
|
243 | : [f] "s" (mp_push_digit_asm), "r" (rn), "r" (ra), "r" (rb)
|
244 | : "memory");
|
245 |
|
246 | return rd;
|
247 | }
|
248 |
|
249 | static MP_INLINE
|
250 | void mp_copy (uint8_t n, uint8_t *a, const uint8_t *b)
|
251 | {
|
252 | register uint8_t rn asm (R_NUM) = n;
|
253 | register uint8_t *ra asm ("r26") = a;
|
254 | register const uint8_t *rb asm ("r30") = b;
|
255 | asm volatile ("%~call %x[f]"
|
256 | :
|
257 | : [f] "s" (mp_copy_asm), "r" (rn), "r" (ra), "r" (rb)
|
258 | : "memory");
|
259 | }
|
260 |
|
261 |
|
262 | static MP_INLINE
|
263 | void mp_add0_m (uint8_t n, uint8_t *a, int8_t b, const uint8_t *m)
|
264 | {
|
265 | uint8_t carry = mp_add0 (n, a, b);
|
266 |
|
267 | if (b >= 0)
|
268 | {
|
269 | if (carry || mp_cmp (n, a, m, 0) >= 0)
|
270 | {
|
271 | mp_sub (n, a, m);
|
272 | }
|
273 | }
|
274 | else if (carry)
|
275 | {
|
276 | mp_add (n, a, m);
|
277 | }
|
278 | }
|
279 |
|
280 | #endif
|