blob: b75f182d968b68cb07e0b8214f21ba2bbdfc6b67 [file] [log] [blame]
/*
* 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