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 */
21 /* md_init *********************************************************************
23 Do some machine dependent initialization.
25 *******************************************************************************/
33 /* md_stacktrace_get_returnaddress *********************************************
35 Returns the return address of the current stackframe, specified by
36 the passed stack pointer and the stack frame size.
38 *******************************************************************************/
40 u1 *md_stacktrace_get_returnaddress(u1 *sp, u4 framesize)
43 /* flush register windows to the stack */
46 /* the return address resides in register i7, the last register in the
47 * 16-extended-word save area
49 ra = *((u1 **) (sp + 120));
51 /* ra is the address of the call instr, advance to the real return address */
58 /* md_codegen_get_pv_from_pc ***************************************************
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)
67 277afffe ldah pv,-2(ra)
68 237ba61c lda pv,-23012(pv)
70 *******************************************************************************/
72 u1 *md_codegen_get_pv_from_pc(u1 *ra)
81 /* get the instruction word after jump and nop */
82 mcode = *((u4 *) (ra+8) );
84 /* check if we have 2 instructions (ldah, lda) */
86 /* shift instruction word, mask rd and rs1 */
87 mcode_masked = (mcode >> 13) & 0x60fc1;
89 if (mcode_masked == 0x40001) {
91 /* get displacement of first instruction (ldah) */
93 offset = (s4) (mcode << 16);
96 /* get displacement of second instruction (lda) */
98 mcode = *((u4 *) (ra + 1 * 4));
100 assert((mcode >> 16) == 0x237b);
102 offset = (s2) (mcode & 0x0000ffff);
106 /* get displacement of first instruction (lda) */
108 assert((mcode >> 16) == 0x237a);
110 /* mask and extend the negative sign for the 13 bit immediate */
111 offset = (s2) ((mcode & 0x00001fff) | 0xffffe000);
119 /* md_get_method_patch_address *************************************************
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).
125 INVOKESTATIC/SPECIAL:
127 dfdeffb8 ld s8,-72(s8)
141 df39ff90 ld t9,-112(t9)
142 df3e0018 ld s8,24(t9)
146 *******************************************************************************/
148 u1 *md_get_method_patch_address(u1 *ra, stackframeinfo *sfi, u1 *mptr)
154 /* go back to the actual load instruction (3 instructions on MIPS) */
158 /* get first instruction word on current PC */
160 mcode = *((u4 *) ra);
162 /* check if we have 2 instructions (lui) */
164 if ((mcode >> 16) == 0x3c19) {
165 /* XXX write a regression for this */
168 /* get displacement of first instruction (lui) */
170 offset = (s4) (mcode << 16);
172 /* get displacement of second instruction (daddiu) */
174 mcode = *((u4 *) (ra + 1 * 4));
176 assert((mcode >> 16) != 0x6739);
178 offset += (s2) (mcode & 0x0000ffff);
181 /* get first instruction (ld) */
183 mcode = *((u4 *) ra);
185 /* get the offset from the instruction */
187 offset = (s2) (mcode & 0x0000ffff);
189 /* check for call with REG_METHODPTR: ld s8,x(t9) */
191 #if SIZEOF_VOID_P == 8
192 if ((mcode >> 16) == 0xdf3e) {
194 if ((mcode >> 16) == 0x8f3e) {
196 /* in this case we use the passed method pointer */
201 /* in the normal case we check for a `ld s8,x(s8)' instruction */
203 #if SIZEOF_VOID_P == 8
204 assert((mcode >> 16) == 0xdfde);
206 assert((mcode >> 16) == 0x8fde);
209 /* and get the final data segment address */
211 pa = sfi->pv + offset;
219 /* md_cacheflush ***************************************************************
221 Calls the system's function to flush the instruction and data
224 *******************************************************************************/
226 void md_cacheflush(u1 *addr, s4 nbytes)
232 /* md_icacheflush **************************************************************
234 Calls the system's function to flush the instruction cache.
236 *******************************************************************************/
238 void md_icacheflush(u1 *addr, s4 nbytes)
244 /* md_patch_replacement_point **************************************************
246 Patch the given replacement point.
248 *******************************************************************************/
250 void md_patch_replacement_point(rplpoint *rp)
254 /* save the current machine code */
255 mcode = *(u4*)rp->pc;
257 /* write the new machine code */
258 *(u4*)(rp->pc) = (u4) rp->mcode;
260 /* store saved mcode */
263 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
271 /* flush instruction cache */
272 /* md_icacheflush(rp->pc,4); */
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 * ---------------------------------------------------------------------
282 * indent-tabs-mode: t
286 * vim:noexpandtab:sw=4:ts=4: