[interp] Remove varargs from InterpFrame and recompute it instead (#16598)
[mono-project.git] / mono / mini / mini-riscv.c
blobf43a213ea71fef5357f4471c68bdaa9362bf16e9
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 #include <mono/utils/mono-hwcap.h>
9 #include "mini-runtime.h"
11 #ifdef TARGET_RISCV64
12 #include "cpu-riscv64.h"
13 #else
14 #include "cpu-riscv32.h"
15 #endif
17 static gboolean riscv_stdext_a, riscv_stdext_b, riscv_stdext_c,
18 riscv_stdext_d, riscv_stdext_f, riscv_stdext_j,
19 riscv_stdext_l, riscv_stdext_m, riscv_stdext_n,
20 riscv_stdext_p, riscv_stdext_q, riscv_stdext_t,
21 riscv_stdext_v;
23 void
24 mono_arch_cpu_init (void)
28 void
29 mono_arch_init (void)
31 riscv_stdext_a = mono_hwcap_riscv_has_stdext_a;
32 riscv_stdext_c = mono_hwcap_riscv_has_stdext_c;
33 riscv_stdext_d = mono_hwcap_riscv_has_stdext_d;
34 riscv_stdext_f = mono_hwcap_riscv_has_stdext_f;
35 riscv_stdext_m = mono_hwcap_riscv_has_stdext_m;
38 void
39 mono_arch_finish_init (void)
43 void
44 mono_arch_register_lowlevel_calls (void)
48 void
49 mono_arch_cleanup (void)
53 void
54 mono_arch_set_target (char *mtriple)
56 // riscv{32,64}[extensions]-[<vendor>-]<system>-<abi>
58 size_t len = strlen (MONO_RISCV_ARCHITECTURE);
60 if (!strncmp (mtriple, MONO_RISCV_ARCHITECTURE, len)) {
61 mtriple += len;
63 for (;;) {
64 char c = *mtriple;
66 if (!c || c == '-')
67 break;
69 // ISA manual says upper and lower case are both OK.
70 switch (c) {
71 case 'A':
72 case 'a':
73 riscv_stdext_a = TRUE;
74 break;
75 case 'B':
76 case 'b':
77 riscv_stdext_b = TRUE;
78 break;
79 case 'C':
80 case 'c':
81 riscv_stdext_c = TRUE;
82 break;
83 case 'D':
84 case 'd':
85 riscv_stdext_d = TRUE;
86 break;
87 case 'F':
88 case 'f':
89 riscv_stdext_f = TRUE;
90 break;
91 case 'J':
92 case 'j':
93 riscv_stdext_j = TRUE;
94 break;
95 case 'L':
96 case 'l':
97 riscv_stdext_l = TRUE;
98 break;
99 case 'M':
100 case 'm':
101 riscv_stdext_m = TRUE;
102 break;
103 case 'N':
104 case 'n':
105 riscv_stdext_n = TRUE;
106 break;
107 case 'P':
108 case 'p':
109 riscv_stdext_p = TRUE;
110 break;
111 case 'Q':
112 case 'q':
113 riscv_stdext_q = TRUE;
114 break;
115 case 'T':
116 case 't':
117 riscv_stdext_t = TRUE;
118 break;
119 case 'V':
120 case 'v':
121 riscv_stdext_v = TRUE;
122 break;
123 default:
124 break;
127 mtriple++;
132 guint32
133 mono_arch_cpu_optimizations (guint32 *exclude_mask)
135 *exclude_mask = 0;
136 return 0;
139 guint32
140 mono_arch_cpu_enumerate_simd_versions (void)
142 return 0;
145 gboolean
146 mono_arch_have_fast_tls (void)
148 return TRUE;
151 gboolean
152 mono_arch_opcode_supported (int opcode)
154 switch (opcode) {
155 case OP_ATOMIC_ADD_I4:
156 case OP_ATOMIC_EXCHANGE_I4:
157 case OP_ATOMIC_CAS_I4:
158 case OP_ATOMIC_LOAD_I1:
159 case OP_ATOMIC_LOAD_I2:
160 case OP_ATOMIC_LOAD_I4:
161 case OP_ATOMIC_LOAD_U1:
162 case OP_ATOMIC_LOAD_U2:
163 case OP_ATOMIC_LOAD_U4:
164 case OP_ATOMIC_STORE_I1:
165 case OP_ATOMIC_STORE_I2:
166 case OP_ATOMIC_STORE_I4:
167 case OP_ATOMIC_STORE_U1:
168 case OP_ATOMIC_STORE_U2:
169 case OP_ATOMIC_STORE_U4:
170 #ifdef TARGET_RISCV64
171 case OP_ATOMIC_ADD_I8:
172 case OP_ATOMIC_EXCHANGE_I8:
173 case OP_ATOMIC_CAS_I8:
174 case OP_ATOMIC_LOAD_I8:
175 case OP_ATOMIC_LOAD_U8:
176 case OP_ATOMIC_STORE_I8:
177 case OP_ATOMIC_STORE_U8:
178 #endif
179 return riscv_stdext_a;
180 case OP_ATOMIC_LOAD_R4:
181 case OP_ATOMIC_STORE_R4:
182 #ifdef TARGET_RISCV64
183 case OP_ATOMIC_LOAD_R8:
184 case OP_ATOMIC_STORE_R8:
185 #endif
186 return riscv_stdext_a && riscv_stdext_d;
187 default:
188 return FALSE;
192 const char *
193 mono_arch_regname (int reg)
195 static const char *names [RISCV_N_GREGS] = {
196 "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2",
197 "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5",
198 "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7",
199 "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6",
202 if (reg >= 0 && reg < G_N_ELEMENTS (names))
203 return names [reg];
205 return "x?";
208 const char*
209 mono_arch_fregname (int reg)
211 static const char *names [RISCV_N_FREGS] = {
212 "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7",
213 "fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5",
214 "fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7",
215 "fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11",
218 if (reg >= 0 && reg < G_N_ELEMENTS (names))
219 return names [reg];
221 return "f?";
224 gpointer
225 mono_arch_get_this_arg_from_call (host_mgreg_t *regs, guint8 *code)
227 return (gpointer) regs [RISCV_A0];
230 MonoMethod *
231 mono_arch_find_imt_method (host_mgreg_t *regs, guint8 *code)
233 return (MonoMethod *) regs [MONO_ARCH_IMT_REG];
236 MonoVTable *
237 mono_arch_find_static_call_vtable (host_mgreg_t *regs, guint8 *code)
239 return (MonoVTable *) regs [MONO_ARCH_VTABLE_REG];
242 host_mgreg_t
243 mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
245 return ctx->gregs [reg];
248 void
249 mono_arch_context_set_int_reg (MonoContext *ctx, int reg, host_mgreg_t val)
251 ctx->gregs [reg] = val;
254 void
255 mono_arch_flush_register_windows (void)
259 void
260 mono_arch_flush_icache (guint8 *code, gint size)
262 #ifndef MONO_CROSS_COMPILE
263 __builtin___clear_cache (code, code + size);
264 #endif
267 MonoDynCallInfo *
268 mono_arch_dyn_call_prepare (MonoMethodSignature *sig)
270 NOT_IMPLEMENTED;
271 return NULL;
274 void
275 mono_arch_dyn_call_free (MonoDynCallInfo *info)
277 NOT_IMPLEMENTED;
281 mono_arch_dyn_call_get_buf_size (MonoDynCallInfo *info)
283 NOT_IMPLEMENTED;
284 return 0;
287 void
288 mono_arch_start_dyn_call (MonoDynCallInfo *info, gpointer **args, guint8 *ret,
289 guint8 *buf)
291 NOT_IMPLEMENTED;
294 void
295 mono_arch_finish_dyn_call (MonoDynCallInfo *info, guint8 *buf)
297 NOT_IMPLEMENTED;
301 mono_arch_get_argument_info (MonoMethodSignature *csig, int param_count,
302 MonoJitArgumentInfo *arg_info)
304 NOT_IMPLEMENTED;
305 return 0;
308 void
309 mono_arch_patch_code_new (MonoCompile *cfg, MonoDomain *domain, guint8 *code,
310 MonoJumpInfo *ji, gpointer target)
312 NOT_IMPLEMENTED;
315 /* Set arguments in the ccontext (for i2n entry) */
316 void
317 mono_arch_set_native_call_context_args (CallContext *ccontext, gpointer frame, MonoMethodSignature *sig)
319 NOT_IMPLEMENTED;
322 /* Set return value in the ccontext (for n2i return) */
323 void
324 mono_arch_set_native_call_context_ret (CallContext *ccontext, gpointer frame, MonoMethodSignature *sig)
326 NOT_IMPLEMENTED;
329 /* Gets the arguments from ccontext (for n2i entry) */
330 void
331 mono_arch_get_native_call_context_args (CallContext *ccontext, gpointer frame, MonoMethodSignature *sig)
333 NOT_IMPLEMENTED;
336 /* Gets the return value from ccontext (for i2n exit) */
337 void
338 mono_arch_get_native_call_context_ret (CallContext *ccontext, gpointer frame, MonoMethodSignature *sig)
340 NOT_IMPLEMENTED;
343 #ifndef DISABLE_JIT
345 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
347 gboolean
348 mono_arch_is_soft_float (void)
350 return !riscv_stdext_d;
353 #endif
355 gboolean
356 mono_arch_opcode_needs_emulation (MonoCompile *cfg, int opcode)
358 switch (opcode) {
359 case OP_IDIV:
360 case OP_IDIV_UN:
361 case OP_IREM:
362 case OP_IREM_UN:
363 #ifdef TARGET_RISCV64
364 case OP_LDIV:
365 case OP_LDIV_UN:
366 case OP_LREM:
367 case OP_LREM_UN:
368 #endif
369 return !riscv_stdext_m;
370 default:
371 return TRUE;
375 gboolean
376 mono_arch_tailcall_supported (MonoCompile *cfg, MonoMethodSignature *caller_sig, MonoMethodSignature *callee_sig, gboolean virtual_)
378 NOT_IMPLEMENTED;
381 gboolean
382 mono_arch_is_inst_imm (int opcode, int imm_opcode, gint64 imm)
384 // TODO: Make a proper decision based on opcode.
385 return TRUE;
388 GList *
389 mono_arch_get_allocatable_int_vars (MonoCompile *cfg)
391 GList *vars = NULL;
393 for (guint i = 0; i < cfg->num_varinfo; i++) {
394 MonoInst *ins = cfg->varinfo [i];
395 MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
397 if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos)
398 continue;
400 if ((ins->flags & (MONO_INST_IS_DEAD | MONO_INST_VOLATILE | MONO_INST_INDIRECT)) ||
401 (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG))
402 continue;
404 if (!mono_is_regsize_var (ins->inst_vtype))
405 continue;
407 vars = g_list_prepend (vars, vmv);
410 vars = mono_varlist_sort (cfg, vars, 0);
412 return vars;
415 GList *
416 mono_arch_get_global_int_regs (MonoCompile *cfg)
418 GList *regs = NULL;
420 for (int i = RISCV_S0; i <= RISCV_S11; i++)
421 regs = g_list_prepend (regs, GUINT_TO_POINTER (i));
423 return regs;
426 guint32
427 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv)
429 return cfg->varinfo [vmv->idx]->opcode == OP_ARG ? 1 : 2;
432 #ifdef ENABLE_LLVM
434 LLVMCallInfo*
435 mono_arch_get_llvm_call_info (MonoCompile *cfg, MonoMethodSignature *sig)
437 NOT_IMPLEMENTED;
440 #endif
442 void
443 mono_arch_create_vars (MonoCompile *cfg)
445 NOT_IMPLEMENTED;
448 MonoInst *
449 mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod,
450 MonoMethodSignature *fsig, MonoInst **args)
452 return NULL;
455 void
456 mono_arch_emit_call (MonoCompile *cfg, MonoCallInst *call)
458 NOT_IMPLEMENTED;
461 void
462 mono_arch_emit_outarg_vt (MonoCompile *cfg, MonoInst *ins, MonoInst *src)
464 NOT_IMPLEMENTED;
467 void
468 mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
470 NOT_IMPLEMENTED;
473 void
474 mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
476 NOT_IMPLEMENTED;
479 void
480 mono_arch_decompose_long_opts (MonoCompile *cfg, MonoInst *long_ins)
482 #ifdef TARGET_RISCV32
483 NOT_IMPLEMENTED;
484 #endif
487 void
488 mono_arch_allocate_vars (MonoCompile *cfg)
490 NOT_IMPLEMENTED;
493 void
494 mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
496 NOT_IMPLEMENTED;
499 void
500 mono_arch_peephole_pass_1 (MonoCompile *cfg, MonoBasicBlock *bb)
504 void
505 mono_arch_peephole_pass_2 (MonoCompile *cfg, MonoBasicBlock *bb)
509 // Uses at most 8 bytes on RV32I and 16 bytes on RV64I.
510 guint8 *
511 mono_riscv_emit_imm (guint8 *code, int rd, gsize imm)
513 #ifdef TARGET_RISCV64
514 if (RISCV_VALID_I_IMM (imm)) {
515 riscv_addi (code, rd, RISCV_ZERO, imm);
516 return code;
520 * This is not pretty, but RV64I doesn't make it easy to load constants.
521 * Need to figure out something better.
523 riscv_jal (code, rd, sizeof (guint64));
524 *(guint64 *) code = imm;
525 code += sizeof (guint64);
526 riscv_ld (code, rd, rd, 0);
527 #else
528 if (RISCV_VALID_I_IMM (imm)) {
529 riscv_addi (code, rd, RISCV_ZERO, imm);
530 return code;
533 riscv_lui (code, rd, RISCV_BITS (imm, 12, 20));
535 if (!RISCV_VALID_U_IMM (imm))
536 riscv_ori (code, rd, rd, RISCV_BITS (imm, 0, 12));
537 #endif
539 return code;
542 // Uses at most 16 bytes on RV32I and 24 bytes on RV64I.
543 guint8 *
544 mono_riscv_emit_load (guint8 *code, int rd, int rs1, gint32 imm)
546 if (RISCV_VALID_I_IMM (imm)) {
547 #ifdef TARGET_RISCV64
548 riscv_ld (code, rd, rs1, imm);
549 #else
550 riscv_lw (code, rd, rs1, imm);
551 #endif
552 } else {
553 code = mono_riscv_emit_imm (code, rd, imm);
554 riscv_add (code, rd, rs1, rd);
555 #ifdef TARGET_RISCV64
556 riscv_ld (code, rd, rd, 0);
557 #else
558 riscv_lw (code, rd, rd, 0);
559 #endif
562 return code;
565 // May clobber t1. Uses at most 16 bytes on RV32I and 24 bytes on RV64I.
566 guint8 *
567 mono_riscv_emit_store (guint8 *code, int rs1, int rs2, gint32 imm)
569 if (RISCV_VALID_S_IMM (imm)) {
570 #ifdef TARGET_RISCV64
571 riscv_sd (code, rs1, rs2, imm);
572 #else
573 riscv_sw (code, rs1, rs2, imm);
574 #endif
575 } else {
576 code = mono_riscv_emit_imm (code, RISCV_T1, imm);
577 riscv_add (code, RISCV_T1, rs2, RISCV_T1);
578 #ifdef TARGET_RISCV64
579 riscv_sd (code, rs1, RISCV_T1, 0);
580 #else
581 riscv_sw (code, rs1, RISCV_T1, 0);
582 #endif
585 return code;
588 guint8 *
589 mono_arch_emit_prolog (MonoCompile *cfg)
591 NOT_IMPLEMENTED;
594 void
595 mono_arch_emit_epilog (MonoCompile *cfg)
597 NOT_IMPLEMENTED;
600 void
601 mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
603 NOT_IMPLEMENTED;
606 void
607 mono_arch_emit_exceptions (MonoCompile *cfg)
609 NOT_IMPLEMENTED;
612 guint32
613 mono_arch_get_patch_offset (guint8 *code)
615 NOT_IMPLEMENTED;
616 return 0;
619 GSList *
620 mono_arch_get_trampolines (gboolean aot)
622 NOT_IMPLEMENTED;
623 return NULL;
626 #endif
628 #if defined(MONO_ARCH_SOFT_DEBUG_SUPPORTED)
629 void
630 mono_arch_set_breakpoint (MonoJitInfo *ji, guint8 *ip)
632 NOT_IMPLEMENTED;
635 void
636 mono_arch_clear_breakpoint (MonoJitInfo *ji, guint8 *ip)
638 NOT_IMPLEMENTED;
641 void
642 mono_arch_start_single_stepping (void)
644 NOT_IMPLEMENTED;
647 void
648 mono_arch_stop_single_stepping (void)
650 NOT_IMPLEMENTED;
653 gboolean
654 mono_arch_is_single_step_event (void *info, void *sigctx)
656 NOT_IMPLEMENTED;
657 return FALSE;
660 gboolean
661 mono_arch_is_breakpoint_event (void *info, void *sigctx)
663 NOT_IMPLEMENTED;
664 return FALSE;
667 void
668 mono_arch_skip_breakpoint (MonoContext *ctx, MonoJitInfo *ji)
670 NOT_IMPLEMENTED;
673 void
674 mono_arch_skip_single_step (MonoContext *ctx)
676 NOT_IMPLEMENTED;
679 gpointer
680 mono_arch_get_seq_point_info (MonoDomain *domain, guint8 *code)
682 NOT_IMPLEMENTED;
683 return NULL;
685 #endif /* MONO_ARCH_SOFT_DEBUG_SUPPORTED */
687 gpointer
688 mono_arch_load_function (MonoJitICallId jit_icall_id)
690 return NULL;