rcp.h
Go to the documentation of this file.
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
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
32extern "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
56static __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
63static __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
71static __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
78static __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.
127static __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
133static __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)
143static __rcpinline void rcp_bvalid(uint32_t b) {
144 rcp_asm ("mcr p7, #1, %0, c0, c0, #0\n" : : "r" (b));
145}
146
147static __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)
152static __rcpinline void rcp_btrue(uint32_t b) {
153 rcp_asm ("mcr p7, #2, %0, c0, c0, #0\n" : : "r" (b));
154}
155
156static __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)
161static __rcpinline void rcp_bfalse(uint32_t b) {
162 rcp_asm ("mcr p7, #3, %0, c0, c0, #1\n" : : "r" (b));
163}
164
165static __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
170static __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
174static __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
179static __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
183static __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
188static __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
192static __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
197static __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
201static __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
206static __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
210static __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
215static __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
219static __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
227static __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
231static __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
236static __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
240static __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.
249static __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).
258static __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
296static __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
929mcr p7, #4, r0, \h , \l , #0
930.endm
931.macro rcp_count_set cnt
932rcp_switch_u8_to_ch_cl rcp_count_set_impl, \cnt
933.endm
934
935.macro rcp_count_set_nodelay_impl h, l
936mcr2 p7, #4, r0, \h , \l , #0
937.endm
938.macro rcp_count_set_nodelay cnt
939rcp_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
948rcp_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
955rcp_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
964rcp_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
973rcp_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
982rcp_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
990rcp_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