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