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 5233 2006-08-14 10:59:39Z 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 /* check for StackOverflowException */
101 threads_check_stackoverflow(sp);
104 _mc->gregs[REG_RAX] =
105 (ptrint) stacktrace_hardware_nullpointerexception(NULL, sp, ra, xpc);
107 _mc->gregs[REG_R10] = (ptrint) xpc; /* REG_ITMP2_XPC */
108 _mc->gregs[REG_RIP] = (ptrint) asm_handle_exception;
112 /* md_signal_handler_sigfpe ****************************************************
114 ArithmeticException signal handler for hardware divide by zero
117 *******************************************************************************/
119 void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p)
127 _uc = (ucontext_t *) _p;
128 _mc = &_uc->uc_mcontext;
130 /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
131 different to the ones in <ucontext.h>. */
133 sp = (u1 *) _mc->gregs[REG_RSP];
134 xpc = (u1 *) _mc->gregs[REG_RIP];
135 ra = xpc; /* return address is equal to xpc */
137 _mc->gregs[REG_RAX] =
138 (ptrint) stacktrace_hardware_arithmeticexception(NULL, sp, ra, xpc);
140 _mc->gregs[REG_R10] = (ptrint) xpc; /* REG_ITMP2_XPC */
141 _mc->gregs[REG_RIP] = (ptrint) asm_handle_exception;
145 /* md_signal_handler_sigusr2 ***************************************************
147 Signal handler for profiling sampling.
149 *******************************************************************************/
151 #if defined(ENABLE_THREADS)
152 void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p)
161 _uc = (ucontext_t *) _p;
162 _mc = &_uc->uc_mcontext;
164 /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
165 different to the ones in <ucontext.h>. */
167 pc = (u1 *) _mc->gregs[REG_RIP];
174 #if defined(ENABLE_THREADS)
175 void thread_restartcriticalsection(ucontext_t *_uc)
180 _mc = &_uc->uc_mcontext;
182 pc = critical_find_restart_point((void *) _mc->gregs[REG_RIP]);
185 _mc->gregs[REG_RIP] = (ptrint) pc;
190 /* md_stacktrace_get_returnaddress *********************************************
192 Returns the return address of the current stackframe, specified by
193 the passed stack pointer and the stack frame size.
195 *******************************************************************************/
197 u1 *md_stacktrace_get_returnaddress(u1 *sp, u4 framesize)
201 /* on x86_64 the return address is above the current stack frame */
203 ra = *((u1 **) (sp + framesize));
209 /* md_get_method_patch_address *************************************************
211 Gets the patch address of the currently compiled method. The offset
212 is extracted from the load instruction(s) before the jump and added
213 to the right base address (PV or REG_METHODPTR).
215 INVOKESTATIC/SPECIAL:
217 4d 8b 15 e2 fe ff ff mov -286(%rip),%r10
218 49 ff d2 rex64Z callq *%r10
222 4c 8b 17 mov (%rdi),%r10
223 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
224 48 ff d3 rex64 callq *%rax
228 4c 8b 17 mov (%rdi),%r10
229 4d 8b 92 00 00 00 00 mov 0x0(%r10),%r10
230 49 8b 82 00 00 00 00 mov 0x0(%r10),%rax
231 48 ff d3 rex64 callq *%r11
233 *******************************************************************************/
235 u1 *md_get_method_patch_address(u1 *ra, stackframeinfo *sfi, u1 *mptr)
239 u1 *pa; /* patch address */
241 /* go back to the actual call instruction (3-bytes) */
245 /* get the last byte of the call */
249 /* check for the different calls */
252 /* INVOKESTATIC/SPECIAL */
254 /* Get the offset from the instruction (the offset address is
255 4-bytes before the call instruction). */
257 offset = *((s4 *) (ra - 4));
259 /* add the offset to the return address (IP-relative addressing) */
263 else if (mcode == 0xd3) {
264 /* INVOKEVIRTUAL/INTERFACE */
266 /* Get the offset from the instruction (the offset address is
267 4-bytes before the call instruction). */
269 offset = *((s4 *) (ra - 4));
271 /* add the offset to the method pointer */
276 /* catch any problems */
285 /* md_codegen_get_pv_from_pc ***************************************************
287 On this architecture just a wrapper function to
288 codegen_get_pv_from_pc.
290 *******************************************************************************/
292 u1 *md_codegen_get_pv_from_pc(u1 *ra)
296 /* Get the start address of the function which contains this
297 address from the method table. */
299 pv = codegen_get_pv_from_pc(ra);
305 /* md_cacheflush ***************************************************************
307 Calls the system's function to flush the instruction and data
310 *******************************************************************************/
312 void md_cacheflush(u1 *addr, s4 nbytes)
318 /* md_icacheflush **************************************************************
320 Calls the system's function to flush the instruction cache.
322 *******************************************************************************/
324 void md_icacheflush(u1 *addr, s4 nbytes)
330 /* md_dcacheflush **************************************************************
332 Calls the system's function to flush the data cache.
334 *******************************************************************************/
336 void md_dcacheflush(u1 *addr, s4 nbytes)
342 /* md_patch_replacement_point **************************************************
344 Patch the given replacement point.
346 *******************************************************************************/
348 void md_patch_replacement_point(rplpoint *rp)
352 /* XXX this is probably unsafe! */
354 /* save the current machine code */
355 mcode = *(u8*)rp->pc;
357 /* write spinning instruction */
358 *(u2*)(rp->pc) = 0xebfe;
361 rp->pc[4] = (rp->mcode >> 32);
363 /* write first word */
364 *(u4*)(rp->pc) = (u4) rp->mcode;
366 /* store saved mcode */
369 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
377 /* XXX if required asm_cacheflush(rp->pc,8); */
381 * These are local overrides for various environment variables in Emacs.
382 * Please do not remove this and leave it at the end of the file, where
383 * Emacs will automagically detect them.
384 * ---------------------------------------------------------------------
387 * indent-tabs-mode: t
391 * vim:noexpandtab:sw=4:ts=4: