1 /*
2  * Copyright (c) 2024 Raspberry Pi Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef _HARDWARE_HAZARD3_INSTRUCTIONS_H
8 #define _HARDWARE_HAZARD3_INSTRUCTIONS_H
9 
10 #include "pico.h"
11 
12 // Get list of supported extensions based on platform:
13 #include "hardware/hazard3/features.h"
14 
15 /** \file hardware/hazard3/instructions.h
16  *  \addtogroup hardware_hazard3
17  *
18  * \brief Intrinsics and asm macros for Hazard3 custom instructions
19  *
20  * The implementation of these intrinsics depends on the feature macros
21  * defined in hardware/hazard3/features.h. When the relevant feature is not
22  * present, the intrinsics fall back on an RV32I equivalent if possible.
23  *
24  */
25 
26 #ifdef __ASSEMBLER__
27 
28 // Assembly language instruction macros for Hazard3 custom instructions
29 
30 // h3.bextm: Extract up to 8 consecutive bits from register rs1, with the
31 // first bit indexed by rs2, and bit count configured by an immediate value.
32 // R-format instruction. Pseudocode:
33 //
34 //     rd = (rs1 >> rs2[4:0]) & ~(-1 << nbits)
35 
36 .macro h3.bextm rd rs1 rs2 nbits
37 .if (\nbits < 1) || (\nbits > 8)
38 .err
39 .endif
40 #ifdef __hazard3_extension_xh3bextm
41     .insn r 0x0b, 0x4, (((\nbits - 1) & 0x7 ) << 1), \rd, \rs1, \rs2
42 #else
43     srl  \rd, \rs1, \rs2
44     andi \rd, \rd, ((1 << \nbits) - 1)
45 #endif
46 .endm
47 
48 // h3.bextmi: Extract up to 8 consecutive bits from register rs1, with the
49 // first bit index and the number of bits both configured by immediate
50 // values. I-format instruction. Pseudocode:
51 //
52 //     rd = (rs1 >> shamt) & ~(-1 << nbits)
53 
54 .macro h3.bextmi rd rs1 shamt nbits
55 .if (\nbits < 1) || (\nbits > 8)
56 .err
57 .endif
58 .if (\shamt < 0) || (\shamt > 31)
59 .err
60 .endif
61 #ifdef __hazard3_extension_xh3bextm
62     .insn i 0x0b, 0x4, \rd, \rs1, (\shamt & 0x1f) | (((\nbits - 1) & 0x7 ) << 6)
63 #else
64     srli \rd, \rs1, \shamt
65     andi \rd, \rd, ((1 << \nbits) - 1)
66 #endif
67 .endm
68 
69 // h3.block: enter an idle state until another processor in the same
70 // multiprocessor complex executes an h3.unblock instruction, or the
71 // processor is interrupted. Fall through immediately if an h3.unblock has
72 // been received since the last execution of an h3.block on this processor.
73 // On RP2350, processors also have their own h3.unblock signals reflected
74 // back to them.
75 
76 .macro h3.block
77 #ifdef __hazard3_extension_xh3power
78     slt x0, x0, x0
79 #else
80     nop
81 #endif
82 .endm
83 
84 // h3.unblock: signal other processors in the same multiprocessor complex to
85 // exit the idle state entered by an h3.block instruction. On RP2350, this
86 // signal is also reflected back to the processor that executed the
87 // h3.unblock, which will cause that processor's next h3.block to fall
88 // through immediately.
89 
90 .macro h3.unblock
91 #ifdef __hazard3_extension_xh3power
92     slt x0, x0, x1
93 #else
94     nop
95 #endif
96 .endm
97 
98 #else // !__ASSEMBLER__
99 
100 // C language instruction macros for Hazard3 custom instructions
101 
102 #ifdef __cplusplus
103 extern "C" {
104 #endif
105 
106 // nbits must be a constant expression
107 #ifdef __hazard3_extension_xh3bextm
108 #define __hazard3_bextm(nbits, rs1, rs2) ({\
109     uint32_t __h3_bextm_rd; \
110     asm (".insn r 0x0b, 0, %3, %0, %1, %2"\
111         : "=r" (__h3_bextm_rd) \
112         : "r" (rs1), "r" (rs2), "i" ((((nbits) - 1) & 0x7) << 1)\
113     ); \
114     __h3_bextm_rd; \
115 })
116 #else
117 #define __hazard3_bextm(nbits, rs1, rs2) (((rs1) >> ((rs2) & 0x1f)) & (0xffu >> (7 - (((nbits) - 1) & 0x7))))
118 #endif
119 
120 // nbits and shamt must be constant expressions
121 #ifdef __hazard3_extension_xh3bextm
122 #define __hazard3_bextmi(nbits, rs1, shamt) ({\
123     uint32_t __h3_bextmi_rd; \
124     asm (".insn i 0x0b, 0x4, %0, %1, %2"\
125         : "=r" (__h3_bextmi_rd) \
126         : "r" (rs1), "i" ((((nbits) - 1) & 0x7) << 6 | ((shamt) & 0x1f)) \
127     ); \
128     __h3_bextmi_rd; \
129 })
130 #else
131 #define __hazard3_bextm(nbits, rs1, rs2) (((rs1) >> ((shamt) & 0x1f)) & (0xffu >> (7 - (((nbits) - 1) & 0x7))))
132 #endif
133 
134 #ifdef __hazard3_extension_xh3power
135 #define __hazard3_block() asm volatile ("slt x0, x0, x0" : : : "memory")
136 #else
137 #define __hazard3_block() do {} while (0)
138 #endif
139 
140 #ifdef __hazard3_extension_xh3power
141 #define __hazard3_unblock() asm volatile ("slt x0, x0, x1" : : : "memory")
142 #else
143 #define __hazard3_unblock() do {} while (0)
144 #endif
145 
146 #ifdef __cplusplus
147 }
148 #endif
149 
150 #endif // !__ASSEMBLER__
151 
152 #endif
153