--- /dev/null
+#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__ */
+
--- /dev/null
+#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;
+}
+
--- /dev/null
+
+/*
+ * 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;
+}