8 #include "vm/jit/sparc64/md-abi.h"
10 #include "vm/exceptions.h"
11 #include "vm/stringlocal.h"
12 #include "vm/jit/asmpart.h"
13 #include "vm/jit/stacktrace.h"
15 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
16 #include "vm/options.h" /* XXX debug */
17 #include "vm/jit/disass.h" /* XXX debug */
20 /* shift away 13-bit immediate, mask rd and rs1 */
21 #define SHIFT_AND_MASK(instr) \
22 ((instr >> 13) & 0x60fc1)
24 #define IS_SETHI(instr) \
25 ((instr & 0xc1c00000) == 0x00800000)
27 inline s2 decode_13bit_imm(u4 instr) {
30 /* mask everything else in the instruction */
31 imm = instr & 0x00001fff;
33 /* sign extend 13-bit to 16-bit */
40 /* md_init *********************************************************************
42 Do some machine dependent initialization.
44 *******************************************************************************/
52 /* md_codegen_patch_branch *****************************************************
54 Back-patches a branch instruction.
56 *******************************************************************************/
58 void md_codegen_patch_branch(codegendata *cd, s4 branchmpc, s4 targetmpc)
62 s4 disp; /* branch displacement */
66 /* calculate the patch position */
68 mcodeptr = (s4 *) (cd->mcodebase + branchmpc);
70 /* get the instruction before the exception point */
74 /* check for BPcc instruction */
75 if (((mcode >> 16) & 0xc1c0) != 0x0040)
78 /* Calculate the branch displacement. For branches we need a
79 displacement relative and shifted to the branch PC. */
81 disp = (targetmpc - branchmpc) >> 2;
83 /* check branch displacement */
85 if ((disp < (s4) 0xfffc0000) || (disp > (s4) 0x003ffff))
86 vm_abort("branch displacement is out of range: %d > +/-%d", disp, 0x003ffff);
88 /* patch the branch instruction before the mcodeptr */
90 mcodeptr[-1] |= (disp & 0x003ffff);
94 /* md_stacktrace_get_returnaddress *********************************************
96 Returns the return address of the current stackframe, specified by
97 the passed stack pointer and the stack frame size.
99 *******************************************************************************/
101 u1 *md_stacktrace_get_returnaddress(u1 *sp, u4 framesize)
104 /* flush register windows to the stack */
107 /* the return address resides in register i7, the last register in the
108 * 16-extended-word save area
110 ra = *((u1 **) (sp + 120 + BIAS));
112 /* ra is the address of the call instr, advance to the real return address */
119 /* md_codegen_get_pv_from_pc ***************************************************
121 This reconstructs and returns the PV of a method given a return address
122 pointer. (basically, same was as the generated code following the jump does)
128 277afffe ldah pv,-2(ra)
129 237ba61c lda pv,-23012(pv)
131 *******************************************************************************/
133 u1 *md_codegen_get_pv_from_pc(u1 *ra)
142 /* get the instruction word after jump and nop */
143 mcode = *((u4 *) (ra+8) );
145 /* check if we have 2 instructions (ldah, lda) */
147 mcode_masked = SHIFT_AND_MASK(mcode);
149 if (mcode_masked == 0x40001) {
151 /* get displacement of first instruction (ldah) */
153 offset = (s4) (mcode << 16);
156 /* get displacement of second instruction (lda) */
158 mcode = *((u4 *) (ra + 1 * 4));
160 assert((mcode >> 16) == 0x237b);
162 offset = (s2) (mcode & 0x0000ffff);
166 /* get displacement of first instruction (lda) */
168 assert((mcode >> 16) == 0x237a);
170 /* mask and extend the negative sign for the 13 bit immediate */
171 offset = decode_13bit_imm(mcode);
183 /* md_get_method_patch_address *************************************************
185 Gets the patch address of the currently compiled method. The offset
186 is extracted from the load instruction(s) before the jump and added
187 to the right base address (PV or REG_METHODPTR).
189 INVOKESTATIC/SPECIAL:
191 dfdeffb8 ldx [i5 - 72],o5
198 df3e0000 ld [g2 + 0],o5
205 df39ff90 ld [g2 - 112],g2
206 df3e0018 ld [g2 + 24],o5
210 *******************************************************************************/
212 u1 *md_get_method_patch_address(u1 *ra, stackframeinfo *sfi, u1 *mptr)
214 u4 mcode, mcode_masked;
218 /* go back to the actual load instruction (1 instruction before jump) */
219 /* ra is the address of the jump instruction on SPARC */
222 /* get first instruction word on current PC */
224 mcode = *((u4 *) ra);
227 /* check if we have 2 instructions (lui) */
229 if (IS_SETHI(mcode)) {
230 /* XXX write a regression for this */
233 /* get displacement of first instruction (lui) */
235 offset = (s4) (mcode << 16);
237 /* get displacement of second instruction (daddiu) */
239 mcode = *((u4 *) (ra + 1 * 4));
241 assert((mcode >> 16) != 0x6739);
243 offset += (s2) (mcode & 0x0000ffff);
247 /* shift and maks rd */
249 mcode_masked = (mcode >> 13) & 0x060fff;
251 /* get the offset from the instruction */
253 offset = decode_13bit_imm(mcode);
255 /* check for call with rs1 == REG_METHODPTR: ldx [g2+x],pv_caller */
257 if (mcode_masked == 0x0602c5) {
258 /* in this case we use the passed method pointer */
263 /* in the normal case we check for a `ldx [i5+x],pv_caller' instruction */
265 assert(mcode_masked == 0x0602fb);
267 printf("data segment: pv=0x%08x, offset=%d\n", sfi->pv, offset);
269 /* and get the final data segment address */
271 pa = sfi->pv + offset;
279 /* md_cacheflush ***************************************************************
281 Calls the system's function to flush the instruction and data
284 *******************************************************************************/
286 void md_cacheflush(u1 *addr, s4 nbytes)
292 /* md_icacheflush **************************************************************
294 Calls the system's function to flush the instruction cache.
296 *******************************************************************************/
298 void md_icacheflush(u1 *addr, s4 nbytes)
304 /* md_patch_replacement_point **************************************************
306 Patch the given replacement point.
308 *******************************************************************************/
310 void md_patch_replacement_point(rplpoint *rp)
314 /* save the current machine code */
315 mcode = *(u4*)rp->pc;
317 /* write the new machine code */
318 *(u4*)(rp->pc) = (u4) rp->mcode;
320 /* store saved mcode */
323 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
331 /* flush instruction cache */
332 /* md_icacheflush(rp->pc,4); */
336 * These are local overrides for various environment variables in Emacs.
337 * Please do not remove this and leave it at the end of the file, where
338 * Emacs will automagically detect them.
339 * ---------------------------------------------------------------------
342 * indent-tabs-mode: t
346 * vim:noexpandtab:sw=4:ts=4: