CACAO
md.cpp
Go to the documentation of this file.
1 /* src/vm/jit/powerpc64/md.cpp - machine dependent PowerPC functions
2 
3  Copyright (C) 1996-2013
4  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 
6  This file is part of CACAO.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2, or (at
11  your option) any later version.
12 
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  02110-1301, USA.
22 
23 */
24 
25 
26 #include "config.h"
27 
28 #include <cassert>
29 #include <stdint.h>
30 
31 #include "vm/types.hpp"
32 
33 #include "md-abi.hpp"
34 
36 #include "vm/jit/powerpc64/md.hpp"
37 
38 #include "vm/global.hpp"
39 
40 #include "vm/jit/jit.hpp"
41 #include "vm/jit/trap.hpp"
42 
43 
44 /* md_init *********************************************************************
45 
46  Do some machine dependent initialization.
47 
48 *******************************************************************************/
49 
50 void md_init(void)
51 {
52  /* nothing to do */
53 }
54 
55 
56 /* md_jit_method_patch_address *************************************************
57 
58  Gets the patch address of the currently compiled method. The offset
59  is extracted from the load instruction(s) before the jump and added
60  to the right base address (PV or REG_METHODPTR).
61 
62  INVOKESTATIC/SPECIAL:
63 
64  e9ceffb8 ld r14,-72(r14)
65  7dc903a6 mtctr r14
66  4e800421 bctrl
67 
68  INVOKEVIRTUAL:
69 
70 FIXME 81830000 lwz r12,0(r3)
71  e9cc0000 ld r14,0(r12)
72  7dc903a6 mtctr r14
73  4e800421 bctrl
74 
75 
76  INVOKEINTERFACE:
77 
78 FIXME 81830000 lwz r12,0(r3)
79 FIXME 818c0000 lwz r12,0(r12)
80 FIXME 81ac0000 lwz r13,0(r12)
81  7dc903a6 mtctr r14
82  4e800421 bctrl
83 
84 *******************************************************************************/
85 
86 void *md_jit_method_patch_address(void *pv, void *ra, void *mptr)
87 {
88  uint32_t *pc;
89  uint32_t mcode;
90  int32_t offset;
91  void *pa;
92 
93  /* Go back to the actual load instruction (3 instructions). */
94 
95  pc = ((uint32_t *) ra) - 3;
96 
97  /* get first instruction word (lwz) */
98 
99  mcode = pc[0];
100 
101  /* check if we have 2 instructions (addis, addi) */
102 
103  if ((mcode >> 16) == 0x3c19) {
104  /* XXX write a regression for this */
105  pa = NULL;
106  assert(0);
107 
108  /* get displacement of first instruction (addis) */
109 
110  offset = (int32_t) (mcode << 16);
111 
112  /* get displacement of second instruction (addi) */
113 
114  mcode = pc[1];
115 
116  assert((mcode >> 16) != 0x6739);
117 
118  offset += (int16_t) (mcode & 0x0000ffff);
119  }
120  else {
121  /* get the offset from the instruction */
122 
123  offset = (int16_t) (mcode & 0x0000ffff);
124 
125  /* check for load from PV */
126 
127  if ((mcode >> 16) == 0xe9ce) {
128  /* get the final data segment address */
129 
130  pa = ((uint8_t *) pv) + offset;
131  }
132  else if ((mcode >> 16) == 0xe9cc) {
133  /* in this case we use the passed method pointer */
134 
135  /* return NULL if no mptr was specified (used for replacement) */
136 
137  if (mptr == NULL)
138  return NULL;
139 
140  pa = ((uint8_t *) mptr) + offset;
141  }
142  else {
143  /* catch any problems */
144 
145  vm_abort("md_jit_method_patch_address: unknown instruction %x",
146  mcode);
147 
148  /* keep compiler happy */
149 
150  pa = NULL;
151  }
152  }
153 
154  return pa;
155 }
156 
157 
158 /**
159  * Decode the trap instruction at the given PC.
160  *
161  * @param trp information about trap to be filled
162  * @param sig signal number
163  * @param xpc exception PC
164  * @param es execution state of the machine
165  * @return true if trap was decoded successfully, false otherwise.
166  */
167 bool md_trap_decode(trapinfo_t* trp, int sig, void* xpc, executionstate_t* es)
168 {
169  // Get the throwing instruction.
170  uint32_t mcode = *((uint32_t*) xpc);
171 
172  switch (sig) {
173  case TRAP_SIGILL:
174  // Check for valid trap instruction.
175  if (mcode == 0x00000000) {
176  trp->type = TRAP_PATCHER;
177  trp->value = 0;
178  return true;
179  }
180  return false;
181 
182  case TRAP_SIGSEGV:
183  {
184  // Decode the throwing instruction.
185  int s1 = M_INSTR_OP2_IMM_A(mcode);
186  int16_t disp = M_INSTR_OP2_IMM_I(mcode);
187  int d = M_INSTR_OP2_IMM_D(mcode);
188 
189  // We use the exception type as load displacement.
190  if (s1 == REG_ZERO) {
191  trp->type = disp;
192  trp->value = es->intregs[d];
193  return true;
194  }
195 
196  // Default case is a normal NullPointerException.
197  if (es->intregs[s1] == 0) {
199  trp->value = 0;
200  return true;
201  }
202 
203  return false;
204  }
205 
206  default:
207  return false;
208  }
209 }
210 
211 
212 /* md_patch_replacement_point **************************************************
213 
214  Patch the given replacement point.
215 
216 *******************************************************************************/
217 
218 #if defined(ENABLE_REPLACEMENT)
219 void md_patch_replacement_point(u1 *pc, u1 *savedmcode, bool revert)
220 {
221  u4 mcode;
222 
223  if (revert) {
224  /* restore the patched-over instruction */
225  *(u4*)(pc) = *(u4*)(savedmcode);
226  }
227  else {
228  /* save the current machine code */
229  *(u4*)(savedmcode) = *(u4*)(pc);
230 
231  /* build the machine code for the patch */
232  mcode = (0x80000000 | TRAP_PATCHER);
233 
234  /* write the new machine code */
235  *(u4*)(pc) = (u4) mcode;
236  }
237 
238  /* flush instruction cache */
239  md_icacheflush(pc,4);
240 }
241 #endif /* defined(ENABLE_REPLACEMENT) */
242 
243 
244 /*
245  * These are local overrides for various environment variables in Emacs.
246  * Please do not remove this and leave it at the end of the file, where
247  * Emacs will automagically detect them.
248  * ---------------------------------------------------------------------
249  * Local variables:
250  * mode: c++
251  * indent-tabs-mode: t
252  * c-basic-offset: 4
253  * tab-width: 4
254  * End:
255  * vim:noexpandtab:sw=4:ts=4:
256  */
#define pv
Definition: md-asm.hpp:65
intptr_t value
Value (numeric or address) passed with the trap.
Definition: trap.hpp:44
#define mptr
Definition: md-asm.hpp:66
#define ra
Definition: md-asm.hpp:62
#define M_INSTR_OP2_IMM_I(x)
Definition: codegen.hpp:115
Contains information about a decoded trap instruction.
Definition: trap.hpp:42
uint8_t u1
Definition: types.hpp:40
void vm_abort(const char *text,...)
Definition: vm.cpp:2586
#define xpc
Definition: md-asm.hpp:51
int type
Specific trap type (see md-trap.h).
Definition: trap.hpp:43
#define M_INSTR_OP2_IMM_A(x)
Definition: codegen.hpp:114
#define M_INSTR_OP2_IMM_D(x)
Definition: codegen.hpp:113
void * md_jit_method_patch_address(void *pv, void *ra, void *mptr)
Definition: md.cpp:83
uint32_t u4
Definition: types.hpp:46
#define pc
Definition: md-asm.hpp:56
bool md_trap_decode(trapinfo_t *trp, int sig, void *xpc, executionstate_t *es)
Decode the trap instruction at the given PC.
Definition: md.cpp:192
int8_t s1
Definition: types.hpp:39
uintptr_t intregs[INT_REG_CNT]
#define REG_ZERO
Definition: md-abi.hpp:54
void md_init(void)
Definition: md.cpp:48
static void md_icacheflush(void *addr, int nbytes)
Definition: md.hpp:151