* src/vm/jit/sparc64/codegen.c: Ported to unified variables.
[cacao.git] / src / vm / jit / sparc64 / md.c
1
2 #include <assert.h>
3
4 #include "config.h"
5
6 #include "vm/types.h"
7
8 #include "vm/jit/sparc64/md-abi.h"
9
10 #include "vm/exceptions.h"
11 #include "vm/stringlocal.h"
12 #include "vm/jit/asmpart.h"
13 #include "vm/jit/stacktrace.h"
14
15 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
16 #include "vm/options.h" /* XXX debug */
17 #include "vm/jit/disass.h" /* XXX debug */
18 #endif
19
20
21 /* md_init *********************************************************************
22
23    Do some machine dependent initialization.
24
25 *******************************************************************************/
26
27 void md_init(void)
28 {
29         /* do nothing */
30 }
31
32
33 /* md_stacktrace_get_returnaddress *********************************************
34
35    Returns the return address of the current stackframe, specified by
36    the passed stack pointer and the stack frame size.
37
38 *******************************************************************************/
39
40 u1 *md_stacktrace_get_returnaddress(u1 *sp, u4 framesize)
41 {
42         u1 *ra;
43         /* flush register windows to the stack */
44         __asm__ ("flushw");
45
46         /* the return address resides in register i7, the last register in the
47          * 16-extended-word save area
48          */
49         ra = *((u1 **) (sp + 120));
50         
51         /* ra is the address of the call instr, advance to the real return address  */
52         ra += 8;
53
54         return ra;
55 }
56
57
58 /* md_codegen_get_pv_from_pc ***************************************************
59
60    This reconstructs and returns the PV of a method given a return address
61    pointer. (basically, same was as the generated code following the jump does)
62    
63    Machine code:
64
65    6b5b4000    jmpl    (pv)
66    10000000    nop
67    277afffe    ldah    pv,-2(ra)
68    237ba61c    lda     pv,-23012(pv)
69
70 *******************************************************************************/
71
72 u1 *md_codegen_get_pv_from_pc(u1 *ra)
73 {
74         u1 *pv;
75         u8  mcode;
76         u4  mcode_masked;
77         s2  offset;
78
79         pv = ra;
80
81         /* get the instruction word after jump and nop */
82         mcode = *((u4 *) (ra+8) );
83
84         /* check if we have 2 instructions (ldah, lda) */
85
86         /* shift instruction word,  mask rd and rs1    */ 
87         mcode_masked = (mcode >> 13) & 0x60fc1;
88
89         if (mcode_masked == 0x40001) {
90 #if 0
91                 /* get displacement of first instruction (ldah) */
92
93                 offset = (s4) (mcode << 16);
94                 pv += offset;
95
96                 /* get displacement of second instruction (lda) */
97
98                 mcode = *((u4 *) (ra + 1 * 4));
99
100                 assert((mcode >> 16) == 0x237b);
101
102                 offset = (s2) (mcode & 0x0000ffff);
103                 pv += offset;
104
105         } else {
106                 /* get displacement of first instruction (lda) */
107
108                 assert((mcode >> 16) == 0x237a);
109 #endif
110                 /* mask and extend the negative sign for the 13 bit immediate */
111                 offset = (s2) ((mcode & 0x00001fff) | 0xffffe000);
112
113                 pv += offset;
114         }
115
116         return pv;
117 }
118
119 /* md_get_method_patch_address *************************************************
120
121    Gets the patch address of the currently compiled method. The offset
122    is extracted from the load instruction(s) before the jump and added
123    to the right base address (PV or REG_METHODPTR).
124
125    INVOKESTATIC/SPECIAL:
126
127    dfdeffb8    ld       s8,-72(s8)
128    03c0f809    jalr     s8
129    00000000    nop
130
131    INVOKEVIRTUAL:
132
133    dc990000    ld       t9,0(a0)
134    df3e0000    ld       s8,0(t9)
135    03c0f809    jalr     s8
136    00000000    nop
137
138    INVOKEINTERFACE:
139
140    dc990000    ld       t9,0(a0)
141    df39ff90    ld       t9,-112(t9)
142    df3e0018    ld       s8,24(t9)
143    03c0f809    jalr     s8
144    00000000    nop
145
146 *******************************************************************************/
147
148 u1 *md_get_method_patch_address(u1 *ra, stackframeinfo *sfi, u1 *mptr)
149 {
150         u4  mcode;
151         s4  offset;
152         u1 *pa;
153
154         /* go back to the actual load instruction (3 instructions on MIPS) */
155
156         ra -= 3 * 4;
157
158         /* get first instruction word on current PC */
159
160         mcode = *((u4 *) ra);
161
162         /* check if we have 2 instructions (lui) */
163
164         if ((mcode >> 16) == 0x3c19) {
165                 /* XXX write a regression for this */
166                 assert(0);
167
168                 /* get displacement of first instruction (lui) */
169
170                 offset = (s4) (mcode << 16);
171
172                 /* get displacement of second instruction (daddiu) */
173
174                 mcode = *((u4 *) (ra + 1 * 4));
175
176                 assert((mcode >> 16) != 0x6739);
177
178                 offset += (s2) (mcode & 0x0000ffff);
179
180         } else {
181                 /* get first instruction (ld) */
182
183                 mcode = *((u4 *) ra);
184
185                 /* get the offset from the instruction */
186
187                 offset = (s2) (mcode & 0x0000ffff);
188
189                 /* check for call with REG_METHODPTR: ld s8,x(t9) */
190
191 #if SIZEOF_VOID_P == 8
192                 if ((mcode >> 16) == 0xdf3e) {
193 #else
194                 if ((mcode >> 16) == 0x8f3e) {
195 #endif
196                         /* in this case we use the passed method pointer */
197
198                         pa = mptr + offset;
199
200                 } else {
201                         /* in the normal case we check for a `ld s8,x(s8)' instruction */
202
203 #if SIZEOF_VOID_P == 8
204                         assert((mcode >> 16) == 0xdfde);
205 #else
206                         assert((mcode >> 16) == 0x8fde);
207 #endif
208
209                         /* and get the final data segment address */
210
211                         pa = sfi->pv + offset;
212                 }
213         }
214
215         return pa;
216 }
217
218
219 /* md_cacheflush ***************************************************************
220
221    Calls the system's function to flush the instruction and data
222    cache.
223
224 *******************************************************************************/
225
226 void md_cacheflush(u1 *addr, s4 nbytes)
227 {
228         /* don't know yet */    
229 }
230
231
232 /* md_icacheflush **************************************************************
233
234    Calls the system's function to flush the instruction cache.
235
236 *******************************************************************************/
237
238 void md_icacheflush(u1 *addr, s4 nbytes)
239 {
240         /* don't know yet */    
241 }
242
243
244 /* md_patch_replacement_point **************************************************
245
246    Patch the given replacement point.
247
248 *******************************************************************************/
249
250 void md_patch_replacement_point(rplpoint *rp)
251 {
252     u8 mcode;
253
254         /* save the current machine code */
255         mcode = *(u4*)rp->pc;
256
257         /* write the new machine code */
258     *(u4*)(rp->pc) = (u4) rp->mcode;
259
260         /* store saved mcode */
261         rp->mcode = mcode;
262         
263 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
264         {
265                 u1* u1ptr = rp->pc;
266                 DISASSINSTR(u1ptr);
267                 fflush(stdout);
268         }
269 #endif
270                         
271         /* flush instruction cache */
272     /* md_icacheflush(rp->pc,4); */
273 }
274
275 /*
276  * These are local overrides for various environment variables in Emacs.
277  * Please do not remove this and leave it at the end of the file, where
278  * Emacs will automagically detect them.
279  * ---------------------------------------------------------------------
280  * Local variables:
281  * mode: c
282  * indent-tabs-mode: t
283  * c-basic-offset: 4
284  * tab-width: 4
285  * End:
286  * vim:noexpandtab:sw=4:ts=4:
287  */