提交 6b27b55a 编写于 作者: Z Zoltan Varga

2004-06-30 Zoltan Varga <vargaz@freemail.hu>

	* mini-ops.h cpu-sparc.md mini-sparc.h mini-sparc.c exceptions-sparc.c tramp-sparc.c inssel-long.brg: Add SPARC64 support.

svn path=/trunk/mono/; revision=30578
上级 0c3b1698
......@@ -15,7 +15,7 @@
# i integer register
# b base register (used in address references)
# f floating point register
# l register pair
# l register pair (same as 'i' on v9)
#
# len:number describe the maximun length in bytes of the instruction
# number is a positive integer
......@@ -46,7 +46,7 @@
# See the code in mini-sparc32.c for more details on how the specifiers are used.
#
nop: len:4
break: len:8
break: len:64
ldarg.0:
ldarg.1:
ldarg.2:
......@@ -83,8 +83,8 @@ ldc.r4:
ldc.r8:
dup:
pop:
jmp: len:32
call: dest:i clob:c len:16
jmp: len:64
call: dest:i clob:c len:40
calli:
ret:
br.s:
......@@ -108,17 +108,23 @@ bge: len:8
bgt: len:8
ble: len:8
blt: len:8
bne.un: len:16
bge.un: len:16
bgt.un: len:16
ble.un: len:16
blt.un: len:16
sparc_brz: len: 8
sparc_brlez: len: 8
sparc_brlz: len: 8
sparc_brnz: len: 8
sparc_brgz: len: 8
sparc_brgez: len: 8
bne.un: len:64
bge.un: len:64
bgt.un: len:64
ble.un: len:64
blt.un: len:64
sparc_brz: src1:i len: 8
sparc_brlez: src1:i len: 8
sparc_brlz: src1:i len: 8
sparc_brnz: src1:i len: 8
sparc_brgz: src1:i len: 8
sparc_brgez: src1:i len: 8
sparc_cond_exc_eqz: src1:i len:64
sparc_cond_exc_nez: src1:i len:64
sparc_cond_exc_ltz: src1:i len:64
sparc_cond_exc_gtz: src1:i len:64
sparc_cond_exc_gez: src1:i len:64
sparc_cond_exc_lez: src1:i len:64
switch:
ldind.i1: dest:i len:4
ldind.u1: dest:i len:4
......@@ -138,13 +144,13 @@ stind.i4: src1:b src2:i
stind.i8:
stind.r4: src1:b src2:f
stind.r8: src1:b src2:f
add: dest:i src1:i src2:i len:4
add: dest:i src1:i src2:i len:64
sub: dest:i src1:i src2:i len:4
mul: dest:i src1:i src2:i len:4
div: dest:i src1:i src2:i len:20
div: dest:i src1:i src2:i len:64
div.un: dest:i src1:i src2:i len:8
rem: dest:d src1:i src2:i len:28
rem.un: dest:d src1:i src2:i len:16
rem: dest:d src1:i src2:i len:64
rem.un: dest:d src1:i src2:i len:64
and: dest:i src1:i src2:i len:4
or: dest:i src1:i src2:i len:4
xor: dest:i src1:i src2:i len:4
......@@ -157,8 +163,8 @@ conv.i1: dest:i src1:i len:8
conv.i2: dest:i src1:i len:8
conv.i4: dest:i src1:i len:4
conv.i8:
conv.r4: dest:f src1:i len:16
conv.r8: dest:f src1:i len:12
conv.r4: dest:f src1:i len:64
conv.r8: dest:f src1:i len:64
conv.u4: dest:i src1:i len:
conv.u8:
callvirt:
......@@ -170,7 +176,7 @@ castclass:
isinst:
conv.r.un:
unbox:
throw: src1:i len:8
throw: src1:i len:64
ldfld:
ldflda:
stfld:
......@@ -216,7 +222,7 @@ conv.ovf.u1:
conv.ovf.i2:
conv.ovf.u2:
conv.ovf.i4:
conv.ovf.u4:
conv.ovf.u4: dest:i src1:i len:64
conv.ovf.i8:
conv.ovf.u8:
refanyval:
......@@ -230,13 +236,13 @@ conv.ovf.i:
conv.ovf.u:
add.ovf:
add.ovf.un:
mul.ovf: dest:i src1:i src2:i len:24
mul.ovf.un: dest:i src1:i src2:i len:20
mul.ovf: dest:i src1:i src2:i len:64
mul.ovf.un: dest:i src1:i src2:i len:64
sub.ovf:
sub.ovf.un:
start_handler: len:20
endfinally: len:20
endfilter: len:16
start_handler: len:64
endfinally: len:64
endfilter: len:64
leave:
leave.s:
stind.i:
......@@ -250,11 +256,11 @@ prefix2:
prefix1:
prefixref:
arglist: src1:i
ceq: dest:i len:12
cgt: dest:i len:12
cgt.un: dest:i len:12
clt: dest:i len:12
clt.un: dest:i len:12
ceq: dest:i len:64
cgt: dest:i len:64
cgt.un: dest:i len:64
clt: dest:i len:64
clt.un: dest:i len:64
ldftn:
ldvirtftn:
ldarg:
......@@ -263,8 +269,8 @@ starg:
ldloc:
ldloca:
stloc:
localloc: dest:i src1:i len:24
sparc_localloc_imm: dest:i len:16
localloc: dest:i src1:i len:64
sparc_localloc_imm: dest:i len:64
unaligned.:
volatile.:
tail.:
......@@ -291,97 +297,99 @@ store:
phi:
rename:
compare: src1:i src2:i len:4
compare_imm: src1:i len:12
fcompare: src1:f src2:f len:12
lcompare:
icompare: src1:i src2:i len:4
compare_imm: src1:i len:64
icompare_imm: src1:i len:64
fcompare: src1:f src2:f len:64
lcompare: src1:i src2:i len:4
local:
arg:
setfret: dest:f src1:f len:8
# FIXME: Mono-specifc opcodes (OP_) Need to clean these up
outarg: src1:i len:1
outarg_imm: len:5
retarg:
setret: dest:a src1:i len:4
setlret: dest:l src1:i src2:i len:8
setreg: dest:i src1:i len:4 clob:r
setregimm: dest:i len:8 clob:r
setregimm: dest:i len:64 clob:r
setfreg: dest:f src1:f len:4 clob:r
sparc_setfreg_float: dest:f src1:f len:4 clob:r
checkthis: src1:b len:4
oparglist: src1:i len:12
voidcall: len:12 clob:c
voidcall_reg: src1:i len:12 clob:c
voidcall_membase: src1:b len:16 clob:c
fcall: dest:f len:20 clob:c
fcall_reg: dest:f src1:i len:20 clob:c
fcall_membase: dest:f src1:b len:24 clob:c
lcall: dest:l len:20 clob:c
lcall_reg: dest:l src1:i len:20 clob:c
lcall_membase: dest:l src1:b len:24 clob:c
vcall: len:16 clob:c
vcall_reg: src1:i len:16 clob:c
vcall_membase: src1:b len:24 clob:c
call_reg: dest:i src1:i len:16 clob:c
call_membase: dest:i src1:b len:20 clob:c
oparglist: src1:i len:64
voidcall: len:64 clob:c
voidcall_reg: src1:i len:64 clob:c
voidcall_membase: src1:b len:64 clob:c
fcall: dest:f len:42 clob:c
fcall_reg: dest:f src1:i len:64 clob:c
fcall_membase: dest:f src1:b len:64 clob:c
lcall: dest:l len:42 clob:c
lcall_reg: dest:l src1:i len:64 clob:c
lcall_membase: dest:l src1:b len:64 clob:c
vcall: len:40 clob:c
vcall_reg: src1:i len:64 clob:c
vcall_membase: src1:b len:64 clob:c
call_reg: dest:i src1:i len:64 clob:c
call_membase: dest:i src1:b len:64 clob:c
trap:
iconst: dest:i len:8
i8const:
r4const: dest:f len:16
r8const: dest:f len:12
iconst: dest:i len:64
i8const: dest:i len:64
r4const: dest:f len:64
r8const: dest:f len:64
regvar:
reg:
regoffset:
label:
store_membase_imm: dest:b len:20
store_membase_reg: dest:b src1:i len:12
storei1_membase_imm: dest:b len:20
storei1_membase_reg: dest:b src1:i len:12
storei2_membase_imm: dest:b len:20
storei2_membase_reg: dest:b src1:i len:12
storei4_membase_imm: dest:b len:20
storei4_membase_reg: dest:b src1:i len:12
storei8_membase_imm: dest:b len:20
storei8_membase_reg: dest:b src1:i len:12
storer4_membase_reg: dest:b src1:f len:20
storer8_membase_reg: dest:b src1:f len:20
load_membase: dest:i src1:b len:12
loadi1_membase: dest:i src1:b len:12
loadu1_membase: dest:i src1:b len:12
loadi2_membase: dest:i src1:b len:12
loadu2_membase: dest:i src1:b len:12
loadi4_membase: dest:i src1:b len:12
loadu4_membase: dest:i src1:b len:12
loadi8_membase: dest:i src1:b
loadr4_membase: dest:f src1:b len:16
loadr8_membase: dest:f src1:b len:20
store_membase_imm: dest:b len:64
store_membase_reg: dest:b src1:i len:64
storei1_membase_imm: dest:b len:64
storei1_membase_reg: dest:b src1:i len:64
storei2_membase_imm: dest:b len:64
storei2_membase_reg: dest:b src1:i len:64
storei4_membase_imm: dest:b len:64
storei4_membase_reg: dest:b src1:i len:64
storei8_membase_imm: dest:b len:64 len:64
storei8_membase_reg: dest:b src1:i len:64
storer4_membase_reg: dest:b src1:f len:64
storer8_membase_reg: dest:b src1:f len:64
load_membase: dest:i src1:b len:64
loadi1_membase: dest:i src1:b len:64
loadu1_membase: dest:i src1:b len:64
loadi2_membase: dest:i src1:b len:64
loadu2_membase: dest:i src1:b len:64
loadi4_membase: dest:i src1:b len:64
loadu4_membase: dest:i src1:b len:64
loadi8_membase: dest:i src1:b len:64
loadr4_membase: dest:f src1:b len:64
loadr8_membase: dest:f src1:b len:64
loadu4_mem: dest:i len:8
move: dest:i src1:i len:4
add_imm: dest:i src1:i len:12
sub_imm: dest:i src1:i len:12
mul_imm: dest:i src1:i len:12
div_imm: dest:a src1:i src2:i len:28
div_un_imm: dest:a src1:i src2:i len:12
rem_imm: dest:d src1:i src2:i len:36
rem_un_imm: dest:d src1:i src2:i len:16
and_imm: dest:i src1:i len:12
or_imm: dest:i src1:i len:12
xor_imm: dest:i src1:i len:12
shl_imm: dest:i src1:i len:12
shr_imm: dest:i src1:i len:12
shr_un_imm: dest:i src1:i len:12
cond_exc_eq: len:12
cond_exc_ne_un: len:12
cond_exc_lt: len:12
cond_exc_lt_un: len:12
cond_exc_gt: len:12
cond_exc_gt_un: len:12
cond_exc_ge: len:12
cond_exc_ge_un: len:12
cond_exc_le: len:12
cond_exc_le_un: len:12
cond_exc_ov: len:12
cond_exc_no: len:12
cond_exc_c: len:12
cond_exc_nc: len:12
add_imm: dest:i src1:i len:64
sub_imm: dest:i src1:i len:64
mul_imm: dest:i src1:i len:64
div_imm: dest:a src1:i src2:i len:64
div_un_imm: dest:a src1:i src2:i len:64
rem_imm: dest:d src1:i src2:i len:64
rem_un_imm: dest:d src1:i src2:i len:64
and_imm: dest:i src1:i len:64
or_imm: dest:i src1:i len:64
xor_imm: dest:i src1:i len:64
shl_imm: dest:i src1:i len:64
shr_imm: dest:i src1:i len:64
shr_un_imm: dest:i src1:i len:64
cond_exc_eq: len:64
cond_exc_ne_un: len:64
cond_exc_lt: len:64
cond_exc_lt_un: len:64
cond_exc_gt: len:64
cond_exc_gt_un: len:64
cond_exc_ge: len:64
cond_exc_ge_un: len:64
cond_exc_le: len:64
cond_exc_le_un: len:64
cond_exc_ov: len:64
cond_exc_no: len:64
cond_exc_c: len:64
cond_exc_nc: len:64
long_add:
long_sub:
long_mul:
......@@ -392,9 +400,9 @@ long_rem_un:
long_and:
long_or:
long_xor:
long_shl:
long_shr:
long_shr_un:
long_shl: dest:i src1:i src2:i len:64
long_shr: dest:i src1:i src2:i len:64
long_shr_un: dest:i src1:i src2:i len:64
long_neg:
long_not:
long_conv_to_i1:
......@@ -439,11 +447,11 @@ long_cgt:
long_cgt_un:
long_clt:
long_clt_un:
long_conv_to_r_un: dest:f src1:i src2:i len:37
long_conv_to_r_un: dest:f src1:i src2:i len:64
long_conv_to_u:
long_shr_imm:
long_shr_un_imm:
long_shl_imm:
long_shr_imm: dest:i src1:i len:64
long_shr_un_imm: dest:i src1:i len:64
long_shl_imm: dest:i src1:i len:64
long_add_imm:
long_sub_imm:
long_beq:
......@@ -457,22 +465,22 @@ long_bge_un:
long_ble:
long_ble_un:
float_beq: len:8
float_bne_un: len:16
float_bne_un: len:64
float_blt: len:8
float_blt_un: len:16
float_blt_un: len:64
float_bgt: len:8
float_btg_un: len:16
float_bge: len:16
float_bge_un: len:16
float_ble: len:16
float_ble_un: len:16
float_btg_un: len:64
float_bge: len:64
float_bge_un: len:64
float_ble: len:64
float_ble_un: len:64
float_add: dest:f src1:f src2:f len:4
float_sub: dest:f src1:f src2:f len:4
float_mul: dest:f src1:f src2:f len:4
float_div: dest:f src1:f src2:f len:4
float_div_un: dest:f src1:f src2:f len:4
float_rem: dest:f src1:f src2:f len:16
float_rem_un: dest:f src1:f src2:f len:16
float_rem: dest:f src1:f src2:f len:64
float_rem_un: dest:f src1:f src2:f len:64
float_neg: dest:f src1:f len:4
float_not: dest:f src1:f len:4
float_conv_to_i1: dest:i src1:f len:40
......@@ -512,23 +520,74 @@ float_conv_to_ovf_i4:
float_conv_to_ovf_u4:
float_conv_to_ovf_i8:
float_conv_to_ovf_u8:
float_ceq: dest:i src1:f src2:f len:16
float_cgt: dest:i src1:f src2:f len:16
float_cgt_un: dest:i src1:f src2:f len:24
float_clt: dest:i src1:f src2:f len:16
float_clt_un: dest:i src1:f src2:f len:24
float_conv_to_u: dest:i src1:f len:36
call_handler: len:12
op_endfilter: src1:i len:12
aot_const: dest:i len:8
float_ceq: dest:i src1:f src2:f len:64
float_cgt: dest:i src1:f src2:f len:64
float_cgt_un: dest:i src1:f src2:f len:64
float_clt: dest:i src1:f src2:f len:64
float_clt_un: dest:i src1:f src2:f len:64
float_conv_to_u: dest:i src1:f len:64
call_handler: len:64
op_endfilter: src1:i len:64
aot_const: dest:i len:64
adc: dest:i src1:i src2:i len:4
addcc: dest:i src1:i src2:i len:4
subcc: dest:i src1:i src2:i len:4
adc_imm: dest:i src1:i len:12
adc_imm: dest:i src1:i len:64
sbb: dest:i src1:i src2:i len:4
sbb_imm: dest:i src1:i len:12
sbb_imm: dest:i src1:i len:64
br_reg: 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
fmove: dest:f src1:f len:8
# 32 bit opcodes
int_add: dest:i src1:i src2:i len:64
int_sub: dest:i src1:i src2:i len:64
int_mul: dest:i src1:i src2:i len:64
int_div: dest:i src1:i src2:i len:64
int_div_un: dest:i src1:i src2:i len:64
int_rem: dest:i src1:i src2:i len:64
int_rem_un: dest:i src1:i src2:i len:64
int_and: dest:i src1:i src2:i len:64
int_or: dest:i src1:i src2:i len:64
int_xor: dest:i src1:i src2:i len:64
int_shl: dest:i src1:i src2:i len:64
int_shr: dest:i src1:i src2:i len:64
int_shr_un: dest:i src1:i src2:i len:64
int_adc: dest:i src1:i src2:i len:64
int_adc_imm: dest:i src1:i len:64
int_sbb: dest:i src1:i src2:i len:64
int_sbb_imm: dest:i src1:i len:64
int_addcc: dest:i src1:i src2:i len:64
int_subcc: dest:i src1:i src2:i len:64
int_add_imm: dest:i src1:i len:64
int_sub_imm: dest:i src1:i len:64
int_mul_imm: dest:i src1:i len:64
int_div_imm: dest:i src1:i len:64
int_div_un_imm: dest:i src1:i len:64
int_rem_imm: dest:i src1:i len:64
int_rem_un_imm: dest:i src1:i len:64
int_and_imm: dest:i src1:i len:64
int_or_imm: dest:i src1:i len:64
int_xor_imm: dest:i src1:i len:64
int_shl_imm: dest:i src1:i len:64
int_shr_imm: dest:i src1:i len:64
int_shr_un_imm: dest:i src1:i len:64
int_neg: dest:i src1:i len:64
int_not: dest:i src1:i len:64
int_ceq: dest:i len:64
int_cgt: dest:i len:64
int_cgt_un: dest:i len:64
int_clt: dest:i len:64
int_clt_un: dest:i len:64
int_beq: len:64
int_bne_un: len:64
int_blt: len:64
int_blt_un: len:64
int_bgt: len:64
int_bgt_un: len:64
int_bge: len:64
int_bge_un: len:64
int_ble: len:64
int_ble_un: len:64
......@@ -30,6 +30,8 @@
#define REG_SP REG_O6
#endif
#define MONO_SPARC_WINDOW_ADDR(sp) ((gpointer*)(((guint8*)(sp)) + MONO_SPARC_STACK_BIAS))
/*
* mono_arch_get_restore_context:
*
......@@ -47,8 +49,8 @@ mono_arch_get_restore_context (void)
code = start;
sparc_ld_imm (code, sparc_o0, G_STRUCT_OFFSET (MonoContext, ip), sparc_i7);
sparc_ld_imm (code, sparc_o0, G_STRUCT_OFFSET (MonoContext, sp), sparc_i6);
sparc_ldi_imm (code, sparc_o0, G_STRUCT_OFFSET (MonoContext, ip), sparc_i7);
sparc_ldi_imm (code, sparc_o0, G_STRUCT_OFFSET (MonoContext, sp), sparc_i6);
sparc_jmpl_imm (code, sparc_i7, 0, sparc_g0);
/* FIXME: This does not return to the correct window */
......@@ -90,13 +92,13 @@ mono_arch_get_call_filter (void)
*/
/* Create first frame */
sparc_save_imm (code, sparc_sp, -160, sparc_sp);
sparc_save_imm (code, sparc_sp, -256, sparc_sp);
sparc_mov_reg_reg (code, sparc_i1, sparc_o0);
sparc_ld_imm (code, sparc_i0, G_STRUCT_OFFSET (MonoContext, sp), sparc_o1);
sparc_ldi_imm (code, sparc_i0, G_STRUCT_OFFSET (MonoContext, sp), sparc_o1);
/* Create second frame */
sparc_save_imm (code, sparc_sp, -160, sparc_sp);
sparc_save_imm (code, sparc_sp, -256, sparc_sp);
sparc_mov_reg_reg (code, sparc_i0, sparc_o0);
sparc_mov_reg_reg (code, sparc_i1, sparc_o1);
......@@ -117,17 +119,17 @@ mono_arch_get_call_filter (void)
* method containing the filter.
*/
for (i = 0; i < 16; ++i)
sparc_ld_imm (code, sparc_o1, i * 4, sparc_l0 + i);
sparc_ldi_imm (code, sparc_o1, MONO_SPARC_STACK_BIAS + i * sizeof (gpointer), sparc_l0 + i);
/* Save %fp to a location reserved in mono_arch_allocate_vars */
sparc_st_imm (code, sparc_o7, sparc_fp, -4);
sparc_sti_imm (code, sparc_o7, sparc_fp, MONO_SPARC_STACK_BIAS - sizeof (gpointer));
/* Call the filter code, after this returns, %o0 will hold the result */
sparc_call_imm (code, sparc_o0, 0);
sparc_nop (code);
/* Restore original %fp */
sparc_ld_imm (code, sparc_fp, -4, sparc_fp);
sparc_ldi_imm (code, sparc_fp, MONO_SPARC_STACK_BIAS - sizeof (gpointer), sparc_fp);
sparc_mov_reg_reg (code, sparc_o0, sparc_i0);
......@@ -149,17 +151,19 @@ mono_arch_get_call_filter (void)
}
static void
throw_exception (MonoObject *ex, guint32 sp, guint32 ip)
throw_exception (MonoObject *ex, gpointer sp, gpointer ip)
{
MonoContext ctx;
static void (*restore_context) (MonoContext *);
gpointer *window;
if (!restore_context)
restore_context = mono_arch_get_restore_context ();
ctx.sp = (guint32*)sp;
window = MONO_SPARC_WINDOW_ADDR (sp);
ctx.sp = (gpointer*)sp;
ctx.ip = ip;
ctx.fp = (guint32*)ctx.sp [sparc_i6 - 16];
ctx.fp = (gpointer*)(MONO_SPARC_WINDOW_ADDR (sp) [sparc_i6 - 16]);
mono_handle_exception (&ctx, ex, ip, FALSE);
restore_context (&ctx);
......@@ -187,7 +191,7 @@ mono_arch_get_throw_exception (void)
inited = 1;
code = start;
sparc_save_imm (code, sparc_sp, -160, sparc_sp);
sparc_save_imm (code, sparc_sp, -512, sparc_sp);
sparc_flushw (code);
sparc_mov_reg_reg (code, sparc_i0, sparc_o0);
......@@ -212,9 +216,10 @@ mono_arch_get_throw_exception (void)
gpointer
mono_arch_get_throw_exception_by_name (void)
{
static guint32 start [32];
static guint32 start [64];
static int inited = 0;
guint32 *code;
int reg;
if (inited)
return start;
......@@ -222,6 +227,12 @@ mono_arch_get_throw_exception_by_name (void)
inited = 1;
code = start;
#ifdef SPARCV9
reg = sparc_g4;
#else
reg = sparc_g1;
#endif
sparc_save_imm (code, sparc_sp, -160, sparc_sp);
sparc_mov_reg_reg (code, sparc_i0, sparc_o2);
......@@ -236,9 +247,9 @@ mono_arch_get_throw_exception_by_name (void)
/* Put original return address into %o7 */
sparc_mov_reg_reg (code, sparc_o1, sparc_o7);
sparc_set (code, mono_arch_get_throw_exception (), sparc_g1);
sparc_set (code, mono_arch_get_throw_exception (), reg);
/* Use a jmp instead of a call so o7 is preserved */
sparc_jmpl_imm (code, sparc_g1, 0, sparc_g0);
sparc_jmpl_imm (code, reg, 0, sparc_g0);
sparc_nop (code);
g_assert ((code - start) < 32);
......@@ -262,7 +273,7 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf
{
MonoJitInfo *ji;
gpointer ip = MONO_CONTEXT_GET_IP (ctx);
guint32 *window;
gpointer *window;
/* Avoid costly table lookup during stack overflow */
if (prev_ji && (ip > prev_ji->code_start && ((guint8*)ip < ((guint8*)prev_ji->code_start) + prev_ji->code_size)))
......@@ -321,10 +332,10 @@ mono_arch_find_jit_info (MonoDomain *domain, MonoJitTlsData *jit_tls, MonoJitInf
}
/* Restore ip and sp from the saved register window */
window = (guint32*)ctx->sp;
window = MONO_SPARC_WINDOW_ADDR (ctx->sp);
new_ctx->ip = window [sparc_i7 - 16];
new_ctx->sp = (guint32*)(window [sparc_i6 - 16]);
new_ctx->fp = (guint32*)(new_ctx->sp [sparc_i6 - 16]);
new_ctx->sp = (gpointer*)(window [sparc_i6 - 16]);
new_ctx->fp = (gpointer*)(MONO_SPARC_WINDOW_ADDR (new_ctx->sp) [sparc_i6 - 16]);
*res = *ji;
return res;
......@@ -369,6 +380,7 @@ mono_arch_handle_exception (void *sigctx, gpointer obj, gboolean test_only)
{
MonoContext mctx;
ucontext_t *ctx = (ucontext_t*)sigctx;
gpointer *window;
/*
* Access to the machine state using the ucontext_t parameter is somewhat
......@@ -384,7 +396,8 @@ mono_arch_handle_exception (void *sigctx, gpointer obj, gboolean test_only)
mctx.ip = ctx->uc_mcontext.gregs [REG_PC];
mctx.sp = ctx->uc_mcontext.gregs [REG_SP];
mctx.fp = mctx.sp [sparc_fp - 16];
window = (gpointer*)(((guint8*)mctx.sp) + MONO_SPARC_STACK_BIAS);
mctx.fp = window [sparc_fp - 16];
mono_handle_exception (&mctx, obj, mctx.ip, test_only);
......@@ -392,7 +405,8 @@ mono_arch_handle_exception (void *sigctx, gpointer obj, gboolean test_only)
ctx->uc_mcontext.gregs [REG_PC] = mctx.ip;
ctx->uc_mcontext.gregs [REG_nPC] = mctx.ip + 4;
ctx->uc_mcontext.gregs [REG_SP] = mctx.sp;
mctx.sp [sparc_fp - 16] = mctx.fp;
window = (gpointer*)(((guint8*)mctx.sp) + MONO_SPARC_STACK_BIAS);
window [sparc_fp - 16] = mctx.fp;
return TRUE;
}
......
......@@ -9,6 +9,10 @@
# (C) 2002 Ximian, Inc.
#
reg: OP_I8CONST {
MONO_EMIT_NEW_I8CONST (s, state->reg1, tree->inst_l);
}
reg: CEE_LDIND_I8 (base) {
MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI8_MEMBASE, state->reg1,
state->left->tree->inst_basereg, state->left->tree->inst_offset);
......@@ -19,29 +23,633 @@ stmt: CEE_STIND_I8 (base, reg) {
state->left->tree->inst_offset, state->right->reg1);
}
stmt: CEE_STIND_REF (base, OP_I8CONST),
stmt: CEE_STIND_I (base, OP_I8CONST),
stmt: CEE_STIND_I8 (base, OP_I8CONST),
stmt: CEE_STIND_REF (base, OP_ICONST),
stmt: CEE_STIND_I (base, OP_ICONST),
stmt: CEE_STIND_I8 (base, OP_ICONST) {
MONO_EMIT_STORE_MEMBASE_IMM (s, tree, OP_STOREI8_MEMBASE_IMM, state->left->tree->inst_basereg,
state->left->tree->inst_offset, state->right->tree->inst_c0);
}
stmt: CEE_STIND_I8 (reg, reg) {
MONO_EMIT_STORE_MEMBASE (s, tree, OP_STOREI8_MEMBASE_REG, state->left->tree->inst_basereg,
state->left->tree->inst_offset, state->right->reg1);
}
reg: OP_LADD (reg, reg) {
MONO_EMIT_NEW_BIALU (s, CEE_ADD, state->reg1, state->left->reg1, state->right->reg1);
}
reg: OP_LSUB (reg, reg) {
MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg1, state->left->reg1, state->right->reg1);
}
reg: OP_LNEG (reg) {
MONO_EMIT_NEW_UNALU (s, CEE_NEG, state->reg1, state->left->reg1);
}
reg: OP_LNOT (reg) {
MONO_EMIT_NEW_UNALU (s, CEE_NOT, state->reg1, state->left->reg1);
}
reg: OP_LAND (reg, reg) {
MONO_EMIT_NEW_BIALU (s, CEE_AND, state->reg1, state->left->reg1, state->right->reg1);
}
reg: OP_LOR (reg, reg) {
MONO_EMIT_NEW_BIALU (s, CEE_OR, state->reg1, state->left->reg1, state->right->reg1);
}
reg: OP_LXOR (reg, reg) {
MONO_EMIT_NEW_BIALU (s, CEE_XOR, state->reg1, state->left->reg1, state->right->reg1);
}
reg: OP_LADD_OVF (reg, reg) {
MONO_EMIT_NEW_BIALU (s, OP_ADDCC, state->reg1, state->left->reg1, state->right->reg1);
MONO_EMIT_NEW_COND_EXC (s, OV, "OverflowException");
}
reg: OP_LADD_OVF_UN (reg, reg) {
MONO_EMIT_NEW_BIALU (s, OP_ADDCC, state->reg1, state->left->reg1, state->right->reg1);
MONO_EMIT_NEW_COND_EXC (s, C, "OverflowException");
}
reg: OP_LSUB_OVF (reg, reg) {
MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1);
MONO_EMIT_NEW_COND_EXC (s, OV, "OverflowException");
}
reg: OP_LSUB_OVF_UN (reg, reg) {
MONO_EMIT_NEW_BIALU (s, OP_SUBCC, state->reg1, state->left->reg1, state->right->reg1);
MONO_EMIT_NEW_COND_EXC (s, C, "OverflowException");
}
reg: OP_LONG_SHRUN_32 (reg) {
MONO_EMIT_BIALU_IMM (s, tree, OP_LSHR_UN_IMM, state->reg1, state->left->reg1, 32);
}
#
# shift operations
#
reg: OP_LSHL (reg, reg) {
MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
}
reg: OP_LSHL (reg, OP_ICONST) {
MONO_EMIT_BIALU_IMM (s, tree, OP_LSHL_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
}
reg: OP_LSHR (reg, reg) {
MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
}
reg: OP_LSHR_IMM (reg, OP_ICONST) {
MONO_EMIT_BIALU_IMM (s, tree, OP_LSHR_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
}
reg: OP_LSHR_UN (reg, reg) {
MONO_EMIT_BIALU (s, tree, tree->opcode, state->reg1, state->left->reg1, state->right->reg1);
}
reg: OP_LSHR_UN (reg, OP_ICONST) {
MONO_EMIT_BIALU_IMM (s, tree, OP_LSHR_UN_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
}
#
# Conversions
#
reg: CEE_CONV_I8 (reg) {
/* Sign extend the value in the lower word into the upper word */
MONO_EMIT_BIALU_IMM (s, tree, OP_SHR_IMM, state->reg1, state->left->reg1, 0);
}
reg: CEE_CONV_U8 (reg) {
/* Clean out the upper word */
MONO_EMIT_BIALU_IMM (s, tree, OP_SHR_UN_IMM, state->reg1, state->left->reg1, 0);
}
i8con: CEE_CONV_U8 (OP_ICONST) "0" {
/*
* This is needed since constant propagation eliminates some
* stind.i4/ldind.i4 pairs, along with the conversions done by them.
*/
int data = state->left->tree->inst_c0;
tree->opcode = OP_I8CONST;
tree->inst_ls_word = data;
tree->inst_ms_word = 0;
}
reg: OP_LCONV_TO_I4 (reg) {
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
reg: OP_FCONV_TO_I8 (freg) {
g_assert_not_reached ();
MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
}
reg: OP_FCONV_TO_U8 (freg) {
g_assert_not_reached ();
MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
}
freg: CEE_CONV_R_UN (reg) {
g_assert_not_reached ();
reg: OP_LCONV_TO_I4 (i8con) {
MONO_EMIT_NEW_ICONST (s, state->reg1, state->left->tree->inst_ls_word);
}
freg: CEE_CONV_R4 (reg) {
g_assert_not_reached ();
reg: OP_LCONV_TO_I4 (reg) {
/* Sign extend the value in the lower word into the upper word */
MONO_EMIT_BIALU_IMM (s, tree, OP_SHR_IMM, state->reg1, state->left->reg1, 0);
}
reg: OP_LCONV_TO_U4 (reg) {
/* Clean out the upper word */
MONO_EMIT_BIALU_IMM (s, tree, OP_SHR_UN_IMM, state->reg1, state->left->reg1, 0);
}
freg: CEE_CONV_R8 (reg) {
reg: OP_LCONV_TO_U8 (reg) {
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_I8 (reg) {
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_U (reg) {
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_I (reg) {
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_I1 (reg) {
MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_U1 (reg) {
MONO_EMIT_UNALU (s, tree, CEE_CONV_U1, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_I2 (reg) {
MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_U2 (reg) {
MONO_EMIT_UNALU (s, tree, CEE_CONV_U2, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_OVF_I1 (reg) {
MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 127);
MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, -128);
MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
MONO_EMIT_UNALU (s, tree, CEE_CONV_I1, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_OVF_U1 (reg) {
/* probe value to be within 0 to 255 */
MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 255);
MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xff);
}
reg: OP_LCONV_TO_OVF_U1_UN (reg) {
/* probe value to be within 0 to 255 */
MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 255);
MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xff);
}
reg: OP_LCONV_TO_OVF_I2 (reg) {
/* Probe value to be within -32768 and 32767 */
MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 32767);
MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, -32768);
MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
MONO_EMIT_UNALU (s, tree, CEE_CONV_I2, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_OVF_U2 (reg) {
/* Probe value to be within 0 and 65535 */
MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0xffff);
MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xffff);
}
reg: OP_LCONV_TO_OVF_U2_UN (reg) {
/* Probe value to be within 0 and 65535 */
MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0xffff);
MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
MONO_EMIT_BIALU_IMM (s, tree, OP_AND_IMM, state->reg1, state->left->reg1, 0xffff);
}
reg: OP_LCONV_TO_OVF_I4 (reg) {
MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0x7fffffff);
MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, -2147483648);
MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_OVF_U4_UN (reg) {
MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0xffffffff);
MONO_EMIT_NEW_COND_EXC (s, GT_UN, "OverflowException");
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_OVF_U4 (reg) {
MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0xffffffffUL);
MONO_EMIT_NEW_COND_EXC (s, GT, "OverflowException");
MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg1, 0);
MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_OVF_I_UN (reg),
reg: OP_LCONV_TO_OVF_I8_UN (reg) {
MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg1, 0);
MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_OVF_U8 (reg) {
MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg1, 0);
MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_OVF_I8 (reg) {
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_OVF_U8_UN (reg) {
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
reg: OP_LCONV_TO_OVF_I (reg) {
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
freg: OP_LCONV_TO_R_UN (lreg) {
MONO_EMIT_UNALU (s, tree, tree->opcode, state->reg1, state->left->reg1);
}
reg: CEE_CONV_OVF_I8 (reg) {
/* Sign extend the value in the lower word into the upper word */
MONO_EMIT_BIALU_IMM (s, tree, OP_SHR_IMM, state->reg1, state->left->reg1, 0);
}
reg: CEE_CONV_OVF_I8_UN (reg) {
/* an unsigned 32 bit num always fits in a signed 64 bit one */
/* Clean out the upper word */
MONO_EMIT_BIALU_IMM (s, tree, OP_SHR_UN_IMM, state->reg1, state->left->reg1, 0);
}
reg: CEE_CONV_OVF_U8 (reg) {
MONO_EMIT_NEW_COMPARE_IMM (s, state->left->reg1, 0);
MONO_EMIT_NEW_COND_EXC (s, LT, "OverflowException");
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
}
reg: CEE_CONV_OVF_U8_UN (reg) {
g_assert_not_reached ();
}
reg: OP_LCALLVIRT (reg) {
mini_emit_virtual_call (s, state, tree, OP_LCALL, OP_LCALL_MEMBASE);
}
reg: OP_LCALL {
tree->dreg = state->reg1;
mono_bblock_add_inst (s->cbb, tree);
}
reg: OP_LCALL_REG (reg) {
tree->sreg1 = state->left->reg1;
tree->dreg = state->reg1;
mono_bblock_add_inst (s->cbb, tree);
}
reg: OP_LCALL_REG (OP_ICONST) {
tree->opcode = OP_LCALL;
((MonoCallInst*)tree)->fptr = state->left->tree->inst_p0;
tree->dreg = state->reg1;
mono_bblock_add_inst (s->cbb, tree);
}
stmt: CEE_STIND_I4 (OP_REGVAR, OP_ICONST) {
tree->inst_c0 = state->right->tree->inst_c0;
tree->opcode = OP_ICONST;
tree->dreg = state->left->tree->dreg;
mono_bblock_add_inst (s->cbb, tree);
}
stmt: CEE_STIND_I4 (OP_REGVAR, reg) {
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->left->tree->dreg, state->right->reg1);
}
stmt: CEE_STIND_I4 (OP_REGVAR, CEE_LDIND_I4 (OP_REGVAR)) {
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->left->tree->dreg, state->right->left->tree->dreg);
}
stmt: CEE_STIND_I4 (OP_REGVAR, CEE_LDIND_I4 (base)) {
MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI4_MEMBASE, state->left->tree->dreg,
state->right->left->tree->inst_basereg,
state->right->left->tree->inst_offset);
}
cflags: OP_LCOMPARE (reg, reg) {
tree->sreg1 = state->left->reg1;
tree->sreg2 = state->right->reg1;
mono_bblock_add_inst (s->cbb, tree);
}
cflags: OP_LCOMPARE (CEE_LDIND_I8 (OP_REGVAR), reg) {
tree->sreg1 = state->left->left->tree->dreg;
tree->sreg2 = state->right->reg1;
mono_bblock_add_inst (s->cbb, tree);
}
cflags: OP_LCOMPARE (CEE_LDIND_I (OP_REGVAR), CEE_LDIND_I (OP_REGVAR)) {
tree->sreg1 = state->left->left->tree->dreg;
tree->sreg2 = state->right->left->tree->dreg;
mono_bblock_add_inst (s->cbb, tree);
}
cflags: OP_LCOMPARE (CEE_LDIND_I8 (OP_REGVAR), OP_ICONST) {
tree->opcode = OP_COMPARE_IMM;
tree->sreg1 = state->left->left->tree->dreg;
tree->inst_imm = state->right->tree->inst_c0;
mono_bblock_add_inst (s->cbb, tree);
}
cflags: OP_LCOMPARE (reg, OP_ICONST) {
tree->opcode = OP_COMPARE_IMM;
tree->sreg1 = state->left->reg1;
tree->inst_imm = state->right->tree->inst_c0;
mono_bblock_add_inst (s->cbb, tree);
}
cflags: OP_LCOMPARE (reg, OP_I8CONST) {
tree->opcode = OP_COMPARE_IMM;
tree->sreg1 = state->left->reg1;
tree->inst_imm = state->right->tree->inst_c0;
mono_bblock_add_inst (s->cbb, tree);
}
stmt: CEE_BNE_UN (cflags) {
mono_bblock_add_inst (s->cbb, tree);
}
stmt: CEE_BEQ (cflags) {
mono_bblock_add_inst (s->cbb, tree);
}
stmt: CEE_BLT (cflags) {
mono_bblock_add_inst (s->cbb, tree);
}
stmt: CEE_BLT_UN (cflags) {
mono_bblock_add_inst (s->cbb, tree);
}
stmt: CEE_BGT (cflags) {
mono_bblock_add_inst (s->cbb, tree);
}
stmt: CEE_BGT_UN (cflags) {
mono_bblock_add_inst (s->cbb, tree);
}
stmt: CEE_BGE (cflags) {
mono_bblock_add_inst (s->cbb, tree);
}
stmt: CEE_BGE_UN (cflags) {
mono_bblock_add_inst (s->cbb, tree);
}
stmt: CEE_BLE (cflags) {
mono_bblock_add_inst (s->cbb, tree);
}
stmt: CEE_BLE_UN (cflags) {
mono_bblock_add_inst (s->cbb, tree);
}
#
# 32 bit rules
#
#
# basic alu operations
#
reg: CEE_AND (reg, reg) {
MONO_EMIT_BIALU (s, tree, OP_IAND, state->reg1, state->left->reg1, state->right->reg1);
}
reg: CEE_AND (reg, OP_ICONST) {
MONO_EMIT_BIALU_IMM (s, tree, OP_IAND_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
}
reg: CEE_OR (reg, reg) {
MONO_EMIT_BIALU (s, tree, OP_IOR, state->reg1, state->left->reg1, state->right->reg1);
}
reg: CEE_OR (reg, OP_ICONST) {
MONO_EMIT_BIALU_IMM (s, tree, OP_IOR_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
}
reg: CEE_XOR (reg, reg) {
MONO_EMIT_BIALU (s, tree, OP_IXOR, state->reg1, state->left->reg1, state->right->reg1);
}
reg: CEE_XOR (reg, OP_ICONST) {
MONO_EMIT_BIALU_IMM (s, tree, OP_IXOR_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
}
reg: CEE_NEG (reg) {
MONO_EMIT_UNALU (s, tree, OP_INEG, state->reg1, state->left->reg1);
}
reg: CEE_NOT (reg) {
MONO_EMIT_UNALU (s, tree, OP_INOT, state->reg1, state->left->reg1);
}
reg: CEE_ADD (reg, reg) {
MONO_EMIT_BIALU (s, tree, OP_IADD, state->reg1, state->left->reg1, state->right->reg1);
}
reg: CEE_ADD (reg, OP_ICONST) {
MONO_EMIT_BIALU_IMM (s, tree, OP_IADD_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
}
reg: CEE_ADD_OVF (reg, reg) {
MONO_EMIT_NEW_BIALU (s, OP_IADDCC, state->reg1, state->left->reg1, state->right->reg1);
MONO_EMIT_NEW_COND_EXC (s, IOV, "OverflowException");
}
reg: CEE_ADD_OVF_UN (reg, reg) {
MONO_EMIT_NEW_BIALU (s, OP_IADDCC, state->reg1, state->left->reg1, state->right->reg1);
MONO_EMIT_NEW_COND_EXC (s, IC, "OverflowException");
}
reg: CEE_SUB (reg, reg) {
MONO_EMIT_BIALU (s, tree, OP_ISUB, state->reg1, state->left->reg1, state->right->reg1);
}
reg: CEE_SUB (reg, CEE_LDIND_I4 (OP_REGVAR)) {
MONO_EMIT_BIALU (s, tree, OP_ISUB, state->reg1, state->left->reg1, state->right->left->tree->dreg);
}
reg: CEE_SUB (reg, OP_ICONST) {
MONO_EMIT_BIALU_IMM (s, tree, OP_ISUB_IMM, state->reg1, state->left->reg1, state->right->tree->inst_c0);
}
reg: CEE_SUB_OVF (reg, reg) {
MONO_EMIT_NEW_BIALU (s, OP_ISUBCC, state->reg1, state->left->reg1, state->right->reg1);
MONO_EMIT_NEW_COND_EXC (s, IOV, "OverflowException");
}
reg: CEE_SUB_OVF_UN (reg, reg) {
MONO_EMIT_NEW_BIALU (s, OP_ISUBCC, state->reg1, state->left->reg1, state->right->reg1);
MONO_EMIT_NEW_COND_EXC (s, IC, "OverflowException");
}
c32flags: OP_COMPARE (reg, reg) {
tree->opcode = OP_ICOMPARE;
tree->sreg1 = state->left->reg1;
tree->sreg2 = state->right->reg1;
mono_bblock_add_inst (s->cbb, tree);
}
c32flags: OP_COMPARE (CEE_LDIND_I (OP_REGVAR), CEE_LDIND_I (OP_REGVAR)) {
tree->opcode = OP_ICOMPARE;
tree->sreg1 = state->left->left->tree->dreg;
tree->sreg2 = state->right->left->tree->dreg;
mono_bblock_add_inst (s->cbb, tree);
}
c32flags: OP_COMPARE (CEE_LDIND_I (OP_REGVAR), OP_ICONST) {
tree->opcode = OP_ICOMPARE_IMM;
tree->sreg1 = state->left->left->tree->dreg;
tree->inst_imm = state->right->tree->inst_c0;
mono_bblock_add_inst (s->cbb, tree);
}
c32flags: OP_COMPARE (CEE_LDIND_I4 (OP_REGVAR), reg) {
tree->opcode = OP_ICOMPARE;
tree->sreg1 = state->left->left->tree->dreg;
tree->sreg2 = state->right->reg1;
mono_bblock_add_inst (s->cbb, tree);
}
c32flags: OP_COMPARE (CEE_LDIND_I4 (OP_REGVAR), OP_ICONST) {
tree->opcode = OP_ICOMPARE_IMM;
tree->sreg1 = state->left->left->tree->dreg;
tree->inst_imm = state->right->tree->inst_c0;
mono_bblock_add_inst (s->cbb, tree);
}
c32flags: OP_COMPARE (reg, OP_ICONST) {
tree->opcode = OP_ICOMPARE_IMM;
tree->sreg1 = state->left->reg1;
tree->inst_imm = state->right->tree->inst_c0;
mono_bblock_add_inst (s->cbb, tree);
}
stmt: CEE_BNE_UN (c32flags) {
tree->opcode = OP_IBNE_UN;
mono_bblock_add_inst (s->cbb, tree);
}
stmt: CEE_BEQ (c32flags) {
tree->opcode = OP_IBEQ;
mono_bblock_add_inst (s->cbb, tree);
}
stmt: CEE_BLT (c32flags) {
tree->opcode = OP_IBLT;
mono_bblock_add_inst (s->cbb, tree);
}
stmt: CEE_BLT_UN (c32flags) {
tree->opcode = OP_IBLT_UN;
mono_bblock_add_inst (s->cbb, tree);
}
stmt: CEE_BGT (c32flags) {
tree->opcode = OP_IBGT;
mono_bblock_add_inst (s->cbb, tree);
}
stmt: CEE_BGT_UN (c32flags) {
tree->opcode = OP_IBGT_UN;
mono_bblock_add_inst (s->cbb, tree);
}
stmt: CEE_BGE (c32flags) {
tree->opcode = OP_IBGE;
mono_bblock_add_inst (s->cbb, tree);
}
stmt: CEE_BGE_UN (c32flags) {
tree->opcode = OP_IBGE_UN;
mono_bblock_add_inst (s->cbb, tree);
}
stmt: CEE_BLE (c32flags) {
tree->opcode = OP_IBLE;
mono_bblock_add_inst (s->cbb, tree);
}
stmt: CEE_BLE_UN (c32flags) {
tree->opcode = OP_IBLE_UN;
mono_bblock_add_inst (s->cbb, tree);
}
reg: OP_CEQ (c32flags) {
tree->opcode = OP_ICEQ;
tree->dreg = state->reg1;
mono_bblock_add_inst (s->cbb, tree);
}
reg: OP_CLT (c32flags) {
tree->opcode = OP_ICLT;
tree->dreg = state->reg1;
mono_bblock_add_inst (s->cbb, tree);
}
reg: OP_CLT_UN (c32flags) {
tree->opcode = OP_ICLT_UN;
tree->dreg = state->reg1;
mono_bblock_add_inst (s->cbb, tree);
}
reg: OP_CGT (c32flags) {
tree->opcode = OP_ICGT;
tree->dreg = state->reg1;
mono_bblock_add_inst (s->cbb, tree);
}
reg: OP_CGT_UN (c32flags) {
tree->opcode = OP_ICGT_UN;
tree->dreg = state->reg1;
mono_bblock_add_inst (s->cbb, tree);
}
%%
......@@ -10,6 +10,8 @@ MINI_OP(OP_COMPARE, "compare")
MINI_OP(OP_COMPARE_IMM, "compare_imm")
MINI_OP(OP_FCOMPARE, "fcompare")
MINI_OP(OP_LCOMPARE, "lcompare")
MINI_OP(OP_ICOMPARE, "icompare")
MINI_OP(OP_ICOMPARE_IMM, "icompare_imm")
MINI_OP(OP_LOCAL, "local")
MINI_OP(OP_ARG, "arg")
MINI_OP(OP_ARGLIST, "oparglist")
......@@ -200,6 +202,64 @@ MINI_OP(OP_LBGE_UN, "long_bge_un")
MINI_OP(OP_LBLE, "long_ble")
MINI_OP(OP_LBLE_UN, "long_ble_un")
/* 32 bit opcodes on 64 bit machines */
MINI_OP(OP_IADD, "int_add")
MINI_OP(OP_ISUB, "int_sub")
MINI_OP(OP_IMUL, "int_mul")
MINI_OP(OP_IDIV, "int_div")
MINI_OP(OP_IDIV_UN, "int_div_un")
MINI_OP(OP_IREM, "int_rem")
MINI_OP(OP_IREM_UN, "int_rem_un")
MINI_OP(OP_IAND, "int_and")
MINI_OP(OP_IOR, "int_or")
MINI_OP(OP_IXOR, "int_xor")
MINI_OP(OP_ISHL, "int_shl")
MINI_OP(OP_ISHR, "int_shr")
MINI_OP(OP_ISHR_UN, "int_shr_un")
MINI_OP(OP_IADC, "int_adc")
MINI_OP(OP_IADC_IMM, "int_adc_imm")
MINI_OP(OP_ISBB, "int_sbb")
MINI_OP(OP_ISBB_IMM, "int_sbb_imm")
MINI_OP(OP_IADDCC, "int_addcc")
MINI_OP(OP_ISUBCC, "int_subcc")
MINI_OP(OP_IADD_IMM, "int_add_imm")
MINI_OP(OP_ISUB_IMM, "int_sub_imm")
MINI_OP(OP_IMUL_IMM, "int_mul_imm")
MINI_OP(OP_IDIV_IMM, "int_div_imm")
MINI_OP(OP_IDIV_UN_IMM, "int_div_un_imm")
MINI_OP(OP_IREM_IMM, "int_rem_imm")
MINI_OP(OP_IREM_UN_IMM, "int_rem_un_imm")
MINI_OP(OP_IAND_IMM, "int_and_imm")
MINI_OP(OP_IOR_IMM, "int_or_imm")
MINI_OP(OP_IXOR_IMM, "int_xor_imm")
MINI_OP(OP_ISHL_IMM, "int_shl_imm")
MINI_OP(OP_ISHR_IMM, "int_shr_imm")
MINI_OP(OP_ISHR_UN_IMM, "int_shr_un_imm")
MINI_OP(OP_INEG, "int_neg")
MINI_OP(OP_INOT, "int_not")
MINI_OP(OP_ICEQ, "int_ceq")
MINI_OP(OP_ICGT, "int_cgt")
MINI_OP(OP_ICGT_UN,"int_cgt_un")
MINI_OP(OP_ICLT, "int_clt")
MINI_OP(OP_ICLT_UN,"int_clt_un")
MINI_OP(OP_IBEQ, "int_beq")
MINI_OP(OP_IBNE_UN, "int_bne_un")
MINI_OP(OP_IBLT, "int_blt")
MINI_OP(OP_IBLT_UN, "int_blt_un")
MINI_OP(OP_IBGT, "int_bgt")
MINI_OP(OP_IBGT_UN, "int_bgt_un")
MINI_OP(OP_IBGE, "int_bge")
MINI_OP(OP_IBGE_UN, "int_bge_un")
MINI_OP(OP_IBLE, "int_ble")
MINI_OP(OP_IBLE_UN, "int_ble_un")
MINI_OP(OP_COND_EXC_IOV, "cond_exc_iov")
MINI_OP(OP_COND_EXC_IC, "cond_exc_ic")
MINI_OP(OP_FBEQ, "float_beq")
MINI_OP(OP_FBNE_UN,"float_bne_un")
MINI_OP(OP_FBLT, "float_blt")
......@@ -362,14 +422,24 @@ MINI_OP(OP_SPARC_OUTARG_REGPAIR, "sparc_outarg_regpair")
MINI_OP(OP_SPARC_OUTARG_MEM, "sparc_outarg_mem")
MINI_OP(OP_SPARC_OUTARG_MEMPAIR, "sparc_outarg_mempair")
MINI_OP(OP_SPARC_OUTARG_SPLIT_REG_STACK, "sparc_outarg_split_reg_stack")
MINI_OP(OP_SPARC_OUTARG_FLOAT_REG, "sparc_outarg_float_reg")
MINI_OP(OP_SPARC_OUTARG_DOUBLE_REG, "sparc_outarg_double_reg")
MINI_OP(OP_SPARC_INARG_VT, "sparc_inarg_vt")
MINI_OP(OP_SPARC_LOCALLOC_IMM, "sparc_localloc_imm")
MINI_OP(OP_SPARC_SETFREG_FLOAT, "sparc_setfreg_float")
MINI_OP(OP_SPARC_BRZ, "sparc_brz")
MINI_OP(OP_SPARC_BRLEZ, "sparc_brlez")
MINI_OP(OP_SPARC_BRLZ, "sparc_brlz")
MINI_OP(OP_SPARC_BRNZ, "sparc_brnz")
MINI_OP(OP_SPARC_BRGZ, "sparc_brgz")
MINI_OP(OP_SPARC_BRGEZ, "sparc_brgez")
MINI_OP(OP_SPARC_COND_EXC_EQZ, "sparc_cond_exc_eqz")
MINI_OP(OP_SPARC_COND_EXC_GEZ, "sparc_cond_exc_gez")
MINI_OP(OP_SPARC_COND_EXC_GTZ, "sparc_cond_exc_gtz")
MINI_OP(OP_SPARC_COND_EXC_LEZ, "sparc_cond_exc_lez")
MINI_OP(OP_SPARC_COND_EXC_LTZ, "sparc_cond_exc_ltz")
MINI_OP(OP_SPARC_COND_EXC_NEZ, "sparc_cond_exc_nez")
MINI_OP(OP_S390_LOADARG, "s390_loadarg")
MINI_OP(OP_S390_ARGPTR, "s390_argptr")
......
此差异已折叠。
......@@ -8,36 +8,42 @@
#define MONO_MAX_IREGS 32
#define MONO_MAX_FREGS 32
#define MONO_ARCH_FRAME_ALIGNMENT 8
#define MONO_ARCH_FRAME_ALIGNMENT (sizeof (gpointer) * 2)
#define MONO_ARCH_CODE_ALIGNMENT 32
#define MONO_ARCH_BASEREG sparc_fp
#define MONO_ARCH_RETREG1 sparc_i0
#ifdef SPARCV9
#define MONO_SPARC_STACK_BIAS 2047
#else
#define MONO_SPARC_STACK_BIAS 0
#endif
struct MonoLMF {
gpointer previous_lmf;
gpointer lmf_addr;
MonoMethod *method;
guint32 ip;
guint32 sp;
guint32 ebp;
gpointer ip;
gpointer sp;
gpointer ebp;
};
typedef struct MonoContext {
guint32 ip;
guint32 *sp;
guint32 *fp;
guint8 *ip;
gpointer *sp;
gpointer *fp;
} MonoContext;
typedef struct MonoCompileArch {
guint32 lmf_offset;
guint32 localloc_offset;
gint32 lmf_offset;
gint32 localloc_offset;
} MonoCompileArch;
#define MONO_CONTEXT_SET_IP(ctx,eip) do { (ctx)->ip = (guint32)(eip); } while (0);
#define MONO_CONTEXT_SET_BP(ctx,ebp) do { (ctx)->fp = (guint32*)(ebp); } while (0);
#define MONO_CONTEXT_SET_SP(ctx,esp) do { (ctx)->sp = (guint32*)(esp); } while (0);
#define MONO_CONTEXT_SET_IP(ctx,eip) do { (ctx)->ip = (gpointer)(eip); } while (0);
#define MONO_CONTEXT_SET_BP(ctx,ebp) do { (ctx)->fp = (gpointer*)(ebp); } while (0);
#define MONO_CONTEXT_SET_SP(ctx,esp) do { (ctx)->sp = (gpointer*)(esp); } while (0);
#define MONO_CONTEXT_GET_IP(ctx) ((gpointer)((ctx)->ip))
#define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->fp))
......@@ -55,6 +61,10 @@ typedef struct MonoCompileArch {
#define MONO_ARCH_EMULATE_FREM 1
#define MONO_ARCH_NEED_DIV_CHECK 1
#ifdef SPARCV9
#define MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
#endif
#ifndef __GNUC__
/* assume Sun compiler if not GCC */
static void * __builtin_return_address(int depth)
......@@ -90,12 +100,14 @@ static void * __builtin_frame_address(int depth)
gboolean mono_sparc_is_virtual_call (guint32 *code);
gpointer* mono_sparc_get_vcall_slot_addr (guint32 *code, guint32 *fp);
gpointer* mono_sparc_get_vcall_slot_addr (guint32 *code, gpointer *fp);
void mono_sparc_flushw (void);
gboolean mono_sparc_is_v9 (void);
gboolean mono_sparc_is_sparc64 (void);
struct MonoCompile;
guint32* mono_sparc_emit_save_lmf (guint32* code, guint32 lmf_offset);
......
......@@ -48,20 +48,25 @@ static gpointer
get_unbox_trampoline (MonoMethod *m, gpointer addr)
{
guint8 *code, *start;
int this_pos = 4;
int this_pos = 4, reg;
if (!m->signature->ret->byref && MONO_TYPE_ISSTRUCT (m->signature->ret))
this_pos = 8;
start = code = g_malloc (32);
start = code = g_malloc (36);
/* This executes in the context of the caller, hence o0 */
sparc_add_imm (code, 0, sparc_o0, sizeof (MonoObject), sparc_o0);
sparc_set (code, addr, sparc_g1);
sparc_jmpl (code, sparc_g1, sparc_g0, sparc_g0);
#ifdef SPARCV9
reg = sparc_g4;
#else
reg = sparc_g1;
#endif
sparc_set (code, addr, reg);
sparc_jmpl (code, reg, sparc_g0, sparc_g0);
sparc_nop (code);
g_assert ((code - start) <= 32);
g_assert ((code - start) <= 36);
mono_arch_flush_icache (start, code - start);
......@@ -118,11 +123,13 @@ sparc_class_init_trampoline (MonoVTable *vtable, guint32 *code)
sparc_nop (code);
}
#define ALIGN_TO(val,align) (((val) + ((align) - 1)) & ~((align) - 1))
static guchar*
create_trampoline_code (MonoTrampolineType tramp_type)
{
guint8 *buf, *code, *tramp_addr;
guint32 lmf_offset;
guint32 lmf_offset, method_reg, i;
static guint8* generic_jump_trampoline = NULL;
static guint8 *generic_class_init_trampoline = NULL;
......@@ -141,33 +148,44 @@ create_trampoline_code (MonoTrampolineType tramp_type)
break;
}
code = buf = g_malloc (256);
code = buf = g_malloc (512);
sparc_save_imm (code, sparc_sp, -608, sparc_sp);
/* FIXME: save lmf etc */
#ifdef SPARCV9
method_reg = sparc_g4;
#else
method_reg = sparc_g1;
#endif
sparc_save_imm (code, sparc_sp, -200, sparc_sp);
#ifdef SPARCV9
/* Save fp regs since they are not preserved by calls */
for (i = 0; i < 16; i ++)
sparc_stdf_imm (code, sparc_f0 + (i * 2), sparc_sp, MONO_SPARC_STACK_BIAS + 320 + (i * 8));
#endif
/* We receive the method address in %r1, so save it here */
sparc_st_imm (code, sparc_g1, sparc_sp, 128);
sparc_sti_imm (code, method_reg, sparc_sp, MONO_SPARC_STACK_BIAS + 200);
/* Save lmf since compilation can raise exceptions */
lmf_offset = - sizeof (MonoLMF);
lmf_offset = MONO_SPARC_STACK_BIAS - sizeof (MonoLMF);
/* Save the data for the parent (managed) frame */
/* Save ip */
sparc_st_imm (code, sparc_i7, sparc_fp, lmf_offset + G_STRUCT_OFFSET (MonoLMF, ip));
sparc_sti_imm (code, sparc_i7, sparc_fp, lmf_offset + G_STRUCT_OFFSET (MonoLMF, ip));
/* Save sp */
sparc_st_imm (code, sparc_fp, sparc_fp, lmf_offset + G_STRUCT_OFFSET (MonoLMF, sp));
sparc_sti_imm (code, sparc_fp, sparc_fp, lmf_offset + G_STRUCT_OFFSET (MonoLMF, sp));
/* Save fp */
/* Load previous fp from the saved register window */
sparc_flushw (code);
sparc_ld_imm (code, sparc_fp, (sparc_i6 - 16) * 4, sparc_o7);
sparc_st_imm (code, sparc_o7, sparc_fp, lmf_offset + G_STRUCT_OFFSET (MonoLMF, ebp));
sparc_ldi_imm (code, sparc_fp, MONO_SPARC_STACK_BIAS + (sparc_i6 - 16) * sizeof (gpointer), sparc_o7);
sparc_sti_imm (code, sparc_o7, sparc_fp, lmf_offset + G_STRUCT_OFFSET (MonoLMF, ebp));
/* Save method */
sparc_st_imm (code, sparc_g1, sparc_fp, lmf_offset + G_STRUCT_OFFSET (MonoLMF, method));
sparc_sti_imm (code, method_reg, sparc_fp, lmf_offset + G_STRUCT_OFFSET (MonoLMF, method));
sparc_call_simple (code, (guint8*)mono_get_lmf_addr - (guint8*)code);
sparc_set (code, mono_get_lmf_addr, sparc_o7);
sparc_jmpl (code, sparc_o7, sparc_g0, sparc_o7);
sparc_nop (code);
code = mono_sparc_emit_save_lmf (code, lmf_offset);
......@@ -176,21 +194,29 @@ create_trampoline_code (MonoTrampolineType tramp_type)
tramp_addr = &sparc_class_init_trampoline;
else
tramp_addr = &sparc_magic_trampoline;
sparc_ld_imm (code, sparc_sp, 128, sparc_o0);
sparc_ldi_imm (code, sparc_sp, MONO_SPARC_STACK_BIAS + 200, sparc_o0);
/* pass parent frame address as third argument */
sparc_mov_reg_reg (code, sparc_fp, sparc_o2);
sparc_call_simple (code, tramp_addr - code);
/* set %o1 to caller address in delay slot */
sparc_set (code, tramp_addr, sparc_o7);
/* set %o1 to caller address */
sparc_mov_reg_reg (code, sparc_i7, sparc_o1);
sparc_jmpl (code, sparc_o7, sparc_g0, sparc_o7);
sparc_nop (code);
/* Save result */
sparc_st_imm (code, sparc_o0, sparc_sp, 128);
sparc_sti_imm (code, sparc_o0, sparc_sp, MONO_SPARC_STACK_BIAS + 304);
/* Restore lmf */
code = mono_sparc_emit_restore_lmf (code, lmf_offset);
/* Reload result */
sparc_ld_imm (code, sparc_sp, 128, sparc_o0);
sparc_ldi_imm (code, sparc_sp, MONO_SPARC_STACK_BIAS + 304, sparc_o0);
#ifdef SPARCV9
/* Reload fp regs */
for (i = 0; i < 16; i ++)
sparc_lddf_imm (code, sparc_sp, MONO_SPARC_STACK_BIAS + 320 + (i * 8), sparc_f0 + (i * 2));
#endif
if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT)
sparc_ret (code);
......@@ -200,7 +226,28 @@ create_trampoline_code (MonoTrampolineType tramp_type)
/* restore previous frame in delay slot */
sparc_restore_simple (code);
g_assert ((code - buf) <= 256);
/*
{
gpointer addr;
sparc_save_imm (code, sparc_sp, -608, sparc_sp);
addr = code;
sparc_call_simple (code, 16);
sparc_nop (code);
sparc_rett_simple (code);
sparc_nop (code);
sparc_save_imm (code, sparc_sp, -608, sparc_sp);
sparc_ta (code, 1);
tramp_addr = &sparc_magic_trampoline;
sparc_call_simple (code, tramp_addr - code);
sparc_nop (code);
sparc_rett_simple (code);
sparc_nop (code);
}
*/
g_assert ((code - buf) <= 512);
switch (tramp_type) {
case MONO_TRAMPOLINE_GENERIC:
......@@ -222,18 +269,24 @@ create_trampoline_code (MonoTrampolineType tramp_type)
#define TRAMPOLINE_SIZE (((SPARC_SET_MAX_SIZE >> 2) * 2) + 2)
static MonoJitInfo*
create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type)
create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain)
{
MonoJitInfo *ji;
guint32 *code, *buf, *tramp;
tramp = create_trampoline_code (tramp_type);
code = buf = g_malloc (TRAMPOLINE_SIZE * 4);
mono_domain_lock (domain);
code = buf = mono_code_manager_reserve (domain->code_mp, TRAMPOLINE_SIZE * 4);
mono_domain_unlock (domain);
/* We have to use g5 here because there is no other free register */
sparc_set (code, tramp, sparc_g5);
sparc_set (code, arg1, sparc_r1);
#ifdef SPARCV9
sparc_set (code, arg1, sparc_g4);
#else
sparc_set (code, arg1, sparc_g1);
#endif
sparc_jmpl (code, sparc_g5, sparc_g0, sparc_g0);
sparc_nop (code);
......@@ -253,7 +306,7 @@ create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type)
MonoJitInfo*
mono_arch_create_jump_trampoline (MonoMethod *method)
{
MonoJitInfo *ji = create_specific_trampoline (method, MONO_TRAMPOLINE_JUMP);
MonoJitInfo *ji = create_specific_trampoline (method, MONO_TRAMPOLINE_JUMP, mono_domain_get ());
ji->method = method;
return ji;
......@@ -282,7 +335,7 @@ mono_arch_create_jit_trampoline (MonoMethod *method)
if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
return mono_arch_create_jit_trampoline (mono_marshal_get_synchronized_wrapper (method));
ji = create_specific_trampoline (method, MONO_TRAMPOLINE_GENERIC);
ji = create_specific_trampoline (method, MONO_TRAMPOLINE_GENERIC, mono_domain_get ());
method->info = ji->code_start;
g_free (ji);
......@@ -306,7 +359,7 @@ mono_arch_create_class_init_trampoline (MonoVTable *vtable)
MonoJitInfo *ji;
gpointer code;
ji = create_specific_trampoline (vtable, MONO_TRAMPOLINE_CLASS_INIT);
ji = create_specific_trampoline (vtable, MONO_TRAMPOLINE_CLASS_INIT, vtable->domain);
code = ji->code_start;
g_free (ji);
......@@ -322,10 +375,10 @@ mono_debugger_create_notification_function (gpointer *notification_address)
guint8 *ptr, *buf;
ptr = buf = g_malloc0 (16);
//x86_breakpoint (buf);
if (notification_address)
*notification_address = buf;
//x86_ret (buf);
g_assert_not_reached ();
return ptr;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册