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_MINI_RISCV_H__
8 #define __MONO_MINI_RISCV_H__
10 #include <mono/arch/riscv/riscv-codegen.h>
13 #define MONO_RISCV_ARCHITECTURE "riscv64"
15 #define MONO_RISCV_ARCHITECTURE "riscv32"
18 #if defined (RISCV_FPABI_SOFT)
19 #define MONO_ARCH_SOFT_FLOAT_FALLBACK
20 #define RISCV_FP_MODEL "soft-fp"
21 #elif defined (RISCV_FPABI_DOUBLE)
22 #define RISCV_FP_MODEL "double-fp"
23 #elif defined (RISCV_FPABI_SINGLE)
24 #define RISCV_FP_MODEL "single-fp"
25 #error "The single-precision RISC-V hard float ABI is not currently supported."
27 #error "Unknown RISC-V FPABI. This is probably a bug in configure.ac."
30 #define MONO_ARCH_ARCHITECTURE MONO_RISCV_ARCHITECTURE "," RISCV_FP_MODEL
33 #define MONO_ARCH_CPU_SPEC mono_riscv64_cpu_desc
35 #define MONO_ARCH_CPU_SPEC mono_riscv32_cpu_desc
38 #define MONO_MAX_IREGS (RISCV_N_GREGS)
39 #define MONO_MAX_FREGS (RISCV_N_FREGS)
42 * Register usage conventions:
44 * - a0..a7 and fa0..fa7 are argument/return registers.
45 * - s0..11 and fs0..fs11 are callee-saved registers.
46 * - a0..a1 are used as fixed registers (for the 'a' spec, soft float, and
47 * longs on 32-bit, as appropriate).
48 * - t0..t1, ra, and ft0..ft2 are used as scratch registers and can't be
49 * allocated by the register allocator.
50 * - t2 is used as the RGCTX/IMT register and can't be allocated by the
52 * - a0 is used as the VTable register for lazy fetch trampolines.
53 * - sp, fp, gp, and tp are all reserved by the ABI and can't be allocated by
54 * the register allocator.
55 * - x0 is hard-wired to zero and can't be allocated by the register allocator.
58 #define MONO_ARCH_CALLEE_REGS (0b11110000000000111111110000000000)
59 #define MONO_ARCH_CALLEE_SAVED_REGS (0b00001111111111000000001100000000)
61 #ifdef RISCV_FPABI_SOFT
63 #define MONO_ARCH_CALLEE_FREGS (0b11111111111111111111111111111000)
64 #define MONO_ARCH_CALLEE_SAVED_FREGS (0b00000000000000000000000000000000)
68 #define MONO_ARCH_CALLEE_FREGS (0b11110000000000111111110011111000)
69 #define MONO_ARCH_CALLEE_SAVED_FREGS (0b00001111111111000000001100000000)
73 #define MONO_ARCH_INST_SREG2_MASK(ins) \
75 #define MONO_ARCH_INST_IS_FLOAT(desc) \
76 (!mono_arch_is_soft_float () && (desc) == 'f')
80 #define MONO_ARCH_INST_FIXED_REG(desc) \
81 ((desc) == 'a' || (mono_arch_is_soft_float () && (desc) == 'f') ? RISCV_A0 : -1)
82 #define MONO_ARCH_INST_IS_REGPAIR(desc) \
84 #define MONO_ARCH_INST_REGPAIR_REG2(desc, hreg1) \
89 #define MONO_ARCH_INST_FIXED_REG(desc) \
90 ((desc) == 'a' || (desc) == 'l' || (mono_arch_is_soft_float () && (desc) == 'f') ? RISCV_A0 : -1)
91 #define MONO_ARCH_INST_IS_REGPAIR(desc) \
92 ((desc) == 'l' || (mono_arch_is_soft_float () && (desc) == 'f'))
93 #define MONO_ARCH_INST_REGPAIR_REG2(desc, hreg1) \
98 #define MONO_ARCH_RGCTX_REG (RISCV_T2)
99 #define MONO_ARCH_IMT_REG (RISCV_T2)
100 #define MONO_ARCH_VTABLE_REG (RISCV_A0)
102 #define MONO_ARCH_HAVE_VOLATILE_NON_PARAM_REGISTER 0
104 #define MONO_ARCH_USE_FPSTACK (FALSE)
106 #define MONO_ARCH_FRAME_ALIGNMENT (16)
107 #define MONO_ARCH_CODE_ALIGNMENT (32)
109 #define MONO_ARCH_EMULATE_MUL_DIV (1)
110 #define MONO_ARCH_EMULATE_FREM (1)
112 #ifdef TARGET_RISCV64
114 #define MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS (1)
118 #define MONO_ARCH_EMULATE_CONV_R8_UN (1)
119 #define MONO_ARCH_EMULATE_FCONV_TO_I8 (1)
120 #define MONO_ARCH_EMULATE_LCONV_TO_R8 (1)
121 #define MONO_ARCH_EMULATE_LCONV_TO_R4 (1)
122 #define MONO_ARCH_EMULATE_LCONV_TO_R8_UN (1)
124 #define MONO_ARCH_NEED_DIV_CHECK (1)
126 #define MONO_ARCH_HAVE_OP_TAIL_CALL (1)
127 #define MONO_ARCH_HAVE_OP_GENERIC_CLASS_INIT (1)
128 #define MONO_ARCH_HAVE_CARD_TABLE_WBARRIER (1)
130 #define MONO_ARCH_HAVE_GENERALIZED_IMT_TRAMPOLINE (1)
131 #define MONO_ARCH_HAVE_GENERAL_RGCTX_LAZY_FETCH_TRAMPOLINE (1)
132 #define MONO_ARCH_HAVE_SDB_TRAMPOLINES (1)
133 #define MONO_ARCH_HAVE_INTERP_PINVOKE_TRAMP (1)
134 #define MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES (1)
136 #define MONO_ARCH_USE_SIGACTION (1)
137 #define MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX (1)
139 #define MONO_ARCH_HAVE_CONTEXT_SET_INT_REG (1)
140 #define MONO_ARCH_HAVE_DECOMPOSE_LONG_OPTS (1)
141 #define MONO_ARCH_HAVE_DECOMPOSE_OPTS (1)
142 #define MONO_ARCH_HAVE_EXCEPTIONS_INIT (1)
143 #define MONO_ARCH_HAVE_GET_TRAMPOLINES (1)
144 #define MONO_ARCH_HAVE_OPCODE_NEEDS_EMULATION (1)
145 #define MONO_ARCH_HAVE_PATCH_CODE_NEW (1)
146 #define MONO_ARCH_HAVE_SETUP_ASYNC_CALLBACK (1)
147 #define MONO_ARCH_HAVE_SETUP_RESUME_FROM_SIGNAL_HANDLER_CTX (1)
149 #define MONO_ARCH_GSHARED_SUPPORTED (1)
150 #define MONO_ARCH_INTERPRETER_SUPPORTED (1)
151 //#define MONO_ARCH_AOT_SUPPORTED (1)
152 //#define MONO_ARCH_LLVM_SUPPORTED (1)
153 //#define MONO_ARCH_SOFT_DEBUG_SUPPORTED (1)
156 // #define MONO_ARCH_HAVE_INTERP_ENTRY_TRAMPOLINE (1)
157 // #define MONO_ARCH_HAVE_INTERP_PINVOKE_TRAMP (1)
158 // #define MONO_ARCH_HAVE_INTERP_NATIVE_TO_MANAGED (1)
163 #define MONO_CONTEXT_SET_LLVM_EXC_REG(ctx, exc) \
165 (ctx)->gregs [RISCV_A0] = (host_mgreg_t) exc; \
168 #define MONO_INIT_CONTEXT_FROM_FUNC(ctx, func) \
170 MONO_CONTEXT_SET_IP ((ctx), (func)); \
171 MONO_CONTEXT_SET_SP ((ctx), __builtin_frame_address (0)); \
172 MONO_CONTEXT_SET_BP ((ctx), __builtin_frame_address (0)); \
176 // If the second-lowest bit of this field is set, this is a MonoLMFExt.
177 gpointer previous_lmf
;
182 host_mgreg_t gregs
[RISCV_N_GSREGS
]; // s0..s11
183 double fregs
[RISCV_N_FSREGS
]; // fs0..fs11
186 #define MONO_ARCH_INIT_TOP_LMF_ENTRY(lmf)
192 MONO_R_RISCV_IMM
= 1,
194 MONO_R_RISCV_BEQ
= 3,
195 MONO_R_RISCV_BNE
= 4,
196 MONO_R_RISCV_BLT
= 5,
197 MONO_R_RISCV_BGE
= 6,
198 MONO_R_RISCV_BLTU
= 7,
199 MONO_R_RISCV_BGEU
= 8,
202 __attribute__ ((warn_unused_result
)) guint8
*
203 mono_riscv_emit_imm (guint8
*code
, int rd
, gsize imm
);
205 __attribute__ ((warn_unused_result
)) guint8
*
206 mono_riscv_emit_load (guint8
*code
, int rd
, int rs1
, gint32 imm
);
208 __attribute__ ((warn_unused_result
)) guint8
*
209 mono_riscv_emit_store (guint8
*code
, int rs1
, int rs2
, gint32 imm
);