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.
7 #ifndef __MONO_RISCV_CODEGEN_H__
8 #define __MONO_RISCV_CODEGEN_H__
13 #ifdef MONO_RISCV_CODEGEN_TEST
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
25 #define g_assert(expr) \
27 if (G_UNLIKELY (!(expr))) { \
28 fprintf (stderr, "* Assertion at %s:%d, condition `%s' not met\n", __FILE__, __LINE__, #expr); \
69 RISCV_ZERO
= RISCV_X0
,
71 // Argument and return registers.
82 // Callee-saved registers.
94 RISCV_S10
= RISCV_X26
,
95 RISCV_S11
= RISCV_X27
,
97 // Temporary registers.
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.
119 #define RISCV_N_GREGS (32)
120 #define RISCV_N_GAREGS (8)
121 #define RISCV_N_GSREGS (12)
122 #define RISCV_N_GTREGS (7)
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)
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.
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
,
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
,
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) \
258 *(guint32 *) (p) = (insn); \
259 (p) += sizeof (guint32); \
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.
337 #define _riscv_r_op(p, opcode, funct3, funct7, rd, rs1, rs2) \
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) | \
351 * The R4-type encoding is used for floating point fused multiply-add
363 #define _riscv_r4_op(p, opcode, funct3, funct2, rd, rs1, rs2, rs3) \
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) | \
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.
386 * [20..31] imm[0..11]
389 #define _riscv_i_op(p, opcode, funct3, rd, rs1, imm) \
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) | \
398 (RISCV_ENCODE_I_IMM ((gint32) (gssize) (imm)))); \
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.
414 #define _riscv_is_op(p, opcode, funct3, rstype, rd, rs1, shamt) \
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) | \
423 (RISCV_BITS ((shamt), 0, 5) << 20) | \
428 * A further specialization of the I-type encoding used for shifts by immediate
429 * values in RV64I. The shift amount field is larger.
439 #define _riscv_ls_op(p, opcode, funct3, rstype, rd, rs1, shamt) \
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) | \
448 (RISCV_BITS ((shamt), 0, 6) << 20) | \
453 * This is a specialization of the I-type encoding used for accessing control
454 * and status registers.
463 #define _riscv_ic_op(p, opcode, funct3, rd, csr, rs1) \
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) | \
472 (RISCV_BITS ((csr), 0, 12) << 20)); \
476 * The S-type encoding is used for stores with signed offsets.
483 * [25..31] imm[5..11]
486 #define _riscv_s_op(p, opcode, funct3, rs2, rs1, imm) \
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) | \
495 (RISCV_ENCODE_S_IMM ((gint32) (gssize) (imm)))); \
499 * The B-type encoding is used for conditional branches with signed offsets.
507 * [25..30] imm[5..10]
511 #define _riscv_b_op(p, opcode, funct3, rs1, rs2, imm) \
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) | \
520 (RISCV_ENCODE_B_IMM ((gint32) (gssize) (imm)))); \
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.
529 * [12..31] imm[12..31]
532 #define _riscv_u_op(p, opcode, rd, imm) \
534 g_assert (RISCV_VALID_REG ((rd))); \
535 g_assert (RISCV_VALID_U_IMM ((guint32) (gsize) (imm))); \
536 _riscv_emit ((p), ((opcode) << 0) | \
538 (RISCV_ENCODE_U_IMM ((guint32) (gsize) (imm)))); \
542 * The J-type encoding is used exclusively for JAL.
546 * [12..19] imm[12..19]
548 * [21..30] imm[1..10]
552 #define _riscv_j_op(p, opcode, rd, imm) \
554 g_assert (RISCV_VALID_REG ((rd))); \
555 g_assert (RISCV_VALID_J_IMM ((gint32) (gssize) (imm))); \
556 _riscv_emit ((p), ((opcode) << 0) | \
558 (RISCV_ENCODE_J_IMM ((gint32) (gssize) (imm)))); \
562 * Fence instructions have a peculiar encoding that isn't quite like any of the
563 * other formal encoding categories.
574 #define _riscv_f_op(p, opcode, funct3, rd, rs1, pred, succ, imm) \
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) | \
584 (RISCV_BITS ((succ), 0, 4) << 20) | \
585 (RISCV_BITS ((pred), 0, 4) << 24) | \
586 (RISCV_BITS ((guint32) (gsize) (imm), 0, 4) << 28)); \
590 * Atomic instructions have a peculiar encoding that isn't quite like any of
591 * the other formal encoding categories.
602 #define _riscv_a_op(p, opcode, funct3, funct5, ordering, rd, rs2, rs1) \
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) | \
613 (RISCV_BITS ((ordering), 0, 2) << 25) | \
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.
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))
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))
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))
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))
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))
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))
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))
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)
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)
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)
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)