X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Finssel-ia64.brg;h=decc72c06903aede70a08d48e9c93dabb7a43519;hb=6644c191b8292d9a07227f182be9ce689c1848e2;hp=9b48686a4fa3efd3a0a0059e797d6428ae7efcb7;hpb=f3a7b5e02cd2abbe32485731de507f2938b5bfd6;p=mono.git diff --git a/mono/mini/inssel-ia64.brg b/mono/mini/inssel-ia64.brg index 9b48686a4fa..decc72c0690 100644 --- a/mono/mini/inssel-ia64.brg +++ b/mono/mini/inssel-ia64.brg @@ -1,4 +1,8 @@ +int size_to_ia64_load_u_membase_inc (int size); +int size_to_store_membase_reg (int size); +int size_to_ia64_store_membase_inc_reg (int size); + %% # @@ -132,7 +136,7 @@ stmt: OP_OUTARG_REG (reg) { tree->dreg = mono_regstate_next_int (s->rs); mono_bblock_add_inst (s->cbb, tree); - mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, FALSE); + mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE); } stmt: OP_OUTARG_REG (CEE_LDIND_I (base)), @@ -153,7 +157,7 @@ stmt: OP_OUTARG_REG (CEE_LDIND_I8 (base)) { MONO_EMIT_LOAD_MEMBASE_OP (s, tree, ldind_to_load_membase (state->left->tree->opcode), dreg, base->inst_basereg, base->inst_offset); - mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, FALSE); + mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE); } stmt: OP_OUTARG_REG (OP_I8CONST), @@ -166,7 +170,7 @@ stmt: OP_OUTARG_REG (OP_ICONST) { tree->dreg = mono_regstate_next_int (s->rs); mono_bblock_add_inst (s->cbb, tree); - mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, FALSE); + mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE); } stmt: OP_OUTARG_REG (CEE_LDIND_I (OP_REGVAR)), @@ -181,7 +185,7 @@ stmt: OP_OUTARG_REG (CEE_LDIND_REF (OP_REGVAR)) { tree->dreg = mono_regstate_next_int (s->rs); mono_bblock_add_inst (s->cbb, tree); - mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, FALSE); + mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE); } stmt: OP_OUTARG_FREG (freg) { @@ -192,7 +196,7 @@ stmt: OP_OUTARG_FREG (freg) { tree->dreg = mono_regstate_next_float (s->rs); mono_bblock_add_inst (s->cbb, tree); - mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, TRUE); + mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, TRUE); } stmt: OP_OUTARG (reg) { @@ -218,7 +222,7 @@ stmt: OP_OUTARG_REG (CEE_LDOBJ (OP_REGOFFSET)) { tree->dreg = mono_regstate_next_int (s->rs); mono_bblock_add_inst (s->cbb, tree); - mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, FALSE); + mono_call_inst_add_outarg_reg (s, call, tree->dreg, tree->unused, FALSE); } stmt: OP_SETRET (reg) { @@ -253,11 +257,15 @@ stmt: OP_OUTARG_VT (CEE_LDOBJ (base), base) { if (!sz) return; - sz += 7; - sz &= ~7; mini_emit_memcpy (s, stack_addr->inst_basereg, stack_addr->inst_offset, vt->inst_basereg, vt->inst_offset, sz, 0); } +# This handles trees like outarg_vt (refanytype) +stmt: OP_OUTARG_VT (reg, base) { + MonoInst *stack_addr = state->right->tree; + + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI8_MEMBASE_REG, stack_addr->inst_basereg, stack_addr->inst_offset, state->left->reg1); +} stmt: OP_START_HANDLER { mono_bblock_add_inst (s->cbb, tree); @@ -278,4 +286,177 @@ reg: OP_LOCALLOC (reg) { mono_bblock_add_inst (s->cbb, tree); } +reg: CEE_LDIND_REF (OP_REGVAR), +reg: CEE_LDIND_I (OP_REGVAR), +reg: CEE_LDIND_I8 (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; +} + +reg: OP_ATOMIC_ADD_NEW_I4 (base, OP_ICONST), +reg: OP_ATOMIC_ADD_NEW_I8 (base, OP_ICONST) { + tree->opcode = tree->opcode == OP_ATOMIC_ADD_NEW_I4 ? OP_IA64_FETCHADD4_IMM : OP_IA64_FETCHADD8_IMM; + tree->dreg = state->reg1; + tree->inst_imm = state->right->tree->inst_imm; + tree->inst_basereg = state->left->tree->inst_basereg; + tree->inst_offset = state->left->tree->inst_offset; + + mono_bblock_add_inst (s->cbb, tree); +} cost { + int imm = state->right->tree->inst_imm; + + MBCOND (imm == 1 || imm == 4 || imm == 8 || imm == 16 || imm == -1 || imm == -4 || imm == -8 || imm == -16); + return 1; +} + +reg: OP_ATOMIC_EXCHANGE_I4 (base, reg), +reg: OP_ATOMIC_EXCHANGE_I8 (base, reg), +reg: OP_ATOMIC_ADD_NEW_I4 (base, reg), +reg: OP_ATOMIC_ADD_NEW_I8 (base, reg) { + tree->opcode = tree->opcode; + tree->dreg = state->reg1; + tree->sreg2 = state->right->reg1; + tree->inst_basereg = state->left->tree->inst_basereg; + tree->inst_offset = state->left->tree->inst_offset; + + mono_bblock_add_inst (s->cbb, tree); +} + +# Optimized memset implementation +stmt: OP_MEMSET (base) "0" { + int dest_reg, dest_reg2, val_reg, unit, align; + int size = tree->unused; + + dest_reg = mono_regstate_next_int (s->rs); + + if (state->left->tree->inst_basereg == s->frame_reg) + /* Aligned by mono_allocate_stack_slots */ + align = 8; + else + align = 4; + + if (tree->inst_imm == 0) + val_reg = IA64_R0; + else { + val_reg = mono_regstate_next_int (s->rs); + + MONO_EMIT_NEW_ICONST (s, val_reg, tree->inst_imm); + } + + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, dest_reg, state->left->tree->inst_basereg, state->left->tree->inst_offset); + + for (unit = align; unit >= 1; unit = unit >> 1) { + dest_reg2 = mono_regstate_next_int (s->rs); + + /* Use two destination regs to increase paralellism */ + if (size >= 2 * unit) { + int diff = (size / (2 * unit)) * unit; + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, dest_reg2, state->left->tree->inst_basereg, state->left->tree->inst_offset + diff); + + while (size >= (2 * unit)) { + MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg, 0, val_reg); + MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg2, 0, val_reg); + size -= 2 * unit; + } + + if (size > 0) + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, dest_reg, dest_reg, diff); + } + + while (size >= unit) { + if (size == unit) + MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_store_membase_reg (unit), dest_reg, 0, val_reg); + else + MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg, 0, val_reg); + size -= unit; + } + } + +} + +# Optimized memcpy implementation +stmt: OP_MEMCPY (base, base) "0" { + int cur_reg, src_reg, dest_reg, unit; + int size = tree->unused; + int align; + + src_reg = mono_regstate_next_int (s->rs); + dest_reg = mono_regstate_next_int (s->rs); + + if ((state->left->tree->inst_basereg == s->frame_reg) && + (state->right->tree->inst_basereg == s->frame_reg)) + /* Aligned by mono_allocate_stack_slots */ + align = 8; + else + align = 4; + + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, dest_reg, state->left->tree->inst_basereg, state->left->tree->inst_offset); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, src_reg, state->right->tree->inst_basereg, state->right->tree->inst_offset); + + for (unit = align; unit >= 1; unit = unit >> 1) { + while (size >= unit) { + cur_reg = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, size_to_ia64_load_u_membase_inc (unit), cur_reg, src_reg, 0); + MONO_EMIT_NEW_STORE_MEMBASE (s, size_to_ia64_store_membase_inc_reg (unit), dest_reg, 0, cur_reg); + size -= unit; + } + } +} + %% + +int +size_to_ia64_load_u_membase_inc (int size) +{ + switch (size) { + case 1: + return OP_IA64_LOADU1_MEMBASE_INC; + case 2: + return OP_IA64_LOADU2_MEMBASE_INC; + case 4: + return OP_IA64_LOADU4_MEMBASE_INC; + case 8: + return OP_IA64_LOADI8_MEMBASE_INC; + default: + g_assert_not_reached (); + return -1; + } +} + +int +size_to_store_membase_reg (int size) +{ + switch (size) { + case 1: + return OP_STOREI1_MEMBASE_REG; + case 2: + return OP_STOREI2_MEMBASE_REG; + case 4: + return OP_STOREI4_MEMBASE_REG; + case 8: + return OP_STOREI8_MEMBASE_REG; + default: + g_assert_not_reached (); + return -1; + } +} + +int +size_to_ia64_store_membase_inc_reg (int size) +{ + switch (size) { + case 1: + return OP_IA64_STOREI1_MEMBASE_INC_REG; + case 2: + return OP_IA64_STOREI2_MEMBASE_INC_REG; + case 4: + return OP_IA64_STOREI4_MEMBASE_INC_REG; + case 8: + return OP_IA64_STOREI8_MEMBASE_INC_REG; + default: + g_assert_not_reached (); + return -1; + } +}