X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Finssel-s390x.brg;h=f0940f75af302ef37e30f88312bf2a16a2e6a760;hb=824e66edd228b294f297e1d2257342db834a423b;hp=885c545d55a97007e97563faba9d16278577bd59;hpb=e54afad3445effa28adfad80e19821df97629230;p=mono.git diff --git a/mono/mini/inssel-s390x.brg b/mono/mini/inssel-s390x.brg index 885c545d55a..f0940f75af3 100644 --- a/mono/mini/inssel-s390x.brg +++ b/mono/mini/inssel-s390x.brg @@ -1,7 +1,7 @@ %% # -# inssel-s390.brg: burg file for special s390 instructions +# inssel-s390x.brg: burg file for special s390 instructions # # Author: # Neale Ferguson (Neale.Ferguson@SoftwareAG-usa.com) @@ -30,53 +30,23 @@ stmt: OP_ENDFILTER (reg) { mono_bblock_add_inst (s->cbb, tree); } -lreg: OP_LADD_OVF (lreg, lreg) "0" { - /* ADC sets the condition code */ - MONO_EMIT_NEW_BIALU (s, OP_ADDCC, state->reg1, state->left->reg1, state->right->reg1); - MONO_EMIT_NEW_BIALU (s, OP_ADD_OVF_CARRY, state->reg2, state->left->reg2, state->right->reg2); -} - -lreg: OP_LADD_OVF_UN (lreg, lreg) "0" { - /* ADC sets the condition code */ - MONO_EMIT_NEW_BIALU (s, OP_ADDCC, state->reg1, state->left->reg1, state->right->reg1); - MONO_EMIT_NEW_BIALU (s, OP_ADD_OVF_UN_CARRY, state->reg2, state->left->reg2, state->right->reg2); -} - -lreg: OP_LSUB_OVF (lreg, lreg) "0" { - /* SBB sets the condition code */ - MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1); - MONO_EMIT_NEW_BIALU (s, OP_SUB_OVF_CARRY, state->reg2, state->left->reg2, state->right->reg2); -} - -lreg: OP_LSUB_OVF_UN (lreg, lreg) "0" { - /* SBB sets the condition code */ - MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1); - MONO_EMIT_NEW_BIALU (s, OP_SUB_OVF_UN_CARRY, state->reg2, state->left->reg2, state->right->reg2); -} - -reg: CEE_ADD_OVF (reg, reg) "0" { - MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1); -} - -reg: CEE_ADD_OVF_UN (reg, reg) "0" { - MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1); -} - -reg: CEE_SUB_OVF (reg, reg) "0" { +reg: CEE_ADD_OVF (reg, reg), +reg: OP_LADD_OVF (reg, reg), +reg: CEE_ADD_OVF_UN (reg, reg), +reg: OP_LADD_OVF_UN (reg, reg), +reg: CEE_SUB_OVF (reg, reg), +reg: OP_LSUB_OVF (reg, reg), +reg: CEE_SUB_OVF_UN (reg, reg), +reg: OP_LSUB_OVF_UN (reg, reg) "0" { MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1); } -reg: CEE_SUB_OVF_UN (reg, reg) "0" { - MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1); +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 */ - /* S/390 ABI uses r2/r3 for returning 64-bit integers */ - /*------------------------------------------------------*/ - MONO_EMIT_NEW_UNALU (s, OP_MOVE, s390_r2, state->right->reg1); - MONO_EMIT_NEW_UNALU (s, OP_MOVE, s390_r3, state->right->reg2); +reg: CEE_LDIND_I8 (OP_REGVAR) { + state->reg1 = state->left->tree->dreg; } freg: OP_LCONV_TO_R8 (lreg) { @@ -109,6 +79,16 @@ stmt: OP_MEMCPY (reg, reg) "0" { MONO_EMIT_NEW_MOVE (s, state->left->reg1, 0, state->right->reg1, 0, size); } +stmt: OP_MEMCPY (base, base) "0" { + int size = tree->unused; + if (size > 0) + MONO_EMIT_NEW_MOVE (s, state->left->tree->sreg1, + state->left->tree->inst_offset, + state->right->tree->sreg1, + state->right->tree->inst_offset, + size); +} + reg: OP_LOCALLOC (OP_ICONST) { /* microcoded in mini-s390.c */ tree->sreg1 = mono_regstate_next_int (s->rs); @@ -126,26 +106,17 @@ reg: OP_LOCALLOC (reg) { stmt: OP_SETRET (reg) { tree->opcode = OP_MOVE; tree->sreg1 = state->left->reg1; - tree->dreg = s390_r2; - mono_bblock_add_inst (s->cbb, tree); -} - -stmt: OP_SETRET (lreg) { - tree->opcode = OP_MOVE; - tree->sreg1 = state->left->reg1; - tree->dreg = s390_r2; + tree->dreg = state->left->reg2; mono_bblock_add_inst (s->cbb, tree); } stmt: OP_SETRET (freg) { - if (s->method->signature->ret->type == MONO_TYPE_R4) { + if (mono_method_signature (s->method)->ret->type == MONO_TYPE_R4) { tree->opcode = OP_S390_SETF4RET; tree->sreg1 = state->left->reg1; - tree->dreg = s390_f0; } else { tree->opcode = OP_FMOVE; tree->sreg1 = state->left->reg1; - tree->dreg = s390_f0; } mono_bblock_add_inst (s->cbb, tree); } @@ -157,287 +128,289 @@ stmt: OP_SETRET (OP_ICONST) { mono_bblock_add_inst (s->cbb, tree); } -lreg: OP_LSUB_OVF_UN (lreg, lreg) "0" { - /*----------------------------------------------------------------------*/ - /* SBB sets the condition code - CC 0 or 1 indicates Borrow == Overflow */ - /*----------------------------------------------------------------------*/ - MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1); - MONO_EMIT_NEW_BIALU (s, OP_SBB, state->reg2, state->left->reg2, state->right->reg2); - MONO_EMIT_NEW_COND_EXC (s, NC, "OverflowException"); -} - stmt: OP_OUTARG (reg) { - if (tree->inst_imm) { - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, tree->inst_imm, state->left->reg1); - return; - } + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + tree->opcode = OP_SETREG; - tree->dreg = tree->unused; - tree->sreg1 = state->left->reg1; + 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, tree->unused, FALSE); } -stmt: OP_OUTARG (OP_REGVAR) { - if (tree->inst_imm) { - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, tree->inst_imm, state->left->tree->dreg); - return; - } - tree->opcode = OP_SETREG; - tree->dreg = tree->unused; - tree->sreg1 = state->left->tree->dreg; - mono_bblock_add_inst (s->cbb, tree); +stmt: OP_OUTARG_MEMBASE (reg) { + MonoCallArgParm *arg = (MonoCallArgParm *) tree; + + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, + arg->offset, state->left->reg1); } -stmt: OP_OUTARG (lreg) { - if (tree->inst_imm) { - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, tree->inst_imm, state->left->reg2); - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, tree->inst_imm + 4, state->left->reg1); - return; - } - MONO_EMIT_NEW_UNALU (s, OP_SETREG, tree->unused, state->left->reg2); - tree->opcode = OP_SETREG; - tree->dreg = tree->unused + 1; - tree->sreg1 = state->left->reg1; +stmt: OP_OUTARG (OP_REGVAR) { + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + + tree->opcode = OP_SETREG; + 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, tree->unused, FALSE); } -stmt: OP_OUTARG (OP_I8CONST) { - if (tree->inst_imm) { - MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STORE_MEMBASE_IMM, - STK_BASE, tree->inst_imm, - state->left->tree->inst_c0); - return; - } - tree->opcode = OP_SETREGIMM; - tree->dreg = tree->unused; - tree->inst_c0 = state->left->tree->inst_c0; - mono_bblock_add_inst (s->cbb, tree); +stmt: OP_OUTARG_MEMBASE (OP_REGVAR) { + MonoCallArgParm *arg = (MonoCallArgParm *) tree; + + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, + arg->offset, state->left->tree->dreg); } +stmt: OP_OUTARG (OP_I8CONST), stmt: OP_OUTARG (OP_ICONST) { - if (tree->inst_imm) { - MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STOREI4_MEMBASE_IMM, - STK_BASE, tree->inst_imm, - state->left->tree->inst_c0); - return; - } - tree->opcode = OP_SETREGIMM; - tree->dreg = tree->unused; - tree->inst_c0 = state->left->tree->inst_c0; + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + + 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, tree->unused, FALSE); +} + +stmt: OP_OUTARG_MEMBASE (OP_ICONST) { + MonoCallArgParm *arg = (MonoCallArgParm *) tree; + + MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STORE_MEMBASE_IMM, STK_BASE, + arg->offset, state->left->tree->inst_c0); } stmt: OP_OUTARG (CEE_LDIND_REF (OP_REGVAR)) { - if (tree->inst_imm) { - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, tree->inst_imm, state->left->left->tree->dreg); - return; - } - tree->opcode = OP_SETREG; - tree->sreg1 = state->left->left->tree->dreg; - tree->dreg = tree->unused; + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + + tree->opcode = OP_SETREG; + tree->sreg1 = state->left->left->tree->dreg; + 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, tree->unused, FALSE); } -stmt: OP_OUTARG (OP_LDADDR (OP_S390_LOADARG)) { - if (tree->inst_imm) { - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, tree->inst_imm, state->left->left->tree->dreg); - return; - } - MONO_EMIT_BIALU_IMM (s, tree, OP_ADD_IMM, tree->unused, - state->left->left->tree->sreg1, - state->left->left->tree->inst_offset); +stmt: OP_OUTARG_MEMBASE (CEE_LDIND_REF (OP_REGVAR)) { + MonoCallArgParm *arg = (MonoCallArgParm *) tree; + + MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STORE_MEMBASE_IMM, STK_BASE, + arg->offset, state->left->tree->inst_c0); } -stmt: OP_OUTARG (freg) { - if (tree->inst_imm) { - /*----------------------------------------------*/ - /* The length stored in unused tells us whether */ - /* we need to store a float or a double */ - /*----------------------------------------------*/ - if ((tree->unused & 0xff00) == 0x0400) { - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, - STK_BASE, tree->inst_imm, - state->left->reg1); - } else { - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, - STK_BASE, tree->inst_imm, - state->left->reg1); - } - return; - } - tree->opcode = OP_SETFREG; - tree->sreg1 = state->left->reg1; - tree->dreg = tree->unused; - mono_bblock_add_inst (s->cbb, tree); +stmt: OP_OUTARG_MEMBASE (OP_LDADDR (OP_S390_LOADARG)) { + MonoCallArgParm *arg = (MonoCallArgParm *) tree; + + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, + arg->offset, state->left->left->tree->dreg); +} + +freg: OP_FCONV_TO_R4 (freg) "0" { + MONO_EMIT_UNALU (s, tree, OP_FMOVE, state->reg1, state->left->reg1); } stmt: OP_OUTARG_R4 (freg) { - if (tree->inst_imm) { - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, STK_BASE, tree->inst_imm, state->left->reg1); - return; - } + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + + tree->opcode = OP_S390_SETF4RET; + 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->unused, TRUE); +} + +stmt: OP_OUTARG_R8 (freg), +stmt: OP_OUTARG (freg) { + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + tree->opcode = OP_SETFREG; - tree->sreg1 = state->left->reg1; - tree->dreg = tree->unused; + 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->unused, TRUE); } -stmt: OP_OUTARG_R8 (freg) { - if (tree->inst_imm) { - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, STK_BASE, tree->inst_imm, state->left->reg1); - return; +stmt: OP_OUTARG_MEMBASE (freg) { + MonoCallArgParm *arg = (MonoCallArgParm *) tree; + + /*----------------------------------------------*/ + /* The length stored in size tells us whether */ + /* we need to store a float or a double */ + /*----------------------------------------------*/ + if (arg->size == 4) { + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, + STK_BASE, arg->offset+4, + state->left->reg1); + } else { + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, + STK_BASE, arg->offset, + state->left->reg1); } +} + +stmt: OP_OUTARG_R4 (CEE_LDOBJ (OP_REGOFFSET)), +stmt: OP_OUTARG_R8 (CEE_LDOBJ (OP_REGOFFSET)) { + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + tree->opcode = OP_SETFREG; - tree->sreg1 = state->left->reg1; - tree->dreg = tree->unused; + 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->unused, TRUE); } stmt: OP_OUTARG_VT (CEE_LDOBJ (base)) { - MonoInst *vt = state->left->left->tree; + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + MonoCallArgParm *arg = (MonoCallArgParm *) tree; + MonoInst *vt = state->left->left->tree; + int start_reg = tree->sreg1; - int size = tree->unused; + int size = arg->size; int soffset = vt->inst_offset; - int tmpr; + int treg; -//printf("OP_OUTARG_VT(CEE_LDOBJ(base))\n"); if (size < 0) { size = -size; + treg = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_MOVE(s, STK_BASE, arg->offPrm, + vt->inst_basereg, soffset, size); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, arg->offPrm); if (start_reg != STK_BASE) { - MONO_EMIT_NEW_MOVE(s, STK_BASE, tree->sreg2, - vt->inst_basereg, soffset, size); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, start_reg, - STK_BASE, tree->sreg2); + mono_call_inst_add_outarg_reg (s, call, treg, start_reg, FALSE); } else { - MONO_EMIT_NEW_MOVE(s, STK_BASE, tree->sreg2+sizeof(gpointer), - vt->inst_basereg, soffset, size); - tmpr = mono_regstate_next_int (s->rs); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, STK_BASE, - tree->sreg2+sizeof(gpointer)); MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, - STK_BASE, tree->sreg2, tmpr); + STK_BASE, arg->offset, treg); } } else { if (start_reg != STK_BASE) { MONO_OUTPUT_VTR (s, size, start_reg, vt->inst_basereg, soffset); } else { - MONO_OUTPUT_VTS (s, size, STK_BASE, tree->inst_imm, + MONO_OUTPUT_VTS (s, size, STK_BASE, arg->offset, vt->inst_basereg, soffset); } } } stmt: OP_OUTARG_VT (CEE_LDOBJ (OP_S390_ARGPTR)) { - MonoInst *vt = state->left->left->tree; + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + MonoCallArgParm *arg = (MonoCallArgParm *) tree; + MonoInst *vt = state->left->left->tree; + int start_reg = tree->sreg1; - int size = tree->unused; + int size = arg->size; int soffset = vt->inst_offset; - int tmpr; //printf("OP_OUTARG_VT(CEE_LDOBJ(OP_S390_ARGPTR))\n"); - if (size < 0) { - size = -size; - if (start_reg != STK_BASE) { - MONO_EMIT_NEW_MOVE (s, STK_BASE, tree->inst_imm, - vt->inst_basereg, soffset, size); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, start_reg, - STK_BASE, tree->sreg2); - } else { - MONO_EMIT_NEW_MOVE (s, STK_BASE, - tree->inst_imm+sizeof(gpointer), - vt->inst_basereg, soffset, size); - tmpr = mono_regstate_next_int (s->rs); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, STK_BASE, - tree->inst_imm+sizeof(gpointer)); - MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, - STK_BASE, tree->inst_imm, - tmpr); - } + if (start_reg != STK_BASE) { + MONO_OUTPUT_VTR (s, size, start_reg, vt->inst_basereg, soffset); } else { - if (start_reg != STK_BASE) { - MONO_OUTPUT_VTR (s, size, start_reg, vt->inst_basereg, soffset); - } else { - MONO_OUTPUT_VTS (s, size, STK_BASE, - tree->inst_imm, - vt->inst_basereg, soffset); - } - } + MONO_OUTPUT_VTS (s, size, STK_BASE, arg->offset, + vt->inst_basereg, soffset); + } } stmt: OP_OUTARG_VT (CEE_LDOBJ (OP_REGOFFSET)) "0" { - MonoInst *vt = state->left->left->tree; + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + MonoCallArgParm *arg = (MonoCallArgParm *) tree; + MonoInst *vt = state->left->left->tree; + int start_reg = tree->sreg1; - int size = tree->unused; + int size = arg->size; int soffset = vt->inst_offset; - int tmpr; + int treg; //printf("OP_OUTARG_VT(CEE_LDOBJ(OP_REGOFFSET))\n"); if (size < 0) { size = -size; + treg = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_MOVE (s, STK_BASE, arg->offPrm, + vt->inst_basereg, soffset, size); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, arg->offPrm); if (start_reg != STK_BASE) { - MONO_EMIT_NEW_MOVE (s, STK_BASE, tree->sreg2, - vt->inst_basereg, soffset, size); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, start_reg, - STK_BASE, tree->sreg2); + mono_call_inst_add_outarg_reg (s, call, treg, start_reg, FALSE); } else { - MONO_EMIT_NEW_MOVE (s, STK_BASE, - tree->sreg2+sizeof(gpointer), - vt->inst_basereg, soffset, size); - tmpr = mono_regstate_next_int (s->rs); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, STK_BASE, - tree->sreg2+sizeof(gpointer)); MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, - STK_BASE, tree->sreg2, - tmpr); + STK_BASE, arg->offset, treg); } } else { if (start_reg != STK_BASE) { MONO_OUTPUT_VTR(s, size, start_reg, vt->inst_basereg, soffset); } else { - MONO_OUTPUT_VTS(s, size, STK_BASE, tree->inst_imm, + MONO_OUTPUT_VTS(s, size, STK_BASE, arg->offset, vt->inst_basereg, soffset); } } } stmt: OP_OUTARG_VT (CEE_LDOBJ (OP_S390_LOADARG)) { - MonoInst *vt = state->left->left->tree; - int start_reg = tree->sreg1; - int size = -tree->unused; + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + MonoCallArgParm *arg = (MonoCallArgParm *) tree; + MonoInst *vt = state->left->left->tree; + + int start_reg = tree->inst_basereg; + int size = -arg->size; int soffset = vt->inst_offset; - int tmpr; + int treg; //printf("OP_OUTARG_VT(CEE_LDOBJ(OP_S390_LOADARG))\n"); + treg = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_UNALU (s, OP_S390_BKCHAIN, treg, s->frame_reg); + MONO_EMIT_NEW_LOAD_MEMBASE (s, treg, treg, vt->unused); + MONO_EMIT_NEW_MOVE (s, STK_BASE, soffset, treg, 0, size); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, soffset); if (start_reg != STK_BASE) { - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, start_reg, STK_BASE, soffset); - MONO_EMIT_NEW_MOVE (s, STK_BASE, tree->sreg2, start_reg, 0, size); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, start_reg, - STK_BASE, tree->sreg2); + mono_call_inst_add_outarg_reg (s, call, treg, start_reg, FALSE); + } else { + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, + STK_BASE, arg->offset, treg); + } +} + +stmt: OP_OUTARG_VT (CEE_LDOBJ (OP_S390_ARGREG)) { + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + MonoCallArgParm *arg = (MonoCallArgParm *) tree; + MonoInst *vt = state->left->left->tree; + + int start_reg = tree->inst_basereg; + int size = -arg->size; + int soffset = vt->inst_offset; + int treg; + +//printf("OP_OUTARG_VT(CEE_LDOBJ(OP_S390_ARGREG))\n"); + treg = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_LOAD_MEMBASE (s, treg, s->frame_reg, soffset); + MONO_EMIT_NEW_MOVE (s, STK_BASE, arg->offPrm, treg, 0, size); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, arg->offPrm); + if (start_reg != STK_BASE) { + mono_call_inst_add_outarg_reg (s, call, treg, start_reg, FALSE); } else { - MONO_EMIT_NEW_MOVE (s, STK_BASE, - tree->inst_imm+sizeof(gpointer), - vt->inst_basereg, soffset, size); - tmpr = mono_regstate_next_int (s->rs); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, STK_BASE, - tree->inst_imm+sizeof(gpointer)); MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, - STK_BASE, tree->inst_imm, - tmpr); + STK_BASE, arg->offset, treg); } } stmt: OP_OUTARG_VT (OP_ICONST) { + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + MonoCallArgParm *arg = (MonoCallArgParm *) tree; + int start_reg = tree->sreg1; - int size = tree->unused; + int size = arg->size; int nregs = size / 4; -//printf("OP_OUTARG_VT(OP_ICONST)\n"); +//printf("OP_OUTARG_VT(OP_ICONST) %d\n",nregs); if (start_reg != STK_BASE) { if (nregs) { tree->opcode = OP_SETREGIMM; - tree->dreg = start_reg; + 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, start_reg, FALSE); } } else { MONO_OUTPUT_VTS (s, size, STK_BASE, tree->inst_c0, @@ -446,46 +419,53 @@ stmt: OP_OUTARG_VT (OP_ICONST) { } stmt: OP_OUTARG_VT (reg) { - int start_reg = tree->sreg1; - int size = tree->unused; - int soffset = tree->sreg2; - int tmpr; + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + MonoCallArgParm *arg = (MonoCallArgParm *) tree; + MonoInst *vt = state->left->left->tree; + int start_reg = tree->sreg1; + int size = arg->size; + int soffset = vt->inst_offset; + int treg; -//printf("OP_OUTARG_VT(reg)\n"); if (size < 0) { size = -size; + treg = mono_regstate_next_int (s->rs); if (start_reg != STK_BASE) { - MONO_EMIT_NEW_MOVE (s, STK_BASE, soffset, - state->left->tree->sreg1, - tree->inst_imm, size); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, start_reg, - STK_BASE, soffset); +//printf("OP_OUTARG_VT(reg) 1\n"); + MONO_EMIT_NEW_MOVE (s, STK_BASE, arg->offPrm, state->left->reg1, + 0, size); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, + STK_BASE, arg->offPrm); + mono_call_inst_add_outarg_reg (s, call, treg, start_reg, FALSE); } else { - MONO_EMIT_NEW_MOVE (s, STK_BASE, - soffset+sizeof(gpointer), - state->left->tree->sreg1, - tree->inst_imm, size); - tmpr = mono_regstate_next_int (s->rs); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, STK_BASE, - soffset+sizeof(gpointer)); +//printf("OP_OUTARG_VT(reg) 1\n"); + MONO_EMIT_NEW_MOVE (s, STK_BASE, soffset+size, state->left->reg1, + 0, size); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, + soffset+size); MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, - STK_BASE, tree->inst_imm, - tmpr); + STK_BASE, arg->offset, treg); } } else { if (start_reg != STK_BASE) { - MONO_OUTPUT_VTR (s, size, start_reg, STK_BASE, - state->left->tree->inst_offset); + MONO_OUTPUT_VTR (s, size, start_reg, STK_BASE, soffset); } else { - MONO_OUTPUT_VTS (s, size, STK_BASE, soffset, tmpr, +//printf("OP_OUTARG_VT(reg) 2\n"); + treg = mono_regstate_next_int (s->rs); + MONO_OUTPUT_VTS (s, size, STK_BASE, soffset, treg, state->left->tree->inst_offset); - tmpr = mono_regstate_next_int (s->rs); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, STK_BASE, - s->stack_offset); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, + s->stack_offset); } } } +stmt: OP_OUTARG_VT (OP_REFANYTYPE (reg)) "0" { +//printf("OP_OUTARG_VT (OP_REFANYTYPE (base))\n"); + MONO_EMIT_NEW_LOAD_MEMBASE (s, state->tree->sreg1, state->left->left->reg1, + G_STRUCT_OFFSET (MonoTypedRef, type)); +} + stmt: CEE_STIND_R8 (OP_REGVAR, freg) { /* nothing to do: the value is already on the FP stack */ } @@ -589,49 +569,113 @@ base: OP_S390_STKARG "0" { int tmpr; tmpr = mono_regstate_next_int (s->rs); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, s->frame_reg, - (s->stack_offset+state->tree->unused)); + MONO_EMIT_NEW_UNALU (s, OP_S390_BKCHAIN, tmpr, s->frame_reg); tree->inst_offset = state->tree->inst_offset; tree->inst_basereg = tmpr; } -base: OP_LDADDR (OP_S390_LOADARG) "0" { +reg: CEE_LDIND_I4 (CEE_REFANYVAL (base)) "0" { + MonoInst *base = state->left->left->left->tree; int tmpr; tmpr = mono_regstate_next_int (s->rs); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, s->frame_reg, - state->left->tree->inst_offset); - tree->inst_offset = 0; - tree->inst_basereg = tmpr; + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, base->sreg1, base->inst_offset); + MONO_EMIT_NEW_LOAD_MEMBASE (s, tmpr, tmpr, G_STRUCT_OFFSET (MonoTypedRef, value)); + MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI4_MEMBASE, state->reg1, tmpr, 4); } -base: OP_LDADDR (OP_S390_ARGPTR) "0" { +reg: CEE_LDIND_I2 (CEE_REFANYVAL (base)) "0" { + MonoInst *base = state->left->left->left->tree; int tmpr; tmpr = mono_regstate_next_int (s->rs); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, s->frame_reg, + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, base->sreg1, base->inst_offset); + MONO_EMIT_NEW_LOAD_MEMBASE (s, tmpr, tmpr, G_STRUCT_OFFSET (MonoTypedRef, value)); + MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI2_MEMBASE, state->reg1, tmpr, 6); +} + +reg: CEE_LDIND_I1 (CEE_REFANYVAL (base)) "0" { + MonoInst *base = state->left->left->left->tree; + int tmpr; + + tmpr = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, base->sreg1, base->inst_offset); + MONO_EMIT_NEW_LOAD_MEMBASE (s, tmpr, tmpr, G_STRUCT_OFFSET (MonoTypedRef, value)); + MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI1_MEMBASE, state->reg1, tmpr, 7); +} + +reg: CEE_LDIND_U4 (CEE_REFANYVAL (base)) "0" { + MonoInst *base = state->left->left->left->tree; + int tmpr; + + tmpr = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, base->sreg1, base->inst_offset); + MONO_EMIT_NEW_LOAD_MEMBASE (s, tmpr, tmpr, G_STRUCT_OFFSET (MonoTypedRef, value)); + MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADU4_MEMBASE, state->reg1, tmpr, 4); +} + +reg: CEE_LDIND_U2 (CEE_REFANYVAL (base)) "0" { + MonoInst *base = state->left->left->left->tree; + int tmpr; + + tmpr = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, base->sreg1, base->inst_offset); + MONO_EMIT_NEW_LOAD_MEMBASE (s, tmpr, tmpr, G_STRUCT_OFFSET (MonoTypedRef, value)); + MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADU2_MEMBASE, state->reg1, tmpr, 6); +} + +reg: CEE_LDIND_U1 (CEE_REFANYVAL (base)) "0" { + MonoInst *base = state->left->left->left->tree; + int tmpr; + + tmpr = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, base->sreg1, base->inst_offset); + MONO_EMIT_NEW_LOAD_MEMBASE (s, tmpr, tmpr, G_STRUCT_OFFSET (MonoTypedRef, value)); + MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADU1_MEMBASE, state->reg1, tmpr, 7); +} + +reg: OP_LDADDR (OP_S390_ARGREG), +reg: CEE_LDOBJ (OP_S390_ARGREG) "0" { + MONO_EMIT_LOAD_MEMBASE (s, tree, state->reg1, s->frame_reg, state->left->tree->inst_offset); +} + +base: OP_LDADDR (OP_S390_LOADARG) "0" { + int treg; + + treg = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_UNALU (s, OP_S390_BKCHAIN, treg, s->frame_reg); + MONO_EMIT_NEW_LOAD_MEMBASE (s, treg, treg, state->left->tree->unused); + tree->inst_offset = 0; + tree->inst_basereg = treg; +} + +base: OP_LDADDR (OP_S390_ARGPTR) "0" { + int treg; + + treg = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, s->frame_reg, state->left->tree->inst_offset); tree->inst_offset = 0; - tree->inst_basereg = tmpr; + tree->inst_basereg = treg; } base: OP_LDADDR (OP_S390_STKARG) "0" { int tmpr; tmpr = mono_regstate_next_int (s->rs); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, s->frame_reg, - (s->stack_offset + state->left->tree->unused)); + MONO_EMIT_NEW_UNALU (s, OP_S390_BKCHAIN, tmpr, s->frame_reg); MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, tmpr, - state->left->tree->inst_offset); + state->left->tree->inst_offset); tree->inst_offset = 0; tree->inst_basereg = tmpr; } -reg: OP_LDADDR (OP_S390_LOADARG) "2" { - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, s->frame_reg, - state->left->tree->inst_offset); - tree->inst_offset = 0; - tree->inst_basereg = state->reg1; +reg: OP_LDADDR (OP_S390_LOADARG) { + int treg; + + treg = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_UNALU (s, OP_S390_BKCHAIN, treg, s->frame_reg); + MONO_EMIT_LOAD_MEMBASE (s, tree, state->reg1, treg, state->left->tree->inst_offset); } reg: OP_LDADDR (OP_S390_ARGPTR) "2" { @@ -642,10 +686,10 @@ reg: OP_LDADDR (OP_S390_ARGPTR) "2" { } reg: OP_LDADDR (OP_S390_STKARG) "2" { - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, s->frame_reg, - (s->stack_offset + state->left->tree->unused)); + MONO_EMIT_NEW_UNALU (s, OP_S390_BKCHAIN, state->reg1, s->frame_reg); MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, state->reg1, - state->left->tree->inst_offset); + (state->left->tree->unused + + state->left->tree->inst_offset)); tree->inst_offset = 0; tree->inst_basereg = state->reg1; } @@ -655,39 +699,127 @@ reg: CEE_LDOBJ (OP_S390_LOADARG) "1" { state->left->tree->inst_offset); } -reg: CEE_LDOBJ (OP_S390_ARGPTR) "1" { +reg: CEE_LDOBJ (OP_S390_ARGPTR) "0" { MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, s->frame_reg, state->left->tree->inst_offset); } reg: CEE_LDOBJ (OP_S390_STKARG) "1" { - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, s->frame_reg, - (s->stack_offset + state->left->tree->unused)); + MONO_EMIT_NEW_UNALU (s, OP_S390_BKCHAIN, state->reg1, s->frame_reg); MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, state->reg1, - state->left->tree->inst_offset); + (state->left->tree->unused + + state->left->tree->inst_offset)); tree->inst_offset = 0; tree->dreg = state->reg1; } base: CEE_LDOBJ (OP_S390_ARGPTR) "0" { - int tmpr; + int treg; - tmpr = mono_regstate_next_int (s->rs); - MONO_EMIT_NEW_LOAD_MEMBASE (s, tmpr, s->frame_reg, + treg = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, s->frame_reg, state->left->tree->inst_offset); tree->inst_offset = 0; - tree->dreg = tmpr; + tree->inst_basereg = treg; } base: CEE_LDOBJ (OP_S390_STKARG) "0" { int tmpr; tmpr = mono_regstate_next_int (s->rs); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, s->frame_reg, - (s->stack_offset + state->left->tree->unused)); + MONO_EMIT_NEW_UNALU (s, OP_S390_BKCHAIN, tmpr, s->frame_reg); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, tmpr, state->left->tree->unused); MONO_EMIT_NEW_LOAD_MEMBASE (s, tmpr, tmpr, state->left->tree->inst_offset); tree->inst_offset = 0; tree->inst_basereg = tmpr; } + +reg: OP_ATOMIC_ADD_NEW_I8 (base, reg), +reg: OP_ATOMIC_ADD_NEW_I4 (base, reg), +reg: OP_ATOMIC_ADD_I8 (base, reg), +reg: OP_ATOMIC_ADD_I4 (base, reg) { + tree->inst_basereg = state->left->tree->inst_basereg; + tree->inst_offset = state->left->tree->inst_offset; + tree->dreg = state->reg1; + tree->sreg2 = state->right->reg1; + + mono_bblock_add_inst (s->cbb, tree); +} + +reg: OP_ATOMIC_EXCHANGE_I8 (base, reg), +reg: OP_ATOMIC_EXCHANGE_I4 (base, reg) { + 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); +} + +reg: OP_LSHL (reg, reg), +reg: OP_LSHR (reg, reg), +reg: OP_LSHR_UN (reg, reg), +reg: OP_LMUL (reg, reg), +reg: OP_LDIV (reg, reg), +reg: OP_LDIV_UN (reg, reg), +reg: OP_LREM (reg, reg), +reg: OP_LREM_UN (reg, reg), +reg: OP_LMUL_OVF (reg, reg), +reg: OP_LMUL_OVF_UN (reg, reg) "0" { + MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1); +} + +reg: OP_LMUL (reg, OP_I8CONST) { + MONO_EMIT_BIALU_IMM (s, tree, OP_LMUL_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0); +} cost { + MBCOND (mono_arch_is_inst_imm (state->right->tree->inst_c0)); + return 0; +} + +reg: OP_LSHL (reg, OP_ICONST) { + MONO_EMIT_BIALU_IMM (s, tree, OP_LSHL_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0); +} cost { + MBCOND (mono_arch_is_inst_imm (state->right->tree->inst_c0)); + return 0; +} + +reg: OP_LSHR (reg, OP_ICONST) { + MONO_EMIT_BIALU_IMM (s, tree, OP_LSHR_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0); +} cost { + MBCOND (mono_arch_is_inst_imm (state->right->tree->inst_c0)); + return 0; +} + +reg: OP_LSHR_UN (reg, OP_ICONST) { + MONO_EMIT_BIALU_IMM (s, tree, OP_LSHR_UN_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0); +} cost { + MBCOND (mono_arch_is_inst_imm (state->right->tree->inst_c0)); + return 0; +} + +reg: OP_LCONV_TO_I4 (reg) "0" { + /* Sign extend the value in the lower word into the upper word */ + MONO_EMIT_BIALU_IMM (s, tree, CEE_CONV_I4, state->reg1, state->left->reg1, 0); +} + +reg: OP_LCONV_TO_U4 (reg) "0" { + /* Clean out the upper word */ + MONO_EMIT_BIALU_IMM (s, tree, CEE_CONV_U4, state->reg1, state->left->reg1, 0); +} + +freg: OP_LCONV_TO_R8 (reg) { + /* FIXME: Move this inssel-long.brg */ + tree->sreg1 = state->left->reg1; + tree->dreg = state->reg1; + mono_bblock_add_inst (s->cbb, tree); +} + +freg: OP_LCONV_TO_R4 (reg) { + /* FIXME: Move this inssel-long.brg */ + tree->sreg1 = state->left->reg1; + tree->dreg = state->reg1; + mono_bblock_add_inst (s->cbb, tree); +} + %%