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 + + +