From d5e13192f99b1127b382172b7988e6199740a65f Mon Sep 17 00:00:00 2001 From: Neale Ferguson Date: Fri, 2 Dec 2005 19:07:56 +0000 Subject: [PATCH] Bring s390 JIT up to current level svn path=/trunk/mono/; revision=53840 --- mono/mini/Makefile.am | 5 +- mono/mini/cpu-s390.md | 74 +-- mono/mini/inssel-s390.brg | 600 ++++++++++++------- mono/mini/inssel-s390x.brg | 408 +++++++------ mono/mini/mini-codegen.c | 3 + mono/mini/mini-ops.h | 1 + mono/mini/mini-s390.c | 1424 +++++++++++--------------------------------- mono/mini/mini-s390.h | 92 ++- mono/mini/mini-s390x.c | 2 +- 9 files changed, 1081 insertions(+), 1528 deletions(-) diff --git a/mono/mini/Makefile.am b/mono/mini/Makefile.am index 31a08abd69e..7c019c53c78 100644 --- a/mono/mini/Makefile.am +++ b/mono/mini/Makefile.am @@ -150,6 +150,7 @@ s390_sources = \ mini-s390.c \ mini-s390.h \ exceptions-s390.c \ + mini-codegen.c \ tramp-s390.c s390x_sources = \ @@ -350,10 +351,10 @@ cpu-sparc.h: cpu-sparc.md genmdesc$(EXEEXT) ./genmdesc $(srcdir)/cpu-sparc.md cpu-sparc.h sparc_desc cpu-s390.h: cpu-s390.md genmdesc$(EXEEXT) - ./genmdesc $(srcdir)/cpu-s390.md cpu-s390.h s390 + ./genmdesc $(srcdir)/cpu-s390.md cpu-s390.h s390_cpu_desc cpu-s390x.h: cpu-s390x.md genmdesc$(EXEEXT) - ./genmdesc $(srcdir)/cpu-s390x.md cpu-s390x.h s390x + ./genmdesc $(srcdir)/cpu-s390x.md cpu-s390x.h s390x_cpu_desc cpu-ia64.h: cpu-ia64.md genmdesc$(EXEEXT) ./genmdesc $(srcdir)/cpu-ia64.md cpu-ia64.h ia64_desc diff --git a/mono/mini/cpu-s390.md b/mono/mini/cpu-s390.md index 1655acb1e7b..ebf2c94e480 100644 --- a/mono/mini/cpu-s390.md +++ b/mono/mini/cpu-s390.md @@ -48,9 +48,9 @@ adc: dest:i src1:i src2:i len:6 adc_imm: dest:i src1:i len:18 -add.ovf.un: len: 8 dest:i src1:i src2:i +add.ovf.un: len: 10 dest:i src1:i src2:i add.ovf: len: 24 dest:i src1:i src2:i -add: dest:i src1:i src2:i len:4 clob:1 +add: dest:i src1:i src2:i len:6 clob:1 add_imm: dest:i src1:i len:18 addcc_imm: dest:i src1:i len:18 add_ovf_carry: dest:i src1:1 src2:i len:28 @@ -93,10 +93,10 @@ brfalse.s: brfalse: brtrue.s: brtrue: -call: dest:a clob:c len:6 +call: dest:o len:6 clob:c call_handler: len:12 -call_membase: dest:a src1:b len:12 clob:c -call_reg: dest:a src1:i len:8 clob:c +call_membase: dest:o src1:b len:12 clob:c +call_reg: dest:o src1:i len:8 clob:c calli: callvirt: castclass: @@ -123,8 +123,8 @@ cond_exc_nc: len:8 cond_exc_ne_un: len:8 cond_exc_no: len:8 cond_exc_ov: len:8 -conv.i1: dest:i src1:i len:24 -conv.i2: dest:i src1:i len:24 +conv.i1: dest:i src1:i len:26 +conv.i2: dest:i src1:i len:26 conv.i4: dest:i src1:i len:2 conv.i8: conv.i: dest:i src1:i len:2 @@ -158,17 +158,17 @@ conv.u8: conv.u: dest:i src1:i len:4 cpblk: cpobj: -div.un: dest:a src1:i src2:i len:12 clob:d -div: dest:a src1:i src2:i len:10 clob:d +div.un: dest:a src1:i src2:i len:12 +div: dest:a src1:i src2:i len:10 div_imm: dest:i src1:i src2:i len:24 div_un_imm: dest:i src1:i src2:i len:24 dup: endfilter: len:20 endfinally: len: 20 endmac: -fcall: dest:f len:10 clob:c -fcall_membase: dest:f src1:b len:14 clob:c -fcall_reg: dest:f src1:i len:10 clob:c +fcall: dest:g len:10 clob:c +fcall_membase: dest:g src1:b len:14 clob:c +fcall_reg: dest:g src1:i len:10 clob:c fcompare: src1:f src2:f len:14 float_add: dest:f src1:f src2:f len:6 float_add_ovf: @@ -241,9 +241,9 @@ initobj: isinst: jmp: len:40 label: -lcall: dest:l len:8 clob:c -lcall_membase: dest:l src1:b len:12 clob:c -lcall_reg: dest:l src1:i len:8 clob:c +lcall: dest:L len:8 clob:c +lcall_membase: dest:L src1:b len:12 clob:c +lcall_reg: dest:L src1:i len:8 clob:c lcompare: ldaddr: ldarg.0: @@ -329,8 +329,8 @@ local: localloc: dest:i src1:i len:62 long_add: long_add_imm: -long_add_ovf: -long_add_ovf_un: +long_add_ovf_un: len:18 dest:l src1:l src2:i +long_add_ovf: len:24 dest:l src1:l src2:i long_and: long_beq: long_bge: @@ -398,8 +398,8 @@ long_shr_un: long_shr_un_imm: long_sub: long_sub_imm: -long_sub_ovf: -long_sub_ovf_un: +long_sub_ovf_un: len:18 dest:l src1:l src2:i +long_sub_ovf: len:36 dest:l src1:l src2:i long_xor: mkrefany: mono_ldptr: @@ -408,21 +408,21 @@ mono_objaddr: mono_retobj: mono_vtaddr: move: dest:i src1:i len:4 -mul.ovf.un: dest:i src1:i src2:i len:20 clob:1 -mul.ovf: dest:i src1:i src2:i len:42 clob:1 -mul: dest:i src1:i src2:i len:4 clob:1 +mul.ovf.un: dest:i src1:i src2:i len:20 +mul.ovf: dest:i src1:i src2:i len:42 +mul: dest:i src1:i src2:i len:6 mul_imm: dest:i src1:i len:18 -neg: dest:i src1:i len:4 clob:1 +neg: dest:i src1:i len:4 newarr: newobj: nop: len:4 -not: dest:i src1:i len:8 clob:1 +not: dest:i src1:i len:8 op_bigmul: len:2 dest:l src1:a src2:i op_bigmul_un: len:2 dest:l src1:a src2:i op_endfilter: src1:i len:12 op_rethrow: src1:i len:8 oparglist: src1:i len:20 -or: dest:i src1:i src2:i len:4 clob:1 +or: dest:i src1:i src2:i len:4 or_imm: dest:i src1:i len:16 outarg: src1:i len:1 outarg_imm: len:5 @@ -443,27 +443,27 @@ refanyval: reg: regoffset: regvar: -rem.un: dest:d src1:i src2:i len:12 clob:d -rem: dest:d src1:i src2:i len:10 clob:d +rem.un: dest:d src1:i src2:i len:12 +rem: dest:d src1:i src2:i len:10 rem_imm: dest:i src1:i src2:i len:24 rem_un_imm: dest:i src1:i src2:i len:24 rename: ret: retarg: s390_move: len:48 dest:b src1:b -s390_setf4ret: dest:f src1:f len:4 clob:r +s390_setf4ret: dest:f src1:f len:4 tls_get: dest:i len:44 sbb: dest:i src1:i src2:i len:8 -sbb_imm: dest:i src1:i len:16 -setfreg: dest:f src1:f len:4 clob:r +sbb_imm: dest:i src1:i len:18 +setfreg: dest:f src1:f len:4 setlret: src1:i src2:i len:12 -setreg: dest:i src1:i len:4 clob:r -setregimm: dest:i len:18 clob:r +setreg: dest:i src1:i len:4 +setregimm: dest:i len:18 setret: dest:a src1:i len:6 -shl: dest:i src1:i src2:i clob:s len:6 +shl: dest:i src1:i src2:i clob:s len:8 shl_imm: dest:i src1:i len:8 -shr.un: dest:i src1:i src2:i clob:s len:6 -shr: dest:i src1:i src2:i clob:s len:6 +shr.un: dest:i src1:i src2:i clob:s len:8 +shr: dest:i src1:i src2:i clob:s len:8 shr_imm: dest:i src1:i len:8 shr_un_imm: dest:i src1:i len:8 sizeof: @@ -511,7 +511,7 @@ storer8_membase_reg: dest:b src1:f len:22 stsfld: sub.ovf.un: len:10 dest:i src1:i src2:i sub.ovf: len:24 dest:i src1:i src2:i -sub: dest:i src1:i src2:i len:4 clob:1 +sub: dest:i src1:i src2:i len:6 sub_imm: dest:i src1:i len:18 subcc_imm: dest:i src1:i len:18 sub_ovf_carry: dest:i src1:1 src2:i len:28 @@ -530,5 +530,5 @@ voidcall: len:8 clob:c voidcall_membase: src1:b len:12 clob:c voidcall_reg: src1:i len:8 clob:c volatile.: -xor: dest:i src1:i src2:i len:4 clob:1 +xor: dest:i src1:i src2:i len:4 xor_imm: dest:i src1:i len:16 diff --git a/mono/mini/inssel-s390.brg b/mono/mini/inssel-s390.brg index c8c79b74412..a62bcfa6f04 100644 --- a/mono/mini/inssel-s390.brg +++ b/mono/mini/inssel-s390.brg @@ -31,27 +31,25 @@ stmt: OP_ENDFILTER (reg) { } 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); + MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1); } 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); + MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1); } +#reg: 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 (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); + MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1); } 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); + MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1); } reg: CEE_ADD_OVF (reg, reg) "0" { @@ -168,140 +166,290 @@ 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"); -} - +#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 (call, tree->dreg, tree->unused, FALSE); +} + +stmt: OP_OUTARG_MEMBASE (reg) { + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, + argParm->offset, state->left->reg1); + + g_free(argParm); } 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; + 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 (call, tree->dreg, tree->unused, FALSE); } +stmt: OP_OUTARG_MEMBASE (OP_REGVAR) { + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, + argParm->offset, state->left->tree->dreg); + + g_free(argParm); +} + +#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; +# } +# tree->opcode = OP_SETREG; +# tree->dreg = tree->unused; +# tree->sreg1 = state->left->reg1; +# mono_bblock_add_inst (s->cbb, tree); +#} + +#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 (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; - } + MonoCallInst *call = (MonoCallInst*)tree->inst_right; + int tdreg; + tdreg = mono_regstate_next_int (s->rs); MONO_EMIT_NEW_UNALU (s, OP_SETREG, tree->unused, state->left->reg2); + + mono_call_inst_add_outarg_reg (call, tdreg, tree->unused, FALSE); + tree->opcode = OP_SETREG; - tree->dreg = tree->unused + 1; + 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 (call, tree->dreg, tree->unused + 1, FALSE); +# tree->dreg = tree->unused + 1; } +stmt: OP_OUTARG_MEMBASE (lreg) { + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, + argParm->offset, state->left->reg2); + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, + argParm->offset + 4, state->left->reg1); + g_free(argParm); +} + +#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; +# mono_bblock_add_inst (s->cbb, tree); +#} + stmt: OP_OUTARG (OP_ICONST) { - 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; + 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 (call, tree->dreg, tree->unused, FALSE); +} + +stmt: OP_OUTARG_MEMBASE (OP_ICONST) { + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + + MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STORE_MEMBASE_IMM, STK_BASE, + argParm->offset, state->left->tree->inst_c0); + + g_free (argParm); } 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 (call, tree->dreg, tree->unused, FALSE); } +stmt: OP_OUTARG_MEMBASE (CEE_LDIND_REF (OP_REGVAR)) { + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + + MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STORE_MEMBASE_IMM, STK_BASE, + argParm->offset, state->left->tree->inst_c0); + + g_free(argParm); +} + +#stmt: OP_OUTARG (OP_ICONST) { +# 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 (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; +# mono_bblock_add_inst (s->cbb, tree); +#} + 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 (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)) { + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, + argParm->offset, state->left->left->tree->dreg); + + g_free(argParm); } +#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_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; - } - tree->opcode = OP_SETFREG; - tree->sreg1 = state->left->reg1; - tree->dreg = tree->unused; + MonoCallInst *call = (MonoCallInst*)tree->inst_right; + + tree->opcode = OP_FCONV_TO_R4; + 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 (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_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 (call, tree->dreg, tree->unused, TRUE); } -stmt: OP_OUTARG_R8 (CEE_LDOBJ (OP_REGOFFSET)) { - 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) { + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + + /*----------------------------------------------*/ + /* The length stored in size tells us whether */ + /* we need to store a float or a double */ + /*----------------------------------------------*/ + if (argParm->size == 4) { + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, + STK_BASE, argParm->offset, + state->left->reg1); + } else { + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, + STK_BASE, argParm->offset, + state->left->reg1); } + g_free(argParm); +} + +#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; +# } +# tree->opcode = OP_SETFREG; +# tree->sreg1 = state->left->reg1; +# tree->dreg = tree->unused; +# mono_bblock_add_inst (s->cbb, tree); +#} +# +#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; +# } +# tree->opcode = OP_SETFREG; +# tree->sreg1 = state->left->reg1; +# tree->dreg = tree->unused; +# mono_bblock_add_inst (s->cbb, tree); +#} + +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 (call, tree->dreg, tree->unused, TRUE); } +#stmt: OP_OUTARG_R8 (CEE_LDOBJ (OP_REGOFFSET)) { +# if (tree->inst_imm) { +# 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); +#} + freg: OP_FCONV_TO_R4 (CEE_LDOBJ (OP_REGOFFSET)) { MonoInst *vt = state->left->left->tree; @@ -319,206 +467,225 @@ freg: OP_FCONV_TO_R8 (CEE_LDOBJ (OP_REGOFFSET)) { stmt: OP_OUTARG_VT (CEE_LDOBJ (base)) { - MonoInst *vt = state->left->left->tree; + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + MonoInst *vt = state->left->left->tree; + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + int start_reg = tree->sreg1; - int size = tree->unused; + int size = argParm->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); if (start_reg != STK_BASE) { - MONO_EMIT_NEW_MOVE(s, STK_BASE, tree->sreg2, + MONO_EMIT_NEW_MOVE(s, STK_BASE, argParm->offPrm, vt->inst_basereg, soffset, size); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, start_reg, - STK_BASE, tree->sreg2); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, + STK_BASE, argParm->offPrm); + mono_call_inst_add_outarg_reg (call, treg, start_reg, FALSE); } else { - MONO_EMIT_NEW_MOVE(s, STK_BASE, tree->sreg2+sizeof(gpointer), + MONO_EMIT_NEW_MOVE(s, STK_BASE, argParm->offPrm+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_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, + argParm->offPrm+sizeof(gpointer)); MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, - STK_BASE, tree->sreg2, tmpr); + STK_BASE, argParm->offPrm, 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, argParm->offset, vt->inst_basereg, soffset); } } + g_free(argParm); } stmt: OP_OUTARG_VT (CEE_LDOBJ (OP_S390_ARGPTR)) { - MonoInst *vt = state->left->left->tree; + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + MonoInst *vt = state->left->left->tree; + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + int start_reg = tree->sreg1; - int size = tree->unused; + int size = argParm->size; int soffset = vt->inst_offset; - int tmpr; + int treg; //printf("OP_OUTARG_VT(CEE_LDOBJ(OP_S390_ARGPTR))\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, tree->inst_imm, + MONO_EMIT_NEW_MOVE (s, STK_BASE, argParm->offset, vt->inst_basereg, soffset, size); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, start_reg, - STK_BASE, tree->sreg2); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, + STK_BASE, argParm->offPrm); + mono_call_inst_add_outarg_reg (call, treg, start_reg, FALSE); } else { MONO_EMIT_NEW_MOVE (s, STK_BASE, - tree->inst_imm+sizeof(gpointer), + argParm->offset+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_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, + argParm->offset+sizeof(gpointer)); MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, - STK_BASE, tree->inst_imm, - tmpr); + STK_BASE, argParm->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, argParm->offset, vt->inst_basereg, soffset); } } + g_free(argParm); } stmt: OP_OUTARG_VT (CEE_LDOBJ (OP_REGOFFSET)) "0" { - MonoInst *vt = state->left->left->tree; + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + MonoInst *vt = state->left->left->tree; + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + int start_reg = tree->sreg1; - int size = tree->unused; + int size = argParm->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); if (start_reg != STK_BASE) { - MONO_EMIT_NEW_MOVE (s, STK_BASE, tree->sreg2, +// MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, +// STK_BASE, soffset); + MONO_EMIT_NEW_MOVE (s, STK_BASE, argParm->offPrm, vt->inst_basereg, soffset, size); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, start_reg, - STK_BASE, tree->sreg2); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, + STK_BASE, argParm->offPrm); + mono_call_inst_add_outarg_reg (call, treg, start_reg, FALSE); } else { MONO_EMIT_NEW_MOVE (s, STK_BASE, - tree->sreg2+sizeof(gpointer), + argParm->offPrm+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_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, + argParm->offPrm+sizeof(gpointer)); MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, - STK_BASE, tree->sreg2, - tmpr); + STK_BASE, argParm->offPrm, 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, argParm->offset, vt->inst_basereg, soffset); } } + g_free(argParm); } stmt: OP_OUTARG_VT (CEE_LDOBJ (OP_S390_LOADARG)) { - MonoInst *vt = state->left->left->tree; + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + MonoInst *vt = state->left->left->tree; + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + int start_reg = tree->sreg1; - int size = -tree->unused; + int size = -argParm->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); 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_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, soffset); + MONO_EMIT_NEW_MOVE (s, STK_BASE, argParm->offPrm, treg, 0, size); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, + STK_BASE, argParm->offPrm); + mono_call_inst_add_outarg_reg (call, treg, start_reg, FALSE); } else { MONO_EMIT_NEW_MOVE (s, STK_BASE, - tree->inst_imm+sizeof(gpointer), + argParm->offset+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_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, + argParm->offset+sizeof(gpointer)); MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, - STK_BASE, tree->inst_imm, - tmpr); + STK_BASE, argParm->offset, treg); } + g_free(argParm); } stmt: OP_OUTARG_VT (OP_ICONST) { + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; int start_reg = tree->sreg1; - int size = tree->unused; + int size = argParm->size; int nregs = size / 4; //printf("OP_OUTARG_VT(OP_ICONST)\n"); 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 (call, tree->dreg, start_reg, FALSE); } } else { MONO_OUTPUT_VTS (s, size, STK_BASE, tree->inst_c0, s->frame_reg, tree->inst_offset); } + g_free(argParm); } stmt: OP_OUTARG_VT (reg) { + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + MonoInst *vt = state->left->left->tree; int start_reg = tree->sreg1; - int size = tree->unused; - int soffset = tree->sreg2; - int tmpr; + int size = argParm->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); + MONO_EMIT_NEW_MOVE (s, STK_BASE, argParm->offPrm, state->left->reg1, + 0, size); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, + STK_BASE, argParm->offPrm); + mono_call_inst_add_outarg_reg (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)); + 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, argParm->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, + 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); + treg = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, + s->stack_offset); } } + g_free(argParm); } stmt: OP_OUTARG_VT (OP_REFANYTYPE (reg)) "0" { + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + //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)); -// MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREI4_MEMBASE_REG, STK_BASE, -// tree->sreg2, state->reg1); -// MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, state->reg1, STK_BASE, tree->sreg2); + g_free(argParm); } stmt: CEE_STIND_R8 (OP_REGVAR, freg) { @@ -621,48 +788,51 @@ reg: OP_CGT_UN (OP_COMPARE (freg, freg)) { } base: OP_S390_STKARG "0" { - int tmpr; + int treg; - 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_LOAD_MEMBASE (s, tmpr, s->frame_reg, 0); + treg = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_LOAD_MEMBASE (s, treg, STK_BASE, 0); +// MONO_EMIT_NEW_LOAD_MEMBASE (s, treg, s->frame_reg, 0); tree->inst_offset = state->tree->inst_offset; - tree->inst_basereg = tmpr; + tree->inst_basereg = treg; +} + +reg: OP_LDADDR (OP_S390_ARGREG), +reg: CEE_LDOBJ (OP_S390_ARGREG) "0" { + int treg; + + MONO_EMIT_LOAD_MEMBASE (s, tree, state->reg1, s->frame_reg, state->left->tree->inst_offset); } base: OP_LDADDR (OP_S390_LOADARG) "0" { - int tmpr; + int treg; - tmpr = mono_regstate_next_int (s->rs); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, 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->inst_basereg = tmpr; + tree->inst_basereg = treg; } base: OP_LDADDR (OP_S390_ARGPTR) "0" { - int tmpr; + int treg; - tmpr = mono_regstate_next_int (s->rs); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, 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->inst_basereg = tmpr; + tree->inst_basereg = treg; } base: OP_LDADDR (OP_S390_STKARG) "0" { - int tmpr; - -printf("OP_LDADDR (OP_S390_STKARG)\n"); - 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_LOAD_MEMBASE (s, tmpr, s->frame_reg, 0); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, tmpr, + int treg; + + treg = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_LOAD_MEMBASE (s, treg, STK_BASE, 0); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, treg, state->left->tree->inst_offset); tree->inst_offset = 0; - tree->inst_basereg = tmpr; + tree->inst_basereg = treg; } reg: OP_LDADDR (OP_S390_LOADARG) "2" { @@ -708,24 +878,24 @@ reg: CEE_LDOBJ (OP_S390_STKARG) "1" { } base: CEE_LDOBJ (OP_S390_ARGPTR) "0" { - int tmpr; + int treg; - tmpr = mono_regstate_next_int (s->rs); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, 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->inst_basereg = tmpr; + tree->inst_basereg = treg; } base: CEE_LDOBJ (OP_S390_STKARG) "0" { - int tmpr; + int treg; - tmpr = mono_regstate_next_int (s->rs); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, tmpr, s->frame_reg, + treg = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, s->frame_reg, (s->stack_offset + state->left->tree->unused)); - MONO_EMIT_NEW_LOAD_MEMBASE (s, tmpr, tmpr, state->left->tree->inst_offset); + MONO_EMIT_NEW_LOAD_MEMBASE (s, treg, treg, state->left->tree->inst_offset); tree->inst_offset = 0; - tree->inst_basereg = tmpr; + tree->inst_basereg = treg; } reg: OP_ATOMIC_ADD_NEW_I4 (base, reg), diff --git a/mono/mini/inssel-s390x.brg b/mono/mini/inssel-s390x.brg index 18222c1bea2..5d89eb9159e 100644 --- a/mono/mini/inssel-s390x.brg +++ b/mono/mini/inssel-s390x.brg @@ -134,25 +134,42 @@ stmt: OP_SETRET (OP_ICONST) { } 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 (call, tree->dreg, tree->unused, FALSE); +} + +stmt: OP_OUTARG_MEMBASE (reg) { + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, + argParm->offset, state->left->reg1); + + g_free(argParm); } 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; + 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 (call, tree->dreg, tree->unused, FALSE); +} + +stmt: OP_OUTARG_MEMBASE (OP_REGVAR) { + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, + argParm->offset, state->left->tree->dreg); + + g_free(argParm); } stmt: OP_OUTARG (OP_I8CONST) { @@ -169,48 +186,117 @@ 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 (call, tree->dreg, tree->unused, FALSE); +} + +stmt: OP_OUTARG_MEMBASE (OP_ICONST) { + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + + MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STORE_MEMBASE_IMM, STK_BASE, + argParm->offset, state->left->tree->inst_c0); + + g_free (argParm); } 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 (call, tree->dreg, tree->unused, FALSE); } -stmt: OP_OUTARG (CEE_LDIND_I (OP_REGVAR)) { - tree->opcode = OP_SETREG; - tree->dreg = tree->unused; - tree->sreg1 = state->left->left->tree->dreg; +stmt: OP_OUTARG_MEMBASE (CEE_LDIND_REF (OP_REGVAR)) { + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + + MONO_EMIT_NEW_STORE_MEMBASE_IMM (s, OP_STORE_MEMBASE_IMM, STK_BASE, + argParm->offset, state->left->tree->inst_c0); + + g_free(argParm); +} + +stmt: OP_OUTARG_MEMBASE (OP_LDADDR (OP_S390_LOADARG)) { + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, STK_BASE, + argParm->offset, state->left->left->tree->dreg); + + g_free(argParm); +} + +stmt: OP_OUTARG_R4 (freg) { + MonoCallInst *call = (MonoCallInst*)tree->inst_right; + + tree->opcode = OP_FCONV_TO_R4; + 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 (call, tree->dreg, tree->unused, TRUE); } -stmt: OP_OUTARG (CEE_LDIND_I8 (OP_REGVAR)) { - tree->opcode = OP_SETREG; - tree->dreg = tree->unused; - tree->sreg1 = state->left->left->tree->dreg; +stmt: OP_OUTARG_R8 (freg), +stmt: OP_OUTARG (freg) { + MonoCallInst *call = (MonoCallInst*)tree->inst_right; + + tree->opcode = OP_SETFREG; + 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 (call, tree->dreg, tree->unused, TRUE); +} + +stmt: OP_OUTARG_MEMBASE (freg) { + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + + /*----------------------------------------------*/ + /* The length stored in size tells us whether */ + /* we need to store a float or a double */ + /*----------------------------------------------*/ + if (argParm->size == 4) { + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER4_MEMBASE_REG, + STK_BASE, argParm->offset, + state->left->reg1); + } else { + MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORER8_MEMBASE_REG, + STK_BASE, argParm->offset, + state->left->reg1); + } + g_free(argParm); +} + +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->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 (call, tree->dreg, tree->unused, TRUE); } -stmt: OP_OUTARG (CEE_LDIND_I4 (OP_REGVAR)) { +stmt: OP_OUTARG (CEE_LDIND_I (OP_REGVAR)), +stmt: OP_OUTARG (CEE_LDIND_I4 (OP_REGVAR)), +stmt: OP_OUTARG (CEE_LDIND_I8 (OP_REGVAR)) { + MonoCallInst *call = (MonoCallInst*)tree->inst_right; + tree->opcode = OP_SETREG; - tree->dreg = tree->unused; + tree->dreg = mono_regstate_next_float (s->rs); tree->sreg1 = state->left->left->tree->dreg; mono_bblock_add_inst (s->cbb, tree); + + mono_call_inst_add_outarg_reg (call, tree->dreg, tree->unused, TRUE); } stmt: OP_OUTARG (CEE_LDIND_I (base)) { @@ -227,256 +313,228 @@ stmt: OP_OUTARG (CEE_LDIND_I4 (base)) { mono_bblock_add_inst (s->cbb, tree); } -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 (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_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; - } - tree->opcode = OP_SETFREG; - tree->sreg1 = state->left->reg1; - tree->dreg = tree->unused; - mono_bblock_add_inst (s->cbb, tree); -} - -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; - } - tree->opcode = OP_SETFREG; - tree->sreg1 = state->left->reg1; - tree->dreg = tree->unused; - mono_bblock_add_inst (s->cbb, tree); -} - stmt: OP_OUTARG_VT (CEE_LDOBJ (base)) { - MonoInst *vt = state->left->left->tree; + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + MonoInst *vt = state->left->left->tree; + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + int start_reg = tree->sreg1; - int size = tree->unused; + int size = argParm->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); if (start_reg != STK_BASE) { - MONO_EMIT_NEW_MOVE(s, STK_BASE, tree->sreg2, + MONO_EMIT_NEW_MOVE(s, STK_BASE, argParm->offPrm, vt->inst_basereg, soffset, size); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, start_reg, - STK_BASE, tree->sreg2); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, + STK_BASE, argParm->offPrm); + mono_call_inst_add_outarg_reg (call, treg, start_reg, FALSE); } else { - MONO_EMIT_NEW_MOVE(s, STK_BASE, tree->sreg2+sizeof(gpointer), + MONO_EMIT_NEW_MOVE(s, STK_BASE, argParm->offPrm+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_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, + argParm->offPrm+sizeof(gpointer)); MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, - STK_BASE, tree->sreg2, tmpr); + STK_BASE, argParm->offPrm, 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, argParm->offset, vt->inst_basereg, soffset); } } + g_free(argParm); } stmt: OP_OUTARG_VT (CEE_LDOBJ (OP_S390_ARGPTR)) { - MonoInst *vt = state->left->left->tree; + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + MonoInst *vt = state->left->left->tree; + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + int start_reg = tree->sreg1; - int size = tree->unused; + int size = argParm->size; int soffset = vt->inst_offset; - int tmpr; + int treg; //printf("OP_OUTARG_VT(CEE_LDOBJ(OP_S390_ARGPTR))\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, tree->inst_imm, + MONO_EMIT_NEW_MOVE (s, STK_BASE, argParm->offset, vt->inst_basereg, soffset, size); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, start_reg, - STK_BASE, tree->sreg2); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, + STK_BASE, argParm->offPrm); + mono_call_inst_add_outarg_reg (call, treg, start_reg, FALSE); } else { MONO_EMIT_NEW_MOVE (s, STK_BASE, - tree->inst_imm+sizeof(gpointer), + argParm->offset+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_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, + argParm->offset+sizeof(gpointer)); MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, - STK_BASE, tree->inst_imm, - tmpr); + STK_BASE, argParm->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, argParm->offset, vt->inst_basereg, soffset); } } + g_free(argParm); } stmt: OP_OUTARG_VT (CEE_LDOBJ (OP_REGOFFSET)) "0" { - MonoInst *vt = state->left->left->tree; + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + MonoInst *vt = state->left->left->tree; + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + int start_reg = tree->sreg1; - int size = tree->unused; + int size = argParm->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); if (start_reg != STK_BASE) { - MONO_EMIT_NEW_MOVE (s, STK_BASE, tree->sreg2, +// MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, +// STK_BASE, soffset); + MONO_EMIT_NEW_MOVE (s, STK_BASE, argParm->offPrm, vt->inst_basereg, soffset, size); - MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, start_reg, - STK_BASE, tree->sreg2); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, + STK_BASE, argParm->offPrm); + mono_call_inst_add_outarg_reg (call, treg, start_reg, FALSE); } else { MONO_EMIT_NEW_MOVE (s, STK_BASE, - tree->sreg2+sizeof(gpointer), + argParm->offPrm+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_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, + argParm->offPrm+sizeof(gpointer)); MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, - STK_BASE, tree->sreg2, - tmpr); + STK_BASE, argParm->offPrm, 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, argParm->offset, vt->inst_basereg, soffset); } } + g_free(argParm); } stmt: OP_OUTARG_VT (CEE_LDOBJ (OP_S390_LOADARG)) { - MonoInst *vt = state->left->left->tree; + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + MonoInst *vt = state->left->left->tree; + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + int start_reg = tree->sreg1; - int size = -tree->unused; + int size = -argParm->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); 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_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, soffset); + MONO_EMIT_NEW_MOVE (s, STK_BASE, argParm->offPrm, treg, 0, size); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, + STK_BASE, argParm->offPrm); + mono_call_inst_add_outarg_reg (call, treg, start_reg, FALSE); } else { MONO_EMIT_NEW_MOVE (s, STK_BASE, - tree->inst_imm+sizeof(gpointer), + argParm->offset+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_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, + argParm->offset+sizeof(gpointer)); MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STORE_MEMBASE_REG, - STK_BASE, tree->inst_imm, - tmpr); + STK_BASE, argParm->offset, treg); } + g_free(argParm); } stmt: OP_OUTARG_VT (OP_ICONST) { + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; int start_reg = tree->sreg1; - int size = tree->unused; + int size = argParm->size; int nregs = size / 4; //printf("OP_OUTARG_VT(OP_ICONST)\n"); 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 (call, tree->dreg, start_reg, FALSE); } } else { MONO_OUTPUT_VTS (s, size, STK_BASE, tree->inst_c0, s->frame_reg, tree->inst_offset); } + g_free(argParm); } stmt: OP_OUTARG_VT (reg) { + MonoCallInst *call = (MonoCallInst*) tree->inst_right; + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + MonoInst *vt = state->left->left->tree; int start_reg = tree->sreg1; - int size = tree->unused; - int soffset = tree->sreg2; - int tmpr; + int size = argParm->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); + MONO_EMIT_NEW_MOVE (s, STK_BASE, argParm->offPrm, state->left->reg1, + 0, size); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, + STK_BASE, argParm->offPrm); + mono_call_inst_add_outarg_reg (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)); + 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, argParm->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, + 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); + treg = mono_regstate_next_int (s->rs); + MONO_EMIT_NEW_BIALU_IMM (s, OP_ADD_IMM, treg, STK_BASE, + s->stack_offset); } } + g_free(argParm); } +stmt: OP_OUTARG_VT (OP_REFANYTYPE (reg)) "0" { + MonoS390ArgParm *argParm = (MonoS390ArgParm *) tree->unused; + +//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)); + g_free(argParm); +} + stmt: CEE_STIND_R8 (OP_REGVAR, freg) { /* nothing to do: the value is already on the FP stack */ } diff --git a/mono/mini/mini-codegen.c b/mono/mini/mini-codegen.c index d514b6e0afb..cfc57f2a53a 100644 --- a/mono/mini/mini-codegen.c +++ b/mono/mini/mini-codegen.c @@ -40,6 +40,9 @@ static const char*const * ins_spec = ia64_desc; #elif defined(__arm__) const char * const arm_cpu_desc [OP_LAST]; static const char*const * ins_spec = arm_cpu_desc; +#elif defined(__s390__) +const char * const s390_cpu_desc [OP_LAST]; +static const char*const * ins_spec = s390_cpu_desc; #else #error "Not implemented" #endif diff --git a/mono/mini/mini-ops.h b/mono/mini/mini-ops.h index c244619db32..645ef254475 100644 --- a/mono/mini/mini-ops.h +++ b/mono/mini/mini-ops.h @@ -597,6 +597,7 @@ MINI_OP(OP_SPARC_COND_EXC_NEZ, "sparc_cond_exc_nez") MINI_OP(OP_S390_LOADARG, "s390_loadarg") +MINI_OP(OP_S390_ARGREG, "s390_argreg") MINI_OP(OP_S390_ARGPTR, "s390_argptr") MINI_OP(OP_S390_STKARG, "s390_stkarg") MINI_OP(OP_S390_MOVE, "s390_move") diff --git a/mono/mini/mini-s390.c b/mono/mini/mini-s390.c index 6ed6b83abd3..e0edfbe1d89 100644 --- a/mono/mini/mini-s390.c +++ b/mono/mini/mini-s390.c @@ -133,18 +133,6 @@ if (ins->flags & MONO_INST_BRLABEL) { \ #define MAX_EXC 16 -/*----------------------------------------*/ -/* use s390_r2-s390_r5 as temp registers */ -/*----------------------------------------*/ -#define S390_CALLER_REGS (0x10fc) -#define reg_is_freeable(r) (S390_CALLER_REGS & 1 << (r)) - -/*----------------------------------------*/ -/* use s390_f1/s390_f3-s390_f15 as temps */ -/*----------------------------------------*/ -#define S390_CALLER_FREGS (0xfffa) -#define freg_is_freeable(r) ((r) >= 1 && (r) <= 14) - #define S390_TRACE_STACK_SIZE (5*sizeof(gint32)+3*sizeof(gdouble)) #define MAX (a, b) ((a) > (b) ? (a) : (b)) @@ -177,6 +165,7 @@ typedef struct { guint stack_size, local_size, code_size, + parm_size, retStruct; } size_data; @@ -192,13 +181,6 @@ enum { SAVE_FP }; -typedef struct { - int born_in; - int killed_in; - int last_use; - int prev_use; -} RegTrack; - typedef struct InstList InstList; struct InstList { @@ -217,7 +199,7 @@ enum { typedef struct { gint32 offset; /* offset from caller's stack */ - gint32 offparm; /* offset on callee's stack */ + gint32 offparm; /* offset from callee's stack */ guint16 vtsize; /* in param area */ guint8 reg; guint8 regtype; /* See RegType* */ @@ -228,6 +210,7 @@ typedef struct { int nargs; guint32 stack_usage; guint32 struct_ret; + guint32 offStruct; ArgInfo ret; ArgInfo sigCookie; ArgInfo args [1]; @@ -252,25 +235,14 @@ static void enter_method (MonoMethod *, RegParm *, char *); static void leave_method (MonoMethod *, ...); static gboolean is_regsize_var (MonoType *); static inline void add_general (guint *, size_data *, ArgInfo *, gboolean); +static inline void add_stackParm (guint *, size_data *, ArgInfo *, gint); static inline void add_float (guint *, size_data *, ArgInfo *); static CallInfo * calculate_sizes (MonoMethodSignature *, size_data *, gboolean); static void peephole_pass (MonoCompile *, MonoBasicBlock *); -static int mono_spillvar_offset (MonoCompile *, int); -static int mono_spillvar_offset_float (MonoCompile *, int); -static void print_ins (int, MonoInst *); -static void print_regtrack (RegTrack *, int); -static InstList * inst_list_prepend (MonoMemPool *, InstList *, MonoInst *); -static int get_register_force_spilling (MonoCompile *, InstList *, MonoInst *, int); -static int get_register_spilling (MonoCompile *, InstList *, MonoInst *, guint32, int); -static int get_float_register_spilling (MonoCompile *, InstList *, MonoInst *, guint32, int); -static MonoInst * create_copy_ins (MonoCompile *, int, int, MonoInst *); -static MonoInst * create_copy_ins_float (MonoCompile *, int, int, MonoInst *); -static MonoInst * create_spilled_store (MonoCompile *, int, int, int, MonoInst *); -static MonoInst * create_spilled_store_float (MonoCompile *, int, int, int, MonoInst *); -static void insert_before_ins (MonoInst *, InstList *, MonoInst *); -static int alloc_int_reg (MonoCompile *, InstList *, MonoInst *, int, guint32); static guchar * emit_float_to_int (MonoCompile *, guchar *, int, int, int, gboolean); static unsigned char * mono_emit_stack_alloc (guchar *, MonoInst *); +static void mono_arch_break(void); +gpointer mono_arch_get_lmf_addr (void); /*========================= End of Prototypes ======================*/ @@ -282,7 +254,7 @@ int mono_exc_esp_offset = 0; static int indent_level = 0; -static const char*const * ins_spec = s390; +static const char*const * ins_spec = s390_cpu_desc; static gboolean tls_offset_inited = FALSE; @@ -290,6 +262,10 @@ static int appdomain_tls_offset = -1, lmf_tls_offset = -1, thread_tls_offset = -1; +pthread_key_t lmf_addr_key; + +gboolean lmf_addr_key_inited = FALSE; + #if 0 extern __thread MonoDomain *tls_appdomain; @@ -317,9 +293,37 @@ mono_arch_regname (int reg) { "s390_r10", "s390_r11", "s390_r12", "s390_r13", "s390_r14", "s390_r15" }; + if (reg >= 0 && reg < 16) return rnames [reg]; - return "unknown"; + else + return "unknown"; +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_fregname */ +/* */ +/* Function - Returns the name of the register specified by */ +/* the input parameter. */ +/* */ +/*------------------------------------------------------------------*/ + +const char* +mono_arch_fregname (int reg) { + static const char * rnames[] = { + "s390_f0", "s390_f1", "s390_f2", "s390_f3", "s390_f4", + "s390_f5", "s390_f6", "s390_f7", "s390_f8", "s390_f9", + "s390_f10", "s390_f11", "s390_f12", "s390_f13", "s390_f14", + "s390_f15" + }; + + if (reg >= 0 && reg < 16) + return rnames [reg]; + else + return "unknown"; } /*========================= End of Function ========================*/ @@ -586,15 +590,16 @@ enum_parmtype: if ((obj) && (obj->vtable)) { printf("[CLASS/OBJ:"); class = obj->vtable->klass; - if (class == mono_defaults.string_class) { - printf("[STRING:%p:%s]", - *obj, mono_string_to_utf8 (obj)); - } else if (class == mono_defaults.int32_class) { - printf("[INT32:%p:%d]", - obj, *(gint32 *)((char *)obj + sizeof (MonoObject))); - } else - printf("[%s.%s:%p]", - class->name_space, class->name, obj); + printf("%p [%p] ",obj,curParm); +// if (class == mono_defaults.string_class) { +// printf("[STRING:%p:%s]", +// *obj, mono_string_to_utf8 (obj)); +// } else if (class == mono_defaults.int32_class) { +// printf("[INT32:%p:%d]", +// obj, *(gint32 *)((char *)obj + sizeof (MonoObject))); +// } else +// printf("[%s.%s:%p]", +// class->name_space, class->name, obj); printf("], "); } else { printf("[OBJECT:null], "); @@ -617,7 +622,7 @@ enum_parmtype: printf("[INT8:%lld], ", *((gint64 *) (curParm))); break; case MONO_TYPE_R4 : - printf("[FLOAT4:%f], ", *((float *) (curParm))); + printf("[FLOAT4:%g], ", *((double *) (curParm))); break; case MONO_TYPE_R8 : printf("[FLOAT8:%g], ", *((double *) (curParm))); @@ -637,7 +642,7 @@ enum_parmtype: if ((info->native_size == sizeof(float)) && (info->num_fields == 1) && (info->fields[0].field->type->type == MONO_TYPE_R4)) { - printf("[FLOAT4:%f], ", *((float *) (curParm))); + printf("[FLOAT4:%f], ", *((float *) (curParm))); break; } @@ -670,6 +675,7 @@ enum_parmtype: /*========================= End of Function ========================*/ +static int lc = 0; /*------------------------------------------------------------------*/ /* */ /* Name - enter_method */ @@ -685,7 +691,6 @@ enter_method (MonoMethod *method, RegParm *rParm, char *sp) int i, oParm = 0, iParm = 0; MonoClass *class; MonoObject *obj; - MonoJitArgumentInfo *arg_info; MonoMethodSignature *sig; char *fname; guint32 ip; @@ -694,6 +699,12 @@ enter_method (MonoMethod *method, RegParm *rParm, char *sp) size_data sz; void *curParm; + +lc++; +if (lc > 50000) { +fseek(stdout, 0L, SEEK_SET); +lc = 0; +} fname = mono_method_full_name (method, TRUE); indent (1); printf ("ENTER: %s(", fname); @@ -725,14 +736,15 @@ enter_method (MonoMethod *method, RegParm *rParm, char *sp) printf ("this:[NULL], "); } else { if (obj) { - class = obj->vtable->klass; - if (class == mono_defaults.string_class) { - printf ("this:[STRING:%p:%s], ", - obj, mono_string_to_utf8 ((MonoString *)obj)); - } else { - printf ("this:%p[%s.%s], ", - obj, class->name_space, class->name); - } +// class = obj->vtable->klass; +// if (class == mono_defaults.string_class) { +// printf ("this:[STRING:%p:%s], ", +// obj, mono_string_to_utf8 ((MonoString *)obj)); +// } else { +// printf ("this:%p[%s.%s], ", +// obj, class->name_space, class->name); +// } +printf("this:%p, ",obj); } else printf ("this:NULL, "); } @@ -740,7 +752,7 @@ enter_method (MonoMethod *method, RegParm *rParm, char *sp) } for (i = 0; i < sig->param_count; ++i) { - ainfo = cinfo->args + (i + oParm); + ainfo = &cinfo->args[i + oParm]; switch (ainfo->regtype) { case RegTypeGeneral : decodeParm(sig->params[i], &(rParm->gr[ainfo->reg-2]), ainfo->size); @@ -886,16 +898,16 @@ handle_enum: case MONO_TYPE_OBJECT: { MonoObject *o = va_arg (ap, MonoObject *); - if ((o) && (o->vtable)) { - if (o->vtable->klass == mono_defaults.boolean_class) { - printf ("[BOOLEAN:%p:%d]", o, *((guint8 *)o + sizeof (MonoObject))); - } else if (o->vtable->klass == mono_defaults.int32_class) { - printf ("[INT32:%p:%d]", o, *((gint32 *)((char *)o + sizeof (MonoObject)))); - } else if (o->vtable->klass == mono_defaults.int64_class) { - printf ("[INT64:%p:%lld]", o, *((gint64 *)((char *)o + sizeof (MonoObject)))); - } else - printf ("[%s.%s:%p]", o->vtable->klass->name_space, o->vtable->klass->name, o); - } else +// if ((o) && (o->vtable)) { +// if (o->vtable->klass == mono_defaults.boolean_class) { +// printf ("[BOOLEAN:%p:%d]", o, *((guint8 *)o + sizeof (MonoObject))); +// } else if (o->vtable->klass == mono_defaults.int32_class) { +// printf ("[INT32:%p:%d]", o, *((gint32 *)((char *)o + sizeof (MonoObject)))); +// } else if (o->vtable->klass == mono_defaults.int64_class) { +// printf ("[INT64:%p:%lld]", o, *((gint64 *)((char *)o + sizeof (MonoObject)))); +// } else +// printf ("[%s.%s:%p]", o->vtable->klass->name_space, o->vtable->klass->name, o); +// } else printf ("[OBJECT:%p]", o); break; @@ -919,8 +931,9 @@ handle_enum: break; } case MONO_TYPE_R4: { - double f = va_arg (ap, double); - printf ("[FLOAT4:%f]\n", (float) f); + float f; + f = va_arg (ap, double); + printf ("[FLOAT4:%f]\n", f); break; } case MONO_TYPE_R8: { @@ -943,7 +956,7 @@ handle_enum: (info->num_fields == 1) && (info->fields[0].field->type->type == MONO_TYPE_R4)) { double f = va_arg (ap, double); - printf("[FLOAT4:%f]\n", (float) f); + printf("[FLOAT4:%g]\n", (double) f); break; } @@ -1083,10 +1096,11 @@ mono_arch_get_allocatable_int_vars (MonoCompile *cfg) MonoMethodVar *vmv = MONO_VARINFO (cfg, i); /* unused vars */ - if (vmv->range.first_use.abs_pos > vmv->range.last_use.abs_pos) + if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos) continue; - if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) || (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG)) + if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) || + (ins->opcode != OP_LOCAL && ins->opcode != OP_ARG)) continue; /* we can only allocate 32 bit values */ @@ -1165,6 +1179,7 @@ add_general (guint *gr, size_data *sz, ArgInfo *ainfo, gboolean simple) ainfo->reg = STK_BASE; ainfo->regtype = RegTypeBase; sz->stack_size += sizeof(int); + sz->local_size += sizeof(int); sz->code_size += 12; } else { ainfo->reg = *gr; @@ -1177,6 +1192,7 @@ add_general (guint *gr, size_data *sz, ArgInfo *ainfo, gboolean simple) ainfo->reg = STK_BASE; ainfo->regtype = RegTypeBase; sz->stack_size += sizeof(long long); + sz->local_size += sizeof(long long); sz->code_size += 10; } else { ainfo->reg = *gr; @@ -1191,6 +1207,38 @@ add_general (guint *gr, size_data *sz, ArgInfo *ainfo, gboolean simple) /*------------------------------------------------------------------*/ /* */ +/* Name - add_stackParm */ +/* */ +/* Function - Determine code and stack size incremements for a */ +/* parameter. */ +/* */ +/*------------------------------------------------------------------*/ + +static void inline +add_stackParm (guint *gr, size_data *sz, ArgInfo *ainfo, gint size) +{ + if (*gr > S390_LAST_ARG_REG) { + sz->stack_size = S390_ALIGN(sz->stack_size, sizeof(long)); + ainfo->offset = sz->stack_size; + ainfo->reg = STK_BASE; +// sz->parm_size += sizeof(gpointer); + } else { + ainfo->reg = *gr; +// sz->parm_size += size; + } + (*gr) ++; + ainfo->offparm = sz->parm_size; + ainfo->size = sizeof(gpointer); + ainfo->regtype = RegTypeStructByAddr; + ainfo->vtsize = size; + sz->local_size += (size + sizeof(gpointer)); + sz->parm_size += size; +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ /* Name - add_float */ /* */ /* Function - Determine code and stack size incremements for a */ @@ -1213,6 +1261,7 @@ add_float (guint *fr, size_data *sz, ArgInfo *ainfo) ainfo->regtype = RegTypeBase; sz->code_size += 4; sz->stack_size += ainfo->size; + sz->local_size += ainfo->size; } } @@ -1242,9 +1291,11 @@ calculate_sizes (MonoMethodSignature *sig, size_data *sz, gr = s390_r2; nParm = 0; cinfo->struct_ret = 0; + cinfo->offStruct = 0; sz->retStruct = 0; sz->stack_size = S390_MINIMAL_STACK_SIZE; sz->code_size = 0; + sz->parm_size = 0; sz->local_size = 0; /*----------------------------------------------------------*/ @@ -1301,8 +1352,6 @@ enum_retvalue: cinfo->struct_ret = 1; cinfo->ret.size = size; cinfo->ret.vtsize = size; - cinfo->ret.offset = sz->stack_size; - sz->stack_size += S390_ALIGN(size, align); gr++; break; } @@ -1312,8 +1361,6 @@ enum_retvalue: cinfo->struct_ret = 1; cinfo->ret.size = size; cinfo->ret.vtsize = size; - cinfo->ret.offset = sz->stack_size; - sz->stack_size += S390_ALIGN(size, align); gr++; break; case MONO_TYPE_VOID: @@ -1351,6 +1398,7 @@ enum_retvalue: nParm++; continue; } + simpletype = mono_type_get_underlying_type(sig->params [i])->type; switch (simpletype) { case MONO_TYPE_BOOLEAN: @@ -1430,7 +1478,6 @@ enum_retvalue: cinfo->args[nParm].vtsize = 0; cinfo->args[nParm].size = 0; - cinfo->args[nParm].offparm = sz->local_size; switch (size) { /*----------------------------------*/ @@ -1456,14 +1503,7 @@ enum_retvalue: sz->local_size += sizeof(long); break; default: - add_general(&gr, sz, cinfo->args+nParm, TRUE); - cinfo->args[nParm].size = sizeof(int); - cinfo->args[nParm].regtype = RegTypeStructByAddr; - cinfo->args[nParm].vtsize = size; - sz->code_size += 40; - sz->local_size += size; - if (cinfo->args[nParm].reg == STK_BASE) - sz->local_size += sizeof(gpointer); + add_stackParm(&gr, sz, cinfo->args+nParm, size); nParm++; } } @@ -1473,7 +1513,6 @@ enum_retvalue: cinfo->args[nParm].vtsize = 0; cinfo->args[nParm].size = 0; - cinfo->args[nParm].offparm = sz->local_size; switch (size) { /*----------------------------------*/ @@ -1499,14 +1538,7 @@ enum_retvalue: sz->local_size += sizeof(long); break; default: - add_general(&gr, sz, cinfo->args+nParm, TRUE); - cinfo->args[nParm].size = sizeof(int); - cinfo->args[nParm].regtype = RegTypeStructByAddr; - cinfo->args[nParm].vtsize = size; - sz->code_size += 40; - sz->local_size += size; - if (cinfo->args[nParm].reg == STK_BASE) - sz->local_size += sizeof(gpointer); + add_stackParm(&gr, sz, cinfo->args+nParm, size); nParm++; } } @@ -1516,8 +1548,28 @@ enum_retvalue: } } - cinfo->stack_usage = S390_ALIGN(sz->stack_size+sz->local_size, - S390_STACK_ALIGNMENT); + /*----------------------------------------------------------*/ + /* If we are passing a structure back then if it won't be */ + /* in a register(s) then we make room at the end of the */ + /* parameters that may have been placed on the stack */ + /*----------------------------------------------------------*/ + if (cinfo->struct_ret) { + cinfo->ret.offset = sz->stack_size; + switch (cinfo->ret.size) { + case 0: + case 1: + case 2: + case 4: + case 8: + break; + default: + sz->stack_size += S390_ALIGN(cinfo->ret.size, align); + } + } + + cinfo->offStruct = sz->stack_size; +// cinfo->stack_usage = S390_ALIGN(sz->stack_size+sz->local_size, +// S390_STACK_ALIGNMENT); return (cinfo); } @@ -1630,11 +1682,19 @@ mono_arch_allocate_vars (MonoCompile *cfg) if (inst->opcode != OP_REGVAR) { switch (cinfo->args[iParm].regtype) { case RegTypeStructByAddr : + if (cinfo->args[iParm].reg == STK_BASE) { inst->opcode = OP_S390_LOADARG; inst->inst_basereg = frame_reg; size = abs(cinfo->args[iParm].vtsize); - offset = S390_ALIGN(offset, size); + offset = S390_ALIGN(offset, sizeof(long)); inst->inst_offset = offset; + } else { + inst->opcode = OP_S390_ARGREG; + inst->inst_basereg = frame_reg; + size = sizeof(gpointer); + offset = S390_ALIGN(offset, size); + inst->inst_offset = offset; + } break; case RegTypeStructByVal : inst->opcode = OP_S390_ARGPTR; @@ -1729,11 +1789,6 @@ mono_arch_allocate_vars (MonoCompile *cfg) /* includes pushing, moving argments to the correct */ /* etc. */ /* */ -/* Note - FIXME: We need an alignment solution for */ -/* enter_method and mono_arch_call_opcode, currently */ -/* alignment in mono_arch_call_opcode is computed */ -/* without arch_get_argument_info. */ -/* */ /*------------------------------------------------------------------*/ MonoCallInst* @@ -1741,6 +1796,7 @@ mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb, MonoCallInst *call, int is_virtual) { MonoInst *arg, *in; MonoMethodSignature *sig; + MonoS390ArgParm *argParm; int i, n, lParamArea; CallInfo *cinfo; ArgInfo *ainfo; @@ -1752,8 +1808,10 @@ mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb, cinfo = calculate_sizes (sig, &sz, sig->pinvoke); - call->stack_usage = cinfo->stack_usage; - lParamArea = MAX((cinfo->stack_usage - S390_MINIMAL_STACK_SIZE), 0); +// call->stack_usage = cinfo->stack_usage; +// lParamArea = MAX((cinfo->stack_usage - S390_MINIMAL_STACK_SIZE), 0); + call->stack_usage = MAX((sz.stack_size + sz.local_size), call->stack_usage); + lParamArea = MAX((call->stack_usage - S390_MINIMAL_STACK_SIZE), 0); cfg->param_area = MAX (((signed) cfg->param_area), lParamArea); cfg->flags |= MONO_CFG_HAS_CALLS; @@ -1771,9 +1829,14 @@ mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb, MONO_INST_NEW (cfg, sigArg, OP_ICONST); sigArg->inst_p0 = call->signature; - MONO_INST_NEW (cfg, arg, OP_OUTARG); - arg->inst_imm = cinfo->sigCookie.offset; - arg->inst_left = sigArg; + MONO_INST_NEW (cfg, arg, OP_OUTARG_MEMBASE); + arg->inst_left = sigArg; + arg->inst_right = (MonoInst *) call; + argParm = g_malloc(sizeof(MonoS390ArgParm)); + argParm->size = ainfo->size; + argParm->offset = cinfo->sigCookie.offset; + arg->unused = (gint32) argParm; + call->used_iregs |= 1 << ainfo->reg; arg->next = call->out_args; call->out_args = arg; @@ -1786,12 +1849,13 @@ mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb, } else { MONO_INST_NEW (cfg, arg, OP_OUTARG); in = call->args [i]; - arg->cil_code = in->cil_code; - arg->inst_left = in; - arg->type = in->type; + arg->cil_code = in->cil_code; + arg->inst_left = in; + arg->type = in->type; /* prepend, we'll need to reverse them later */ - arg->next = call->out_args; - call->out_args = arg; + arg->next = call->out_args; + call->out_args = arg; + arg->inst_right = (MonoInst *) call; if (ainfo->regtype == RegTypeGeneral) { arg->unused = ainfo->reg; call->used_iregs |= 1 << ainfo->reg; @@ -1799,11 +1863,13 @@ mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb, call->used_iregs |= 1 << (ainfo->reg + 1); } else if (ainfo->regtype == RegTypeStructByAddr) { call->used_iregs |= 1 << ainfo->reg; - arg->sreg1 = ainfo->reg; - arg->opcode = OP_OUTARG_VT; - arg->unused = -ainfo->vtsize; - arg->inst_imm = ainfo->offset; - arg->sreg2 = ainfo->offparm + S390_MINIMAL_STACK_SIZE; + arg->sreg1 = ainfo->reg; + arg->opcode = OP_OUTARG_VT; + argParm = g_malloc(sizeof(MonoS390ArgParm)); + argParm->size = -ainfo->vtsize; + argParm->offset = ainfo->offset; + argParm->offPrm = ainfo->offparm + cinfo->offStruct; + arg->unused = (gint32) argParm; } else if (ainfo->regtype == RegTypeStructByVal) { if (ainfo->reg != STK_BASE) { switch (ainfo->size) { @@ -1821,26 +1887,26 @@ mono_arch_call_opcode (MonoCompile *cfg, MonoBasicBlock* bb, call->used_iregs |= 1 << ainfo->reg; } } - arg->sreg1 = ainfo->reg; - arg->opcode = OP_OUTARG_VT; - arg->unused = ainfo->size; - arg->inst_imm = ainfo->offset; - arg->sreg2 = ainfo->offparm + S390_MINIMAL_STACK_SIZE; + arg->sreg1 = ainfo->reg; + arg->opcode = OP_OUTARG_VT; + argParm = g_malloc(sizeof(MonoS390ArgParm)); + argParm->size = ainfo->size; + argParm->offset = ainfo->offset; + argParm->offPrm = ainfo->offparm + cinfo->offStruct; + arg->unused = (gint32) argParm; } else if (ainfo->regtype == RegTypeBase) { - arg->opcode = OP_OUTARG; - arg->unused = ainfo->reg | (ainfo->size << 8); - arg->inst_imm = ainfo->offset; - call->used_fregs |= 1 << ainfo->reg; + arg->opcode = OP_OUTARG_MEMBASE; + arg->sreg1 = ainfo->reg; + argParm = g_malloc(sizeof(MonoS390ArgParm)); + argParm->size = ainfo->size; + argParm->offset = ainfo->offset; + arg->unused = (gint32) argParm; + call->used_iregs |= 1 << ainfo->reg; } else if (ainfo->regtype == RegTypeFP) { arg->unused = ainfo->reg; call->used_fregs |= 1 << ainfo->reg; - if (ainfo->size == 4) { - MonoInst *conv; + if (ainfo->size == 4) arg->opcode = OP_OUTARG_R4; - MONO_INST_NEW (cfg, conv, OP_FCONV_TO_R4); - conv->inst_left = arg->inst_left; - arg->inst_left = conv; - } else arg->opcode = OP_OUTARG_R8; } else { @@ -1900,7 +1966,7 @@ void* mono_arch_instrument_prolog (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments) { - guchar *code = p; + guchar *code = p; int parmOffset, fpOffset; @@ -2094,7 +2160,6 @@ peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb) ins = ins->next; continue; } else { - //static int c = 0; printf ("MATCHX %s %d\n", cfg->method->name,c++); ins->opcode = OP_MOVE; ins->sreg1 = last_ins->sreg1; } @@ -2209,539 +2274,6 @@ peephole_pass (MonoCompile *cfg, MonoBasicBlock *bb) /*------------------------------------------------------------------*/ /* */ -/* Name - mono_spillvar_offset */ -/* */ -/* Function - Returns the offset used by spillvar. It allocates */ -/* a new spill variable if necessary. */ -/* */ -/*------------------------------------------------------------------*/ - -static int -mono_spillvar_offset (MonoCompile *cfg, int spillvar) -{ - MonoSpillInfo **si, *info; - int i = 0; - - si = &cfg->spill_info; - - while (i <= spillvar) { - - if (!*si) { - *si = info = mono_mempool_alloc (cfg->mempool, sizeof (MonoSpillInfo)); - info->next = NULL; - info->offset = cfg->stack_offset; - cfg->stack_offset += sizeof (gpointer); - } - - if (i == spillvar) - return (*si)->offset; - - i++; - si = &(*si)->next; - } - - g_assert_not_reached (); - return 0; -} - -/*========================= End of Function ========================*/ - -/*------------------------------------------------------------------*/ -/* */ -/* Name - mono_spillvar_offset_float */ -/* */ -/* Function - */ -/* */ -/*------------------------------------------------------------------*/ - -static int -mono_spillvar_offset_float (MonoCompile *cfg, int spillvar) -{ - MonoSpillInfo **si, *info; - int i = 0; - - si = &cfg->spill_info_float; - - while (i <= spillvar) { - - if (!*si) { - *si = info = mono_mempool_alloc (cfg->mempool, sizeof (MonoSpillInfo)); - info->next = NULL; - cfg->stack_offset = S390_ALIGN(cfg->stack_offset, S390_STACK_ALIGNMENT); - info->offset = cfg->stack_offset; - cfg->stack_offset += sizeof (double); - } - - if (i == spillvar) - return (*si)->offset; - - i++; - si = &(*si)->next; - } - - g_assert_not_reached (); - return 0; -} - -/*========================= End of Function ========================*/ - -/*------------------------------------------------------------------*/ -/* */ -/* Name - print_ins */ -/* */ -/* Function - Decode and print the instruction for tracing. */ -/* */ -/*------------------------------------------------------------------*/ - -static void -print_ins (int i, MonoInst *ins) -{ - const char *spec = ins_spec [ins->opcode]; - g_print ("\t%-2d %s", i, mono_inst_name (ins->opcode)); - if (spec [MONO_INST_DEST]) { - if (ins->dreg >= MONO_MAX_IREGS) - g_print (" R%d <-", ins->dreg); - else - g_print (" %s <-", mono_arch_regname (ins->dreg)); - } - if (spec [MONO_INST_SRC1]) { - if (ins->sreg1 >= MONO_MAX_IREGS) - g_print (" R%d", ins->sreg1); - else - g_print (" %s", mono_arch_regname (ins->sreg1)); - } - if (spec [MONO_INST_SRC2]) { - if (ins->sreg2 >= MONO_MAX_IREGS) - g_print (" R%d", ins->sreg2); - else - g_print (" %s", mono_arch_regname (ins->sreg2)); - } - if (spec [MONO_INST_CLOB]) - g_print (" clobbers: %c", spec [MONO_INST_CLOB]); - g_print ("\n"); -} - -/*========================= End of Function ========================*/ - -/*------------------------------------------------------------------*/ -/* */ -/* Name - print_regtrack. */ -/* */ -/* Function - */ -/* */ -/*------------------------------------------------------------------*/ - -static void -print_regtrack (RegTrack *t, int num) -{ - int i; - char buf [32]; - const char *r; - - for (i = 0; i < num; ++i) { - if (!t [i].born_in) - continue; - if (i >= MONO_MAX_IREGS) { - g_snprintf (buf, sizeof(buf), "R%d", i); - r = buf; - } else - r = mono_arch_regname (i); - g_print ("liveness: %s [%d - %d]\n", r, t [i].born_in, t[i].last_use); - } -} - -/*========================= End of Function ========================*/ - -/*------------------------------------------------------------------*/ -/* */ -/* Name - inst_list_prepend */ -/* */ -/* Function - Prepend an instruction to the list. */ -/* */ -/*------------------------------------------------------------------*/ - -static inline InstList* -inst_list_prepend (MonoMemPool *pool, InstList *list, MonoInst *data) -{ - InstList *item = mono_mempool_alloc (pool, sizeof (InstList)); - item->data = data; - item->prev = NULL; - item->next = list; - if (list) - list->prev = item; - return item; -} - -/*========================= End of Function ========================*/ - -/*------------------------------------------------------------------*/ -/* */ -/* Name - get_register_force_spilling */ -/* */ -/* Function - Force the spilling of the variable in the */ -/* symbolic register 'reg'. */ -/* */ -/*------------------------------------------------------------------*/ - -static int -get_register_force_spilling (MonoCompile *cfg, InstList *item, MonoInst *ins, int reg) -{ - MonoInst *load; - int i, sel, spill; - - sel = cfg->rs->iassign [reg]; - i = reg; - spill = ++cfg->spill_count; - cfg->rs->iassign [i] = -spill - 1; - mono_regstate_free_int (cfg->rs, sel); - /*----------------------------------------------------------*/ - /* we need to create a spill var and insert a load to sel */ - /* after the current instruction */ - /*----------------------------------------------------------*/ - MONO_INST_NEW (cfg, load, OP_LOAD_MEMBASE); - load->dreg = sel; - load->inst_basereg = cfg->frame_reg; - load->inst_offset = mono_spillvar_offset (cfg, spill); - if (item->prev) { - while (ins->next != item->prev->data) - ins = ins->next; - } - load->next = ins->next; - ins->next = load; - DEBUG (g_print ("SPILLED LOAD (%d at 0x%08x(%%sp)) R%d (freed %s)\n", - spill, load->inst_offset, i, mono_arch_regname (sel))); - i = mono_regstate_alloc_int (cfg->rs, 1 << sel); - g_assert (i == sel); - - return sel; -} - -/*========================= End of Function ========================*/ - -/*------------------------------------------------------------------*/ -/* */ -/* Name - get_register_spilling */ -/* */ -/* Function - */ -/* */ -/*------------------------------------------------------------------*/ - -static int -get_register_spilling (MonoCompile *cfg, InstList *item, MonoInst *ins, guint32 regmask, int reg) -{ - MonoInst *load; - int i, sel, spill; - - DEBUG (g_print ("start regmask to assign R%d: 0x%08x (R%d <- R%d R%d)\n", reg, regmask, ins->dreg, ins->sreg1, ins->sreg2)); - /* exclude the registers in the current instruction */ - if (reg != ins->sreg1 && - (reg_is_freeable (ins->sreg1) || - (ins->sreg1 >= MONO_MAX_IREGS && - cfg->rs->iassign [ins->sreg1] >= 0))) { - if (ins->sreg1 >= MONO_MAX_IREGS) - regmask &= ~ (1 << cfg->rs->iassign [ins->sreg1]); - else - regmask &= ~ (1 << ins->sreg1); - DEBUG (g_print ("excluding sreg1 %s\n", mono_arch_regname (ins->sreg1))); - } - if (reg != ins->sreg2 && - (reg_is_freeable (ins->sreg2) || - (ins->sreg2 >= MONO_MAX_IREGS && - cfg->rs->iassign [ins->sreg2] >= 0))) { - if (ins->sreg2 >= MONO_MAX_IREGS) - regmask &= ~ (1 << cfg->rs->iassign [ins->sreg2]); - else - regmask &= ~ (1 << ins->sreg2); - DEBUG (g_print ("excluding sreg2 %s %d\n", mono_arch_regname (ins->sreg2), ins->sreg2)); - } - if (reg != ins->dreg && reg_is_freeable (ins->dreg)) { - regmask &= ~ (1 << ins->dreg); - DEBUG (g_print ("excluding dreg %s\n", mono_arch_regname (ins->dreg))); - } - - DEBUG (g_print ("available regmask: 0x%08x\n", regmask)); - g_assert (regmask); /* need at least a register we can free */ - sel = -1; - /* we should track prev_use and spill the register that's farther */ - for (i = 0; i < MONO_MAX_IREGS; ++i) { - if (regmask & (1 << i)) { - sel = i; - DEBUG (g_print ("selected register %s has assignment %d\n", mono_arch_regname (sel), cfg->rs->iassign [sel])); - break; - } - } - i = cfg->rs->isymbolic [sel]; - spill = ++cfg->spill_count; - cfg->rs->iassign [i] = -spill - 1; - mono_regstate_free_int (cfg->rs, sel); - /* we need to create a spill var and insert a load to sel after the current instruction */ - MONO_INST_NEW (cfg, load, OP_LOAD_MEMBASE); - load->dreg = sel; - load->inst_basereg = cfg->frame_reg; - load->inst_offset = mono_spillvar_offset (cfg, spill); - if (item->prev) { - while (ins->next != item->prev->data) - ins = ins->next; - } - load->next = ins->next; - ins->next = load; - DEBUG (g_print ("SPILLED LOAD (%d at 0x%08x(%%sp)) R%d (freed %s)\n", spill, load->inst_offset, i, mono_arch_regname (sel))); - i = mono_regstate_alloc_int (cfg->rs, 1 << sel); - g_assert (i == sel); - - return sel; -} - -/*========================= End of Function ========================*/ - -/*------------------------------------------------------------------*/ -/* */ -/* Name - get_float_register_spilling */ -/* */ -/* Function - */ -/* */ -/*------------------------------------------------------------------*/ - -static int -get_float_register_spilling (MonoCompile *cfg, InstList *item, MonoInst *ins, guint32 regmask, int reg) -{ - MonoInst *load; - int i, sel, spill; - - DEBUG (g_print ("start regmask to assign R%d: 0x%08x (R%d <- R%d R%d)\n", reg, regmask, ins->dreg, ins->sreg1, ins->sreg2)); - /* exclude the registers in the current instruction */ - if (reg != ins->sreg1 && - (freg_is_freeable (ins->sreg1) || - (ins->sreg1 >= MONO_MAX_FREGS && - cfg->rs->fassign [ins->sreg1] >= 0))) { - if (ins->sreg1 >= MONO_MAX_FREGS) - regmask &= ~ (1 << cfg->rs->fassign [ins->sreg1]); - else - regmask &= ~ (1 << ins->sreg1); - DEBUG (g_print ("excluding sreg1 %s\n", mono_arch_regname (ins->sreg1))); - } - if (reg != ins->sreg2 && - (freg_is_freeable (ins->sreg2) || - (ins->sreg2 >= MONO_MAX_FREGS && - cfg->rs->fassign [ins->sreg2] >= 0))) { - if (ins->sreg2 >= MONO_MAX_FREGS) - regmask &= ~ (1 << cfg->rs->fassign [ins->sreg2]); - else - regmask &= ~ (1 << ins->sreg2); - DEBUG (g_print ("excluding sreg2 %s %d\n", mono_arch_regname (ins->sreg2), ins->sreg2)); - } - if (reg != ins->dreg && freg_is_freeable (ins->dreg)) { - regmask &= ~ (1 << ins->dreg); - DEBUG (g_print ("excluding dreg %s\n", mono_arch_regname (ins->dreg))); - } - - DEBUG (g_print ("available regmask: 0x%08x\n", regmask)); - g_assert (regmask); /* need at least a register we can free */ - sel = -1; - /* we should track prev_use and spill the register that's farther */ - for (i = 0; i < MONO_MAX_FREGS; ++i) { - if (regmask & (1 << i)) { - sel = i; - DEBUG (g_print ("selected register %s has assignment %d\n", - mono_arch_regname (sel), cfg->rs->fassign [sel])); - break; - } - } - i = cfg->rs->fsymbolic [sel]; - spill = ++cfg->spill_count; - cfg->rs->fassign [i] = -spill - 1; - mono_regstate_free_float(cfg->rs, sel); - /* we need to create a spill var and insert a load to sel after the current instruction */ - MONO_INST_NEW (cfg, load, OP_LOADR8_MEMBASE); - load->dreg = sel; - load->inst_basereg = cfg->frame_reg; - load->inst_offset = mono_spillvar_offset_float (cfg, spill); - if (item->prev) { - while (ins->next != item->prev->data) - ins = ins->next; - } - load->next = ins->next; - ins->next = load; - DEBUG (g_print ("SPILLED LOAD (%d at 0x%08x(%%sp)) R%d (freed %s)\n", spill, load->inst_offset, i, mono_arch_regname (sel))); - i = mono_regstate_alloc_float (cfg->rs, 1 << sel); - g_assert (i == sel); - - return sel; -} - -/*========================= End of Function ========================*/ - -/*------------------------------------------------------------------*/ -/* */ -/* Name - create_copy_ins */ -/* */ -/* Function - Create an instruction to copy from reg to reg. */ -/* */ -/*------------------------------------------------------------------*/ - -static MonoInst* -create_copy_ins (MonoCompile *cfg, int dest, int src, MonoInst *ins) -{ - MonoInst *copy; - MONO_INST_NEW (cfg, copy, OP_MOVE); - copy->dreg = dest; - copy->sreg1 = src; - if (ins) { - copy->next = ins->next; - ins->next = copy; - } - DEBUG (g_print ("\tforced copy from %s to %s\n", - mono_arch_regname (src), mono_arch_regname (dest))); - return copy; -} - -/*========================= End of Function ========================*/ - -/*------------------------------------------------------------------*/ -/* */ -/* Name - create_copy_ins_float */ -/* */ -/* Function - Create an instruction to copy from float reg to */ -/* float reg. */ -/* */ -/*------------------------------------------------------------------*/ - -static MonoInst* -create_copy_ins_float (MonoCompile *cfg, int dest, int src, MonoInst *ins) -{ - MonoInst *copy; - MONO_INST_NEW (cfg, copy, OP_FMOVE); - copy->dreg = dest; - copy->sreg1 = src; - if (ins) { - copy->next = ins->next; - ins->next = copy; - } - DEBUG (g_print ("\tforced copy from %s to %s\n", - mono_arch_regname (src), mono_arch_regname (dest))); - return copy; -} - -/*========================= End of Function ========================*/ - -/*------------------------------------------------------------------*/ -/* */ -/* Name - create_spilled_store */ -/* */ -/* Function - Spill register to storage. */ -/* */ -/*------------------------------------------------------------------*/ - -static MonoInst* -create_spilled_store (MonoCompile *cfg, int spill, int reg, int prev_reg, MonoInst *ins) -{ - MonoInst *store; - MONO_INST_NEW (cfg, store, OP_STORE_MEMBASE_REG); - store->sreg1 = reg; - store->inst_destbasereg = cfg->frame_reg; - store->inst_offset = mono_spillvar_offset (cfg, spill); - if (ins) { - store->next = ins->next; - ins->next = store; - } - DEBUG (g_print ("SPILLED STORE (%d at 0x%08x(%%sp)) R%d (from %s)\n", - spill, store->inst_offset, prev_reg, mono_arch_regname (reg))); - return store; -} - -/*========================= End of Function ========================*/ - -/*------------------------------------------------------------------*/ -/* */ -/* Name - create_spilled_store_float */ -/* */ -/* Function - Spill floating point register to storage. */ -/* */ -/*------------------------------------------------------------------*/ - -static MonoInst* -create_spilled_store_float (MonoCompile *cfg, int spill, int reg, int prev_reg, MonoInst *ins) -{ - MonoInst *store; - MONO_INST_NEW (cfg, store, OP_STORER8_MEMBASE_REG); - store->sreg1 = reg; - store->inst_destbasereg = cfg->frame_reg; - store->inst_offset = mono_spillvar_offset_float (cfg, spill); - if (ins) { - store->next = ins->next; - ins->next = store; - } - DEBUG (g_print ("SPILLED STORE (%d at 0x%08x(%%sp)) R%d (from %s)\n", - spill, store->inst_offset, prev_reg, mono_arch_regname (reg))); - return store; -} - -/*========================= End of Function ========================*/ - -/*------------------------------------------------------------------*/ -/* */ -/* Name - insert_before_ins */ -/* */ -/* Function - Insert an instruction before another. */ -/* */ -/*------------------------------------------------------------------*/ - -static void -insert_before_ins (MonoInst *ins, InstList *item, MonoInst* to_insert) -{ - MonoInst *prev; - g_assert (item->next); - prev = item->next->data; - - while (prev->next != ins) - prev = prev->next; - to_insert->next = ins; - prev->next = to_insert; - /* - * needed otherwise in the next instruction we can add an ins to the - * end and that would get past this instruction. - */ - item->data = to_insert; -} - -/*========================= End of Function ========================*/ - -/*------------------------------------------------------------------*/ -/* */ -/* Name - alloc_int_reg */ -/* */ -/* Function - Allocate a general register. */ -/* */ -/*------------------------------------------------------------------*/ - -static int -alloc_int_reg (MonoCompile *cfg, InstList *curinst, MonoInst *ins, int sym_reg, guint32 allow_mask) -{ - int val = cfg->rs->iassign [sym_reg]; - DEBUG (g_print ("Allocating a general register for %d (%d) with mask %08x\n",val,sym_reg,allow_mask)); - if (val < 0) { - int spill = 0; - if (val < -1) { - /* the register gets spilled after this inst */ - spill = -val -1; - } - val = mono_regstate_alloc_int (cfg->rs, allow_mask); - if (val < 0) - val = get_register_spilling (cfg, curinst, ins, allow_mask, sym_reg); - cfg->rs->iassign [sym_reg] = val; - /* add option to store before the instruction for src registers */ - if (spill) - create_spilled_store (cfg, spill, val, sym_reg, ins); - } - DEBUG (g_print ("Allocated %d for %d\n",val,sym_reg)); - cfg->rs->isymbolic [val] = sym_reg; - return val; -} - -/*========================= End of Function ========================*/ - -/*------------------------------------------------------------------*/ -/* */ /* Name - mono_arch_local_regalloc. */ /* */ /* Function - We first scan the list of instructions and we */ @@ -2757,380 +2289,7 @@ alloc_int_reg (MonoCompile *cfg, InstList *curinst, MonoInst *ins, int sym_reg, void mono_arch_local_regalloc (MonoCompile *cfg, MonoBasicBlock *bb) { - MonoInst *ins; - MonoRegState *rs = cfg->rs; - int i, val; - RegTrack *reginfo, *reginfof; - RegTrack *reginfo1, *reginfo2, *reginfod; - InstList *tmp, *reversed = NULL; - const char *spec; - guint32 src1_mask, src2_mask, dest_mask; - guint32 cur_iregs, cur_fregs; - - if (!bb->code) - return; - rs->next_vireg = bb->max_ireg; - rs->next_vfreg = bb->max_freg; - mono_regstate_assign (rs); - reginfo = mono_mempool_alloc0 (cfg->mempool, sizeof (RegTrack) * rs->next_vireg); - reginfof = mono_mempool_alloc0 (cfg->mempool, sizeof (RegTrack) * rs->next_vfreg); - rs->ifree_mask = S390_CALLER_REGS; - rs->ffree_mask = S390_CALLER_FREGS; - - ins = bb->code; - i = 1; - DEBUG (g_print ("LOCAL regalloc: basic block: %d\n", bb->block_num)); - /* forward pass on the instructions to collect register liveness info */ - while (ins) { - spec = ins_spec [ins->opcode]; - DEBUG (print_ins (i, ins)); -// if (spec [MONO_INST_CLOB] == 'c') { -// MonoCallInst * call = (MonoCallInst*)ins; -// int j; -// } - if (spec [MONO_INST_SRC1]) { - if (spec [MONO_INST_SRC1] == 'f') - reginfo1 = reginfof; - else - reginfo1 = reginfo; - reginfo1 [ins->sreg1].prev_use = reginfo1 [ins->sreg1].last_use; - reginfo1 [ins->sreg1].last_use = i; - } else { - ins->sreg1 = -1; - } - if (spec [MONO_INST_SRC2]) { - if (spec [MONO_INST_SRC2] == 'f') - reginfo2 = reginfof; - else - reginfo2 = reginfo; - reginfo2 [ins->sreg2].prev_use = reginfo2 [ins->sreg2].last_use; - reginfo2 [ins->sreg2].last_use = i; - } else { - ins->sreg2 = -1; - } - if (spec [MONO_INST_DEST]) { - if (spec [MONO_INST_DEST] == 'f') - reginfod = reginfof; - else - reginfod = reginfo; - if (spec [MONO_INST_DEST] != 'b') /* it's not just a base register */ - reginfod [ins->dreg].killed_in = i; - reginfod [ins->dreg].prev_use = reginfod [ins->dreg].last_use; - reginfod [ins->dreg].last_use = i; - if (reginfod [ins->dreg].born_in == 0 || reginfod [ins->dreg].born_in > i) - reginfod [ins->dreg].born_in = i; - if (spec [MONO_INST_DEST] == 'l') { - /* result in R2/R3, the virtual register is allocated sequentially */ - reginfod [ins->dreg + 1].prev_use = reginfod [ins->dreg + 1].last_use; - reginfod [ins->dreg + 1].last_use = i; - if (reginfod [ins->dreg + 1].born_in == 0 || reginfod [ins->dreg + 1].born_in > i) - reginfod [ins->dreg + 1].born_in = i; - } - } else { - ins->dreg = -1; - } - reversed = inst_list_prepend (cfg->mempool, reversed, ins); - ++i; - ins = ins->next; - } - - cur_iregs = S390_CALLER_REGS; - cur_fregs = S390_CALLER_FREGS; - - DEBUG (print_regtrack (reginfo, rs->next_vireg)); - DEBUG (print_regtrack (reginfof, rs->next_vfreg)); - tmp = reversed; - while (tmp) { - int prev_dreg, prev_sreg1, prev_sreg2; - --i; - ins = tmp->data; - spec = ins_spec [ins->opcode]; - DEBUG (g_print ("processing:")); - DEBUG (print_ins (i, ins)); - /* make the register available for allocation: FIXME add fp reg */ - if (ins->opcode == OP_SETREG || ins->opcode == OP_SETREGIMM) { - cur_iregs |= 1 << ins->dreg; - DEBUG (g_print ("adding %d to cur_iregs\n", ins->dreg)); - } else if (ins->opcode == OP_SETFREG) { - cur_fregs |= 1 << ins->dreg; - DEBUG (g_print ("adding %d to cur_fregs\n", ins->dreg)); - } else if (spec [MONO_INST_CLOB] == 'c') { - MonoCallInst *cinst = (MonoCallInst*)ins; - DEBUG (g_print ("excluding regs 0x%x from cur_iregs (0x%x)\n", - cinst->used_iregs, cur_iregs)); - DEBUG (g_print ("excluding fpregs 0x%x from cur_fregs (0x%x)\n", - cinst->used_fregs, cur_fregs)); - cur_iregs &= ~cinst->used_iregs; - cur_fregs &= ~cinst->used_fregs; - DEBUG (g_print ("available cur_iregs: 0x%x\n", cur_iregs)); - DEBUG (g_print ("available cur_fregs: 0x%x\n", cur_fregs)); - /*------------------------------------------------------------*/ - /* registers used by the calling convention are excluded from */ - /* allocation: they will be selectively enabled when they are */ - /* assigned by the special SETREG opcodes. */ - /*------------------------------------------------------------*/ - } - dest_mask = src1_mask = src2_mask = cur_iregs; - /*------------------------------------------------------*/ - /* update for use with FP regs... */ - /*------------------------------------------------------*/ - if (spec [MONO_INST_DEST] == 'f') { - dest_mask = cur_fregs; - if (ins->dreg >= MONO_MAX_FREGS) { - val = rs->fassign [ins->dreg]; - prev_dreg = ins->dreg; - if (val < 0) { - int spill = 0; - if (val < -1) { - /* the register gets spilled after this inst */ - spill = -val -1; - } - val = mono_regstate_alloc_float (rs, dest_mask); - if (val < 0) - val = get_float_register_spilling (cfg, tmp, ins, dest_mask, ins->dreg); - rs->fassign [ins->dreg] = val; - if (spill) - create_spilled_store_float (cfg, spill, val, prev_dreg, ins); - } - DEBUG (g_print ("\tassigned dreg %s to dest R%d\n", - mono_arch_regname (val), ins->dreg)); - rs->fsymbolic [val] = prev_dreg; - ins->dreg = val; - if (spec [MONO_INST_CLOB] == 'c' && ins->dreg != s390_f0) { - /* this instruction only outputs to s390_f0, need to copy */ - create_copy_ins_float (cfg, ins->dreg, s390_f0, ins); - } - } else { - prev_dreg = -1; - } - if (freg_is_freeable (ins->dreg) && prev_dreg >= 0 && (reginfof [prev_dreg].born_in >= i || !(cur_fregs & (1 << ins->dreg)))) { - DEBUG (g_print ("\tfreeable %s (R%d) (born in %d)\n", mono_arch_regname (ins->dreg), prev_dreg, reginfo [prev_dreg].born_in)); - mono_regstate_free_float (rs, ins->dreg); - } - } else if (ins->dreg >= MONO_MAX_IREGS) { - val = rs->iassign [ins->dreg]; - prev_dreg = ins->dreg; - if (val < 0) { - int spill = 0; - if (val < -1) { - /* the register gets spilled after this inst */ - spill = -val -1; - } - val = mono_regstate_alloc_int (rs, dest_mask); - if (val < 0) - val = get_register_spilling (cfg, tmp, ins, dest_mask, ins->dreg); - rs->iassign [ins->dreg] = val; - if (spill) - create_spilled_store (cfg, spill, val, prev_dreg, ins); - } - DEBUG (g_print ("\tassigned dreg %s to dest R%d (prev: R%d)\n", - mono_arch_regname (val), ins->dreg, prev_dreg)); - rs->isymbolic [val] = prev_dreg; - ins->dreg = val; - if (spec [MONO_INST_DEST] == 'l') { - int hreg = prev_dreg + 1; - val = rs->iassign [hreg]; - if (val < 0) { - int spill = 0; - if (val < -1) { - /* the register gets spilled after this inst */ - spill = -val -1; - } - val = mono_regstate_alloc_int (rs, dest_mask); - if (val < 0) - val = get_register_spilling (cfg, tmp, ins, dest_mask, hreg); - rs->iassign [hreg] = val; - if (spill) - create_spilled_store (cfg, spill, val, hreg, ins); - } - DEBUG (g_print ("\tassigned hreg %s to dest R%d\n", mono_arch_regname (val), hreg)); - rs->isymbolic [val] = hreg; - /* FIXME:? ins->dreg = val; */ - if (ins->dreg == s390_r3) { - if (val != s390_r2) - create_copy_ins (cfg, val, s390_r2, ins); - } else if (ins->dreg == s390_r2) { - if (val == s390_r3) { - /* swap */ - create_copy_ins (cfg, s390_r3, s390_r0, ins); - create_copy_ins (cfg, s390_r2, s390_r3, ins); - create_copy_ins (cfg, s390_r0, s390_r2, ins); - } else { - /* two forced copies */ - create_copy_ins (cfg, ins->dreg, s390_r3, ins); - create_copy_ins (cfg, val, s390_r2, ins); - } - } else { - if (val == s390_r2) { - create_copy_ins (cfg, ins->dreg, s390_r2, ins); - } else { - /* two forced copies */ - create_copy_ins (cfg, val, s390_r2, ins); - create_copy_ins (cfg, ins->dreg, s390_r3, ins); - } - } - if (reg_is_freeable (val) && - hreg >= 0 && - (reginfo [hreg].born_in >= i && - !(cur_iregs & (1 << val)))) { - DEBUG (g_print ("\tfreeable %s (R%d)\n", mono_arch_regname (val), hreg)); - mono_regstate_free_int (rs, val); - } - } else if (spec [MONO_INST_DEST] == 'a' && ins->dreg != s390_r2 && spec [MONO_INST_CLOB] != 'd') { - /* this instruction only outputs to s390_r2, need to copy */ - create_copy_ins (cfg, ins->dreg, s390_r2, ins); - } - } else { - prev_dreg = -1; - } - if (spec [MONO_INST_DEST] == 'f' && - freg_is_freeable (ins->dreg) && - prev_dreg >= 0 && (reginfof [prev_dreg].born_in >= i)) { - DEBUG (g_print ("\tfreeable %s (R%d) (born in %d)\n", mono_arch_regname (ins->dreg), prev_dreg, reginfo [prev_dreg].born_in)); - mono_regstate_free_float (rs, ins->dreg); - } else if (spec [MONO_INST_DEST] != 'f' && - reg_is_freeable (ins->dreg) && - prev_dreg >= 0 && (reginfo [prev_dreg].born_in >= i)) { - DEBUG (g_print ("\tfreeable %s (R%d) (born in %d)\n", mono_arch_regname (ins->dreg), prev_dreg, reginfo [prev_dreg].born_in)); - mono_regstate_free_int (rs, ins->dreg); - } - if (spec [MONO_INST_SRC1] == 'f') { - src1_mask = cur_fregs; - if (ins->sreg1 >= MONO_MAX_FREGS) { - val = rs->fassign [ins->sreg1]; - prev_sreg1 = ins->sreg1; - if (val < 0) { - int spill = 0; - if (val < -1) { - /* the register gets spilled after this inst */ - spill = -val -1; - } - val = mono_regstate_alloc_float (rs, src1_mask); - if (val < 0) - val = get_float_register_spilling (cfg, tmp, ins, src1_mask, ins->sreg1); - rs->fassign [ins->sreg1] = val; - DEBUG (g_print ("\tassigned sreg1 %s to R%d\n", mono_arch_regname (val), ins->sreg1)); - if (spill) { - MonoInst *store = create_spilled_store_float (cfg, spill, val, prev_sreg1, NULL); - insert_before_ins (ins, tmp, store); - } - } - rs->fsymbolic [val] = prev_sreg1; - ins->sreg1 = val; - } else { - prev_sreg1 = -1; - } - } else if (ins->sreg1 >= MONO_MAX_IREGS) { - val = rs->iassign [ins->sreg1]; - prev_sreg1 = ins->sreg1; - if (val < 0) { - int spill = 0; - if (val < -1) { - /* the register gets spilled after this inst */ - spill = -val -1; - } - val = mono_regstate_alloc_int (rs, src1_mask); - if (val < 0) - val = get_register_spilling (cfg, tmp, ins, - src1_mask, - ins->sreg1); - rs->iassign [ins->sreg1] = val; - DEBUG (g_print ("\tassigned sreg1 %s to R%d\n", - mono_arch_regname (val), ins->sreg1)); - if (spill) { - MonoInst *store; - store = create_spilled_store (cfg, spill, val, - prev_sreg1, NULL); - insert_before_ins (ins, tmp, store); - } - } - rs->isymbolic [val] = prev_sreg1; - ins->sreg1 = val; - } else { - prev_sreg1 = -1; - } - /*----------------------------------------------*/ - /* handle clobbering of sreg1 */ - /*----------------------------------------------*/ - if ((spec [MONO_INST_CLOB] == '1' || - spec [MONO_INST_CLOB] == 's') && - ins->dreg != ins->sreg1) { - MonoInst *copy; - copy = create_copy_ins (cfg, ins->dreg, ins->sreg1, NULL); - DEBUG (g_print ("\tneed to copy sreg1 %s to dreg %s\n", - mono_arch_regname (ins->sreg1), - mono_arch_regname (ins->dreg))); - if (ins->sreg2 == -1 || spec [MONO_INST_CLOB] == 's') { - /* note: the copy is inserted before the current instruction! */ - insert_before_ins (ins, tmp, copy); - /* we set sreg1 to dest as well */ - prev_sreg1 = ins->sreg1 = ins->dreg; - } else { - /* inserted after the operation */ - copy->next = ins->next; - ins->next = copy; - } - } - - if (spec [MONO_INST_SRC2] == 'f') { - src2_mask = cur_fregs; - if (ins->sreg2 >= MONO_MAX_FREGS) { - val = rs->fassign [ins->sreg2]; - prev_sreg2 = ins->sreg2; - if (val < 0) { - int spill = 0; - if (val < -1) { - /* the register gets spilled after this inst */ - spill = -val -1; - } - val = mono_regstate_alloc_float (rs, src2_mask); - if (val < 0) - val = get_float_register_spilling (cfg, tmp, ins, src2_mask, ins->sreg2); - rs->fassign [ins->sreg2] = val; - DEBUG (g_print ("\tassigned sreg2 %s to R%d\n", mono_arch_regname (val), ins->sreg2)); - if (spill) - create_spilled_store_float (cfg, spill, val, prev_sreg2, ins); - } - rs->fsymbolic [val] = prev_sreg2; - ins->sreg2 = val; - } else { - prev_sreg2 = -1; - } - } else if (ins->sreg2 >= MONO_MAX_IREGS) { - val = rs->iassign [ins->sreg2]; - prev_sreg2 = ins->sreg2; - if (val < 0) { - int spill = 0; - if (val < -1) { - /* the register gets spilled after this inst */ - spill = -val -1; - } - val = mono_regstate_alloc_int (rs, src2_mask); - if (val < 0) - val = get_register_spilling (cfg, tmp, ins, src2_mask, ins->sreg2); - rs->iassign [ins->sreg2] = val; - DEBUG (g_print ("\tassigned sreg2 %s to R%d\n", mono_arch_regname (val), ins->sreg2)); - if (spill) - create_spilled_store (cfg, spill, val, prev_sreg2, ins); - } - rs->isymbolic [val] = prev_sreg2; - ins->sreg2 = val; - } else { - prev_sreg2 = -1; - } - - if (spec [MONO_INST_CLOB] == 'c') { - int j, s; - guint32 clob_mask = S390_CALLER_REGS; - for (j = 0; j < MONO_MAX_IREGS; ++j) { - s = 1 << j; - if ((clob_mask & s) && !(rs->ifree_mask & s) && j != ins->sreg1) { - //g_warning ("register %s busy at call site\n", mono_arch_regname (j)); - } - } - } - tmp = tmp->next; - } + mono_local_regalloc(cfg, bb); } /*========================= End of Function ========================*/ @@ -3532,7 +2691,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } break; case CEE_BREAK: { - s390_break (code); + mono_add_patch_info (cfg, offset, MONO_PATCH_INFO_ABS, mono_arch_break); + s390_brasl (code, s390_r14, 0); } break; case OP_ADDCC: { @@ -3607,6 +2767,25 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException"); } break; + case OP_LADD_OVF: { + short int *o[1]; + CHECK_SRCDST_COM; + s390_alr (code, ins->dreg, src2); + s390_jnc (code, 0); CODEPTR(code, o[0]); + s390_ahi (code, ins->dreg+1, 1); + EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException"); + PTRSLOT (code, o[0]); + s390_ar (code, ins->dreg+1, src2+1); + EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException"); + } + break; + case OP_LADD_OVF_UN: { + CHECK_SRCDST_COM; + s390_alr (code, ins->dreg, src2); + s390_alcr (code, ins->dreg+1, src2+1); + EMIT_COND_SYSTEM_EXCEPTION (S390_CC_CY, "OverflowException"); + } + break; case OP_ADD_OVF_CARRY: { CHECK_SRCDST_COM; s390_lhi (code, s390_r0, 0); @@ -3700,6 +2879,26 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) EMIT_COND_SYSTEM_EXCEPTION (S390_CC_NC, "OverflowException"); } break; + case OP_LSUB_OVF: { + short int *o[3]; + CHECK_SRCDST_COM; + s390_lr (code, s390_r1, src2+1); + s390_slr (code, ins->dreg, src2); + s390_jnl (code, 0); CODEPTR(code, o[0]); + s390_ahi (code, s390_r1, 1); + EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException"); + PTRSLOT (code, o[0]); + s390_sr (code, ins->dreg+1, s390_r1); + EMIT_COND_SYSTEM_EXCEPTION (S390_CC_OV, "OverflowException"); + } + break; + case OP_LSUB_OVF_UN: { + CHECK_SRCDST_COM; + s390_slr (code, ins->dreg, src2); + s390_slbr (code, ins->dreg+1, src2+1); + EMIT_COND_SYSTEM_EXCEPTION (S390_CC_LT, "OverflowException"); + } + break; case OP_SUB_OVF_CARRY: { CHECK_SRCDST_NCOM; s390_lhi (code, s390_r0, 0); @@ -3945,11 +3144,14 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_basr (code, s390_r13, 0); s390_j (code, 4); s390_word (code, ins->inst_imm); - if (ins->dreg != ins->sreg1) { - s390_lr (code, ins->dreg, ins->sreg1); - } +// if (ins->dreg != ins->sreg1) { +// s390_lr (code, ins->dreg, ins->sreg1); +// } s390_l (code, s390_r13, 0, s390_r13, 4); } + if (ins->dreg != ins->sreg1) { + s390_lr (code, ins->dreg, ins->sreg1); + } s390_msr (code, ins->dreg, s390_r13); } break; @@ -4064,7 +3266,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_FCONV_TO_R4: { if ((ins->next) && - (ins->next->opcode != OP_STORER4_MEMBASE_REG)) + (ins->next->opcode != OP_FMOVE) && + (ins->next->opcode != OP_STORER4_MEMBASE_REG)) s390_ledbr (code, ins->dreg, ins->sreg1); } break; @@ -4178,9 +3381,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) g_assert_not_reached (); break; case OP_LOCALLOC: { - int alloca_skip = S390_MINIMAL_STACK_SIZE + cfg->param_area + - S390_STACK_ALIGNMENT - 1; - int area_offset = S390_ALIGN(alloca_skip, S390_STACK_ALIGNMENT); +// int alloca_skip = S390_MINIMAL_STACK_SIZE + cfg->param_area + +// S390_STACK_ALIGNMENT - 1; +// int area_offset = S390_ALIGN(alloca_skip, S390_STACK_ALIGNMENT); + int area_offset = S390_MINIMAL_STACK_SIZE; s390_lr (code, s390_r1, ins->sreg1); if (ins->flags & MONO_INST_INIT) s390_lr (code, s390_r0, ins->sreg1); @@ -4188,8 +3392,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_srl (code, s390_r1, 0, 3); s390_sll (code, s390_r1, 0, 3); s390_l (code, s390_r13, 0, STK_BASE, 0); - s390_lcr (code, s390_r1, s390_r1); - s390_la (code, STK_BASE, STK_BASE, s390_r1, 0); + s390_sr (code, STK_BASE, s390_r1); s390_st (code, s390_r13, 0, STK_BASE, 0); s390_la (code, ins->dreg, 0, STK_BASE, area_offset); s390_srl (code, ins->dreg, 0, 3); @@ -4745,8 +3948,24 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) void mono_arch_register_lowlevel_calls (void) { - mono_register_jit_icall (enter_method, "mono_enter_method", NULL, TRUE); - mono_register_jit_icall (leave_method, "mono_leave_method", NULL, TRUE); + mono_register_jit_icall (mono_arch_break, "mono_arch_break", NULL, TRUE); + mono_register_jit_icall (mono_arch_get_lmf_addr, "mono_arch_get_lmf_addr", NULL, TRUE); +} + +/*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_patch_code */ +/* */ +/* Function - Process the patch data created during the */ +/* instruction build process. This resolves jumps, */ +/* calls, variables etc. */ +/* */ +/*------------------------------------------------------------------*/ + +static void +mono_arch_break(void) { } /*========================= End of Function ========================*/ @@ -4835,6 +4054,9 @@ mono_arch_emit_prolog (MonoCompile *cfg) size_data sz; int tracing = 0; int lmfOffset; \ + int lFname, + lJump; + char *fname; if (mono_jit_trace_calls != NULL && mono_trace_eval (method)) tracing = 1; @@ -4842,6 +4064,14 @@ mono_arch_emit_prolog (MonoCompile *cfg) cfg->code_size = 512; cfg->native_code = code = g_malloc (cfg->code_size); + fname = mono_method_full_name (method, TRUE); + lFname = strlen(fname); + lJump = (((lFname + 1) >> 1) << 1); + s390_j (code, lJump/2+2); + memcpy (code, fname, lFname); + code += lJump; + g_free (fname); + if (cfg->flags & MONO_CFG_HAS_TAIL) { s390_stm (code, s390_r2, s390_r14, STK_BASE, S390_PARM_SAVE_OFFSET); for (pos = 0; pos < 4; pos++) @@ -4994,15 +4224,16 @@ mono_arch_emit_prolog (MonoCompile *cfg) s390_lr (code, s390_r13, ainfo->reg); s390_ahi (code, s390_r13, alloc_size); s390_l (code, s390_r13, 0, s390_r13, - ainfo->offparm + S390_MINIMAL_STACK_SIZE); + ainfo->offparm + cinfo->offStruct); code = emit_memcpy (code, abs(ainfo->vtsize), inst->inst_basereg, inst->inst_offset, s390_r13, 0); } else { - code = emit_memcpy (code, abs(ainfo->vtsize), - inst->inst_basereg, - inst->inst_offset, - ainfo->reg, 0); + s390_st (code, ainfo->reg, 0, inst->inst_basereg, inst->inst_offset); +// code = emit_memcpy (code, abs(ainfo->vtsize), +// inst->inst_basereg, +// inst->inst_offset, +// ainfo->reg, 0); } } else g_assert_not_reached (); @@ -5012,29 +4243,27 @@ mono_arch_emit_prolog (MonoCompile *cfg) if (method->save_lmf) { /*---------------------------------------------------------------*/ + /* we build the MonoLMF structure on the stack - see mini-s390.h */ + /*---------------------------------------------------------------*/ + lmfOffset = alloc_size - sizeof(MonoLMF); + + s390_lr (code, s390_r13, cfg->frame_reg); + s390_ahi (code, s390_r13, lmfOffset); + + /*---------------------------------------------------------------*/ /* Preserve the parameter registers while we fix up the lmf */ /*---------------------------------------------------------------*/ - s390_lr (code, s390_r7, s390_r2); - s390_lr (code, s390_r8, s390_r3); - s390_lr (code, s390_r9, s390_r4); - s390_lr (code, s390_r10, s390_r5); + s390_stm (code, s390_r2, s390_r6, s390_r13, + G_STRUCT_OFFSET(MonoLMF, pregs[0])); - mono_add_patch_info (cfg, code - cfg->native_code, - MONO_PATCH_INFO_INTERNAL_METHOD, - (gpointer)"mono_get_lmf_addr"); /*---------------------------------------------------------------*/ /* On return from this call r2 have the address of the &lmf */ /*---------------------------------------------------------------*/ + mono_add_patch_info (cfg, code - cfg->native_code, + MONO_PATCH_INFO_INTERNAL_METHOD, + (gpointer)"mono_get_lmf_addr"); s390_brasl (code, s390_r14, 0); - /*---------------------------------------------------------------*/ - /* we build the MonoLMF structure on the stack - see mini-s390.h */ - /*---------------------------------------------------------------*/ - lmfOffset = alloc_size - sizeof(MonoLMF); - - s390_lr (code, s390_r13, cfg->frame_reg); - s390_ahi (code, s390_r13, lmfOffset); - /*---------------------------------------------------------------*/ /* Set lmf.lmf_addr = jit_tls->lmf */ /*---------------------------------------------------------------*/ @@ -5089,14 +4318,12 @@ mono_arch_emit_prolog (MonoCompile *cfg) /*---------------------------------------------------------------*/ /* Restore the parameter registers now that we've set up the lmf */ /*---------------------------------------------------------------*/ - s390_lr (code, s390_r2, s390_r7); - s390_lr (code, s390_r3, s390_r8); - s390_lr (code, s390_r4, s390_r9); - s390_lr (code, s390_r5, s390_r10); + s390_lm (code, s390_r2, s390_r6, s390_r13, + G_STRUCT_OFFSET(MonoLMF, pregs[0])); } if (tracing) - code = mono_arch_instrument_prolog (cfg, enter_method, code, TRUE); + code = mono_arch_instrument_prolog(cfg, enter_method, code, TRUE); cfg->code_len = code - cfg->native_code; g_free (cinfo); @@ -5334,7 +4561,9 @@ mono_arch_setup_jit_tls_data (MonoJitTlsData *tls) /* Setup an alternate signal stack */ /*----------------------------------------------------------*/ tls->stack_size = stSize; - tls->signal_stack = g_malloc (SIGNAL_STACK_SIZE); + tls->signal_stack = mmap (0, SIGNAL_STACK_SIZE, + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); tls->signal_stack_size = SIGNAL_STACK_SIZE; sa.ss_sp = tls->signal_stack; @@ -5342,6 +4571,11 @@ mono_arch_setup_jit_tls_data (MonoJitTlsData *tls) sa.ss_flags = SS_ONSTACK; sigaltstack (&sa, NULL); #endif + if (!lmf_addr_key_inited) { + lmf_addr_key_inited = TRUE; + pthread_key_create (&lmf_addr_key, NULL); + } + pthread_setspecific (lmf_addr_key, &tls->lmf); } @@ -5367,7 +4601,7 @@ mono_arch_free_jit_tls_data (MonoJitTlsData *tls) sigaltstack (&sa, NULL); if (tls->signal_stack) - g_free (tls->signal_stack); + munmap(tls->signal_stack, SIGNAL_STACK_SIZE); #endif } @@ -5394,19 +4628,21 @@ mono_arch_emit_this_vret_args (MonoCompile *cfg, MonoCallInst *inst, int this_re if (this_reg != -1) { MonoInst *this; MONO_INST_NEW (cfg, this, OP_SETREG); - this->type = this_type; + this->type = this_type; this->sreg1 = this_reg; - this->dreg = this_dreg; + this->dreg = mono_regstate_next_int (cfg->rs); mono_bblock_add_inst (cfg->cbb, this); + mono_call_inst_add_outarg_reg (inst, this->dreg, this_dreg, FALSE); } if (vt_reg != -1) { MonoInst *vtarg; MONO_INST_NEW (cfg, vtarg, OP_SETREG); - vtarg->type = STACK_MP; + vtarg->type = STACK_MP; vtarg->sreg1 = vt_reg; - vtarg->dreg = s390_r2; + vtarg->dreg = mono_regstate_next_int (cfg->rs); mono_bblock_add_inst (cfg->cbb, vtarg); + mono_call_inst_add_outarg_reg (inst, vtarg->dreg, s390_r2, FALSE); } } @@ -5493,6 +4729,7 @@ mono_arch_print_tree (MonoInst *tree, int arity) switch (tree->opcode) { case OP_S390_LOADARG: + case OP_S390_ARGREG: case OP_S390_ARGPTR: printf ("[0x%x(%s)]", tree->inst_offset, mono_arch_regname (tree->inst_basereg)); @@ -5617,3 +4854,22 @@ mono_arch_flush_register_windows (void) } /*========================= End of Function ========================*/ + +/*------------------------------------------------------------------*/ +/* */ +/* Name - mono_arch_get_lmf_addr */ +/* */ +/* Function - */ +/* */ +/* Returns - */ +/* */ +/*------------------------------------------------------------------*/ + +gpointer +mono_arch_get_lmf_addr (void) +{ + return pthread_getspecific (lmf_addr_key); +} + + +/*========================= End of Function ========================*/ diff --git a/mono/mini/mini-s390.h b/mono/mini/mini-s390.h index db65bfdebad..18800b1840a 100644 --- a/mono/mini/mini-s390.h +++ b/mono/mini/mini-s390.h @@ -7,7 +7,10 @@ #define MONO_MAX_IREGS 16 #define MONO_MAX_FREGS 16 -#define MONO_ARCH_FRAME_ALIGNMENT 8 +/*-------------------------------------------*/ +/* Parameters used by the register allocator */ +/*-------------------------------------------*/ +#define MONO_ARCH_HAS_XP_LOCAL_REGALLOC 1 #define MONO_EMIT_NEW_MOVE(cfg,dest,offset,src,imm,size) do { \ MonoInst *inst; \ @@ -51,25 +54,32 @@ } while (0) #define MONO_OUTPUT_VTR(cfg, size, dr, sr, so) do { \ + int reg = mono_regstate_next_int (cfg->rs); \ switch (size) { \ case 1: \ MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU1_MEMBASE, \ - dr, sr, so); \ + reg, sr, so); \ + mono_call_inst_add_outarg_reg (call, reg, dr, FALSE); \ break; \ case 2: \ MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOADU2_MEMBASE, \ - dr, sr, so); \ + reg, sr, so); \ + mono_call_inst_add_outarg_reg (call, reg, dr, FALSE); \ break; \ case 4: \ MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOAD_MEMBASE, \ - dr, sr, so); \ + reg, sr, so); \ + mono_call_inst_add_outarg_reg (call, reg, dr, FALSE); \ break; \ case 8: \ MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOAD_MEMBASE, \ - dr, sr, so); \ + reg, sr, so); \ + mono_call_inst_add_outarg_reg (call, reg, dr, FALSE); \ dr++; so += sizeof(guint32); \ + reg = mono_regstate_next_int (cfg->rs); \ MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg, OP_LOAD_MEMBASE, \ - dr, sr, so); \ + reg, sr, so); \ + mono_call_inst_add_outarg_reg (call, reg, dr, FALSE); \ break; \ } \ } while (0) @@ -98,16 +108,13 @@ } \ } while (0) -/* fixme: align to 16byte instead of 32byte (we align to 32byte to get - * reproduceable results for benchmarks */ -#define MONO_ARCH_CODE_ALIGNMENT 32 - struct MonoLMF { gpointer previous_lmf; gpointer lmf_addr; MonoMethod *method; gulong ebp; gulong eip; + gulong pregs[6]; gulong gregs[16]; gdouble fregs[16]; }; @@ -119,12 +126,19 @@ typedef struct MonoCompileArch { typedef struct { - void *prev; - void *unused[5]; - void *regs[8]; - void *return_address; + void *prev; + void *unused[5]; + void *regs[8]; + void *return_address; } MonoS390StackFrame; +typedef struct +{ + gint32 size; + gint32 offset; + gint32 offPrm; +} MonoS390ArgParm; + #define MONO_ARCH_EMULATE_FCONV_TO_I8 1 #define MONO_ARCH_EMULATE_LCONV_TO_R8 1 #define MONO_ARCH_EMULATE_LCONV_TO_R4 1 @@ -150,6 +164,56 @@ typedef struct #define S390_NUM_REG_ARGS (S390_LAST_ARG_REG-S390_FIRST_ARG_REG+1) #define S390_NUM_REG_FPARGS (S390_LAST_FPARG_REG-S390_FIRST_FPARG_REG) +/*===============================================*/ +/* Definitions used by mini-codegen.c */ +/*===============================================*/ + +/*--------------------------------------------*/ +/* use s390_r2-s390_r6 as parm registers */ +/* s390_r0, s390_r1, s390_r13 used internally */ +/* s390_r15 is the stack pointer */ +/*--------------------------------------------*/ +#define MONO_ARCH_CALLEE_REGS (0x1ffc) + +#define MONO_ARCH_CALLEE_SAVED_REGS 0xff80 + +/*----------------------------------------*/ +/* use s390_f1/s390_f3-s390_f15 as temps */ +/*----------------------------------------*/ + +#define MONO_ARCH_CALLEE_FREGS (0xfffe) + +#define MONO_ARCH_CALLEE_SAVED_FREGS 0 + +#define MONO_ARCH_USE_FPSTACK FALSE +#define MONO_ARCH_FPSTACK_SIZE 0 + +#define MONO_ARCH_INST_FIXED_REG(desc) ((desc == 'o') ? s390_r2 : \ + ((desc == 'L') ? s390_r3 : \ + ((desc == 'g') ? s390_f0 : - 1))) + +#define MONO_ARCH_INST_IS_FLOAT(desc) ((desc == 'f') || (desc == 'g')) + +#define MONO_ARCH_INST_SREG2_MASK(ins) (0) + +#define MONO_ARCH_INST_IS_REGPAIR(desc) ((desc == 'l') || (desc == 'L')) +//#define MONO_ARCH_INST_IS_REGPAIR(desc) (0) +#define MONO_ARCH_INST_REGPAIR_REG2(desc,hr) ((desc == 'l') ? (hr + 1) : \ + ((desc == 'L') ? s390_r2 : -1)) + +#define MONO_ARCH_IS_GLOBAL_IREG(reg) 0 + +#define MONO_ARCH_FRAME_ALIGNMENT (sizeof (glong)) +#define MONO_ARCH_CODE_ALIGNMENT 32 + +#define MONO_ARCH_BASEREG s390_r15 +#define MONO_ARCH_RETREG1 s390_r2 + +#define MONO_SPARC_STACK_BIAS 0 + +/*-----------------------------------------------*/ +/* Macros used to generate instructions */ +/*-----------------------------------------------*/ #define S390_OFFSET(b, t) (guchar *) ((gint32) (b) - (gint32) (t)) #define S390_RELATIVE(b, t) (guchar *) ((((gint32) (b) - (gint32) (t))) / 2) diff --git a/mono/mini/mini-s390x.c b/mono/mini/mini-s390x.c index b6dfb79ee83..1a1c707b125 100644 --- a/mono/mini/mini-s390x.c +++ b/mono/mini/mini-s390x.c @@ -1007,7 +1007,7 @@ mono_arch_get_allocatable_int_vars (MonoCompile *cfg) MonoMethodVar *vmv = MONO_VARINFO (cfg, i); /* unused vars */ - if (vmv->range.first_use.abs_pos > vmv->range.last_use.abs_pos) + if (vmv->range.first_use.abs_pos >= vmv->range.last_use.abs_pos) continue; if (ins->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT) || -- 2.11.4.GIT