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