mirror of
https://github.com/raspberrypi/pico-sdk.git
synced 2025-12-10 07:14:36 +01:00
1008 lines
26 KiB
C
1008 lines
26 KiB
C
/*
|
|
* 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 masks
|
|
#if !PICO_RP2040
|
|
|
|
#define RCP_MASK_TRUE _u(0xa500a500)
|
|
#define RCP_MASK_FALSE _u(0x00c300c3)
|
|
#define RCP_MASK_INTXOR _u(0x96009600)
|
|
|
|
// RCP instructions (these instructions are Arm-only)
|
|
#if HAS_REDUNDANCY_COPROCESSOR
|
|
// ----------------------------------------------------------------------------
|
|
// 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 // HAS_REDUNDANCY_COPROCESSOR
|
|
#endif // !PICO_RP2040
|
|
#endif // __ASSEMBLER__
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
#endif
|
|
#endif
|