1 /* src/vm/jit/x86_64/md.c - machine dependent x86_64 Linux functions
3 Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4 C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5 E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6 J. Wenninger, Institut f. Computersprachen - TU Wien
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 Contact: cacao@cacaojvm.org
27 Authors: Christian Thalinger
29 Changes: Edwin Steiner
31 $Id: md.c 4908 2006-05-12 16:49:50Z edwin $
44 #include "vm/jit/x86_64/md-abi.h"
46 #include "vm/exceptions.h"
47 #include "vm/signallocal.h"
48 #include "vm/jit/asmpart.h"
49 #include "vm/jit/stacktrace.h"
51 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
52 #include "vm/options.h" /* XXX debug */
53 #include "vm/jit/disass.h" /* XXX debug */
57 /* md_init *********************************************************************
59 Do some machine dependent initialization.
61 *******************************************************************************/
69 /* md_signal_handler_sigsegv ***************************************************
71 NullPointerException signal handler for hardware null pointer
74 *******************************************************************************/
76 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
84 _uc = (ucontext_t *) _p;
85 _mc = &_uc->uc_mcontext;
87 /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
88 different to the ones in <ucontext.h>. */
90 sp = (u1 *) _mc->gregs[REG_RSP];
91 xpc = (u1 *) _mc->gregs[REG_RIP];
92 ra = xpc; /* return address is equal to xpc */
95 (ptrint) stacktrace_hardware_nullpointerexception(NULL, sp, ra, xpc);
97 _mc->gregs[REG_R10] = (ptrint) xpc; /* REG_ITMP2_XPC */
98 _mc->gregs[REG_RIP] = (ptrint) asm_handle_exception;
102 /* md_signal_handler_sigfpe ****************************************************
104 ArithmeticException signal handler for hardware divide by zero
107 *******************************************************************************/
109 void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p)
117 _uc = (ucontext_t *) _p;
118 _mc = &_uc->uc_mcontext;
120 /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
121 different to the ones in <ucontext.h>. */
123 sp = (u1 *) _mc->gregs[REG_RSP];
124 xpc = (u1 *) _mc->gregs[REG_RIP];
125 ra = xpc; /* return address is equal to xpc */
127 _mc->gregs[REG_RAX] =
128 (ptrint) stacktrace_hardware_arithmeticexception(NULL, sp, ra, xpc);
130 _mc->gregs[REG_R10] = (ptrint) xpc; /* REG_ITMP2_XPC */
131 _mc->gregs[REG_RIP] = (ptrint) asm_handle_exception;
135 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
136 void thread_restartcriticalsection(ucontext_t *uc)
140 critical = critical_find_restart_point((void *) uc->uc_mcontext.gregs[REG_RIP]);
143 uc->uc_mcontext.gregs[REG_RIP] = (ptrint) critical;
148 /* md_stacktrace_get_returnaddress *********************************************
150 Returns the return address of the current stackframe, specified by
151 the passed stack pointer and the stack frame size.
153 *******************************************************************************/
155 u1 *md_stacktrace_get_returnaddress(u1 *sp, u4 framesize)
159 /* on x86_64 the return address is above the current stack frame */
161 ra = *((u1 **) (sp + framesize));
167 /* md_get_method_patch_address *************************************************
169 Gets the patch address of the currently compiled method. The offset
170 is extracted from the load instruction(s) before the jump and added
171 to the right base address (PV or REG_METHODPTR).
173 INVOKESTATIC/SPECIAL:
175 49 ba 98 3a ed ab aa 2a 00 00 mov $0x2aaaabed3a98,%r10
176 49 ff d2 rex64Z callq *%r10
180 4c 8b 17 mov (%rdi),%r10
181 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
182 48 ff d3 rex64 callq *%rax
186 4c 8b 17 mov (%rdi),%r10
187 4d 8b 92 00 00 00 00 mov 0x0(%r10),%r10
188 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
189 48 ff d3 rex64 callq *%r11
191 *******************************************************************************/
193 u1 *md_get_method_patch_address(u1 *ra, stackframeinfo *sfi, u1 *mptr)
197 u1 *pa; /* patch address */
199 /* go back to the actual call instruction (3-bytes) */
203 /* get the last byte of the call */
207 /* check for the different calls */
209 /* INVOKESTATIC/SPECIAL */
212 /* patch address is 8-bytes before the call instruction */
216 } else if (mcode == 0xd3) {
217 /* INVOKEVIRTUAL/INTERFACE */
219 /* Get the offset from the instruction (the offset address is
220 4-bytes before the call instruction). */
222 offset = *((s4 *) (ra - 4));
224 /* add the offset to the method pointer */
229 /* catch any problems */
238 /* md_codegen_findmethod *******************************************************
240 On this architecture just a wrapper function to codegen_findmethod.
242 *******************************************************************************/
244 u1 *md_codegen_findmethod(u1 *ra)
248 /* the the start address of the function which contains this
249 address from the method table */
251 pv = codegen_findmethod(ra);
257 /* md_cacheflush ***************************************************************
259 Calls the system's function to flush the instruction and data
262 *******************************************************************************/
264 void md_cacheflush(u1 *addr, s4 nbytes)
270 /* md_icacheflush **************************************************************
272 Calls the system's function to flush the instruction cache.
274 *******************************************************************************/
276 void md_icacheflush(u1 *addr, s4 nbytes)
282 /* md_dcacheflush **************************************************************
284 Calls the system's function to flush the data cache.
286 *******************************************************************************/
288 void md_dcacheflush(u1 *addr, s4 nbytes)
294 /* md_patch_replacement_point **************************************************
296 Patch the given replacement point.
298 *******************************************************************************/
300 void md_patch_replacement_point(rplpoint *rp)
304 /* XXX this is probably unsafe! */
306 /* save the current machine code */
307 mcode = *(u8*)rp->pc;
309 /* write spinning instruction */
310 *(u2*)(rp->pc) = 0xebfe;
313 rp->pc[4] = (rp->mcode >> 32);
315 /* write first word */
316 *(u4*)(rp->pc) = (u4) rp->mcode;
318 /* store saved mcode */
321 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
329 /* XXX if required asm_cacheflush(rp->pc,8); */
333 * These are local overrides for various environment variables in Emacs.
334 * Please do not remove this and leave it at the end of the file, where
335 * Emacs will automagically detect them.
336 * ---------------------------------------------------------------------
339 * indent-tabs-mode: t
343 * vim:noexpandtab:sw=4:ts=4: