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 7581 2007-03-26 07:23:16Z 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"
72 #include "vm/jit/s390/codegen.h"
75 #define OOPS() assert(0);
77 /* md_init *********************************************************************
79 Do some machine dependent initialization.
81 *******************************************************************************/
89 /* md_signal_handler_sigsegv ***************************************************
91 NullPointerException signal handler for hardware null pointer
94 *******************************************************************************/
96 void md_signal_handler_sigsegv(int sig, siginfo_t *siginfo, void *_p)
104 _uc = (ucontext_t *) _p;
105 _mc = &_uc->uc_mcontext;
107 /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
108 different to the ones in <ucontext.h>. */
110 sp = (u1 *) _mc->gregs[REG_RSP];
111 xpc = (u1 *) _mc->gregs[REG_RIP];
112 ra = xpc; /* return address is equal to xpc */
115 /* check for StackOverflowException */
117 threads_check_stackoverflow(sp);
120 _mc->gregs[REG_RAX] =
121 (ptrint) stacktrace_hardware_nullpointerexception(NULL, sp, ra, xpc);
123 _mc->gregs[REG_R10] = (ptrint) xpc; /* REG_ITMP2_XPC */
124 _mc->gregs[REG_RIP] = (ptrint) asm_handle_exception;
128 /* md_signal_handler_sigfpe ****************************************************
130 ArithmeticException signal handler for hardware divide by zero
133 *******************************************************************************/
135 void md_signal_handler_sigfpe(int sig, siginfo_t *siginfo, void *_p)
143 _uc = (ucontext_t *) _p;
144 _mc = &_uc->uc_mcontext;
146 /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
147 different to the ones in <ucontext.h>. */
149 sp = (u1 *) _mc->gregs[REG_RSP];
150 xpc = (u1 *) _mc->gregs[REG_RIP];
151 ra = xpc; /* return address is equal to xpc */
153 _mc->gregs[REG_RAX] =
154 (ptrint) stacktrace_hardware_arithmeticexception(NULL, sp, ra, xpc);
156 _mc->gregs[REG_R10] = (ptrint) xpc; /* REG_ITMP2_XPC */
157 _mc->gregs[REG_RIP] = (ptrint) asm_handle_exception;
161 /* md_signal_handler_sigusr2 ***************************************************
163 Signal handler for profiling sampling.
165 *******************************************************************************/
167 #if defined(ENABLE_THREADS)
168 void md_signal_handler_sigusr2(int sig, siginfo_t *siginfo, void *_p)
177 _uc = (ucontext_t *) _p;
178 _mc = &_uc->uc_mcontext;
180 /* ATTENTION: Don't use CACAO's internal REG_* defines as they are
181 different to the ones in <ucontext.h>. */
183 pc = (u1 *) _mc->gregs[REG_RIP];
190 #if defined(ENABLE_THREADS)
191 void thread_restartcriticalsection(ucontext_t *_uc)
196 _mc = &_uc->uc_mcontext;
198 pc = critical_find_restart_point((void *) _mc->gregs[REG_RIP]);
201 _mc->gregs[REG_RIP] = (ptrint) pc;
206 /* md_codegen_patch_branch *****************************************************
208 Back-patches a branch instruction.
210 *******************************************************************************/
212 void md_codegen_patch_branch(codegendata *cd, s4 branchmpc, s4 targetmpc)
216 s4 disp; /* branch displacement */
218 /* calculate the patch position */
220 mcodeptr = (s4 *) (cd->mcodebase + branchmpc);
222 /* Calculate the branch displacement. */
224 disp = targetmpc - branchmpc;
225 disp += 4; /* size of branch */
226 disp /= 2; /* specified in halfwords */
228 ASSERT_VALID_BRANCH(disp);
230 /* patch the branch instruction before the mcodeptr */
232 mcodeptr[-1] |= (disp & 0xFFFF);
236 /* md_stacktrace_get_returnaddress *********************************************
238 Returns the return address of the current stackframe, specified by
239 the passed stack pointer and the stack frame size.
241 *******************************************************************************/
243 u1 *md_stacktrace_get_returnaddress(u1 *sp, u4 framesize)
247 /* on S390 the return address is located on the top of the stackframe */
249 ra = *((u1 **) (sp + framesize - SIZEOF_VOID_P));
255 /* md_get_method_patch_address *************************************************
257 Gets the patch address of the currently compiled method. The offset
258 is extracted from the load instruction(s) before the jump and added
259 to the right base address (PV or REG_METHODPTR).
261 INVOKESTATIC/SPECIAL:
263 0x7748d7b2: a7 18 ff d4 lhi %r1,-44
265 0x7748d7b6: 58 d1 d0 00 l %r13,0(%r1,%r13)
267 0x7748d7ba: 0d ed basr %r14,%r13
272 0x7748d82a: 58 c0 20 00 l %r12,0(%r2)
274 0x7748d82e: 58 d0 c0 00 l %r13,0(%r12)
276 0x7748d832: 0d ed basr %r14,%r13
282 last 2 instructions the same as in invokevirtual
284 *******************************************************************************/
286 u1 *md_get_method_patch_address(u1 *ra, stackframeinfo *sfi, u1 *mptr)
290 u1 *pa; /* patch address */
292 /* go back to the load before the call instruction */
294 ra = ra - 2 /* sizeof bcr */ - 4 /* sizeof l */;
296 /* get the base register of the load */
300 /* check for the different calls */
302 if (base == 0xd) { /* pv relative */
303 /* INVOKESTATIC/SPECIAL */
305 /* the offset is in the load before the load */
307 offset = *((s2 *) (ra - 2));
309 /* add the offset to the procedure vector */
311 pa = sfi->pv + offset;
313 else if (base == 0xc) { /* mptr relative */
314 /* INVOKEVIRTUAL/INTERFACE */
316 offset = *((u2 *)(ra + 2)) & 0xFFF;
318 /* add offset to method pointer */
323 /* catch any problems */
331 /* md_codegen_get_pv_from_pc ***************************************************
333 On this architecture just a wrapper function to
334 codegen_get_pv_from_pc.
336 *******************************************************************************/
338 u1 *md_codegen_get_pv_from_pc(u1 *ra)
342 /* Get the start address of the function which contains this
343 address from the method table. */
345 pv = codegen_get_pv_from_pc(ra);
351 /* md_cacheflush ***************************************************************
353 Calls the system's function to flush the instruction and data
356 *******************************************************************************/
358 void md_cacheflush(u1 *addr, s4 nbytes)
364 /* md_icacheflush **************************************************************
366 Calls the system's function to flush the instruction cache.
368 *******************************************************************************/
370 void md_icacheflush(u1 *addr, s4 nbytes)
376 /* md_dcacheflush **************************************************************
378 Calls the system's function to flush the data cache.
380 *******************************************************************************/
382 void md_dcacheflush(u1 *addr, s4 nbytes)
388 /* md_patch_replacement_point **************************************************
390 Patch the given replacement point.
392 *******************************************************************************/
394 void md_patch_replacement_point(rplpoint *rp)
398 /* XXX this is probably unsafe! */
400 /* save the current machine code */
401 mcode = *(u8*)rp->pc;
403 /* write spinning instruction */
404 *(u2*)(rp->pc) = 0xebfe;
407 rp->pc[4] = (rp->mcode >> 32);
409 /* write first word */
410 *(u4*)(rp->pc) = (u4) rp->mcode;
412 /* store saved mcode */
415 #if !defined(NDEBUG) && defined(ENABLE_DISASSEMBLER)
423 /* XXX if required asm_cacheflush(rp->pc,8); */
427 * These are local overrides for various environment variables in Emacs.
428 * Please do not remove this and leave it at the end of the file, where
429 * Emacs will automagically detect them.
430 * ---------------------------------------------------------------------
433 * indent-tabs-mode: t
437 * vim:noexpandtab:sw=4:ts=4: