1 /*
2  * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef _PICO_RCP_H
8 #define _PICO_RCP_H
9 
10 #include "pico.h"
11 
12 /** \file hardware/rcp.h
13  * \defgroup hardware_rcp hardware_rcp
14  * \brief Inline functions and assembly macros for the Redundancy Coprocessor
15  */
16 
17 // ----------------------------------------------------------------------------
18 // RCP instructions (this header is Arm-only)
19 #if defined(PICO_RP2350) && !defined(__riscv)
20 
21 #define RCP_MASK_TRUE   _u(0xa500a500)
22 #define RCP_MASK_FALSE  _u(0x00c300c3)
23 #define RCP_MASK_INTXOR _u(0x96009600)
24 
25 // ----------------------------------------------------------------------------
26 // Macros and inline functions for use in C files
27 #ifndef __ASSEMBLER__
28 
29 #define __rcpinline __force_inline
30 
31 #ifdef __cplusplus
32 extern "C" {
33 #endif
34 
35 #ifndef __riscv // should never do an rcp_asm in risc-v code
36 #if __ARM_ARCH_8M_MAIN__
37 #define rcp_asm pico_default_asm_volatile
38 #elif __ARM_ARCH_8M_BASE__
39 #define rcp_asm(...) ({pico_default_asm_volatile(".cpu cortex-m33\n" __VA_ARGS__); pico_default_asm_volatile(".cpu cortex-m23"); })
40 #elif __ARM_ARCH_6M__
41 #define rcp_asm(...) ({pico_default_asm_volatile(".cpu cortex-m33\n" __VA_ARGS__); pico_default_asm_volatile(".cpu cortex-m0plus"); })
42 #else
43 #error unknown ARM architecture
44 #endif
45 
46 // Each macro has a default version (e.g. rcp_salt_core0) and a no-delay version
47 // (e.g. rcp_salt_core0_nodelay). The default version adds an up to 127-cycle
48 // pseudorandom delay on each coprocessor instruction, whereas the no-delay version
49 // does not have this delay. The difference in the generated code is whether an MCR
50 // (e.g.) or MCR2 opcode is emitted.
51 
52 // ----------------------------------------------------------------------------
53 // RCP Canary instructions
54 
55 // Initialise 64-bit salt value for core 0
rcp_salt_core0(uint64_t salt)56 static __rcpinline void rcp_salt_core0(uint64_t salt) {
57     rcp_asm (
58             "mcrr p7, #8, %0, %1, c0\n"
59             : : "r" (salt & 0xffffffffu), "r" (salt >> 32)
60             );
61 }
62 
rcp_salt_core0_nodelay(uint64_t salt)63 static __rcpinline void rcp_salt_core0_nodelay(uint64_t salt) {
64     rcp_asm (
65             "mcrr2 p7, #8, %0, %1, c0\n"
66             : : "r" (salt & 0xffffffffu), "r" (salt >> 32)
67             );
68 }
69 
70 // Initialise 64-bit salt value for core 1
rcp_salt_core1(uint64_t salt)71 static __rcpinline void rcp_salt_core1(uint64_t salt) {
72     rcp_asm (
73             "mcrr p7, #8, %0, %1, c1\n"
74             : : "r" (salt & 0xffffffffu), "r" (salt >> 32)
75             );
76 }
77 
rcp_salt_core1_nodelay(uint64_t salt)78 static __rcpinline void rcp_salt_core1_nodelay(uint64_t salt) {
79     rcp_asm (
80             "mcrr2 p7, #8, %0, %1, c1\n"
81             : : "r" (salt & 0xffffffffu), "r" (salt >> 32)
82             );
83 }
84 
85 // Get a 32-bit canary value. `tag` must be a constant expression.
86 #define rcp_canary_get(tag) ({ \
87     uint32_t __canary_u32; \
88     rcp_asm ( \
89         "mrc p7, #0, %0, c%c1, c%c2, #1\n" \
90         : "=r" (__canary_u32) \
91         : "i" ((tag >> 4) & 0xf), "i" (tag & 0xf) \
92     ); \
93     __canary_u32; \
94 })
95 
96 #define rcp_canary_get_nodelay(tag) ({ \
97     uint32_t __canary_u32; \
98     rcp_asm ( \
99         "mrc2 p7, #0, %0, c%c1, c%c2, #1\n" \
100         : "=r" (__canary_u32) \
101         : "i" (((tag) >> 4) & 0xf), "i" ((tag) & 0xf) \
102     ); \
103     __canary_u32; \
104 })
105 
106 // Assert that canary matches result of rcp_canary_get with the same tags:
107 #define rcp_canary_check(tag, canary) ({ \
108     rcp_asm ( \
109         "mcr p7, #0, %0, c%c1, c%c2, #1\n" \
110         : : "r" (canary), \
111         "i" (((tag) >> 4) & 0xf), "i" ((tag) & 0xf) \
112     ); \
113 })
114 
115 #define rcp_canary_check_nodelay(tag, canary) ({ \
116     rcp_asm ( \
117         "mcr2 p7, #0, %0, c%c1, c%c2, #1\n" \
118         : : "r" (canary), \
119         "i" (((tag) >> 4) & 0xf), "i" ((tag) & 0xf) \
120     ); \
121 })
122 
123 // Return true/false bit pattern for whether the salt for this core has been
124 // initialised. (Invoking with Rt=0xf will set the Arm N flag if initialised.)
125 // If the salt has not been initialised then any operation other than
126 // initialising the salt or checking the canary status is a hard error.
rcp_canary_status(void)127 static __rcpinline uint32_t rcp_canary_status(void) {
128     uint32_t ret;
129     rcp_asm ("mrc p7, #1, %0, c0, c0, #0\n" : "=r" (ret));
130     return ret;
131 }
132 
rcp_canary_status_nodelay(void)133 static __rcpinline uint32_t rcp_canary_status_nodelay(void) {
134     uint32_t ret;
135     rcp_asm ("mrc2 p7, #1, %0, c0, c0, #0\n" : "=r" (ret));
136     return ret;
137 }
138 
139 // ----------------------------------------------------------------------------
140 // RCP Boolean instructions
141 
142 // Assert b is a valid boolean (0xa500a500u or 0x00c300c3u)
rcp_bvalid(uint32_t b)143 static __rcpinline void rcp_bvalid(uint32_t b) {
144     rcp_asm ("mcr p7, #1, %0, c0, c0, #0\n" : : "r" (b));
145 }
146 
rcp_bvalid_nodelay(uint32_t b)147 static __rcpinline void rcp_bvalid_nodelay(uint32_t b) {
148     rcp_asm ("mcr2 p7, #1, %0, c0, c0, #0\n" : : "r" (b));
149 }
150 
151 // Assert b is true (0xa500a500u)
rcp_btrue(uint32_t b)152 static __rcpinline void rcp_btrue(uint32_t b) {
153     rcp_asm ("mcr p7, #2, %0, c0, c0, #0\n" : : "r" (b));
154 }
155 
rcp_btrue_nodelay(uint32_t b)156 static __rcpinline void rcp_btrue_nodelay(uint32_t b) {
157     rcp_asm ("mcr2 p7, #2, %0, c0, c0, #0\n" : : "r" (b));
158 }
159 
160 // Assert b is false (0x00c300c3u)
rcp_bfalse(uint32_t b)161 static __rcpinline void rcp_bfalse(uint32_t b) {
162     rcp_asm ("mcr p7, #3, %0, c0, c0, #1\n" : : "r" (b));
163 }
164 
rcp_bfalse_nodelay(uint32_t b)165 static __rcpinline void rcp_bfalse_nodelay(uint32_t b) {
166     rcp_asm ("mcr2 p7, #3, %0, c0, c0, #1\n" : : "r" (b));
167 }
168 
169 // Assert b0 and b1 are both valid booleans
rcp_b2valid(uint32_t b0,uint32_t b1)170 static __rcpinline void rcp_b2valid(uint32_t b0, uint32_t b1) {
171     rcp_asm ("mcrr p7, #0, %0, %1, c8\n" : : "r" (b0), "r" (b1));
172 }
173 
rcp_b2valid_nodelay(uint32_t b0,uint32_t b1)174 static __rcpinline void rcp_b2valid_nodelay(uint32_t b0, uint32_t b1) {
175     rcp_asm ("mcrr2 p7, #0, %0, %1, c8\n" : : "r" (b0), "r" (b1));
176 }
177 
178 // Assert b0 and b1 are both true
rcp_b2and(uint32_t b0,uint32_t b1)179 static __rcpinline void rcp_b2and(uint32_t b0, uint32_t b1) {
180     rcp_asm ("mcrr p7, #1, %0, %1, c0\n" : : "r" (b0), "r" (b1));
181 }
182 
rcp_b2and_nodelay(uint32_t b0,uint32_t b1)183 static __rcpinline void rcp_b2and_nodelay(uint32_t b0, uint32_t b1) {
184     rcp_asm ("mcrr2 p7, #1, %0, %1, c0\n" : : "r" (b0), "r" (b1));
185 }
186 
187 // Assert b0 and b1 are valid, and at least one is true
rcp_b2or(uint32_t b0,uint32_t b1)188 static __rcpinline void rcp_b2or(uint32_t b0, uint32_t b1) {
189     rcp_asm ("mcrr p7, #2, %0, %1, c0\n" : : "r" (b0), "r" (b1));
190 }
191 
rcp_b2or_nodelay(uint32_t b0,uint32_t b1)192 static __rcpinline void rcp_b2or_nodelay(uint32_t b0, uint32_t b1) {
193     rcp_asm ("mcrr2 p7, #2, %0, %1, c0\n" : : "r" (b0), "r" (b1));
194 }
195 
196 // Assert (b ^ mask) is a valid boolean
rcp_bxorvalid(uint32_t b,uint32_t mask)197 static __rcpinline void rcp_bxorvalid(uint32_t b, uint32_t mask) {
198     rcp_asm ("mcrr p7, #3, %0, %1, c8\n" : : "r" (b), "r" (mask));
199 }
200 
rcp_bxorvalid_nodelay(uint32_t b,uint32_t mask)201 static __rcpinline void rcp_bxorvalid_nodelay(uint32_t b, uint32_t mask) {
202     rcp_asm ("mcrr2 p7, #3, %0, %1, c8\n" : : "r" (b), "r" (mask));
203 }
204 
205 // Assert (b ^ mask) is true
rcp_bxortrue(uint32_t b,uint32_t mask)206 static __rcpinline void rcp_bxortrue(uint32_t b, uint32_t mask) {
207     rcp_asm ("mcrr p7, #4, %0, %1, c0\n" : : "r" (b), "r" (mask));
208 }
209 
rcp_bxortrue_nodelay(uint32_t b,uint32_t mask)210 static __rcpinline void rcp_bxortrue_nodelay(uint32_t b, uint32_t mask) {
211     rcp_asm ("mcrr2 p7, #4, %0, %1, c0\n" : : "r" (b), "r" (mask));
212 }
213 
214 // Assert (b ^ mask) is false
rcp_bxorfalse(uint32_t b,uint32_t mask)215 static __rcpinline void rcp_bxorfalse(uint32_t b, uint32_t mask) {
216     rcp_asm ("mcrr p7, #5, %0, %1, c8\n" : : "r" (b), "r" (mask));
217 }
218 
rcp_bxorfalse_nodelay(uint32_t b,uint32_t mask)219 static __rcpinline void rcp_bxorfalse_nodelay(uint32_t b, uint32_t mask) {
220     rcp_asm ("mcrr2 p7, #5, %0, %1, c8\n" : : "r" (b), "r" (mask));
221 }
222 
223 // ----------------------------------------------------------------------------
224 // RCP Integer instructions
225 
226 // Assert (x ^ parity) == 0x96009600u
rcp_ivalid(uint32_t x,uint32_t parity)227 static __rcpinline void rcp_ivalid(uint32_t x, uint32_t parity) {
228     rcp_asm ("mcrr p7, #6, %0, %1, c8\n" : : "r" (x), "r" (parity));
229 }
230 
rcp_ivalid_nodelay(uint32_t x,uint32_t parity)231 static __rcpinline void rcp_ivalid_nodelay(uint32_t x, uint32_t parity) {
232     rcp_asm ("mcrr2 p7, #6, %0, %1, c8\n" : : "r" (x), "r" (parity));
233 }
234 
235 // Assert x == y
rcp_iequal(uint32_t x,uint32_t y)236 static __rcpinline void rcp_iequal(uint32_t x, uint32_t y) {
237     rcp_asm ("mcrr p7, #7, %0, %1, c0\n" : : "r" (x), "r" (y));
238 }
239 
rcp_iequal_nodelay(uint32_t x,uint32_t y)240 static __rcpinline void rcp_iequal_nodelay(uint32_t x, uint32_t y) {
241     rcp_asm ("mcrr2 p7, #7, %0, %1, c0\n" : : "r" (x), "r" (y));
242 }
243 
244 // ----------------------------------------------------------------------------
245 // RCP Random instructions
246 
247 // Return a random 8-bit value generated from the upper 24 bits of the 64-bit
248 // salt value. This is the same PRNG used for random delay values.
rcp_random_byte(void)249 static __rcpinline uint8_t rcp_random_byte(void) {
250     uint8_t ret;
251     rcp_asm ("mrc2 p7, #2, %0, c0, c0, #0\n" : "=r" (ret));
252     return ret;
253 }
254 
255 // Note neither version of this has delay, since the PRNG for the random delay
256 // is the same as the one read by this MRC instruction (and it's only stepped
257 // once).
rcp_random_byte_nodelay(void)258 static __rcpinline uint8_t rcp_random_byte_nodelay(void) {
259     uint8_t ret;
260     rcp_asm ("mrc2 p7, #2, %0, c0, c0, #0\n" : "=r" (ret));
261     return ret;
262 }
263 
264 // ----------------------------------------------------------------------------
265 // RCP Sequence count instructions
266 
267 // Directly write value cnt to the sequence counter.
268 // cnt must be a constant expression.
269 #define rcp_count_set(cnt) rcp_asm ( \
270     "mcr p7, #4, r0, c%c0, c%c1, #0\n" \
271     : : "i"(((cnt) >> 4) & 0xf), "i"((cnt) & 0xf) \
272 );
273 
274 #define rcp_count_set_nodelay(cnt) rcp_asm ( \
275     "mcr2 p7, #4, r0, c%c0, c%c1, #0\n" \
276     : : "i"(((cnt) >> 4) & 0xf), "i"((cnt) & 0xf) \
277 );
278 
279 // Check value cnt against the sequence counter, then increment the counter.
280 // cnt must be a constant expression.
281 #define rcp_count_check(cnt) rcp_asm ( \
282     "mcr p7, #5, r0, c%c0, c%c1, #1\n" \
283     : : "i"(((cnt) >> 4) & 0xf), "i"((cnt) & 0xf) \
284 );
285 
286 #define rcp_count_check_nodelay(cnt) rcp_asm ( \
287     "mcr2 p7, #5, r0, c%c0, c%c1, #1\n" \
288     : : "i"(((cnt) >> 4) & 0xf), "i"((cnt) & 0xf) \
289 );
290 
291 // ----------------------------------------------------------------------------
292 // RCP Panic instructions
293 
294 // Stall the coprocessor port. If the coprocessor access goes away, assert NMI
295 
rcp_panic(void)296 static __rcpinline __attribute__((noreturn)) void rcp_panic(void) {
297     rcp_asm("cdp p7, #0, c0, c0, c0, #1");
298     __builtin_unreachable();
299 }
300 
301 // There is no nodelay version.
302 
303 #endif // !__riscv
304 // ----------------------------------------------------------------------------
305 // GAS macros for RCP instructions, for direct use in ASM files
306 #else // __ASSEMBLER__
307 #ifndef __riscv
308 
309 // Assert b is a valid boolean (0xa500a500u or 0x00c300c3u)
310 .macro rcp_bvalid r
311     mcr p7, #1, \r , c0, c0, #0
312 .endm
313 
314 .macro rcp_bvalid_nodelay r
315     mcr2 p7, #1, \r , c0, c0, #0
316 .endm
317 
318 // Assert b is true (0xa500a500u)
319 .macro rcp_btrue r
320     mcr p7, #2, \r , c0, c0, #0
321 .endm
322 
323 .macro rcp_btrue_nodelay r
324     mcr2 p7, #2, \r , c0, c0, #0
325 .endm
326 
327 // Assert b is false (0x00c300c3u)
328 .macro rcp_bfalse r
329     mcr p7, #3, \r , c0, c0, #1
330 .endm
331 
332 .macro rcp_bfalse_nodelay r
333     mcr2 p7, #3, \r , c0, c0, #1
334 .endm
335 
336 // Assert b0 and b1 are both valid booleans
337 .macro rcp_b2valid b0, b1
338     mcrr p7, #0, \b0 , \b1 , c8
339 .endm
340 
341 .macro rcp_b2valid_nodelay b0, b1
342     mcrr2 p7, #0, \b0 , \b1 , c8
343 .endm
344 
345 // Assert b0 and b1 are both true
346 .macro rcp_b2and b0, b1
347     mcrr p7, #1, \b0 , \b1 , c0
348 .endm
349 
350 .macro rcp_b2and_nodelay b0, b1
351     mcrr2 p7, #1, \b0 , \b1 , c0
352 .endm
353 
354 // Assert b0 and b1 are valid, and at least one is true
355 .macro rcp_b2or b0, b1
356     mcrr p7, #2, \b0 , \b1 , c0
357 .endm
358 
359 .macro rcp_b2or_nodelay b0, b1
360     mcrr2 p7, #2, \b0 , \b1 , c0
361 .endm
362 
363 // Assert (b ^ mask) is a valid boolean
364 .macro rcp_bxorvalid b, mask
365     mcrr p7, #3, \b , \mask , c8
366 .endm
367 
368 .macro rcp_bxorvalid_nodelay b, mask
369     mcrr2 p7, #3, \b , \mask , c8
370 .endm
371 
372 // Assert (b ^ mask) is true
373 .macro rcp_bxortrue b, mask
374     mcrr p7, #4, \b , \mask , c0
375 .endm
376 
377 .macro rcp_bxortrue_nodelay b, mask
378     mcrr2 p7, #4, \b , \mask , c0
379 .endm
380 
381 // Assert (b ^ mask) is false
382 .macro rcp_bxorfalse b, mask
383     mcrr p7, #5, \b , \mask , c8
384 .endm
385 
386 .macro rcp_bxorfalse_nodelay b, mask
387     mcrr2 p7, #5, \b , \mask , c8
388 .endm
389 
390 // Assert (x ^ parity) == 0x96009600u
391 .macro rcp_ivalid x, parity
392     mcrr p7, #6, \x , \parity , c8
393 .endm
394 
395 .macro rcp_ivalid_nodelay x, parity
396     mcrr2 p7, #6, \x , \parity , c8
397 .endm
398 
399 // Assert x == y
400 .macro rcp_iequal x, y
401     mcrr p7, #7, \x , \y , c0
402 .endm
403 
404 .macro rcp_iequal_nodelay x, y
405     mcrr2 p7, #7, \x , \y , c0
406 .endm
407 
408 // They call this "metaprogramming" I think
409 .macro rcp_switch_u8_to_ch_cl macro_name, x, args:vararg
410 .if (\x) == 0
411 \macro_name  c0,  c0, \args
412 .elseif (\x) == 1
413 \macro_name  c0,  c1, \args
414 .elseif (\x) == 2
415 \macro_name  c0,  c2, \args
416 .elseif (\x) == 3
417 \macro_name  c0,  c3, \args
418 .elseif (\x) == 4
419 \macro_name  c0,  c4, \args
420 .elseif (\x) == 5
421 \macro_name  c0,  c5, \args
422 .elseif (\x) == 6
423 \macro_name  c0,  c6, \args
424 .elseif (\x) == 7
425 \macro_name  c0,  c7, \args
426 .elseif (\x) == 8
427 \macro_name  c0,  c8, \args
428 .elseif (\x) == 9
429 \macro_name  c0,  c9, \args
430 .elseif (\x) == 10
431 \macro_name  c0, c10, \args
432 .elseif (\x) == 11
433 \macro_name  c0, c11, \args
434 .elseif (\x) == 12
435 \macro_name  c0, c12, \args
436 .elseif (\x) == 13
437 \macro_name  c0, c13, \args
438 .elseif (\x) == 14
439 \macro_name  c0, c14, \args
440 .elseif (\x) == 15
441 \macro_name  c0, c15, \args
442 .elseif (\x) == 16
443 \macro_name  c1,  c0, \args
444 .elseif (\x) == 17
445 \macro_name  c1,  c1, \args
446 .elseif (\x) == 18
447 \macro_name  c1,  c2, \args
448 .elseif (\x) == 19
449 \macro_name  c1,  c3, \args
450 .elseif (\x) == 20
451 \macro_name  c1,  c4, \args
452 .elseif (\x) == 21
453 \macro_name  c1,  c5, \args
454 .elseif (\x) == 22
455 \macro_name  c1,  c6, \args
456 .elseif (\x) == 23
457 \macro_name  c1,  c7, \args
458 .elseif (\x) == 24
459 \macro_name  c1,  c8, \args
460 .elseif (\x) == 25
461 \macro_name  c1,  c9, \args
462 .elseif (\x) == 26
463 \macro_name  c1, c10, \args
464 .elseif (\x) == 27
465 \macro_name  c1, c11, \args
466 .elseif (\x) == 28
467 \macro_name  c1, c12, \args
468 .elseif (\x) == 29
469 \macro_name  c1, c13, \args
470 .elseif (\x) == 30
471 \macro_name  c1, c14, \args
472 .elseif (\x) == 31
473 \macro_name  c1, c15, \args
474 .elseif (\x) == 32
475 \macro_name  c2,  c0, \args
476 .elseif (\x) == 33
477 \macro_name  c2,  c1, \args
478 .elseif (\x) == 34
479 \macro_name  c2,  c2, \args
480 .elseif (\x) == 35
481 \macro_name  c2,  c3, \args
482 .elseif (\x) == 36
483 \macro_name  c2,  c4, \args
484 .elseif (\x) == 37
485 \macro_name  c2,  c5, \args
486 .elseif (\x) == 38
487 \macro_name  c2,  c6, \args
488 .elseif (\x) == 39
489 \macro_name  c2,  c7, \args
490 .elseif (\x) == 40
491 \macro_name  c2,  c8, \args
492 .elseif (\x) == 41
493 \macro_name  c2,  c9, \args
494 .elseif (\x) == 42
495 \macro_name  c2, c10, \args
496 .elseif (\x) == 43
497 \macro_name  c2, c11, \args
498 .elseif (\x) == 44
499 \macro_name  c2, c12, \args
500 .elseif (\x) == 45
501 \macro_name  c2, c13, \args
502 .elseif (\x) == 46
503 \macro_name  c2, c14, \args
504 .elseif (\x) == 47
505 \macro_name  c2, c15, \args
506 .elseif (\x) == 48
507 \macro_name  c3,  c0, \args
508 .elseif (\x) == 49
509 \macro_name  c3,  c1, \args
510 .elseif (\x) == 50
511 \macro_name  c3,  c2, \args
512 .elseif (\x) == 51
513 \macro_name  c3,  c3, \args
514 .elseif (\x) == 52
515 \macro_name  c3,  c4, \args
516 .elseif (\x) == 53
517 \macro_name  c3,  c5, \args
518 .elseif (\x) == 54
519 \macro_name  c3,  c6, \args
520 .elseif (\x) == 55
521 \macro_name  c3,  c7, \args
522 .elseif (\x) == 56
523 \macro_name  c3,  c8, \args
524 .elseif (\x) == 57
525 \macro_name  c3,  c9, \args
526 .elseif (\x) == 58
527 \macro_name  c3, c10, \args
528 .elseif (\x) == 59
529 \macro_name  c3, c11, \args
530 .elseif (\x) == 60
531 \macro_name  c3, c12, \args
532 .elseif (\x) == 61
533 \macro_name  c3, c13, \args
534 .elseif (\x) == 62
535 \macro_name  c3, c14, \args
536 .elseif (\x) == 63
537 \macro_name  c3, c15, \args
538 .elseif (\x) == 64
539 \macro_name  c4,  c0, \args
540 .elseif (\x) == 65
541 \macro_name  c4,  c1, \args
542 .elseif (\x) == 66
543 \macro_name  c4,  c2, \args
544 .elseif (\x) == 67
545 \macro_name  c4,  c3, \args
546 .elseif (\x) == 68
547 \macro_name  c4,  c4, \args
548 .elseif (\x) == 69
549 \macro_name  c4,  c5, \args
550 .elseif (\x) == 70
551 \macro_name  c4,  c6, \args
552 .elseif (\x) == 71
553 \macro_name  c4,  c7, \args
554 .elseif (\x) == 72
555 \macro_name  c4,  c8, \args
556 .elseif (\x) == 73
557 \macro_name  c4,  c9, \args
558 .elseif (\x) == 74
559 \macro_name  c4, c10, \args
560 .elseif (\x) == 75
561 \macro_name  c4, c11, \args
562 .elseif (\x) == 76
563 \macro_name  c4, c12, \args
564 .elseif (\x) == 77
565 \macro_name  c4, c13, \args
566 .elseif (\x) == 78
567 \macro_name  c4, c14, \args
568 .elseif (\x) == 79
569 \macro_name  c4, c15, \args
570 .elseif (\x) == 80
571 \macro_name  c5,  c0, \args
572 .elseif (\x) == 81
573 \macro_name  c5,  c1, \args
574 .elseif (\x) == 82
575 \macro_name  c5,  c2, \args
576 .elseif (\x) == 83
577 \macro_name  c5,  c3, \args
578 .elseif (\x) == 84
579 \macro_name  c5,  c4, \args
580 .elseif (\x) == 85
581 \macro_name  c5,  c5, \args
582 .elseif (\x) == 86
583 \macro_name  c5,  c6, \args
584 .elseif (\x) == 87
585 \macro_name  c5,  c7, \args
586 .elseif (\x) == 88
587 \macro_name  c5,  c8, \args
588 .elseif (\x) == 89
589 \macro_name  c5,  c9, \args
590 .elseif (\x) == 90
591 \macro_name  c5, c10, \args
592 .elseif (\x) == 91
593 \macro_name  c5, c11, \args
594 .elseif (\x) == 92
595 \macro_name  c5, c12, \args
596 .elseif (\x) == 93
597 \macro_name  c5, c13, \args
598 .elseif (\x) == 94
599 \macro_name  c5, c14, \args
600 .elseif (\x) == 95
601 \macro_name  c5, c15, \args
602 .elseif (\x) == 96
603 \macro_name  c6,  c0, \args
604 .elseif (\x) == 97
605 \macro_name  c6,  c1, \args
606 .elseif (\x) == 98
607 \macro_name  c6,  c2, \args
608 .elseif (\x) == 99
609 \macro_name  c6,  c3, \args
610 .elseif (\x) == 100
611 \macro_name  c6,  c4, \args
612 .elseif (\x) == 101
613 \macro_name  c6,  c5, \args
614 .elseif (\x) == 102
615 \macro_name  c6,  c6, \args
616 .elseif (\x) == 103
617 \macro_name  c6,  c7, \args
618 .elseif (\x) == 104
619 \macro_name  c6,  c8, \args
620 .elseif (\x) == 105
621 \macro_name  c6,  c9, \args
622 .elseif (\x) == 106
623 \macro_name  c6, c10, \args
624 .elseif (\x) == 107
625 \macro_name  c6, c11, \args
626 .elseif (\x) == 108
627 \macro_name  c6, c12, \args
628 .elseif (\x) == 109
629 \macro_name  c6, c13, \args
630 .elseif (\x) == 110
631 \macro_name  c6, c14, \args
632 .elseif (\x) == 111
633 \macro_name  c6, c15, \args
634 .elseif (\x) == 112
635 \macro_name  c7,  c0, \args
636 .elseif (\x) == 113
637 \macro_name  c7,  c1, \args
638 .elseif (\x) == 114
639 \macro_name  c7,  c2, \args
640 .elseif (\x) == 115
641 \macro_name  c7,  c3, \args
642 .elseif (\x) == 116
643 \macro_name  c7,  c4, \args
644 .elseif (\x) == 117
645 \macro_name  c7,  c5, \args
646 .elseif (\x) == 118
647 \macro_name  c7,  c6, \args
648 .elseif (\x) == 119
649 \macro_name  c7,  c7, \args
650 .elseif (\x) == 120
651 \macro_name  c7,  c8, \args
652 .elseif (\x) == 121
653 \macro_name  c7,  c9, \args
654 .elseif (\x) == 122
655 \macro_name  c7, c10, \args
656 .elseif (\x) == 123
657 \macro_name  c7, c11, \args
658 .elseif (\x) == 124
659 \macro_name  c7, c12, \args
660 .elseif (\x) == 125
661 \macro_name  c7, c13, \args
662 .elseif (\x) == 126
663 \macro_name  c7, c14, \args
664 .elseif (\x) == 127
665 \macro_name  c7, c15, \args
666 .elseif (\x) == 128
667 \macro_name  c8,  c0, \args
668 .elseif (\x) == 129
669 \macro_name  c8,  c1, \args
670 .elseif (\x) == 130
671 \macro_name  c8,  c2, \args
672 .elseif (\x) == 131
673 \macro_name  c8,  c3, \args
674 .elseif (\x) == 132
675 \macro_name  c8,  c4, \args
676 .elseif (\x) == 133
677 \macro_name  c8,  c5, \args
678 .elseif (\x) == 134
679 \macro_name  c8,  c6, \args
680 .elseif (\x) == 135
681 \macro_name  c8,  c7, \args
682 .elseif (\x) == 136
683 \macro_name  c8,  c8, \args
684 .elseif (\x) == 137
685 \macro_name  c8,  c9, \args
686 .elseif (\x) == 138
687 \macro_name  c8, c10, \args
688 .elseif (\x) == 139
689 \macro_name  c8, c11, \args
690 .elseif (\x) == 140
691 \macro_name  c8, c12, \args
692 .elseif (\x) == 141
693 \macro_name  c8, c13, \args
694 .elseif (\x) == 142
695 \macro_name  c8, c14, \args
696 .elseif (\x) == 143
697 \macro_name  c8, c15, \args
698 .elseif (\x) == 144
699 \macro_name  c9,  c0, \args
700 .elseif (\x) == 145
701 \macro_name  c9,  c1, \args
702 .elseif (\x) == 146
703 \macro_name  c9,  c2, \args
704 .elseif (\x) == 147
705 \macro_name  c9,  c3, \args
706 .elseif (\x) == 148
707 \macro_name  c9,  c4, \args
708 .elseif (\x) == 149
709 \macro_name  c9,  c5, \args
710 .elseif (\x) == 150
711 \macro_name  c9,  c6, \args
712 .elseif (\x) == 151
713 \macro_name  c9,  c7, \args
714 .elseif (\x) == 152
715 \macro_name  c9,  c8, \args
716 .elseif (\x) == 153
717 \macro_name  c9,  c9, \args
718 .elseif (\x) == 154
719 \macro_name  c9, c10, \args
720 .elseif (\x) == 155
721 \macro_name  c9, c11, \args
722 .elseif (\x) == 156
723 \macro_name  c9, c12, \args
724 .elseif (\x) == 157
725 \macro_name  c9, c13, \args
726 .elseif (\x) == 158
727 \macro_name  c9, c14, \args
728 .elseif (\x) == 159
729 \macro_name  c9, c15, \args
730 .elseif (\x) == 160
731 \macro_name c10,  c0, \args
732 .elseif (\x) == 161
733 \macro_name c10,  c1, \args
734 .elseif (\x) == 162
735 \macro_name c10,  c2, \args
736 .elseif (\x) == 163
737 \macro_name c10,  c3, \args
738 .elseif (\x) == 164
739 \macro_name c10,  c4, \args
740 .elseif (\x) == 165
741 \macro_name c10,  c5, \args
742 .elseif (\x) == 166
743 \macro_name c10,  c6, \args
744 .elseif (\x) == 167
745 \macro_name c10,  c7, \args
746 .elseif (\x) == 168
747 \macro_name c10,  c8, \args
748 .elseif (\x) == 169
749 \macro_name c10,  c9, \args
750 .elseif (\x) == 170
751 \macro_name c10, c10, \args
752 .elseif (\x) == 171
753 \macro_name c10, c11, \args
754 .elseif (\x) == 172
755 \macro_name c10, c12, \args
756 .elseif (\x) == 173
757 \macro_name c10, c13, \args
758 .elseif (\x) == 174
759 \macro_name c10, c14, \args
760 .elseif (\x) == 175
761 \macro_name c10, c15, \args
762 .elseif (\x) == 176
763 \macro_name c11,  c0, \args
764 .elseif (\x) == 177
765 \macro_name c11,  c1, \args
766 .elseif (\x) == 178
767 \macro_name c11,  c2, \args
768 .elseif (\x) == 179
769 \macro_name c11,  c3, \args
770 .elseif (\x) == 180
771 \macro_name c11,  c4, \args
772 .elseif (\x) == 181
773 \macro_name c11,  c5, \args
774 .elseif (\x) == 182
775 \macro_name c11,  c6, \args
776 .elseif (\x) == 183
777 \macro_name c11,  c7, \args
778 .elseif (\x) == 184
779 \macro_name c11,  c8, \args
780 .elseif (\x) == 185
781 \macro_name c11,  c9, \args
782 .elseif (\x) == 186
783 \macro_name c11, c10, \args
784 .elseif (\x) == 187
785 \macro_name c11, c11, \args
786 .elseif (\x) == 188
787 \macro_name c11, c12, \args
788 .elseif (\x) == 189
789 \macro_name c11, c13, \args
790 .elseif (\x) == 190
791 \macro_name c11, c14, \args
792 .elseif (\x) == 191
793 \macro_name c11, c15, \args
794 .elseif (\x) == 192
795 \macro_name c12,  c0, \args
796 .elseif (\x) == 193
797 \macro_name c12,  c1, \args
798 .elseif (\x) == 194
799 \macro_name c12,  c2, \args
800 .elseif (\x) == 195
801 \macro_name c12,  c3, \args
802 .elseif (\x) == 196
803 \macro_name c12,  c4, \args
804 .elseif (\x) == 197
805 \macro_name c12,  c5, \args
806 .elseif (\x) == 198
807 \macro_name c12,  c6, \args
808 .elseif (\x) == 199
809 \macro_name c12,  c7, \args
810 .elseif (\x) == 200
811 \macro_name c12,  c8, \args
812 .elseif (\x) == 201
813 \macro_name c12,  c9, \args
814 .elseif (\x) == 202
815 \macro_name c12, c10, \args
816 .elseif (\x) == 203
817 \macro_name c12, c11, \args
818 .elseif (\x) == 204
819 \macro_name c12, c12, \args
820 .elseif (\x) == 205
821 \macro_name c12, c13, \args
822 .elseif (\x) == 206
823 \macro_name c12, c14, \args
824 .elseif (\x) == 207
825 \macro_name c12, c15, \args
826 .elseif (\x) == 208
827 \macro_name c13,  c0, \args
828 .elseif (\x) == 209
829 \macro_name c13,  c1, \args
830 .elseif (\x) == 210
831 \macro_name c13,  c2, \args
832 .elseif (\x) == 211
833 \macro_name c13,  c3, \args
834 .elseif (\x) == 212
835 \macro_name c13,  c4, \args
836 .elseif (\x) == 213
837 \macro_name c13,  c5, \args
838 .elseif (\x) == 214
839 \macro_name c13,  c6, \args
840 .elseif (\x) == 215
841 \macro_name c13,  c7, \args
842 .elseif (\x) == 216
843 \macro_name c13,  c8, \args
844 .elseif (\x) == 217
845 \macro_name c13,  c9, \args
846 .elseif (\x) == 218
847 \macro_name c13, c10, \args
848 .elseif (\x) == 219
849 \macro_name c13, c11, \args
850 .elseif (\x) == 220
851 \macro_name c13, c12, \args
852 .elseif (\x) == 221
853 \macro_name c13, c13, \args
854 .elseif (\x) == 222
855 \macro_name c13, c14, \args
856 .elseif (\x) == 223
857 \macro_name c13, c15, \args
858 .elseif (\x) == 224
859 \macro_name c14,  c0, \args
860 .elseif (\x) == 225
861 \macro_name c14,  c1, \args
862 .elseif (\x) == 226
863 \macro_name c14,  c2, \args
864 .elseif (\x) == 227
865 \macro_name c14,  c3, \args
866 .elseif (\x) == 228
867 \macro_name c14,  c4, \args
868 .elseif (\x) == 229
869 \macro_name c14,  c5, \args
870 .elseif (\x) == 230
871 \macro_name c14,  c6, \args
872 .elseif (\x) == 231
873 \macro_name c14,  c7, \args
874 .elseif (\x) == 232
875 \macro_name c14,  c8, \args
876 .elseif (\x) == 233
877 \macro_name c14,  c9, \args
878 .elseif (\x) == 234
879 \macro_name c14, c10, \args
880 .elseif (\x) == 235
881 \macro_name c14, c11, \args
882 .elseif (\x) == 236
883 \macro_name c14, c12, \args
884 .elseif (\x) == 237
885 \macro_name c14, c13, \args
886 .elseif (\x) == 238
887 \macro_name c14, c14, \args
888 .elseif (\x) == 239
889 \macro_name c14, c15, \args
890 .elseif (\x) == 240
891 \macro_name c15,  c0, \args
892 .elseif (\x) == 241
893 \macro_name c15,  c1, \args
894 .elseif (\x) == 242
895 \macro_name c15,  c2, \args
896 .elseif (\x) == 243
897 \macro_name c15,  c3, \args
898 .elseif (\x) == 244
899 \macro_name c15,  c4, \args
900 .elseif (\x) == 245
901 \macro_name c15,  c5, \args
902 .elseif (\x) == 246
903 \macro_name c15,  c6, \args
904 .elseif (\x) == 247
905 \macro_name c15,  c7, \args
906 .elseif (\x) == 248
907 \macro_name c15,  c8, \args
908 .elseif (\x) == 249
909 \macro_name c15,  c9, \args
910 .elseif (\x) == 250
911 \macro_name c15, c10, \args
912 .elseif (\x) == 251
913 \macro_name c15, c11, \args
914 .elseif (\x) == 252
915 \macro_name c15, c12, \args
916 .elseif (\x) == 253
917 \macro_name c15, c13, \args
918 .elseif (\x) == 254
919 \macro_name c15, c14, \args
920 .elseif (\x) == 255
921 \macro_name c15, c15, \args
922 .else
923 .error "Value outside of range 0-255"
924 .endif
925 .endm
926 
927 // Directly write 8-bit constant expression cnt to the sequence counter.
928 .macro rcp_count_set_impl h, l
929 mcr p7, #4, r0, \h , \l , #0
930 .endm
931 .macro rcp_count_set cnt
932 rcp_switch_u8_to_ch_cl rcp_count_set_impl, \cnt
933 .endm
934 
935 .macro rcp_count_set_nodelay_impl h, l
936 mcr2 p7, #4, r0, \h , \l , #0
937 .endm
938 .macro rcp_count_set_nodelay cnt
939 rcp_switch_u8_to_ch_cl rcp_count_set_nodelay_impl, \cnt
940 .endm
941 
942 // Check 8-bit constant expression cnt against the sequence counter, then
943 // increment the counter.
944 .macro rcp_count_check_impl h, l
945     mcr p7, #5, r0, \h, \l, #1
946 .endm
947 .macro rcp_count_check cnt
948 rcp_switch_u8_to_ch_cl rcp_count_check_impl, \cnt
949 .endm
950 
951 .macro rcp_count_check_nodelay_impl h, l
952     mcr2 p7, #5, r0, \h, \l, #1
953 .endm
954 .macro rcp_count_check_nodelay cnt
955 rcp_switch_u8_to_ch_cl rcp_count_check_nodelay_impl, \cnt
956 .endm
957 
958 // Get a 32-bit canary value. `tag` must be a constant expression.
959 .macro rcp_canary_get_impl h, l, x
960    mrc p7, #0, \x, \h, \l, #1
961 .endm
962 
963 .macro rcp_canary_get x, tag
964 rcp_switch_u8_to_ch_cl rcp_canary_get_impl \tag, \x
965 .endm
966 
967 // Get a 32-bit canary value. `tag` must be a constant expression.
968 .macro rcp_canary_get_nodelay_impl h, l, x
969    mrc2 p7, #0, \x, \h, \l, #1
970 .endm
971 
972 .macro rcp_canary_get_nodelay x, tag
973 rcp_switch_u8_to_ch_cl rcp_canary_get_nodelay_impl \tag, \x
974 .endm
975 
976 // Assert that canary matches result of rcp_canary_get with the same tags:
977 .macro rcp_canary_check_impl h, l, x
978    mcr p7, #0, \x, \h, \l, #1
979 .endm
980 
981 .macro rcp_canary_check x, tag
982 rcp_switch_u8_to_ch_cl rcp_canary_check_impl \tag, \x
983 .endm
984 
985 .macro rcp_canary_check_nodelay_impl h, l, x
986    mcr2 p7, #0, \x, \h, \l, #1
987 .endm
988 
989 .macro rcp_canary_check_nodelay x, tag
990 rcp_switch_u8_to_ch_cl rcp_canary_check_nodelay_impl \tag, \x
991 .endm
992 
993 .macro rcp_panic
994     cdp p7, #0, c0, c0, c0, #1
995 .endm
996 
997 #endif // !__riscv
998 #endif // __ASSEMBLER__
999 // ----------------------------------------------------------------------------
1000 
1001 #ifdef __cplusplus
1002 }
1003 #endif
1004 #endif
1005 #endif
1006