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 5172 2006-07-25 15:33:58Z twisti $
44 #include "vm/jit/x86_64/md-abi.h"
46 #if defined(ENABLE_THREADS)
47 # include "threads/native/threads.h"
50 #include "vm/exceptions.h"
51 #include "vm/signallocal.h"
52 #include "vm/jit/asmpart.h"
53 #include "vm/jit/stacktrace.h"
55 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
56 #include "vm/options.h" /* XXX debug */
57 #include "vm/jit/disass.h" /* XXX debug */
61 /* md_init *********************************************************************
63 Do some machine dependent initialization.
65 *******************************************************************************/
73 /* md_signal_handler_sigsegv ***************************************************
75 NullPointerException signal handler for hardware null pointer
78 *******************************************************************************/
80 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
88 _uc = (ucontext_t *) _p;
89 _mc = &_uc->uc_mcontext;
91 /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
92 different to the ones in <ucontext.h>. */
94 sp = (u1 *) _mc->gregs[REG_RSP];
95 xpc = (u1 *) _mc->gregs[REG_RIP];
96 ra = xpc; /* return address is equal to xpc */
99 (ptrint) stacktrace_hardware_nullpointerexception(NULL, sp, ra, xpc);
101 _mc->gregs[REG_R10] = (ptrint) xpc; /* REG_ITMP2_XPC */
102 _mc->gregs[REG_RIP] = (ptrint) asm_handle_exception;
106 /* md_signal_handler_sigfpe ****************************************************
108 ArithmeticException signal handler for hardware divide by zero
111 *******************************************************************************/
113 void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p)
121 _uc = (ucontext_t *) _p;
122 _mc = &_uc->uc_mcontext;
124 /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
125 different to the ones in <ucontext.h>. */
127 sp = (u1 *) _mc->gregs[REG_RSP];
128 xpc = (u1 *) _mc->gregs[REG_RIP];
129 ra = xpc; /* return address is equal to xpc */
131 _mc->gregs[REG_RAX] =
132 (ptrint) stacktrace_hardware_arithmeticexception(NULL, sp, ra, xpc);
134 _mc->gregs[REG_R10] = (ptrint) xpc; /* REG_ITMP2_XPC */
135 _mc->gregs[REG_RIP] = (ptrint) asm_handle_exception;
139 /* md_signal_handler_sigusr2 ***************************************************
141 Signal handler for profiling sampling.
143 *******************************************************************************/
145 #if defined(ENABLE_THREADS)
146 void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p)
155 _uc = (ucontext_t *) _p;
156 _mc = &_uc->uc_mcontext;
158 /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
159 different to the ones in <ucontext.h>. */
161 pc = (u1 *) _mc->gregs[REG_RIP];
168 #if defined(ENABLE_THREADS)
169 void thread_restartcriticalsection(ucontext_t *_uc)
174 _mc = &_uc->uc_mcontext;
176 pc = critical_find_restart_point((void *) _mc->gregs[REG_RIP]);
179 _mc->gregs[REG_RIP] = (ptrint) pc;
184 /* md_stacktrace_get_returnaddress *********************************************
186 Returns the return address of the current stackframe, specified by
187 the passed stack pointer and the stack frame size.
189 *******************************************************************************/
191 u1 *md_stacktrace_get_returnaddress(u1 *sp, u4 framesize)
195 /* on x86_64 the return address is above the current stack frame */
197 ra = *((u1 **) (sp + framesize));
203 /* md_get_method_patch_address *************************************************
205 Gets the patch address of the currently compiled method. The offset
206 is extracted from the load instruction(s) before the jump and added
207 to the right base address (PV or REG_METHODPTR).
209 INVOKESTATIC/SPECIAL:
211 49 ba 98 3a ed ab aa 2a 00 00 mov $0x2aaaabed3a98,%r10
212 49 ff d2 rex64Z callq *%r10
216 4c 8b 17 mov (%rdi),%r10
217 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
218 48 ff d3 rex64 callq *%rax
222 4c 8b 17 mov (%rdi),%r10
223 4d 8b 92 00 00 00 00 mov 0x0(%r10),%r10
224 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
225 48 ff d3 rex64 callq *%r11
227 *******************************************************************************/
229 u1 *md_get_method_patch_address(u1 *ra, stackframeinfo *sfi, u1 *mptr)
233 u1 *pa; /* patch address */
235 /* go back to the actual call instruction (3-bytes) */
239 /* get the last byte of the call */
243 /* check for the different calls */
245 /* INVOKESTATIC/SPECIAL */
248 /* patch address is 8-bytes before the call instruction */
252 } else if (mcode == 0xd3) {
253 /* INVOKEVIRTUAL/INTERFACE */
255 /* Get the offset from the instruction (the offset address is
256 4-bytes before the call instruction). */
258 offset = *((s4 *) (ra - 4));
260 /* add the offset to the method pointer */
265 /* catch any problems */
274 /* md_codegen_findmethod *******************************************************
276 On this architecture just a wrapper function to codegen_findmethod.
278 *******************************************************************************/
280 u1 *md_codegen_findmethod(u1 *ra)
284 /* the the start address of the function which contains this
285 address from the method table */
287 pv = codegen_findmethod(ra);
293 /* md_cacheflush ***************************************************************
295 Calls the system's function to flush the instruction and data
298 *******************************************************************************/
300 void md_cacheflush(u1 *addr, s4 nbytes)
306 /* md_icacheflush **************************************************************
308 Calls the system's function to flush the instruction cache.
310 *******************************************************************************/
312 void md_icacheflush(u1 *addr, s4 nbytes)
318 /* md_dcacheflush **************************************************************
320 Calls the system's function to flush the data cache.
322 *******************************************************************************/
324 void md_dcacheflush(u1 *addr, s4 nbytes)
330 /* md_patch_replacement_point **************************************************
332 Patch the given replacement point.
334 *******************************************************************************/
336 void md_patch_replacement_point(rplpoint *rp)
340 /* XXX this is probably unsafe! */
342 /* save the current machine code */
343 mcode = *(u8*)rp->pc;
345 /* write spinning instruction */
346 *(u2*)(rp->pc) = 0xebfe;
349 rp->pc[4] = (rp->mcode >> 32);
351 /* write first word */
352 *(u4*)(rp->pc) = (u4) rp->mcode;
354 /* store saved mcode */
357 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
365 /* XXX if required asm_cacheflush(rp->pc,8); */
369 * These are local overrides for various environment variables in Emacs.
370 * Please do not remove this and leave it at the end of the file, where
371 * Emacs will automagically detect them.
372 * ---------------------------------------------------------------------
375 * indent-tabs-mode: t
379 * vim:noexpandtab:sw=4:ts=4: