[metadata] Remove native threadpool from netcore build (#17856)
[mono-project.git] / mono / arch / riscv / riscv-codegen.h
blob9bd4b4a58223c849204cb4fdc46c01505412fb8e
1 /*
2 * Licensed to the .NET Foundation under one or more agreements.
3 * The .NET Foundation licenses this file to you under the MIT license.
4 * See the LICENSE file in the project root for more information.
5 */
7 #ifndef __MONO_RISCV_CODEGEN_H__
8 #define __MONO_RISCV_CODEGEN_H__
10 #include "config.h"
11 #include <glib.h>
13 #ifdef MONO_RISCV_CODEGEN_TEST
15 #include <stdio.h>
16 #include <stdlib.h>
19 * Avoid having to link with eglib in the codegen test program so that it can
20 * be built with a native toolchain even if we're building Mono with a cross
21 * toolchain.
24 #undef g_assert
25 #define g_assert(expr) \
26 do { \
27 if (G_UNLIKELY (!(expr))) { \
28 fprintf (stderr, "* Assertion at %s:%d, condition `%s' not met\n", __FILE__, __LINE__, #expr); \
29 abort (); \
30 } \
31 } while (0)
33 #endif
35 enum {
36 RISCV_X0 = 0,
37 RISCV_X1 = 1,
38 RISCV_X2 = 2,
39 RISCV_X3 = 3,
40 RISCV_X4 = 4,
41 RISCV_X5 = 5,
42 RISCV_X6 = 6,
43 RISCV_X7 = 7,
44 RISCV_X8 = 8,
45 RISCV_X9 = 9,
46 RISCV_X10 = 10,
47 RISCV_X11 = 11,
48 RISCV_X12 = 12,
49 RISCV_X13 = 13,
50 RISCV_X14 = 14,
51 RISCV_X15 = 15,
52 RISCV_X16 = 16,
53 RISCV_X17 = 17,
54 RISCV_X18 = 18,
55 RISCV_X19 = 19,
56 RISCV_X20 = 20,
57 RISCV_X21 = 21,
58 RISCV_X22 = 22,
59 RISCV_X23 = 23,
60 RISCV_X24 = 24,
61 RISCV_X25 = 25,
62 RISCV_X26 = 26,
63 RISCV_X27 = 27,
64 RISCV_X28 = 28,
65 RISCV_X29 = 29,
66 RISCV_X30 = 30,
67 RISCV_X31 = 31,
69 RISCV_ZERO = RISCV_X0,
71 // Argument and return registers.
73 RISCV_A0 = RISCV_X10,
74 RISCV_A1 = RISCV_X11,
75 RISCV_A2 = RISCV_X12,
76 RISCV_A3 = RISCV_X13,
77 RISCV_A4 = RISCV_X14,
78 RISCV_A5 = RISCV_X15,
79 RISCV_A6 = RISCV_X16,
80 RISCV_A7 = RISCV_X17,
82 // Callee-saved registers.
84 RISCV_S0 = RISCV_X8,
85 RISCV_S1 = RISCV_X9,
86 RISCV_S2 = RISCV_X18,
87 RISCV_S3 = RISCV_X19,
88 RISCV_S4 = RISCV_X20,
89 RISCV_S5 = RISCV_X21,
90 RISCV_S6 = RISCV_X22,
91 RISCV_S7 = RISCV_X23,
92 RISCV_S8 = RISCV_X24,
93 RISCV_S9 = RISCV_X25,
94 RISCV_S10 = RISCV_X26,
95 RISCV_S11 = RISCV_X27,
97 // Temporary registers.
99 RISCV_T0 = RISCV_X5,
100 RISCV_T1 = RISCV_X6,
101 RISCV_T2 = RISCV_X7,
102 RISCV_T3 = RISCV_X28,
103 RISCV_T4 = RISCV_X29,
104 RISCV_T5 = RISCV_X30,
105 RISCV_T6 = RISCV_X31,
107 // Call stack registers.
109 RISCV_SP = RISCV_X2, // Stack pointer.
110 RISCV_RA = RISCV_X1, // Return address (AKA link register).
111 RISCV_FP = RISCV_S0, // Frame pointer (AKA base pointer).
113 // ABI implementation registers.
115 RISCV_GP = RISCV_X3,
116 RISCV_TP = RISCV_X4,
119 #define RISCV_N_GREGS (32)
120 #define RISCV_N_GAREGS (8)
121 #define RISCV_N_GSREGS (12)
122 #define RISCV_N_GTREGS (7)
124 enum {
125 RISCV_F0 = 0,
126 RISCV_F1 = 1,
127 RISCV_F2 = 2,
128 RISCV_F3 = 3,
129 RISCV_F4 = 4,
130 RISCV_F5 = 5,
131 RISCV_F6 = 6,
132 RISCV_F7 = 7,
133 RISCV_F8 = 8,
134 RISCV_F9 = 9,
135 RISCV_F10 = 10,
136 RISCV_F11 = 11,
137 RISCV_F12 = 12,
138 RISCV_F13 = 13,
139 RISCV_F14 = 14,
140 RISCV_F15 = 15,
141 RISCV_F16 = 16,
142 RISCV_F17 = 17,
143 RISCV_F18 = 18,
144 RISCV_F19 = 19,
145 RISCV_F20 = 20,
146 RISCV_F21 = 21,
147 RISCV_F22 = 22,
148 RISCV_F23 = 23,
149 RISCV_F24 = 24,
150 RISCV_F25 = 25,
151 RISCV_F26 = 26,
152 RISCV_F27 = 27,
153 RISCV_F28 = 28,
154 RISCV_F29 = 29,
155 RISCV_F30 = 30,
156 RISCV_F31 = 31,
158 // Argument and return registers.
160 RISCV_FA0 = RISCV_F10,
161 RISCV_FA1 = RISCV_F11,
162 RISCV_FA2 = RISCV_F12,
163 RISCV_FA3 = RISCV_F13,
164 RISCV_FA4 = RISCV_F14,
165 RISCV_FA5 = RISCV_F15,
166 RISCV_FA6 = RISCV_F16,
167 RISCV_FA7 = RISCV_F17,
169 // Callee-saved registers.
171 RISCV_FS0 = RISCV_F8,
172 RISCV_FS1 = RISCV_F9,
173 RISCV_FS2 = RISCV_F18,
174 RISCV_FS3 = RISCV_F19,
175 RISCV_FS4 = RISCV_F20,
176 RISCV_FS5 = RISCV_F21,
177 RISCV_FS6 = RISCV_F22,
178 RISCV_FS7 = RISCV_F23,
179 RISCV_FS8 = RISCV_F24,
180 RISCV_FS9 = RISCV_F25,
181 RISCV_FS10 = RISCV_F26,
182 RISCV_FS11 = RISCV_F27,
184 // Temporary registers.
186 RISCV_FT0 = RISCV_F0,
187 RISCV_FT1 = RISCV_F1,
188 RISCV_FT2 = RISCV_F2,
189 RISCV_FT3 = RISCV_F3,
190 RISCV_FT4 = RISCV_F4,
191 RISCV_FT5 = RISCV_F5,
192 RISCV_FT6 = RISCV_F6,
193 RISCV_FT7 = RISCV_F7,
194 RISCV_FT8 = RISCV_F28,
195 RISCV_FT9 = RISCV_F29,
196 RISCV_FT10 = RISCV_F30,
197 RISCV_FT11 = RISCV_F31,
200 #define RISCV_N_FREGS (32)
201 #define RISCV_N_FAREGS (8)
202 #define RISCV_N_FSREGS (12)
203 #define RISCV_N_FTREGS (12)
205 enum {
206 // Floating point.
208 RISCV_CSR_FFLAGS = 0x001, // Accrued exceptions.
209 RISCV_CSR_FRM = 0x002, // Rounding mode.
210 RISCV_CSR_FCSR = 0x003, // Combination of FFLAGS and FRM.
212 // Counters and timers.
214 RISCV_CSR_CYCLE = 0xc00, // Cycle counter.
215 RISCV_CSR_TIME = 0xc01, // Wall clock time.
216 RISCV_CSR_INSTRET = 0xc02, // Instruction counter.
218 #ifdef TARGET_RISCV32
219 RISCV_CSR_CYCLEH = 0xc80, // Upper 32 bits of CYCLE.
220 RISCV_CSR_TIMEH = 0xc81, // Upper 32 bits of TIME.
221 RISCV_CSR_INSTRETH = 0xc82, // Upper 32 bits of INSTRET.
222 #endif
225 enum {
226 RISCV_FENCE_NONE = 0b0000,
228 RISCV_FENCE_W = 0b0001, // Memory writes.
229 RISCV_FENCE_R = 0b0010, // Memory reads.
230 RISCV_FENCE_O = 0b0100, // Device outputs.
231 RISCV_FENCE_I = 0b1000, // Device inputs.
233 RISCV_FENCE_MEM = RISCV_FENCE_W | RISCV_FENCE_R,
234 RISCV_FENCE_DEV = RISCV_FENCE_O | RISCV_FENCE_I,
235 RISCV_FENCE_ALL = RISCV_FENCE_DEV | RISCV_FENCE_MEM,
238 enum {
239 RISCV_ORDER_NONE = 0b00,
241 RISCV_ORDER_RL = 0b01, // Release semantics.
242 RISCV_ORDER_AQ = 0b10, // Acquire semantics.
244 RISCV_ORDER_ALL = RISCV_ORDER_RL | RISCV_ORDER_AQ,
247 enum {
248 RISCV_ROUND_NE = 0b000, // Round to nearest (ties to even).
249 RISCV_ROUND_TZ = 0b001, // Round towards zero.
250 RISCV_ROUND_DN = 0b010, // Round down (towards negative infinity).
251 RISCV_ROUND_UP = 0b011, // Round up (towards positive infinity).
252 RISCV_ROUND_MM = 0b100, // Round to nearest (ties to max magnitude).
253 RISCV_ROUND_DY = 0b111, // Use current rounding mode in the FRM CSR.
256 #define _riscv_emit(p, insn) \
257 do { \
258 *(guint32 *) (p) = (insn); \
259 (p) += sizeof (guint32); \
260 } while (0)
262 #define RISCV_BITS(value, start, count) (((value) >> (start)) & ((1 << (count)) - 1))
263 #define RISCV_SIGN(value) (-(((value) >> (sizeof (guint32) * 8 - 1)) & 1))
265 // Encode an imemdiate for use in an instruction.
267 #define RISCV_ENCODE_I_IMM(imm) \
268 (RISCV_BITS ((imm), 0, 12) << 20)
269 #define RISCV_ENCODE_S_IMM(imm) \
270 ((RISCV_BITS ((imm), 0, 5) << 7) | (RISCV_BITS ((imm), 5, 7) << 25))
271 #define RISCV_ENCODE_B_IMM(imm) \
272 ((RISCV_BITS ((imm), 11, 1) << 7) | (RISCV_BITS ((imm), 1, 4) << 8) | \
273 (RISCV_BITS ((imm), 5, 6) << 25) | (RISCV_BITS ((imm), 12, 1) << 31))
274 #define RISCV_ENCODE_U_IMM(imm) \
275 (RISCV_BITS ((imm), 0, 20) << 12)
276 #define RISCV_ENCODE_J_IMM(imm) \
277 ((RISCV_BITS ((imm), 1, 10) << 21) | (RISCV_BITS ((imm), 11, 1) << 20) | \
278 (RISCV_BITS ((imm), 12, 8) << 12) | (RISCV_BITS ((imm), 20, 1) << 31))
280 // Decode an immediate from an instruction.
282 #define RISCV_DECODE_I_IMM(ins) \
283 ((RISCV_BITS ((ins), 20, 12) << 0) | (RISCV_SIGN ((ins)) << 12))
284 #define RISCV_DECODE_S_IMM(ins) \
285 ((RISCV_BITS ((ins), 7, 5) << 0) | (RISCV_BITS ((ins), 25, 7) << 5) | \
286 (RISCV_SIGN ((ins)) << 12))
287 #define RISCV_DECODE_B_IMM(ins) \
288 ((RISCV_BITS ((ins), 8, 4) << 1) | (RISCV_BITS ((ins), 25, 6) << 5) | \
289 (RISCV_BITS ((ins), 7, 1) << 11) | (RISCV_SIGN((ins)) << 12))
290 #define RISCV_DECODE_U_IMM(ins) \
291 (RISCV_BITS ((ins), 12, 20) << 0)
292 #define RISCV_DECODE_J_IMM(ins) \
293 ((RISCV_BITS ((ins), 21, 10) << 1) | (RISCV_BITS ((ins), 20, 1) << 11) | \
294 (RISCV_BITS ((ins), 12, 8) << 12) | (RISCV_SIGN ((ins)) << 20))
296 // Check a value for validity as an immediate.
298 #define RISCV_VALID_I_IMM(value) \
299 (RISCV_DECODE_I_IMM (RISCV_ENCODE_I_IMM ((value))) == (value))
300 #define RISCV_VALID_S_IMM(value) \
301 (RISCV_DECODE_S_IMM (RISCV_ENCODE_S_IMM ((value))) == (value))
302 #define RISCV_VALID_B_IMM(value) \
303 (RISCV_DECODE_B_IMM (RISCV_ENCODE_B_IMM ((value))) == (value))
304 #define RISCV_VALID_U_IMM(value) \
305 (RISCV_DECODE_U_IMM (RISCV_ENCODE_U_IMM ((value))) == (value))
306 #define RISCV_VALID_J_IMM(value) \
307 (RISCV_DECODE_J_IMM (RISCV_ENCODE_J_IMM ((value))) == (value))
309 // Check various values for validity in an instruction.
311 #define RISCV_VALID_REG(value) \
312 (RISCV_BITS ((value), 0, 5) == (value))
313 #define RISCV_VALID_CSR(value) \
314 (RISCV_BITS ((value), 0, 12) == (value))
315 #define RISCV_VALID_IS_AMOUNT(value) \
316 (RISCV_BITS ((value), 0, 5) == (value))
317 #define RISCV_VALID_LS_AMOUNT(value) \
318 (RISCV_BITS ((value), 0, 6) == (value))
319 #define RISCV_VALID_FENCE(value) \
320 (RISCV_BITS ((value), 0, 4) == (value))
321 #define RISCV_VALID_ORDERING(value) \
322 (RISCV_BITS ((value), 0, 2) == (value))
325 * The R-type encoding is used for a variety of instructions that operate on
326 * registers only, such as most integer instructions, atomic instructions, and
327 * some floating point instructions.
329 * [0....6] opcode
330 * [7...11] rd
331 * [12..14] funct3
332 * [15..19] rs1
333 * [20..24] rs2
334 * [25..31] funct7
337 #define _riscv_r_op(p, opcode, funct3, funct7, rd, rs1, rs2) \
338 do { \
339 g_assert (RISCV_VALID_REG ((rd))); \
340 g_assert (RISCV_VALID_REG ((rs1))); \
341 g_assert (RISCV_VALID_REG ((rs2))); \
342 _riscv_emit ((p), ((opcode) << 0) | \
343 ((rd) << 7) | \
344 ((funct3) << 12) | \
345 ((rs1) << 15) | \
346 ((rs2) << 20) | \
347 ((funct7) << 25)); \
348 } while (0)
351 * The R4-type encoding is used for floating point fused multiply-add
352 * instructions.
354 * [0....6] opcode
355 * [7...11] rd
356 * [12..14] funct3
357 * [15..19] rs1
358 * [20..24] rs2
359 * [25..26] funct2
360 * [27..31] rs3
363 #define _riscv_r4_op(p, opcode, funct3, funct2, rd, rs1, rs2, rs3) \
364 do { \
365 g_assert (RISCV_VALID_REG ((rd))); \
366 g_assert (RISCV_VALID_REG ((rs1))); \
367 g_assert (RISCV_VALID_REG ((rs2))); \
368 g_assert (RISCV_VALID_REG ((rs3))); \
369 _riscv_emit ((p), ((opcode) << 0) | \
370 ((rd) << 7) | \
371 ((funct3) << 12) | \
372 ((rs1) << 15) | \
373 ((rs2) << 20) | \
374 ((funct2) << 25) | \
375 ((rs3) << 27)); \
376 } while (0)
379 * The I-type encoding is used for a variety of instructions, such as JALR,
380 * loads, and most integer instructions that operate on immediates.
382 * [0....6] opcode
383 * [7...11] rd
384 * [12..14] funct3
385 * [15..19] rs1
386 * [20..31] imm[0..11]
389 #define _riscv_i_op(p, opcode, funct3, rd, rs1, imm) \
390 do { \
391 g_assert (RISCV_VALID_REG ((rd))); \
392 g_assert (RISCV_VALID_REG ((rs1))); \
393 g_assert (RISCV_VALID_I_IMM ((gint32) (gssize) (imm))); \
394 _riscv_emit ((p), ((opcode) << 0) | \
395 ((rd) << 7) | \
396 ((funct3) << 12) | \
397 ((rs1) << 15) | \
398 (RISCV_ENCODE_I_IMM ((gint32) (gssize) (imm)))); \
399 } while (0)
402 * This is a specialization of the I-type encoding used for shifts by immediate
403 * values. The shift amount and right shift type are encoded into separate
404 * parts of the imm field.
406 * [0....6] opcode
407 * [7...11] rd
408 * [12..14] funct3
409 * [15..19] rs1
410 * [20..24] shamt
411 * [25..31] rstype
414 #define _riscv_is_op(p, opcode, funct3, rstype, rd, rs1, shamt) \
415 do { \
416 g_assert (RISCV_VALID_REG ((rd))); \
417 g_assert (RISCV_VALID_REG ((rs1))); \
418 g_assert (RISCV_VALID_IS_AMOUNT ((shamt))); \
419 _riscv_emit ((p), ((opcode) << 0) | \
420 ((rd) << 7) | \
421 ((funct3) << 12) | \
422 ((rs1) << 15) | \
423 (RISCV_BITS ((shamt), 0, 5) << 20) | \
424 ((rstype) << 25)); \
425 } while (0)
428 * A further specialization of the I-type encoding used for shifts by immediate
429 * values in RV64I. The shift amount field is larger.
431 * [0....6] opcode
432 * [7...11] rd
433 * [12..14] funct3
434 * [15..19] rs1
435 * [20..25] shamt
436 * [26..31] rstype
439 #define _riscv_ls_op(p, opcode, funct3, rstype, rd, rs1, shamt) \
440 do { \
441 g_assert (RISCV_VALID_REG ((rd))); \
442 g_assert (RISCV_VALID_REG ((rs1))); \
443 g_assert (RISCV_VALID_LS_AMOUNT ((shamt))); \
444 _riscv_emit ((p), ((opcode) << 0) | \
445 ((rd) << 7) | \
446 ((funct3) << 12) | \
447 ((rs1) << 15) | \
448 (RISCV_BITS ((shamt), 0, 6) << 20) | \
449 ((rstype) << 26)); \
450 } while (0)
453 * This is a specialization of the I-type encoding used for accessing control
454 * and status registers.
456 * [0....6] opcode
457 * [7...11] rd
458 * [12..14] funct3
459 * [15..19] rs1/zimm
460 * [20..31] csr
463 #define _riscv_ic_op(p, opcode, funct3, rd, csr, rs1) \
464 do { \
465 g_assert (RISCV_VALID_REG ((rd))); \
466 g_assert (RISCV_VALID_REG ((rs1))); \
467 g_assert (RISCV_VALID_CSR ((csr))); \
468 _riscv_emit ((p), ((opcode) << 0) | \
469 ((rd) << 7) | \
470 ((funct3) << 12) | \
471 ((rs1) << 15) | \
472 (RISCV_BITS ((csr), 0, 12) << 20)); \
473 } while (0)
476 * The S-type encoding is used for stores with signed offsets.
478 * [0....6] opcode
479 * [7...11] imm[0..4]
480 * [12..14] funct3
481 * [15..19] rs1
482 * [20..24] rs2
483 * [25..31] imm[5..11]
486 #define _riscv_s_op(p, opcode, funct3, rs2, rs1, imm) \
487 do { \
488 g_assert (RISCV_VALID_REG ((rs1))); \
489 g_assert (RISCV_VALID_REG ((rs2))); \
490 g_assert (RISCV_VALID_S_IMM ((gint32) (gssize) (imm))); \
491 _riscv_emit ((p), ((opcode) << 0) | \
492 ((funct3) << 12) | \
493 ((rs1) << 15) | \
494 ((rs2) << 20) | \
495 (RISCV_ENCODE_S_IMM ((gint32) (gssize) (imm)))); \
496 } while (0)
499 * The B-type encoding is used for conditional branches with signed offsets.
501 * [0....6] opcode
502 * [7....7] imm[11]
503 * [8...11] imm[1..4]
504 * [12..14] funct3
505 * [15..19] rs1
506 * [20..24] rs2
507 * [25..30] imm[5..10]
508 * [31..31] imm[12]
511 #define _riscv_b_op(p, opcode, funct3, rs1, rs2, imm) \
512 do { \
513 g_assert (RISCV_VALID_REG ((rs1))); \
514 g_assert (RISCV_VALID_REG ((rs2))); \
515 g_assert (RISCV_VALID_B_IMM ((gint32) (gssize) (imm))); \
516 _riscv_emit ((p), ((opcode) << 0) | \
517 ((funct3) << 12) | \
518 ((rs1) << 15) | \
519 ((rs2) << 20) | \
520 (RISCV_ENCODE_B_IMM ((gint32) (gssize) (imm)))); \
521 } while (0)
524 * The U-type encoding is used for LUI and AUIPC only, i.e. for instructions
525 * that create 32-bit values from 20-bit immediates.
527 * [0....6] opcode
528 * [7...11] rd
529 * [12..31] imm[12..31]
532 #define _riscv_u_op(p, opcode, rd, imm) \
533 do { \
534 g_assert (RISCV_VALID_REG ((rd))); \
535 g_assert (RISCV_VALID_U_IMM ((guint32) (gsize) (imm))); \
536 _riscv_emit ((p), ((opcode) << 0) | \
537 ((rd) << 7) | \
538 (RISCV_ENCODE_U_IMM ((guint32) (gsize) (imm)))); \
539 } while (0)
542 * The J-type encoding is used exclusively for JAL.
544 * [0....6] opcode
545 * [7...11] rd
546 * [12..19] imm[12..19]
547 * [20..20] imm[11]
548 * [21..30] imm[1..10]
549 * [31..31] imm[20]
552 #define _riscv_j_op(p, opcode, rd, imm) \
553 do { \
554 g_assert (RISCV_VALID_REG ((rd))); \
555 g_assert (RISCV_VALID_J_IMM ((gint32) (gssize) (imm))); \
556 _riscv_emit ((p), ((opcode) << 0) | \
557 ((rd) << 7) | \
558 (RISCV_ENCODE_J_IMM ((gint32) (gssize) (imm)))); \
559 } while (0)
562 * Fence instructions have a peculiar encoding that isn't quite like any of the
563 * other formal encoding categories.
565 * [0....6] opcode
566 * [7...11] rd
567 * [12..14] funct3
568 * [15..19] rs1
569 * [20..23] succ
570 * [24..27] pred
571 * [28..31] imm[0..3]
574 #define _riscv_f_op(p, opcode, funct3, rd, rs1, pred, succ, imm) \
575 do { \
576 g_assert (RISCV_VALID_REG ((rd))); \
577 g_assert (RISCV_VALID_REG ((rs1))); \
578 g_assert (RISCV_VALID_FENCE ((pred))); \
579 g_assert (RISCV_VALID_FENCE ((succ))); \
580 _riscv_emit ((p), ((opcode) << 0) | \
581 ((rd) << 7) | \
582 ((funct3) << 12) | \
583 ((rs1) << 15) | \
584 (RISCV_BITS ((succ), 0, 4) << 20) | \
585 (RISCV_BITS ((pred), 0, 4) << 24) | \
586 (RISCV_BITS ((guint32) (gsize) (imm), 0, 4) << 28)); \
587 } while (0)
590 * Atomic instructions have a peculiar encoding that isn't quite like any of
591 * the other formal encoding categories.
593 * [0....6] opcode
594 * [7...11] rd
595 * [12..14] funct3
596 * [15..19] rs1
597 * [20..24] rs2
598 * [25..26] ordering
599 * [27..31] funct5
602 #define _riscv_a_op(p, opcode, funct3, funct5, ordering, rd, rs2, rs1) \
603 do { \
604 g_assert (RISCV_VALID_REG ((rd))); \
605 g_assert (RISCV_VALID_REG ((rs1))); \
606 g_assert (RISCV_VALID_REG ((rs2))); \
607 g_assert (RISCV_VALID_ORDERING ((ordering))); \
608 _riscv_emit ((p), ((opcode) << 0) | \
609 ((rd) << 7) | \
610 ((funct3) << 12) | \
611 ((rs1) << 15) | \
612 ((rs2) << 20) | \
613 (RISCV_BITS ((ordering), 0, 2) << 25) | \
614 ((funct5) << 27)); \
615 } while (0)
618 * NOTE: When you add new codegen macros or change existing ones, you must
619 * expand riscv-codegen-test.c to cover them, and update riscv-codegen.exp32
620 * and riscv-codegen.exp64 as needed.
623 // RV32I
625 #define riscv_lui(p, rd, imm) _riscv_u_op ((p), 0b0110111, (rd), (imm))
626 #define riscv_auipc(p, rd, imm) _riscv_u_op ((p), 0b0010111, (rd), (imm))
627 #define riscv_jal(p, rd, imm) _riscv_j_op ((p), 0b1101111, (rd), (imm))
628 #define riscv_jalr(p, rd, rs1, imm) _riscv_i_op ((p), 0b1100111, 0b000, (rd), (rs1), (imm))
629 #define riscv_beq(p, rs1, rs2, imm) _riscv_b_op ((p), 0b1100011, 0b000, (rs1), (rs2), (imm))
630 #define riscv_bne(p, rs1, rs2, imm) _riscv_b_op ((p), 0b1100011, 0b001, (rs1), (rs2), (imm))
631 #define riscv_blt(p, rs1, rs2, imm) _riscv_b_op ((p), 0b1100011, 0b100, (rs1), (rs2), (imm))
632 #define riscv_bge(p, rs1, rs2, imm) _riscv_b_op ((p), 0b1100011, 0b101, (rs1), (rs2), (imm))
633 #define riscv_bltu(p, rs1, rs2, imm) _riscv_b_op ((p), 0b1100011, 0b110, (rs1), (rs2), (imm))
634 #define riscv_bgeu(p, rs1, rs2, imm) _riscv_b_op ((p), 0b1100011, 0b111, (rs1), (rs2), (imm))
635 #define riscv_lb(p, rd, rs1, imm) _riscv_i_op ((p), 0b0000011, 0b000, (rd), (rs1), (imm))
636 #define riscv_lh(p, rd, rs1, imm) _riscv_i_op ((p), 0b0000011, 0b001, (rd), (rs1), (imm))
637 #define riscv_lw(p, rd, rs1, imm) _riscv_i_op ((p), 0b0000011, 0b010, (rd), (rs1), (imm))
638 #define riscv_lbu(p, rd, rs1, imm) _riscv_i_op ((p), 0b0000011, 0b100, (rd), (rs1), (imm))
639 #define riscv_lhu(p, rd, rs1, imm) _riscv_i_op ((p), 0b0000011, 0b101, (rd), (rs1), (imm))
640 #define riscv_sb(p, rs2, rs1, imm) _riscv_s_op ((p), 0b0100011, 0b000, (rs2), (rs1), (imm))
641 #define riscv_sh(p, rs2, rs1, imm) _riscv_s_op ((p), 0b0100011, 0b001, (rs2), (rs1), (imm))
642 #define riscv_sw(p, rs2, rs1, imm) _riscv_s_op ((p), 0b0100011, 0b010, (rs2), (rs1), (imm))
643 #define riscv_addi(p, rd, rs1, imm) _riscv_i_op ((p), 0b0010011, 0b000, (rd), (rs1), (imm))
644 #define riscv_slti(p, rd, rs1, imm) _riscv_i_op ((p), 0b0010011, 0b010, (rd), (rs1), (imm))
645 #define riscv_sltiu(p, rd, rs1, imm) _riscv_i_op ((p), 0b0010011, 0b011, (rd), (rs1), (imm))
646 #define riscv_xori(p, rd, rs1, imm) _riscv_i_op ((p), 0b0010011, 0b100, (rd), (rs1), (imm))
647 #define riscv_ori(p, rd, rs1, imm) _riscv_i_op ((p), 0b0010011, 0b110, (rd), (rs1), (imm))
648 #define riscv_andi(p, rd, rs1, imm) _riscv_i_op ((p), 0b0010011, 0b111, (rd), (rs1), (imm))
649 #ifdef TARGET_RISCV32
650 #define riscv_slli(p, rd, rs1, shamt) _riscv_is_op ((p), 0b0010011, 0b001, 0b0000000, (rd), (rs1), (shamt))
651 #define riscv_srli(p, rd, rs1, shamt) _riscv_is_op ((p), 0b0010011, 0b101, 0b0000000, (rd), (rs1), (shamt))
652 #define riscv_srai(p, rd, rs1, shamt) _riscv_is_op ((p), 0b0010011, 0b101, 0b0100000, (rd), (rs1), (shamt))
653 #endif
654 #define riscv_add(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0110011, 0b000, 0b0000000, (rd), (rs1), (rs2))
655 #define riscv_sub(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0110011, 0b000, 0b0100000, (rd), (rs1), (rs2))
656 #define riscv_sll(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0110011, 0b001, 0b0000000, (rd), (rs1), (rs2))
657 #define riscv_slt(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0110011, 0b010, 0b0000000, (rd), (rs1), (rs2))
658 #define riscv_sltu(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0110011, 0b011, 0b0000000, (rd), (rs1), (rs2))
659 #define riscv_xor(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0110011, 0b100, 0b0000000, (rd), (rs1), (rs2))
660 #define riscv_srl(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0110011, 0b101, 0b0000000, (rd), (rs1), (rs2))
661 #define riscv_sra(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0110011, 0b101, 0b0100000, (rd), (rs1), (rs2))
662 #define riscv_or(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0110011, 0b110, 0b0000000, (rd), (rs1), (rs2))
663 #define riscv_and(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0110011, 0b111, 0b0000000, (rd), (rs1), (rs2))
664 #define riscv_fence(p, pred, succ) _riscv_f_op ((p), 0b0001111, 0b000, 0b00000, 0b00000, (pred), (succ), 0b0000)
665 #define riscv_fence_i(p) _riscv_f_op ((p), 0b0001111, 0b001, 0b00000, 0b00000, 0b0000, 0b0000, 0b0000)
666 #define riscv_ecall(p) _riscv_i_op ((p), 0b1110011, 0b000, 0b00000, 0b00000, 0b000000000000)
667 #define riscv_ebreak(p) _riscv_i_op ((p), 0b1110011, 0b000, 0b00000, 0b00000, 0b000000000001)
668 #define riscv_csrrw(p, rd, csr, rs1) _riscv_ic_op ((p), 0b1110011, 0b001, (rd), (csr), (rs1))
669 #define riscv_csrrs(p, rd, csr, rs1) _riscv_ic_op ((p), 0b1110011, 0b010, (rd), (csr), (rs1))
670 #define riscv_csrrc(p, rd, csr, rs1) _riscv_ic_op ((p), 0b1110011, 0b011, (rd), (csr), (rs1))
671 #define riscv_csrrwi(p, rd, csr, imm) _riscv_ic_op ((p), 0b1110011, 0b101, (rd), (csr), (imm))
672 #define riscv_csrrsi(p, rd, csr, imm) _riscv_ic_op ((p), 0b1110011, 0b110, (rd), (csr), (imm))
673 #define riscv_csrrci(p, rd, csr, imm) _riscv_ic_op ((p), 0b1110011, 0b111, (rd), (csr), (imm))
675 // RV64I
677 #ifdef TARGET_RISCV64
678 #define riscv_lwu(p, rd, rs1, imm) _riscv_i_op ((p), 0b0000011, 0b110, (rd), (rs1), (imm))
679 #define riscv_ld(p, rd, rs1, imm) _riscv_i_op ((p), 0b0000011, 0b011, (rd), (rs1), (imm))
680 #define riscv_sd(p, rs2, rs1, imm) _riscv_s_op ((p), 0b0100011, 0b011, (rs2), (rs1), (imm))
681 #define riscv_slli(p, rd, rs1, shamt) _riscv_ls_op ((p), 0b0010011, 0b001, 0b000000, (rd), (rs1), (shamt))
682 #define riscv_srli(p, rd, rs1, shamt) _riscv_ls_op ((p), 0b0010011, 0b101, 0b000000, (rd), (rs1), (shamt))
683 #define riscv_srai(p, rd, rs1, shamt) _riscv_ls_op ((p), 0b0010011, 0b101, 0b010000, (rd), (rs1), (shamt))
684 #define riscv_addiw(p, rd, rs1, imm) _riscv_i_op ((p), 0b0011011, 0b000, (rd), (rs1), (imm))
685 #define riscv_slliw(p, rd, rs1, shamt) _riscv_is_op ((p), 0b0011011, 0b001, 0b0000000, (rd), (rs1), (shamt))
686 #define riscv_srliw(p, rd, rs1, shamt) _riscv_is_op ((p), 0b0011011, 0b101, 0b0000000, (rd), (rs1), (shamt))
687 #define riscv_sraiw(p, rd, rs1, shamt) _riscv_is_op ((p), 0b0011011, 0b101, 0b0100000, (rd), (rs1), (shamt))
688 #define riscv_addw(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0111011, 0b000, 0b0000000, (rd), (rs1), (rs2))
689 #define riscv_subw(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0111011, 0b000, 0b0100000, (rd), (rs1), (rs2))
690 #define riscv_sllw(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0111011, 0b001, 0b0000000, (rd), (rs1), (rs2))
691 #define riscv_srlw(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0111011, 0b101, 0b0000000, (rd), (rs1), (rs2))
692 #define riscv_sraw(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0111011, 0b101, 0b0100000, (rd), (rs1), (rs2))
693 #endif
695 // RV32M
697 #define riscv_mul(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0110011, 0b000, 0b0000001, (rd), (rs1), (rs2))
698 #define riscv_mulh(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0110011, 0b001, 0b0000001, (rd), (rs1), (rs2))
699 #define riscv_mulhsu(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0110011, 0b010, 0b0000001, (rd), (rs1), (rs2))
700 #define riscv_mulhu(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0110011, 0b011, 0b0000001, (rd), (rs1), (rs2))
701 #define riscv_div(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0110011, 0b100, 0b0000001, (rd), (rs1), (rs2))
702 #define riscv_divu(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0110011, 0b101, 0b0000001, (rd), (rs1), (rs2))
703 #define riscv_rem(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0110011, 0b110, 0b0000001, (rd), (rs1), (rs2))
704 #define riscv_remu(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0110011, 0b111, 0b0000001, (rd), (rs1), (rs2))
706 // RV64M
708 #ifdef TARGET_RISCV64
709 #define riscv_mulw(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0111011, 0b000, 0b0000001, (rd), (rs1), (rs2))
710 #define riscv_divw(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0111011, 0b100, 0b0000001, (rd), (rs1), (rs2))
711 #define riscv_divuw(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0111011, 0b101, 0b0000001, (rd), (rs1), (rs2))
712 #define riscv_remw(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0111011, 0b110, 0b0000001, (rd), (rs1), (rs2))
713 #define riscv_remuw(p, rd, rs1, rs2) _riscv_r_op ((p), 0b0111011, 0b111, 0b0000001, (rd), (rs1), (rs2))
714 #endif
716 // RV32A
718 #define riscv_lr_w(p, ordering, rd, rs1) _riscv_a_op ((p), 0b0101111, 0b010, 0b00010, (ordering), (rd), 0b00000, (rs1))
719 #define riscv_sc_w(p, ordering, rd, rs2, rs1) _riscv_a_op ((p), 0b0101111, 0b010, 0b00011, (ordering), (rd), (rs2), (rs1))
720 #define riscv_amoswap_w(p, ordering, rd, rs2, rs1) _riscv_a_op ((p), 0b0101111, 0b010, 0b00001, (ordering), (rd), (rs2), (rs1))
721 #define riscv_amoadd_w(p, ordering, rd, rs2, rs1) _riscv_a_op ((p), 0b0101111, 0b010, 0b00000, (ordering), (rd), (rs2), (rs1))
722 #define riscv_amoxor_w(p, ordering, rd, rs2, rs1) _riscv_a_op ((p), 0b0101111, 0b010, 0b00100, (ordering), (rd), (rs2), (rs1))
723 #define riscv_amoand_w(p, ordering, rd, rs2, rs1) _riscv_a_op ((p), 0b0101111, 0b010, 0b01100, (ordering), (rd), (rs2), (rs1))
724 #define riscv_amoor_w(p, ordering, rd, rs2, rs1) _riscv_a_op ((p), 0b0101111, 0b010, 0b01000, (ordering), (rd), (rs2), (rs1))
725 #define riscv_amomin_w(p, ordering, rd, rs2, rs1) _riscv_a_op ((p), 0b0101111, 0b010, 0b10000, (ordering), (rd), (rs2), (rs1))
726 #define riscv_amomax_w(p, ordering, rd, rs2, rs1) _riscv_a_op ((p), 0b0101111, 0b010, 0b10100, (ordering), (rd), (rs2), (rs1))
727 #define riscv_amominu_w(p, ordering, rd, rs2, rs1) _riscv_a_op ((p), 0b0101111, 0b010, 0b11000, (ordering), (rd), (rs2), (rs1))
728 #define riscv_amomaxu_w(p, ordering, rd, rs2, rs1) _riscv_a_op ((p), 0b0101111, 0b010, 0b11100, (ordering), (rd), (rs2), (rs1))
730 // RV64A
732 #ifdef TARGET_RISCV64
733 #define riscv_lr_d(p, ordering, rd, rs1) _riscv_a_op ((p), 0b0101111, 0b011, 0b00010, (ordering), (rd), 0b00000, (rs1))
734 #define riscv_sc_d(p, ordering, rd, rs2, rs1) _riscv_a_op ((p), 0b0101111, 0b011, 0b00011, (ordering), (rd), (rs2), (rs1))
735 #define riscv_amoswap_d(p, ordering, rd, rs2, rs1) _riscv_a_op ((p), 0b0101111, 0b011, 0b00001, (ordering), (rd), (rs2), (rs1))
736 #define riscv_amoadd_d(p, ordering, rd, rs2, rs1) _riscv_a_op ((p), 0b0101111, 0b011, 0b00000, (ordering), (rd), (rs2), (rs1))
737 #define riscv_amoxor_d(p, ordering, rd, rs2, rs1) _riscv_a_op ((p), 0b0101111, 0b011, 0b00100, (ordering), (rd), (rs2), (rs1))
738 #define riscv_amoand_d(p, ordering, rd, rs2, rs1) _riscv_a_op ((p), 0b0101111, 0b011, 0b01100, (ordering), (rd), (rs2), (rs1))
739 #define riscv_amoor_d(p, ordering, rd, rs2, rs1) _riscv_a_op ((p), 0b0101111, 0b011, 0b01000, (ordering), (rd), (rs2), (rs1))
740 #define riscv_amomin_d(p, ordering, rd, rs2, rs1) _riscv_a_op ((p), 0b0101111, 0b011, 0b10000, (ordering), (rd), (rs2), (rs1))
741 #define riscv_amomax_d(p, ordering, rd, rs2, rs1) _riscv_a_op ((p), 0b0101111, 0b011, 0b10100, (ordering), (rd), (rs2), (rs1))
742 #define riscv_amominu_d(p, ordering, rd, rs2, rs1) _riscv_a_op ((p), 0b0101111, 0b011, 0b11000, (ordering), (rd), (rs2), (rs1))
743 #define riscv_amomaxu_d(p, ordering, rd, rs2, rs1) _riscv_a_op ((p), 0b0101111, 0b011, 0b11100, (ordering), (rd), (rs2), (rs1))
744 #endif
746 // RV32F
748 #define riscv_flw(p, rd, rs1, imm) _riscv_i_op ((p), 0b0000111, 0b010, (rd), (rs1), (imm))
749 #define riscv_fsw(p, rs2, rs1, imm) _riscv_s_op ((p), 0b0100111, 0b010, (rs2), (rs1), (imm))
750 #define riscv_fmadd_s(p, rm, rd, rs1, rs2, rs3) _riscv_r4_op ((p), 0b1000011, (rm), 0b00, (rd), (rs1), (rs2), (rs3))
751 #define riscv_fmsub_s(p, rm, rd, rs1, rs2, rs3) _riscv_r4_op ((p), 0b1000111, (rm), 0b00, (rd), (rs1), (rs2), (rs3))
752 #define riscv_fnmadd_s(p, rm, rd, rs1, rs2, rs3) _riscv_r4_op ((p), 0b1001011, (rm), 0b00, (rd), (rs1), (rs2), (rs3))
753 #define riscv_fnmsub_s(p, rm, rd, rs1, rs2, rs3) _riscv_r4_op ((p), 0b1001111, (rm), 0b00, (rd), (rs1), (rs2), (rs3))
754 #define riscv_fadd_s(p, rm, rd, rs1, rs2) _riscv_r_op ((p), 0b1010011, (rm), 0b0000000, (rd), (rs1), (rs2))
755 #define riscv_fsub_s(p, rm, rd, rs1, rs2) _riscv_r_op ((p), 0b1010011, (rm), 0b0000100, (rd), (rs1), (rs2))
756 #define riscv_fmul_s(p, rm, rd, rs1, rs2) _riscv_r_op ((p), 0b1010011, (rm), 0b0001000, (rd), (rs1), (rs2))
757 #define riscv_fdiv_s(p, rm, rd, rs1, rs2) _riscv_r_op ((p), 0b1010011, (rm), 0b0001100, (rd), (rs1), (rs2))
758 #define riscv_fsqrt_s(p, rm, rd, rs1) _riscv_r_op ((p), 0b1010011, (rm), 0b0101100, (rd), (rs1), 0b00000)
759 #define riscv_fsgnj_s(p, rd, rs1, rs2) _riscv_r_op ((p), 0b1010011, 0b000, 0b0010000, (rd), (rs1), (rs2))
760 #define riscv_fsgnjn_s(p, rd, rs1, rs2) _riscv_r_op ((p), 0b1010011, 0b001, 0b0010000, (rd), (rs1), (rs2))
761 #define riscv_fsgnjx_s(p, rd, rs1, rs2) _riscv_r_op ((p), 0b1010011, 0b010, 0b0010000, (rd), (rs1), (rs2))
762 #define riscv_fmin_s(p, rd, rs1, rs2) _riscv_r_op ((p), 0b1010011, 0b000, 0b0010100, (rd), (rs1), (rs2))
763 #define riscv_fmax_s(p, rd, rs1, rs2) _riscv_r_op ((p), 0b1010011, 0b001, 0b0010100, (rd), (rs1), (rs2))
764 #define riscv_fcvt_w_s(p, rm, rd, rs1) _riscv_r_op ((p), 0b1010011, (rm), 0b1100000, (rd), (rs1), 0b00000)
765 #define riscv_fcvt_wu_s(p, rm, rd, rs1) _riscv_r_op ((p), 0b1010011, (rm), 0b1100000, (rd), (rs1), 0b00001)
766 #define riscv_fmv_x_w(p, rd, rs1) _riscv_r_op ((p), 0b1010011, 0b000, 0b1110000, (rd), (rs1), 0b00000)
767 #define riscv_feq_s(p, rd, rs1, rs2) _riscv_r_op ((p), 0b1010011, 0b010, 0b1010000, (rd), (rs1), (rs2))
768 #define riscv_flt_s(p, rd, rs1, rs2) _riscv_r_op ((p), 0b1010011, 0b001, 0b1010000, (rd), (rs1), (rs2))
769 #define riscv_fle_s(p, rd, rs1, rs2) _riscv_r_op ((p), 0b1010011, 0b000, 0b1010000, (rd), (rs1), (rs2))
770 #define riscv_fclass_s(p, rd, rs1) _riscv_r_op ((p), 0b1010011, 0b001, 0b1110000, (rd), (rs1), 0b00000)
771 #define riscv_fcvt_s_w(p, rm, rd, rs1) _riscv_r_op ((p), 0b1010011, (rm), 0b1101000, (rd), (rs1), 0b00000)
772 #define riscv_fcvt_s_wu(p, rm, rd, rs1) _riscv_r_op ((p), 0b1010011, (rm), 0b1101000, (rd), (rs1), 0b00001)
773 #define riscv_fmv_w_x(p, rd, rs1) _riscv_r_op ((p), 0b1010011, 0b000, 0b1111000, (rd), (rs1), 0b00000)
775 // RV64F
777 #ifdef TARGET_RISCV64
778 #define riscv_fcvt_l_s(p, rm, rd, rs1) _riscv_r_op ((p), 0b1010011, (rm), 0b1100000, (rd), (rs1), 0b00010)
779 #define riscv_fcvt_lu_s(p, rm, rd, rs1) _riscv_r_op ((p), 0b1010011, (rm), 0b1100000, (rd), (rs1), 0b00011)
780 #define riscv_fcvt_s_l(p, rm, rd, rs1) _riscv_r_op ((p), 0b1010011, (rm), 0b1101000, (rd), (rs1), 0b00010)
781 #define riscv_fcvt_s_lu(p, rm, rd, rs1) _riscv_r_op ((p), 0b1010011, (rm), 0b1101000, (rd), (rs1), 0b00011)
782 #endif
784 // RV32D
786 #define riscv_fld(p, rd, rs1, imm) _riscv_i_op ((p), 0b0000111, 0b011, (rd), (rs1), (imm))
787 #define riscv_fsd(p, rs2, rs1, imm) _riscv_s_op ((p), 0b0100111, 0b011, (rs2), (rs1), (imm))
788 #define riscv_fmadd_d(p, rm, rd, rs1, rs2, rs3) _riscv_r4_op ((p), 0b1000011, (rm), 0b01, (rd), (rs1), (rs2), (rs3))
789 #define riscv_fmsub_d(p, rm, rd, rs1, rs2, rs3) _riscv_r4_op ((p), 0b1000111, (rm), 0b01, (rd), (rs1), (rs2), (rs3))
790 #define riscv_fnmadd_d(p, rm, rd, rs1, rs2, rs3) _riscv_r4_op ((p), 0b1001011, (rm), 0b01, (rd), (rs1), (rs2), (rs3))
791 #define riscv_fnmsub_d(p, rm, rd, rs1, rs2, rs3) _riscv_r4_op ((p), 0b1001111, (rm), 0b01, (rd), (rs1), (rs2), (rs3))
792 #define riscv_fadd_d(p, rm, rd, rs1, rs2) _riscv_r_op ((p), 0b1010011, (rm), 0b0000001, (rd), (rs1), (rs2))
793 #define riscv_fsub_d(p, rm, rd, rs1, rs2) _riscv_r_op ((p), 0b1010011, (rm), 0b0000101, (rd), (rs1), (rs2))
794 #define riscv_fmul_d(p, rm, rd, rs1, rs2) _riscv_r_op ((p), 0b1010011, (rm), 0b0001001, (rd), (rs1), (rs2))
795 #define riscv_fdiv_d(p, rm, rd, rs1, rs2) _riscv_r_op ((p), 0b1010011, (rm), 0b0001101, (rd), (rs1), (rs2))
796 #define riscv_fsqrt_d(p, rm, rd, rs1) _riscv_r_op ((p), 0b1010011, (rm), 0b0101101, (rd), (rs1), 0b00000)
797 #define riscv_fsgnj_d(p, rd, rs1, rs2) _riscv_r_op ((p), 0b1010011, 0b000, 0b0010001, (rd), (rs1), (rs2))
798 #define riscv_fsgnjn_d(p, rd, rs1, rs2) _riscv_r_op ((p), 0b1010011, 0b001, 0b0010001, (rd), (rs1), (rs2))
799 #define riscv_fsgnjx_d(p, rd, rs1, rs2) _riscv_r_op ((p), 0b1010011, 0b010, 0b0010001, (rd), (rs1), (rs2))
800 #define riscv_fmin_d(p, rd, rs1, rs2) _riscv_r_op ((p), 0b1010011, 0b000, 0b0010101, (rd), (rs1), (rs2))
801 #define riscv_fmax_d(p, rd, rs1, rs2) _riscv_r_op ((p), 0b1010011, 0b001, 0b0010101, (rd), (rs1), (rs2))
802 #define riscv_fcvt_s_d(p, rm, rd, rs1) _riscv_r_op ((p), 0b1010011, (rm), 0b0100000, (rd), (rs1), 0b00001)
803 #define riscv_fcvt_d_s(p, rd, rs1) _riscv_r_op ((p), 0b1010011, 0b000, 0b0100001, (rd), (rs1), 0b00000)
804 #define riscv_feq_d(p, rd, rs1, rs2) _riscv_r_op ((p), 0b1010011, 0b010, 0b1010001, (rd), (rs1), (rs2))
805 #define riscv_flt_d(p, rd, rs1, rs2) _riscv_r_op ((p), 0b1010011, 0b001, 0b1010001, (rd), (rs1), (rs2))
806 #define riscv_fle_d(p, rd, rs1, rs2) _riscv_r_op ((p), 0b1010011, 0b000, 0b1010001, (rd), (rs1), (rs2))
807 #define riscv_fclass_d(p, rd, rs1) _riscv_r_op ((p), 0b1010011, 0b001, 0b1110001, (rd), (rs1), 0b00000)
808 #define riscv_fcvt_w_d(p, rm, rd, rs1) _riscv_r_op ((p), 0b1010011, (rm), 0b1100001, (rd), (rs1), 0b00000)
809 #define riscv_fcvt_wu_d(p, rm, rd, rs1) _riscv_r_op ((p), 0b1010011, (rm), 0b1100001, (rd), (rs1), 0b00001)
810 #define riscv_fcvt_d_w(p, rd, rs1) _riscv_r_op ((p), 0b1010011, 0b000, 0b1101001, (rd), (rs1), 0b00000)
811 #define riscv_fcvt_d_wu(p, rd, rs1) _riscv_r_op ((p), 0b1010011, 0b000, 0b1101001, (rd), (rs1), 0b00001)
813 // RV64D
815 #ifdef TARGET_RISCV64
816 #define riscv_fcvt_l_d(p, rm, rd, rs1) _riscv_r_op ((p), 0b1010011, (rm), 0b1100001, (rd), (rs1), 0b00010)
817 #define riscv_fcvt_lu_d(p, rm, rd, rs1) _riscv_r_op ((p), 0b1010011, (rm), 0b1100001, (rd), (rs1), 0b00011)
818 #define riscv_fmv_x_d(p, rd, rs1) _riscv_r_op ((p), 0b1010011, 0b000, 0b1110001, (rd), (rs1), 0b00000)
819 #define riscv_fcvt_d_l(p, rm, rd, rs1) _riscv_r_op ((p), 0b1010011, (rm), 0b1101001, (rd), (rs1), 0b00010)
820 #define riscv_fcvt_d_lu(p, rm, rd, rs1) _riscv_r_op ((p), 0b1010011, (rm), 0b1101001, (rd), (rs1), 0b00011)
821 #define riscv_fmv_d_x(p, rd, rs1) _riscv_r_op ((p), 0b1010011, 0b000, 0b1111001, (rd), (rs1), 0b00000)
822 #endif
824 #endif