Mon Feb 11 18:40:04 CET 2002 Paolo Molaro <lupus@ximian.com>
authorPaolo Molaro <lupus@oddwiz.org>
Mon, 11 Feb 2002 13:49:06 +0000 (13:49 -0000)
committerPaolo Molaro <lupus@oddwiz.org>
Mon, 11 Feb 2002 13:49:06 +0000 (13:49 -0000)
* sparc/*: sparc codegen header and some untested trampoline code.

svn path=/trunk/mono/; revision=2315

mono/arch/ChangeLog
mono/arch/Makefile.am
mono/arch/sparc/Makefile.am [new file with mode: 0644]
mono/arch/sparc/sparc-codegen.h [new file with mode: 0644]
mono/arch/sparc/test.c [new file with mode: 0644]
mono/arch/sparc/tramp.c [new file with mode: 0644]

index a85e8658e459a98c1a658dcbff9b4c3b9e1e7a16..10a73f6b265d582ceb16b5f555d053217c8550a7 100644 (file)
@@ -1,4 +1,8 @@
 
+Mon Feb 11 18:40:04 CET 2002 Paolo Molaro <lupus@ximian.com>
+
+       * sparc/*: sparc codegen header and some untested trampoline code.
+
 Mon Feb 11 12:32:35 CET 2002 Paolo Molaro <lupus@ximian.com>
 
        * x86/tramp.c: fix handling of multiple marshaleed strings.
index 36a9c0e713b928823a431046e1afc6f428523322..fc760391b8b6522f68b3eda84053740cda758080 100644 (file)
@@ -1,5 +1,5 @@
 SUBDIRS = $(arch_target)
-DIST_SUBDIRS = x86 ppc
+DIST_SUBDIRS = x86 ppc sparc
 
 INCLUDES = $(GLIB_CFLAGS) -I$(top_srcdir)
 
diff --git a/mono/arch/sparc/Makefile.am b/mono/arch/sparc/Makefile.am
new file mode 100644 (file)
index 0000000..e0f7689
--- /dev/null
@@ -0,0 +1,7 @@
+
+INCLUDES = $(GLIB_CFLAGS) -I$(top_srcdir)
+
+noinst_LTLIBRARIES = libmonoarch-sparc.la
+
+libmonoarch_sparc_la_SOURCES = tramp.c sparc-codegen.h
+
diff --git a/mono/arch/sparc/sparc-codegen.h b/mono/arch/sparc/sparc-codegen.h
new file mode 100644 (file)
index 0000000..04a23c3
--- /dev/null
@@ -0,0 +1,486 @@
+#ifndef __SPARC_CODEGEN_H__
+#define __SPARC_CODEGEN_H__
+
+typedef enum {
+       sparc_r0 = 0,
+       sparc_r1 = 1,
+       sparc_r2 = 2,
+       sparc_r3 = 3,
+       sparc_r4 = 4,
+       sparc_r5 = 5,
+       sparc_r6 = 6,
+       sparc_r7 = 7,
+       sparc_r8 = 8,
+       sparc_r9 = 9,
+       sparc_r10 = 10,
+       sparc_r11 = 11,
+       sparc_r12 = 12,
+       sparc_r13 = 13,
+       sparc_r14 = 14,
+       sparc_r15 = 15,
+       sparc_r16 = 16,
+       sparc_r17 = 17,
+       sparc_r18 = 18,
+       sparc_r19 = 19,
+       sparc_r20 = 20,
+       sparc_r21 = 21,
+       sparc_r22 = 22,
+       sparc_r23 = 23,
+       sparc_r24 = 24,
+       sparc_r25 = 25,
+       sparc_r26 = 26,
+       sparc_r27 = 27,
+       sparc_r28 = 28,
+       sparc_r29 = 29,
+       sparc_r30 = 30,
+       sparc_r31 = 31,
+       /* aliases */
+       /* global registers */
+       sparc_g0 = 0, sparc_zero = 0,
+       sparc_g1 = 1,
+       sparc_g2 = 2,
+       sparc_g3 = 3,
+       sparc_g4 = 4,
+       sparc_g5 = 5,
+       sparc_g6 = 6,
+       sparc_g7 = 7,
+       /* out registers */
+       sparc_o0 = 8,
+       sparc_o1 = 9,
+       sparc_o2 = 10,
+       sparc_o3 = 11,
+       sparc_o4 = 12,
+       sparc_o5 = 13,
+       sparc_o6 = 14, sparc_sp = 14,
+       sparc_o7 = 15, sparc_callsite = 15,
+       /* local registers */
+       sparc_l0 = 16,
+       sparc_l1 = 17,
+       sparc_l2 = 18,
+       sparc_l3 = 19,
+       sparc_l4 = 20,
+       sparc_l5 = 21,
+       sparc_l6 = 22,
+       sparc_l7 = 23,
+       /* in registers */
+       sparc_i0 = 24,
+       sparc_i1 = 25,
+       sparc_i2 = 26,
+       sparc_i3 = 27,
+       sparc_i4 = 28,
+       sparc_i5 = 29,
+       sparc_i6 = 30, sparc_fp = 30,
+       sparc_i7 = 31,
+       sparc_nreg = 32,
+       /* floating point registers */
+       sparc_f0 = 0,
+       sparc_f1 = 1,
+       sparc_f2 = 2,
+       sparc_f3 = 3,
+       sparc_f4 = 4,
+       sparc_f5 = 5,
+       sparc_f6 = 6,
+       sparc_f7 = 7,
+       sparc_f8 = 8,
+       sparc_f9 = 9,
+       sparc_f10 = 10,
+       sparc_f11 = 11,
+       sparc_f12 = 12,
+       sparc_f13 = 13,
+       sparc_f14 = 14,
+       sparc_f15 = 15,
+       sparc_f16 = 16,
+       sparc_f17 = 17,
+       sparc_f18 = 18,
+       sparc_f19 = 19,
+       sparc_f20 = 20,
+       sparc_f21 = 21,
+       sparc_f22 = 22,
+       sparc_f23 = 23,
+       sparc_f24 = 24,
+       sparc_f25 = 25,
+       sparc_f26 = 26,
+       sparc_f27 = 27,
+       sparc_f28 = 28,
+       sparc_f29 = 29,
+       sparc_f30 = 30,
+       sparc_f31 = 31,
+} SparcRegister;
+
+typedef enum {
+       sparc_bn   = 0, sparc_bnever = 0,
+       sparc_be   = 1,
+       sparc_ble  = 2,
+       sparc_bl   = 3,
+       sparc_bleu = 4,
+       sparc_bcs  = 5, sparc_blu = 5,
+       sparc_bneg = 6,
+       sparc_bvs  = 7, sparc_boverflow = 7,
+       sparc_ba   = 8, sparc_balways = 8,
+       sparc_bne  = 9,
+       sparc_bg   = 10,
+       sparc_bge  = 11,
+       sparc_bgu  = 12,
+       sparc_bcc  = 13, sparc_beu = 13,
+       sparc_bpos = 14,
+       sparc_bvc  = 15
+} SparcCond;
+
+typedef enum {
+       /* with fcmp */
+       sparc_feq = 0,
+       sparc_fl  = 1,
+       sparc_fg  = 2,
+       sparc_unordered = 3,
+       /* branch ops */
+       sparc_fba   = 8,
+       sparc_fbn   = 0,
+       sparc_fbu   = 7,
+       sparc_fbg   = 6,
+       sparc_fbug  = 5,
+       sparc_fbl   = 4,
+       sparc_fbul  = 3,
+       sparc_fblg  = 2,
+       sparc_fbne  = 1,
+       sparc_fbe   = 9,
+       sparc_fbue  = 10,
+       sparc_fbge  = 11,
+       sparc_fbuge = 12,
+       sparc_fble  = 13,
+       sparc_fbule = 14,
+       sparc_fbo   = 15
+} SparcFCond;
+
+typedef enum {
+       /* fop1 format */
+       sparc_fitos = 196,
+       sparc_fitod = 200,
+       sparc_fstoi = 209,
+       sparc_fdtoi = 210,
+       sparc_fstod = 201,
+       sparc_fdtos = 198,
+       sparc_fmov  = 1,
+       sparc_fneg  = 5,
+       sparc_fabs  = 9,
+       sparc_fsqrts = 41,
+       sparc_fsqrtd = 42,
+       sparc_fadds  = 65,
+       sparc_faddd  = 66,
+       sparc_fsubs  = 69,
+       sparc_fsubd  = 70,
+       sparc_fmuls  = 73,
+       sparc_fmuld  = 74,
+       sparc_fdivs  = 77,
+       sparc_fdivd  = 78,
+       /* fop2 format */
+       sparc_fcmps  = 81,
+       sparc_fcmpd  = 82
+} SparcFOp;
+
+typedef struct {
+       unsigned int op   : 2; /* always 1 */
+       unsigned int disp : 30;
+} sparc_format1;
+
+typedef struct {
+       unsigned int op   : 2; /* always 0 */
+       unsigned int rd   : 5;
+       unsigned int op2  : 3;
+       unsigned int disp : 22;
+} sparc_format2a;
+
+typedef struct {
+       unsigned int op   : 2; /* always 0 */
+       unsigned int a    : 1;
+       unsigned int cond : 4;
+       unsigned int op2  : 3;
+       unsigned int disp : 22;
+} sparc_format2b;
+
+typedef struct {
+       unsigned int op   : 2; /* 2 or 3 */
+       unsigned int rd   : 5;
+       unsigned int op3  : 6;
+       unsigned int rs1  : 5;
+       unsigned int i    : 1;
+       unsigned int asi  : 8;
+       unsigned int rs2  : 5;
+} sparc_format3a;
+
+typedef struct {
+       unsigned int op   : 2; /* 2 or 3 */
+       unsigned int rd   : 5;
+       unsigned int op3  : 6;
+       unsigned int rs1  : 5;
+       unsigned int i    : 1;
+       unsigned int imm  : 13;
+} sparc_format3b;
+
+typedef struct {
+       unsigned int op   : 2; /* 2 or 3 */
+       unsigned int rd   : 5;
+       unsigned int op3  : 6;
+       unsigned int rs1  : 5;
+       unsigned int opf  : 9;
+       unsigned int rs2  : 5;
+} sparc_format3c;
+
+/* for use in logical ops, use 0 to not set flags */
+#define sparc_cc 16
+
+#define sparc_encode_call(ins,addr) \
+       do {    \
+               sparc_format1 *__f = (sparc_format1*)(ins);     \
+               __f->op = 1;    \
+               __f->disp = ((unsigned int)(addr) >> 2);        \
+               (ins) = (unsigned int*)__f + 1; \
+       } while (0)
+
+#define sparc_encode_format2a(ins,val,oper,dest) \
+       do {    \
+               sparc_format2a *__f = (sparc_format2a*)(ins);   \
+               __f->op = 0;    \
+               __f->rd = (dest);       \
+               __f->op2 = (oper);      \
+               __f->disp = (val) & 0x3fffff;   \
+               (ins) = (unsigned int*)__f + 1; \
+       } while (0)
+
+#define sparc_encode_format2b(ins,aval,bcond,oper,disp22) \
+       do {    \
+               sparc_format2b *__f = (sparc_format2b*)(ins);   \
+               __f->op = 0;    \
+               __f->a = (aval);        \
+               __f->cond = (bcond);    \
+               __f->op2 = (oper);      \
+               __f->disp = (disp22);   \
+               (ins) = (unsigned int*)__f + 1; \
+       } while (0)
+
+#define sparc_encode_format3a(ins,opval,asival,r1,r2,oper,dest) \
+       do {    \
+               sparc_format3a *__f = (sparc_format3a*)(ins);   \
+               __f->op = (opval);      \
+               __f->asi = (asival);    \
+               __f->i = 0;     \
+               __f->rd = (dest);       \
+               __f->rs1 = (r1);        \
+               __f->rs2 = (r2);        \
+               __f->op3 = (oper);      \
+               (ins) = (unsigned int*)__f + 1; \
+       } while (0)
+
+#define sparc_encode_format3b(ins,opval,r1,val,oper,dest) \
+       do {    \
+               sparc_format3b *__f = (sparc_format3b*)(ins);   \
+               __f->op = (opval);      \
+               __f->imm = (val);       \
+               __f->i = 1;     \
+               __f->rd = (dest);       \
+               __f->rs1 = (r1);        \
+               __f->op3 = (oper);      \
+               (ins) = (unsigned int*)__f + 1; \
+       } while (0)
+
+#define sparc_encode_format3c(ins,opval,opfval,r1,oper,r2,dest) \
+       do {    \
+               sparc_format3c *__f = (sparc_format3c*)(ins);   \
+               __f->op = (opval);      \
+               __f->opf = (opfval);    \
+               __f->rd = (dest);       \
+               __f->rs1 = (r1);        \
+               __f->rs2 = (r2);        \
+               __f->op3 = (oper);      \
+               (ins) = (unsigned int*)__f + 1; \
+       } while (0)
+
+/* is it useful to provide a non-default value? */
+#define sparc_asi 0x0
+
+/* load */
+#define sparc_ldsb(ins,base,disp,dest) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),9,(dest))
+#define sparc_ldsb_imm(ins,base,disp,dest) sparc_encode_format3b((ins),3,(base),(disp),9,(dest))
+
+#define sparc_ldsh(ins,base,disp,dest) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),10,(dest))
+#define sparc_ldsh_imm(ins,base,disp,dest) sparc_encode_format3b((ins),3,(base),(disp),10,(dest))
+
+#define sparc_ldub(ins,base,disp,dest) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),1,(dest))
+#define sparc_ldub_imm(ins,base,disp,dest) sparc_encode_format3b((ins),3,(base),(disp),1,(dest))
+
+#define sparc_lduh(ins,base,disp,dest) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),2,(dest))
+#define sparc_lduh_imm(ins,base,disp,dest) sparc_encode_format3b((ins),3,(base),(disp),2,(dest))
+
+#define sparc_ld(ins,base,disp,dest) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),0,(dest))
+#define sparc_ld_imm(ins,base,disp,dest) sparc_encode_format3b((ins),3,(base),(disp),0,(dest))
+
+#define sparc_ldd(ins,base,disp,dest) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),3,(dest))
+#define sparc_ldd_imm(ins,base,disp,dest) sparc_encode_format3b((ins),3,(base),(disp),3,(dest))
+
+#define sparc_ldf(ins,base,disp,dest) sparc_encode_format3a((ins),3,0,(base),(disp),32,(dest))
+#define sparc_ldf_imm(ins,base,disp,dest) sparc_encode_format3b((ins),3,(base),(disp),32,(dest))
+
+#define sparc_lddf(ins,base,disp,dest) sparc_encode_format3a((ins),3,0,(base),(disp),35,(dest))
+#define sparc_lddf_imm(ins,base,disp,dest) sparc_encode_format3b((ins),3,(base),(disp),35,(dest))
+
+/* store */
+#define sparc_stb(ins,src,base,disp) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),5,(src))
+#define sparc_stb_imm(ins,src,base,disp) sparc_encode_format3b((ins),3,(base),(disp),5,(src))
+
+#define sparc_sth(ins,src,base,disp) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),6,(src))
+#define sparc_sth_imm(ins,src,base,disp) sparc_encode_format3b((ins),3,(base),(disp),6,(src))
+
+#define sparc_st(ins,src,base,disp) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),4,(src))
+#define sparc_st_imm(ins,src,base,disp) sparc_encode_format3b((ins),3,(base),(disp),4,(src))
+
+#define sparc_std(ins,src,base,disp) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),7,(src))
+#define sparc_std_imm(ins,src,base,disp) sparc_encode_format3b((ins),3,(base),(disp),7,(src))
+
+#define sparc_stf(ins,src,base,disp) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),36,(src))
+#define sparc_stf_imm(ins,src,base,disp) sparc_encode_format3b((ins),3,(base),(disp),36,(src))
+
+#define sparc_stdf(ins,src,base,disp) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),39,(src))
+#define sparc_stdf_imm(ins,src,base,disp) sparc_encode_format3b((ins),3,(base),(disp),39,(src))
+
+/* swap */
+#define sparc_ldstub(ins,base,disp,dest) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),13,(dest))
+#define sparc_ldstub_imm(ins,base,disp,dest) sparc_encode_format3b((ins),3,(base),(disp),13,(dest))
+
+#define sparc_swap(ins,base,disp,dest) sparc_encode_format3a((ins),3,sparc_asi,(base),(disp),15,(dest))
+#define sparc_swap_imm(ins,base,disp,dest) sparc_encode_format3b((ins),3,(base),(disp),15,(dest))
+
+/* misc */
+/* note: with sethi val is the full 32 bit value (think of it as %hi(val)) */
+#define sparc_sethi(ins,val,dest) sparc_encode_format2a((ins),((val)>>10),4,(dest))
+
+#define sparc_nop(ins) sparc_sethi((ins),0,sparc_zero)
+
+#define sparc_save(ins,src,disp,dest) sparc_encode_format3a((ins),2,0,(src),(disp),60,(dest))
+#define sparc_save_imm(ins,src,disp,dest) sparc_encode_format3b((ins),2,(src),(disp),60,(dest))
+
+#define sparc_restore(ins,src,disp,dest) sparc_encode_format3a((ins),2,0,(src),(disp),61,(dest))
+#define sparc_restore_imm(ins,src,disp,dest) sparc_encode_format3b((ins),2,(src),(disp),61,(dest))
+
+#define sparc_jmpl(ins,base,disp,dest) sparc_encode_format3a((ins),2,0,(base),(disp),56,(dest))
+#define sparc_jmpl_imm(ins,base,disp,dest) sparc_encode_format3b((ins),2,(base),(disp),56,(dest))
+
+#define sparc_call_simple(ins,addr) sparc_encode_call((ins),((unsigned int)(addr)>>2))
+
+#define sparc_rdy(ins,dest) sparc_encode_format3a((ins),2,0,0,0,40,(dest))
+
+#define sparc_wry(ins,base,disp) sparc_encode_format3a((ins),2,0,(base),(disp),48,0)
+#define sparc_wry_imm(ins,base,disp) sparc_encode_format3b((ins),2,(base),(disp),48,0)
+
+/* stbar, unimp, flush */
+#define sparc_stbar(ins) sparc_encode_format3a((ins),2,0,15,0,40,0)
+#define sparc_unimp(ins,val) sparc_encode_format2b((ins),0,0,0,(val))
+
+#define sparc_flush(ins,base,disp) sparc_encode_format3a((ins),2,0,(base),(disp),59,0)
+#define sparc_flush_imm(ins,base,disp) sparc_encode_format3b((ins),2,(base),(disp),59,0)
+
+/* trap */
+
+/* alu fop */
+/* provide wrappers for: fitos, fitod, fstoi, fdtoi, fstod, fdtos, fmov, fneg, fabs */
+
+#define sparc_fop(ins,r1,op,r2,dest) sparc_encode_format3c((ins),2,(op),(r1),52,(r2),(dest))
+#define sparc_fcmp(ins,r1,op,r2) sparc_encode_format3c((ins),2,(op),(r1),53,(r2),0)
+
+/* logical */
+#define sparc_and(ins,setcc,r1,r2,dest) sparc_encode_format3a((ins),2,0,(r1),(r2),(setcc)|1,(dest))
+#define sparc_and_imm(ins,setcc,r1,imm,dest) sparc_encode_format3b((ins),2,(r1),(imm),(setcc)|1,(dest))
+
+#define sparc_andn(ins,setcc,r1,r2,dest) sparc_encode_format3a((ins),2,0,(r1),(r2),(setcc)|5,(dest))
+#define sparc_andn_imm(ins,setcc,r1,imm,dest) sparc_encode_format3b((ins),2,(r1),(imm),(setcc)|5,(dest))
+
+#define sparc_or(ins,setcc,r1,r2,dest) sparc_encode_format3a((ins),2,0,(r1),(r2),(setcc)|2,(dest))
+#define sparc_or_imm(ins,setcc,r1,imm,dest) sparc_encode_format3b((ins),2,(r1),(imm),(setcc)|2,(dest))
+
+#define sparc_orn(ins,setcc,r1,r2,dest) sparc_encode_format3a((ins),2,0,(r1),(r2),(setcc)|6,(dest))
+#define sparc_orn_imm(ins,setcc,r1,imm,dest) sparc_encode_format3b((ins),2,(r1),(imm),(setcc)|6,(dest))
+
+#define sparc_xor(ins,setcc,r1,r2,dest) sparc_encode_format3a((ins),2,0,(r1),(r2),(setcc)|3,(dest))
+#define sparc_xor_imm(ins,setcc,r1,imm,dest) sparc_encode_format3b((ins),2,(r1),(r2),(imm)|3,(dest))
+
+#define sparc_xnor(ins,setcc,r1,r2,dest) sparc_encode_format3a((ins),2,0,(r1),(r2),(setcc)|7,(dest))
+#define sparc_xnor_imm(ins,setcc,r1,imm,dest) sparc_encode_format3b((ins),2,(r1),(imm),(setcc)|7,(dest))
+
+/* shift */
+#define sparc_sll(ins,src,disp,dest) sparc_encode_format3a((ins),2,0,(src),(disp),37,(dest))
+#define sparc_sll_imm(ins,src,disp,dest) sparc_encode_format3b((ins),2,(src),(disp),37,(dest))
+
+#define sparc_srl(ins,src,disp,dest) sparc_encode_format3a((ins),2,0,(src),(disp),38,(dest))
+#define sparc_srl_imm(ins,src,disp,dest) sparc_encode_format3b((ins),2,(src),(disp),38,(dest))
+
+#define sparc_sra(ins,src,disp,dest) sparc_encode_format3a((ins),2,0,(src),(disp),39,(dest))
+#define sparc_sra_imm(ins,src,disp,dest) sparc_encode_format3b((ins),2,(src),(disp),39,(dest))
+
+/* alu */
+#define sparc_add(ins,setcc,r1,r2,dest) sparc_encode_format3a((ins),2,0,(r1),(r2),(setcc)|0,(dest))
+#define sparc_add_imm(ins,setcc,r1,imm,dest) sparc_encode_format3b((ins),2,(r1),(imm),(setcc)|0,(dest))
+
+#define sparc_addx(ins,setcc,r1,r2,dest) sparc_encode_format3a((ins),2,0,(r1),(r2),(setcc)|8,(dest))
+#define sparc_addx_imm(ins,setcc,r1,imm,dest) sparc_encode_format3b((ins),2,(r1),(imm),(setcc)|8,(dest))
+
+#define sparc_sub(ins,setcc,r1,r2,dest) sparc_encode_format3a((ins),2,0,(r1),(r2),(setcc)|4,(dest))
+#define sparc_sub_imm(ins,setcc,r1,imm,dest) sparc_encode_format3b((ins),2,(r1),(imm),(setcc)|4,(dest))
+
+#define sparc_subx(ins,setcc,r1,r2,dest) sparc_encode_format3a((ins),2,0,(r1),(r2),(setcc)|12,(dest))
+#define sparc_subx_imm(ins,setcc,r1,imm,dest) sparc_encode_format3b((ins),2,(r1),(imm),(setcc)|12,(dest))
+
+#define sparc_muls(ins,r1,r2,dest) sparc_encode_format3a((ins),2,0,(r1),(r2),36,(dest))
+#define sparc_muls_imm(ins,r1,imm,dest) sparc_encode_format3b((ins),2,(r1),(imm),36,(dest))
+
+#define sparc_umul(ins,setcc,r1,r2,dest) sparc_encode_format3a((ins),2,0,(r1),(r2),(setcc)|10,(dest))
+#define sparc_umul_imm(ins,setcc,r1,imm,dest) sparc_encode_format3b((ins),2,(r1),(imm),(setcc)|10,(dest))
+
+#define sparc_smul(ins,setcc,r1,r2,dest) sparc_encode_format3a((ins),2,0,(r1),(r2),(setcc)|11,(dest))
+#define sparc_smul_imm(ins,setcc,r1,imm,dest) sparc_encode_format3b((ins),2,(r1),(imm),(setcc)|11,(dest))
+
+#define sparc_udiv(ins,setcc,r1,r2,dest) sparc_encode_format3a((ins),2,0,(r1),(r2),(setcc)|14,(dest))
+#define sparc_udiv_imm(ins,setcc,r1,imm,dest) sparc_encode_format3b((ins),2,(r1),(imm),(setcc)|14,(dest))
+
+#define sparc_sdiv(ins,setcc,r1,r2,dest) sparc_encode_format3a((ins),2,0,(r1),(r2),(setcc)|15,(dest))
+#define sparc_sdiv_imm(ins,setcc,r1,imm,dest) sparc_encode_format3b((ins),2,(r1),(imm),(setcc)|15,(dest))
+
+
+/* branch */
+#define sparc_branch(ins,aval,condval,displ) sparc_encode_format2b((ins),(aval),(condval),2,(displ))
+/* FIXME: float condition codes are different: unify. */
+#define sparc_fbranch(ins,aval,condval,displ) sparc_encode_format2b((ins),(aval),(condval),6,(displ))
+
+/* synthetic instructions */
+#define sparc_cmp(ins,r1,r2) sparc_sub((ins),sparc_cc,(r1),(r2),sparc_g0)
+#define sparc_cmp_imm(ins,r1,imm) sparc_sub_imm((ins),sparc_cc,(r1),(imm),sparc_g0)
+
+#define sparc_jmp(ins,base,disp) sparc_jmpl((ins),(base),(disp),sparc_g0)
+#define sparc_jmp_imm(ins,base,disp) sparc_jmpl_imm((ins),(base),(disp),sparc_g0)
+#define sparc_call(ins,base,disp) sparc_jmpl((ins),(base),(disp),sparc_o7)
+#define sparc_call_imm(ins,base,disp) sparc_jmpl_imm((ins),(base),(disp),sparc_o7)
+
+#define sparc_test(ins,reg) sparc_or ((ins),sparc_cc,sparc_g0,(reg),sparc_g0)
+
+#define sparc_ret(ins) sparc_jmpl_imm((ins),sparc_i7,8,sparc_g0)
+#define sparc_retl(ins) sparc_jmpl_imm((ins),sparc_o7,8,sparc_g0)
+#define sparc_restore_simple(ins) sparc_restore((ins),sparc_g0,sparc_g0,sparc_g0)
+
+#define sparc_set(ins,val,reg) \
+       do {    \
+               if (((val) & 0x1fff) == 0)      \
+                       sparc_sethi((ins),(val),(reg)); \
+               else if (((val) >= -4096) && ((val) <= 4095))   \
+                       sparc_or_imm((ins),FALSE,sparc_g0,(val),(reg)); \
+               else {  \
+                       sparc_sethi((ins),(val),(reg)); \
+                       sparc_or_imm((ins),FALSE,(reg),(val)&0x3ff,(reg));      \
+               }       \
+       } while (0)
+
+#define sparc_not(ins,reg) sparc_xnor((ins),FALSE,(reg),sparc_g0,(reg))
+#define sparc_neg(ins,reg) sparc_sub((ins),FALSE,sparc_g0,(reg),(reg))
+#define sparc_clr_reg(ins,reg) sparc_or((ins),FALSE,sparc_g0,sparc_g0,(reg))
+
+#define sparc_mov_reg_reg(ins,src,dest) sparc_or_imm((ins),FALSE,(src),0,(dest))
+
+
+#endif /* __SPARC_CODEGEN_H__ */
+
diff --git a/mono/arch/sparc/test.c b/mono/arch/sparc/test.c
new file mode 100644 (file)
index 0000000..0d4ad18
--- /dev/null
@@ -0,0 +1,123 @@
+#include <glib.h>
+#include "sparc-codegen.h"
+
+/* don't run the resulting program, it will destroy your computer,
+ * just objdump -d it to inspect we generated the correct assembler.
+ */
+
+int
+main ()
+{
+       guint32 *p;
+       guint32 code_buffer [500];
+       guint32 local_size = 0, stack_size = 0, code_size = 6;
+       guint32 arg_pos, simpletype;
+       unsigned char *ins;
+       int i, stringp, cur_out_reg, size;
+
+       p = code_buffer;
+
+       printf (".text\n.align 4\n.globl main\n.type main,@function\nmain:\n");
+
+       /*
+        * Standard function prolog.
+        */
+       sparc_save_imm (p, sparc_sp, -112-stack_size, sparc_sp);
+       cur_out_reg = sparc_o0;
+       arg_pos = 0;
+
+       if (1) {
+               sparc_mov_reg_reg (p, sparc_i2, cur_out_reg);
+               ++cur_out_reg;
+       }
+
+       sparc_ld_imm (p, sparc_i3, arg_pos, cur_out_reg);
+       ++cur_out_reg;
+       sparc_ld_imm (p, sparc_i3, arg_pos+4, cur_out_reg);
+       ++cur_out_reg;
+       /* 
+        * Insert call to function 
+        */
+       sparc_jmpl (p, sparc_i0, 0, sparc_callsite);
+       sparc_nop (p);
+
+       sparc_jmpl_imm (p, sparc_i7, 8, sparc_zero);
+       sparc_restore (p, sparc_zero, sparc_zero, sparc_zero);
+
+       sparc_ldsb (p, sparc_i3, sparc_l0, sparc_o5);
+       sparc_ldsb_imm (p, sparc_i3, 2, sparc_o5);
+
+       sparc_ldsh (p, sparc_i3, sparc_l0, sparc_o5);
+       sparc_ldsh_imm (p, sparc_i3, 2, sparc_o5);
+
+       sparc_ldub (p, sparc_i3, sparc_l0, sparc_o5);
+       sparc_ldub_imm (p, sparc_i3, 2, sparc_o5);
+
+       sparc_lduh (p, sparc_i3, sparc_l0, sparc_o5);
+       sparc_lduh_imm (p, sparc_i3, 2, sparc_o5);
+
+       sparc_ldf (p, sparc_i3, sparc_l0, sparc_o5);
+       sparc_ldf_imm (p, sparc_i3, 2, sparc_o5);
+
+       sparc_stb (p, sparc_i3, sparc_l0, sparc_l2);
+       sparc_stb_imm (p, sparc_i3, sparc_o5, 2);
+
+       sparc_sethi (p, 0xff000000, sparc_o2);
+       sparc_rdy (p, sparc_l0);
+       sparc_wry (p, sparc_l0, sparc_l1);
+       sparc_wry_imm (p, sparc_l0, 16);
+       sparc_stbar (p);
+       sparc_unimp (p, 24);
+       sparc_flush (p, sparc_l4, 0);
+
+       sparc_and (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
+       sparc_and_imm (p, FALSE, sparc_l0, 0xff, sparc_o1);
+       sparc_andn (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
+       sparc_or (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
+       sparc_orn (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
+       sparc_xor (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
+       sparc_xnor (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
+
+       sparc_sll (p, sparc_l0, sparc_l1, sparc_o1);
+       sparc_sll_imm (p, sparc_l0, 2, sparc_o1);
+       sparc_srl (p, sparc_l0, sparc_l1, sparc_o1);
+       sparc_srl_imm (p, sparc_l0, 2, sparc_o1);
+       sparc_sra (p, sparc_l0, sparc_l1, sparc_o1);
+       sparc_sra_imm (p, sparc_l0, 2, sparc_o1);
+
+       sparc_add (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
+       sparc_add_imm (p, FALSE, sparc_l0, 0xff, sparc_o1);
+       sparc_addx (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
+       sparc_sub (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
+       sparc_subx (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
+
+       sparc_muls (p, sparc_l0, sparc_l1, sparc_o1);
+       sparc_umul (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
+       sparc_smul (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
+       sparc_udiv (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
+       sparc_sdiv (p, sparc_cc, sparc_l0, sparc_l1, sparc_o1);
+
+       sparc_branch (p, FALSE, sparc_bne, -12);
+       sparc_ret (p);
+       sparc_retl (p);
+       sparc_test (p, sparc_l4);
+       sparc_cmp (p, sparc_l4, sparc_l6);
+       sparc_cmp_imm (p, sparc_l4, 4);
+       sparc_restore_simple (p);
+
+       sparc_set (p, 0xff000000, sparc_l7);
+       sparc_set (p, 1, sparc_l7);
+       sparc_set (p, 0xff0000ff, sparc_l7);
+
+       sparc_not (p, sparc_g2);
+       sparc_neg (p, sparc_g3);
+       sparc_clr_reg (p, sparc_g4);
+
+
+       size = (p-code_buffer)*4;
+       ins = (gchar*)code_buffer;
+       for (i = 0; i < size; ++i)
+               printf (".byte %d\n", (unsigned int) ins [i]);
+       return 0;
+}
+
diff --git a/mono/arch/sparc/tramp.c b/mono/arch/sparc/tramp.c
new file mode 100644 (file)
index 0000000..ded60e6
--- /dev/null
@@ -0,0 +1,342 @@
+
+/*
+ * Create trampolines to invoke arbitrary functions.
+ * 
+ * Copyright (C) Ximian Inc.
+ * 
+ * Author: Paolo Molaro (lupus@ximian.com)
+ * 
+ */
+
+#include "config.h"
+#include <stdlib.h>
+#include "sparc-codegen.h"
+#include "mono/metadata/class.h"
+#include "mono/metadata/tabledefs.h"
+#include "mono/interpreter/interp.h"
+
+/*
+ * The resulting function takes the form:
+ * void func (void (*callme)(), void *retval, void *this_obj, stackval *arguments);
+ */
+#define FUNC_ADDR_POS  sparc_i0
+#define RETVAL_POS     sparc_i1
+#define THIS_POS       sparc_i2
+#define ARGP_POS       sparc_i3
+#define LOC_POS        -4
+
+#define ARG_SIZE       sizeof (stackval)
+
+MonoPIFunc
+mono_create_trampoline (MonoMethod *method, int runtime)
+{
+       MonoMethodSignature *sig;
+       guint32 *p, *code_buffer;
+       guint32 local_size = 0, stack_size = 0, code_size = 6;
+       guint32 arg_pos, simpletype;
+       int i, stringp, cur_out_reg;
+
+       sig = method->signature;
+       
+       if (sig->hasthis)
+               code_size ++;
+       
+       for (i = 0; i < sig->param_count; ++i) {
+               if (sig->params [i]->byref) {
+                       stack_size += sizeof (gpointer);
+                       code_size += i < 6 ? 1 : 3;
+                       continue;
+               }
+               simpletype = sig->params [i]->type;
+enum_calc_size:
+               switch (simpletype) {
+               case MONO_TYPE_BOOLEAN:
+               case MONO_TYPE_CHAR:
+               case MONO_TYPE_I1:
+               case MONO_TYPE_U1:
+               case MONO_TYPE_I2:
+               case MONO_TYPE_U2:
+               case MONO_TYPE_I4:
+               case MONO_TYPE_U4:
+               case MONO_TYPE_I:
+               case MONO_TYPE_U:
+               case MONO_TYPE_PTR:
+               case MONO_TYPE_R4:
+               case MONO_TYPE_SZARRAY:
+               case MONO_TYPE_CLASS:
+               case MONO_TYPE_OBJECT:
+                       stack_size += 4;
+                       code_size += i < 6 ? 1 : 3;
+                       break;
+               case MONO_TYPE_VALUETYPE:
+                       if (sig->params [i]->data.klass->enumtype) {
+                               simpletype = sig->params [i]->data.klass->enum_basetype->type;
+                               goto enum_calc_size;
+                       }
+                       if (mono_class_value_size (sig->params [i]->data.klass, NULL) != 4)
+                               g_error ("can only marshal enums, not generic structures (size: %d)", mono_class_value_size (sig->params [i]->data.klass, NULL));
+                       stack_size += 4;
+                       code_size += i < 6 ? 1 : 3;
+                       break;
+               case MONO_TYPE_STRING:
+                       stack_size += 4;
+                       code_size += 5;
+                       local_size++;
+                       break;
+               case MONO_TYPE_I8:
+                       stack_size += 8;
+                       code_size += i < 6 ? 2 : 3;
+                       break;
+               case MONO_TYPE_R8:
+                       stack_size += 8;
+                       code_size += i < 6 ? 2 : 3;
+                       break;
+               default:
+                       g_error ("Can't trampoline 0x%x", sig->params [i]->type);
+               }
+       }
+       /*
+        * FIXME: take into account large return values.
+        */
+
+       code_buffer = p = alloca (code_size * 4);
+       cur_out_reg = sparc_o0;
+
+       /*
+        * Standard function prolog.
+        */
+       sparc_save_imm (p, sparc_sp, -112-stack_size, sparc_sp);
+       /*
+        * We store some local vars here to handle string pointers.
+        * and align to 16 byte boundary...
+        */
+#if 0
+       if (local_size) {
+               x86_alu_reg_imm (p, X86_SUB, X86_ESP, local_size * 4);
+               stack_size = (stack_size * local_size * 4) % 16;
+       } else {
+               stack_size = stack_size % 16;
+       }
+       if (stack_size)
+               x86_alu_reg_imm (p, X86_SUB, X86_ESP, stack_size);
+#endif
+
+       /*
+        * %i3 has the pointer to the args.
+        */
+
+       if (sig->hasthis) {
+               sparc_mov_reg_reg (p, sparc_i2, cur_out_reg);
+               ++cur_out_reg;
+       }
+
+       /*
+        * Push arguments in reverse order.
+        */
+       stringp = 0;
+       for (i = 0; i < sig->param_count; ++i) {
+               arg_pos = ARG_SIZE * i;
+               if (sig->params [i]->byref) {
+                       sparc_ld_imm (p, sparc_i3, arg_pos, cur_out_reg);
+                       ++cur_out_reg;
+                       continue;
+               }
+               simpletype = sig->params [i]->type;
+enum_marshal:
+               switch (simpletype) {
+               case MONO_TYPE_BOOLEAN:
+               case MONO_TYPE_I1:
+               case MONO_TYPE_U1:
+               case MONO_TYPE_I2:
+               case MONO_TYPE_U2:
+               case MONO_TYPE_CHAR:
+               case MONO_TYPE_I4:
+               case MONO_TYPE_U4:
+               case MONO_TYPE_I:
+               case MONO_TYPE_U:
+               case MONO_TYPE_PTR:
+               case MONO_TYPE_SZARRAY:
+               case MONO_TYPE_CLASS:
+               case MONO_TYPE_OBJECT:
+               case MONO_TYPE_R4:
+                       sparc_ld_imm (p, sparc_i3, arg_pos, cur_out_reg);
+                       ++cur_out_reg;
+                       break;
+               case MONO_TYPE_VALUETYPE:
+                       if (!sig->params [i]->data.klass->enumtype) {
+                               /* it's a structure that fits in 4 bytes, need to push the value pointed to */
+                               /*x86_mov_reg_membase (p, X86_EAX, X86_EDX, arg_pos, 4);
+                               x86_push_regp (p, X86_EAX);*/
+                               g_assert (0);
+                       } else {
+                               /* it's an enum value */
+                               simpletype = sig->params [i]->data.klass->enum_basetype->type;
+                               goto enum_marshal;
+                       }
+                       break;
+               case MONO_TYPE_R8:
+                       sparc_ld_imm (p, sparc_i3, arg_pos, cur_out_reg);
+                       ++cur_out_reg;
+                       sparc_ld_imm (p, sparc_i3, arg_pos+4, cur_out_reg);
+                       ++cur_out_reg;
+                       break;
+#if 0
+               case MONO_TYPE_STRING:
+                       /* 
+                        * If it is an internalcall we assume it's the object we want.
+                        * Yet another reason why MONO_TYPE_STRING should not be used to indicate char*.
+                        */
+                       if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || runtime) {
+                               x86_push_membase (p, X86_EDX, arg_pos);
+                               break;
+                       }
+                       /*if (frame->method->flags & PINVOKE_ATTRIBUTE_CHAR_SET_ANSI*/
+                       x86_push_membase (p, X86_EDX, arg_pos);
+                       x86_mov_reg_imm (p, X86_EDX, mono_string_to_utf8);
+                       x86_call_reg (p, X86_EDX);
+                       x86_alu_reg_imm (p, X86_ADD, X86_ESP, 4);
+                       x86_push_reg (p, X86_EAX);
+                       /*
+                        * Store the pointer in a local we'll free later.
+                        */
+                       stringp++;
+                       x86_mov_membase_reg (p, X86_EBP, LOC_POS * stringp, X86_EAX, 4);
+                       /*
+                        * we didn't save the reg: restore it here.
+                        */
+                       if (i > 1)
+                               x86_mov_reg_membase (p, X86_EDX, X86_EBP, ARGP_POS, 4);
+                       break;
+#endif
+               case MONO_TYPE_I8:
+                       sparc_ld_imm (p, sparc_i3, arg_pos, cur_out_reg);
+                       ++cur_out_reg;
+                       sparc_ld_imm (p, sparc_i3, arg_pos+4, cur_out_reg);
+                       ++cur_out_reg;
+                       break;
+               default:
+                       g_error ("Can't trampoline 0x%x", sig->params [i]->type);
+               }
+       }
+
+       /* 
+        * Insert call to function 
+        */
+       sparc_jmpl_imm (p, sparc_i0, 0, sparc_callsite);
+       sparc_nop (p);
+
+       /*
+        * Handle retval.
+        * Small integer and pointer values are in EAX.
+        * Long integers are in EAX:EDX.
+        * FP values are on the FP stack.
+        */
+#if 0
+       if (sig->ret->byref) {
+               x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4);
+               x86_mov_regp_reg (p, X86_ECX, X86_EAX, 4);
+       } else {
+               simpletype = sig->ret->type;
+enum_retvalue:
+               switch (simpletype) {
+               case MONO_TYPE_BOOLEAN:
+               case MONO_TYPE_I1:
+               case MONO_TYPE_U1:
+                       x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4);
+                       x86_mov_regp_reg (p, X86_ECX, X86_EAX, 1);
+                       break;
+               case MONO_TYPE_CHAR:
+               case MONO_TYPE_I2:
+               case MONO_TYPE_U2:
+                       x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4);
+                       x86_mov_regp_reg (p, X86_ECX, X86_EAX, 2);
+                       break;
+               case MONO_TYPE_I4:
+               case MONO_TYPE_U4:
+               case MONO_TYPE_I:
+               case MONO_TYPE_U:
+               case MONO_TYPE_CLASS:
+               case MONO_TYPE_OBJECT:
+               case MONO_TYPE_SZARRAY:
+               case MONO_TYPE_ARRAY:
+                       x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4);
+                       x86_mov_regp_reg (p, X86_ECX, X86_EAX, 4);
+                       break;
+               case MONO_TYPE_STRING: 
+                       if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || runtime) {
+                               x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4);
+                               x86_mov_regp_reg (p, X86_ECX, X86_EAX, 4);
+                               break;
+                       }
+
+                       /* If the argument is non-null, then convert the value back */
+                       x86_alu_reg_reg (p, X86_OR, X86_EAX, X86_EAX);
+                       x86_branch8 (p, X86_CC_EQ, 11, FALSE);
+                       x86_push_reg (p, X86_EAX);
+                       x86_mov_reg_imm (p, X86_EDX, mono_string_new);
+                       x86_call_reg (p, X86_EDX);
+                       x86_alu_reg_imm (p, X86_ADD, X86_ESP, 4);
+
+                       x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4);
+                       x86_mov_regp_reg (p, X86_ECX, X86_EAX, 4);
+                       break;
+               case MONO_TYPE_R4:
+                       x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4);
+                       x86_fst_membase (p, X86_ECX, 0, FALSE, TRUE);
+                       break;
+               case MONO_TYPE_R8:
+                       x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4);
+                       x86_fst_membase (p, X86_ECX, 0, TRUE, TRUE);
+                       break;
+               case MONO_TYPE_I8:
+                       x86_mov_reg_membase (p, X86_ECX, X86_EBP, RETVAL_POS, 4);
+                       x86_mov_regp_reg (p, X86_ECX, X86_EAX, 4);
+                       x86_mov_membase_reg (p, X86_ECX, 4, X86_EDX, 4);
+                       break;
+               case MONO_TYPE_VALUETYPE:
+                       if (sig->ret->data.klass->enumtype) {
+                               simpletype = sig->ret->data.klass->enum_basetype->type;
+                               goto enum_retvalue;
+                       }
+               case MONO_TYPE_VOID:
+                       break;
+               default:
+                       g_error ("Can't handle as return value 0x%x", sig->ret->type);
+               }
+       }
+#endif
+       /*
+        * free the allocated strings.
+        */
+#if 0
+       if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) {
+               if (local_size)
+                       x86_mov_reg_imm (p, X86_EDX, g_free);
+               for (i = 1; i <= local_size; ++i) {
+                       x86_push_membase (p, X86_EBP, LOC_POS * i);
+                       x86_call_reg (p, X86_EDX);
+               }
+       }
+#endif
+       /*
+        * Standard epilog.
+        * 8 may be 12 when returning structures (to skip unimp opcode).
+        */
+       sparc_jmpl_imm (p, sparc_i7, 8, sparc_zero);
+       sparc_restore (p, sparc_zero, sparc_zero, sparc_zero);
+
+       /* FIXME: need to flush */
+       return g_memdup (code_buffer, 4 * (p - code_buffer));
+}
+
+void *
+mono_create_method_pointer (MonoMethod *method)
+{
+       return NULL;
+}
+
+MonoMethod*
+mono_method_pointer_get (void *code)
+{
+       return NULL;
+}