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 7534 2007-03-16 23:00:18Z pm $
55 #include "vm/jit/s390/md-abi.h"
57 #if defined(ENABLE_THREADS)
58 # include "threads/native/threads.h"
61 #include "vm/exceptions.h"
62 #include "vm/signallocal.h"
63 #include "vm/jit/asmpart.h"
64 #include "vm/jit/stacktrace.h"
66 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
67 #include "vmcore/options.h" /* XXX debug */
68 #include "vm/jit/disass.h" /* XXX debug */
71 #include "vm/jit/codegen-common.h"
74 #define OOPS() assert(0);
76 /* md_init *********************************************************************
78 Do some machine dependent initialization.
80 *******************************************************************************/
88 /* md_signal_handler_sigsegv ***************************************************
90 NullPointerException signal handler for hardware null pointer
93 *******************************************************************************/
95 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
103 _uc = (ucontext_t *) _p;
104 _mc = &_uc->uc_mcontext;
106 /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
107 different to the ones in <ucontext.h>. */
109 sp = (u1 *) _mc->gregs[REG_RSP];
110 xpc = (u1 *) _mc->gregs[REG_RIP];
111 ra = xpc; /* return address is equal to xpc */
114 /* check for StackOverflowException */
116 threads_check_stackoverflow(sp);
119 _mc->gregs[REG_RAX] =
120 (ptrint) stacktrace_hardware_nullpointerexception(NULL, sp, ra, xpc);
122 _mc->gregs[REG_R10] = (ptrint) xpc; /* REG_ITMP2_XPC */
123 _mc->gregs[REG_RIP] = (ptrint) asm_handle_exception;
127 /* md_signal_handler_sigfpe ****************************************************
129 ArithmeticException signal handler for hardware divide by zero
132 *******************************************************************************/
134 void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p)
142 _uc = (ucontext_t *) _p;
143 _mc = &_uc->uc_mcontext;
145 /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
146 different to the ones in <ucontext.h>. */
148 sp = (u1 *) _mc->gregs[REG_RSP];
149 xpc = (u1 *) _mc->gregs[REG_RIP];
150 ra = xpc; /* return address is equal to xpc */
152 _mc->gregs[REG_RAX] =
153 (ptrint) stacktrace_hardware_arithmeticexception(NULL, sp, ra, xpc);
155 _mc->gregs[REG_R10] = (ptrint) xpc; /* REG_ITMP2_XPC */
156 _mc->gregs[REG_RIP] = (ptrint) asm_handle_exception;
160 /* md_signal_handler_sigusr2 ***************************************************
162 Signal handler for profiling sampling.
164 *******************************************************************************/
166 #if defined(ENABLE_THREADS)
167 void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p)
176 _uc = (ucontext_t *) _p;
177 _mc = &_uc->uc_mcontext;
179 /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
180 different to the ones in <ucontext.h>. */
182 pc = (u1 *) _mc->gregs[REG_RIP];
189 #if defined(ENABLE_THREADS)
190 void thread_restartcriticalsection(ucontext_t *_uc)
195 _mc = &_uc->uc_mcontext;
197 pc = critical_find_restart_point((void *) _mc->gregs[REG_RIP]);
200 _mc->gregs[REG_RIP] = (ptrint) pc;
205 /* md_codegen_patch_branch *****************************************************
207 Back-patches a branch instruction.
209 *******************************************************************************/
211 void md_codegen_patch_branch(codegendata *cd, s4 branchmpc, s4 targetmpc)
215 s4 disp; /* branch displacement */
217 /* calculate the patch position */
219 mcodeptr = (s4 *) (cd->mcodebase + branchmpc);
221 /* Calculate the branch displacement. */
223 disp = targetmpc - branchmpc;
224 disp += 4; /* size of branch */
225 disp /= 2; /* specified in halfwords */
227 /* TODO check for overflow */
229 /* patch the branch instruction before the mcodeptr */
231 mcodeptr[-1] |= (disp & 0xFFFF);
235 /* md_stacktrace_get_returnaddress *********************************************
237 Returns the return address of the current stackframe, specified by
238 the passed stack pointer and the stack frame size.
240 *******************************************************************************/
242 u1 *md_stacktrace_get_returnaddress(u1 *sp, u4 framesize)
246 /* on S390 the return address is located on the top of the stackframe */
248 ra = *((u1 **) (sp + framesize - SIZEOF_VOID_P));
254 /* md_get_method_patch_address *************************************************
256 Gets the patch address of the currently compiled method. The offset
257 is extracted from the load instruction(s) before the jump and added
258 to the right base address (PV or REG_METHODPTR).
260 INVOKESTATIC/SPECIAL:
262 0x7748d7b2: a7 18 ff d4 lhi %r1,-44
264 0x7748d7b6: 58 d1 d0 00 l %r13,0(%r1,%r13)
266 0x7748d7ba: 0d ed basr %r14,%r13
271 0x7748d82a: 58 c0 20 00 l %r12,0(%r2)
273 0x7748d82e: 58 d0 c0 00 l %r13,0(%r12)
275 0x7748d832: 0d ed basr %r14,%r13
281 last 2 instructions the same as in invokevirtual
283 *******************************************************************************/
285 u1 *md_get_method_patch_address(u1 *ra, stackframeinfo *sfi, u1 *mptr)
289 u1 *pa; /* patch address */
291 /* go back to the load before the call instruction */
293 ra = ra - 2 /* sizeof bcr */ - 4 /* sizeof l */;
295 /* get the base register of the load */
299 /* check for the different calls */
301 if (base == 0xd) { /* pv relative */
302 /* INVOKESTATIC/SPECIAL */
304 /* the offset is in the load before the load */
306 offset = *((s2 *) (ra - 2));
308 /* add the offset to the procedure vector */
310 pa = sfi->pv + offset;
312 else if (base == 0xc) { /* mptr relative */
313 /* INVOKEVIRTUAL/INTERFACE */
315 offset = *((u2 *)(ra + 2)) & 0xFFF;
317 /* add offset to method pointer */
322 /* catch any problems */
330 /* md_codegen_get_pv_from_pc ***************************************************
332 On this architecture just a wrapper function to
333 codegen_get_pv_from_pc.
335 *******************************************************************************/
337 u1 *md_codegen_get_pv_from_pc(u1 *ra)
341 /* Get the start address of the function which contains this
342 address from the method table. */
344 pv = codegen_get_pv_from_pc(ra);
350 /* md_cacheflush ***************************************************************
352 Calls the system's function to flush the instruction and data
355 *******************************************************************************/
357 void md_cacheflush(u1 *addr, s4 nbytes)
363 /* md_icacheflush **************************************************************
365 Calls the system's function to flush the instruction cache.
367 *******************************************************************************/
369 void md_icacheflush(u1 *addr, s4 nbytes)
375 /* md_dcacheflush **************************************************************
377 Calls the system's function to flush the data cache.
379 *******************************************************************************/
381 void md_dcacheflush(u1 *addr, s4 nbytes)
387 /* md_patch_replacement_point **************************************************
389 Patch the given replacement point.
391 *******************************************************************************/
393 void md_patch_replacement_point(rplpoint *rp)
397 /* XXX this is probably unsafe! */
399 /* save the current machine code */
400 mcode = *(u8*)rp->pc;
402 /* write spinning instruction */
403 *(u2*)(rp->pc) = 0xebfe;
406 rp->pc[4] = (rp->mcode >> 32);
408 /* write first word */
409 *(u4*)(rp->pc) = (u4) rp->mcode;
411 /* store saved mcode */
414 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
422 /* XXX if required asm_cacheflush(rp->pc,8); */
426 * These are local overrides for various environment variables in Emacs.
427 * Please do not remove this and leave it at the end of the file, where
428 * Emacs will automagically detect them.
429 * ---------------------------------------------------------------------
432 * indent-tabs-mode: t
436 * vim:noexpandtab:sw=4:ts=4: