%% # # inssel-long32-mips.brg: burg file for integer instructions on 32bit MIPS # # Author: # Mark Mason (mason@broadcom.com) # # Based on inssel-long32.brg by: # Dietmar Maurer (dietmar@ximian.com) # # (C) 2006 Broadcom # (C) 2002 Ximian, Inc. # # # 32 bit rules # # # basic alu operations # reg: CEE_AND (reg, reg), reg: CEE_OR (reg, reg), reg: CEE_XOR (reg, reg), reg: CEE_ADD (reg, reg), reg: CEE_SUB (reg, reg), reg: CEE_MUL (reg, reg), reg: CEE_MUL_OVF (reg, reg), reg: CEE_MUL_OVF_UN (reg, reg), reg: CEE_DIV (reg, reg), reg: CEE_DIV_UN (reg, reg), reg: CEE_REM (reg, reg), reg: CEE_REM_UN (reg, reg), reg: CEE_SHL (reg, reg), reg: CEE_SHR (reg, reg), reg: CEE_SHR_UN (reg, reg) { MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1); } reg: CEE_NEG (reg), reg: CEE_NOT (reg) { MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1); } reg: CEE_AND (reg, OP_ICONST) { MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0); } reg: CEE_OR (reg, OP_ICONST) { MONO_EMIT_BIALU_IMM (s, tree, OP_OR_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0); } reg: CEE_XOR (reg, OP_ICONST) { MONO_EMIT_BIALU_IMM (s, tree, OP_XOR_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0); } reg: CEE_ADD (reg, OP_ICONST) { MONO_EMIT_BIALU_IMM (s, tree, OP_ADD_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0); } reg: CEE_SUB (reg, OP_ICONST) { MONO_EMIT_BIALU_IMM (s, tree, OP_SUB_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0); } reg: CEE_MUL (reg, OP_ICONST) { MONO_EMIT_BIALU_IMM (s, tree, OP_MUL_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0); } reg: CEE_SHL (reg, OP_ICONST) { MONO_EMIT_BIALU_IMM (s, tree, OP_SHL_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0); } reg: CEE_SHR (reg, OP_ICONST) { MONO_EMIT_BIALU_IMM (s, tree, OP_SHR_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0); } reg: CEE_SHR_UN (reg, OP_ICONST) { MONO_EMIT_BIALU_IMM (s, tree, OP_SHR_UN_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0); } reg: CEE_ADD_OVF (reg, reg) { MONO_EMIT_NEW_BIALU (s, OP_ADDCC, state->reg1, state->left->reg1, state->right->reg1); MONO_EMIT_NEW_COND_EXC (s, OV, "OverflowException"); } reg: CEE_ADD_OVF_UN (reg, reg) { MONO_EMIT_NEW_BIALU (s, OP_ADDCC, state->reg1, state->left->reg1, state->right->reg1); MONO_EMIT_NEW_COND_EXC (s, C, "OverflowException"); } reg: CEE_SUB (reg, CEE_LDIND_I4 (OP_REGVAR)) { MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->left->tree->dreg); } reg: CEE_SUB_OVF (reg, reg) { MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1); MONO_EMIT_NEW_COND_EXC (s, OV, "OverflowException"); } reg: CEE_SUB_OVF_UN (reg, reg) { MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1); MONO_EMIT_NEW_COND_EXC (s, C, "OverflowException"); } # cflags: OP_COMPARE (reg, reg) { # tree->sreg1 = state->left->reg1; # tree->sreg2 = state->right->reg1; # mono_bblock_add_inst (s->cbb, tree); # } # cflags: OP_COMPARE (CEE_LDIND_REF (OP_REGVAR), reg), # cflags: OP_COMPARE (CEE_LDIND_I (OP_REGVAR), reg), # cflags: OP_COMPARE (CEE_LDIND_I4 (OP_REGVAR), reg), # cflags: OP_COMPARE (CEE_LDIND_U4 (OP_REGVAR), reg) { # tree->sreg1 = state->left->left->tree->dreg; # tree->sreg2 = state->right->reg1; # mono_bblock_add_inst (s->cbb, tree); # } # # cflags: OP_COMPARE (CEE_LDIND_REF (OP_REGVAR), CEE_LDIND_REF (OP_REGVAR)), # cflags: OP_COMPARE (CEE_LDIND_I (OP_REGVAR), CEE_LDIND_I (OP_REGVAR)), # cflags: OP_COMPARE (CEE_LDIND_I4 (OP_REGVAR), CEE_LDIND_I4 (OP_REGVAR)), # cflags: OP_COMPARE (CEE_LDIND_U4 (OP_REGVAR), CEE_LDIND_U4 (OP_REGVAR)) { # tree->sreg1 = state->left->left->tree->dreg; # tree->sreg2 = state->right->left->tree->dreg; # mono_bblock_add_inst (s->cbb, tree); # } # # cflags: OP_COMPARE (CEE_LDIND_REF (OP_REGVAR), OP_ICONST), # cflags: OP_COMPARE (CEE_LDIND_I (OP_REGVAR), OP_ICONST), # cflags: OP_COMPARE (CEE_LDIND_I4 (OP_REGVAR), OP_ICONST), # cflags: OP_COMPARE (CEE_LDIND_U4 (OP_REGVAR), OP_ICONST) { # tree->opcode = OP_COMPARE_IMM; # tree->sreg1 = state->left->left->tree->dreg; # tree->inst_imm = state->right->tree->inst_c0; # mono_bblock_add_inst (s->cbb, tree); # } # # cflags: OP_COMPARE (reg, OP_ICONST) { # tree->opcode = OP_COMPARE_IMM; # tree->sreg1 = state->left->reg1; # tree->inst_imm = state->right->tree->inst_c0; # mono_bblock_add_inst (s->cbb, tree); # } # # stmt: CEE_BNE_UN (cflags), # stmt: CEE_BEQ (cflags), # stmt: CEE_BLT (cflags), # stmt: CEE_BLT_UN (cflags), # stmt: CEE_BGT (cflags), # stmt: CEE_BGT_UN (cflags), # stmt: CEE_BGE (cflags), # stmt: CEE_BGE_UN (cflags), # stmt: CEE_BLE (cflags), # stmt: CEE_BLE_UN (cflags) { # mono_bblock_add_inst (s->cbb, tree); # } # # reg: OP_CEQ (cflags), # reg: OP_CLT (cflags), # reg: OP_CLT_UN (cflags), # reg: OP_CGT (cflags), # reg: OP_CGT_UN (cflags) { # tree->dreg = state->reg1; # mono_bblock_add_inst (s->cbb, tree); # } # # 64 bit rules # # # We use a new non-terminal called "lreg" for 64bit registers, and # emulate lreg with 2 32bit registers. # stmt: CEE_POP (lreg) { /* do nothing */ } i8con: CEE_CONV_I8 (OP_ICONST) "0" { int data = state->left->tree->inst_c0; tree->opcode = OP_I8CONST; tree->inst_ls_word = data; if (data < 0) tree->inst_ms_word = -1; else tree->inst_ms_word = 0; } i8con: CEE_CONV_U8 (OP_ICONST) "0" { int data = state->left->tree->inst_c0; tree->opcode = OP_I8CONST; tree->inst_ls_word = data; tree->inst_ms_word = 0; } i8con: OP_I8CONST "0" lreg: OP_ICONST { int data = state->tree->inst_c0; MONO_EMIT_NEW_ICONST (s, state->reg1, data); if (data >= 0) MONO_EMIT_NEW_ICONST (s, state->reg2, 0); else MONO_EMIT_NEW_ICONST (s, state->reg2, -1); } lreg: OP_I8CONST { MONO_EMIT_NEW_ICONST (s, state->reg1, tree->inst_ls_word); MONO_EMIT_NEW_ICONST (s, state->reg2, tree->inst_ms_word); } lreg: CEE_LDIND_I8 (base) { MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, state->reg1, state->left->tree->inst_basereg, state->left->tree->inst_offset + MINI_LS_WORD_OFFSET); MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, state->reg2, state->left->tree->inst_basereg, state->left->tree->inst_offset + MINI_MS_WORD_OFFSET); } stmt: CEE_STIND_I8 (base, lreg) { MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, state->left->tree->inst_basereg, state->left->tree->inst_offset + MINI_LS_WORD_OFFSET, state->right->reg1); MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, state->left->tree->inst_basereg, state->left->tree->inst_offset + MINI_MS_WORD_OFFSET, state->right->reg2); } stmt: CEE_STIND_I8 (base, i8con) { MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STOREI4_MEMBASE_IMM, state->left->tree->inst_basereg, state->left->tree->inst_offset + MINI_LS_WORD_OFFSET, state->right->tree->inst_ls_word); MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STOREI4_MEMBASE_IMM, state->left->tree->inst_basereg, state->left->tree->inst_offset + MINI_MS_WORD_OFFSET, state->right->tree->inst_ms_word); } lreg: OP_BIGMUL (reg, reg), lreg: OP_BIGMUL_UN (reg, reg) { MONO_EMIT_NEW_BIALU (s, tree->opcode, state->reg1, state->left->reg1, state->right->reg1); } lreg: OP_LONG_SHRUN_32 (lreg) { /* just move the upper half to the lower and zero the high word */ MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg2); MONO_EMIT_NEW_ICONST (s, state->reg2, 0); } reg: OP_LCONV_TO_I4 (OP_LONG_SHRUN_32 (lreg)), reg: OP_LCONV_TO_U4 (OP_LONG_SHRUN_32 (lreg)) { MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->left->reg2); } lreg: OP_LONG_SHRUN_32 (CEE_LDIND_I8 (base)) { /* just move the upper half to the lower and zero the high word */ MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, state->reg1, state->left->left->tree->inst_basereg, state->left->left->tree->inst_offset + MINI_MS_WORD_OFFSET); MONO_EMIT_NEW_ICONST (s, state->reg2, 0); } reg: OP_LCONV_TO_I4 (OP_LONG_SHRUN_32 (CEE_LDIND_I8 (base))), reg: OP_LCONV_TO_U4 (OP_LONG_SHRUN_32 (CEE_LDIND_I8 (base))) { /* just move the upper half to the lower and zero the high word */ MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, state->reg1, state->left->left->left->tree->inst_basereg, state->left->left->left->tree->inst_offset + MINI_MS_WORD_OFFSET); } lreg: OP_LADD (lreg, i8con) { int tmp1 = mono_regstate_next_int (s->rs); MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, state->left->reg1, state->right->tree->inst_ls_word); MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, tmp1, state->reg1, state->left->reg1); MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg2, state->left->reg2, state->right->tree->inst_ms_word); MONO_EMIT_BIALU (s, tree, CEE_ADD, state->reg2, tmp1, state->reg2); } lreg: OP_LADD (lreg, lreg) { int tmp1 = mono_regstate_next_int (s->rs); MONO_EMIT_NEW_BIALU (s, CEE_ADD, state->reg1, state->left->reg1, state->right->reg1); MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, tmp1, state->reg1, state->left->reg1); MONO_EMIT_NEW_BIALU (s, CEE_ADD, state->reg2, state->left->reg2, state->right->reg2); MONO_EMIT_BIALU (s, tree, CEE_ADD, state->reg2, tmp1, state->reg2); } lreg: OP_LADD_OVF (lreg, lreg) { int tmp1 = mono_regstate_next_int (s->rs); int tmp2 = mono_regstate_next_int (s->rs); int tmp3 = mono_regstate_next_int (s->rs); int tmp4 = mono_regstate_next_int (s->rs); int tmp5 = mono_regstate_next_int (s->rs); MONO_EMIT_NEW_BIALU (s, CEE_ADD, state->reg1, state->left->reg1, state->right->reg1); /* tmp1 holds the carry from the low 32-bit to the high 32-bits */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, tmp5, state->reg1, state->left->reg1); /* add the high 32-bits, and add in the carry from the low 32-bits */ MONO_EMIT_NEW_BIALU (s, CEE_ADD, state->reg2, state->left->reg2, state->right->reg2); MONO_EMIT_NEW_BIALU (s, CEE_ADD, state->reg2, tmp5, state->reg2); /* Overflow happens if * neg + neg = pos or * pos + pos = neg * XOR of the high bits returns 0 if the signs match * XOR of that with the high bit of the result return 1 if overflow. */ /* tmp1 = 0 if the signs of the two inputs match, 1 otherwise */ MONO_EMIT_NEW_BIALU (s, CEE_XOR, tmp1, state->left->reg2, state->right->reg2); /* set tmp2 = 0 if bit31 of results matches is different than the operands */ MONO_EMIT_NEW_BIALU (s, CEE_XOR, tmp2, state->reg2, state->right->reg2); MONO_EMIT_NEW_UNALU (s, CEE_NOT, tmp2, tmp2); /* OR(tmp1, tmp2) = 0 if both conditions are true */ MONO_EMIT_NEW_BIALU (s, CEE_OR, tmp3, tmp2, tmp1); MONO_EMIT_NEW_BIALU_IMM (s, OP_SHR_IMM, tmp4, tmp3, 31); /* Now, if (tmp4 == 0) then overflow */ MONO_EMIT_NEW_COMPARE_EXC (s, EQ, tmp4, mips_zero, "OverflowException"); } lreg: OP_LADD_OVF_UN (lreg, lreg) { int tmp1 = mono_regstate_next_int (s->rs); int tmp2 = mono_regstate_next_int (s->rs); MONO_EMIT_NEW_BIALU (s, CEE_ADD, state->reg1, state->left->reg1, state->right->reg1); MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, tmp1, state->reg1, state->left->reg1); MONO_EMIT_NEW_BIALU (s, CEE_ADD, state->reg2, state->left->reg2, state->right->reg2); MONO_EMIT_NEW_BIALU (s, CEE_ADD, state->reg2, tmp1, state->reg2); MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, tmp2, state->reg2, state->left->reg2); MONO_EMIT_NEW_COMPARE_EXC (s, NE_UN, tmp2, mips_zero, "OverflowException"); } lreg: OP_LSUB (lreg, i8con) { int tmp1 = mono_regstate_next_int (s->rs); MONO_EMIT_NEW_BIALU_IMM (s, OP_SUB_IMM, state->reg1, state->left->reg1, state->right->tree->inst_ls_word); MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, tmp1, state->left->reg1, state->reg1); MONO_EMIT_NEW_BIALU_IMM (s, OP_SUB_IMM, state->reg2, state->left->reg2, state->right->tree->inst_ms_word); MONO_EMIT_BIALU (s, tree, CEE_SUB, state->reg2, state->reg2, tmp1); } lreg: OP_LSUB (lreg, lreg) { int tmp1 = mono_regstate_next_int (s->rs); MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg1, state->left->reg1, state->right->reg1); MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, tmp1, state->left->reg1, state->reg1); MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg2, state->left->reg2, state->right->reg2); MONO_EMIT_BIALU (s, tree, CEE_SUB, state->reg2, state->reg2, tmp1); } lreg: OP_LSUB_OVF (lreg, lreg) { int tmp1 = mono_regstate_next_int (s->rs); int tmp2 = mono_regstate_next_int (s->rs); int tmp3 = mono_regstate_next_int (s->rs); int tmp4 = mono_regstate_next_int (s->rs); int tmp5 = mono_regstate_next_int (s->rs); MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg1, state->left->reg1, state->right->reg1); MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, tmp5, state->left->reg1, state->reg1); MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg2, state->left->reg2, state->right->reg2); MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg2, state->reg2, tmp5); /* Overflow happens if * neg - pos = pos or * pos - neg = neg * XOR of bit31 of the lhs & rhs = 1 if the signs are different * * tmp1 = (lhs ^ rhs) * tmp2 = (lhs ^ result) * if ((tmp1 < 0) & (tmp2 < 0)) then overflow */ MONO_EMIT_NEW_BIALU (s, CEE_XOR, tmp1, state->left->reg2, state->right->reg2); MONO_EMIT_NEW_BIALU (s, CEE_XOR, tmp2, state->left->reg2, state->reg2); MONO_EMIT_NEW_BIALU (s, CEE_AND, tmp3, tmp2, tmp1); MONO_EMIT_NEW_BIALU_IMM (s, OP_SHR_IMM, tmp4, tmp3, 31); /* Now, if (tmp4 == 1) then overflow */ MONO_EMIT_NEW_COMPARE_EXC (s, NE_UN, tmp4, mips_zero, "OverflowException"); } lreg: OP_LSUB_OVF_UN (lreg, lreg) { int tmp1 = mono_regstate_next_int (s->rs); int tmp2 = mono_regstate_next_int (s->rs); MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg1, state->left->reg1, state->right->reg1); MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, tmp1, state->left->reg1, state->reg1); MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg2, state->left->reg2, state->right->reg2); MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg2, state->reg2, tmp1); MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, tmp2, state->left->reg2, state->reg2); MONO_EMIT_NEW_COMPARE_EXC (s, NE_UN, tmp2, mips_zero, "OverflowException"); } lreg: OP_LAND (lreg, lreg) { MONO_EMIT_NEW_BIALU (s, CEE_AND, state->reg1, state->left->reg1, state->right->reg1); MONO_EMIT_BIALU (s, tree, CEE_AND, state->reg2, state->left->reg2, state->right->reg2); } lreg: OP_LAND (lreg, i8con) { if (state->right->tree->inst_ls_word == 0xffffffff) MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1); else if (state->right->tree->inst_ls_word == 0) MONO_EMIT_NEW_ICONST (s, state->reg1, 0); else MONO_EMIT_NEW_BIALU_IMM (s, OP_AND_IMM, state->reg1, state->left->reg1, state->right->tree->inst_ls_word); if (state->right->tree->inst_ms_word == 0xffffffff) MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2); else if (state->right->tree->inst_ms_word == 0) MONO_EMIT_NEW_ICONST (s, state->reg2, 0); else MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg2, state->left->reg2, state->right->tree->inst_ms_word); } lreg: OP_LOR (lreg, lreg) { MONO_EMIT_NEW_BIALU (s, CEE_OR, state->reg1, state->left->reg1, state->right->reg1); MONO_EMIT_BIALU (s, tree, CEE_OR, state->reg2, state->left->reg2, state->right->reg2); } lreg: OP_LOR (lreg, i8con) { MONO_EMIT_NEW_BIALU_IMM (s, OP_OR_IMM, state->reg1, state->left->reg1, state->right->tree->inst_ls_word); MONO_EMIT_BIALU_IMM (s, tree, OP_OR_IMM, state->reg2, state->left->reg2, state->right->tree->inst_ms_word); } lreg: OP_LXOR (lreg, lreg) { MONO_EMIT_NEW_BIALU (s, CEE_XOR, state->reg1, state->left->reg1, state->right->reg1); MONO_EMIT_BIALU (s, tree, CEE_XOR, state->reg2, state->left->reg2, state->right->reg2); } lreg: OP_LXOR (lreg, i8con) { MONO_EMIT_NEW_BIALU_IMM (s, OP_XOR_IMM, state->reg1, state->left->reg1, state->right->tree->inst_ls_word); MONO_EMIT_BIALU_IMM (s, tree, OP_XOR_IMM, state->reg2, state->left->reg2, state->right->tree->inst_ms_word); } lreg: OP_LNOT (lreg) { MONO_EMIT_NEW_UNALU (s, CEE_NOT, state->reg1, state->left->reg1); MONO_EMIT_UNALU (s, tree, CEE_NOT, state->reg2, state->left->reg2); } lreg: OP_LNEG (lreg) "4" { MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg1, mips_zero, state->left->reg1); MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, mips_zero, state->reg1); MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg2, mips_zero, state->left->reg2); MONO_EMIT_BIALU (s, tree, CEE_SUB, state->reg2, state->reg2, mips_at); } reg: OP_CEQ (OP_LCOMPARE (lreg, lreg)) { MonoInst *word_differs; int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = state->left->right->reg1; int rreg2 = state->left->right->reg2; MONO_NEW_LABEL (s, word_differs); MONO_EMIT_NEW_ICONST (s, state->reg1, 0); MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BNE_UN, lreg2, rreg2, word_differs); MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BNE_UN, lreg1, rreg1, word_differs); MONO_EMIT_NEW_ICONST (s, state->reg1, 1); mono_bblock_add_inst (s->cbb, word_differs); } reg: OP_CLT (OP_LCOMPARE (lreg, lreg)) { MonoInst *set_to_0, *set_to_1; int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = state->left->right->reg1; int rreg2 = state->left->right->reg2; MONO_NEW_LABEL (s, set_to_0); MONO_NEW_LABEL (s, set_to_1); MONO_EMIT_NEW_ICONST (s, state->reg1, 0); MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BGT, lreg2, rreg2, set_to_0); MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BNE_UN, lreg2, rreg2, set_to_1); MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BGE_UN, lreg1, rreg1, set_to_0); mono_bblock_add_inst (s->cbb, set_to_1); MONO_EMIT_NEW_ICONST (s, state->reg1, 1); mono_bblock_add_inst (s->cbb, set_to_0); } reg: OP_CLT_UN (OP_LCOMPARE (lreg, lreg)) { MonoInst *set_to_0, *set_to_1; int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = state->left->right->reg1; int rreg2 = state->left->right->reg2; MONO_NEW_LABEL (s, set_to_0); MONO_NEW_LABEL (s, set_to_1); MONO_EMIT_NEW_ICONST (s, state->reg1, 0); MONO_EMIT_NEW_ICONST (s, state->reg1, 0); MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BGT_UN, lreg2, rreg2, set_to_0); MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BNE_UN, lreg2, rreg2, set_to_1); MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BGE_UN, lreg1, rreg1, set_to_0); mono_bblock_add_inst (s->cbb, set_to_1); MONO_EMIT_NEW_ICONST (s, state->reg1, 1); mono_bblock_add_inst (s->cbb, set_to_0); } reg: OP_CGT (OP_LCOMPARE (lreg, lreg)) { MonoInst *set_to_0, *set_to_1; int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = state->left->right->reg1; int rreg2 = state->left->right->reg2; MONO_NEW_LABEL (s, set_to_0); MONO_NEW_LABEL (s, set_to_1); MONO_EMIT_NEW_ICONST (s, state->reg1, 0); MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BGT, rreg2, lreg2, set_to_0); MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BNE_UN, rreg2, lreg2, set_to_1); MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BGE_UN, rreg1, lreg1, set_to_0); mono_bblock_add_inst (s->cbb, set_to_1); MONO_EMIT_NEW_ICONST (s, state->reg1, 1); mono_bblock_add_inst (s->cbb, set_to_0); } reg: OP_CGT_UN (OP_LCOMPARE (lreg, lreg)) { MonoInst *set_to_0, *set_to_1; int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = state->left->right->reg1; int rreg2 = state->left->right->reg2; MONO_NEW_LABEL (s, set_to_0); MONO_NEW_LABEL (s, set_to_1); MONO_EMIT_NEW_ICONST (s, state->reg1, 0); MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BGT_UN, rreg2, lreg2, set_to_0); MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BNE_UN, rreg2, lreg2, set_to_1); MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BGE_UN, rreg1, lreg1, set_to_0); mono_bblock_add_inst (s->cbb, set_to_1); MONO_EMIT_NEW_ICONST (s, state->reg1, 1); mono_bblock_add_inst (s->cbb, set_to_0); } stmt: CEE_BNE_UN (OP_LCOMPARE (lreg, lreg)) { int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = state->left->right->reg1; int rreg2 = state->left->right->reg2; MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, lreg2, rreg2, tree->inst_true_bb); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, lreg1, rreg1, tree->inst_true_bb); } stmt: CEE_BNE_UN (OP_LCOMPARE (lreg, i8con)) { int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = mono_regstate_next_int (s->rs); int rreg2 = mono_regstate_next_int (s->rs); MONO_EMIT_NEW_ICONST (s, rreg2, state->left->right->tree->inst_ms_word); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, lreg2, rreg2, tree->inst_true_bb); MONO_EMIT_NEW_ICONST (s, rreg1, state->left->right->tree->inst_ls_word); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, lreg1, rreg1, tree->inst_true_bb); } stmt: CEE_BEQ (OP_LCOMPARE (lreg, lreg)) { int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = state->left->right->reg1; int rreg2 = state->left->right->reg2; MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, lreg2, rreg2, tree->inst_false_bb); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BEQ, lreg1, rreg1, tree->inst_true_bb); } stmt: CEE_BEQ (OP_LCOMPARE (lreg, i8con)) { int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = mono_regstate_next_int (s->rs); int rreg2 = mono_regstate_next_int (s->rs); MONO_EMIT_NEW_ICONST (s, rreg2, state->left->right->tree->inst_ms_word); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, lreg2, rreg2, tree->inst_false_bb); MONO_EMIT_NEW_ICONST (s, rreg1, state->left->right->tree->inst_ls_word); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BEQ, lreg1, rreg1, tree->inst_true_bb); } stmt: CEE_BLE (OP_LCOMPARE (lreg, lreg)) { int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = state->left->right->reg1; int rreg2 = state->left->right->reg2; /* if (lreg2 < rreg2) -> true */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLT, mips_at, lreg2, rreg2); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_true_bb); /* if (lreg2 != rreg2) -> false */ MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, lreg2, rreg2, tree->inst_false_bb); /* (lreg2 == rreg2), if (lreg1 <= rreg1) -> true [or if (rreg1 < lreg1) -> false] */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, rreg1, lreg1); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_false_bb); MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_true_bb); } stmt: CEE_BLE (OP_LCOMPARE (lreg, i8con)) { int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = mono_regstate_next_int (s->rs); int rreg2 = mono_regstate_next_int (s->rs); MONO_EMIT_NEW_ICONST (s, rreg2, state->left->right->tree->inst_ms_word); /* if (lreg2 < rreg2) -> true */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLT, mips_at, lreg2, rreg2); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_true_bb); /* if (lreg2 != rreg2) -> false */ MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, lreg2, rreg2, tree->inst_false_bb); /* (rreg2 == lreg2), if (lreg1 <= rreg1) -> true [or if (rreg1 < lreg1) -> false] */ MONO_EMIT_NEW_ICONST (s, rreg1, state->left->right->tree->inst_ls_word); MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, rreg1, lreg1); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_false_bb); MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_true_bb); } stmt: CEE_BLE_UN (OP_LCOMPARE (lreg, lreg)) { int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = state->left->right->reg1; int rreg2 = state->left->right->reg2; /* if (lreg2 < rreg2) -> true */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, lreg2, rreg2); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_true_bb); /* if (lreg2 != rreg2) -> false */ MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, lreg2, rreg2, tree->inst_false_bb); /* (lreg2 == rreg2), if (lreg1 <= rreg1) -> true [or if (rreg1 < lreg1) -> false] */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, rreg1, lreg1); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_false_bb); MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_true_bb); } stmt: CEE_BLE_UN (OP_LCOMPARE (lreg, i8con)) { int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = mono_regstate_next_int (s->rs); int rreg2 = mono_regstate_next_int (s->rs); MONO_EMIT_NEW_ICONST (s, rreg2, state->left->right->tree->inst_ms_word); /* if (lreg2 < rreg2) -> true */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, lreg2, rreg2); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_true_bb); /* if (lreg2 != rreg2) -> false */ MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, lreg2, rreg2, tree->inst_false_bb); /* (rreg2 == lreg2), if (rreg1 <= lreg1) -> true [or if (rreg1 < lreg1) -> false] */ MONO_EMIT_NEW_ICONST (s, rreg1, state->left->right->tree->inst_ls_word); MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, rreg1, lreg1); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_false_bb); MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_true_bb); } stmt: CEE_BGE (OP_LCOMPARE (lreg, lreg)) { int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = state->left->right->reg1; int rreg2 = state->left->right->reg2; /* if (lreg2 < rreg2) -> false */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLT, mips_at, lreg2, rreg2); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_false_bb); /* if (lreg2 != rreg2) -> true */ MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, lreg2, rreg2, tree->inst_true_bb); /* (lreg2 == rreg2), so if (lreg1 < rreg1) -> false */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, lreg1, rreg1); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_false_bb); MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_true_bb); } stmt: CEE_BGE (OP_LCOMPARE (lreg, i8con)) { int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = mono_regstate_next_int (s->rs); int rreg2 = mono_regstate_next_int (s->rs); MONO_EMIT_NEW_ICONST (s, rreg2, state->left->right->tree->inst_ms_word); /* if (lreg2 < rreg2) -> false */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLT, mips_at, lreg2, rreg2); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_false_bb); /* if (lreg2 != rreg2) -> true */ MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, lreg2, rreg2, tree->inst_true_bb); MONO_EMIT_NEW_ICONST (s, rreg1, state->left->right->tree->inst_ls_word); /* (lreg2 == rreg2), so if (lreg1 < rreg1) -> false */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, lreg1, rreg1); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_false_bb); MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_true_bb); } stmt: CEE_BGE_UN (OP_LCOMPARE (lreg, lreg)) { int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = state->left->right->reg1; int rreg2 = state->left->right->reg2; /* if (lreg2 < rreg2) -> false */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, lreg2, rreg2); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_false_bb); /* if (lreg2 != rreg2) -> true */ MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, lreg2, rreg2, tree->inst_true_bb); /* (rreg2 == lreg2), so if (lreg1 < rreg1) -> false */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, lreg1, rreg1); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_false_bb); MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_true_bb); } stmt: CEE_BGE_UN (OP_LCOMPARE (lreg, i8con)) { int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = mono_regstate_next_int (s->rs); int rreg2 = mono_regstate_next_int (s->rs); MONO_EMIT_NEW_ICONST (s, rreg2, state->left->right->tree->inst_ms_word); /* if (lreg2 < rreg2) -> false */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, lreg2, rreg2); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_false_bb); /* if (lreg2 != rreg2) -> true */ MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, lreg2, rreg2, tree->inst_true_bb); MONO_EMIT_NEW_ICONST (s, rreg1, state->left->right->tree->inst_ls_word); /* (lreg2 == rreg2), so if (lreg1 < rreg1) -> false */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, lreg1, rreg1); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_false_bb); MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_true_bb); } stmt: CEE_BLT (OP_LCOMPARE (lreg, lreg)) { int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = state->left->right->reg1; int rreg2 = state->left->right->reg2; /* if (lreg2 < rreg2) -> true */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLT, mips_at, lreg2, rreg2); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_true_bb); /* if (lreg2 != rreg2) -> false */ MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, lreg2, rreg2, tree->inst_false_bb); /* (lreg2 == rreg2), if (lreg1 < rreg1) -> true */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, lreg1, rreg1); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_true_bb); MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_false_bb); } stmt: CEE_BLT (OP_LCOMPARE (lreg, i8con)) { int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = mono_regstate_next_int (s->rs); int rreg2 = mono_regstate_next_int (s->rs); MONO_EMIT_NEW_ICONST (s, rreg2, state->left->right->tree->inst_ms_word); /* if (lreg2 < rreg2) -> true */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLT, mips_at, lreg2, rreg2); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_true_bb); /* if (lreg2 != rreg2) -> false */ MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, lreg2, rreg2, tree->inst_false_bb); MONO_EMIT_NEW_ICONST (s, rreg1, state->left->right->tree->inst_ls_word); /* (lreg2 == rreg2), if (lreg1 < rreg1) -> true */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, lreg1, rreg1); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_true_bb); MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_false_bb); } stmt: CEE_BLT_UN (OP_LCOMPARE (lreg, lreg)) { int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = state->left->right->reg1; int rreg2 = state->left->right->reg2; /* if (lreg2 < rreg2) -> true */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, lreg2, rreg2); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_true_bb); /* if (lreg2 != rreg2) -> false */ MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, lreg2, rreg2, tree->inst_false_bb); /* (lreg2 == rreg2), if (lreg1 < rreg1) -> true */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, lreg1, rreg1); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_true_bb); MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_false_bb); } stmt: CEE_BLT_UN (OP_LCOMPARE (lreg, i8con)) { int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = mono_regstate_next_int (s->rs); int rreg2 = mono_regstate_next_int (s->rs); MONO_EMIT_NEW_ICONST (s, rreg2, state->left->right->tree->inst_ms_word); /* if (lreg2 < rreg2) -> true */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, lreg2, rreg2); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_true_bb); /* if (lreg2 != rreg2) -> false */ MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, lreg2, rreg2, tree->inst_false_bb); MONO_EMIT_NEW_ICONST (s, rreg1, state->left->right->tree->inst_ls_word); /* (lreg2 == rreg2), if (lreg1 < rreg1) -> true */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, lreg1, rreg1); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_true_bb); MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_false_bb); } stmt: CEE_BGT (OP_LCOMPARE (lreg, lreg)) { int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = state->left->right->reg1; int rreg2 = state->left->right->reg2; /* if (lreg2 < rreg2) -> false */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLT, mips_at, lreg2, rreg2); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_false_bb); /* if (lreg2 != rreg2) -> true */ MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, lreg2, rreg2, tree->inst_true_bb); /* (rreg2 == lreg2), so if (lreg1 > rreg1) -> true */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, rreg1, lreg1); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_true_bb); MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_false_bb); } stmt: CEE_BGT (OP_LCOMPARE (lreg, i8con)) { int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = mono_regstate_next_int (s->rs); int rreg2 = mono_regstate_next_int (s->rs); MONO_EMIT_NEW_ICONST (s, rreg2, state->left->right->tree->inst_ms_word); /* if (lreg2 < rreg2) -> false */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLT, mips_at, lreg2, rreg2); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_false_bb); /* if (lreg2 != rreg2) -> true */ MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, lreg2, rreg2, tree->inst_true_bb); MONO_EMIT_NEW_ICONST (s, rreg1, state->left->right->tree->inst_ls_word); /* (rreg2 == lreg2), so if (lreg1 > rreg1) -> true */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, rreg1, lreg1); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_true_bb); MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_false_bb); } stmt: CEE_BGT_UN (OP_LCOMPARE (lreg, lreg)) { int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = state->left->right->reg1; int rreg2 = state->left->right->reg2; /* if (lreg2 < rreg2) -> false */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, lreg2, rreg2); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_false_bb); /* if (lreg2 != rreg2) -> true */ MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, lreg2, rreg2, tree->inst_true_bb); /* (rreg2 == lreg2), so if (lreg1 > rreg1) -> true */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, rreg1, lreg1); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_true_bb); MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_false_bb); } stmt: CEE_BGT_UN (OP_LCOMPARE (lreg, i8con)) { int lreg1 = state->left->left->reg1; int lreg2 = state->left->left->reg2; int rreg1 = mono_regstate_next_int (s->rs); int rreg2 = mono_regstate_next_int (s->rs); MONO_EMIT_NEW_ICONST (s, rreg2, state->left->right->tree->inst_ms_word); /* if (lreg2 < rreg2) -> false */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, lreg2, rreg2); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_false_bb); /* if (lreg2 != rreg2) -> true */ MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, lreg2, rreg2, tree->inst_true_bb); MONO_EMIT_NEW_ICONST (s, rreg1, state->left->right->tree->inst_ls_word); /* (rreg2 == lreg2), so if (lreg1 > rreg1) -> true */ MONO_EMIT_NEW_BIALU (s, OP_MIPS_SLTU, mips_at, rreg1, lreg1); MONO_EMIT_NEW_COMPARE_BRANCH_BLOCK (s, OP_MIPS_BNE, mips_at, mips_zero, tree->inst_true_bb); MONO_EMIT_NEW_BRANCH_BLOCK (s, OP_BR, tree->inst_false_bb); } lreg: CEE_CONV_I8 (OP_ICONST) { int data = state->left->tree->inst_c0; MONO_EMIT_NEW_ICONST (s, state->reg1, data); if (data >= 0) MONO_EMIT_NEW_ICONST (s, state->reg2, 0); else MONO_EMIT_NEW_ICONST (s, state->reg2, -1); } lreg: CEE_CONV_I8 (reg) { MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1); MONO_EMIT_NEW_BIALU_IMM (s, OP_SHR_IMM, state->reg2, state->left->reg1, 31); } lreg: CEE_CONV_U8 (reg) { MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1); MONO_EMIT_NEW_ICONST (s, state->reg2, 0); } lreg: CEE_CONV_OVF_U8 (reg) { MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg1, 0, "OverflowException"); MONO_EMIT_NEW_ICONST (s, state->reg2, 0); MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1); } lreg: CEE_CONV_OVF_I8 (reg) { /* a signed 32 bit num always fits in a signed 64 bit one */ MONO_EMIT_NEW_BIALU_IMM (s, OP_SHR_IMM, state->reg2, state->left->reg1, 31); MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1); } lreg: CEE_CONV_OVF_I8_UN (reg) { /* an unsigned 32 bit num always fits in a signed 64 bit one */ MONO_EMIT_NEW_ICONST (s, state->reg2, 0); MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1); } lreg: CEE_CONV_OVF_U8_UN (reg) { MONO_EMIT_NEW_ICONST (s, state->reg2, 0); MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1); } freg: OP_LCONV_TO_R_UN (lreg) { MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->left->reg2); } lreg: OP_FCONV_TO_I8 (freg) { MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1); } lreg: OP_FCONV_TO_U8 (freg) { MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1); } reg: OP_LCONV_TO_I4 (i8con) { MONO_EMIT_NEW_ICONST (s, state->reg1, state->left->tree->inst_ls_word); } reg: OP_LCONV_TO_I4 (lreg), reg: OP_LCONV_TO_U4 (lreg) { MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1); } reg: OP_LCONV_TO_I4 (CEE_LDIND_I8 (base)), reg: OP_LCONV_TO_U4 (CEE_LDIND_I8 (base)) { MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI4_MEMBASE, state->reg1, state->left->left->tree->inst_basereg, state->left->left->tree->inst_offset + MINI_LS_WORD_OFFSET); } lreg: OP_LCONV_TO_U8 (lreg), lreg: OP_LCONV_TO_I8 (lreg) { MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1); MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2); } reg: OP_LCONV_TO_U (lreg), reg: OP_LCONV_TO_I (lreg) { MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1); } reg: OP_LCONV_TO_I1 (lreg) { MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1); } reg: OP_LCONV_TO_U1 (lreg) { MONO_EMIT_UNALU (s, tree, CEE_CONV_U1, state->reg1, state->left->reg1); } reg: OP_LCONV_TO_I2 (lreg) { MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1); } reg: OP_LCONV_TO_U2 (lreg) { MONO_EMIT_UNALU (s, tree, CEE_CONV_U2, state->reg1, state->left->reg1); } reg: OP_LCONV_TO_OVF_I1_UN (lreg) { MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, state->left->reg2, 0, "OverflowException"); MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT, state->left->reg1, 127, "OverflowException"); MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg1, -128, "OverflowException"); MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1); } reg: OP_LCONV_TO_OVF_I1 (lreg) { MonoInst *is_negative, *end_label; MONO_NEW_LABEL (s, is_negative); MONO_NEW_LABEL (s, end_label); MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT, state->left->reg2, 0, "OverflowException"); MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg2, -1, "OverflowException"); MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BLT, state->left->reg2, mips_zero, is_negative); /* Positive */ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT_UN, state->left->reg1, 127, "OverflowException"); MONO_EMIT_NEW_BRANCH_LABEL (s, OP_BR, end_label); /* Negative */ mono_bblock_add_inst (s->cbb, is_negative); MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT_UN, state->left->reg1, -128, "OverflowException"); mono_bblock_add_inst (s->cbb, end_label); MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1); } reg: OP_LCONV_TO_OVF_U1_UN (lreg), reg: OP_LCONV_TO_OVF_U1 (lreg) { MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, state->left->reg2, 0, "OverflowException"); /* probe value to be within 0 to 255 */ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT_UN, state->left->reg1, 255, "OverflowException"); MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xff); } reg: OP_LCONV_TO_OVF_I2 (lreg) { MonoInst *is_negative, *end_label; MONO_NEW_LABEL (s, is_negative); MONO_NEW_LABEL (s, end_label); MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT, state->left->reg2, 0, "OverflowException"); MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg2, -1, "OverflowException"); MONO_EMIT_NEW_COMPARE_BRANCH_LABEL (s, CEE_BLT, state->left->reg2, mips_zero, is_negative); /* Positive */ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT_UN, state->left->reg1, 32767, "OverflowException"); MONO_EMIT_NEW_BRANCH_LABEL (s, OP_BR, end_label); /* Negative */ mono_bblock_add_inst (s->cbb, is_negative); MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT_UN, state->left->reg1, -32768, "OverflowException"); mono_bblock_add_inst (s->cbb, end_label); MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1); } reg: OP_LCONV_TO_OVF_I2_UN (lreg) { MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, state->left->reg2, 0, "OverflowException"); /* Probe value to be within -32768 and 32767 */ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT, state->left->reg1, 32767, "OverflowException"); MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg1, -32768, "OverflowException"); MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1); } reg: OP_LCONV_TO_OVF_U2_UN (lreg), reg: OP_LCONV_TO_OVF_U2 (lreg) { MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, state->left->reg2, 0, "OverflowException"); /* Probe value to be within 0 and 65535 */ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, GT_UN, state->left->reg1, 0xffff, "OverflowException"); MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xffff); } reg: OP_LCONV_TO_OVF_U4_UN (lreg) { MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, state->left->reg2, 0, "OverflowException"); MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1); } reg: OP_LCONV_TO_OVF_I_UN (lreg) { MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, state->left->reg2, 0, "OverflowException"); MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1); } reg: OP_LCONV_TO_OVF_U4 (lreg) { MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, state->left->reg2, 0, "OverflowException"); MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1); } reg: OP_LCONV_TO_OVF_I4_UN (lreg) { MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, state->left->reg2, 0, "OverflowException"); MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg1, 0, "OverflowException"); MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1); } reg: OP_LCONV_TO_OVF_I (lreg), reg: OP_LCONV_TO_OVF_I4 (lreg) { 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); } lreg: OP_LCONV_TO_OVF_I8_UN (lreg) { MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg2, 0, "OverflowException"); MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1); MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2); } lreg: OP_LCONV_TO_OVF_U8 (lreg) { MONO_EMIT_NEW_COMPARE_IMM_EXC (s, LT, state->left->reg2, 0, "OverflowException"); MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1); MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2); } lreg: OP_LCONV_TO_OVF_I8 (lreg) { MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1); MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2); } lreg: OP_LCONV_TO_OVF_U8_UN (lreg) { MONO_EMIT_NEW_UNALU (s, OP_MOVE, state->reg1, state->left->reg1); MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg2, state->left->reg2); } lreg: OP_LCALLVIRT (reg) { mini_emit_virtual_call (s, state, tree, OP_LCALL, OP_LCALL_MEMBASE); } lreg: OP_LCALL { tree->dreg = state->reg1; mono_bblock_add_inst (s->cbb, tree); } lreg: OP_LCALL_RGCTX (reg) { emit_rgctx_argument (s, tree, state->left->reg1, OP_LCALL); tree->dreg = state->reg1; mono_bblock_add_inst (s->cbb, tree); } lreg: OP_LCALL_REG (reg) { tree->sreg1 = state->left->reg1; tree->dreg = state->reg1; mono_bblock_add_inst (s->cbb, tree); } lreg: OP_LCALL_REG_RGCTX (reg, reg) { emit_rgctx_argument (s, tree, state->right->reg1, OP_LCALL_REG); tree->sreg1 = state->left->reg1; tree->dreg = state->reg1; mono_bblock_add_inst (s->cbb, tree); } lreg: OP_LCALL_REG (OP_ICONST) { tree->opcode = OP_LCALL; ((MonoCallInst*)tree)->fptr = state->left->tree->inst_p0; tree->dreg = state->reg1; mono_bblock_add_inst (s->cbb, tree); } %%