Skip to content

Commit 045b526

Browse files
authored
[Mono][RISC-V] emit mul inst instead of emulated mul (#85445)
* update makefile * add format file * use mul inst instead of emulate mul process stack size larger than imm32 * emit get_throw_trampoline * mono_riscv_throw_exception * fix error of stack trace * test case * output inst idiv fix mono_riscv_emit_branch_exc * implement mono_arch_get_throw_corlib_exception * fix rdiv * move ArgOnStack arg at prologue lowering OP_XOR_IMM&OP_IXOR_IMM * fix emit_imm * test imm * update test case * use swich to process return value * fix offset of params in a call * lowering OP_IDIV_IMM * fmt * remove test file * address comment
1 parent 42742cd commit 045b526

File tree

6 files changed

+347
-109
lines changed

6 files changed

+347
-109
lines changed

src/mono/mono/arch/riscv/riscv-codegen.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -293,8 +293,7 @@ enum {
293293
(RISCV_BITS ((ins), 12, 8) << 12) | (RISCV_SIGN ((ins)) << 20))
294294

295295
// Check a value for validity as an immediate.
296-
#define RISCV_VALID_IMM(value) \
297-
(((gint32)value) == (value))
296+
#define RISCV_VALID_IMM32(value) (((gint32)value) == (value))
298297
#define RISCV_VALID_I_IMM(value) \
299298
(RISCV_DECODE_I_IMM (RISCV_ENCODE_I_IMM ((value))) == (value))
300299
#define RISCV_VALID_S_IMM(value) \

src/mono/mono/mini/cpu-riscv64.mdesc

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -65,22 +65,22 @@ fcall: dest:f len:8 clob:c
6565
lcall: dest:a len:16 clob:c
6666
lcall_membase: dest:a src1:b len:8 clob:c
6767

68-
store_membase_reg: dest:b src1:i len:4
69-
storei1_membase_reg: dest:b src1:i len:4
70-
storei2_membase_reg: dest:b src1:i len:4
71-
storei4_membase_reg: dest:b src1:i len:4
72-
storei8_membase_reg: dest:b src1:i len:4
68+
store_membase_reg: dest:b src1:i len:24
69+
storei1_membase_reg: dest:b src1:i len:24
70+
storei2_membase_reg: dest:b src1:i len:24
71+
storei4_membase_reg: dest:b src1:i len:24
72+
storei8_membase_reg: dest:b src1:i len:24
7373
storer4_membase_reg: dest:b src1:f len:4
7474
storer8_membase_reg: dest:b src1:f len:4
7575

7676
load_membase: dest:i src1:b len:24
77-
loadu1_membase: dest:i src1:b len:16
78-
loadi1_membase: dest:i src1:b len:16
79-
loadu2_membase: dest:i src1:b len:16
80-
loadi2_membase: dest:i src1:b len:16
81-
loadu4_membase: dest:i src1:b len:16
82-
loadi4_membase: dest:i src1:b len:16
83-
loadi8_membase: dest:i src1:b len:16
77+
loadu1_membase: dest:i src1:b len:24
78+
loadi1_membase: dest:i src1:b len:24
79+
loadu2_membase: dest:i src1:b len:24
80+
loadi2_membase: dest:i src1:b len:24
81+
loadu4_membase: dest:i src1:b len:24
82+
loadi4_membase: dest:i src1:b len:24
83+
loadi8_membase: dest:i src1:b len:24
8484
loadr4_membase: dest:f src1:b len:16
8585
loadr8_membase: dest:f src1:b len:16
8686

@@ -110,10 +110,14 @@ int_sub: dest:i src1:i src2:i len:4
110110
long_sub: dest:i src1:i src2:i len:4
111111
int_mul: dest:i src1:i src2:i len:4
112112
r4_mul: dest:f src1:f src2:f len:4
113+
long_mul: dest:i src1:i src2:i len:4
113114
float_mul: dest:f src1:f src2:f len:4
115+
int_div: dest:i src1:i src2:i len:32
114116
long_div: dest:i src1:i src2:i len:32
117+
int_div_un: dest:i src1:i src2:i len:32
115118
long_div_un: dest:i src1:i src2:i len:32
116119
r4_div: dest:f src1:f src2:f len:36
120+
float_div: dest:f src1:f src2:f len:4
117121
int_rem: dest:i src1:i src2:i len:32
118122
long_rem: dest:i src1:i src2:i len:32
119123
int_rem_un: dest:i src1:i src2:i len:32
@@ -173,11 +177,11 @@ riscv_bge: src1:i src2:i len:8
173177
riscv_bgeu: src1:i src2:i len:8
174178
riscv_blt: src1:i src2:i len:8
175179
riscv_bltu: src1:i src2:i len:8
176-
riscv_exc_beq: src1:i src2:i len:32
177-
riscv_exc_bne: src1:i src2:i len:32
178-
riscv_exc_bgeu: src1:i src2:i len:32
179-
riscv_exc_blt: src1:i src2:i len:32
180-
riscv_exc_bltu: src1:i src2:i len:32
180+
riscv_exc_beq: src1:i src2:i len:12
181+
riscv_exc_bne: src1:i src2:i len:12
182+
riscv_exc_bgeu: src1:i src2:i len:12
183+
riscv_exc_blt: src1:i src2:i len:12
184+
riscv_exc_bltu: src1:i src2:i len:12
181185
riscv_slt: dest:i src1:i src2:i len:4
182186
riscv_sltu: dest:i src1:i src2:i len:4
183187
riscv_slti: dest:i src1:i len:4

src/mono/mono/mini/exceptions-riscv.c

Lines changed: 161 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "mini-runtime.h"
77

88
#include <mono/metadata/abi-details.h>
9+
#include <mono/metadata/tokentype.h>
910
#include <mono/utils/mono-sigcontext.h>
1011
#include "mono/utils/mono-tls-inline.h"
1112

@@ -67,18 +68,160 @@ mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot)
6768
return start;
6869
}
6970

71+
void
72+
mono_riscv_throw_exception (gpointer arg, host_mgreg_t pc, host_mgreg_t *int_regs, gdouble *fp_regs, gboolean corlib, gboolean rethrow, gboolean preserve_ips){
73+
ERROR_DECL (error);
74+
MonoContext ctx;
75+
MonoObject *exc = NULL;
76+
guint32 ex_token_index, ex_token;
77+
if (!corlib)
78+
exc = (MonoObject *)arg;
79+
else {
80+
ex_token_index = (guint64)arg;
81+
ex_token = MONO_TOKEN_TYPE_DEF | ex_token_index;
82+
exc = (MonoObject *)mono_exception_from_token (mono_defaults.corlib, ex_token);
83+
}
84+
85+
/* Adjust pc so it points into the call instruction */
86+
pc -= 4;
87+
88+
/* Initialize a ctx based on the arguments */
89+
memset (&ctx, 0, sizeof (MonoContext));
90+
memcpy (&(ctx.gregs [0]), int_regs, sizeof (host_mgreg_t) * RISCV_N_GREGS);
91+
memcpy (&(ctx.fregs [0]), fp_regs, sizeof (host_mgreg_t) * RISCV_N_FREGS);
92+
93+
ctx.gregs [0] = pc;
94+
95+
if (mono_object_isinst_checked (exc, mono_defaults.exception_class, error)) {
96+
MonoException *mono_ex = (MonoException *)exc;
97+
if (!rethrow && !mono_ex->caught_in_unmanaged) {
98+
mono_ex->stack_trace = NULL;
99+
mono_ex->trace_ips = NULL;
100+
} else if (preserve_ips) {
101+
mono_ex->caught_in_unmanaged = TRUE;
102+
}
103+
}
104+
105+
mono_error_assert_ok (error);
106+
107+
mono_handle_exception (&ctx, exc);
108+
109+
mono_restore_context (&ctx);
110+
}
111+
70112
gpointer
71113
mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
72114
{
73115
*info = NULL;
74116
return nop_stub (0x37);
75117
}
76118

119+
static gpointer
120+
get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm, gboolean resume_unwind, const char *tramp_name, MonoTrampInfo **info, gboolean aot, gboolean preserve_ips){
121+
guint8 *start, *code;
122+
MonoJumpInfo *ji = NULL;
123+
GSList *unwind_ops = NULL;
124+
int i, offset, gregs_offset, fregs_offset, frame_size, num_fregs;
125+
126+
code = start = mono_global_codeman_reserve (size);
127+
128+
/* This will being called by JITted code, the exception object/type token is in A0 */
129+
130+
/* Compute stack frame size and offsets */
131+
offset = 0;
132+
/* ra & fp */
133+
offset += 2 * sizeof (host_mgreg_t);
134+
135+
/* gregs */
136+
offset += RISCV_N_GREGS * sizeof (host_mgreg_t);
137+
gregs_offset = offset;
138+
139+
/* fregs */
140+
num_fregs = RISCV_N_FREGS;
141+
offset += num_fregs * sizeof (host_mgreg_t);
142+
fregs_offset = offset;
143+
frame_size = ALIGN_TO (offset, MONO_ARCH_FRAME_ALIGNMENT);
144+
145+
MINI_BEGIN_CODEGEN ();
146+
147+
/* Setup a frame */
148+
g_assert (RISCV_VALID_I_IMM (-frame_size));
149+
riscv_addi (code, RISCV_SP, RISCV_SP, -frame_size);
150+
code = mono_riscv_emit_store (code, RISCV_RA, RISCV_SP, frame_size - sizeof (host_mgreg_t), 0);
151+
code = mono_riscv_emit_store (code, RISCV_FP, RISCV_SP, frame_size - 2 * sizeof (host_mgreg_t), 0);
152+
riscv_addi (code, RISCV_FP, RISCV_SP, frame_size);
153+
154+
/* Save gregs */
155+
code = mono_riscv_emit_store_stack (code, 0xffffffff, RISCV_FP, -gregs_offset, FALSE);
156+
if (corlib && !llvm)
157+
/* The real ra is in A1 */
158+
code = mono_riscv_emit_store (code, RISCV_A1, RISCV_FP, -gregs_offset + (RISCV_RA * sizeof (host_mgreg_t)), 0);
159+
160+
/* Save previous fp/sp */
161+
code = mono_riscv_emit_load (code, RISCV_T0, RISCV_FP, -2 * sizeof (host_mgreg_t), 0);
162+
code = mono_riscv_emit_store (code, RISCV_T0, RISCV_FP, -gregs_offset + (RISCV_FP * sizeof (host_mgreg_t)), 0);
163+
// current fp is previous sp
164+
code = mono_riscv_emit_store (code, RISCV_FP, RISCV_FP, -gregs_offset + (RISCV_SP * sizeof (host_mgreg_t)), 0);
165+
166+
/* Save fregs */
167+
if (riscv_stdext_f || riscv_stdext_d)
168+
code = mono_riscv_emit_store_stack (code, 0xffffffff, RISCV_FP, -fregs_offset, TRUE);
169+
170+
/* Call the C trampoline function */
171+
/* Arg1 = exception object/type token */
172+
// riscv_addi (code, RISCV_A0, RISCV_A0, 0);
173+
/* Arg2 = caller ip, should be return address in this case */
174+
if (corlib) {
175+
// caller ip are set to A1 already
176+
if (llvm)
177+
NOT_IMPLEMENTED;
178+
} else
179+
code = mono_riscv_emit_load (code, RISCV_A1, RISCV_FP, -sizeof (host_mgreg_t), 0);
180+
/* Arg 3 = gregs */
181+
riscv_addi (code, RISCV_A2, RISCV_FP, -gregs_offset);
182+
/* Arg 4 = fregs */
183+
riscv_addi (code, RISCV_A3, RISCV_FP, -fregs_offset);
184+
/* Arg 5 = corlib */
185+
riscv_addi (code, RISCV_A4, RISCV_ZERO, corlib ? 1 : 0);
186+
/* Arg 6 = rethrow */
187+
riscv_addi (code, RISCV_A5, RISCV_ZERO, rethrow ? 1 : 0);
188+
if (!resume_unwind) {
189+
/* Arg 7 = preserve_ips */
190+
riscv_addi (code, RISCV_A6, RISCV_ZERO, preserve_ips ? 1 : 0);
191+
}
192+
193+
/* Call the function */
194+
if (aot) {
195+
NOT_IMPLEMENTED;
196+
} else {
197+
gpointer icall_func;
198+
199+
if (resume_unwind)
200+
// icall_func = (gpointer)mono_riscv_resume_unwind;
201+
NOT_IMPLEMENTED;
202+
else
203+
icall_func = (gpointer)mono_riscv_throw_exception;
204+
205+
code = mono_riscv_emit_imm (code, RISCV_RA, (guint64)icall_func);
206+
}
207+
riscv_jalr (code, RISCV_ZERO, RISCV_RA, 0);
208+
/* This shouldn't return */
209+
/* hang in debugger */
210+
riscv_ebreak (code);
211+
212+
g_assert ((code - start) < size);
213+
MINI_END_CODEGEN (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL);
214+
215+
if (info)
216+
*info = mono_tramp_info_create (tramp_name, start, code - start, ji, unwind_ops);
217+
218+
return MINI_ADDR_TO_FTNPTR (start);
219+
}
220+
77221
gpointer
78222
mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot)
79223
{
80-
*info = NULL;
81-
return nop_stub (0x77);
224+
return get_throw_trampoline (384, FALSE, FALSE, FALSE, FALSE, "throw_exception", info, aot, FALSE);
82225
}
83226

84227
gpointer
@@ -98,8 +241,7 @@ mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot)
98241
gpointer
99242
mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot)
100243
{
101-
*info = NULL;
102-
return nop_stub (0xaa);
244+
return get_throw_trampoline (384, TRUE, FALSE, FALSE, FALSE, "throw_corlib_exception", info, aot, FALSE);
103245
}
104246

105247
#else
@@ -160,8 +302,6 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls, MonoJitInfo *ji,
160302
MonoContext *ctx, MonoContext *new_ctx, MonoLMF **lmf,
161303
host_mgreg_t **save_locations, StackFrameInfo *frame)
162304
{
163-
gpointer ip = MONO_CONTEXT_GET_IP (ctx);
164-
165305
memset (frame, 0, sizeof (StackFrameInfo));
166306
frame->ji = ji;
167307

@@ -174,7 +314,6 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls, MonoJitInfo *ji,
174314
guint32 unwind_info_len;
175315
guint8 *unwind_info;
176316

177-
178317
if (ji->is_trampoline)
179318
frame->type = FRAME_TYPE_TRAMPOLINE;
180319
else
@@ -190,28 +329,32 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls, MonoJitInfo *ji,
190329
for (int i = 0; i < 10; i++)
191330
(regs + MONO_MAX_IREGS) [i] = *((host_mgreg_t*)&new_ctx->fregs [RISCV_F18 + i]);
192331

332+
gpointer ip = MINI_FTNPTR_TO_ADDR (MONO_CONTEXT_GET_IP (ctx));
333+
193334
gboolean success = mono_unwind_frame (unwind_info, unwind_info_len, (guint8 *)ji->code_start,
194335
(guint8 *)ji->code_start + ji->code_size, (guint8 *)ip, NULL, regs,
195336
MONO_MAX_IREGS + 12 + 1, save_locations, MONO_MAX_IREGS, (guint8 **)&cfa);
196337

197338
if (!success)
198339
return FALSE;
199340

200-
memcpy (&new_ctx->gregs, regs, sizeof (host_mgreg_t) * 32);
341+
memcpy (new_ctx->gregs, regs, sizeof (host_mgreg_t) * MONO_MAX_IREGS);
201342
for (int i = 0; i < 2; i++)
202343
*((host_mgreg_t*)&new_ctx->fregs [RISCV_F8 + i]) = (regs + MONO_MAX_IREGS) [i];
203344
for (int i = 0; i < 10; i++)
204-
*((host_mgreg_t*)&new_ctx->fregs [RISCV_F18 + i]) = (regs + MONO_MAX_IREGS) [i];
345+
*((host_mgreg_t *)&new_ctx->fregs [RISCV_F18 + i]) = (regs + MONO_MAX_IREGS) [2 + i];
205346

347+
new_ctx->gregs [0] = regs [RISCV_RA];
206348
new_ctx->gregs [RISCV_SP] = (host_mgreg_t)(gsize)cfa;
207349

208-
if (*lmf && (*lmf)->gregs [RISCV_FP] && (MONO_CONTEXT_GET_SP (ctx) >= (gpointer)(*lmf)->gregs [RISCV_SP])) {
350+
if (*lmf && (*lmf)->gregs [MONO_ARCH_LMF_REG_SP] &&
351+
(MONO_CONTEXT_GET_SP (ctx) >= (gpointer)(*lmf)->gregs [MONO_ARCH_LMF_REG_SP])) {
209352
/* remove any unused lmf */
210353
*lmf = (MonoLMF *)(((gsize)(*lmf)->previous_lmf) & ~(TARGET_SIZEOF_VOID_P - 1));
211354
}
212355

213-
/* we substract 1, so that the pc points into the call instruction */
214-
new_ctx->gregs [RISCV_ZERO]--;
356+
/* we subtract 1, so that the PC points into the call instruction */
357+
new_ctx->gregs [0]--;
215358

216359
return TRUE;
217360
} else if (*lmf) {
@@ -223,10 +366,14 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls, MonoJitInfo *ji,
223366
if (!ji)
224367
return FALSE;
225368

226-
memcpy (&new_ctx->gregs, (*lmf)->gregs, sizeof (host_mgreg_t) * RISCV_N_GREGS);
369+
g_assert (MONO_ARCH_LMF_REGS == ((MONO_ARCH_CALLEE_SAVED_REGS) | (1 << RISCV_SP)));
370+
371+
memcpy (&new_ctx->gregs [0], &(*lmf)->gregs [0], sizeof (host_mgreg_t) * RISCV_N_GREGS);
372+
// new_ctx->gregs [RISCV_FP] = (*lmf)->gregs [MONO_ARCH_LMF_REG_FP];
373+
// new_ctx->gregs [RISCV_SP] = (*lmf)->gregs [MONO_ARCH_LMF_REG_SP];
227374
new_ctx->gregs [0] = (*lmf)->pc; // use [0] as pc reg since x0 is hard-wired zero
228375

229-
/* we substract 1, so that the IP points into the call instruction */
376+
/* we subtract 1, so that the PC points into the call instruction */
230377
new_ctx->gregs [0]--;
231378

232379
*lmf = (MonoLMF *)(((gsize)(*lmf)->previous_lmf) & ~(TARGET_SIZEOF_VOID_P - 1));

0 commit comments

Comments
 (0)