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_stacktrace_get_returnaddress *********************************************
54 Returns the return address of the current stackframe, specified by
55 the passed stack pointer and the stack frame size.
57 *******************************************************************************/
59 u1 *md_stacktrace_get_returnaddress(u1 *sp, u4 framesize)
62 /* flush register windows to the stack */
65 /* the return address resides in register i7, the last register in the
66 * 16-extended-word save area
68 ra = *((u1 **) (sp + 120 + BIAS));
70 /* ra is the address of the call instr, advance to the real return address */
77 /* md_codegen_get_pv_from_pc ***************************************************
79 This reconstructs and returns the PV of a method given a return address
80 pointer. (basically, same was as the generated code following the jump does)
86 277afffe ldah pv,-2(ra)
87 237ba61c lda pv,-23012(pv)
89 *******************************************************************************/
91 u1 *md_codegen_get_pv_from_pc(u1 *ra)
100 /* get the instruction word after jump and nop */
101 mcode = *((u4 *) (ra+8) );
103 /* check if we have 2 instructions (ldah, lda) */
105 mcode_masked = SHIFT_AND_MASK(mcode);
107 if (mcode_masked == 0x40001) {
109 /* get displacement of first instruction (ldah) */
111 offset = (s4) (mcode << 16);
114 /* get displacement of second instruction (lda) */
116 mcode = *((u4 *) (ra + 1 * 4));
118 assert((mcode >> 16) == 0x237b);
120 offset = (s2) (mcode & 0x0000ffff);
124 /* get displacement of first instruction (lda) */
126 assert((mcode >> 16) == 0x237a);
128 /* mask and extend the negative sign for the 13 bit immediate */
129 offset = decode_13bit_imm(mcode);
141 /* md_get_method_patch_address *************************************************
143 Gets the patch address of the currently compiled method. The offset
144 is extracted from the load instruction(s) before the jump and added
145 to the right base address (PV or REG_METHODPTR).
147 INVOKESTATIC/SPECIAL:
149 dfdeffb8 ldx [i5 - 72],o5
156 df3e0000 ld [g2 + 0],o5
163 df39ff90 ld [g2 - 112],g2
164 df3e0018 ld [g2 + 24],o5
168 *******************************************************************************/
170 u1 *md_get_method_patch_address(u1 *ra, stackframeinfo *sfi, u1 *mptr)
172 u4 mcode, mcode_masked;
176 /* go back to the actual load instruction (1 instruction before jump) */
177 /* ra is the address of the jump instruction on SPARC */
180 /* get first instruction word on current PC */
182 mcode = *((u4 *) ra);
185 /* check if we have 2 instructions (lui) */
187 if (IS_SETHI(mcode)) {
188 /* XXX write a regression for this */
191 /* get displacement of first instruction (lui) */
193 offset = (s4) (mcode << 16);
195 /* get displacement of second instruction (daddiu) */
197 mcode = *((u4 *) (ra + 1 * 4));
199 assert((mcode >> 16) != 0x6739);
201 offset += (s2) (mcode & 0x0000ffff);
205 /* shift and maks rd */
207 mcode_masked = (mcode >> 13) & 0x060fff;
209 /* get the offset from the instruction */
211 offset = decode_13bit_imm(mcode);
213 /* check for call with rs1 == REG_METHODPTR: ldx [g2+x],pv_caller */
215 if (mcode_masked == 0x0602c5) {
216 /* in this case we use the passed method pointer */
221 /* in the normal case we check for a `ldx [i5+x],pv_caller' instruction */
223 assert(mcode_masked == 0x0602fb);
225 printf("data segment: pv=0x%08x, offset=%d\n", sfi->pv, offset);
227 /* and get the final data segment address */
229 pa = sfi->pv + offset;
237 /* md_cacheflush ***************************************************************
239 Calls the system's function to flush the instruction and data
242 *******************************************************************************/
244 void md_cacheflush(u1 *addr, s4 nbytes)
250 /* md_icacheflush **************************************************************
252 Calls the system's function to flush the instruction cache.
254 *******************************************************************************/
256 void md_icacheflush(u1 *addr, s4 nbytes)
262 /* md_patch_replacement_point **************************************************
264 Patch the given replacement point.
266 *******************************************************************************/
268 void md_patch_replacement_point(rplpoint *rp)
272 /* save the current machine code */
273 mcode = *(u4*)rp->pc;
275 /* write the new machine code */
276 *(u4*)(rp->pc) = (u4) rp->mcode;
278 /* store saved mcode */
281 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
289 /* flush instruction cache */
290 /* md_icacheflush(rp->pc,4); */
294 * These are local overrides for various environment variables in Emacs.
295 * Please do not remove this and leave it at the end of the file, where
296 * Emacs will automagically detect them.
297 * ---------------------------------------------------------------------
300 * indent-tabs-mode: t
304 * vim:noexpandtab:sw=4:ts=4: