1 #include "config.h"
2 #include "dill.h"
3 #include "dill_internal.h"
4 #include "sparc.h"
5 
dill_sparc_hidden_modi(int a,int b)6 extern long dill_sparc_hidden_modi(int a, int b)
7 { return a % b; }
dill_sparc_hidden_mod(long a,long b)8 extern long dill_sparc_hidden_mod(long a, long b)
9 { return a % b; }
dill_sparc_hidden_umod(unsigned long a,unsigned long b)10 extern unsigned long dill_sparc_hidden_umod(unsigned long a, unsigned long b)
11 { return a % b; }
dill_sparc_hidden_umodi(unsigned int a,unsigned int b)12 extern unsigned int dill_sparc_hidden_umodi(unsigned int a, unsigned int b)
13 { return a % b; }
dill_sparc_hidden_ultod(unsigned long a)14 extern double dill_sparc_hidden_ultod(unsigned long a)
15 { return (double) a; }
dill_sparc_hidden_ultof(unsigned long a)16 extern float dill_sparc_hidden_ultof(unsigned long a)
17 { return (float) a; }
dill_sparc_hidden_dtoul(double a)18 extern unsigned long dill_sparc_hidden_dtoul(double a)
19 { return (unsigned long) a; }
dill_sparc_hidden_dtou(double a)20 extern unsigned int dill_sparc_hidden_dtou(double a)
21 { return (unsigned int) a; }
dill_sparc_hidden_ftoul(float a)22 extern unsigned long dill_sparc_hidden_ftoul(float a)
23 { return (unsigned long) a; }
dill_sparc_hidden_ftou(float a)24 extern unsigned int dill_sparc_hidden_ftou(float a)
25 { return (unsigned int) a; }
dill_sparc_hidden_udiv(unsigned long a,unsigned long b)26 extern long dill_sparc_hidden_udiv(unsigned long a, unsigned long b)
27 { return a / b; }
28 
29 static xfer_entry sparc_xfer_recs[] = {
30     {"dill_sparc_hidden_modi", (void*)dill_sparc_hidden_modi},
31     {"dill_sparc_hidden_mod", (void*)dill_sparc_hidden_mod},
32     {"dill_sparc_hidden_umodi", (void*)dill_sparc_hidden_umodi},
33     {"dill_sparc_hidden_umod", (void*)dill_sparc_hidden_umod},
34     {"dill_sparc_hidden_ultod", (void*)dill_sparc_hidden_ultod},
35     {"dill_sparc_hidden_ultof", (void*)dill_sparc_hidden_ultof},
36     {"dill_sparc_hidden_dtoul", (void*)dill_sparc_hidden_dtoul},
37     {"dill_sparc_hidden_ftoul", (void*)dill_sparc_hidden_ftoul},
38     {"dill_sparc_hidden_dtou", (void*)dill_sparc_hidden_dtou},
39     {"dill_sparc_hidden_ftou", (void*)dill_sparc_hidden_ftou},
40     {"dill_sparc_hidden_udiv", (void*)dill_sparc_hidden_udiv},
41     {(char*)0, (void*)0}};
42 
43 #define sparc_sethi(r, imm) (HDR(0)|RD(r)|OP2(0x4)|imm)
44 #define sparc_ori(dest, src, imm) (HDR(0x2)|OP3(0x2)|IM|RD(dest)|RS1(src)|imm)
45 #define sparc_or(dest, src1, src2) (HDR(0x2)|OP3(0x2)|RD(dest)|RS1(src1)|RS2(src2))
46 #define sparc_sllx(dest, src1,imm) (HDR(0x2)|OP3(0x25)|RD(dest)|RS1(src1)|IM|SIMM13(imm)|(1<<12) )
47 
48 extern void
sparc_rt_call_link(char * code,call_t * t,int force_plt)49 sparc_rt_call_link(char *code, call_t *t, int force_plt)
50 {
51     int i;
52 
53     for(i=0; i< t->call_count; i++) {
54 	int *call_addr = (int*) (code + t->call_locs[i].loc);
55 	if (!force_plt && (t->call_locs[i].mach_info == (void*)0)) {
56 	    /* no PLT */
57 	    int call_offset = (unsigned long)t->call_locs[i].xfer_addr -
58 		(unsigned long)call_addr;
59 
60 	    /* div addr diff by 4 for sparc offset value */
61 	    call_offset = call_offset >> 2;
62 	    *call_addr &= 0xc0000000;
63 	    *call_addr |= (call_offset & 0x3fffffff);
64 	} else {
65 	    int *plt = (int*)(code + t->call_locs[i].loc);
66 	    union {
67 		void *xa;
68 		long xl;
69 	    }u;
70 	    u.xa = t->call_locs[i].xfer_addr;
71 	    plt[0] = sparc_sethi(_g1, hh(u.xl));
72 	    plt[1] = sparc_ori(_g1, _g1, hm(u.xl));
73 	    plt[2] = sparc_sethi(_l0, lm(u.xl));
74 	    plt[3] = sparc_ori(_l0, _l0, lo(u.xl));
75 	    plt[4] = sparc_sllx(_g1, _g1, 32);
76 	    plt[5] = sparc_or(_g1, _g1, _l0);
77 	}
78     }
79 }
80 
81 static void
sparc_flush(void * base,void * limit)82 sparc_flush(void *base, void *limit)
83 {
84 #if defined(HOST_SPARC) || defined(HOST_SPARCV9)
85     {
86 	volatile void *ptr = base;
87 
88 #ifdef __GNUC__
89 	/* flush every 8 bytes of preallocated insn stream. */
90 	while((char*)ptr < (char*) limit) {
91 	    asm volatile ("iflush %0" : /* */ : "r" (ptr));
92 	    ptr = (char *)ptr + 8;
93 	}
94 	asm volatile("nop");
95 	asm volatile("nop");
96 	asm volatile("nop");
97 	asm volatile("nop");
98 	asm volatile("nop");
99 #else
100 	int nbytes = (char*)limit - (char*)base;
101 	for(; nbytes > 0;nbytes -= 8) {
102 	    asm("add %i0, 8, %i0");
103 	    asm ("iflush %i0");
104 	}
105 
106 	asm ("nop");
107 	asm ("nop");
108 	asm ("nop");
109 	asm ("nop");
110 	asm ("nop");
111 #endif
112 #ifdef USE_MEMBAR
113 	asm("membar #Sync");
114 #endif
115     }
116 #endif
117 }
118 
119 extern char *
sparc_package_stitch(char * code,call_t * t,dill_pkg pkg)120 sparc_package_stitch(char *code, call_t *t, dill_pkg pkg)
121 {
122     int force_plt = 0;
123     dill_lookup_xfer_addrs(t, &sparc_xfer_recs[0]);
124 #if defined(HOST_SPARCV9)
125     force_plt = 1;
126 #endif
127     sparc_rt_call_link(code, t, force_plt);
128     sparc_flush(code, code + pkg->code_size);
129     return code + pkg->entry_offset;
130 }
131