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);
137 /* md_get_method_patch_address *************************************************
139 Gets the patch address of the currently compiled method. The offset
140 is extracted from the load instruction(s) before the jump and added
141 to the right base address (PV or REG_METHODPTR).
143 INVOKESTATIC/SPECIAL:
145 dfdeffb8 ldx [i5 - 72],o5
152 df3e0000 ld [g2 + 0],o5
159 df39ff90 ld [g2 - 112],g2
160 df3e0018 ld [g2 + 24],o5
164 *******************************************************************************/
166 u1 *md_get_method_patch_address(u1 *ra, stackframeinfo *sfi, u1 *mptr)
168 u4 mcode, mcode_masked;
172 /* go back to the actual load instruction (1 instruction before jump) */
173 /* ra is the address of the jump instruction on SPARC */
176 /* get first instruction word on current PC */
178 mcode = *((u4 *) ra);
181 /* check if we have 2 instructions (lui) */
183 if (IS_SETHI(mcode)) {
184 /* XXX write a regression for this */
187 /* get displacement of first instruction (lui) */
189 offset = (s4) (mcode << 16);
191 /* get displacement of second instruction (daddiu) */
193 mcode = *((u4 *) (ra + 1 * 4));
195 assert((mcode >> 16) != 0x6739);
197 offset += (s2) (mcode & 0x0000ffff);
201 /* shift and maks rd */
203 mcode_masked = (mcode >> 13) & 0x060fff;
205 /* get the offset from the instruction */
207 offset = decode_13bit_imm(mcode);
209 /* check for call with rs1 == REG_METHODPTR: ldx [g2+x],pv_caller */
211 if (mcode_masked == 0x0602c5) {
212 /* in this case we use the passed method pointer */
217 /* in the normal case we check for a `ldx [i5+x],pv_caller' instruction */
219 assert(mcode_masked == 0x0602fb);
221 /* and get the final data segment address */
223 pa = sfi->pv + offset;
231 /* md_cacheflush ***************************************************************
233 Calls the system's function to flush the instruction and data
236 *******************************************************************************/
238 void md_cacheflush(u1 *addr, s4 nbytes)
244 /* md_icacheflush **************************************************************
246 Calls the system's function to flush the instruction cache.
248 *******************************************************************************/
250 void md_icacheflush(u1 *addr, s4 nbytes)
256 /* md_patch_replacement_point **************************************************
258 Patch the given replacement point.
260 *******************************************************************************/
262 void md_patch_replacement_point(rplpoint *rp)
266 /* save the current machine code */
267 mcode = *(u4*)rp->pc;
269 /* write the new machine code */
270 *(u4*)(rp->pc) = (u4) rp->mcode;
272 /* store saved mcode */
275 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
283 /* flush instruction cache */
284 /* md_icacheflush(rp->pc,4); */
288 * These are local overrides for various environment variables in Emacs.
289 * Please do not remove this and leave it at the end of the file, where
290 * Emacs will automagically detect them.
291 * ---------------------------------------------------------------------
294 * indent-tabs-mode: t
298 * vim:noexpandtab:sw=4:ts=4: