diff --git a/src/mono/mono/arch/riscv/riscv-codegen.h b/src/mono/mono/arch/riscv/riscv-codegen.h
index 054c0b0744c4e3..1cd369c2bd9d1e 100644
--- a/src/mono/mono/arch/riscv/riscv-codegen.h
+++ b/src/mono/mono/arch/riscv/riscv-codegen.h
@@ -252,6 +252,21 @@ enum {
RISCV_ROUND_DY = 0b111, // Use current rounding mode in the FRM CSR.
};
+enum {
+ RISCV_FCLASS_NINF = 0b1 << 0, // Negative infinity.
+ RISCV_FCLASS_NN = 0b1 << 1, // Negative normal.
+ RISCV_FCLASS_ND = 0b1 << 2, // Negative denormal.
+ RISCV_FCLASS_NZ = 0b1 << 3, // Negative zero.
+ RISCV_FCLASS_PZ = 0b1 << 4, // Positive zero.
+ RISCV_FCLASS_PD = 0b1 << 5, // Positive denormal.
+ RISCV_FCLASS_PN = 0b1 << 6, // Positive normal.
+ RISCV_FCLASS_PINF = 0b1 << 7, // Positive infinity.
+ RISCV_FCLASS_SNAN = 0b1 << 8, // Signalling NaN.
+ RISCV_FCLASS_QNAN = 0b1 << 9, // Quiet NaN.
+ RISCV_FCLASS_INF = RISCV_FCLASS_NINF | RISCV_FCLASS_PINF,
+ RISCV_FCLASS_NAN = RISCV_FCLASS_SNAN | RISCV_FCLASS_QNAN,
+};
+
#define _riscv_emit(p, insn) \
do { \
*(guint32 *) (p) = (insn); \
diff --git a/src/mono/mono/mini/cpu-riscv64.mdesc b/src/mono/mono/mini/cpu-riscv64.mdesc
index 8eb340ea1fd2ea..eba087a9b5901c 100644
--- a/src/mono/mono/mini/cpu-riscv64.mdesc
+++ b/src/mono/mono/mini/cpu-riscv64.mdesc
@@ -45,6 +45,7 @@ endfilter: src1:i len:32
localloc: dest:i src1:i len:52
localloc_imm: dest:i len:28
generic_class_init: src1:a len:12 clob:c
+ckfinite: dest:f src1:f len:28
break: len:4
throw: src1:i len:4
@@ -63,23 +64,30 @@ vcall2: len:16 clob:c
vcall2_reg: src1:i len:16 clob:c
vcall2_membase: src1:b len:28 clob:c
fcall: dest:f len:8 clob:c
-rcall: dest:f len:8 clob:c
-rcall_membase: dest:f src1:b len:12 clob:c
fcall_reg: dest:f src1:i len:8 clob:c
fcall_membase: dest:f src1:b len:12 clob:c
+rcall: dest:f len:8 clob:c
+rcall_reg: dest:f src1:i len:8 clob:c
+rcall_membase: dest:f src1:b len:12 clob:c
# Note: in RV32, it shoule be
# lcall: dest:l ...
lcall: dest:a len:16 clob:c
+lcall_reg: dest:a src1:i len:4 clob:c
lcall_membase: dest:a src1:b len:8 clob:c
+tailcall_parameter: len:24
+tailcall: len:60 clob:c
+tailcall_membase: src1:b len:60 clob:c
+tailcall_reg: src1:b len:60 clob:c
+
store_membase_reg: dest:b src1:i len:24
storei1_membase_reg: dest:b src1:i len:24
storei2_membase_reg: dest:b src1:i len:24
storei4_membase_reg: dest:b src1:i len:24
storei8_membase_reg: dest:b src1:i len:24
-storer4_membase_reg: dest:b src1:f len:4
-storer8_membase_reg: dest:b src1:f len:4
+storer4_membase_reg: dest:b src1:f len:24
+storer8_membase_reg: dest:b src1:f len:24
load_membase: dest:i src1:b len:24
loadu1_membase: dest:i src1:b len:24
@@ -89,18 +97,26 @@ loadi2_membase: dest:i src1:b len:24
loadu4_membase: dest:i src1:b len:24
loadi4_membase: dest:i src1:b len:24
loadi8_membase: dest:i src1:b len:24
-loadr4_membase: dest:f src1:b len:16
-loadr8_membase: dest:f src1:b len:16
+loadr4_membase: dest:f src1:b len:24
+loadr8_membase: dest:f src1:b len:24
memory_barrier: len:4
atomic_add_i4: dest:i src1:i src2:i len:4
atomic_add_i8: dest:i src1:i src2:i len:4
+atomic_store_i1: dest:b src1:i len:8
atomic_store_u1: dest:b src1:i len:8
+atomic_store_i2: dest:b src1:i len:8
+atomic_store_u2: dest:b src1:i len:8
atomic_store_i4: dest:b src1:i len:8
-atomic_store_u8: dest:b src1:i len:8
+atomic_store_u4: dest:b src1:i len:8
atomic_store_i8: dest:b src1:i len:8
+atomic_store_u8: dest:b src1:i len:8
+atomic_load_i1: dest:b src1:i len:12
atomic_load_u1: dest:b src1:i len:12
+atomic_load_i2: dest:b src1:i len:12
+atomic_load_u2: dest:b src1:i len:12
atomic_load_i4: dest:b src1:i len:12
+atomic_load_u4: dest:b src1:i len:12
atomic_load_i8: dest:b src1:i len:12
atomic_load_u8: dest:b src1:i len:12
atomic_cas_i4: dest:i src1:i src2:i src3:i len:24
@@ -112,48 +128,65 @@ move: dest:i src1:i len:4
lmove: dest:i src1:i len:4
fmove: dest:f src1:f len:4
rmove: dest:f src1:f len:4
+move_f_to_i4: dest:i src1:f len:4
+move_i4_to_f: dest:f src1:i len:4
+move_f_to_i8: dest:i src1:f len:4
+move_i8_to_f: dest:f src1:i len:4
iconst: dest:i len:16
-i8const: dest:i len:16
int_add: dest:i src1:i src2:i len:4
-long_add: dest:i src1:i src2:i len:4
-float_add: dest:f src1:f src2:f len:4
int_sub: dest:i src1:i src2:i len:4
-long_sub: dest:i src1:i src2:i len:4
-float_sub: dest:f src1:f src2:f len:4
-float_neg: dest:f src1:f len:4
int_mul: dest:i src1:i src2:i len:4
-r4_mul: dest:f src1:f src2:f len:4
-long_mul: dest:i src1:i src2:i len:4
-float_mul: dest:f src1:f src2:f len:4
int_div: dest:i src1:i src2:i len:32
-long_div: dest:i src1:i src2:i len:32
int_div_un: dest:i src1:i src2:i len:32
-long_div_un: dest:i src1:i src2:i len:32
-r4_div: dest:f src1:f src2:f len:36
-float_div: dest:f src1:f src2:f len:36
int_rem: dest:i src1:i src2:i len:32
-long_rem: dest:i src1:i src2:i len:32
int_rem_un: dest:i src1:i src2:i len:32
+
+i8const: dest:i len:16
+long_add: dest:i src1:i src2:i len:4
+long_sub: dest:i src1:i src2:i len:4
+long_mul: dest:i src1:i src2:i len:4
+long_div: dest:i src1:i src2:i len:32
+long_div_un: dest:i src1:i src2:i len:32
+long_rem: dest:i src1:i src2:i len:32
long_rem_un: dest:i src1:i src2:i len:32
-r4const: dest:f len:16
r8const: dest:f len:16
+float_neg: dest:f src1:f len:4
+float_add: dest:f src1:f src2:f len:4
+float_sub: dest:f src1:f src2:f len:4
+float_mul: dest:f src1:f src2:f len:4
+float_div: dest:f src1:f src2:f len:36
+
+r4const: dest:f len:16
+r4_neg: dest:f src1:f len:4
+r4_add: dest:f src1:f src2:f len:4
+r4_sub: dest:f src1:f src2:f len:4
+r4_mul: dest:f src1:f src2:f len:4
+r4_div: dest:f src1:f src2:f len:36
+
+
int_conv_to_r4: dest:f src1:i len:4
int_conv_to_r8: dest:f src1:i len:4
r4_conv_to_i8: dest:i src1:f len:4
r4_conv_to_r8: dest:f src1:f len:4
r4_conv_to_i4: dest:i src1:f len:4
+r4_conv_to_u4: dest:i src1:f len:4
+r4_conv_to_u8: dest:i src1:f len:4
float_conv_to_i4: dest:i src1:f len:4
+float_conv_to_u4: dest:i src1:f len:4
float_conv_to_r4: dest:f src1:f len:4
float_conv_to_i8: dest:i src1:f len:4
+float_conv_to_u8: dest:i src1:f len:4
+
+r4_ceq: dest:i src1:f src2:f len:4
+r4_clt: dest:i src1:f src2:f len:4
+r4_clt_un: dest:i src1:f src2:f len:4
+r4_cle: dest:i src1:f src2:f len:4
float_ceq: dest:i src1:f src2:f len:4
float_cle: dest:i src1:f src2:f len:4
float_clt: dest:i src1:f src2:f len:4
float_clt_un: dest:i src1:f src2:f len:4
-r4_clt: dest:i src1:f src2:f len:4
-r4_clt_un: dest:i src1:f src2:f len:4
-r4_cle: dest:i src1:f src2:f len:4
add_imm: dest:i src1:i len:4
int_add_imm: dest:i src1:i len:4
@@ -182,15 +215,19 @@ long_and: dest:i src1:i src2:i len:4
long_and_imm: dest:i src1:i len:4
long_or: dest:i src1:i src2:i len:4
long_xor: dest:i src1:i src2:i len:4
+long_xor_imm: dest:i src1:i len:4
long_or_imm: dest:i src1:i len:4
long_shl: dest:i src1:i src2:i len:4
long_shl_imm: dest:i src1:i len:4
+long_shr: dest:i src1:i src2:i len:4
long_shr_un: dest:i src1:i src2:i len:4
long_shr_imm: dest:i src1:i len:4
long_shr_un_imm: dest:i src1:i len:4
riscv_setfreg_r4: dest:f src1:f len:4
+riscv_float_bnan: src1:f len:16
+riscv_r4_bnan: src1:f len:16
riscv_beq: src1:i src2:i len:8
riscv_bne: src1:i src2:i len:8
@@ -198,11 +235,11 @@ riscv_bge: src1:i src2:i len:8
riscv_bgeu: src1:i src2:i len:8
riscv_blt: src1:i src2:i len:8
riscv_bltu: src1:i src2:i len:8
-riscv_exc_beq: src1:i src2:i len:12
-riscv_exc_bne: src1:i src2:i len:12
-riscv_exc_bgeu: src1:i src2:i len:12
-riscv_exc_blt: src1:i src2:i len:12
-riscv_exc_bltu: src1:i src2:i len:12
+riscv_exc_beq: src1:i src2:i len:16
+riscv_exc_bne: src1:i src2:i len:16
+riscv_exc_bgeu: src1:i src2:i len:16
+riscv_exc_blt: src1:i src2:i len:16
+riscv_exc_bltu: src1:i src2:i len:16
riscv_slt: dest:i src1:i src2:i len:4
riscv_sltu: dest:i src1:i src2:i len:4
riscv_slti: dest:i src1:i len:4
diff --git a/src/mono/mono/mini/exceptions-riscv.c b/src/mono/mono/mini/exceptions-riscv.c
index fec9d18fafb603..40f65789fb5569 100644
--- a/src/mono/mono/mini/exceptions-riscv.c
+++ b/src/mono/mono/mini/exceptions-riscv.c
@@ -83,7 +83,7 @@ mono_riscv_throw_exception (gpointer arg, host_mgreg_t pc, host_mgreg_t *int_reg
}
/* Adjust pc so it points into the call instruction */
- pc -= 4;
+ pc--;
/* Initialize a ctx based on the arguments */
memset (&ctx, 0, sizeof (MonoContext));
@@ -114,7 +114,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
{
guint8 *code;
guint8 *start;
- int i, size, offset, gregs_offset, fregs_offset, ctx_offset, num_fregs, frame_size;
+ int size, offset, gregs_offset, fregs_offset, ctx_offset, frame_size;
MonoJumpInfo *ji = NULL;
GSList *unwind_ops = NULL;
diff --git a/src/mono/mono/mini/mini-ops.h b/src/mono/mono/mini/mini-ops.h
index 17dbc05d8763a1..ccdc1726a30258 100644
--- a/src/mono/mono/mini/mini-ops.h
+++ b/src/mono/mono/mini/mini-ops.h
@@ -1889,6 +1889,8 @@ MINI_OP(OP_RISCV_BGE, "riscv_bge", NONE, IREG, IREG)
MINI_OP(OP_RISCV_BGEU, "riscv_bgeu", NONE, IREG, IREG)
MINI_OP(OP_RISCV_BLT, "riscv_blt", NONE, IREG, IREG)
MINI_OP(OP_RISCV_BLTU, "riscv_bltu", NONE, IREG, IREG)
+MINI_OP(OP_RISCV_RBNAN, "riscv_r4_bnan", NONE, FREG, NONE)
+MINI_OP(OP_RISCV_FBNAN, "riscv_float_bnan", NONE, FREG, NONE)
MINI_OP(OP_RISCV_ADDIW, "riscv_addiw", IREG, IREG, NONE)
diff --git a/src/mono/mono/mini/mini-riscv.c b/src/mono/mono/mini/mini-riscv.c
index 4ef94ee41cd21c..afaa6838dd27f0 100644
--- a/src/mono/mono/mini/mini-riscv.c
+++ b/src/mono/mono/mini/mini-riscv.c
@@ -955,6 +955,7 @@ add_param (CallInfo *cinfo, ArgInfo *ainfo, MonoType *t)
add_valuetype (cinfo, ainfo, ptype);
break;
case MONO_TYPE_VALUETYPE:
+ case MONO_TYPE_TYPEDBYREF:
add_valuetype (cinfo, ainfo, ptype);
break;
@@ -1228,11 +1229,14 @@ mono_arch_opcode_needs_emulation (MonoCompile *cfg, int opcode)
return !riscv_stdext_m;
case OP_FADD:
+ case OP_RADD:
case OP_FSUB:
+ case OP_RSUB:
case OP_FDIV:
case OP_RDIV:
case OP_FMUL:
case OP_RMUL:
+ case OP_RNEG:
case OP_FNEG:
case OP_FMOVE:
case OP_RMOVE:
@@ -1258,15 +1262,23 @@ mono_arch_opcode_needs_emulation (MonoCompile *cfg, int opcode)
case OP_FBGT_UN:
case OP_RCONV_TO_I2:
case OP_RCONV_TO_I4:
+ case OP_RCONV_TO_U4:
case OP_ICONV_TO_R4:
+ case OP_FCONV_TO_I1:
+ case OP_FCONV_TO_U1:
+ case OP_FCONV_TO_I2:
+ case OP_FCONV_TO_U2:
+ case OP_FCONV_TO_I4:
+ case OP_FCONV_TO_R4:
+ case OP_FCONV_TO_U4:
#ifdef TARGET_RISCV64
case OP_R8CONST:
case OP_ICONV_TO_R8:
case OP_LCONV_TO_R8:
- case OP_FCONV_TO_I4:
- case OP_FCONV_TO_R4:
case OP_FCONV_TO_R8:
case OP_FCONV_TO_I8:
+ case OP_FCONV_TO_U8:
+ case OP_FCONV_TO_OVF_U8:
case OP_RCONV_TO_R8:
#endif
return !mono_arch_is_soft_float ();
@@ -1278,7 +1290,36 @@ mono_arch_opcode_needs_emulation (MonoCompile *cfg, int opcode)
gboolean
mono_arch_tailcall_supported (MonoCompile *cfg, MonoMethodSignature *caller_sig, MonoMethodSignature *callee_sig, gboolean virtual_)
{
- NOT_IMPLEMENTED;
+ g_assert (caller_sig);
+ g_assert (callee_sig);
+
+ CallInfo *caller_info = get_call_info (NULL, caller_sig);
+ CallInfo *callee_info = get_call_info (NULL, callee_sig);
+
+ // Do not tail call optimize functions with varargs passed by stack.
+ gboolean res = IS_SUPPORTED_TAILCALL (callee_sig->call_convention != MONO_CALL_VARARG);
+
+ // Byval parameters hand the function a pointer directly into the stack area
+ // we want to reuse during a tail call. Do not tail call optimize functions with
+ // byval parameters.
+ //
+ // Do not tail call optimize if stack is used to pass parameters.
+ const ArgInfo *ainfo;
+ ainfo = callee_info->args + callee_sig->hasthis;
+ for (int i = 0; res && i < callee_sig->param_count; ++i) {
+ res == IS_SUPPORTED_TAILCALL (ainfo [i].storage < ArgOnStack);
+ }
+
+ // Do not tail call optimize if callee uses structret semantics.
+ res &= IS_SUPPORTED_TAILCALL (callee_info->ret.storage < ArgVtypeByRef);
+
+ // Do not tail call optimize if caller uses structret semantics.
+ res &= IS_SUPPORTED_TAILCALL (caller_info->ret.storage < ArgVtypeByRef);
+
+ g_free (caller_info);
+ g_free (callee_info);
+
+ return res;
}
gboolean
@@ -1462,11 +1503,13 @@ emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
{
NOT_IMPLEMENTED;
MonoMethodSignature *tmp_sig;
- MonoInst *sig_arg;
+ int sig_reg;
if (MONO_IS_TAILCALL_OPCODE (call))
NOT_IMPLEMENTED;
+ g_assert (cinfo->sig_cookie.storage == ArgOnStack);
+
/*
* mono_ArgIterator_Setup assumes the signature cookie is
* passed first and all the arguments which were before it are
@@ -1479,12 +1522,10 @@ emit_sig_cookie (MonoCompile *cfg, MonoCallInst *call, CallInfo *cinfo)
memcpy (tmp_sig->params, call->signature->params + call->signature->sentinelpos,
tmp_sig->param_count * sizeof (MonoType *));
- MONO_INST_NEW (cfg, sig_arg, OP_ICONST);
- sig_arg->dreg = mono_alloc_ireg (cfg);
- sig_arg->inst_p0 = tmp_sig;
- MONO_ADD_INS (cfg->cbb, sig_arg);
+ sig_reg = mono_alloc_ireg (cfg);
+ MONO_EMIT_NEW_SIGNATURECONST (cfg, sig_reg, tmp_sig);
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, RISCV_SP, cinfo->sig_cookie.offset, sig_arg->dreg);
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, RISCV_SP, cinfo->sig_cookie.offset, sig_reg);
}
/**
@@ -1754,6 +1795,14 @@ mono_arch_emit_setret (MonoCompile *cfg, MonoMethod *method, MonoInst *val)
case ArgInFReg:
MONO_EMIT_NEW_UNALU (cfg, OP_FMOVE, cfg->ret->dreg, val->dreg);
break;
+#ifdef TARGET_RISCV64
+ case ArgInFRegR4:
+ if (COMPILE_LLVM (cfg))
+ NOT_IMPLEMENTED;
+ else
+ MONO_EMIT_NEW_UNALU (cfg, OP_RMOVE, cfg->ret->dreg, val->dreg);
+ break;
+#endif
default:
g_print ("can't process Storage type %d\n", cinfo->ret.storage);
NOT_IMPLEMENTED;
@@ -1764,18 +1813,30 @@ void
mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
{
switch (ins->opcode) {
- case OP_LADD:
- case OP_LADD_IMM:
+ case OP_CKFINITE:
+ case OP_FMOVE:
+ case OP_RMOVE:
case OP_IADD:
+ case OP_LADD:
+ case OP_RADD:
+ case OP_FADD:
case OP_IADD_IMM:
+ case OP_LADD_IMM:
case OP_IADD_OVF:
- case OP_FADD:
+ case OP_LADD_OVF:
+ case OP_LADD_OVF_UN:
+ case OP_IADD_OVF_UN:
case OP_ISUB:
case OP_LSUB:
case OP_FSUB:
+ case OP_RSUB:
case OP_ISUB_IMM:
case OP_LSUB_IMM:
case OP_ISUB_OVF:
+ case OP_LSUB_OVF:
+ case OP_ISUB_OVF_UN:
+ case OP_LSUB_OVF_UN:
+
case OP_INEG:
case OP_LAND:
case OP_LOR:
@@ -1787,22 +1848,37 @@ mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
case OP_ICONV_TO_U1:
case OP_ICONV_TO_I2:
case OP_ICONV_TO_U2:
+ case OP_RCONV_TO_I1:
+ case OP_RCONV_TO_U1:
+ case OP_RCONV_TO_I2:
+ case OP_RCONV_TO_U2:
case OP_RCONV_TO_I4:
+ case OP_RCONV_TO_U4:
+ case OP_FCONV_TO_I1:
+ case OP_FCONV_TO_U1:
+ case OP_FCONV_TO_I2:
+ case OP_FCONV_TO_U2:
case OP_FCONV_TO_I4:
+ case OP_FCONV_TO_U4:
case OP_ICONV_TO_R_UN:
case OP_LCONV_TO_R_UN:
case OP_ICONV_TO_R4:
+ case OP_LCONV_TO_R4:
+ case OP_RCONV_TO_R4:
case OP_RCONV_TO_R8:
#ifdef TARGET_RISCV64
case OP_LXOR_IMM:
case OP_LNEG:
case OP_ICONV_TO_I4:
+ case OP_ICONV_TO_OVF_I4:
+ case OP_ICONV_TO_OVF_I4_UN:
case OP_ICONV_TO_U4:
case OP_ICONV_TO_I8:
case OP_ICONV_TO_U8:
case OP_LCONV_TO_U:
case OP_LCONV_TO_I:
+ case OP_LCONV_TO_I1:
case OP_LCONV_TO_U1:
case OP_LCONV_TO_I2:
case OP_LCONV_TO_U2:
@@ -1811,17 +1887,41 @@ mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
case OP_LCONV_TO_I8:
case OP_LCONV_TO_U8:
+ case OP_LCONV_TO_OVF_I:
+ case OP_LCONV_TO_OVF_I_UN:
+ case OP_LCONV_TO_OVF_U:
+ case OP_LCONV_TO_OVF_U_UN:
+ case OP_LCONV_TO_OVF_I1:
+ case OP_LCONV_TO_OVF_I1_UN:
+ case OP_LCONV_TO_OVF_U1:
+ case OP_LCONV_TO_OVF_U1_UN:
+ case OP_LCONV_TO_OVF_I2:
+ case OP_LCONV_TO_OVF_I2_UN:
+ case OP_LCONV_TO_OVF_U2:
+ case OP_LCONV_TO_OVF_U2_UN:
+ case OP_LCONV_TO_OVF_I4:
+ case OP_LCONV_TO_OVF_I4_UN:
+ case OP_LCONV_TO_OVF_U4:
+ case OP_LCONV_TO_OVF_U4_UN:
+ case OP_LCONV_TO_OVF_I8:
+ case OP_LCONV_TO_OVF_I8_UN:
+ case OP_LCONV_TO_OVF_U8:
+ case OP_LCONV_TO_OVF_U8_UN:
+
case OP_ICONV_TO_R8:
case OP_LCONV_TO_R8:
- case OP_RCONV_TO_I2:
- case OP_FCONV_TO_I2:
case OP_FCONV_TO_R4:
case OP_FCONV_TO_R8:
case OP_FCONV_TO_I8:
+ case OP_FCONV_TO_U8:
case OP_FCONV_TO_OVF_I8:
+ case OP_FCONV_TO_OVF_U8:
case OP_RCONV_TO_I8:
+ case OP_RCONV_TO_U8:
case OP_RCONV_TO_OVF_I8:
+ case OP_RCONV_TO_OVF_U8:
#endif
+ case OP_RNEG:
case OP_FNEG:
case OP_IAND:
case OP_IAND_IMM:
@@ -1837,6 +1937,7 @@ mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
case OP_ISHL_IMM:
case OP_LSHL_IMM:
case OP_ISHR:
+ case OP_LSHR:
case OP_ISHR_UN:
case OP_LSHR_UN:
case OP_ISHR_IMM:
@@ -1850,51 +1951,49 @@ mono_arch_decompose_opts (MonoCompile *cfg, MonoInst *ins)
case OP_FMUL:
case OP_IMUL_IMM:
case OP_LMUL_IMM:
+ case OP_IMUL_OVF:
+ case OP_LMUL_OVF:
+ case OP_IMUL_OVF_UN:
+ case OP_LMUL_OVF_UN:
+ case OP_IMUL_OVF_UN_OOM:
+ case OP_LMUL_OVF_UN_OOM:
case OP_IDIV:
case OP_LDIV:
- case OP_LDIV_UN:
+ case OP_FDIV:
case OP_IDIV_UN:
+ case OP_LDIV_UN:
case OP_IDIV_IMM:
case OP_IDIV_UN_IMM:
case OP_RDIV:
case OP_IREM:
case OP_LREM:
+ case OP_FREM:
+ case OP_RREM:
case OP_IREM_IMM:
case OP_LREM_IMM:
case OP_IREM_UN:
case OP_LREM_UN:
case OP_IREM_UN_IMM:
+ case OP_ICONV_TO_OVF_I:
+ case OP_ICONV_TO_OVF_U:
+ case OP_ICONV_TO_OVF_I1:
+ case OP_ICONV_TO_OVF_I1_UN:
case OP_ICONV_TO_OVF_U1:
case OP_ICONV_TO_OVF_U1_UN:
+ case OP_ICONV_TO_OVF_I2:
+ case OP_ICONV_TO_OVF_I2_UN:
case OP_ICONV_TO_OVF_U2:
case OP_ICONV_TO_OVF_U2_UN:
+ case OP_ICONV_TO_OVF_I8:
+ case OP_ICONV_TO_OVF_I8_UN:
case OP_ICONV_TO_OVF_U4:
case OP_ICONV_TO_OVF_U4_UN:
case OP_ICONV_TO_OVF_U8:
case OP_ICONV_TO_OVF_U8_UN:
- case OP_LCONV_TO_OVF_I:
- case OP_LCONV_TO_OVF_U:
- case OP_LCONV_TO_OVF_U1:
- case OP_LCONV_TO_OVF_U1_UN:
- case OP_LCONV_TO_OVF_U2:
- case OP_LCONV_TO_OVF_U2_UN:
- case OP_LCONV_TO_OVF_I4:
- case OP_LCONV_TO_OVF_I4_UN:
- case OP_LCONV_TO_OVF_U4:
- case OP_LCONV_TO_OVF_U4_UN:
- case OP_LCONV_TO_OVF_U8:
- case OP_LCONV_TO_OVF_U8_UN:
+ case OP_ICONV_TO_OVF_I_UN:
+ case OP_ICONV_TO_OVF_U_UN:
- case OP_LADD_OVF:
- case OP_LADD_OVF_UN:
- case OP_LSUB_OVF:
- case OP_IMUL_OVF:
- case OP_LMUL_OVF:
- case OP_LMUL_OVF_UN:
- case OP_LMUL_OVF_UN_OOM:
-
- case OP_FDIV:
break;
default:
g_print ("Can't decompose the OP %s\n", mono_inst_name (ins->opcode));
@@ -1958,6 +2057,9 @@ mono_arch_allocate_vars (MonoCompile *cfg)
break;
case ArgInIReg:
case ArgInFReg:
+#ifdef TARGET_RISCV64
+ case ArgInFRegR4:
+#endif
cfg->ret->opcode = OP_REGVAR;
cfg->ret->inst_c0 = cinfo->ret.reg;
cfg->ret->dreg = cinfo->ret.reg;
@@ -2143,11 +2245,12 @@ mono_arch_allocate_vars (MonoCompile *cfg)
mono_bblock_insert_before_ins (bb, ins, (dest)); \
} while (0)
-#define NEW_INS_AFTER(cfg, ins, dest, op) \
+#define NEW_INS_AFTER(cfg, ins, next_ins, dest, op) \
do { \
MONO_INST_NEW ((cfg), (dest), (op)); \
(dest)->cil_code = (ins)->cil_code; \
mono_bblock_insert_after_ins (bb, ins, (dest)); \
+ next_ins = dest; \
} while (0)
/*
@@ -2159,7 +2262,7 @@ mono_arch_allocate_vars (MonoCompile *cfg)
void
mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
{
- MonoInst *ins, *last_ins, *n, *temp;
+ MonoInst *ins, *last_ins, *next_ins, *temp;
if (cfg->verbose_level > 2) {
g_print ("BASIC BLOCK %d (before lowering)\n", bb->block_num);
MONO_BB_FOR_EACH_INS (bb, ins)
@@ -2168,10 +2271,11 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
}
}
- MONO_BB_FOR_EACH_INS_SAFE (bb, n, ins)
+ MONO_BB_FOR_EACH_INS_SAFE (bb, next_ins, ins)
{
loop_start:
switch (ins->opcode) {
+ case OP_CKFINITE:
case OP_BREAK:
case OP_IL_SEQ_POINT:
case OP_SEQ_POINT:
@@ -2179,6 +2283,10 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
case OP_BR:
case OP_BR_REG:
case OP_JUMP_TABLE:
+ case OP_TAILCALL_PARAMETER:
+ case OP_TAILCALL:
+ case OP_TAILCALL_REG:
+ case OP_TAILCALL_MEMBASE:
case OP_CALL:
case OP_RCALL:
case OP_FCALL:
@@ -2196,10 +2304,17 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
case OP_MOVE:
case OP_RMOVE:
case OP_FMOVE:
+ case OP_MOVE_F_TO_I4:
+ case OP_MOVE_I4_TO_F:
+#ifdef TARGET_RISCV64
+ case OP_MOVE_F_TO_I8:
+ case OP_MOVE_I8_TO_F:
+#endif
case OP_LMOVE:
case OP_ISUB:
case OP_LSUB:
case OP_FSUB:
+ case OP_RSUB:
case OP_IADD:
case OP_LADD:
case OP_IMUL:
@@ -2225,18 +2340,10 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
case OP_LOR:
case OP_ISHL:
case OP_LSHL:
- case OP_SHL_IMM:
- case OP_ISHL_IMM:
- case OP_LSHL_IMM:
case OP_ISHR:
case OP_ISHR_UN:
- case OP_SHR_IMM:
- case OP_ISHR_IMM:
- case OP_SHR_UN_IMM:
- case OP_ISHR_UN_IMM:
+ case OP_LSHR:
case OP_LSHR_UN:
- case OP_LSHR_IMM:
- case OP_LSHR_UN_IMM:
case OP_LOCALLOC:
/* skip dummy IL */
@@ -2266,12 +2373,20 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
/* Atomic Ext */
case OP_MEMORY_BARRIER:
case OP_ATOMIC_ADD_I4:
+ case OP_ATOMIC_STORE_I1:
case OP_ATOMIC_STORE_U1:
+ case OP_ATOMIC_STORE_I2:
+ case OP_ATOMIC_STORE_U2:
case OP_ATOMIC_STORE_I4:
+ case OP_ATOMIC_STORE_U4:
case OP_ATOMIC_STORE_I8:
case OP_ATOMIC_STORE_U8:
+ case OP_ATOMIC_LOAD_I1:
case OP_ATOMIC_LOAD_U1:
+ case OP_ATOMIC_LOAD_I2:
+ case OP_ATOMIC_LOAD_U2:
case OP_ATOMIC_LOAD_I4:
+ case OP_ATOMIC_LOAD_U4:
case OP_ATOMIC_LOAD_I8:
case OP_ATOMIC_LOAD_U8:
case OP_ATOMIC_CAS_I4:
@@ -2284,49 +2399,31 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
/* Float Ext */
case OP_R8CONST:
+ case OP_RADD:
case OP_FADD:
+ case OP_RNEG:
case OP_FNEG:
case OP_ICONV_TO_R8:
case OP_RCONV_TO_R8:
case OP_RCONV_TO_I8:
case OP_RCONV_TO_I4:
+ case OP_RCONV_TO_U4:
case OP_FCONV_TO_I4:
+ case OP_FCONV_TO_U4:
case OP_FCONV_TO_R4:
case OP_FCONV_TO_I8:
case OP_FCEQ:
+ case OP_FCLE:
case OP_FCLT:
+ case OP_FCLT_UN:
+ case OP_RCEQ:
+ case OP_RCLE:
case OP_RCLT:
case OP_RCLT_UN:
- case OP_FCLT_UN:
case OP_RISCV_SETFREG_R4:
case OP_R4CONST:
case OP_ICONV_TO_R4:
break;
- case OP_FCONV_TO_I2:
- case OP_RCONV_TO_I2: {
- // fconv_to_i2 rd, fs1 => fconv_to_i{4|8} rs1, fs1; {i|l}conv_to_i2 rd, rs1
-#ifdef TARGET_RISCV64
- if (ins->opcode == OP_FCONV_TO_I2)
- NEW_INS_BEFORE (cfg, ins, temp, OP_FCONV_TO_I8);
- else
- NEW_INS_BEFORE (cfg, ins, temp, OP_RCONV_TO_I8);
-#else
- if (ins->opcode == OP_FCONV_TO_I2)
- NEW_INS_BEFORE (cfg, ins, temp, OP_FCONV_TO_I4);
- else
- NEW_INS_BEFORE (cfg, ins, temp, OP_RCONV_TO_I4);
-#endif
- temp->dreg = mono_alloc_ireg (cfg);
- temp->sreg1 = ins->sreg1;
-
-#ifdef TARGET_RISCV64
- ins->opcode = OP_LCONV_TO_I2;
-#else
- ins->opcode = OP_ICONV_TO_I2;
-#endif
- ins->sreg1 = temp->dreg;
- goto loop_start;
- }
case OP_RCGT:
case OP_RCGT_UN: {
// rcgt rd, rs1, rs2 -> rlt rd, rs2, rs1
@@ -2336,6 +2433,31 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
ins->sreg2 = tmp_reg;
break;
}
+ case OP_RCGE:
+ case OP_FCGE: {
+ // rcge rd, rs1, rs2 -> rcle rd, rs2, rs1
+ if (ins->opcode == OP_FCGE)
+ ins->opcode = OP_FCLE;
+ else
+ ins->opcode = OP_RCLE;
+ int tmp_reg = ins->sreg1;
+ ins->sreg1 = ins->sreg2;
+ ins->sreg2 = tmp_reg;
+ break;
+ }
+ case OP_RCNEQ:
+ case OP_FCNEQ: {
+ // fcneq rd, rs1, rs2 -> fceq rd, rs1, rs2, ceq rd, rd, zero
+ if (ins->opcode == OP_FCNEQ)
+ ins->opcode = OP_FCEQ;
+ else
+ ins->opcode = OP_RCEQ;
+ NEW_INS_AFTER (cfg, ins, next_ins, temp, OP_CEQ);
+ temp->dreg = ins->dreg;
+ temp->sreg1 = temp->dreg;
+ temp->sreg2 = RISCV_ZERO;
+ break;
+ }
case OP_FCGT:
case OP_FCGT_UN: {
// fcgt rd, rs1, rs2 -> flt rd, rs2, rs1
@@ -2345,16 +2467,129 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
ins->sreg2 = tmp_reg;
break;
}
+ case OP_FCONV_TO_I1:
+ case OP_RCONV_TO_I1: {
+ // fconv_to_i1 rd, fs1 => fconv_to_i{4|8} rs1, fs1; {i|l}conv_to_i1 rd, rs1
+ int rd = ins->dreg;
+#ifdef TARGET_RISCV64
+ NEW_INS_AFTER (cfg, ins, next_ins, temp, OP_LCONV_TO_I1);
+ if (ins->opcode == OP_FCONV_TO_I1)
+ ins->opcode = OP_FCONV_TO_I8;
+ else
+ ins->opcode = OP_RCONV_TO_I8;
+#else
+ NEW_INS_AFTER (cfg, ins, next_ins, temp, OP_ICONV_TO_I1);
+ if (ins->opcode == OP_FCONV_TO_I1)
+ ins->opcode = OP_FCONV_TO_I4;
+ else
+ ins->opcode = OP_RCONV_TO_I4;
+#endif
+ ins->dreg = mono_alloc_ireg (cfg);
+
+ temp->dreg = rd;
+ temp->sreg1 = ins->dreg;
+ break;
+ }
+ case OP_FCONV_TO_U1:
+ case OP_RCONV_TO_U1: {
+ // fconv_to_u1 rd, fs1 => fconv_to_u{4|8} rs1, fs1; {i|l}conv_to_u1 rd, rs1
+ int rd = ins->dreg;
+#ifdef TARGET_RISCV64
+ NEW_INS_AFTER (cfg, ins, next_ins, temp, OP_LCONV_TO_U1);
+ if (ins->opcode == OP_FCONV_TO_U1)
+ ins->opcode = OP_FCONV_TO_U8;
+ else
+ ins->opcode = OP_RCONV_TO_U8;
+#else
+ NEW_INS_AFTER (cfg, ins, next_ins, temp, OP_ICONV_TO_U1);
+ if (ins->opcode == OP_FCONV_TO_U1)
+ ins->opcode = OP_FCONV_TO_U4;
+ else
+ ins->opcode = OP_RCONV_TO_U4;
+#endif
+ ins->dreg = mono_alloc_ireg (cfg);
+
+ temp->dreg = rd;
+ temp->sreg1 = ins->dreg;
+ break;
+ }
+ case OP_FCONV_TO_I2:
+ case OP_RCONV_TO_I2: {
+ // fconv_to_i2 rd, fs1 => fconv_to_i{4|8} rs1, fs1; {i|l}conv_to_i2 rd, rs1
+ int rd = ins->dreg;
+#ifdef TARGET_RISCV64
+ NEW_INS_AFTER (cfg, ins, next_ins, temp, OP_LCONV_TO_I2);
+ if (ins->opcode == OP_FCONV_TO_I2)
+ ins->opcode = OP_FCONV_TO_I8;
+ else
+ ins->opcode = OP_RCONV_TO_I8;
+#else
+ NEW_INS_AFTER (cfg, ins, next_ins, temp, OP_ICONV_TO_I2);
+ if (ins->opcode == OP_FCONV_TO_I2)
+ ins->opcode = OP_FCONV_TO_I4;
+ else
+ ins->opcode = OP_RCONV_TO_I4;
+#endif
+ ins->dreg = mono_alloc_ireg (cfg);
+
+ temp->dreg = rd;
+ temp->sreg1 = ins->dreg;
+ break;
+ }
+ case OP_FCONV_TO_U2:
+ case OP_RCONV_TO_U2: {
+ // fconv_to_u2 rd, fs1 => fconv_to_u{4|8} rs1, fs1; {i|l}conv_to_u2 rd, rs1
+ int rd = ins->dreg;
+#ifdef TARGET_RISCV64
+ NEW_INS_AFTER (cfg, ins, next_ins, temp, OP_LCONV_TO_U2);
+ if (ins->opcode == OP_FCONV_TO_U2)
+ ins->opcode = OP_FCONV_TO_U8;
+ else
+ ins->opcode = OP_RCONV_TO_U8;
+#else
+ NEW_INS_AFTER (cfg, ins, next_ins, temp, OP_ICONV_TO_U2);
+ if (ins->opcode == OP_FCONV_TO_U2)
+ ins->opcode = OP_FCONV_TO_U4;
+ else
+ ins->opcode = OP_RCONV_TO_U4;
+#endif
+ ins->dreg = mono_alloc_ireg (cfg);
+
+ temp->dreg = rd;
+ temp->sreg1 = ins->dreg;
+ break;
+ }
+ case OP_RCONV_TO_R4: {
+ if (ins->dreg != ins->sreg1)
+ ins->opcode = OP_RMOVE;
+ else
+ NULLIFY_INS (ins);
+ break;
+ }
case OP_RCOMPARE: {
- if (ins->next) {
- if (ins->next->opcode == OP_FBLT || ins->next->opcode == OP_FBLT_UN) {
+ if (next_ins) {
+ // insert two OP_RISCV_FBNAN in case unordered compare
+ if (next_ins->opcode == OP_FBLT_UN || next_ins->opcode == OP_FBGT_UN ||
+ next_ins->opcode == OP_FBGE_UN || next_ins->opcode == OP_FBLE_UN ||
+ next_ins->opcode == OP_FBNE_UN) {
+ NEW_INS_BEFORE (cfg, ins, temp, OP_RISCV_RBNAN);
+ temp->sreg1 = ins->sreg1;
+ temp->inst_many_bb = mono_mempool_alloc (cfg->mempool, sizeof (gpointer) * 2);
+ temp->inst_true_bb = next_ins->inst_true_bb;
+ NEW_INS_BEFORE (cfg, ins, temp, OP_RISCV_RBNAN);
+ temp->sreg1 = ins->sreg2;
+ temp->inst_many_bb = mono_mempool_alloc (cfg->mempool, sizeof (gpointer) * 2);
+ temp->inst_true_bb = next_ins->inst_true_bb;
+ }
+
+ if (next_ins->opcode == OP_FBLT || next_ins->opcode == OP_FBLT_UN) {
ins->opcode = OP_RCLT;
ins->dreg = mono_alloc_ireg (cfg);
- ins->next->opcode = OP_RISCV_BNE;
- ins->next->sreg1 = ins->dreg;
- ins->next->sreg2 = RISCV_ZERO;
- } else if (ins->next->opcode == OP_FBGT || ins->next->opcode == OP_FBGT_UN) {
+ next_ins->opcode = OP_RISCV_BNE;
+ next_ins->sreg1 = ins->dreg;
+ next_ins->sreg2 = RISCV_ZERO;
+ } else if (next_ins->opcode == OP_FBGT || next_ins->opcode == OP_FBGT_UN) {
// rcmp rd, rs1, rs2; fbgt rd -> rcgt rd, rs1, rs2; bne rd, X0
// rcgt rd, rs1, rs2 -> flt.s rd, rs2, rs1
ins->opcode = OP_RCLT;
@@ -2363,10 +2598,10 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
ins->sreg1 = ins->sreg2;
ins->sreg2 = tmp_reg;
- ins->next->opcode = OP_RISCV_BNE;
- ins->next->sreg1 = ins->dreg;
- ins->next->sreg2 = RISCV_ZERO;
- } else if (ins->next->opcode == OP_FBGE || ins->next->opcode == OP_FBGE_UN) {
+ next_ins->opcode = OP_RISCV_BNE;
+ next_ins->sreg1 = ins->dreg;
+ next_ins->sreg2 = RISCV_ZERO;
+ } else if (next_ins->opcode == OP_FBGE || next_ins->opcode == OP_FBGE_UN) {
// rcmp rd, rs1, rs2; fbge rd -> rcle rd, rs2, rs1; bne rd, X0
ins->opcode = OP_RCLE;
ins->dreg = mono_alloc_ireg (cfg);
@@ -2374,18 +2609,34 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
ins->sreg1 = ins->sreg2;
ins->sreg2 = tmp_reg;
- ins->next->opcode = OP_RISCV_BNE;
- ins->next->sreg1 = ins->dreg;
- ins->next->sreg2 = RISCV_ZERO;
- } else if (ins->next->opcode == OP_FBLE || ins->next->opcode == OP_FBLE_UN) {
+ next_ins->opcode = OP_RISCV_BNE;
+ next_ins->sreg1 = ins->dreg;
+ next_ins->sreg2 = RISCV_ZERO;
+ } else if (next_ins->opcode == OP_FBLE || next_ins->opcode == OP_FBLE_UN) {
ins->opcode = OP_RCLE;
ins->dreg = mono_alloc_ireg (cfg);
- ins->next->opcode = OP_RISCV_BNE;
- ins->next->sreg1 = ins->dreg;
- ins->next->sreg2 = RISCV_ZERO;
+ next_ins->opcode = OP_RISCV_BNE;
+ next_ins->sreg1 = ins->dreg;
+ next_ins->sreg2 = RISCV_ZERO;
+ } else if (next_ins->opcode == OP_FBEQ) {
+ // rcmp rs1, rs2; fbeq rd -> rceq rd, rs1, rs2; bne rd, X0
+ ins->opcode = OP_RCEQ;
+ ins->dreg = mono_alloc_ireg (cfg);
+
+ next_ins->opcode = OP_RISCV_BNE;
+ next_ins->sreg1 = ins->dreg;
+ next_ins->sreg2 = RISCV_ZERO;
+ } else if (next_ins->opcode == OP_FBNE_UN) {
+ // rcmp rs1, rs2; fbne rd -> rceq rd, rs1, rs2; beq rd, X0
+ ins->opcode = OP_RCEQ;
+ ins->dreg = mono_alloc_ireg (cfg);
+
+ next_ins->opcode = OP_RISCV_BEQ;
+ next_ins->sreg1 = ins->dreg;
+ next_ins->sreg2 = RISCV_ZERO;
} else {
- g_print ("Unhandaled op %s following after OP_RCOMPARE\n", mono_inst_name (ins->next->opcode));
+ g_print ("Unhandaled op %s following after OP_RCOMPARE\n", mono_inst_name (next_ins->opcode));
NOT_IMPLEMENTED;
}
} else {
@@ -2394,15 +2645,29 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
break;
}
case OP_FCOMPARE: {
- if (ins->next) {
- if (ins->next->opcode == OP_FBLT || ins->next->opcode == OP_FBLT_UN) {
+ if (next_ins) {
+ if (next_ins->opcode == OP_FBLT_UN || next_ins->opcode == OP_FBGT_UN ||
+ next_ins->opcode == OP_FBGE_UN || next_ins->opcode == OP_FBLE_UN ||
+ next_ins->opcode == OP_FBNE_UN) {
+ // insert two OP_RISCV_FBNAN in case unordered compare
+ NEW_INS_BEFORE (cfg, ins, temp, OP_RISCV_FBNAN);
+ temp->sreg1 = ins->sreg1;
+ temp->inst_many_bb = mono_mempool_alloc (cfg->mempool, sizeof (gpointer) * 2);
+ temp->inst_true_bb = next_ins->inst_true_bb;
+ NEW_INS_BEFORE (cfg, ins, temp, OP_RISCV_FBNAN);
+ temp->sreg1 = ins->sreg2;
+ temp->inst_many_bb = mono_mempool_alloc (cfg->mempool, sizeof (gpointer) * 2);
+ temp->inst_true_bb = next_ins->inst_true_bb;
+ }
+
+ if (next_ins->opcode == OP_FBLT || next_ins->opcode == OP_FBLT_UN) {
ins->opcode = OP_FCLT;
ins->dreg = mono_alloc_ireg (cfg);
- ins->next->opcode = OP_RISCV_BNE;
- ins->next->sreg1 = ins->dreg;
- ins->next->sreg2 = RISCV_ZERO;
- } else if (ins->next->opcode == OP_FBGT || ins->next->opcode == OP_FBGT_UN) {
+ next_ins->opcode = OP_RISCV_BNE;
+ next_ins->sreg1 = ins->dreg;
+ next_ins->sreg2 = RISCV_ZERO;
+ } else if (next_ins->opcode == OP_FBGT || next_ins->opcode == OP_FBGT_UN) {
// fcmp rd, rs1, rs2; fbgt rd -> fclt rd, rs2, rs1; bne rd, X0
ins->opcode = OP_FCLT;
ins->dreg = mono_alloc_ireg (cfg);
@@ -2410,10 +2675,10 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
ins->sreg1 = ins->sreg2;
ins->sreg2 = tmp_reg;
- ins->next->opcode = OP_RISCV_BNE;
- ins->next->sreg1 = ins->dreg;
- ins->next->sreg2 = RISCV_ZERO;
- } else if (ins->next->opcode == OP_FBGE || ins->next->opcode == OP_FBGE_UN) {
+ next_ins->opcode = OP_RISCV_BNE;
+ next_ins->sreg1 = ins->dreg;
+ next_ins->sreg2 = RISCV_ZERO;
+ } else if (next_ins->opcode == OP_FBGE || next_ins->opcode == OP_FBGE_UN) {
// fcmp rd, rs1, rs2; fbge rd -> fcle rd, rs2, rs1; bne rd, X0
ins->opcode = OP_FCLE;
ins->dreg = mono_alloc_ireg (cfg);
@@ -2421,38 +2686,40 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
ins->sreg1 = ins->sreg2;
ins->sreg2 = tmp_reg;
- ins->next->opcode = OP_RISCV_BNE;
- ins->next->sreg1 = ins->dreg;
- ins->next->sreg2 = RISCV_ZERO;
- } else if (ins->next->opcode == OP_FBLE || ins->next->opcode == OP_FBLE_UN){
+ next_ins->opcode = OP_RISCV_BNE;
+ next_ins->sreg1 = ins->dreg;
+ next_ins->sreg2 = RISCV_ZERO;
+ } else if (next_ins->opcode == OP_FBLE || next_ins->opcode == OP_FBLE_UN) {
ins->opcode = OP_FCLE;
ins->dreg = mono_alloc_ireg (cfg);
- ins->next->opcode = OP_RISCV_BNE;
- ins->next->sreg1 = ins->dreg;
- ins->next->sreg2 = RISCV_ZERO;
- } else if (ins->next->opcode == OP_FBNE_UN) {
+ next_ins->opcode = OP_RISCV_BNE;
+ next_ins->sreg1 = ins->dreg;
+ next_ins->sreg2 = RISCV_ZERO;
+ } else if (next_ins->opcode == OP_FBNE_UN) {
// fcmp rd, rs1, rs2; fbne rd -> fceq rd, rs1, rs2; beq rd, X0
ins->opcode = OP_FCEQ;
ins->dreg = mono_alloc_ireg (cfg);
ins->sreg1 = ins->sreg1;
ins->sreg2 = ins->sreg2;
- ins->next->opcode = OP_RISCV_BEQ;
- ins->next->sreg1 = ins->dreg;
- ins->next->sreg2 = RISCV_ZERO;
- } else if (ins->next->opcode == OP_FBEQ) {
+ next_ins->opcode = OP_RISCV_BEQ;
+ next_ins->sreg1 = ins->dreg;
+ next_ins->sreg2 = RISCV_ZERO;
+ } else if (next_ins->opcode == OP_FBEQ) {
// fcmp rd, rs1, rs2; fbeq rd -> fceq rd, rs1, rs2; bne rd, X0
ins->opcode = OP_FCEQ;
ins->dreg = mono_alloc_ireg (cfg);
ins->sreg1 = ins->sreg1;
ins->sreg2 = ins->sreg2;
- ins->next->opcode = OP_RISCV_BNE;
- ins->next->sreg1 = ins->dreg;
- ins->next->sreg2 = RISCV_ZERO;
+ next_ins->opcode = OP_RISCV_BNE;
+ next_ins->sreg1 = ins->dreg;
+ next_ins->sreg2 = RISCV_ZERO;
+ } else if (next_ins->opcode == OP_BR) {
+ NULLIFY_INS (ins);
} else {
- g_print ("Unhandaled op %s following after OP_FCOMPARE\n", mono_inst_name (ins->next->opcode));
+ g_print ("Unhandaled op %s following after OP_FCOMPARE\n", mono_inst_name (next_ins->opcode));
NOT_IMPLEMENTED;
}
} else {
@@ -2462,8 +2729,15 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
}
case OP_LOCALLOC_IMM:
- if (ins->inst_imm > 32)
- mono_decompose_op_imm (cfg, bb, ins);
+ if (ins->inst_imm > 32) {
+ NEW_INS_BEFORE (cfg, ins, temp, OP_I8CONST);
+ temp->inst_l = ins->inst_imm;
+ temp->dreg = mono_alloc_ireg (cfg);
+
+ g_assert (mono_op_imm_to_op (ins->opcode) != -1);
+ ins->opcode = GINT_TO_OPCODE (mono_op_imm_to_op (ins->opcode));
+ ins->sreg1 = temp->dreg;
+ }
break;
case OP_CALL_MEMBASE:
@@ -2474,9 +2748,9 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
case OP_VOIDCALL_MEMBASE:
if (!RISCV_VALID_J_IMM (ins->inst_offset)) {
NOT_IMPLEMENTED;
- NEW_INS_BEFORE (cfg, ins, temp, OP_ICONST);
+ NEW_INS_BEFORE (cfg, ins, temp, OP_I8CONST);
temp->dreg = mono_alloc_ireg (cfg);
- temp->inst_c0 = ins->inst_offset;
+ temp->inst_l = ins->inst_offset;
ins->sreg1 = temp->dreg;
@@ -2492,6 +2766,8 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
}
break;
case OP_CALL_REG:
+ case OP_LCALL_REG:
+ case OP_RCALL_REG:
case OP_FCALL_REG:
case OP_VOIDCALL_REG:
case OP_VCALL2_REG:
@@ -2517,8 +2793,8 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
#endif
case OP_STORE_MEMBASE_IMM: {
if (ins->inst_imm != 0) {
- NEW_INS_BEFORE (cfg, ins, temp, OP_ICONST);
- temp->inst_c0 = ins->inst_imm;
+ NEW_INS_BEFORE (cfg, ins, temp, OP_I8CONST);
+ temp->inst_l = ins->inst_imm;
temp->dreg = mono_alloc_ireg (cfg);
ins->sreg1 = temp->dreg;
@@ -2564,22 +2840,19 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
NEW_INS_BEFORE (cfg, ins, temp, OP_FCONV_TO_R4);
temp->dreg = mono_alloc_freg (cfg);
temp->sreg1 = ins->sreg1;
-
ins->sreg1 = temp->dreg;
}
// check if offset is valid I-type Imm
if (!RISCV_VALID_I_IMM (ins->inst_offset)) {
- g_assert (ins->opcode != OP_STORER4_MEMBASE_REG);
-
/**
* iconst t0, offset
* add t0, rd, t0
* store rs1, 0(t0)
*/
int offset_reg = mono_alloc_ireg (cfg);
- NEW_INS_BEFORE (cfg, ins, temp, OP_ICONST);
+ NEW_INS_BEFORE (cfg, ins, temp, OP_I8CONST);
temp->dreg = offset_reg;
- temp->inst_c0 = ins->inst_offset;
+ temp->inst_l = ins->inst_offset;
#ifdef TARGET_RISCV64
NEW_INS_BEFORE (cfg, ins, temp, OP_LADD);
@@ -2610,8 +2883,8 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
case OP_LOADR8_MEMBASE:
case OP_LOAD_MEMBASE:
if (!RISCV_VALID_I_IMM (ins->inst_imm)) {
- NEW_INS_BEFORE (cfg, ins, temp, OP_ICONST);
- temp->inst_c0 = ins->inst_imm;
+ NEW_INS_BEFORE (cfg, ins, temp, OP_I8CONST);
+ temp->inst_l = ins->inst_imm;
temp->dreg = mono_alloc_ireg (cfg);
ins->sreg1 = temp->dreg;
ins->inst_imm = 0;
@@ -2621,57 +2894,60 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
case OP_COMPARE_IMM:
case OP_ICOMPARE_IMM:
case OP_LCOMPARE_IMM: {
- if (ins->next) {
- if (ins->next->opcode == OP_LCEQ || ins->next->opcode == OP_ICEQ) {
+ if (next_ins) {
+ if (next_ins->opcode == OP_LCEQ || next_ins->opcode == OP_ICEQ) {
if (RISCV_VALID_I_IMM (ins->inst_imm)) {
// compare rs1, imm; lceq rd => addi rs2, rs1, -imm; sltiu rd, rs2, 1
- ins->opcode = OP_ADD_IMM;
+ if (next_ins->opcode == OP_ICEQ)
+ ins->opcode = OP_IADD_IMM;
+ else
+ ins->opcode = OP_LADD_IMM;
ins->dreg = mono_alloc_ireg (cfg);
ins->inst_imm = -ins->inst_imm;
- ins->next->opcode = OP_RISCV_SLTIU;
- ins->next->sreg1 = ins->dreg;
- ins->next->inst_imm = 1;
+ next_ins->opcode = OP_RISCV_SLTIU;
+ next_ins->sreg1 = ins->dreg;
+ next_ins->inst_imm = 1;
break;
}
}
- if (ins->next->opcode == OP_ICNEQ) {
+ if (next_ins->opcode == OP_ICNEQ) {
if (RISCV_VALID_I_IMM (ins->inst_imm)) {
// compare rs1, imm; lcneq rd => addi rs2, rs1, -imm; sltu rd, X0, rs2
- ins->opcode = OP_ADD_IMM;
+ ins->opcode = OP_IADD_IMM;
ins->dreg = mono_alloc_ireg (cfg);
ins->inst_imm = -ins->inst_imm;
- ins->next->opcode = OP_RISCV_SLTU;
- ins->next->sreg1 = RISCV_ZERO;
- ins->next->sreg2 = ins->dreg;
+ next_ins->opcode = OP_RISCV_SLTU;
+ next_ins->sreg1 = RISCV_ZERO;
+ next_ins->sreg2 = ins->dreg;
break;
}
- } else if (ins->next->opcode == OP_LCGT_UN || ins->next->opcode == OP_ICGT_UN) {
+ } else if (next_ins->opcode == OP_LCGT_UN || next_ins->opcode == OP_ICGT_UN) {
if (RISCV_VALID_I_IMM (ins->inst_imm + 1)) {
// compare rs1, imm; lcgt_un rd => sltiu rd, rs1, imm; xori rd, rd, 1
ins->opcode = OP_RISCV_SLTIU;
- ins->dreg = ins->next->dreg;
+ ins->dreg = next_ins->dreg;
ins->sreg1 = ins->sreg1;
ins->inst_imm = ins->inst_imm + 1;
- ins->next->opcode = OP_XOR_IMM;
- ins->next->dreg = ins->dreg;
- ins->next->sreg1 = ins->dreg;
- ins->next->inst_imm = 1;
+ next_ins->opcode = OP_XOR_IMM;
+ next_ins->dreg = ins->dreg;
+ next_ins->sreg1 = ins->dreg;
+ next_ins->inst_imm = 1;
break;
}
- } else if (ins->next->opcode == OP_LCGT || ins->next->opcode == OP_ICGT) {
+ } else if (next_ins->opcode == OP_LCGT || next_ins->opcode == OP_ICGT) {
if (RISCV_VALID_I_IMM (ins->inst_imm + 1)) {
ins->opcode = OP_RISCV_SLTI;
- ins->dreg = ins->next->dreg;
+ ins->dreg = next_ins->dreg;
ins->sreg1 = ins->sreg1;
ins->inst_imm = ins->inst_imm + 1;
- ins->next->opcode = OP_XOR_IMM;
- ins->next->dreg = ins->dreg;
- ins->next->sreg1 = ins->dreg;
- ins->next->inst_imm = 1;
+ next_ins->opcode = OP_XOR_IMM;
+ next_ins->dreg = ins->dreg;
+ next_ins->sreg1 = ins->dreg;
+ next_ins->inst_imm = 1;
break;
}
}
@@ -2684,8 +2960,8 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
if (ins->inst_imm == 0) {
ins->sreg2 = RISCV_ZERO;
} else {
- NEW_INS_BEFORE (cfg, ins, temp, OP_ICONST);
- temp->inst_c0 = ins->inst_imm;
+ NEW_INS_BEFORE (cfg, ins, temp, OP_I8CONST);
+ temp->inst_l = ins->inst_imm;
temp->dreg = mono_alloc_ireg (cfg);
ins->sreg2 = temp->dreg;
ins->inst_imm = 0;
@@ -2696,135 +2972,155 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
case OP_COMPARE:
case OP_ICOMPARE:
case OP_LCOMPARE: {
- if (ins->next) {
- if (ins->next->opcode == OP_COND_EXC_EQ || ins->next->opcode == OP_COND_EXC_IEQ) {
- ins->next->opcode = OP_RISCV_EXC_BEQ;
- ins->next->sreg1 = ins->sreg1;
- ins->next->sreg2 = ins->sreg2;
+ if (next_ins) {
+ if (next_ins->opcode == OP_COND_EXC_EQ || next_ins->opcode == OP_COND_EXC_IEQ) {
+ next_ins->opcode = OP_RISCV_EXC_BEQ;
+ next_ins->sreg1 = ins->sreg1;
+ next_ins->sreg2 = ins->sreg2;
NULLIFY_INS (ins);
- } else if (ins->next->opcode == OP_COND_EXC_NE_UN) {
- ins->next->opcode = OP_RISCV_EXC_BNE;
- ins->next->sreg1 = ins->sreg1;
- ins->next->sreg2 = ins->sreg2;
+ } else if (next_ins->opcode == OP_COND_EXC_NE_UN) {
+ next_ins->opcode = OP_RISCV_EXC_BNE;
+ next_ins->sreg1 = ins->sreg1;
+ next_ins->sreg2 = ins->sreg2;
NULLIFY_INS (ins);
- } else if (ins->next->opcode == OP_COND_EXC_LT || ins->next->opcode == OP_COND_EXC_ILT) {
- ins->next->opcode = OP_RISCV_EXC_BLT;
- ins->next->sreg1 = ins->sreg1;
- ins->next->sreg2 = ins->sreg2;
+ } else if (next_ins->opcode == OP_COND_EXC_LT || next_ins->opcode == OP_COND_EXC_ILT) {
+ next_ins->opcode = OP_RISCV_EXC_BLT;
+ next_ins->sreg1 = ins->sreg1;
+ next_ins->sreg2 = ins->sreg2;
NULLIFY_INS (ins);
- } else if (ins->next->opcode == OP_COND_EXC_LT_UN || ins->next->opcode == OP_COND_EXC_ILT_UN) {
- ins->next->opcode = OP_RISCV_EXC_BLTU;
- ins->next->sreg1 = ins->sreg1;
- ins->next->sreg2 = ins->sreg2;
+ } else if (next_ins->opcode == OP_COND_EXC_LT_UN || next_ins->opcode == OP_COND_EXC_ILT_UN) {
+ next_ins->opcode = OP_RISCV_EXC_BLTU;
+ next_ins->sreg1 = ins->sreg1;
+ next_ins->sreg2 = ins->sreg2;
NULLIFY_INS (ins);
- } else if (ins->next->opcode == OP_COND_EXC_LE_UN) {
- ins->next->opcode = OP_RISCV_EXC_BGEU;
- ins->next->sreg1 = ins->sreg2;
- ins->next->sreg2 = ins->sreg1;
+ } else if (next_ins->opcode == OP_COND_EXC_LE_UN) {
+ next_ins->opcode = OP_RISCV_EXC_BGEU;
+ next_ins->sreg1 = ins->sreg2;
+ next_ins->sreg2 = ins->sreg1;
NULLIFY_INS (ins);
- } else if (ins->next->opcode == OP_COND_EXC_IGT || ins->next->opcode == OP_COND_EXC_GT) {
- ins->next->opcode = OP_RISCV_EXC_BLT;
- ins->next->sreg1 = ins->sreg2;
- ins->next->sreg2 = ins->sreg1;
+ } else if (next_ins->opcode == OP_COND_EXC_IGT || next_ins->opcode == OP_COND_EXC_GT) {
+ next_ins->opcode = OP_RISCV_EXC_BLT;
+ next_ins->sreg1 = ins->sreg2;
+ next_ins->sreg2 = ins->sreg1;
NULLIFY_INS (ins);
- } else if (ins->next->opcode == OP_COND_EXC_IGT_UN || ins->next->opcode == OP_COND_EXC_GT_UN) {
- ins->next->opcode = OP_RISCV_EXC_BLTU;
- ins->next->sreg1 = ins->sreg2;
- ins->next->sreg2 = ins->sreg1;
+ } else if (next_ins->opcode == OP_COND_EXC_IGT_UN || next_ins->opcode == OP_COND_EXC_GT_UN) {
+ next_ins->opcode = OP_RISCV_EXC_BLTU;
+ next_ins->sreg1 = ins->sreg2;
+ next_ins->sreg2 = ins->sreg1;
NULLIFY_INS (ins);
- } else if (ins->next->opcode == OP_LBEQ || ins->next->opcode == OP_IBEQ) {
- ins->next->opcode = OP_RISCV_BEQ;
- ins->next->sreg1 = ins->sreg1;
- ins->next->sreg2 = ins->sreg2;
+ } else if (next_ins->opcode == OP_LBEQ || next_ins->opcode == OP_IBEQ) {
+ next_ins->opcode = OP_RISCV_BEQ;
+ next_ins->sreg1 = ins->sreg1;
+ next_ins->sreg2 = ins->sreg2;
NULLIFY_INS (ins);
- } else if (ins->next->opcode == OP_LBNE_UN || ins->next->opcode == OP_IBNE_UN) {
- ins->next->opcode = OP_RISCV_BNE;
- ins->next->sreg1 = ins->sreg1;
- ins->next->sreg2 = ins->sreg2;
+ } else if (next_ins->opcode == OP_LBNE_UN || next_ins->opcode == OP_IBNE_UN) {
+ next_ins->opcode = OP_RISCV_BNE;
+ next_ins->sreg1 = ins->sreg1;
+ next_ins->sreg2 = ins->sreg2;
NULLIFY_INS (ins);
- } else if (ins->next->opcode == OP_LBGE_UN || ins->next->opcode == OP_IBGE_UN) {
- ins->next->opcode = OP_RISCV_BGEU;
- ins->next->sreg1 = ins->sreg1;
- ins->next->sreg2 = ins->sreg2;
+ } else if (next_ins->opcode == OP_LBGE_UN || next_ins->opcode == OP_IBGE_UN) {
+ next_ins->opcode = OP_RISCV_BGEU;
+ next_ins->sreg1 = ins->sreg1;
+ next_ins->sreg2 = ins->sreg2;
NULLIFY_INS (ins);
- } else if (ins->next->opcode == OP_LBGE || ins->next->opcode == OP_IBGE) {
- ins->next->opcode = OP_RISCV_BGE;
- ins->next->sreg1 = ins->sreg1;
- ins->next->sreg2 = ins->sreg2;
+ } else if (next_ins->opcode == OP_LBGE || next_ins->opcode == OP_IBGE) {
+ next_ins->opcode = OP_RISCV_BGE;
+ next_ins->sreg1 = ins->sreg1;
+ next_ins->sreg2 = ins->sreg2;
NULLIFY_INS (ins);
- } else if (ins->next->opcode == OP_LBGT_UN || ins->next->opcode == OP_IBGT_UN) {
- ins->next->opcode = OP_RISCV_BLTU;
- ins->next->sreg1 = ins->sreg2;
- ins->next->sreg2 = ins->sreg1;
+ } else if (next_ins->opcode == OP_LBGT_UN || next_ins->opcode == OP_IBGT_UN) {
+ next_ins->opcode = OP_RISCV_BLTU;
+ next_ins->sreg1 = ins->sreg2;
+ next_ins->sreg2 = ins->sreg1;
NULLIFY_INS (ins);
- } else if (ins->next->opcode == OP_LBGT || ins->next->opcode == OP_IBGT) {
- ins->next->opcode = OP_RISCV_BLT;
- ins->next->sreg1 = ins->sreg2;
- ins->next->sreg2 = ins->sreg1;
+ } else if (next_ins->opcode == OP_LBGT || next_ins->opcode == OP_IBGT) {
+ next_ins->opcode = OP_RISCV_BLT;
+ next_ins->sreg1 = ins->sreg2;
+ next_ins->sreg2 = ins->sreg1;
NULLIFY_INS (ins);
- } else if (ins->next->opcode == OP_LBLE || ins->next->opcode == OP_IBLE) {
+ } else if (next_ins->opcode == OP_LBLE || next_ins->opcode == OP_IBLE) {
// ble rs1, rs2 -> bge rs2, rs1
- ins->next->opcode = OP_RISCV_BGE;
- ins->next->sreg1 = ins->sreg2;
- ins->next->sreg2 = ins->sreg1;
+ next_ins->opcode = OP_RISCV_BGE;
+ next_ins->sreg1 = ins->sreg2;
+ next_ins->sreg2 = ins->sreg1;
NULLIFY_INS (ins);
- } else if (ins->next->opcode == OP_LBLE_UN || ins->next->opcode == OP_IBLE_UN) {
+ } else if (next_ins->opcode == OP_LBLE_UN || next_ins->opcode == OP_IBLE_UN) {
// ble rs1, rs2 -> bge rs2, rs1
- ins->next->opcode = OP_RISCV_BGEU;
- ins->next->sreg1 = ins->sreg2;
- ins->next->sreg2 = ins->sreg1;
+ next_ins->opcode = OP_RISCV_BGEU;
+ next_ins->sreg1 = ins->sreg2;
+ next_ins->sreg2 = ins->sreg1;
NULLIFY_INS (ins);
- } else if (ins->next->opcode == OP_LBLT_UN || ins->next->opcode == OP_IBLT_UN) {
- ins->next->opcode = OP_RISCV_BLTU;
- ins->next->sreg1 = ins->sreg1;
- ins->next->sreg2 = ins->sreg2;
+ } else if (next_ins->opcode == OP_LBLT_UN || next_ins->opcode == OP_IBLT_UN) {
+ next_ins->opcode = OP_RISCV_BLTU;
+ next_ins->sreg1 = ins->sreg1;
+ next_ins->sreg2 = ins->sreg2;
NULLIFY_INS (ins);
- } else if (ins->next->opcode == OP_LBLT || ins->next->opcode == OP_IBLT) {
- ins->next->opcode = OP_RISCV_BLT;
- ins->next->sreg1 = ins->sreg1;
- ins->next->sreg2 = ins->sreg2;
+ } else if (next_ins->opcode == OP_LBLT || next_ins->opcode == OP_IBLT) {
+ next_ins->opcode = OP_RISCV_BLT;
+ next_ins->sreg1 = ins->sreg1;
+ next_ins->sreg2 = ins->sreg2;
NULLIFY_INS (ins);
- } else if (ins->next->opcode == OP_LCLT || ins->next->opcode == OP_ICLT) {
- ins->next->opcode = OP_RISCV_SLT;
- ins->next->sreg1 = ins->sreg1;
- ins->next->sreg2 = ins->sreg2;
+ } else if (next_ins->opcode == OP_LCLT || next_ins->opcode == OP_ICLT) {
+ next_ins->opcode = OP_RISCV_SLT;
+ next_ins->sreg1 = ins->sreg1;
+ next_ins->sreg2 = ins->sreg2;
NULLIFY_INS (ins);
- } else if (ins->next->opcode == OP_LCLT_UN || ins->next->opcode == OP_ICLT_UN) {
- ins->next->opcode = OP_RISCV_SLTU;
- ins->next->sreg1 = ins->sreg1;
- ins->next->sreg2 = ins->sreg2;
+ } else if (next_ins->opcode == OP_LCLT_UN || next_ins->opcode == OP_ICLT_UN) {
+ next_ins->opcode = OP_RISCV_SLTU;
+ next_ins->sreg1 = ins->sreg1;
+ next_ins->sreg2 = ins->sreg2;
NULLIFY_INS (ins);
- } else if (ins->next->opcode == OP_LCEQ || ins->next->opcode == OP_ICEQ) {
+ } else if (next_ins->opcode == OP_LCEQ) {
// compare rs1, rs2; lceq rd => xor rd, rs1, rs2; sltiu rd, rd, 1
ins->opcode = OP_IXOR;
- ins->dreg = ins->next->dreg;
+ ins->dreg = next_ins->dreg;
+
+ next_ins->opcode = OP_RISCV_SLTIU;
+ next_ins->sreg1 = ins->dreg;
+ next_ins->inst_imm = 1;
+ } else if (next_ins->opcode == OP_ICEQ) {
+ // compare rs1, rs2; lceq rd => xor rd, rs1, rs2; sltiu rd, rd, 1
+ ins->opcode = OP_IXOR;
+ ins->dreg = next_ins->dreg;
+
+ next_ins->opcode = OP_RISCV_SLTIU;
+ next_ins->sreg1 = ins->dreg;
+ next_ins->inst_imm = 1;
- ins->next->opcode = OP_RISCV_SLTIU;
- ins->next->sreg1 = ins->dreg;
- ins->next->inst_imm = 1;
- } else if (ins->next->opcode == OP_ICNEQ) {
+ // insert a sext.i4 between XOR and SLTIU
+ // will change next_ins pointer
+ NEW_INS_AFTER (cfg, ins, next_ins, temp, OP_SEXT_I4);
+ temp->dreg = ins->dreg;
+ temp->sreg1 = ins->dreg;
+ } else if (next_ins->opcode == OP_ICNEQ) {
// compare rs1, rs2; lcneq rd => xor rd, rs1, rs2; sltu rd, X0, rd
ins->opcode = OP_IXOR;
- ins->dreg = ins->next->dreg;
-
- ins->next->opcode = OP_RISCV_SLTU;
- ins->next->sreg1 = RISCV_ZERO;
- ins->next->sreg2 = ins->dreg;
- } else if (ins->next->opcode == OP_LCGT || ins->next->opcode == OP_ICGT) {
- ins->next->opcode = OP_RISCV_SLT;
- ins->next->sreg1 = ins->sreg2;
- ins->next->sreg2 = ins->sreg1;
+ ins->dreg = next_ins->dreg;
+
+ next_ins->opcode = OP_RISCV_SLTU;
+ next_ins->sreg1 = RISCV_ZERO;
+ next_ins->sreg2 = ins->dreg;
+
+ // insert a sext.i4 between XOR and SLTU
+ // will change next_ins pointer
+ NEW_INS_AFTER (cfg, ins, next_ins, temp, OP_SEXT_I4);
+ temp->dreg = ins->dreg;
+ temp->sreg1 = ins->dreg;
+ } else if (next_ins->opcode == OP_LCGT || next_ins->opcode == OP_ICGT) {
+ next_ins->opcode = OP_RISCV_SLT;
+ next_ins->sreg1 = ins->sreg2;
+ next_ins->sreg2 = ins->sreg1;
NULLIFY_INS (ins);
- } else if (ins->next->opcode == OP_LCGT_UN || ins->next->opcode == OP_ICGT_UN) {
- ins->next->opcode = OP_RISCV_SLTU;
- ins->next->sreg1 = ins->sreg2;
- ins->next->sreg2 = ins->sreg1;
+ } else if (next_ins->opcode == OP_LCGT_UN || next_ins->opcode == OP_ICGT_UN) {
+ next_ins->opcode = OP_RISCV_SLTU;
+ next_ins->sreg1 = ins->sreg2;
+ next_ins->sreg2 = ins->sreg1;
NULLIFY_INS (ins);
- } else if (ins->next->opcode == OP_IL_SEQ_POINT || ins->next->opcode == OP_MOVE ||
- ins->next->opcode == OP_LOAD_MEMBASE || ins->next->opcode == OP_NOP ||
- ins->next->opcode == OP_LOADI4_MEMBASE || ins->next->opcode == OP_BR ||
- ins->next->opcode == OP_LOADI8_MEMBASE || ins->next->opcode == OP_ICONST ||
- ins->next->opcode == OP_I8CONST || ins->next->opcode == OP_ADD_IMM) {
+ } else if (next_ins->opcode == OP_IL_SEQ_POINT || next_ins->opcode == OP_MOVE ||
+ next_ins->opcode == OP_LOAD_MEMBASE || next_ins->opcode == OP_NOP ||
+ next_ins->opcode == OP_LOADI4_MEMBASE || next_ins->opcode == OP_BR ||
+ next_ins->opcode == OP_LOADI8_MEMBASE || next_ins->opcode == OP_ICONST ||
+ next_ins->opcode == OP_I8CONST || next_ins->opcode == OP_ADD_IMM) {
/**
* there is compare without branch OP followed
*
@@ -2837,7 +3133,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
break;
} else {
g_print ("Unhandaled op %s following after OP_{I|L}COMPARE{|_IMM}\n",
- mono_inst_name (ins->next->opcode));
+ mono_inst_name (next_ins->opcode));
NOT_IMPLEMENTED;
}
} else
@@ -2848,7 +3144,10 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
/* Math */
case OP_INEG:
case OP_LNEG:
- ins->opcode = OP_ISUB;
+ if (ins->opcode == OP_INEG)
+ ins->opcode = OP_ISUB;
+ else
+ ins->opcode = OP_LSUB;
ins->sreg2 = ins->sreg1;
ins->sreg1 = RISCV_ZERO;
break;
@@ -2868,13 +3167,25 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
* slt t2, rd, rs1
* bne t1, t2, overflow
*/
- if (ins->opcode == OP_LSUBCC)
+ if (ins->opcode == OP_SUBCC) {
+#ifdef TARGET_RISCV64
+ ins->opcode = OP_LSUB;
+#else
+ ins->opcode = OP_ISUB;
+#endif
+ } else if (ins->opcode == OP_LSUBCC)
ins->opcode = OP_LSUB;
else
ins->opcode = OP_ISUB;
- MonoInst *branch_ins = ins->next;
+ MonoInst *branch_ins = next_ins;
if (branch_ins) {
- if (branch_ins->opcode == OP_COND_EXC_OV || ins->next->opcode == OP_COND_EXC_IOV) {
+ if (branch_ins->opcode == OP_COND_EXC_NC || branch_ins->opcode == OP_COND_EXC_C ||
+ branch_ins->opcode == OP_COND_EXC_IC) {
+ // bltu rs1, rd, overflow
+ branch_ins->opcode = OP_RISCV_EXC_BLTU;
+ branch_ins->sreg1 = ins->sreg1;
+ branch_ins->sreg2 = ins->dreg;
+ } else if (branch_ins->opcode == OP_COND_EXC_OV || next_ins->opcode == OP_COND_EXC_IOV) {
// bne t1, t2, overflow
branch_ins->opcode = OP_RISCV_EXC_BNE;
branch_ins->sreg1 = mono_alloc_ireg (cfg);
@@ -2902,7 +3213,13 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
case OP_IADD_IMM:
case OP_LADD_IMM:
if (!RISCV_VALID_I_IMM (ins->inst_imm)) {
- mono_decompose_op_imm (cfg, bb, ins);
+ NEW_INS_BEFORE (cfg, ins, temp, OP_I8CONST);
+ temp->inst_l = ins->inst_imm;
+ temp->dreg = mono_alloc_ireg (cfg);
+
+ g_assert (mono_op_imm_to_op (ins->opcode) != -1);
+ ins->opcode = GINT_TO_OPCODE (mono_op_imm_to_op (ins->opcode));
+ ins->sreg2 = temp->dreg;
}
break;
case OP_ADDCC:
@@ -2913,7 +3230,6 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
* slt t4,t0,t1
* bne t3, t4, overflow
*/
-
#ifdef TARGET_RISCV64
if (ins->opcode == OP_ADDCC)
ins->opcode = OP_LADD;
@@ -2921,9 +3237,15 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
#endif
ins->opcode = OP_IADD;
- MonoInst *branch_ins = ins->next;
+ MonoInst *branch_ins = next_ins;
if (branch_ins) {
- if (branch_ins->opcode == OP_COND_EXC_C || branch_ins->opcode == OP_COND_EXC_OV || branch_ins->opcode == OP_COND_EXC_IOV) {
+ if (branch_ins->opcode == OP_COND_EXC_C || branch_ins->opcode == OP_COND_EXC_IC) {
+ // bltu rd, rs1, overflow
+
+ branch_ins->opcode = OP_RISCV_EXC_BLTU;
+ branch_ins->sreg1 = ins->dreg;
+ branch_ins->sreg2 = ins->sreg1;
+ } else if (branch_ins->opcode == OP_COND_EXC_OV || branch_ins->opcode == OP_COND_EXC_IOV) {
// bne t3, t4, overflow
branch_ins->opcode = OP_RISCV_EXC_BNE;
branch_ins->sreg1 = mono_alloc_ireg (cfg);
@@ -2948,50 +3270,45 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
break;
}
case OP_MUL_IMM:
- case OP_IMUL_IMM:
- case OP_LMUL_IMM:
- case OP_IDIV_IMM: {
g_assert (riscv_stdext_m);
- NEW_INS_BEFORE (cfg, ins, temp, OP_ICONST);
- temp->inst_c0 = ins->inst_imm;
+ NEW_INS_BEFORE (cfg, ins, temp, OP_I8CONST);
+ temp->inst_l = ins->inst_imm;
temp->dreg = mono_alloc_ireg (cfg);
ins->sreg2 = temp->dreg;
ins->inst_imm = 0;
- switch (ins->opcode) {
- case OP_MUL_IMM:
#ifdef TARGET_RISCV64
ins->opcode = OP_LMUL;
#else
ins->opcode = OP_IMUL;
#endif
- break;
- case OP_IMUL_IMM:
- ins->opcode = OP_IMUL;
- break;
- case OP_LMUL_IMM:
- ins->opcode = OP_LMUL;
- break;
- case OP_DIV_IMM:
+ break;
+ case OP_DIV_IMM:
+ NEW_INS_BEFORE (cfg, ins, temp, OP_I8CONST);
+ temp->inst_l = ins->inst_imm;
+ temp->dreg = mono_alloc_ireg (cfg);
+
#ifdef TARGET_RISCV64
- ins->opcode = OP_LDIV;
+ g_assert (mono_op_imm_to_op (ins->opcode) == OP_LDIV);
#else
- ins->opcode = OP_IDIV;
+ g_assert (mono_op_imm_to_op (ins->opcode) == OP_IDIV);
#endif
- break;
- case OP_IDIV_IMM:
- ins->opcode = OP_IDIV;
- break;
- case OP_LDIV_IMM:
- ins->opcode = OP_LDIV;
- break;
- }
+ ins->opcode = mono_op_imm_to_op (ins->opcode);
+ ins->sreg2 = temp->dreg;
break;
- }
+ case OP_IMUL_IMM:
+ case OP_LMUL_IMM:
+ case OP_IDIV_IMM:
case OP_IREM_IMM:
case OP_LREM_IMM:
case OP_IREM_UN_IMM:
case OP_LREM_UN_IMM:
- mono_decompose_op_imm (cfg, bb, ins);
+ NEW_INS_BEFORE (cfg, ins, temp, OP_I8CONST);
+ temp->inst_l = ins->inst_imm;
+ temp->dreg = mono_alloc_ireg (cfg);
+
+ g_assert (mono_op_imm_to_op (ins->opcode) != -1);
+ ins->opcode = GINT_TO_OPCODE (mono_op_imm_to_op (ins->opcode));
+ ins->sreg2 = temp->dreg;
break;
// Bit OP
@@ -3003,8 +3320,24 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
case OP_XOR_IMM:
case OP_IXOR_IMM:
case OP_LXOR_IMM:
- if (!RISCV_VALID_I_IMM (ins->inst_imm))
- mono_decompose_op_imm (cfg, bb, ins);
+ case OP_SHL_IMM:
+ case OP_ISHL_IMM:
+ case OP_LSHL_IMM:
+ case OP_LSHR_IMM:
+ case OP_LSHR_UN_IMM:
+ case OP_SHR_IMM:
+ case OP_ISHR_IMM:
+ case OP_SHR_UN_IMM:
+ case OP_ISHR_UN_IMM:
+ if (!RISCV_VALID_LS_AMOUNT (ins->inst_imm)) {
+ NEW_INS_BEFORE (cfg, ins, temp, OP_I8CONST);
+ temp->inst_l = ins->inst_imm;
+ temp->dreg = mono_alloc_ireg (cfg);
+
+ g_assert (mono_op_imm_to_op (ins->opcode) != -1);
+ ins->opcode = GINT_TO_OPCODE (mono_op_imm_to_op (ins->opcode));
+ ins->sreg2 = temp->dreg;
+ }
break;
case OP_INOT:
case OP_LNOT:
@@ -3015,8 +3348,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
case OP_LCONV_TO_I1:
// slli a0, a0, 56
// srai a0, a0, 56
- NEW_INS_BEFORE (cfg, ins, temp, OP_ICONST);
- temp->opcode = OP_SHL_IMM;
+ NEW_INS_BEFORE (cfg, ins, temp, OP_SHL_IMM);
temp->dreg = ins->dreg;
temp->sreg1 = ins->sreg1;
temp->inst_imm = 56;
@@ -3036,8 +3368,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
case OP_LCONV_TO_U2:
// slli a0, a0, 48
// srli a0, a0, 48
- NEW_INS_BEFORE (cfg, ins, temp, OP_ICONST);
- temp->opcode = OP_SHL_IMM;
+ NEW_INS_BEFORE (cfg, ins, temp, OP_SHL_IMM);
temp->dreg = ins->dreg;
temp->sreg1 = ins->sreg1;
temp->inst_imm = 48;
@@ -3051,8 +3382,7 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
case OP_LCONV_TO_I2:
// slli a0, a0, 48
// srai a0, a0, 48
- NEW_INS_BEFORE (cfg, ins, temp, OP_ICONST);
- temp->opcode = OP_SHL_IMM;
+ NEW_INS_BEFORE (cfg, ins, temp, OP_SHL_IMM);
temp->dreg = ins->dreg;
temp->sreg1 = ins->sreg1;
temp->inst_imm = 48;
@@ -3383,9 +3713,9 @@ mono_riscv_emit_load_regarray (guint8 *code, guint64 regs, int basereg, int offs
g_assert (basereg != RISCV_SP);
if (!RISCV_VALID_S_IMM (offset)) {
- code = mono_riscv_emit_imm (code, RISCV_T6, offset);
- riscv_add (code, RISCV_T6, basereg, RISCV_T6);
- basereg = RISCV_T6;
+ code = mono_riscv_emit_imm (code, RISCV_T0, offset);
+ riscv_add (code, RISCV_T0, basereg, RISCV_T0);
+ basereg = RISCV_T0;
offset = 0;
}
@@ -3415,9 +3745,9 @@ mono_riscv_emit_store_regarray (guint8 *code, guint64 regs, int basereg, int off
g_assert (basereg != RISCV_SP);
if (!RISCV_VALID_S_IMM (offset)) {
- code = mono_riscv_emit_imm (code, RISCV_T6, offset);
- riscv_add (code, RISCV_T6, basereg, RISCV_T6);
- basereg = RISCV_T6;
+ code = mono_riscv_emit_imm (code, RISCV_T0, offset);
+ riscv_add (code, RISCV_T0, basereg, RISCV_T0);
+ basereg = RISCV_T0;
offset = 0;
}
@@ -3446,9 +3776,9 @@ mono_riscv_emit_load_stack (guint8 *code, guint64 regs, int basereg, int offset,
g_assert (basereg != RISCV_SP);
if (!RISCV_VALID_S_IMM (offset)) {
- code = mono_riscv_emit_imm (code, RISCV_T6, offset);
- riscv_add (code, RISCV_T6, basereg, RISCV_T6);
- basereg = RISCV_T6;
+ code = mono_riscv_emit_imm (code, RISCV_T0, offset);
+ riscv_add (code, RISCV_T0, basereg, RISCV_T0);
+ basereg = RISCV_T0;
offset = 0;
}
@@ -3714,7 +4044,8 @@ mono_riscv_emit_call (MonoCompile *cfg, guint8 *code, MonoJumpInfoType patch_typ
static guint8 *
mono_riscv_emit_branch_exc (MonoCompile *cfg, guint8 *code, int opcode, int sreg1, int sreg2, const char *exc_name)
{
- riscv_auipc (code, RISCV_T0, 0);
+ riscv_auipc (code, MONO_ARCH_EXC_ADDR_REG, 0);
+ riscv_addi (code, MONO_ARCH_EXC_ADDR_REG, MONO_ARCH_EXC_ADDR_REG, 8);
switch (opcode) {
case OP_RISCV_EXC_BEQ:
riscv_bne (code, sreg1, sreg2, 8);
@@ -3736,6 +4067,7 @@ mono_riscv_emit_branch_exc (MonoCompile *cfg, guint8 *code, int opcode, int sreg
NOT_IMPLEMENTED;
}
mono_add_patch_info_rel (cfg, code - cfg->native_code, MONO_PATCH_INFO_EXC, exc_name, MONO_R_RISCV_JAL);
+ cfg->thunk_area += THUNK_SIZE;
riscv_jal (code, RISCV_ZERO, 0);
return code;
}
@@ -4097,6 +4429,18 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
mono_riscv_patch (branch_label, code, MONO_R_RISCV_BNE);
break;
}
+ case OP_CKFINITE: {
+ g_assert (riscv_stdext_d || riscv_stdext_f);
+ /* Check for infinity and nans */
+ if (riscv_stdext_d)
+ riscv_fclass_d (code, RISCV_T0, ins->sreg1);
+ else
+ riscv_fclass_s (code, RISCV_T0, ins->sreg1);
+
+ riscv_andi (code, RISCV_T0, RISCV_T0, ~(RISCV_FCLASS_INF | RISCV_FCLASS_NAN));
+ code =
+ mono_riscv_emit_branch_exc (cfg, code, OP_RISCV_EXC_BEQ, RISCV_T0, RISCV_ZERO, "ArithmeticException");
+ }
case OP_BREAK:
/*
* gdb does not like encountering the hw breakpoint ins in the debugged code.
@@ -4131,6 +4475,24 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
else
riscv_fsgnj_s (code, ins->dreg, ins->sreg1, ins->sreg1);
break;
+ case OP_MOVE_F_TO_I4:
+ g_assert (riscv_stdext_f);
+ riscv_fmv_x_w (code, ins->dreg, ins->sreg1);
+ break;
+ case OP_MOVE_I4_TO_F:
+ g_assert (riscv_stdext_f);
+ riscv_fmv_w_x (code, ins->dreg, ins->sreg1);
+ break;
+#ifdef TARGET_RISCV64
+ case OP_MOVE_F_TO_I8:
+ g_assert (riscv_stdext_d);
+ riscv_fmv_x_d (code, ins->dreg, ins->sreg1);
+ break;
+ case OP_MOVE_I8_TO_F:
+ g_assert (riscv_stdext_d);
+ riscv_fmv_d_x (code, ins->dreg, ins->sreg1);
+ break;
+#endif
case OP_LOAD_MEMBASE:
code = mono_riscv_emit_load (code, ins->dreg, ins->sreg1, ins->inst_offset, 0);
break;
@@ -4173,8 +4535,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
code = mono_riscv_emit_store (code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset, 8);
break;
case OP_ICONST:
+ code = mono_riscv_emit_imm (code, ins->dreg, (int)ins->inst_c0);
+ break;
case OP_I8CONST:
- code = mono_riscv_emit_imm (code, ins->dreg, ins->inst_c0);
+ code = mono_riscv_emit_imm (code, ins->dreg, ins->inst_l);
break;
case OP_IADD:
#ifdef TARGET_RISCV64
@@ -4184,11 +4548,19 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
case OP_LADD:
riscv_add (code, ins->dreg, ins->sreg1, ins->sreg2);
break;
- case OP_ADD_IMM:
case OP_IADD_IMM:
+#ifdef TARGET_RISCV64
+ riscv_addiw (code, ins->dreg, ins->sreg1, ins->inst_imm);
+ break;
+#endif
+ case OP_ADD_IMM:
case OP_LADD_IMM:
riscv_addi (code, ins->dreg, ins->sreg1, ins->inst_imm);
break;
+ case OP_RADD:
+ g_assert (riscv_stdext_f);
+ riscv_fadd_s (code, RISCV_ROUND_DY, ins->dreg, ins->sreg1, ins->sreg2);
+ break;
case OP_FADD:
g_assert (riscv_stdext_f || riscv_stdext_d);
if (riscv_stdext_d)
@@ -4215,6 +4587,14 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
riscv_fsub_s (code, RISCV_ROUND_DY, ins->dreg, ins->sreg1, ins->sreg2);
}
break;
+ case OP_RSUB:
+ g_assert (riscv_stdext_f);
+ riscv_fsub_s (code, RISCV_ROUND_DY, ins->dreg, ins->sreg1, ins->sreg2);
+ break;
+ case OP_RNEG:
+ g_assert (riscv_stdext_f);
+ riscv_fsgnjn_s (code, ins->dreg, ins->sreg1, ins->sreg1);
+ break;
case OP_FNEG:
g_assert (riscv_stdext_f || riscv_stdext_d);
if (riscv_stdext_d)
@@ -4249,17 +4629,9 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
case OP_FDIV:
g_assert (riscv_stdext_f || riscv_stdext_d);
if (riscv_stdext_d) {
- riscv_fmv_d_x (code, RISCV_FT0, RISCV_ZERO);
- riscv_feq_d (code, RISCV_T0, ins->sreg2, RISCV_FT0);
- code = mono_riscv_emit_branch_exc (cfg, code, OP_RISCV_EXC_BEQ, RISCV_T0, RISCV_ZERO,
- "DivideByZeroException");
riscv_fdiv_d (code, RISCV_ROUND_DY, ins->dreg, ins->sreg1, ins->sreg2);
} else {
NOT_IMPLEMENTED;
- riscv_fmv_w_x (code, RISCV_FT0, RISCV_ZERO);
- riscv_feq_s (code, RISCV_T0, ins->sreg2, RISCV_FT0);
- code = mono_riscv_emit_branch_exc (cfg, code, OP_RISCV_EXC_BEQ, RISCV_T0, RISCV_ZERO,
- "DivideByZeroException");
riscv_fdiv_s (code, RISCV_ROUND_DY, ins->dreg, ins->sreg1, ins->sreg2);
}
break;
@@ -4423,18 +4795,27 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
case OP_ATOMIC_ADD_I8:
riscv_amoadd_d (code, RISCV_ORDER_ALL, ins->dreg, ins->sreg2, ins->sreg1);
break;
- case OP_ATOMIC_LOAD_I4: {
+ case OP_ATOMIC_LOAD_I1:
+ case OP_ATOMIC_LOAD_U1: {
riscv_fence (code, RISCV_FENCE_MEM, RISCV_FENCE_MEM);
- code = mono_riscv_emit_load (code, ins->dreg, ins->sreg1, ins->inst_offset, 4);
+ code = mono_riscv_emit_load (code, ins->dreg, ins->sreg1, ins->inst_offset, 1);
riscv_fence (code, RISCV_FENCE_R, RISCV_FENCE_MEM);
break;
}
- case OP_ATOMIC_LOAD_U1: {
+ case OP_ATOMIC_LOAD_U2:
+ case OP_ATOMIC_LOAD_I2: {
riscv_fence (code, RISCV_FENCE_MEM, RISCV_FENCE_MEM);
- code = mono_riscv_emit_load (code, ins->dreg, ins->sreg1, ins->inst_offset, 1);
+ code = mono_riscv_emit_load (code, ins->dreg, ins->sreg1, ins->inst_offset, 2);
+ riscv_fence (code, RISCV_FENCE_R, RISCV_FENCE_MEM);
+ }
+ case OP_ATOMIC_LOAD_I4:
+ case OP_ATOMIC_LOAD_U4: {
+ riscv_fence (code, RISCV_FENCE_MEM, RISCV_FENCE_MEM);
+ code = mono_riscv_emit_load (code, ins->dreg, ins->sreg1, ins->inst_offset, 4);
riscv_fence (code, RISCV_FENCE_R, RISCV_FENCE_MEM);
break;
}
+ case OP_ATOMIC_STORE_I1:
case OP_ATOMIC_STORE_U1: {
riscv_fence (code, RISCV_FENCE_MEM, RISCV_FENCE_W);
code = mono_riscv_emit_store (code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset, 1);
@@ -4442,7 +4823,16 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
riscv_fence (code, RISCV_FENCE_MEM, RISCV_FENCE_MEM);
break;
}
- case OP_ATOMIC_STORE_I4: {
+ case OP_ATOMIC_STORE_I2:
+ case OP_ATOMIC_STORE_U2: {
+ riscv_fence (code, RISCV_FENCE_MEM, RISCV_FENCE_W);
+ code = mono_riscv_emit_store (code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset, 2);
+ if (ins->backend.memory_barrier_kind == MONO_MEMORY_BARRIER_SEQ)
+ riscv_fence (code, RISCV_FENCE_MEM, RISCV_FENCE_MEM);
+ break;
+ }
+ case OP_ATOMIC_STORE_I4:
+ case OP_ATOMIC_STORE_U4: {
riscv_fence (code, RISCV_FENCE_MEM, RISCV_FENCE_W);
code = mono_riscv_emit_store (code, ins->sreg1, ins->inst_destbasereg, ins->inst_offset, 4);
if (ins->backend.memory_barrier_kind == MONO_MEMORY_BARRIER_SEQ)
@@ -4545,49 +4935,64 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
}
case OP_RCONV_TO_I8: {
g_assert (riscv_stdext_f);
- riscv_fcvt_l_s (code, RISCV_ROUND_DY, ins->dreg, ins->sreg1);
+ riscv_fcvt_l_s (code, RISCV_ROUND_TZ, ins->dreg, ins->sreg1);
+ break;
+ }
+ case OP_FCONV_TO_I8: {
+ g_assert (riscv_stdext_f || riscv_stdext_d);
+ if (riscv_stdext_d)
+ riscv_fcvt_l_d (code, RISCV_ROUND_TZ, ins->dreg, ins->sreg1);
+ else
+ riscv_fcvt_l_s (code, RISCV_ROUND_TZ, ins->dreg, ins->sreg1);
+ break;
+ }
+ case OP_FCONV_TO_U8: {
+ g_assert (riscv_stdext_f || riscv_stdext_d);
+ if (riscv_stdext_d)
+ riscv_fcvt_lu_d (code, RISCV_ROUND_TZ, ins->dreg, ins->sreg1);
+ else
+ riscv_fcvt_lu_s (code, RISCV_ROUND_TZ, ins->dreg, ins->sreg1);
+ break;
+ }
+ case OP_RCONV_TO_U8: {
+ g_assert (riscv_stdext_f);
+ riscv_fcvt_lu_s (code, RISCV_ROUND_TZ, ins->dreg, ins->sreg1);
break;
}
case OP_RCONV_TO_I4: {
g_assert (riscv_stdext_f);
- riscv_fcvt_w_s (code, RISCV_ROUND_DY, ins->dreg, ins->sreg1);
+ riscv_fcvt_w_s (code, RISCV_ROUND_TZ, ins->dreg, ins->sreg1);
+ break;
+ }
+ case OP_RCONV_TO_U4: {
+ g_assert (riscv_stdext_f);
+ riscv_fcvt_wu_s (code, RISCV_ROUND_TZ, ins->dreg, ins->sreg1);
break;
}
case OP_FCONV_TO_I4: {
g_assert (riscv_stdext_f || riscv_stdext_d);
if (riscv_stdext_d)
- riscv_fcvt_w_d (code, RISCV_ROUND_DY, ins->dreg, ins->sreg1);
+ riscv_fcvt_w_d (code, RISCV_ROUND_TZ, ins->dreg, ins->sreg1);
else
- riscv_fcvt_w_s (code, RISCV_ROUND_DY, ins->dreg, ins->sreg1);
+ riscv_fcvt_w_s (code, RISCV_ROUND_TZ, ins->dreg, ins->sreg1);
break;
}
- case OP_FCONV_TO_I8: {
+ case OP_FCONV_TO_U4: {
g_assert (riscv_stdext_f || riscv_stdext_d);
if (riscv_stdext_d)
- riscv_fcvt_l_d (code, RISCV_ROUND_DY, ins->dreg, ins->sreg1);
+ riscv_fcvt_wu_d (code, RISCV_ROUND_TZ, ins->dreg, ins->sreg1);
else
- riscv_fcvt_l_s (code, RISCV_ROUND_DY, ins->dreg, ins->sreg1);
+ riscv_fcvt_wu_s (code, RISCV_ROUND_TZ, ins->dreg, ins->sreg1);
break;
}
case OP_FCONV_TO_R4:
case OP_RISCV_SETFREG_R4: {
g_assert (riscv_stdext_d);
- riscv_fcvt_s_d (code, RISCV_ROUND_DY, ins->dreg, ins->sreg1);
+ riscv_fcvt_s_d (code, RISCV_ROUND_TZ, ins->dreg, ins->sreg1);
break;
}
case OP_RDIV: {
g_assert (riscv_stdext_f);
- /**
- * insert inst for the case Divide By 0
- * fmv.w.x ft0, zero
- * feq.s t0, sreg2, ft0
- * beqz t0, zero
- */
- riscv_fmv_w_x (code, RISCV_FT0, RISCV_ZERO);
- riscv_feq_s (code, RISCV_T0, ins->sreg2, RISCV_FT0);
-
- code = mono_riscv_emit_branch_exc (cfg, code, OP_RISCV_EXC_BEQ, RISCV_T0, RISCV_ZERO,
- "DivideByZeroException");
riscv_fdiv_s (code, RISCV_ROUND_DY, ins->dreg, ins->sreg1, ins->sreg2);
break;
}
@@ -4599,6 +5004,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
riscv_feq_s (code, ins->dreg, ins->sreg1, ins->sreg2);
break;
}
+ case OP_RCEQ: {
+ g_assert (riscv_stdext_f);
+ riscv_feq_s (code, ins->dreg, ins->sreg1, ins->sreg2);
+ break;
+ }
case OP_RCLT:
case OP_RCLT_UN: {
g_assert (riscv_stdext_f);
@@ -4657,10 +5067,81 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
}
/* Calls */
+ case OP_TAILCALL_PARAMETER:
+ // This opcode helps compute sizes, i.e.
+ // of the subsequent OP_TAILCALL, but contributes no code.
+ g_assert (ins->next);
+ break;
+ case OP_TAILCALL:
+ case OP_TAILCALL_REG:
+ case OP_TAILCALL_MEMBASE: {
+ int target_reg = RISCV_T1;
+ call = (MonoCallInst *)ins;
+
+ g_assert (!cfg->method->save_lmf);
+
+ switch (ins->opcode) {
+ case OP_TAILCALL:
+ break;
+ case OP_TAILCALL_REG:
+ g_assert (ins->sreg1 != -1);
+ g_assert (ins->sreg1 != RISCV_T0);
+ g_assert (ins->sreg1 != RISCV_T1);
+ g_assert (ins->sreg1 != RISCV_RA);
+ g_assert (ins->sreg1 != RISCV_SP);
+ g_assert (ins->sreg1 != RISCV_FP);
+ riscv_addi (code, target_reg, ins->sreg1, 0);
+ break;
+ case OP_TAILCALL_MEMBASE:
+ g_assert (ins->sreg1 != -1);
+ g_assert (ins->sreg1 != RISCV_T0);
+ g_assert (ins->sreg1 != RISCV_T1);
+ g_assert (ins->sreg1 != RISCV_RA);
+ g_assert (ins->sreg1 != RISCV_SP);
+ g_assert (ins->sreg1 != RISCV_FP);
+ code = mono_riscv_emit_load (code, target_reg, ins->inst_basereg, ins->inst_offset, 0);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ /* Restore registers */
+ code = mono_riscv_emit_load_stack (code, MONO_ARCH_CALLEE_SAVED_REGS & cfg->used_int_regs, RISCV_FP,
+ -cfg->arch.saved_gregs_offset, FALSE);
+
+ /* Destroy frame */
+ code = mono_riscv_emit_destroy_frame (code);
+
+ switch (ins->opcode) {
+ case OP_TAILCALL:
+ if (cfg->compile_aot) {
+ NOT_IMPLEMENTED;
+ } else {
+ mono_add_patch_info_rel (cfg, GPTRDIFF_TO_INT (code - cfg->native_code),
+ MONO_PATCH_INFO_METHOD_JUMP, call->method, MONO_R_RISCV_JAL);
+ cfg->thunk_area += THUNK_SIZE;
+ riscv_jal (code, RISCV_ZERO, 0);
+ }
+ break;
+ case OP_TAILCALL_REG:
+ case OP_TAILCALL_MEMBASE:
+ // code = mono_arm_emit_brx (code, branch_reg);
+ riscv_jalr (code, RISCV_ZERO, target_reg, 0);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ ins->flags |= MONO_INST_GC_CALLSITE;
+ ins->backend.pc_offset = GPTRDIFF_TO_INT (code - cfg->native_code);
+
+ break;
+ }
case OP_VOIDCALL:
case OP_CALL:
- case OP_RCALL:
case OP_FCALL:
+ case OP_RCALL:
case OP_LCALL:
case OP_VCALL2: {
call = (MonoCallInst *)ins;
@@ -4672,6 +5153,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
break;
}
case OP_CALL_REG:
+ case OP_LCALL_REG:
case OP_RCALL_REG:
case OP_FCALL_REG:
case OP_VOIDCALL_REG:
@@ -4742,6 +5224,24 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
MONO_R_RISCV_IMM);
code = mono_riscv_emit_imm (code, ins->dreg, 0xffffffff);
break;
+ case OP_RISCV_FBNAN:
+ // fclass.d T0, rs1; andi T0, T0, RISCV_FCLASS_NAN; bne T0, zero, target
+ riscv_fclass_d (code, RISCV_T0, ins->sreg1);
+ riscv_andi (code, RISCV_T0, RISCV_T0, RISCV_FCLASS_NAN);
+ mono_add_patch_info_rel (cfg, (code - cfg->native_code), MONO_PATCH_INFO_BB, ins->inst_true_bb,
+ MONO_R_RISCV_BNE);
+ riscv_bne (code, RISCV_T0, RISCV_ZERO, 0);
+ code = mono_riscv_emit_nop (code);
+ break;
+ case OP_RISCV_RBNAN:
+ // fclass.s T0, rs1; andi T0, T0, RISCV_FCLASS_NAN; bne T0, zero, target
+ riscv_fclass_s (code, RISCV_T0, ins->sreg1);
+ riscv_andi (code, RISCV_T0, RISCV_T0, RISCV_FCLASS_NAN);
+ mono_add_patch_info_rel (cfg, (code - cfg->native_code), MONO_PATCH_INFO_BB, ins->inst_true_bb,
+ MONO_R_RISCV_BNE);
+ riscv_bne (code, RISCV_T0, RISCV_ZERO, 0);
+ code = mono_riscv_emit_nop (code);
+ break;
case OP_RISCV_EXC_BNE:
case OP_RISCV_EXC_BEQ:
case OP_RISCV_EXC_BGEU:
@@ -4785,7 +5285,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
* we are called from EH code.
*/
if (cfg->param_area)
- riscv_addi (code, RISCV_SP, RISCV_SP, -cfg->param_area);
+ riscv_addi (code, RISCV_SP, RISCV_SP, -ALIGN_TO (cfg->param_area, MONO_ARCH_FRAME_ALIGNMENT));
break;
}
case OP_CALL_HANDLER:
@@ -4869,7 +5369,7 @@ mono_arch_emit_exceptions (MonoCompile *cfg)
exc_class = mono_class_load_from_name (mono_defaults.corlib, "System", ji->data.name);
code = mono_riscv_emit_imm (code, RISCV_A0, m_class_get_type_token (exc_class) - MONO_TOKEN_TYPE_DEF);
/* A1 = throw ip */
- riscv_addi (code, RISCV_A1, RISCV_T0, 0);
+ riscv_addi (code, RISCV_A1, MONO_ARCH_EXC_ADDR_REG, 0);
/* Branch to the corlib exception throwing trampoline */
ji->ip.i = code - cfg->native_code;
ji->type = MONO_PATCH_INFO_JIT_ICALL_ID;
diff --git a/src/mono/mono/mini/mini-riscv.h b/src/mono/mono/mini/mini-riscv.h
index c03905f038d373..36b092c122bb70 100644
--- a/src/mono/mono/mini/mini-riscv.h
+++ b/src/mono/mono/mini/mini-riscv.h
@@ -62,6 +62,7 @@ extern gboolean riscv_stdext_a, riscv_stdext_b, riscv_stdext_c, riscv_stdext_d,
#define MONO_ARCH_CALLEE_REGS (0b11110000000000111111110000000000)
#define MONO_ARCH_CALLEE_SAVED_REGS (0b00001111111111000000001100000000)
#define MONO_ARCH_IS_CALLEE_SAVED_REG(reg) (MONO_ARCH_CALLEE_SAVED_REGS & (1 << (reg)))
+#define MONO_ARCH_EXC_ADDR_REG (RISCV_T1)
/**
* callee saved regs + sp
@@ -111,7 +112,7 @@ extern gboolean riscv_stdext_a, riscv_stdext_b, riscv_stdext_c, riscv_stdext_d,
#endif
-#define MONO_ARCH_RGCTX_REG (RISCV_T6)
+#define MONO_ARCH_RGCTX_REG (RISCV_T2)
#define MONO_ARCH_IMT_REG MONO_ARCH_RGCTX_REG
#define MONO_ARCH_VTABLE_REG (RISCV_A0)
@@ -166,7 +167,7 @@ extern gboolean riscv_stdext_a, riscv_stdext_b, riscv_stdext_c, riscv_stdext_d,
#define MONO_ARCH_GSHARED_SUPPORTED (1)
#define MONO_ARCH_INTERPRETER_SUPPORTED (1)
//#define MONO_ARCH_AOT_SUPPORTED (1)
-//#define MONO_ARCH_LLVM_SUPPORTED (1)
+#define MONO_ARCH_LLVM_SUPPORTED (1)
#define MONO_ARCH_SOFT_DEBUG_SUPPORTED (1)
#define MONO_ARCH_FLOAT32_SUPPORTED (1)
@@ -232,23 +233,24 @@ typedef struct {
} CallContext;
typedef enum {
+ ArgNone, // only in void return type
ArgInIReg = 0x01,
- ArgOnStack,
ArgInFReg,
#ifdef TARGET_RISCV64
ArgInFRegR4,
#endif
+ ArgOnStack,
ArgOnStackR4,
ArgOnStackR8,
+
/*
* Vtype passed in consecutive int registers.
*/
+ ArgVtypeInIReg,
ArgVtypeByRef,
ArgVtypeByRefOnStack,
ArgVtypeOnStack,
- ArgVtypeInIReg,
- ArgVtypeInMixed,
- ArgNone // only in void return type
+ ArgVtypeInMixed
} ArgStorage;
typedef struct {
@@ -295,6 +297,11 @@ mono_riscv_throw_exception (gpointer arg, host_mgreg_t pc, host_mgreg_t *int_reg
__attribute__ ((warn_unused_result)) guint8 *
mono_riscv_emit_imm (guint8 *code, int rd, gsize imm);
+__attribute__ ((warn_unused_result)) guint8 *mono_riscv_emit_float_imm (guint8 *code,
+ int rd,
+ gsize f_imm,
+ gboolean isSingle);
+
__attribute__ ((warn_unused_result)) guint8 *mono_riscv_emit_float_imm (guint8 *code,
int rd,
gsize f_imm,
diff --git a/src/tests/issues.targets b/src/tests/issues.targets
index 12c37bcde107b7..fa787effd3e868 100644
--- a/src/tests/issues.targets
+++ b/src/tests/issues.targets
@@ -3655,6 +3655,12 @@
+
+
+ https://github.com/dotnet/runtime/issues/54906
+
+
+