OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [sw/] [example/] [bitmanip_test/] [neorv32_b_extension_intrinsics.h] - Blame information for rev 71

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 63 zero_gravi
// #################################################################################################
2 66 zero_gravi
// # << NEORV32 - Intrinsics + Emulation Functions for the CPU B extension >>                      #
3 63 zero_gravi
// # ********************************************************************************************* #
4
// # The intrinsics provided by this library allow to use the hardware bit manipulation unit of    #
5 66 zero_gravi
// # the RISC-V B CPU extension without the need for support by the compiler.                      #
6 63 zero_gravi
// # ********************************************************************************************* #
7
// # BSD 3-Clause License                                                                          #
8
// #                                                                                               #
9 71 zero_gravi
// # Copyright (c) 2022, Stephan Nolting. All rights reserved.                                     #
10 63 zero_gravi
// #                                                                                               #
11
// # Redistribution and use in source and binary forms, with or without modification, are          #
12
// # permitted provided that the following conditions are met:                                     #
13
// #                                                                                               #
14
// # 1. Redistributions of source code must retain the above copyright notice, this list of        #
15
// #    conditions and the following disclaimer.                                                   #
16
// #                                                                                               #
17
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
18
// #    conditions and the following disclaimer in the documentation and/or other materials        #
19
// #    provided with the distribution.                                                            #
20
// #                                                                                               #
21
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
22
// #    endorse or promote products derived from this software without specific prior written      #
23
// #    permission.                                                                                #
24
// #                                                                                               #
25
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
26
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
27
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
28
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
29
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
30
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
31
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
32
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
33
// # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
34
// # ********************************************************************************************* #
35
// # The NEORV32 Processor - https://github.com/stnolting/neorv32              (c) Stephan Nolting #
36
// #################################################################################################
37
 
38
 
39
/**********************************************************************//**
40
 * @file bitmanip_test/neorv32_b_extension_intrinsics.h
41
 * @author Stephan Nolting
42 66 zero_gravi
 * @brief "Intrinsic" library for the NEORV32 bit manipulation B extension.
43 63 zero_gravi
 * Also provides emulation functions for all intrinsics (functionality re-built in pure software).
44
 *
45 66 zero_gravi
 * @warning This library is just a temporary fall-back until the B extension is supported by the upstream RISC-V GCC port.
46 63 zero_gravi
 **************************************************************************/
47
 
48
#ifndef neorv32_b_extension_intrinsics_h
49
#define neorv32_b_extension_intrinsics_h
50
 
51
 
52
// ################################################################################################
53
// "Intrinsics"
54
// ################################################################################################
55
 
56
 
57 66 zero_gravi
// ================================================================================================
58 63 zero_gravi
// Zbb - Base instructions
59 66 zero_gravi
// ================================================================================================
60 63 zero_gravi
 
61
/**********************************************************************//**
62
 * Intrinsic: Bit manipulation CLZ (count leading zeros) [B.Zbb]
63
 *
64 71 zero_gravi
 * @param[in] rs1 Source operand 1.
65 63 zero_gravi
 * @return Number of leading zeros in source operand.
66
 **************************************************************************/
67
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_clz(uint32_t rs1) {
68
 
69 71 zero_gravi
  return CUSTOM_INSTR_R1_TYPE(0b0110000, 0b00000, rs1, 0b001, 0b0010011);
70 63 zero_gravi
}
71
 
72
 
73
/**********************************************************************//**
74
 * Intrinsic: Bit manipulation CTZ (count trailing zeros) [B.Zbb]
75
 *
76 71 zero_gravi
 * @param[in] rs1 Source operand 1.
77 63 zero_gravi
 * @return Number of trailing zeros in source operand.
78
 **************************************************************************/
79
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_ctz(uint32_t rs1) {
80
 
81 71 zero_gravi
  return CUSTOM_INSTR_R1_TYPE(0b0110000, 0b00001, rs1, 0b001, 0b0010011);
82 63 zero_gravi
}
83
 
84
 
85
/**********************************************************************//**
86
 * Intrinsic: Bit manipulation CPOP (count set bits) [B.Zbb]
87
 *
88 71 zero_gravi
 * @param[in] rs1 Source operand 1.
89 63 zero_gravi
 * @return Number of set bits in source operand.
90
 **************************************************************************/
91
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_cpop(uint32_t rs1) {
92
 
93 71 zero_gravi
  return CUSTOM_INSTR_R1_TYPE(0b0110000, 0b00010, rs1, 0b001, 0b0010011);
94 63 zero_gravi
}
95
 
96
 
97
/**********************************************************************//**
98
 * Intrinsic: Bit manipulation SEXT.B (sign-extend byte) [B.Zbb]
99
 *
100 71 zero_gravi
 * @param[in] rs1 Source operand 1.
101 63 zero_gravi
 * @return Sign extended byte (operand(7:0)).
102
 **************************************************************************/
103
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_sextb(uint32_t rs1) {
104
 
105 71 zero_gravi
  return CUSTOM_INSTR_R1_TYPE(0b0110000, 0b00100, rs1, 0b001, 0b0010011);
106 63 zero_gravi
}
107
 
108
 
109
/**********************************************************************//**
110
 * Intrinsic: Bit manipulation SEXT.H (sign-extend half-word) [B.Zbb]
111
 *
112 71 zero_gravi
 * @param[in] rs1 Source operand 1.
113 63 zero_gravi
 * @return Sign-extended half-word (operand(15:0)).
114
 **************************************************************************/
115
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_sexth(uint32_t rs1) {
116
 
117 71 zero_gravi
  return CUSTOM_INSTR_R1_TYPE(0b0110000, 0b00101, rs1, 0b001, 0b0010011);
118 63 zero_gravi
}
119
 
120
 
121
/**********************************************************************//**
122
 * Intrinsic: Bit manipulation ZEXT.H (zero-extend half-word) [B.Zbb]
123
 *
124 71 zero_gravi
 * @param[in] rs1 Source operand 1.
125 63 zero_gravi
 * @return Zero-extended half-word (operand(15:0)).
126
 **************************************************************************/
127
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_zexth(uint32_t rs1) {
128
 
129 71 zero_gravi
  return CUSTOM_INSTR_R1_TYPE(0b0000100, 0b00000, rs1, 0b100, 0b0110011);
130 63 zero_gravi
}
131
 
132
 
133
/**********************************************************************//**
134
 * Intrinsic: Bit manipulation MIN (select signed minimum) [B.Zbb]
135
 *
136 71 zero_gravi
 * @param[in] rs1 Source operand 1.
137
 * @param[in] rs2 Source operand 2.
138 63 zero_gravi
 * @return Signed minimum.
139
 **************************************************************************/
140
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_min(uint32_t rs1, uint32_t rs2) {
141
 
142 71 zero_gravi
  return CUSTOM_INSTR_R2_TYPE(0b0000101, rs2, rs1, 0b100, 0b0110011);
143 63 zero_gravi
}
144
 
145
 
146
/**********************************************************************//**
147
 * Intrinsic: Bit manipulation MINU (select unsigned minimum) [B.Zbb]
148
 *
149 71 zero_gravi
 * @param[in] rs1 Source operand 1.
150
 * @param[in] rs2 Source operand 2.
151 63 zero_gravi
 * @return Unsigned minimum.
152
 **************************************************************************/
153
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_minu(uint32_t rs1, uint32_t rs2) {
154
 
155 71 zero_gravi
  return CUSTOM_INSTR_R2_TYPE(0b0000101, rs2, rs1, 0b101, 0b0110011);
156 63 zero_gravi
}
157
 
158
 
159
/**********************************************************************//**
160
 * Intrinsic: Bit manipulation MAX (select signed maximum) [B.Zbb]
161
 *
162 71 zero_gravi
 * @param[in] rs1 Source operand 1.
163
 * @param[in] rs2 Source operand 2.
164 63 zero_gravi
 * @return Signed maximum.
165
 **************************************************************************/
166
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_max(uint32_t rs1, uint32_t rs2) {
167
 
168 71 zero_gravi
  return CUSTOM_INSTR_R2_TYPE(0b0000101, rs2, rs1, 0b110, 0b0110011);
169 63 zero_gravi
}
170
 
171
 
172
/**********************************************************************//**
173
 * Intrinsic: Bit manipulation MAXU (select unsigned maximum) [B.Zbb]
174
 *
175 71 zero_gravi
 * @param[in] rs1 Source operand 1.
176
 * @param[in] rs2 Source operand 2.
177 63 zero_gravi
 * @return Unsigned maximum.
178
 **************************************************************************/
179
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_maxu(uint32_t rs1, uint32_t rs2) {
180
 
181 71 zero_gravi
  return CUSTOM_INSTR_R2_TYPE(0b0000101, rs2, rs1, 0b111, 0b0110011);
182 63 zero_gravi
}
183
 
184
 
185
/**********************************************************************//**
186
 * Intrinsic: Bit manipulation ANDN (logical and-negate) [B.Zbb]
187
 *
188 71 zero_gravi
 * @param[in] rs1 Source operand 1.
189
 * @param[in] rs2 Source operand 2.
190 63 zero_gravi
 * @return Operand 1 AND NOT operand 2.
191
 **************************************************************************/
192
inline inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_andn(uint32_t rs1, uint32_t rs2) {
193
 
194 71 zero_gravi
  return CUSTOM_INSTR_R2_TYPE(0b0100000, rs2, rs1, 0b111, 0b0110011);
195 63 zero_gravi
}
196
 
197
 
198
/**********************************************************************//**
199
 * Intrinsic: Bit manipulation ORN (logical or-negate) [B.Zbb]
200
 *
201 71 zero_gravi
 * @param[in] rs1 Source operand 1.
202
 * @param[in] rs2 Source operand 2.
203 63 zero_gravi
 * @return Operand 1 OR NOT operand 2.
204
 **************************************************************************/
205
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_orn(uint32_t rs1, uint32_t rs2) {
206
 
207 71 zero_gravi
  return CUSTOM_INSTR_R2_TYPE(0b0100000, rs2, rs1, 0b110, 0b0110011);
208 63 zero_gravi
}
209
 
210
 
211
/**********************************************************************//**
212
 * Intrinsic: Bit manipulation XNOR (logical xor-negate) [B.Zbb]
213
 *
214 71 zero_gravi
 * @param[in] rs1 Source operand 1.
215
 * @param[in] rs2 Source operand 2.
216 63 zero_gravi
 * @return Operand 1 XOR NOT operand 2.
217
 **************************************************************************/
218
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_xnor(uint32_t rs1, uint32_t rs2) {
219
 
220 71 zero_gravi
  return CUSTOM_INSTR_R2_TYPE(0b0100000, rs2, rs1, 0b100, 0b0110011);
221 63 zero_gravi
}
222
 
223
 
224
/**********************************************************************//**
225
 * Intrinsic: Bit manipulation ROL (rotate-left) [B.Zbb]
226
 *
227 71 zero_gravi
 * @param[in] rs1 Source operand 1.
228
 * @param[in] rs2 Source operand 2.
229 63 zero_gravi
 * @return Operand 1 rotated left by operand_2(4:0) positions.
230
 **************************************************************************/
231
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_rol(uint32_t rs1, uint32_t rs2) {
232
 
233 71 zero_gravi
  return CUSTOM_INSTR_R2_TYPE(0b0110000, rs2, rs1, 0b001, 0b0110011);
234 63 zero_gravi
}
235
 
236
 
237
/**********************************************************************//**
238
 * Intrinsic: Bit manipulation ROR (rotate-right) [B.Zbb]
239
 *
240 71 zero_gravi
 * @param[in] rs1 Source operand 1.
241
 * @param[in] rs2 Source operand 2.
242 63 zero_gravi
 * @return Operand 1 rotated right by operand_2(4:0) positions.
243
 **************************************************************************/
244
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_ror(uint32_t rs1, uint32_t rs2) {
245
 
246 71 zero_gravi
  return CUSTOM_INSTR_R2_TYPE(0b0110000, rs2, rs1, 0b101, 0b0110011);
247 63 zero_gravi
}
248
 
249
 
250
/**********************************************************************//**
251
 * Intrinsic: Bit manipulation RORI (rotate-right) by 20 positions. [B.Zbb]
252
 * @warning Fixed shift amount (20) for now.
253
 *
254 71 zero_gravi
 * @param[in] rs1 Source operand 1.
255 63 zero_gravi
 * @return Operand 1 rotated right by 20 positions.
256
 **************************************************************************/
257
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_rori20(uint32_t rs1) {
258
 
259 71 zero_gravi
  return CUSTOM_INSTR_R1_TYPE(0b0110000, 0b10100, rs1, 0b101, 0b0010011);
260 63 zero_gravi
}
261
 
262
 
263
/**********************************************************************//**
264
 * Intrinsic: Bit manipulation ORC.B (or-combine byte) [B.Zbb]
265
 *
266 71 zero_gravi
 * @param[in] rs1 Source operand 1.
267 63 zero_gravi
 * @return OR-combined bytes of operand 1.
268
 **************************************************************************/
269
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_orcb(uint32_t rs1) {
270
 
271 71 zero_gravi
  return CUSTOM_INSTR_R1_TYPE(0b0010100, 0b00111, rs1, 0b101, 0b0010011);
272 63 zero_gravi
}
273
 
274
 
275
/**********************************************************************//**
276
 * Intrinsic: Bit manipulation REV8 (byte-swap) [B.Zbb]
277
 *
278 71 zero_gravi
 * @param[in] rs1 Source operand 1.
279 63 zero_gravi
 * @return Byte swap of operand 1
280
 **************************************************************************/
281
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_rev8(uint32_t rs1) {
282
 
283 71 zero_gravi
  return CUSTOM_INSTR_R1_TYPE(0b0110100, 0b11000, rs1, 0b101, 0b0010011);
284 63 zero_gravi
}
285
 
286
 
287 66 zero_gravi
// ================================================================================================
288 71 zero_gravi
// Zba - Address-generation instructions
289 66 zero_gravi
// ================================================================================================
290
 
291
/**********************************************************************//**
292
 * Intrinsic: Address generation instructions SH1ADD (add with logical-1-shift) [B.Zba]
293
 *
294 71 zero_gravi
 * @param[in] rs1 Source operand 1.
295
 * @param[in] rs2 Source operand 2.
296 66 zero_gravi
 * @return Operand 2 + (Operand 1 << 1)
297
 **************************************************************************/
298
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_sh1add(uint32_t rs1, uint32_t rs2) {
299
 
300 71 zero_gravi
  return CUSTOM_INSTR_R2_TYPE(0b0010000, rs2, rs1, 0b010, 0b0110011);
301 66 zero_gravi
}
302
 
303
 
304
/**********************************************************************//**
305
 * Intrinsic: Address generation instructions SH2ADD (add with logical-2-shift) [B.Zba]
306
 *
307 71 zero_gravi
 * @param[in] rs1 Source operand 1.
308
 * @param[in] rs2 Source operand 2.
309 66 zero_gravi
 * @return Operand 2 + (Operand 1 << 2)
310
 **************************************************************************/
311
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_sh2add(uint32_t rs1, uint32_t rs2) {
312
 
313 71 zero_gravi
  return CUSTOM_INSTR_R2_TYPE(0b0010000, rs2, rs1, 0b100, 0b0110011);
314 66 zero_gravi
}
315
 
316
/**********************************************************************//**
317
 * Intrinsic: Address generation instructions SH1ADD (add with logical-3-shift) [B.Zba]
318
 *
319 71 zero_gravi
 * @param[in] rs1 Source operand 1.
320
 * @param[in] rs2 Source operand 2.
321 66 zero_gravi
 * @return Operand 2 + (Operand 1 << 3)
322
 **************************************************************************/
323
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_sh3add(uint32_t rs1, uint32_t rs2) {
324
 
325 71 zero_gravi
  return CUSTOM_INSTR_R2_TYPE(0b0010000, rs2, rs1, 0b110, 0b0110011);
326
}
327 66 zero_gravi
 
328
 
329 71 zero_gravi
// ================================================================================================
330
// Zbs - Single-bit instructions
331
// ================================================================================================
332 66 zero_gravi
 
333 71 zero_gravi
 
334
/**********************************************************************//**
335
 * Intrinsic: Bit manipulation BCLR (bit-clear) [B.Zbs]
336
 *
337
 * @param[in] rs1 Source operand 1.
338
 * @param[in] rs2 Source operand 2.
339
 * @return Operand 1 with bit cleared indexed by operand_2(4:0).
340
 **************************************************************************/
341
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_bclr(uint32_t rs1, uint32_t rs2) {
342
 
343
  return CUSTOM_INSTR_R2_TYPE(0b0100100, rs2, rs1, 0b001, 0b0110011);
344 66 zero_gravi
}
345
 
346
 
347 71 zero_gravi
/**********************************************************************//**
348
 * Intrinsic: Bit manipulation BCLRI (bit-clear) by 20 positions. [B.Zbs]
349
 * @warning Fixed shift amount (20) for now.
350
 *
351
 * @param[in] rs1 Source operand 1.
352
 * @return Operand 1 with bit cleared at position 20.
353
 **************************************************************************/
354
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_bclri20(uint32_t rs1) {
355 66 zero_gravi
 
356 71 zero_gravi
  return CUSTOM_INSTR_R1_TYPE(0b0100100, 0b10100, rs1, 0b001, 0b0010011);
357
}
358
 
359
 
360
/**********************************************************************//**
361
 * Intrinsic: Bit manipulation BEXT (bit-extract) [B.Zbs]
362
 *
363
 * @param[in] rs1 Source operand 1.
364
 * @param[in] rs2 Source operand 2.
365
 * @return Extract bit from Operand 1 indexed by operand_2(4:0).
366
 **************************************************************************/
367
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_bext(uint32_t rs1, uint32_t rs2) {
368
 
369
  return CUSTOM_INSTR_R2_TYPE(0b0100100, rs2, rs1, 0b101, 0b0110011);
370
}
371
 
372
 
373
/**********************************************************************//**
374
 * Intrinsic: Bit manipulation BEXTI (bit-extract) by 20 positions. [B.Zbs]
375
 * @warning Fixed shift amount (20) for now.
376
 *
377
 * @param[in] rs1 Source operand 1.
378
 * @return Extract bit from Operand 1 at position 20.
379
 **************************************************************************/
380
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_bexti20(uint32_t rs1) {
381
 
382
  return CUSTOM_INSTR_R1_TYPE(0b0100100, 0b10100, rs1, 0b101, 0b0010011);
383
}
384
 
385
 
386
/**********************************************************************//**
387
 * Intrinsic: Bit manipulation BINV (bit-invert) [B.Zbs]
388
 *
389
 * @param[in] rs1 Source operand 1.
390
 * @param[in] rs2 Source operand 2.
391
 * @return Invert bit from Operand 1 indexed by operand_2(4:0).
392
 **************************************************************************/
393
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_binv(uint32_t rs1, uint32_t rs2) {
394
 
395
  return CUSTOM_INSTR_R2_TYPE(0b0110100, rs2, rs1, 0b001, 0b0110011);
396
}
397
 
398
 
399
/**********************************************************************//**
400
 * Intrinsic: Bit manipulation BINVI (bit-invert) by 20 positions. [B.Zbs]
401
 * @warning Fixed shift amount (20) for now.
402
 *
403
 * @param[in] rs1 Source operand 1.
404
 * @return Invert bit from Operand 1 at position 20.
405
 **************************************************************************/
406
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_binvi20(uint32_t rs1) {
407
 
408
  return CUSTOM_INSTR_R1_TYPE(0b0110100, 0b10100, rs1, 0b001, 0b0010011);
409
}
410
 
411
 
412
/**********************************************************************//**
413
 * Intrinsic: Bit manipulation BSET (bit-set) [B.Zbs]
414
 *
415
 * @param[in] rs1 Source operand 1.
416
 * @param[in] rs2 Source operand 2.
417
 * @return set bit from Operand 1 indexed by operand_2(4:0).
418
 **************************************************************************/
419
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_bset(uint32_t rs1, uint32_t rs2) {
420
 
421
  return CUSTOM_INSTR_R2_TYPE(0b0010100, rs2, rs1, 0b001, 0b0110011);
422
}
423
 
424
 
425
/**********************************************************************//**
426
 * Intrinsic: Bit manipulation BSETI (bit-set) by 20 positions. [B.Zbs]
427
 * @warning Fixed shift amount (20) for now.
428
 *
429
 * @param[in] rs1 Source operand 1.
430
 * @return Set bit from Operand 1 at position 20.
431
 **************************************************************************/
432
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_bseti20(uint32_t rs1) {
433
 
434
  return CUSTOM_INSTR_R1_TYPE(0b0010100, 0b10100, rs1, 0b001, 0b0010011);
435
}
436
 
437
 
438
// ================================================================================================
439
// Zbc - Carry-less multiplication instructions
440
// ================================================================================================
441
 
442
 
443
/**********************************************************************//**
444
 * Intrinsic: Bit manipulation CLMUL (carry-less multiplication, low-part) [B.Zbc]
445
 *
446
 * @param[in] rs1 Source operand 1.
447
 * @param[in] rs2 Source operand 2.
448
 * @return Carry-less product, low part.
449
 **************************************************************************/
450
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_clmul(uint32_t rs1, uint32_t rs2) {
451
 
452
  return CUSTOM_INSTR_R2_TYPE(0b0000101, rs2, rs1, 0b001, 0b0110011);
453
}
454
 
455
 
456
/**********************************************************************//**
457
 * Intrinsic: Bit manipulation CLMULH (carry-less multiplication, high-part) [B.Zbc]
458
 *
459
 * @param[in] rs1 Source operand 1.
460
 * @param[in] rs2 Source operand 2.
461
 * @return Carry-less product, high part.
462
 **************************************************************************/
463
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_clmulh(uint32_t rs1, uint32_t rs2) {
464
 
465
  return CUSTOM_INSTR_R2_TYPE(0b0000101, rs2, rs1, 0b011, 0b0110011);
466
}
467
 
468
 
469
/**********************************************************************//**
470
 * Intrinsic: Bit manipulation CLMULR (carry-less multiplication, reversed) [B.Zbc]
471
 *
472
 * @param[in] rs1 Source operand 1.
473
 * @param[in] rs2 Source operand 2.
474
 * @return Carry-less product, low part, reversed.
475
 **************************************************************************/
476
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_clmulr(uint32_t rs1, uint32_t rs2) {
477
 
478
  return CUSTOM_INSTR_R2_TYPE(0b0000101, rs1, rs2, 0b010, 0b0110011);
479
}
480
 
481
 
482 63 zero_gravi
// ################################################################################################
483
// Emulation functions
484
// ################################################################################################
485
 
486
 
487 66 zero_gravi
// ================================================================================================
488 63 zero_gravi
// Zbb - Base instructions
489 66 zero_gravi
// ================================================================================================
490 63 zero_gravi
 
491
 
492
/**********************************************************************//**
493
 * Intrinsic: Bit manipulation CLZ (count leading zeros) [emulation]
494
 *
495 71 zero_gravi
 * @param[in] rs1 Source operand 1.
496 63 zero_gravi
 * @return Number of leading zeros in source operand.
497
 **************************************************************************/
498
uint32_t riscv_emulate_clz(uint32_t rs1) {
499
 
500
  uint32_t sreg = rs1;
501
  uint32_t cnt = 0;
502
 
503
  while(1) {
504
    if (sreg & 0x80000000UL) {
505
      break;
506
    }
507
    else {
508
      sreg <<= 1;
509
      cnt++;
510
    }
511
  }
512
 
513
  return cnt;
514
}
515
 
516
 
517
/**********************************************************************//**
518
 * Intrinsic: Bit manipulation CTZ (count trailing zeros) [emulation]
519
 *
520 71 zero_gravi
 * @param[in] rs1 Source operand 1.
521 63 zero_gravi
 * @return Number of trailing zeros in source operand.
522
 **************************************************************************/
523
uint32_t riscv_emulate_ctz(uint32_t rs1) {
524
 
525
  uint32_t sreg = rs1;
526
  uint32_t cnt = 0;
527
 
528
  while(1) {
529
    if (sreg & 1) {
530
      break;
531
    }
532
    else {
533
      sreg >>= 1;
534
      cnt++;
535
    }
536
  }
537
 
538
  return cnt;
539
}
540
 
541
 
542
/**********************************************************************//**
543
 * Intrinsic: Bit manipulation CPOP (population count) [emulation]
544
 *
545 71 zero_gravi
 * @param[in] rs1 Source operand 1.
546 63 zero_gravi
 * @return Number of set bits in source operand.
547
 **************************************************************************/
548
uint32_t riscv_emulate_cpop(uint32_t rs1) {
549
 
550
  uint32_t sreg = rs1;
551
  uint32_t cnt = 0;
552
  int i;
553
 
554
  for (i=0; i<32; i++) {
555
    if (sreg & 1) {
556
      cnt++;
557
    }
558
    sreg >>= 1;
559
  }
560
 
561
  return cnt;
562
}
563
 
564
 
565
/**********************************************************************//**
566
 * Intrinsic: Bit manipulation SEXT.B (sign-extend byte) [emulation]
567
 *
568 71 zero_gravi
 * @param[in] rs1 Source operand 1.
569 63 zero_gravi
 * @return Sign-extended byte (operand(7:0)).
570
 **************************************************************************/
571
uint32_t riscv_emulate_sextb(uint32_t rs1) {
572
 
573
  uint32_t tmp = rs1 & 0xff;
574
 
575
  if (tmp & 0x80) {
576
    tmp |= 0xFFFFFF00UL;
577
  }
578
 
579
  return tmp;
580
}
581
 
582
 
583
/**********************************************************************//**
584
 * Intrinsic: Bit manipulation SEXT.H (sign-extend half-word) [emulation]
585
 *
586 71 zero_gravi
 * @param[in] rs1 Source operand 1.
587 63 zero_gravi
 * @return Sign-extended half-word (operand(15:0)).
588
 **************************************************************************/
589
uint32_t riscv_emulate_sexth(uint32_t rs1) {
590
 
591
  uint32_t tmp = rs1 & 0xffff;
592
 
593
  if (tmp & 0x8000) {
594
    tmp |= 0xFFFF0000UL;
595
  }
596
 
597
  return tmp;
598
}
599
 
600
 
601
/**********************************************************************//**
602
 * Intrinsic: Bit manipulation ZEXT.H (zero-extend half-word) [emulation]
603
 *
604 71 zero_gravi
 * @param[in] rs1 Source operand 1.
605 63 zero_gravi
 * @return Zero-extended half-word (operand(15:0)).
606
 **************************************************************************/
607
uint32_t riscv_emulate_zexth(uint32_t rs1) {
608
 
609
  return rs1 & 0x0000FFFFUL;
610
}
611
 
612
 
613
/**********************************************************************//**
614
 * Intrinsic: Bit manipulation MIN (select signed minimum) [emulation]
615
 *
616 71 zero_gravi
 * @param[in] rs1 Source operand 1.
617
 * @param[in] rs2 Source operand 1.
618 63 zero_gravi
 * @return Signed minimum.
619
 **************************************************************************/
620
uint32_t riscv_emulate_min(uint32_t rs1, uint32_t rs2) {
621
 
622
  int32_t s_opa = (int32_t)rs1;
623
  int32_t s_opb = (int32_t)rs2;
624
 
625
  if (s_opa < s_opb) {
626
    return rs1;
627
  }
628
  else {
629
    return rs2;
630
  }
631
}
632
 
633
 
634
/**********************************************************************//**
635
 * Intrinsic: Bit manipulation MINU (select unsigned minimum) [emulation]
636
 *
637 71 zero_gravi
 * @param[in] rs1 Source operand 1.
638
 * @param[in] rs2 Source operand 1.
639 63 zero_gravi
 * @return Unsigned minimum.
640
 **************************************************************************/
641
uint32_t riscv_emulate_minu(uint32_t rs1, uint32_t rs2) {
642
 
643
  if (rs1 < rs2) {
644
    return rs1;
645
  }
646
  else {
647
    return rs2;
648
  }
649
}
650
 
651
 
652
/**********************************************************************//**
653
 * Intrinsic: Bit manipulation MAX (select signed maximum) [emulation]
654
 *
655 71 zero_gravi
 * @param[in] rs1 Source operand 1.
656
 * @param[in] rs2 Source operand 1.
657 63 zero_gravi
 * @return Signed maximum.
658
 **************************************************************************/
659
uint32_t riscv_emulate_max(uint32_t rs1, uint32_t rs2) {
660
 
661
  int32_t s_opa = (int32_t)rs1;
662
  int32_t s_opb = (int32_t)rs2;
663
 
664
  if (s_opa < s_opb) {
665
    return rs2;
666
  }
667
  else {
668
    return rs1;
669
  }
670
}
671
 
672
 
673
/**********************************************************************//**
674
 * Intrinsic: Bit manipulation MAXU (select unsigned maximum) [emulation]
675
 *
676 71 zero_gravi
 * @param[in] rs1 Source operand 1.
677
 * @param[in] rs2 Source operand 1.
678 63 zero_gravi
 * @return Unsigned maximum.
679
 **************************************************************************/
680
uint32_t riscv_emulate_maxu(uint32_t rs1, uint32_t rs2) {
681
 
682
  if (rs1 < rs2) {
683
    return rs2;
684
  }
685
  else {
686
    return rs1;
687
  }
688
}
689
 
690
 
691
/**********************************************************************//**
692
 * Intrinsic: Bit manipulation ANDN (logical and-negate) [emulation]
693
 *
694 71 zero_gravi
 * @param[in] rs1 Source operand 1.
695
 * @param[in] rs2 Source operand 1.
696 63 zero_gravi
 * @return Operand 1 AND NOT operand 2.
697
 **************************************************************************/
698
uint32_t riscv_emulate_andn(uint32_t rs1, uint32_t rs2) {
699
 
700
  return rs1 & (~rs2);
701
}
702
 
703
 
704
/**********************************************************************//**
705
 * Intrinsic: Bit manipulation ORN (logical or-negate) [emulation]
706
 *
707 71 zero_gravi
 * @param[in] rs1 Source operand 1.
708
 * @param[in] rs2 Source operand 1.
709 63 zero_gravi
 * @return Operand 1 OR NOT operand 2.
710
 **************************************************************************/
711
uint32_t riscv_emulate_orn(uint32_t rs1, uint32_t rs2) {
712
 
713
  return rs1 | (~rs2);
714
}
715
 
716
 
717
/**********************************************************************//**
718
 * Intrinsic: Bit manipulation XNOR (logical xor-negate) [emulation]
719
 *
720 71 zero_gravi
 * @param[in] rs1 Source operand 1.
721
 * @param[in] rs2 Source operand 1.
722 63 zero_gravi
 * @return Operand 1 XOR NOT operand 2.
723
 **************************************************************************/
724
uint32_t riscv_emulate_xnor(uint32_t rs1, uint32_t rs2) {
725
 
726
  return rs1 ^ (~rs2);
727
}
728
 
729
 
730
/**********************************************************************//**
731
 * Intrinsic: Bit manipulation ROL (rotate-left) [emulation]
732
 *
733 71 zero_gravi
 * @param[in] rs1 Source operand 1.
734
 * @param[in] rs2 Source operand 1.
735 63 zero_gravi
 * @return Operand 1 rotated left by operand_2(4:0) positions.
736
 **************************************************************************/
737
uint32_t riscv_emulate_rol(uint32_t rs1, uint32_t rs2) {
738
 
739
  uint32_t shamt = rs2 & 0x1f;
740
 
741
  uint32_t tmp_a = rs1 << shamt;
742
  uint32_t tmp_b = rs1 >> (32-shamt);
743
 
744
  return tmp_a | tmp_b;
745
}
746
 
747
 
748
/**********************************************************************//**
749
 * Intrinsic: Bit manipulation ROR (rotate-right) [emulation]
750
 *
751 71 zero_gravi
 * @param[in] rs1 Source operand 1.
752
 * @param[in] rs2 Source operand 1.
753 63 zero_gravi
 * @return Operand 1 rotated right by operand_2(4:0) positions.
754
 **************************************************************************/
755
uint32_t riscv_emulate_ror(uint32_t rs1, uint32_t rs2) {
756
 
757
  uint32_t shamt = rs2 & 0x1f;
758
 
759
  uint32_t tmp_a = rs1 >> shamt;
760
  uint32_t tmp_b = rs1 << (32-shamt);
761
 
762
  return tmp_a | tmp_b;
763
}
764
 
765
 
766
/**********************************************************************//**
767
 * Intrinsic: Bit manipulation REV8 (byte swap) [emulation]
768
 *
769 71 zero_gravi
 * @param[in] rs1 Source operand 1.
770 63 zero_gravi
 * @return Operand 1 byte swapped.
771
 **************************************************************************/
772
uint32_t riscv_emulate_rev8(uint32_t rs1) {
773
 
774
  uint32_t tmp_a = (rs1 & 0x000000ffUL) << 24;
775
  uint32_t tmp_b = (rs1 & 0x0000ff00UL) << 8;
776
  uint32_t tmp_c = (rs1 & 0x00ff0000UL) >> 8;
777
  uint32_t tmp_d = (rs1 & 0xff000000UL) >> 24;
778
 
779
  return tmp_a | tmp_b | tmp_c | tmp_d;
780
}
781
 
782
 
783
/**********************************************************************//**
784
 * Intrinsic: Bit manipulation ORCB (or-combine bytes) [emulation]
785
 *
786 71 zero_gravi
 * @param[in] rs1 Source operand 1.
787 63 zero_gravi
 * @return OR-combined bytes of operand 1.
788
 **************************************************************************/
789
uint32_t riscv_emulate_orcb(uint32_t rs1) {
790
 
791
  uint32_t tmp = 0;
792
 
793
  if (rs1 & 0x000000ffUL) {
794
    tmp |= 0x000000ffUL;
795
  }
796
  if (rs1 & 0x0000ff00UL) {
797
    tmp |= 0x0000ff00UL;
798
  }
799
  if (rs1 & 0x00ff0000UL) {
800
    tmp |= 0x00ff0000UL;
801
  }
802
  if (rs1 & 0xff000000UL) {
803
    tmp |= 0xff000000UL;
804
  }
805
 
806
  return tmp;
807
}
808
 
809
 
810 66 zero_gravi
// ================================================================================================
811
// Zba - Address generation instructions
812
// ================================================================================================
813
 
814
 
815
/**********************************************************************//**
816
 * Intrinsic: Address generation instructions SH1ADD (add with logical-1-shift) [emulation]
817
 *
818 71 zero_gravi
 * @param[in] rs1 Source operand 1.
819
 * @param[in] rs2 Source operand 1.
820 66 zero_gravi
 * @return Operand 2 + (Operand 1 << 1)
821
 **************************************************************************/
822
uint32_t riscv_emulate_sh1add(uint32_t rs1, uint32_t rs2) {
823
 
824
  return rs2 + (rs1 << 1);
825
}
826
 
827
 
828
/**********************************************************************//**
829
 * Intrinsic: Address generation instructions SH2ADD (add with logical-2-shift) [emulation]
830
 *
831 71 zero_gravi
 * @param[in] rs1 Source operand 1.
832
 * @param[in] rs2 Source operand 1.
833 66 zero_gravi
 * @return Operand 2 + (Operand 1 << 2)
834
 **************************************************************************/
835
uint32_t riscv_emulate_sh2add(uint32_t rs1, uint32_t rs2) {
836
 
837
  return rs2 + (rs1 << 2);
838
}
839
 
840
 
841
/**********************************************************************//**
842
 * Intrinsic: Address generation instructions SH3ADD (add with logical-3-shift) [emulation]
843
 *
844 71 zero_gravi
 * @param[in] rs1 Source operand 1.
845
 * @param[in] rs2 Source operand 1.
846 66 zero_gravi
 * @return Operand 2 + (Operand 1 << 3)
847
 **************************************************************************/
848
uint32_t riscv_emulate_sh3add(uint32_t rs1, uint32_t rs2) {
849
 
850
  return rs2 + (rs1 << 3);
851
}
852
 
853
 
854 71 zero_gravi
// ================================================================================================
855
// Zbs - Single-bit instructions
856
// ================================================================================================
857
 
858
 
859
/**********************************************************************//**
860
 * Intrinsic: Bit manipulation BCLR (bit-clear) [emulation]
861
 *
862
 * @param[in] rs1 Source operand 1.
863
 * @param[in] rs2 Source operand 1.
864
 * @return Operand 1 with cleared bit indexed by operand_2(4:0).
865
 **************************************************************************/
866
uint32_t riscv_emulate_bclr(uint32_t rs1, uint32_t rs2) {
867
 
868
  uint32_t shamt = rs2 & 0x1f;
869
  uint32_t tmp = 1 << shamt;
870
 
871
  return rs1 & (~tmp);
872
}
873
 
874
 
875
/**********************************************************************//**
876
 * Intrinsic: Bit manipulation BEXT (bit-extract) [emulation]
877
 *
878
 * @param[in] rs1 Source operand 1.
879
 * @param[in] rs2 Source operand 1.
880
 * @return Extract bit from operand 1 indexed by operand_2(4:0).
881
 **************************************************************************/
882
uint32_t riscv_emulate_bext(uint32_t rs1, uint32_t rs2) {
883
 
884
  uint32_t shamt = rs2 & 0x1f;
885
  uint32_t tmp = rs1 >> shamt;
886
 
887
  return tmp & 1;
888
}
889
 
890
 
891
/**********************************************************************//**
892
 * Intrinsic: Bit manipulation BINV (bit-invert) [emulation]
893
 *
894
 * @param[in] rs1 Source operand 1.
895
 * @param[in] rs2 Source operand 1.
896
 * @return Invert bit from operand 1 indexed by operand_2(4:0).
897
 **************************************************************************/
898
uint32_t riscv_emulate_binv(uint32_t rs1, uint32_t rs2) {
899
 
900
  uint32_t shamt = rs2 & 0x1f;
901
  uint32_t tmp = 1 << shamt;
902
 
903
  return rs1 ^ tmp;
904
}
905
 
906
 
907
/**********************************************************************//**
908
 * Intrinsic: Bit manipulation BSET (bit-set) [emulation]
909
 *
910
 * @param[in] rs1 Source operand 1.
911
 * @param[in] rs2 Source operand 1.
912
 * @return Set bit from operand 1 indexed by operand_2(4:0).
913
 **************************************************************************/
914
uint32_t riscv_emulate_bset(uint32_t rs1, uint32_t rs2) {
915
 
916
  uint32_t shamt = rs2 & 0x1f;
917
  uint32_t tmp = 1 << shamt;
918
 
919
  return rs1 | tmp;
920
}
921
 
922
 
923
// ================================================================================================
924
// Zbc - Carry-less multiplication instructions
925
// ================================================================================================
926
 
927
 
928
/**********************************************************************//**
929
 * Intrinsic: Bit manipulation CLMUL (carry-less multiply, low-part) [emulation]
930
 *
931
 * @param[in] rs1 Source operand 1.
932
 * @param[in] rs2 Source operand 1.
933
 * @return Carry-less multiplication product, low part
934
 **************************************************************************/
935
uint32_t riscv_emulate_clmul(uint32_t rs1, uint32_t rs2) {
936
 
937
  uint32_t i;
938
  uint64_t tmp;
939
  union {
940
    uint64_t uint64;
941
    uint32_t uint32[sizeof(uint64_t)/sizeof(uint32_t)];
942
  } res;
943
 
944
  res.uint64 = 0;
945
  for (i=0; i<32; i++) {
946
    if ((rs2 >> i) & 1) {
947
      tmp = (uint64_t)rs1;
948
      tmp = tmp << i;
949
      res.uint64 = res.uint64 ^ tmp;
950
    }
951
  }
952
 
953
  return res.uint32[0];
954
}
955
 
956
 
957
/**********************************************************************//**
958
 * Intrinsic: Bit manipulation CLMULH (carry-less multiply, high-part) [emulation]
959
 *
960
 * @param[in] rs1 Source operand 1.
961
 * @param[in] rs2 Source operand 1.
962
 * @return Carry-less multiplication product, high part
963
 **************************************************************************/
964
uint32_t riscv_emulate_clmulh(uint32_t rs1, uint32_t rs2) {
965
 
966
  uint32_t i;
967
  uint64_t tmp;
968
  union {
969
    uint64_t uint64;
970
    uint32_t uint32[sizeof(uint64_t)/sizeof(uint32_t)];
971
  } res;
972
 
973
  res.uint64 = 0;
974
  for (i=0; i<32; i++) {
975
    if ((rs2 >> i) & 1) {
976
      tmp = (uint64_t)rs1;
977
      tmp = tmp << i;
978
      res.uint64 = res.uint64 ^ tmp;
979
    }
980
  }
981
 
982
  return res.uint32[1];
983
}
984
 
985
 
986
/**********************************************************************//**
987
 * Intrinsic: Bit manipulation CLMUR (carry-less multiply, reversed) [emulation]
988
 *
989
 * @param[in] rs1 Source operand 1.
990
 * @param[in] rs2 Source operand 1.
991
 * @return Carry-less multiplication product, low part, reversed
992
 **************************************************************************/
993
uint32_t riscv_emulate_clmulr(uint32_t rs1, uint32_t rs2) {
994
 
995
  uint32_t i;
996
  uint64_t tmp;
997
  union {
998
    uint64_t uint64;
999
    uint32_t uint32[sizeof(uint64_t)/sizeof(uint32_t)];
1000
  } res;
1001
 
1002
  // bit-reversal of input operands
1003
  uint32_t rs1_rev = 0, rs2_rev = 0;
1004
  for (i=0; i<32; i++) {
1005
    rs1_rev <<= 1;
1006
    if ((rs1 >> i) & 1) {
1007
      rs1_rev |= 1;
1008
    }
1009
    rs2_rev <<= 1;
1010
    if ((rs2 >> i) & 1) {
1011
      rs2_rev |= 1;
1012
    }
1013
  }
1014
 
1015
  res.uint64 = 0;
1016
  for (i=0; i<32; i++) {
1017
    if ((rs2_rev >> i) & 1) {
1018
      tmp = (uint64_t)rs1_rev;
1019
      tmp = tmp << i;
1020
      res.uint64 = res.uint64 ^ tmp;
1021
    }
1022
  }
1023
 
1024
  // bit-reversal of result
1025
  uint32_t result = 0;
1026
  for (i=0; i<32; i++) {
1027
    result <<= 1;
1028
    if ((res.uint32[0] >> i) & 1) {
1029
      result |= 1;
1030
    }
1031
  }
1032
 
1033
  return result;
1034
}
1035
 
1036
 
1037 63 zero_gravi
#endif // neorv32_b_extension_intrinsics_h

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.