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 66

Go to most recent revision | 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
// # Copyright (c) 2021, Stephan Nolting. All rights reserved.                                     #
10
// #                                                                                               #
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
 * @param[in] rs1 Source operand 1 (a0).
65
 * @return Number of leading zeros in source operand.
66
 **************************************************************************/
67
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_clz(uint32_t rs1) {
68
 
69
  register uint32_t result __asm__ ("a0");
70
  register uint32_t tmp_a  __asm__ ("a0") = rs1;
71
 
72
  // dummy instruction to prevent GCC "constprop" optimization
73
  asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a));
74
 
75
  // clz a0, a0
76
  CUSTOM_INSTR_R1_TYPE(0b0110000, 0b00000, a0, 0b001, a0, 0b0010011);
77
 
78
  return result;
79
}
80
 
81
 
82
/**********************************************************************//**
83
 * Intrinsic: Bit manipulation CTZ (count trailing zeros) [B.Zbb]
84
 *
85
 * @param[in] rs1 Source operand 1 (a0).
86
 * @return Number of trailing zeros in source operand.
87
 **************************************************************************/
88
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_ctz(uint32_t rs1) {
89
 
90
  register uint32_t result __asm__ ("a0");
91
  register uint32_t tmp_a  __asm__ ("a0") = rs1;
92
 
93
  // dummy instruction to prevent GCC "constprop" optimization
94
  asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a));
95
 
96
  // ctz a0, a0
97
  CUSTOM_INSTR_R1_TYPE(0b0110000, 0b00001, a0, 0b001, a0, 0b0010011);
98
 
99
  return result;
100
}
101
 
102
 
103
/**********************************************************************//**
104
 * Intrinsic: Bit manipulation CPOP (count set bits) [B.Zbb]
105
 *
106
 * @param[in] rs1 Source operand 1 (a0).
107
 * @return Number of set bits in source operand.
108
 **************************************************************************/
109
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_cpop(uint32_t rs1) {
110
 
111
  register uint32_t result __asm__ ("a0");
112
  register uint32_t tmp_a  __asm__ ("a0") = rs1;
113
 
114
  // dummy instruction to prevent GCC "constprop" optimization
115
  asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a));
116
 
117
  // cpop a0, a0
118
  CUSTOM_INSTR_R1_TYPE(0b0110000, 0b00010, a0, 0b001, a0, 0b0010011);
119
 
120
  return result;
121
}
122
 
123
 
124
/**********************************************************************//**
125
 * Intrinsic: Bit manipulation SEXT.B (sign-extend byte) [B.Zbb]
126
 *
127
 * @param[in] rs1 Source operand 1 (a0).
128
 * @return Sign extended byte (operand(7:0)).
129
 **************************************************************************/
130
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_sextb(uint32_t rs1) {
131
 
132
  register uint32_t result __asm__ ("a0");
133
  register uint32_t tmp_a  __asm__ ("a0") = rs1;
134
 
135
  // dummy instruction to prevent GCC "constprop" optimization
136
  asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a));
137
 
138
  // sext.b a0, a0
139
  CUSTOM_INSTR_R1_TYPE(0b0110000, 0b00100, a0, 0b001, a0, 0b0010011);
140
 
141
  return result;
142
}
143
 
144
 
145
/**********************************************************************//**
146
 * Intrinsic: Bit manipulation SEXT.H (sign-extend half-word) [B.Zbb]
147
 *
148
 * @param[in] rs1 Source operand 1 (a0).
149
 * @return Sign-extended half-word (operand(15:0)).
150
 **************************************************************************/
151
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_sexth(uint32_t rs1) {
152
 
153
  register uint32_t result __asm__ ("a0");
154
  register uint32_t tmp_a  __asm__ ("a0") = rs1;
155
 
156
  // dummy instruction to prevent GCC "constprop" optimization
157
  asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a));
158
 
159
  // sext.h a0, a0
160
  CUSTOM_INSTR_R1_TYPE(0b0110000, 0b00101, a0, 0b001, a0, 0b0010011);
161
 
162
  return result;
163
}
164
 
165
 
166
/**********************************************************************//**
167
 * Intrinsic: Bit manipulation ZEXT.H (zero-extend half-word) [B.Zbb]
168
 *
169
 * @param[in] rs1 Source operand 1 (a0).
170
 * @return Zero-extended half-word (operand(15:0)).
171
 **************************************************************************/
172
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_zexth(uint32_t rs1) {
173
 
174
  register uint32_t result __asm__ ("a0");
175
  register uint32_t tmp_a  __asm__ ("a0") = rs1;
176
 
177
  // dummy instruction to prevent GCC "constprop" optimization
178
  asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a));
179
 
180
  // sext.h a0, a0
181
  CUSTOM_INSTR_R1_TYPE(0b0000100, 0b00000, a0, 0b100, a0, 0b0110011);
182
 
183
  return result;
184
}
185
 
186
 
187
/**********************************************************************//**
188
 * Intrinsic: Bit manipulation MIN (select signed minimum) [B.Zbb]
189
 *
190
 * @param[in] rs1 Source operand 1 (a0).
191
 * @param[in] rs2 Source operand 2 (a0).
192
 * @return Signed minimum.
193
 **************************************************************************/
194
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_min(uint32_t rs1, uint32_t rs2) {
195
 
196
  register uint32_t result __asm__ ("a0");
197
  register uint32_t tmp_a  __asm__ ("a0") = rs1;
198
  register uint32_t tmp_b  __asm__ ("a1") = rs2;
199
 
200
  // dummy instruction to prevent GCC "constprop" optimization
201
  asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
202
 
203
  // min a0, a0, a1
204
  CUSTOM_INSTR_R2_TYPE(0b0000101, a1, a0, 0b100, a0, 0b0110011);
205
 
206
  return result;
207
}
208
 
209
 
210
/**********************************************************************//**
211
 * Intrinsic: Bit manipulation MINU (select unsigned minimum) [B.Zbb]
212
 *
213
 * @param[in] rs1 Source operand 1 (a0).
214
 * @param[in] rs2 Source operand 2 (a0).
215
 * @return Unsigned minimum.
216
 **************************************************************************/
217
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_minu(uint32_t rs1, uint32_t rs2) {
218
 
219
  register uint32_t result __asm__ ("a0");
220
  register uint32_t tmp_a  __asm__ ("a0") = rs1;
221
  register uint32_t tmp_b  __asm__ ("a1") = rs2;
222
 
223
  // dummy instruction to prevent GCC "constprop" optimization
224
  asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
225
 
226
  // minu a0, a0, a1
227
  CUSTOM_INSTR_R2_TYPE(0b0000101, a1, a0, 0b101, a0, 0b0110011);
228
 
229
  return result;
230
}
231
 
232
 
233
/**********************************************************************//**
234
 * Intrinsic: Bit manipulation MAX (select signed maximum) [B.Zbb]
235
 *
236
 * @param[in] rs1 Source operand 1 (a0).
237
 * @param[in] rs2 Source operand 2 (a0).
238
 * @return Signed maximum.
239
 **************************************************************************/
240
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_max(uint32_t rs1, uint32_t rs2) {
241
 
242
  register uint32_t result __asm__ ("a0");
243
  register uint32_t tmp_a  __asm__ ("a0") = rs1;
244
  register uint32_t tmp_b  __asm__ ("a1") = rs2;
245
 
246
  // dummy instruction to prevent GCC "constprop" optimization
247
  asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
248
 
249
  // max a0, a0, a1
250
  CUSTOM_INSTR_R2_TYPE(0b0000101, a1, a0, 0b110, a0, 0b0110011);
251
 
252
  return result;
253
}
254
 
255
 
256
/**********************************************************************//**
257
 * Intrinsic: Bit manipulation MAXU (select unsigned maximum) [B.Zbb]
258
 *
259
 * @param[in] rs1 Source operand 1 (a0).
260
 * @param[in] rs2 Source operand 2 (a0).
261
 * @return Unsigned maximum.
262
 **************************************************************************/
263
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_maxu(uint32_t rs1, uint32_t rs2) {
264
 
265
  register uint32_t result __asm__ ("a0");
266
  register uint32_t tmp_a  __asm__ ("a0") = rs1;
267
  register uint32_t tmp_b  __asm__ ("a1") = rs2;
268
 
269
  // dummy instruction to prevent GCC "constprop" optimization
270
  asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
271
 
272
  // maxu a0, a0, a1
273
  CUSTOM_INSTR_R2_TYPE(0b0000101, a1, a0, 0b111, a0, 0b0110011);
274
 
275
  return result;
276
}
277
 
278
 
279
/**********************************************************************//**
280
 * Intrinsic: Bit manipulation ANDN (logical and-negate) [B.Zbb]
281
 *
282
 * @param[in] rs1 Source operand 1 (a0).
283
 * @param[in] rs2 Source operand 2 (a0).
284
 * @return Operand 1 AND NOT operand 2.
285
 **************************************************************************/
286
inline inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_andn(uint32_t rs1, uint32_t rs2) {
287
 
288
  register uint32_t result __asm__ ("a0");
289
  register uint32_t tmp_a  __asm__ ("a0") = rs1;
290
  register uint32_t tmp_b  __asm__ ("a1") = rs2;
291
 
292
  // dummy instruction to prevent GCC "constprop" optimization
293
  asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
294
 
295
  // andn a0, a0, a1
296
  CUSTOM_INSTR_R2_TYPE(0b0100000, a1, a0, 0b111, a0, 0b0110011);
297
 
298
  return result;
299
}
300
 
301
 
302
/**********************************************************************//**
303
 * Intrinsic: Bit manipulation ORN (logical or-negate) [B.Zbb]
304
 *
305
 * @param[in] rs1 Source operand 1 (a0).
306
 * @param[in] rs2 Source operand 2 (a0).
307
 * @return Operand 1 OR NOT operand 2.
308
 **************************************************************************/
309
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_orn(uint32_t rs1, uint32_t rs2) {
310
 
311
  register uint32_t result __asm__ ("a0");
312
  register uint32_t tmp_a  __asm__ ("a0") = rs1;
313
  register uint32_t tmp_b  __asm__ ("a1") = rs2;
314
 
315
  // dummy instruction to prevent GCC "constprop" optimization
316
  asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
317
 
318
  // orn a0, a0, a1
319
  CUSTOM_INSTR_R2_TYPE(0b0100000, a1, a0, 0b110, a0, 0b0110011);
320
 
321
  return result;
322
}
323
 
324
 
325
/**********************************************************************//**
326
 * Intrinsic: Bit manipulation XNOR (logical xor-negate) [B.Zbb]
327
 *
328
 * @param[in] rs1 Source operand 1 (a0).
329
 * @param[in] rs2 Source operand 2 (a0).
330
 * @return Operand 1 XOR NOT operand 2.
331
 **************************************************************************/
332
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_xnor(uint32_t rs1, uint32_t rs2) {
333
 
334
  register uint32_t result __asm__ ("a0");
335
  register uint32_t tmp_a  __asm__ ("a0") = rs1;
336
  register uint32_t tmp_b  __asm__ ("a1") = rs2;
337
 
338
  // dummy instruction to prevent GCC "constprop" optimization
339
  asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
340
 
341
  // xnor a0, a0, a1
342
  CUSTOM_INSTR_R2_TYPE(0b0100000, a1, a0, 0b100, a0, 0b0110011);
343
 
344
  return result;
345
}
346
 
347
 
348
/**********************************************************************//**
349
 * Intrinsic: Bit manipulation ROL (rotate-left) [B.Zbb]
350
 *
351
 * @param[in] rs1 Source operand 1 (a0).
352
 * @param[in] rs2 Source operand 2 (a0).
353
 * @return Operand 1 rotated left by operand_2(4:0) positions.
354
 **************************************************************************/
355
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_rol(uint32_t rs1, uint32_t rs2) {
356
 
357
  register uint32_t result __asm__ ("a0");
358
  register uint32_t tmp_a  __asm__ ("a0") = rs1;
359
  register uint32_t tmp_b  __asm__ ("a1") = rs2;
360
 
361
  // dummy instruction to prevent GCC "constprop" optimization
362
  asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
363
 
364
  // rol a0, a0, a1
365
  CUSTOM_INSTR_R2_TYPE(0b0110000, a1, a0, 0b001, a0, 0b0110011);
366
 
367
  return result;
368
}
369
 
370
 
371
/**********************************************************************//**
372
 * Intrinsic: Bit manipulation ROR (rotate-right) [B.Zbb]
373
 *
374
 * @param[in] rs1 Source operand 1 (a0).
375
 * @param[in] rs2 Source operand 2 (a0).
376
 * @return Operand 1 rotated right by operand_2(4:0) positions.
377
 **************************************************************************/
378
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_ror(uint32_t rs1, uint32_t rs2) {
379
 
380
  register uint32_t result __asm__ ("a0");
381
  register uint32_t tmp_a  __asm__ ("a0") = rs1;
382
  register uint32_t tmp_b  __asm__ ("a1") = rs2;
383
 
384
  // dummy instruction to prevent GCC "constprop" optimization
385
  asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
386
 
387
  // ror a0, a0, a1
388
  CUSTOM_INSTR_R2_TYPE(0b0110000, a1, a0, 0b101, a0, 0b0110011);
389
 
390
  return result;
391
}
392
 
393
 
394
/**********************************************************************//**
395
 * Intrinsic: Bit manipulation RORI (rotate-right) by 20 positions. [B.Zbb]
396
 * @warning Fixed shift amount (20) for now.
397
 *
398
 * @param[in] rs1 Source operand 1 (a0).
399
 * @return Operand 1 rotated right by 20 positions.
400
 **************************************************************************/
401
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_rori20(uint32_t rs1) {
402
 
403
  register uint32_t result __asm__ ("a0");
404
  register uint32_t tmp_a  __asm__ ("a0") = rs1;
405
 
406
  // dummy instruction to prevent GCC "constprop" optimization
407
  asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a));
408
 
409
  // rori a0, a0, 20
410
  CUSTOM_INSTR_R1_TYPE(0b0110000, 0b10100, a0, 0b101, a0, 0b0010011);
411
 
412
  return result;
413
}
414
 
415
 
416
/**********************************************************************//**
417
 * Intrinsic: Bit manipulation ORC.B (or-combine byte) [B.Zbb]
418
 *
419
 * @param[in] rs1 Source operand 1 (a0).
420
 * @return OR-combined bytes of operand 1.
421
 **************************************************************************/
422
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_orcb(uint32_t rs1) {
423
 
424
  register uint32_t result __asm__ ("a0");
425
  register uint32_t tmp_a  __asm__ ("a0") = rs1;
426
 
427
  // dummy instruction to prevent GCC "constprop" optimization
428
  asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a));
429
 
430
  // gorci a0, a0, 7 (pseudo-instruction: orc.b a0, a0)
431
  CUSTOM_INSTR_R1_TYPE(0b0010100, 0b00111, a0, 0b101, a0, 0b0010011);
432
 
433
  return result;
434
}
435
 
436
 
437
/**********************************************************************//**
438
 * Intrinsic: Bit manipulation REV8 (byte-swap) [B.Zbb]
439
 *
440
 * @param[in] rs1 Source operand 1 (a0).
441
 * @return Byte swap of operand 1
442
 **************************************************************************/
443
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_rev8(uint32_t rs1) {
444
 
445
  register uint32_t result __asm__ ("a0");
446
  register uint32_t tmp_a  __asm__ ("a0") = rs1;
447
 
448
  // dummy instruction to prevent GCC "constprop" optimization
449
  asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a));
450
 
451
  // grevi a0, a0, -8 (pseudo-instruction: rev8 a0, a0)
452
  CUSTOM_INSTR_R1_TYPE(0b0110100, 0b11000, a0, 0b101, a0, 0b0010011);
453
 
454
  return result;
455
}
456
 
457
 
458 66 zero_gravi
// ================================================================================================
459
// Zbb - Base instructions
460
// ================================================================================================
461
 
462
/**********************************************************************//**
463
 * Intrinsic: Address generation instructions SH1ADD (add with logical-1-shift) [B.Zba]
464
 *
465
 * @param[in] rs1 Source operand 1 (a0).
466
 * @param[in] rs2 Source operand 2 (a0).
467
 * @return Operand 2 + (Operand 1 << 1)
468
 **************************************************************************/
469
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_sh1add(uint32_t rs1, uint32_t rs2) {
470
 
471
  register uint32_t result __asm__ ("a0");
472
  register uint32_t tmp_a  __asm__ ("a0") = rs1;
473
  register uint32_t tmp_b  __asm__ ("a1") = rs2;
474
 
475
  // dummy instruction to prevent GCC "constprop" optimization
476
  asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
477
 
478
  // sh1add a0, a0, a1
479
  CUSTOM_INSTR_R2_TYPE(0b0010000, a1, a0, 0b010, a0, 0b0110011);
480
 
481
  return result;
482
}
483
 
484
 
485
/**********************************************************************//**
486
 * Intrinsic: Address generation instructions SH2ADD (add with logical-2-shift) [B.Zba]
487
 *
488
 * @param[in] rs1 Source operand 1 (a0).
489
 * @param[in] rs2 Source operand 2 (a0).
490
 * @return Operand 2 + (Operand 1 << 2)
491
 **************************************************************************/
492
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_sh2add(uint32_t rs1, uint32_t rs2) {
493
 
494
  register uint32_t result __asm__ ("a0");
495
  register uint32_t tmp_a  __asm__ ("a0") = rs1;
496
  register uint32_t tmp_b  __asm__ ("a1") = rs2;
497
 
498
  // dummy instruction to prevent GCC "constprop" optimization
499
  asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
500
 
501
  // sh2add a0, a0, a1
502
  CUSTOM_INSTR_R2_TYPE(0b0010000, a1, a0, 0b100, a0, 0b0110011);
503
 
504
  return result;
505
}
506
 
507
/**********************************************************************//**
508
 * Intrinsic: Address generation instructions SH1ADD (add with logical-3-shift) [B.Zba]
509
 *
510
 * @param[in] rs1 Source operand 1 (a0).
511
 * @param[in] rs2 Source operand 2 (a0).
512
 * @return Operand 2 + (Operand 1 << 3)
513
 **************************************************************************/
514
inline uint32_t __attribute__ ((always_inline)) riscv_intrinsic_sh3add(uint32_t rs1, uint32_t rs2) {
515
 
516
  register uint32_t result __asm__ ("a0");
517
  register uint32_t tmp_a  __asm__ ("a0") = rs1;
518
  register uint32_t tmp_b  __asm__ ("a1") = rs2;
519
 
520
  // dummy instruction to prevent GCC "constprop" optimization
521
  asm volatile ("" : [output] "=r" (result) : [input_i] "r" (tmp_a), [input_j] "r" (tmp_b));
522
 
523
  // sh3add a0, a0, a1
524
  CUSTOM_INSTR_R2_TYPE(0b0010000, a1, a0, 0b110, a0, 0b0110011);
525
 
526
  return result;
527
}
528
 
529
 
530
 
531 63 zero_gravi
// ################################################################################################
532
// Emulation functions
533
// ################################################################################################
534
 
535
 
536 66 zero_gravi
// ================================================================================================
537 63 zero_gravi
// Zbb - Base instructions
538 66 zero_gravi
// ================================================================================================
539 63 zero_gravi
 
540
 
541
/**********************************************************************//**
542
 * Intrinsic: Bit manipulation CLZ (count leading zeros) [emulation]
543
 *
544
 * @param[in] rs1 Source operand 1 (a0).
545
 * @return Number of leading zeros in source operand.
546
 **************************************************************************/
547
uint32_t riscv_emulate_clz(uint32_t rs1) {
548
 
549
  uint32_t sreg = rs1;
550
  uint32_t cnt = 0;
551
 
552
  while(1) {
553
    if (sreg & 0x80000000UL) {
554
      break;
555
    }
556
    else {
557
      sreg <<= 1;
558
      cnt++;
559
    }
560
  }
561
 
562
  return cnt;
563
}
564
 
565
 
566
/**********************************************************************//**
567
 * Intrinsic: Bit manipulation CTZ (count trailing zeros) [emulation]
568
 *
569
 * @param[in] rs1 Source operand 1 (a0).
570
 * @return Number of trailing zeros in source operand.
571
 **************************************************************************/
572
uint32_t riscv_emulate_ctz(uint32_t rs1) {
573
 
574
  uint32_t sreg = rs1;
575
  uint32_t cnt = 0;
576
 
577
  while(1) {
578
    if (sreg & 1) {
579
      break;
580
    }
581
    else {
582
      sreg >>= 1;
583
      cnt++;
584
    }
585
  }
586
 
587
  return cnt;
588
}
589
 
590
 
591
/**********************************************************************//**
592
 * Intrinsic: Bit manipulation CPOP (population count) [emulation]
593
 *
594
 * @param[in] rs1 Source operand 1 (a0).
595
 * @return Number of set bits in source operand.
596
 **************************************************************************/
597
uint32_t riscv_emulate_cpop(uint32_t rs1) {
598
 
599
  uint32_t sreg = rs1;
600
  uint32_t cnt = 0;
601
  int i;
602
 
603
  for (i=0; i<32; i++) {
604
    if (sreg & 1) {
605
      cnt++;
606
    }
607
    sreg >>= 1;
608
  }
609
 
610
  return cnt;
611
}
612
 
613
 
614
/**********************************************************************//**
615
 * Intrinsic: Bit manipulation SEXT.B (sign-extend byte) [emulation]
616
 *
617
 * @param[in] rs1 Source operand 1 (a0).
618
 * @return Sign-extended byte (operand(7:0)).
619
 **************************************************************************/
620
uint32_t riscv_emulate_sextb(uint32_t rs1) {
621
 
622
  uint32_t tmp = rs1 & 0xff;
623
 
624
  if (tmp & 0x80) {
625
    tmp |= 0xFFFFFF00UL;
626
  }
627
 
628
  return tmp;
629
}
630
 
631
 
632
/**********************************************************************//**
633
 * Intrinsic: Bit manipulation SEXT.H (sign-extend half-word) [emulation]
634
 *
635
 * @param[in] rs1 Source operand 1 (a0).
636
 * @return Sign-extended half-word (operand(15:0)).
637
 **************************************************************************/
638
uint32_t riscv_emulate_sexth(uint32_t rs1) {
639
 
640
  uint32_t tmp = rs1 & 0xffff;
641
 
642
  if (tmp & 0x8000) {
643
    tmp |= 0xFFFF0000UL;
644
  }
645
 
646
  return tmp;
647
}
648
 
649
 
650
/**********************************************************************//**
651
 * Intrinsic: Bit manipulation ZEXT.H (zero-extend half-word) [emulation]
652
 *
653
 * @param[in] rs1 Source operand 1 (a0).
654
 * @return Zero-extended half-word (operand(15:0)).
655
 **************************************************************************/
656
uint32_t riscv_emulate_zexth(uint32_t rs1) {
657
 
658
  return rs1 & 0x0000FFFFUL;
659
}
660
 
661
 
662
/**********************************************************************//**
663
 * Intrinsic: Bit manipulation MIN (select signed minimum) [emulation]
664
 *
665
 * @param[in] rs1 Source operand 1 (a0).
666
 * @param[in] rs2 Source operand 1 (a0).
667
 * @return Signed minimum.
668
 **************************************************************************/
669
uint32_t riscv_emulate_min(uint32_t rs1, uint32_t rs2) {
670
 
671
  int32_t s_opa = (int32_t)rs1;
672
  int32_t s_opb = (int32_t)rs2;
673
 
674
  if (s_opa < s_opb) {
675
    return rs1;
676
  }
677
  else {
678
    return rs2;
679
  }
680
}
681
 
682
 
683
/**********************************************************************//**
684
 * Intrinsic: Bit manipulation MINU (select unsigned minimum) [emulation]
685
 *
686
 * @param[in] rs1 Source operand 1 (a0).
687
 * @param[in] rs2 Source operand 1 (a0).
688
 * @return Unsigned minimum.
689
 **************************************************************************/
690
uint32_t riscv_emulate_minu(uint32_t rs1, uint32_t rs2) {
691
 
692
  if (rs1 < rs2) {
693
    return rs1;
694
  }
695
  else {
696
    return rs2;
697
  }
698
}
699
 
700
 
701
/**********************************************************************//**
702
 * Intrinsic: Bit manipulation MAX (select signed maximum) [emulation]
703
 *
704
 * @param[in] rs1 Source operand 1 (a0).
705
 * @param[in] rs2 Source operand 1 (a0).
706
 * @return Signed maximum.
707
 **************************************************************************/
708
uint32_t riscv_emulate_max(uint32_t rs1, uint32_t rs2) {
709
 
710
  int32_t s_opa = (int32_t)rs1;
711
  int32_t s_opb = (int32_t)rs2;
712
 
713
  if (s_opa < s_opb) {
714
    return rs2;
715
  }
716
  else {
717
    return rs1;
718
  }
719
}
720
 
721
 
722
/**********************************************************************//**
723
 * Intrinsic: Bit manipulation MAXU (select unsigned maximum) [emulation]
724
 *
725
 * @param[in] rs1 Source operand 1 (a0).
726
 * @param[in] rs2 Source operand 1 (a0).
727
 * @return Unsigned maximum.
728
 **************************************************************************/
729
uint32_t riscv_emulate_maxu(uint32_t rs1, uint32_t rs2) {
730
 
731
  if (rs1 < rs2) {
732
    return rs2;
733
  }
734
  else {
735
    return rs1;
736
  }
737
}
738
 
739
 
740
/**********************************************************************//**
741
 * Intrinsic: Bit manipulation ANDN (logical and-negate) [emulation]
742
 *
743
 * @param[in] rs1 Source operand 1 (a0).
744
 * @param[in] rs2 Source operand 1 (a0).
745
 * @return Operand 1 AND NOT operand 2.
746
 **************************************************************************/
747
uint32_t riscv_emulate_andn(uint32_t rs1, uint32_t rs2) {
748
 
749
  return rs1 & (~rs2);
750
}
751
 
752
 
753
/**********************************************************************//**
754
 * Intrinsic: Bit manipulation ORN (logical or-negate) [emulation]
755
 *
756
 * @param[in] rs1 Source operand 1 (a0).
757
 * @param[in] rs2 Source operand 1 (a0).
758
 * @return Operand 1 OR NOT operand 2.
759
 **************************************************************************/
760
uint32_t riscv_emulate_orn(uint32_t rs1, uint32_t rs2) {
761
 
762
  return rs1 | (~rs2);
763
}
764
 
765
 
766
/**********************************************************************//**
767
 * Intrinsic: Bit manipulation XNOR (logical xor-negate) [emulation]
768
 *
769
 * @param[in] rs1 Source operand 1 (a0).
770
 * @param[in] rs2 Source operand 1 (a0).
771
 * @return Operand 1 XOR NOT operand 2.
772
 **************************************************************************/
773
uint32_t riscv_emulate_xnor(uint32_t rs1, uint32_t rs2) {
774
 
775
  return rs1 ^ (~rs2);
776
}
777
 
778
 
779
/**********************************************************************//**
780
 * Intrinsic: Bit manipulation ROL (rotate-left) [emulation]
781
 *
782
 * @param[in] rs1 Source operand 1 (a0).
783
 * @param[in] rs2 Source operand 1 (a0).
784
 * @return Operand 1 rotated left by operand_2(4:0) positions.
785
 **************************************************************************/
786
uint32_t riscv_emulate_rol(uint32_t rs1, uint32_t rs2) {
787
 
788
  uint32_t shamt = rs2 & 0x1f;
789
 
790
  uint32_t tmp_a = rs1 << shamt;
791
  uint32_t tmp_b = rs1 >> (32-shamt);
792
 
793
  return tmp_a | tmp_b;
794
}
795
 
796
 
797
/**********************************************************************//**
798
 * Intrinsic: Bit manipulation ROR (rotate-right) [emulation]
799
 *
800
 * @param[in] rs1 Source operand 1 (a0).
801
 * @param[in] rs2 Source operand 1 (a0).
802
 * @return Operand 1 rotated right by operand_2(4:0) positions.
803
 **************************************************************************/
804
uint32_t riscv_emulate_ror(uint32_t rs1, uint32_t rs2) {
805
 
806
  uint32_t shamt = rs2 & 0x1f;
807
 
808
  uint32_t tmp_a = rs1 >> shamt;
809
  uint32_t tmp_b = rs1 << (32-shamt);
810
 
811
  return tmp_a | tmp_b;
812
}
813
 
814
 
815
/**********************************************************************//**
816
 * Intrinsic: Bit manipulation REV8 (byte swap) [emulation]
817
 *
818
 * @param[in] rs1 Source operand 1 (a0).
819
 * @return Operand 1 byte swapped.
820
 **************************************************************************/
821
uint32_t riscv_emulate_rev8(uint32_t rs1) {
822
 
823
  uint32_t tmp_a = (rs1 & 0x000000ffUL) << 24;
824
  uint32_t tmp_b = (rs1 & 0x0000ff00UL) << 8;
825
  uint32_t tmp_c = (rs1 & 0x00ff0000UL) >> 8;
826
  uint32_t tmp_d = (rs1 & 0xff000000UL) >> 24;
827
 
828
  return tmp_a | tmp_b | tmp_c | tmp_d;
829
}
830
 
831
 
832
/**********************************************************************//**
833
 * Intrinsic: Bit manipulation ORCB (or-combine bytes) [emulation]
834
 *
835
 * @param[in] rs1 Source operand 1 (a0).
836
 * @return OR-combined bytes of operand 1.
837
 **************************************************************************/
838
uint32_t riscv_emulate_orcb(uint32_t rs1) {
839
 
840
  uint32_t tmp = 0;
841
 
842
  if (rs1 & 0x000000ffUL) {
843
    tmp |= 0x000000ffUL;
844
  }
845
  if (rs1 & 0x0000ff00UL) {
846
    tmp |= 0x0000ff00UL;
847
  }
848
  if (rs1 & 0x00ff0000UL) {
849
    tmp |= 0x00ff0000UL;
850
  }
851
  if (rs1 & 0xff000000UL) {
852
    tmp |= 0xff000000UL;
853
  }
854
 
855
  return tmp;
856
}
857
 
858
 
859 66 zero_gravi
// ================================================================================================
860
// Zba - Address generation instructions
861
// ================================================================================================
862
 
863
 
864
/**********************************************************************//**
865
 * Intrinsic: Address generation instructions SH1ADD (add with logical-1-shift) [emulation]
866
 *
867
 * @param[in] rs1 Source operand 1 (a0).
868
 * @param[in] rs2 Source operand 1 (a0).
869
 * @return Operand 2 + (Operand 1 << 1)
870
 **************************************************************************/
871
uint32_t riscv_emulate_sh1add(uint32_t rs1, uint32_t rs2) {
872
 
873
  return rs2 + (rs1 << 1);
874
}
875
 
876
 
877
/**********************************************************************//**
878
 * Intrinsic: Address generation instructions SH2ADD (add with logical-2-shift) [emulation]
879
 *
880
 * @param[in] rs1 Source operand 1 (a0).
881
 * @param[in] rs2 Source operand 1 (a0).
882
 * @return Operand 2 + (Operand 1 << 2)
883
 **************************************************************************/
884
uint32_t riscv_emulate_sh2add(uint32_t rs1, uint32_t rs2) {
885
 
886
  return rs2 + (rs1 << 2);
887
}
888
 
889
 
890
/**********************************************************************//**
891
 * Intrinsic: Address generation instructions SH3ADD (add with logical-3-shift) [emulation]
892
 *
893
 * @param[in] rs1 Source operand 1 (a0).
894
 * @param[in] rs2 Source operand 1 (a0).
895
 * @return Operand 2 + (Operand 1 << 3)
896
 **************************************************************************/
897
uint32_t riscv_emulate_sh3add(uint32_t rs1, uint32_t rs2) {
898
 
899
  return rs2 + (rs1 << 3);
900
}
901
 
902
 
903 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.