CACAO
md.cpp
Go to the documentation of this file.
1 /* src/vm/jit/mips/md.cpp - machine dependent MIPS 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 <stdint.h>
29 #include <ucontext.h>
30 
31 #include "vm/jit/mips/codegen.hpp"
32 #include "vm/jit/mips/md.hpp"
33 
34 #include "vm/jit/asmpart.hpp"
35 #include "vm/jit/jit.hpp"
36 #include "vm/jit/trap.hpp"
37 
38 
39 /* md_jit_method_patch_address *************************************************
40 
41  Gets the patch address of the currently compiled method. The offset
42  is extracted from the load instruction(s) before the jump and added
43  to the right base address (PV or REG_METHODPTR).
44 
45  INVOKESTATIC/SPECIAL:
46 
47  dfdeffb8 ld s8,-72(s8)
48  03c0f809 jalr s8
49  00000000 nop
50 
51  INVOKEVIRTUAL:
52 
53  dc990000 ld t9,0(a0)
54  df3e0000 ld s8,0(t9)
55  03c0f809 jalr s8
56  00000000 nop
57 
58  INVOKEINTERFACE:
59 
60  dc990000 ld t9,0(a0)
61  df39ff90 ld t9,-112(t9)
62  df3e0018 ld s8,24(t9)
63  03c0f809 jalr s8
64  00000000 nop
65 
66 *******************************************************************************/
67 
68 void *md_jit_method_patch_address(void *pv, void *ra, void *mptr)
69 {
70  uint32_t *pc;
71  uint32_t mcode;
72  int32_t offset;
73  void *pa;
74 
75  /* go back to the actual load instruction (3 instructions on MIPS) */
76 
77  pc = ((uint32_t *) ra) - 3;
78 
79  /* get first instruction word on current PC */
80 
81  mcode = pc[0];
82 
83  /* check if we have 2 instructions (lui) */
84 
85  if ((mcode >> 16) == 0x3c19) {
86  /* XXX write a regression for this */
87  assert(0);
88 
89  /* get displacement of first instruction (lui) */
90 
91  offset = (int32_t) (mcode << 16);
92 
93  /* get displacement of second instruction (daddiu) */
94 
95  mcode = pc[1];
96 
97  assert((mcode >> 16) != 0x6739);
98 
99  offset += (int16_t) (mcode & 0x0000ffff);
100 
101  pa = NULL;
102  }
103  else {
104  /* get the offset from the instruction */
105 
106  offset = (int16_t) (mcode & 0x0000ffff);
107 
108  /* check for call with REG_METHODPTR: ld s8,x(t9) */
109 
110 #if SIZEOF_VOID_P == 8
111  if ((mcode >> 16) == 0xdf3e) {
112 #else
113  if ((mcode >> 16) == 0x8f3e) {
114 #endif
115  /* in this case we use the passed method pointer */
116 
117  /* return NULL if no mptr was specified (used for replacement) */
118 
119  if (mptr == NULL)
120  return NULL;
121 
122  pa = ((uint8_t *) mptr) + offset;
123  }
124  else {
125  /* in the normal case we check for a `ld s8,x(s8)' instruction */
126 
127 #if SIZEOF_VOID_P == 8
128  assert((mcode >> 16) == 0xdfde);
129 #else
130  assert((mcode >> 16) == 0x8fde);
131 #endif
132 
133  /* and get the final data segment address */
134 
135  pa = ((uint8_t *) pv) + offset;
136  }
137  }
138 
139  return pa;
140 }
141 
142 
143 /**
144  * Decode the trap instruction at the given PC.
145  *
146  * @param trp information about trap to be filled
147  * @param sig signal number
148  * @param xpc exception PC
149  * @param es execution state of the machine
150  * @return true if trap was decoded successfully, false otherwise.
151  */
152 bool md_trap_decode(trapinfo_t* trp, int sig, void* xpc, executionstate_t* es)
153 {
154  // Get the exception-throwing instruction.
155  uint32_t mcode = *((uint32_t*) xpc);
156 
157  switch (sig) {
158  case TRAP_SIGILL:
159  // Check for valid trap instruction.
160  // TODO Check the whole instruction.
161  if (mcode == 0xec000000) {
162  trp->type = TRAP_PATCHER;
163  trp->value = 0;
164  return true;
165  }
166  return false;
167 
168  case TRAP_SIGSEGV:
169  {
170  // Retrieve base address of instruction.
171  int32_t s1 = M_ITYPE_GET_RS(mcode);
172  uintptr_t addr = es->intregs[s1];
173 
174  // Check for special-load.
175  if (s1 == REG_ZERO) {
176  int32_t d = M_ITYPE_GET_RT(mcode);
177  int32_t disp = M_ITYPE_GET_IMM(mcode);
178 
179  // We use the exception type as load displacement.
180  trp->type = disp;
181  trp->value = es->intregs[d];
182  return true;
183  }
184 
185  // Check for implicit NullPointerException.
186  if (addr == 0) {
188  trp->value = 0;
189  return true;
190  }
191 
192  return false;
193  }
194 
195  default:
196  return false;
197  }
198 }
199 
200 
201 /* md_patch_replacement_point **************************************************
202 
203  Patch the given replacement point.
204 
205 *******************************************************************************/
206 
207 #if defined(ENABLE_REPLACEMENT)
208 void md_patch_replacement_point(u1 *pc, u1 *savedmcode, bool revert)
209 {
210  union {
211  u8 both;
212  u4 words[2];
213  } mcode;
214 
215  if (revert) {
216  /* restore the patched-over instruction */
217  *(u8*)(pc) = *(u8*)(savedmcode);
218  }
219  else {
220  /* save the current machine code */
221  *(u8*)(savedmcode) = *(u8*)(pc);
222 
223  /* build the machine code for the patch */
224  assert(0); /* XXX build trap instruction below */
225  mcode.both = 0;
226 
227  /* write the new machine code */
228  *(u8*)(pc) = mcode.both;
229  }
230 
231  /* flush instruction cache */
232  md_icacheflush(pc,2*4);
233 }
234 #endif /* defined(ENABLE_REPLACEMENT) */
235 
236 
237 /*
238  * These are local overrides for various environment variables in Emacs.
239  * Please do not remove this and leave it at the end of the file, where
240  * Emacs will automagically detect them.
241  * ---------------------------------------------------------------------
242  * Local variables:
243  * mode: c++
244  * indent-tabs-mode: t
245  * c-basic-offset: 4
246  * tab-width: 4
247  * End:
248  * vim:noexpandtab:sw=4:ts=4:
249  */
#define M_ITYPE_GET_IMM(x)
Definition: codegen.hpp:106
#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
Contains information about a decoded trap instruction.
Definition: trap.hpp:42
uint8_t u1
Definition: types.hpp:40
#define xpc
Definition: md-asm.hpp:51
uint64_t u8
Definition: types.hpp:49
int type
Specific trap type (see md-trap.h).
Definition: trap.hpp:43
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
#define M_ITYPE_GET_RT(x)
Definition: codegen.hpp:105
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
static void md_icacheflush(void *addr, int nbytes)
Definition: md.hpp:151
#define M_ITYPE_GET_RS(x)
Definition: codegen.hpp:104