%% # # inssel-hppa.brg: burg file for special hppa instructions # # Copyright (c) 2007 Randolph Chung # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # # Load/store operations reg: CEE_LDIND_I1 (OP_REGVAR) { MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->tree->dreg); } reg: CEE_LDIND_I2 (OP_REGVAR) { MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->tree->dreg); } reg: CEE_LDIND_REF (OP_REGVAR), reg: CEE_LDIND_I (OP_REGVAR), reg: CEE_LDIND_I4 (OP_REGVAR), reg: CEE_LDIND_U4 (OP_REGVAR) "0" { state->reg1 = state->left->tree->dreg; tree->dreg = state->reg1; } lreg: CEE_LDIND_I8 (OP_REGVAR) { /* reg2 contains the most significant word */ MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg2, state->left->tree->dreg); tree->opcode = OP_MOVE; tree->dreg = state->reg1; tree->sreg1 = state->left->tree->dreg + 1; mono_bblock_add_inst (s->cbb, tree); } freg: CEE_LDIND_R4 (OP_REGVAR) { MONO_EMIT_UNALU (s, tree, OP_FMOVE, state->reg1, state->left->tree->dreg); } freg: CEE_LDIND_R8 (OP_REGVAR) { MONO_EMIT_UNALU (s, tree, OP_FMOVE, state->reg1, state->left->tree->dreg); } stmt: CEE_STIND_I8 (OP_REGVAR, reg) { MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->left->tree->dreg, state->right->reg1); } stmt: CEE_STIND_I8 (OP_REGVAR, lreg) { /* this should only happen for methods returning a long */ MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->left->tree->dreg, state->right->reg1); MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->left->tree->dreg + 1, state->right->reg2); } # Outputing arguments stmt: OP_OUTARG (reg) { MonoCallInst *call = tree->inst_call; MonoHPPAArgInfo *ai = tree->backend.data; tree->opcode = OP_MOVE; tree->dreg = mono_regstate_next_int (s->rs); tree->sreg1 = state->left->reg1; mono_bblock_add_inst (s->cbb, tree); mono_call_inst_add_outarg_reg (s, call, tree->dreg, ai->reg, FALSE); } stmt: OP_HPPA_OUTARG_REGOFFSET (base) { MonoCallInst *call = tree->inst_call; tree->inst_basereg = state->left->tree->inst_basereg; tree->inst_offset = state->left->tree->inst_offset; tree->dreg = mono_regstate_next_int (s->rs); mono_bblock_add_inst (s->cbb, tree); mono_call_inst_add_outarg_reg (s, call, tree->dreg, hppa_r28, FALSE); } stmt: OP_OUTARG (OP_REGVAR) { MonoCallInst *call = tree->inst_call; MonoHPPAArgInfo *ai = tree->backend.data; tree->opcode = OP_MOVE; tree->dreg = mono_regstate_next_int (s->rs); tree->sreg1 = state->left->tree->dreg; mono_bblock_add_inst (s->cbb, tree); mono_call_inst_add_outarg_reg (s, call, tree->dreg, ai->reg, FALSE); } stmt: OP_OUTARG (lreg) { MonoCallInst *call = tree->inst_call; MonoHPPAArgInfo *ai = tree->backend.data; int tdreg = mono_regstate_next_int (s->rs); MONO_EMIT_NEW_UNALU (s, OP_MOVE, tdreg, state->left->reg2); mono_call_inst_add_outarg_reg (s, call, tdreg, ai->reg, FALSE); tree->opcode = OP_MOVE; tree->dreg = mono_regstate_next_int (s->rs); tree->sreg1 = state->left->reg1; mono_bblock_add_inst (s->cbb, tree); mono_call_inst_add_outarg_reg (s, call, tree->dreg, ai->reg + 1, FALSE); } stmt: OP_OUTARG (OP_ICONST) { MonoCallInst *call = tree->inst_call; MonoHPPAArgInfo *ai = tree->backend.data; tree->opcode = OP_ICONST; tree->dreg = mono_regstate_next_int (s->rs); tree->inst_c0 = state->left->tree->inst_c0; mono_bblock_add_inst (s->cbb, tree); mono_call_inst_add_outarg_reg (s, call, tree->dreg, ai->reg, FALSE); } stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGVAR)) { MonoCallInst *call = tree->inst_call; MonoHPPAArgInfo *ai = tree->backend.data; tree->opcode = OP_MOVE; tree->dreg = mono_regstate_next_int (s->rs); tree->sreg1 = state->left->left->tree->dreg; mono_bblock_add_inst (s->cbb, tree); mono_call_inst_add_outarg_reg (s, call, tree->dreg, ai->reg, FALSE); } stmt: OP_OUTARG_VT (CEE_LDOBJ (base)) "0" { MonoCallInst *call = tree->inst_call; MonoHPPAArgInfo *ai = tree->backend.data; int start_reg = ai->reg; int size = ai->size; int nregs = (size + (sizeof (gpointer) - 1)) / sizeof (gpointer); int i, tmpr, soffset, dreg; MonoInst *vt = state->left->left->tree; soffset = vt->inst_offset; if (ai->pass_in_reg) { for (i = 0; i < nregs; ++i) { tmpr = mono_regstate_next_int (s->rs); MONO_EMIT_NEW_LOAD_MEMBASE (s, tmpr, vt->inst_basereg, soffset); dreg = mono_regstate_next_int (s->rs); if (size < sizeof (gpointer)) MONO_EMIT_NEW_BIALU_IMM (s, OP_SHR_IMM, dreg, tmpr, (sizeof (gpointer) - size) * 8); else MONO_EMIT_NEW_UNALU (s, OP_MOVE, dreg, tmpr); mono_call_inst_add_outarg_reg (s, call, dreg, start_reg + i, FALSE); soffset += sizeof (gpointer); size -= sizeof (gpointer); } } else { mini_emit_memcpy (s, hppa_sp, ai->offset, vt->inst_basereg, soffset, size, 0); } } stmt: OP_OUTARG_R4 (freg) { MonoCallInst *call = tree->inst_call; tree->opcode = OP_HPPA_SETF4REG; tree->dreg = mono_regstate_next_float (s->rs); tree->sreg1 = state->left->reg1; mono_bblock_add_inst (s->cbb, tree); mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, TRUE); } stmt: OP_OUTARG_R4 (OP_R4CONST) { MonoCallInst *call = tree->inst_call; tree->opcode = OP_HPPA_OUTARG_R4CONST; tree->dreg = mono_regstate_next_float (s->rs); tree->inst_p0 = state->left->tree->inst_p0; mono_bblock_add_inst (s->cbb, tree); mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, TRUE); } stmt: OP_OUTARG_R8 (freg), stmt: OP_OUTARG (freg) { MonoCallInst *call = tree->inst_call; tree->opcode = OP_FMOVE; tree->dreg = mono_regstate_next_float (s->rs); tree->sreg1 = state->left->reg1; mono_bblock_add_inst (s->cbb, tree); mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->backend.reg3, TRUE); } stmt: OP_OUTARG_MEMBASE (reg) { MonoHPPAArgInfo *ai = tree->backend.data; switch (ai->size) { case 1: MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI1_MEMBASE_REG, hppa_sp, ai->offset, state->left->reg1); break; case 2: MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI2_MEMBASE_REG, hppa_sp, ai->offset, state->left->reg1); break; case 4: MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, hppa_sp, ai->offset, state->left->reg1); break; default: g_assert_not_reached (); } } stmt: OP_OUTARG_MEMBASE (OP_ICONST) { MonoHPPAArgInfo *ai = tree->backend.data; switch (ai->size) { case 1: MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STOREI1_MEMBASE_IMM, hppa_sp, ai->offset, state->left->tree->inst_c0); break; case 2: MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STOREI2_MEMBASE_IMM, hppa_sp, ai->offset, state->left->tree->inst_c0); break; case 4: MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STORE_MEMBASE_IMM, hppa_sp, ai->offset, state->left->tree->inst_c0); break; default: g_assert_not_reached (); } } stmt: OP_OUTARG_MEMBASE (lreg) { MonoHPPAArgInfo *ai = tree->backend.data; MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, hppa_sp, ai->offset, state->left->reg2); MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, hppa_sp, ai->offset + 4, state->left->reg1); } stmt: OP_OUTARG_MEMBASE (freg) { MonoHPPAArgInfo *ai = tree->backend.data; if (ai->size == 4) MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, hppa_sp, ai->offset, state->left->reg1); else MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, hppa_sp, ai->offset, state->left->reg1); } stmt: OP_OUTARG_MEMBASE (OP_R4CONST) { MonoHPPAArgInfo *ai = tree->backend.data; unsigned int constaddr = mono_regstate_next_int (s->rs); unsigned int tmp = mono_regstate_next_float (s->rs); MONO_EMIT_NEW_ICONST (s, constaddr, (unsigned int)state->left->tree->inst_p0); MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_HPPA_LOADR4_LEFT, tmp, constaddr, 0); MONO_EMIT_NEW_STORE_MEMBASE (s, OP_HPPA_STORER4_LEFT, hppa_sp, ai->offset, tmp); } reg: OP_LOCALLOC (OP_ICONST) { tree->sreg1 = mono_regstate_next_int (s->rs); tree->dreg = state->reg1; MONO_EMIT_NEW_ICONST (s, tree->sreg1, state->left->tree->inst_c0); mono_bblock_add_inst (s->cbb, tree); } reg: OP_LOCALLOC (reg) { tree->dreg = state->reg1; tree->sreg1 = state->left->reg1; mono_bblock_add_inst (s->cbb, tree); } stmt: OP_SETRET (reg) { tree->opcode = OP_MOVE; tree->sreg1 = state->left->reg1; tree->dreg = hppa_r28; mono_bblock_add_inst (s->cbb, tree); } stmt: OP_SETRET (lreg) { tree->opcode = OP_SETLRET; tree->sreg1 = state->left->reg1; tree->sreg2 = state->left->reg2; tree->dreg = hppa_r28; mono_bblock_add_inst (s->cbb, tree); } stmt: OP_SETRET (freg) { if (mono_method_signature (s->method)->ret->type == MONO_TYPE_R4) { tree->opcode = OP_HPPA_SETF4REG; } else { tree->opcode = OP_FMOVE; } tree->sreg1 = state->left->reg1; tree->dreg = hppa_fr4; mono_bblock_add_inst (s->cbb, tree); } # Comparision rules: hppa does not have an addressable status register, so # we have to do compare-and-branch in a single step # Override the cost of the rule in the base inssel.brg so that this is preferred # We are using this so that all the combinations of OP_COMPARE(reg, OP_ICONST) # will get folded into OP_COMPARE(reg, reg) to simplify our compare-and-branch # rules. # FIXME: this is ugly, we should expand the rules here, or try to refactor # the rules in the base set reg: OP_ICONST "0" { tree->dreg = state->reg1; MONO_EMIT_NEW_ICONST (s, state->reg1, tree->inst_c0); } stmt: OP_SWITCH (reg) { MonoInst *label, *inst; int n = GPOINTER_TO_INT (tree->klass); int sreg = mono_regstate_next_int (s->rs); MONO_NEW_LABEL (s, label); MONO_EMIT_NEW_ICONST (s, sreg, n); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK(s, CEE_BGE_UN, state->left->reg1, sreg, tree->inst_many_bb [n]); mono_bblock_add_inst (s->cbb, label); mono_create_jump_table (s, label, tree->inst_many_bb, n); /* the backend code will deal with aot vs normal case */ tree->sreg1 = state->left->reg1; mono_bblock_add_inst (s->cbb, tree); } stmt: CEE_BEQ (OP_COMPARE(reg, reg)), stmt: CEE_BNE_UN (OP_COMPARE(reg, reg)), stmt: CEE_BGE (OP_COMPARE(reg, reg)), stmt: CEE_BGE_UN (OP_COMPARE(reg, reg)), stmt: CEE_BGT (OP_COMPARE(reg, reg)), stmt: CEE_BGT_UN (OP_COMPARE(reg, reg)), stmt: CEE_BLE (OP_COMPARE(reg, reg)), stmt: CEE_BLE_UN (OP_COMPARE(reg, reg)), stmt: CEE_BLT (OP_COMPARE(reg, reg)), stmt: CEE_BLT_UN (OP_COMPARE(reg, reg)) "0" { tree->opcode = OP_HPPA_BEQ + (tree->opcode - CEE_BEQ); tree->sreg1 = state->left->left->reg1; tree->sreg2 = state->left->right->reg1; tree->inst_offset = state->left->left->tree->inst_offset; mono_bblock_add_inst (s->cbb, tree); } reg: OP_CEQ (OP_COMPARE (reg, reg)), reg: OP_CGT (OP_COMPARE (reg, reg)), reg: OP_CGT_UN (OP_COMPARE (reg, reg)), reg: OP_CLT (OP_COMPARE (reg, reg)), reg: OP_CLT_UN (OP_COMPARE (reg, reg)) "0" { MONO_EMIT_BIALU (s, tree, OP_HPPA_CEQ + (tree->opcode - OP_CEQ), state->reg1, state->left->left->reg1, state->left->right->reg1); } reg: OP_CEQ (OP_COMPARE_IMM (reg, OP_ICONST)), reg: OP_CLT (OP_COMPARE_IMM (reg, OP_ICONST)), reg: OP_CLT_UN (OP_COMPARE_IMM (reg, OP_ICONST)), reg: OP_CGT (OP_COMPARE_IMM (reg, OP_ICONST)), reg: OP_CGT_UN (OP_COMPARE_IMM (reg, OP_ICONST)) "0" { MONO_EMIT_BIALU_IMM (s, tree, OP_HPPA_CEQ_IMM + (tree->opcode - OP_CEQ), state->reg1, state->left->left->reg1, state->left->right->reg1); } # Floating point versions of the compare functions stmt: CEE_BEQ (OP_COMPARE (freg, freg)), stmt: CEE_BNE_UN (OP_COMPARE (freg, freg)), stmt: CEE_BLT (OP_COMPARE (freg, freg)), stmt: CEE_BLT_UN (OP_COMPARE (freg, freg)), stmt: CEE_BGT (OP_COMPARE (freg, freg)), stmt: CEE_BGT_UN (OP_COMPARE (freg, freg)), stmt: CEE_BGE (OP_COMPARE (freg, freg)), stmt: CEE_BGE_UN (OP_COMPARE (freg, freg)), stmt: CEE_BLE (OP_COMPARE (freg, freg)), stmt: CEE_BLE_UN (OP_COMPARE (freg, freg)) "0" { tree->opcode = OP_FBEQ + (tree->opcode - CEE_BEQ); tree->sreg1 = state->left->left->reg1; tree->sreg2 = state->left->right->reg1; mono_bblock_add_inst (s->cbb, tree); } reg: OP_CEQ (OP_COMPARE (freg, freg)), reg: OP_CGT (OP_COMPARE (freg, freg)), reg: OP_CGT_UN (OP_COMPARE (freg, freg)), reg: OP_CLT (OP_COMPARE (freg, freg)), reg: OP_CLT_UN (OP_COMPARE (freg, freg)) "0" { tree->opcode = OP_FCEQ + (tree->opcode - OP_CEQ); tree->sreg1 = state->left->left->reg1; tree->sreg2 = state->left->right->reg1; tree->dreg = state->reg1; mono_bblock_add_inst (s->cbb, tree); } # ALU operations reg: CEE_ADD_OVF (reg, reg), reg: CEE_ADD_OVF_UN (reg, reg) "0" { tree->backend.reg3 = tree->opcode; tree->opcode = OP_HPPA_ADD_OVF; tree->sreg1 = state->left->reg1; tree->sreg2 = state->right->reg1; tree->dreg = state->reg1; mono_bblock_add_inst (s->cbb, tree); } lreg: OP_LADD_OVF (lreg, lreg), lreg: OP_LADD_OVF_UN (lreg, lreg) "0" { MONO_EMIT_NEW_BIALU (s, CEE_ADD, state->reg1, state->left->reg1, state->right->reg1); tree->backend.reg3 = tree->opcode; tree->opcode = OP_HPPA_ADDC_OVF; tree->sreg1 = state->left->reg2; tree->sreg2 = state->right->reg2; tree->dreg = state->reg2; mono_bblock_add_inst (s->cbb, tree); } reg: CEE_SUB_OVF (reg, reg), reg: CEE_SUB_OVF_UN (reg, reg) "0" { MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1); tree->backend.reg3 = tree->opcode; tree->opcode = OP_HPPA_SUB_OVF; tree->sreg1 = state->left->reg1; tree->sreg2 = state->right->reg1; tree->dreg = state->reg1; mono_bblock_add_inst (s->cbb, tree); } lreg: OP_LSUB_OVF (lreg, lreg), lreg: OP_LSUB_OVF_UN (lreg, lreg) "0" { MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg1, state->left->reg1, state->right->reg1); tree->backend.reg3 = tree->opcode; tree->opcode = OP_HPPA_SUBB_OVF; tree->sreg1 = state->left->reg2; tree->sreg2 = state->right->reg2; tree->dreg = state->reg2; mono_bblock_add_inst (s->cbb, tree); } lreg: OP_LNEG (lreg) "2" { MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg1, hppa_r0, state->left->reg1); MONO_EMIT_BIALU (s, tree, OP_SBB, state->reg2, hppa_r0, state->left->reg2); } reg: CEE_MUL (reg, reg), reg: CEE_MUL_OVF (reg, reg), reg: CEE_MUL_OVF_UN (reg, reg) "0" { guint32 sreg1 = state->left->reg1; guint32 sreg2 = state->right->reg1; guint32 dreg = state->reg1; guint32 freg1, freg2, freg3; freg1 = mono_regstate_next_float (s->rs); freg2 = mono_regstate_next_float (s->rs); freg3 = mono_regstate_next_float (s->rs); /* TODO: this scribbles on 4-bytes past the end of the stack; need * to figure out how to properly "reserve" a temp stack slot for * this */ MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, hppa_sp, 0, sreg1); MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_HPPA_LOADR4_LEFT, freg1, hppa_sp, 0); MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, hppa_sp, 0, sreg2); MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_HPPA_LOADR4_LEFT, freg2, hppa_sp, 0); MONO_EMIT_NEW_BIALU (s, OP_HPPA_XMPYU, freg3, freg1, freg2); MONO_EMIT_NEW_STORE_MEMBASE (s, OP_HPPA_STORER4_RIGHT, hppa_sp, 0, freg3); MONO_EMIT_LOAD_MEMBASE (s, tree, dreg, hppa_sp, 0); } reg: CEE_MUL(reg, OP_ICONST), reg: OP_MUL_IMM(reg, OP_ICONST), reg: CEE_MUL_OVF (reg, OP_ICONST), reg: CEE_MUL_OVF_UN (reg, OP_ICONST) "0" { guint32 sreg1 = state->left->reg1; gssize imm = state->right->tree->inst_c0; guint32 dreg = state->reg1; guint32 freg1, freg2, freg3; freg1 = mono_regstate_next_float (s->rs); freg2 = mono_regstate_next_float (s->rs); freg3 = mono_regstate_next_float (s->rs); /* TODO: this scribbles on 4-bytes past the end of the stack; need * to figure out how to properly "reserve" a temp stack slot for * this */ MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, hppa_sp, 0, sreg1); MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADR4_MEMBASE, freg1, hppa_sp, 0); MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STORE_MEMBASE_IMM, hppa_sp, 0, imm); MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADR4_MEMBASE, freg2, hppa_sp, 0); MONO_EMIT_NEW_BIALU (s, OP_HPPA_XMPYU, freg3, freg1, freg2); MONO_EMIT_NEW_STORE_MEMBASE (s, OP_HPPA_STORER4_RIGHT, hppa_sp, 0, freg3); MONO_EMIT_LOAD_MEMBASE (s, tree, dreg, hppa_sp, 0); } # Floating point ALU ops freg: OP_FNEG (freg) "0" { extern double hppa_zero; MonoInst *inst = mono_mempool_alloc0 (s->mempool, sizeof (MonoInst)); inst->opcode = OP_R8CONST; inst->dreg = mono_regstate_next_float (s->rs); inst->inst_p0 = (gpointer)&hppa_zero; mono_bblock_add_inst (s->cbb, inst); MONO_EMIT_BIALU (s, tree, OP_FSUB, state->reg1, inst->dreg, state->left->reg1); } # Conversion operations lreg: CEE_CONV_I8 (reg) "0" { int tmpreg = mono_regstate_next_int (s->rs); int negone = mono_regstate_next_int (s->rs); /* branchless code: * low = reg; * tmp = low > -1 ? 1: 0; * high = tmp - 1; if low is zero or pos high becomes 0, else -1 */ MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1); MONO_EMIT_NEW_ICONST (s, negone, -1); MONO_EMIT_NEW_BIALU (s, OP_HPPA_CGT, tmpreg, state->reg1, negone); MONO_EMIT_NEW_BIALU_IMM (s, OP_SUB_IMM, state->reg2, tmpreg, 1); } freg: OP_LCONV_TO_R8 (lreg) { tree->sreg1 = state->left->reg1; tree->dreg = state->reg1; mono_bblock_add_inst (s->cbb, tree); } freg: OP_LCONV_TO_R8 (lreg) { /* Dummy rule */ } freg: OP_LCONV_TO_R4 (lreg) { tree->sreg1 = state->left->reg1; tree->dreg = state->reg1; mono_bblock_add_inst (s->cbb, tree); } reg: OP_LCONV_TO_OVF_I (lreg), reg: OP_LCONV_TO_OVF_I4 (lreg) "0" { int tmp_reg = mono_regstate_next_int (s->rs); /* Overflows if reg2 != sign extension of reg1 */ MONO_EMIT_BIALU_IMM (s, tree, OP_SHR_IMM, tmp_reg, state->left->reg1, 31); MONO_EMIT_NEW_COMPARE_EXC (s, NE_UN, state->left->reg2, tmp_reg, "OverflowException"); MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1); } # Exception handling stmt: OP_START_HANDLER { MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region); tree->inst_left = spvar; mono_bblock_add_inst (s->cbb, tree); } stmt: OP_ENDFINALLY { MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region); tree->inst_left = spvar; mono_bblock_add_inst (s->cbb, tree); } stmt: OP_ENDFILTER (reg) { MonoInst *spvar = mono_find_spvar_for_region (s, s->cbb->region); tree->inst_left = spvar; tree->sreg1 = state->left->reg1; mono_bblock_add_inst (s->cbb, tree); } %%