| /* |
| * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. |
| * |
| * SPDX-License-Identifier: BSD-3-Clause |
| */ |
| |
| #ifndef _PICO_RCP_H |
| #define _PICO_RCP_H |
| |
| #include "pico.h" |
| |
| /** \file hardware/rcp.h |
| * \defgroup hardware_rcp hardware_rcp |
| * \brief Inline functions and assembly macros for the Redundancy Coprocessor |
| */ |
| |
| // ---------------------------------------------------------------------------- |
| // RCP instructions (this header is Arm-only) |
| #if defined(PICO_RP2350) && !defined(__riscv) |
| |
| #define RCP_MASK_TRUE _u(0xa500a500) |
| #define RCP_MASK_FALSE _u(0x00c300c3) |
| #define RCP_MASK_INTXOR _u(0x96009600) |
| |
| // ---------------------------------------------------------------------------- |
| // Macros and inline functions for use in C files |
| #ifndef __ASSEMBLER__ |
| |
| #define __rcpinline __force_inline |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #ifndef __riscv // should never do an rcp_asm in risc-v code |
| #if __ARM_ARCH_8M_MAIN__ |
| #define rcp_asm pico_default_asm_volatile |
| #elif __ARM_ARCH_8M_BASE__ |
| #define rcp_asm(...) ({pico_default_asm_volatile(".cpu cortex-m33\n" __VA_ARGS__); pico_default_asm_volatile(".cpu cortex-m23"); }) |
| #elif __ARM_ARCH_6M__ |
| #define rcp_asm(...) ({pico_default_asm_volatile(".cpu cortex-m33\n" __VA_ARGS__); pico_default_asm_volatile(".cpu cortex-m0plus"); }) |
| #else |
| #error unknown ARM architecture |
| #endif |
| |
| // Each macro has a default version (e.g. rcp_salt_core0) and a no-delay version |
| // (e.g. rcp_salt_core0_nodelay). The default version adds an up to 127-cycle |
| // pseudorandom delay on each coprocessor instruction, whereas the no-delay version |
| // does not have this delay. The difference in the generated code is whether an MCR |
| // (e.g.) or MCR2 opcode is emitted. |
| |
| // ---------------------------------------------------------------------------- |
| // RCP Canary instructions |
| |
| // Initialise 64-bit salt value for core 0 |
| static __rcpinline void rcp_salt_core0(uint64_t salt) { |
| rcp_asm ( |
| "mcrr p7, #8, %0, %1, c0\n" |
| : : "r" (salt & 0xffffffffu), "r" (salt >> 32) |
| ); |
| } |
| |
| static __rcpinline void rcp_salt_core0_nodelay(uint64_t salt) { |
| rcp_asm ( |
| "mcrr2 p7, #8, %0, %1, c0\n" |
| : : "r" (salt & 0xffffffffu), "r" (salt >> 32) |
| ); |
| } |
| |
| // Initialise 64-bit salt value for core 1 |
| static __rcpinline void rcp_salt_core1(uint64_t salt) { |
| rcp_asm ( |
| "mcrr p7, #8, %0, %1, c1\n" |
| : : "r" (salt & 0xffffffffu), "r" (salt >> 32) |
| ); |
| } |
| |
| static __rcpinline void rcp_salt_core1_nodelay(uint64_t salt) { |
| rcp_asm ( |
| "mcrr2 p7, #8, %0, %1, c1\n" |
| : : "r" (salt & 0xffffffffu), "r" (salt >> 32) |
| ); |
| } |
| |
| // Get a 32-bit canary value. `tag` must be a constant expression. |
| #define rcp_canary_get(tag) ({ \ |
| uint32_t __canary_u32; \ |
| rcp_asm ( \ |
| "mrc p7, #0, %0, c%c1, c%c2, #1\n" \ |
| : "=r" (__canary_u32) \ |
| : "i" ((tag >> 4) & 0xf), "i" (tag & 0xf) \ |
| ); \ |
| __canary_u32; \ |
| }) |
| |
| #define rcp_canary_get_nodelay(tag) ({ \ |
| uint32_t __canary_u32; \ |
| rcp_asm ( \ |
| "mrc2 p7, #0, %0, c%c1, c%c2, #1\n" \ |
| : "=r" (__canary_u32) \ |
| : "i" (((tag) >> 4) & 0xf), "i" ((tag) & 0xf) \ |
| ); \ |
| __canary_u32; \ |
| }) |
| |
| // Assert that canary matches result of rcp_canary_get with the same tags: |
| #define rcp_canary_check(tag, canary) ({ \ |
| rcp_asm ( \ |
| "mcr p7, #0, %0, c%c1, c%c2, #1\n" \ |
| : : "r" (canary), \ |
| "i" (((tag) >> 4) & 0xf), "i" ((tag) & 0xf) \ |
| ); \ |
| }) |
| |
| #define rcp_canary_check_nodelay(tag, canary) ({ \ |
| rcp_asm ( \ |
| "mcr2 p7, #0, %0, c%c1, c%c2, #1\n" \ |
| : : "r" (canary), \ |
| "i" (((tag) >> 4) & 0xf), "i" ((tag) & 0xf) \ |
| ); \ |
| }) |
| |
| // Return true/false bit pattern for whether the salt for this core has been |
| // initialised. (Invoking with Rt=0xf will set the Arm N flag if initialised.) |
| // If the salt has not been initialised then any operation other than |
| // initialising the salt or checking the canary status is a hard error. |
| static __rcpinline uint32_t rcp_canary_status(void) { |
| uint32_t ret; |
| rcp_asm ("mrc p7, #1, %0, c0, c0, #0\n" : "=r" (ret)); |
| return ret; |
| } |
| |
| static __rcpinline uint32_t rcp_canary_status_nodelay(void) { |
| uint32_t ret; |
| rcp_asm ("mrc2 p7, #1, %0, c0, c0, #0\n" : "=r" (ret)); |
| return ret; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // RCP Boolean instructions |
| |
| // Assert b is a valid boolean (0xa500a500u or 0x00c300c3u) |
| static __rcpinline void rcp_bvalid(uint32_t b) { |
| rcp_asm ("mcr p7, #1, %0, c0, c0, #0\n" : : "r" (b)); |
| } |
| |
| static __rcpinline void rcp_bvalid_nodelay(uint32_t b) { |
| rcp_asm ("mcr2 p7, #1, %0, c0, c0, #0\n" : : "r" (b)); |
| } |
| |
| // Assert b is true (0xa500a500u) |
| static __rcpinline void rcp_btrue(uint32_t b) { |
| rcp_asm ("mcr p7, #2, %0, c0, c0, #0\n" : : "r" (b)); |
| } |
| |
| static __rcpinline void rcp_btrue_nodelay(uint32_t b) { |
| rcp_asm ("mcr2 p7, #2, %0, c0, c0, #0\n" : : "r" (b)); |
| } |
| |
| // Assert b is false (0x00c300c3u) |
| static __rcpinline void rcp_bfalse(uint32_t b) { |
| rcp_asm ("mcr p7, #3, %0, c0, c0, #1\n" : : "r" (b)); |
| } |
| |
| static __rcpinline void rcp_bfalse_nodelay(uint32_t b) { |
| rcp_asm ("mcr2 p7, #3, %0, c0, c0, #1\n" : : "r" (b)); |
| } |
| |
| // Assert b0 and b1 are both valid booleans |
| static __rcpinline void rcp_b2valid(uint32_t b0, uint32_t b1) { |
| rcp_asm ("mcrr p7, #0, %0, %1, c8\n" : : "r" (b0), "r" (b1)); |
| } |
| |
| static __rcpinline void rcp_b2valid_nodelay(uint32_t b0, uint32_t b1) { |
| rcp_asm ("mcrr2 p7, #0, %0, %1, c8\n" : : "r" (b0), "r" (b1)); |
| } |
| |
| // Assert b0 and b1 are both true |
| static __rcpinline void rcp_b2and(uint32_t b0, uint32_t b1) { |
| rcp_asm ("mcrr p7, #1, %0, %1, c0\n" : : "r" (b0), "r" (b1)); |
| } |
| |
| static __rcpinline void rcp_b2and_nodelay(uint32_t b0, uint32_t b1) { |
| rcp_asm ("mcrr2 p7, #1, %0, %1, c0\n" : : "r" (b0), "r" (b1)); |
| } |
| |
| // Assert b0 and b1 are valid, and at least one is true |
| static __rcpinline void rcp_b2or(uint32_t b0, uint32_t b1) { |
| rcp_asm ("mcrr p7, #2, %0, %1, c0\n" : : "r" (b0), "r" (b1)); |
| } |
| |
| static __rcpinline void rcp_b2or_nodelay(uint32_t b0, uint32_t b1) { |
| rcp_asm ("mcrr2 p7, #2, %0, %1, c0\n" : : "r" (b0), "r" (b1)); |
| } |
| |
| // Assert (b ^ mask) is a valid boolean |
| static __rcpinline void rcp_bxorvalid(uint32_t b, uint32_t mask) { |
| rcp_asm ("mcrr p7, #3, %0, %1, c8\n" : : "r" (b), "r" (mask)); |
| } |
| |
| static __rcpinline void rcp_bxorvalid_nodelay(uint32_t b, uint32_t mask) { |
| rcp_asm ("mcrr2 p7, #3, %0, %1, c8\n" : : "r" (b), "r" (mask)); |
| } |
| |
| // Assert (b ^ mask) is true |
| static __rcpinline void rcp_bxortrue(uint32_t b, uint32_t mask) { |
| rcp_asm ("mcrr p7, #4, %0, %1, c0\n" : : "r" (b), "r" (mask)); |
| } |
| |
| static __rcpinline void rcp_bxortrue_nodelay(uint32_t b, uint32_t mask) { |
| rcp_asm ("mcrr2 p7, #4, %0, %1, c0\n" : : "r" (b), "r" (mask)); |
| } |
| |
| // Assert (b ^ mask) is false |
| static __rcpinline void rcp_bxorfalse(uint32_t b, uint32_t mask) { |
| rcp_asm ("mcrr p7, #5, %0, %1, c8\n" : : "r" (b), "r" (mask)); |
| } |
| |
| static __rcpinline void rcp_bxorfalse_nodelay(uint32_t b, uint32_t mask) { |
| rcp_asm ("mcrr2 p7, #5, %0, %1, c8\n" : : "r" (b), "r" (mask)); |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // RCP Integer instructions |
| |
| // Assert (x ^ parity) == 0x96009600u |
| static __rcpinline void rcp_ivalid(uint32_t x, uint32_t parity) { |
| rcp_asm ("mcrr p7, #6, %0, %1, c8\n" : : "r" (x), "r" (parity)); |
| } |
| |
| static __rcpinline void rcp_ivalid_nodelay(uint32_t x, uint32_t parity) { |
| rcp_asm ("mcrr2 p7, #6, %0, %1, c8\n" : : "r" (x), "r" (parity)); |
| } |
| |
| // Assert x == y |
| static __rcpinline void rcp_iequal(uint32_t x, uint32_t y) { |
| rcp_asm ("mcrr p7, #7, %0, %1, c0\n" : : "r" (x), "r" (y)); |
| } |
| |
| static __rcpinline void rcp_iequal_nodelay(uint32_t x, uint32_t y) { |
| rcp_asm ("mcrr2 p7, #7, %0, %1, c0\n" : : "r" (x), "r" (y)); |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // RCP Random instructions |
| |
| // Return a random 8-bit value generated from the upper 24 bits of the 64-bit |
| // salt value. This is the same PRNG used for random delay values. |
| static __rcpinline uint8_t rcp_random_byte(void) { |
| uint8_t ret; |
| rcp_asm ("mrc2 p7, #2, %0, c0, c0, #0\n" : "=r" (ret)); |
| return ret; |
| } |
| |
| // Note neither version of this has delay, since the PRNG for the random delay |
| // is the same as the one read by this MRC instruction (and it's only stepped |
| // once). |
| static __rcpinline uint8_t rcp_random_byte_nodelay(void) { |
| uint8_t ret; |
| rcp_asm ("mrc2 p7, #2, %0, c0, c0, #0\n" : "=r" (ret)); |
| return ret; |
| } |
| |
| // ---------------------------------------------------------------------------- |
| // RCP Sequence count instructions |
| |
| // Directly write value cnt to the sequence counter. |
| // cnt must be a constant expression. |
| #define rcp_count_set(cnt) rcp_asm ( \ |
| "mcr p7, #4, r0, c%c0, c%c1, #0\n" \ |
| : : "i"(((cnt) >> 4) & 0xf), "i"((cnt) & 0xf) \ |
| ); |
| |
| #define rcp_count_set_nodelay(cnt) rcp_asm ( \ |
| "mcr2 p7, #4, r0, c%c0, c%c1, #0\n" \ |
| : : "i"(((cnt) >> 4) & 0xf), "i"((cnt) & 0xf) \ |
| ); |
| |
| // Check value cnt against the sequence counter, then increment the counter. |
| // cnt must be a constant expression. |
| #define rcp_count_check(cnt) rcp_asm ( \ |
| "mcr p7, #5, r0, c%c0, c%c1, #1\n" \ |
| : : "i"(((cnt) >> 4) & 0xf), "i"((cnt) & 0xf) \ |
| ); |
| |
| #define rcp_count_check_nodelay(cnt) rcp_asm ( \ |
| "mcr2 p7, #5, r0, c%c0, c%c1, #1\n" \ |
| : : "i"(((cnt) >> 4) & 0xf), "i"((cnt) & 0xf) \ |
| ); |
| |
| // ---------------------------------------------------------------------------- |
| // RCP Panic instructions |
| |
| // Stall the coprocessor port. If the coprocessor access goes away, assert NMI |
| |
| static __rcpinline __attribute__((noreturn)) void rcp_panic(void) { |
| rcp_asm("cdp p7, #0, c0, c0, c0, #1"); |
| __builtin_unreachable(); |
| } |
| |
| // There is no nodelay version. |
| |
| #endif // !__riscv |
| // ---------------------------------------------------------------------------- |
| // GAS macros for RCP instructions, for direct use in ASM files |
| #else // __ASSEMBLER__ |
| #ifndef __riscv |
| |
| // Assert b is a valid boolean (0xa500a500u or 0x00c300c3u) |
| .macro rcp_bvalid r |
| mcr p7, #1, \r , c0, c0, #0 |
| .endm |
| |
| .macro rcp_bvalid_nodelay r |
| mcr2 p7, #1, \r , c0, c0, #0 |
| .endm |
| |
| // Assert b is true (0xa500a500u) |
| .macro rcp_btrue r |
| mcr p7, #2, \r , c0, c0, #0 |
| .endm |
| |
| .macro rcp_btrue_nodelay r |
| mcr2 p7, #2, \r , c0, c0, #0 |
| .endm |
| |
| // Assert b is false (0x00c300c3u) |
| .macro rcp_bfalse r |
| mcr p7, #3, \r , c0, c0, #1 |
| .endm |
| |
| .macro rcp_bfalse_nodelay r |
| mcr2 p7, #3, \r , c0, c0, #1 |
| .endm |
| |
| // Assert b0 and b1 are both valid booleans |
| .macro rcp_b2valid b0, b1 |
| mcrr p7, #0, \b0 , \b1 , c8 |
| .endm |
| |
| .macro rcp_b2valid_nodelay b0, b1 |
| mcrr2 p7, #0, \b0 , \b1 , c8 |
| .endm |
| |
| // Assert b0 and b1 are both true |
| .macro rcp_b2and b0, b1 |
| mcrr p7, #1, \b0 , \b1 , c0 |
| .endm |
| |
| .macro rcp_b2and_nodelay b0, b1 |
| mcrr2 p7, #1, \b0 , \b1 , c0 |
| .endm |
| |
| // Assert b0 and b1 are valid, and at least one is true |
| .macro rcp_b2or b0, b1 |
| mcrr p7, #2, \b0 , \b1 , c0 |
| .endm |
| |
| .macro rcp_b2or_nodelay b0, b1 |
| mcrr2 p7, #2, \b0 , \b1 , c0 |
| .endm |
| |
| // Assert (b ^ mask) is a valid boolean |
| .macro rcp_bxorvalid b, mask |
| mcrr p7, #3, \b , \mask , c8 |
| .endm |
| |
| .macro rcp_bxorvalid_nodelay b, mask |
| mcrr2 p7, #3, \b , \mask , c8 |
| .endm |
| |
| // Assert (b ^ mask) is true |
| .macro rcp_bxortrue b, mask |
| mcrr p7, #4, \b , \mask , c0 |
| .endm |
| |
| .macro rcp_bxortrue_nodelay b, mask |
| mcrr2 p7, #4, \b , \mask , c0 |
| .endm |
| |
| // Assert (b ^ mask) is false |
| .macro rcp_bxorfalse b, mask |
| mcrr p7, #5, \b , \mask , c8 |
| .endm |
| |
| .macro rcp_bxorfalse_nodelay b, mask |
| mcrr2 p7, #5, \b , \mask , c8 |
| .endm |
| |
| // Assert (x ^ parity) == 0x96009600u |
| .macro rcp_ivalid x, parity |
| mcrr p7, #6, \x , \parity , c8 |
| .endm |
| |
| .macro rcp_ivalid_nodelay x, parity |
| mcrr2 p7, #6, \x , \parity , c8 |
| .endm |
| |
| // Assert x == y |
| .macro rcp_iequal x, y |
| mcrr p7, #7, \x , \y , c0 |
| .endm |
| |
| .macro rcp_iequal_nodelay x, y |
| mcrr2 p7, #7, \x , \y , c0 |
| .endm |
| |
| // They call this "metaprogramming" I think |
| .macro rcp_switch_u8_to_ch_cl macro_name, x, args:vararg |
| .if (\x) == 0 |
| \macro_name c0, c0, \args |
| .elseif (\x) == 1 |
| \macro_name c0, c1, \args |
| .elseif (\x) == 2 |
| \macro_name c0, c2, \args |
| .elseif (\x) == 3 |
| \macro_name c0, c3, \args |
| .elseif (\x) == 4 |
| \macro_name c0, c4, \args |
| .elseif (\x) == 5 |
| \macro_name c0, c5, \args |
| .elseif (\x) == 6 |
| \macro_name c0, c6, \args |
| .elseif (\x) == 7 |
| \macro_name c0, c7, \args |
| .elseif (\x) == 8 |
| \macro_name c0, c8, \args |
| .elseif (\x) == 9 |
| \macro_name c0, c9, \args |
| .elseif (\x) == 10 |
| \macro_name c0, c10, \args |
| .elseif (\x) == 11 |
| \macro_name c0, c11, \args |
| .elseif (\x) == 12 |
| \macro_name c0, c12, \args |
| .elseif (\x) == 13 |
| \macro_name c0, c13, \args |
| .elseif (\x) == 14 |
| \macro_name c0, c14, \args |
| .elseif (\x) == 15 |
| \macro_name c0, c15, \args |
| .elseif (\x) == 16 |
| \macro_name c1, c0, \args |
| .elseif (\x) == 17 |
| \macro_name c1, c1, \args |
| .elseif (\x) == 18 |
| \macro_name c1, c2, \args |
| .elseif (\x) == 19 |
| \macro_name c1, c3, \args |
| .elseif (\x) == 20 |
| \macro_name c1, c4, \args |
| .elseif (\x) == 21 |
| \macro_name c1, c5, \args |
| .elseif (\x) == 22 |
| \macro_name c1, c6, \args |
| .elseif (\x) == 23 |
| \macro_name c1, c7, \args |
| .elseif (\x) == 24 |
| \macro_name c1, c8, \args |
| .elseif (\x) == 25 |
| \macro_name c1, c9, \args |
| .elseif (\x) == 26 |
| \macro_name c1, c10, \args |
| .elseif (\x) == 27 |
| \macro_name c1, c11, \args |
| .elseif (\x) == 28 |
| \macro_name c1, c12, \args |
| .elseif (\x) == 29 |
| \macro_name c1, c13, \args |
| .elseif (\x) == 30 |
| \macro_name c1, c14, \args |
| .elseif (\x) == 31 |
| \macro_name c1, c15, \args |
| .elseif (\x) == 32 |
| \macro_name c2, c0, \args |
| .elseif (\x) == 33 |
| \macro_name c2, c1, \args |
| .elseif (\x) == 34 |
| \macro_name c2, c2, \args |
| .elseif (\x) == 35 |
| \macro_name c2, c3, \args |
| .elseif (\x) == 36 |
| \macro_name c2, c4, \args |
| .elseif (\x) == 37 |
| \macro_name c2, c5, \args |
| .elseif (\x) == 38 |
| \macro_name c2, c6, \args |
| .elseif (\x) == 39 |
| \macro_name c2, c7, \args |
| .elseif (\x) == 40 |
| \macro_name c2, c8, \args |
| .elseif (\x) == 41 |
| \macro_name c2, c9, \args |
| .elseif (\x) == 42 |
| \macro_name c2, c10, \args |
| .elseif (\x) == 43 |
| \macro_name c2, c11, \args |
| .elseif (\x) == 44 |
| \macro_name c2, c12, \args |
| .elseif (\x) == 45 |
| \macro_name c2, c13, \args |
| .elseif (\x) == 46 |
| \macro_name c2, c14, \args |
| .elseif (\x) == 47 |
| \macro_name c2, c15, \args |
| .elseif (\x) == 48 |
| \macro_name c3, c0, \args |
| .elseif (\x) == 49 |
| \macro_name c3, c1, \args |
| .elseif (\x) == 50 |
| \macro_name c3, c2, \args |
| .elseif (\x) == 51 |
| \macro_name c3, c3, \args |
| .elseif (\x) == 52 |
| \macro_name c3, c4, \args |
| .elseif (\x) == 53 |
| \macro_name c3, c5, \args |
| .elseif (\x) == 54 |
| \macro_name c3, c6, \args |
| .elseif (\x) == 55 |
| \macro_name c3, c7, \args |
| .elseif (\x) == 56 |
| \macro_name c3, c8, \args |
| .elseif (\x) == 57 |
| \macro_name c3, c9, \args |
| .elseif (\x) == 58 |
| \macro_name c3, c10, \args |
| .elseif (\x) == 59 |
| \macro_name c3, c11, \args |
| .elseif (\x) == 60 |
| \macro_name c3, c12, \args |
| .elseif (\x) == 61 |
| \macro_name c3, c13, \args |
| .elseif (\x) == 62 |
| \macro_name c3, c14, \args |
| .elseif (\x) == 63 |
| \macro_name c3, c15, \args |
| .elseif (\x) == 64 |
| \macro_name c4, c0, \args |
| .elseif (\x) == 65 |
| \macro_name c4, c1, \args |
| .elseif (\x) == 66 |
| \macro_name c4, c2, \args |
| .elseif (\x) == 67 |
| \macro_name c4, c3, \args |
| .elseif (\x) == 68 |
| \macro_name c4, c4, \args |
| .elseif (\x) == 69 |
| \macro_name c4, c5, \args |
| .elseif (\x) == 70 |
| \macro_name c4, c6, \args |
| .elseif (\x) == 71 |
| \macro_name c4, c7, \args |
| .elseif (\x) == 72 |
| \macro_name c4, c8, \args |
| .elseif (\x) == 73 |
| \macro_name c4, c9, \args |
| .elseif (\x) == 74 |
| \macro_name c4, c10, \args |
| .elseif (\x) == 75 |
| \macro_name c4, c11, \args |
| .elseif (\x) == 76 |
| \macro_name c4, c12, \args |
| .elseif (\x) == 77 |
| \macro_name c4, c13, \args |
| .elseif (\x) == 78 |
| \macro_name c4, c14, \args |
| .elseif (\x) == 79 |
| \macro_name c4, c15, \args |
| .elseif (\x) == 80 |
| \macro_name c5, c0, \args |
| .elseif (\x) == 81 |
| \macro_name c5, c1, \args |
| .elseif (\x) == 82 |
| \macro_name c5, c2, \args |
| .elseif (\x) == 83 |
| \macro_name c5, c3, \args |
| .elseif (\x) == 84 |
| \macro_name c5, c4, \args |
| .elseif (\x) == 85 |
| \macro_name c5, c5, \args |
| .elseif (\x) == 86 |
| \macro_name c5, c6, \args |
| .elseif (\x) == 87 |
| \macro_name c5, c7, \args |
| .elseif (\x) == 88 |
| \macro_name c5, c8, \args |
| .elseif (\x) == 89 |
| \macro_name c5, c9, \args |
| .elseif (\x) == 90 |
| \macro_name c5, c10, \args |
| .elseif (\x) == 91 |
| \macro_name c5, c11, \args |
| .elseif (\x) == 92 |
| \macro_name c5, c12, \args |
| .elseif (\x) == 93 |
| \macro_name c5, c13, \args |
| .elseif (\x) == 94 |
| \macro_name c5, c14, \args |
| .elseif (\x) == 95 |
| \macro_name c5, c15, \args |
| .elseif (\x) == 96 |
| \macro_name c6, c0, \args |
| .elseif (\x) == 97 |
| \macro_name c6, c1, \args |
| .elseif (\x) == 98 |
| \macro_name c6, c2, \args |
| .elseif (\x) == 99 |
| \macro_name c6, c3, \args |
| .elseif (\x) == 100 |
| \macro_name c6, c4, \args |
| .elseif (\x) == 101 |
| \macro_name c6, c5, \args |
| .elseif (\x) == 102 |
| \macro_name c6, c6, \args |
| .elseif (\x) == 103 |
| \macro_name c6, c7, \args |
| .elseif (\x) == 104 |
| \macro_name c6, c8, \args |
| .elseif (\x) == 105 |
| \macro_name c6, c9, \args |
| .elseif (\x) == 106 |
| \macro_name c6, c10, \args |
| .elseif (\x) == 107 |
| \macro_name c6, c11, \args |
| .elseif (\x) == 108 |
| \macro_name c6, c12, \args |
| .elseif (\x) == 109 |
| \macro_name c6, c13, \args |
| .elseif (\x) == 110 |
| \macro_name c6, c14, \args |
| .elseif (\x) == 111 |
| \macro_name c6, c15, \args |
| .elseif (\x) == 112 |
| \macro_name c7, c0, \args |
| .elseif (\x) == 113 |
| \macro_name c7, c1, \args |
| .elseif (\x) == 114 |
| \macro_name c7, c2, \args |
| .elseif (\x) == 115 |
| \macro_name c7, c3, \args |
| .elseif (\x) == 116 |
| \macro_name c7, c4, \args |
| .elseif (\x) == 117 |
| \macro_name c7, c5, \args |
| .elseif (\x) == 118 |
| \macro_name c7, c6, \args |
| .elseif (\x) == 119 |
| \macro_name c7, c7, \args |
| .elseif (\x) == 120 |
| \macro_name c7, c8, \args |
| .elseif (\x) == 121 |
| \macro_name c7, c9, \args |
| .elseif (\x) == 122 |
| \macro_name c7, c10, \args |
| .elseif (\x) == 123 |
| \macro_name c7, c11, \args |
| .elseif (\x) == 124 |
| \macro_name c7, c12, \args |
| .elseif (\x) == 125 |
| \macro_name c7, c13, \args |
| .elseif (\x) == 126 |
| \macro_name c7, c14, \args |
| .elseif (\x) == 127 |
| \macro_name c7, c15, \args |
| .elseif (\x) == 128 |
| \macro_name c8, c0, \args |
| .elseif (\x) == 129 |
| \macro_name c8, c1, \args |
| .elseif (\x) == 130 |
| \macro_name c8, c2, \args |
| .elseif (\x) == 131 |
| \macro_name c8, c3, \args |
| .elseif (\x) == 132 |
| \macro_name c8, c4, \args |
| .elseif (\x) == 133 |
| \macro_name c8, c5, \args |
| .elseif (\x) == 134 |
| \macro_name c8, c6, \args |
| .elseif (\x) == 135 |
| \macro_name c8, c7, \args |
| .elseif (\x) == 136 |
| \macro_name c8, c8, \args |
| .elseif (\x) == 137 |
| \macro_name c8, c9, \args |
| .elseif (\x) == 138 |
| \macro_name c8, c10, \args |
| .elseif (\x) == 139 |
| \macro_name c8, c11, \args |
| .elseif (\x) == 140 |
| \macro_name c8, c12, \args |
| .elseif (\x) == 141 |
| \macro_name c8, c13, \args |
| .elseif (\x) == 142 |
| \macro_name c8, c14, \args |
| .elseif (\x) == 143 |
| \macro_name c8, c15, \args |
| .elseif (\x) == 144 |
| \macro_name c9, c0, \args |
| .elseif (\x) == 145 |
| \macro_name c9, c1, \args |
| .elseif (\x) == 146 |
| \macro_name c9, c2, \args |
| .elseif (\x) == 147 |
| \macro_name c9, c3, \args |
| .elseif (\x) == 148 |
| \macro_name c9, c4, \args |
| .elseif (\x) == 149 |
| \macro_name c9, c5, \args |
| .elseif (\x) == 150 |
| \macro_name c9, c6, \args |
| .elseif (\x) == 151 |
| \macro_name c9, c7, \args |
| .elseif (\x) == 152 |
| \macro_name c9, c8, \args |
| .elseif (\x) == 153 |
| \macro_name c9, c9, \args |
| .elseif (\x) == 154 |
| \macro_name c9, c10, \args |
| .elseif (\x) == 155 |
| \macro_name c9, c11, \args |
| .elseif (\x) == 156 |
| \macro_name c9, c12, \args |
| .elseif (\x) == 157 |
| \macro_name c9, c13, \args |
| .elseif (\x) == 158 |
| \macro_name c9, c14, \args |
| .elseif (\x) == 159 |
| \macro_name c9, c15, \args |
| .elseif (\x) == 160 |
| \macro_name c10, c0, \args |
| .elseif (\x) == 161 |
| \macro_name c10, c1, \args |
| .elseif (\x) == 162 |
| \macro_name c10, c2, \args |
| .elseif (\x) == 163 |
| \macro_name c10, c3, \args |
| .elseif (\x) == 164 |
| \macro_name c10, c4, \args |
| .elseif (\x) == 165 |
| \macro_name c10, c5, \args |
| .elseif (\x) == 166 |
| \macro_name c10, c6, \args |
| .elseif (\x) == 167 |
| \macro_name c10, c7, \args |
| .elseif (\x) == 168 |
| \macro_name c10, c8, \args |
| .elseif (\x) == 169 |
| \macro_name c10, c9, \args |
| .elseif (\x) == 170 |
| \macro_name c10, c10, \args |
| .elseif (\x) == 171 |
| \macro_name c10, c11, \args |
| .elseif (\x) == 172 |
| \macro_name c10, c12, \args |
| .elseif (\x) == 173 |
| \macro_name c10, c13, \args |
| .elseif (\x) == 174 |
| \macro_name c10, c14, \args |
| .elseif (\x) == 175 |
| \macro_name c10, c15, \args |
| .elseif (\x) == 176 |
| \macro_name c11, c0, \args |
| .elseif (\x) == 177 |
| \macro_name c11, c1, \args |
| .elseif (\x) == 178 |
| \macro_name c11, c2, \args |
| .elseif (\x) == 179 |
| \macro_name c11, c3, \args |
| .elseif (\x) == 180 |
| \macro_name c11, c4, \args |
| .elseif (\x) == 181 |
| \macro_name c11, c5, \args |
| .elseif (\x) == 182 |
| \macro_name c11, c6, \args |
| .elseif (\x) == 183 |
| \macro_name c11, c7, \args |
| .elseif (\x) == 184 |
| \macro_name c11, c8, \args |
| .elseif (\x) == 185 |
| \macro_name c11, c9, \args |
| .elseif (\x) == 186 |
| \macro_name c11, c10, \args |
| .elseif (\x) == 187 |
| \macro_name c11, c11, \args |
| .elseif (\x) == 188 |
| \macro_name c11, c12, \args |
| .elseif (\x) == 189 |
| \macro_name c11, c13, \args |
| .elseif (\x) == 190 |
| \macro_name c11, c14, \args |
| .elseif (\x) == 191 |
| \macro_name c11, c15, \args |
| .elseif (\x) == 192 |
| \macro_name c12, c0, \args |
| .elseif (\x) == 193 |
| \macro_name c12, c1, \args |
| .elseif (\x) == 194 |
| \macro_name c12, c2, \args |
| .elseif (\x) == 195 |
| \macro_name c12, c3, \args |
| .elseif (\x) == 196 |
| \macro_name c12, c4, \args |
| .elseif (\x) == 197 |
| \macro_name c12, c5, \args |
| .elseif (\x) == 198 |
| \macro_name c12, c6, \args |
| .elseif (\x) == 199 |
| \macro_name c12, c7, \args |
| .elseif (\x) == 200 |
| \macro_name c12, c8, \args |
| .elseif (\x) == 201 |
| \macro_name c12, c9, \args |
| .elseif (\x) == 202 |
| \macro_name c12, c10, \args |
| .elseif (\x) == 203 |
| \macro_name c12, c11, \args |
| .elseif (\x) == 204 |
| \macro_name c12, c12, \args |
| .elseif (\x) == 205 |
| \macro_name c12, c13, \args |
| .elseif (\x) == 206 |
| \macro_name c12, c14, \args |
| .elseif (\x) == 207 |
| \macro_name c12, c15, \args |
| .elseif (\x) == 208 |
| \macro_name c13, c0, \args |
| .elseif (\x) == 209 |
| \macro_name c13, c1, \args |
| .elseif (\x) == 210 |
| \macro_name c13, c2, \args |
| .elseif (\x) == 211 |
| \macro_name c13, c3, \args |
| .elseif (\x) == 212 |
| \macro_name c13, c4, \args |
| .elseif (\x) == 213 |
| \macro_name c13, c5, \args |
| .elseif (\x) == 214 |
| \macro_name c13, c6, \args |
| .elseif (\x) == 215 |
| \macro_name c13, c7, \args |
| .elseif (\x) == 216 |
| \macro_name c13, c8, \args |
| .elseif (\x) == 217 |
| \macro_name c13, c9, \args |
| .elseif (\x) == 218 |
| \macro_name c13, c10, \args |
| .elseif (\x) == 219 |
| \macro_name c13, c11, \args |
| .elseif (\x) == 220 |
| \macro_name c13, c12, \args |
| .elseif (\x) == 221 |
| \macro_name c13, c13, \args |
| .elseif (\x) == 222 |
| \macro_name c13, c14, \args |
| .elseif (\x) == 223 |
| \macro_name c13, c15, \args |
| .elseif (\x) == 224 |
| \macro_name c14, c0, \args |
| .elseif (\x) == 225 |
| \macro_name c14, c1, \args |
| .elseif (\x) == 226 |
| \macro_name c14, c2, \args |
| .elseif (\x) == 227 |
| \macro_name c14, c3, \args |
| .elseif (\x) == 228 |
| \macro_name c14, c4, \args |
| .elseif (\x) == 229 |
| \macro_name c14, c5, \args |
| .elseif (\x) == 230 |
| \macro_name c14, c6, \args |
| .elseif (\x) == 231 |
| \macro_name c14, c7, \args |
| .elseif (\x) == 232 |
| \macro_name c14, c8, \args |
| .elseif (\x) == 233 |
| \macro_name c14, c9, \args |
| .elseif (\x) == 234 |
| \macro_name c14, c10, \args |
| .elseif (\x) == 235 |
| \macro_name c14, c11, \args |
| .elseif (\x) == 236 |
| \macro_name c14, c12, \args |
| .elseif (\x) == 237 |
| \macro_name c14, c13, \args |
| .elseif (\x) == 238 |
| \macro_name c14, c14, \args |
| .elseif (\x) == 239 |
| \macro_name c14, c15, \args |
| .elseif (\x) == 240 |
| \macro_name c15, c0, \args |
| .elseif (\x) == 241 |
| \macro_name c15, c1, \args |
| .elseif (\x) == 242 |
| \macro_name c15, c2, \args |
| .elseif (\x) == 243 |
| \macro_name c15, c3, \args |
| .elseif (\x) == 244 |
| \macro_name c15, c4, \args |
| .elseif (\x) == 245 |
| \macro_name c15, c5, \args |
| .elseif (\x) == 246 |
| \macro_name c15, c6, \args |
| .elseif (\x) == 247 |
| \macro_name c15, c7, \args |
| .elseif (\x) == 248 |
| \macro_name c15, c8, \args |
| .elseif (\x) == 249 |
| \macro_name c15, c9, \args |
| .elseif (\x) == 250 |
| \macro_name c15, c10, \args |
| .elseif (\x) == 251 |
| \macro_name c15, c11, \args |
| .elseif (\x) == 252 |
| \macro_name c15, c12, \args |
| .elseif (\x) == 253 |
| \macro_name c15, c13, \args |
| .elseif (\x) == 254 |
| \macro_name c15, c14, \args |
| .elseif (\x) == 255 |
| \macro_name c15, c15, \args |
| .else |
| .error "Value outside of range 0-255" |
| .endif |
| .endm |
| |
| // Directly write 8-bit constant expression cnt to the sequence counter. |
| .macro rcp_count_set_impl h, l |
| mcr p7, #4, r0, \h , \l , #0 |
| .endm |
| .macro rcp_count_set cnt |
| rcp_switch_u8_to_ch_cl rcp_count_set_impl, \cnt |
| .endm |
| |
| .macro rcp_count_set_nodelay_impl h, l |
| mcr2 p7, #4, r0, \h , \l , #0 |
| .endm |
| .macro rcp_count_set_nodelay cnt |
| rcp_switch_u8_to_ch_cl rcp_count_set_nodelay_impl, \cnt |
| .endm |
| |
| // Check 8-bit constant expression cnt against the sequence counter, then |
| // increment the counter. |
| .macro rcp_count_check_impl h, l |
| mcr p7, #5, r0, \h, \l, #1 |
| .endm |
| .macro rcp_count_check cnt |
| rcp_switch_u8_to_ch_cl rcp_count_check_impl, \cnt |
| .endm |
| |
| .macro rcp_count_check_nodelay_impl h, l |
| mcr2 p7, #5, r0, \h, \l, #1 |
| .endm |
| .macro rcp_count_check_nodelay cnt |
| rcp_switch_u8_to_ch_cl rcp_count_check_nodelay_impl, \cnt |
| .endm |
| |
| // Get a 32-bit canary value. `tag` must be a constant expression. |
| .macro rcp_canary_get_impl h, l, x |
| mrc p7, #0, \x, \h, \l, #1 |
| .endm |
| |
| .macro rcp_canary_get x, tag |
| rcp_switch_u8_to_ch_cl rcp_canary_get_impl \tag, \x |
| .endm |
| |
| // Get a 32-bit canary value. `tag` must be a constant expression. |
| .macro rcp_canary_get_nodelay_impl h, l, x |
| mrc2 p7, #0, \x, \h, \l, #1 |
| .endm |
| |
| .macro rcp_canary_get_nodelay x, tag |
| rcp_switch_u8_to_ch_cl rcp_canary_get_nodelay_impl \tag, \x |
| .endm |
| |
| // Assert that canary matches result of rcp_canary_get with the same tags: |
| .macro rcp_canary_check_impl h, l, x |
| mcr p7, #0, \x, \h, \l, #1 |
| .endm |
| |
| .macro rcp_canary_check x, tag |
| rcp_switch_u8_to_ch_cl rcp_canary_check_impl \tag, \x |
| .endm |
| |
| .macro rcp_canary_check_nodelay_impl h, l, x |
| mcr2 p7, #0, \x, \h, \l, #1 |
| .endm |
| |
| .macro rcp_canary_check_nodelay x, tag |
| rcp_switch_u8_to_ch_cl rcp_canary_check_nodelay_impl \tag, \x |
| .endm |
| |
| .macro rcp_panic |
| cdp p7, #0, c0, c0, c0, #1 |
| .endm |
| |
| #endif // !__riscv |
| #endif // __ASSEMBLER__ |
| // ---------------------------------------------------------------------------- |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| #endif |
| #endif |