CACAO
md.cpp
Go to the documentation of this file.
1 /* src/vm/jit/alpha/md.cpp - machine dependent Alpha 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 <stdint.h>
30 #include <ucontext.h>
31 
32 #if defined(__LINUX__)
33 # include <asm/fpu.h>
34 
35 extern "C" unsigned long ieee_get_fp_control();
36 extern "C" void ieee_set_fp_control(unsigned long fp_control);
37 #endif
38 
39 #include "vm/jit/alpha/codegen.hpp"
40 #include "vm/jit/alpha/md.hpp"
41 
42 #include "vm/jit/asmpart.hpp"
43 #include "vm/jit/jit.hpp"
44 #include "vm/jit/trap.hpp"
45 
46 
47 /* global variables ***********************************************************/
48 
49 bool has_ext_instr_set = false; /* has instruction set extensions */
50 
51 
52 /* md_init *********************************************************************
53 
54  Do some machine dependent initialization.
55 
56 *******************************************************************************/
57 
58 void md_init(void)
59 {
60 #if defined(__LINUX__)
61  unsigned long int fpcw;
62 #endif
63 
64  /* check for extended instruction set */
65 
67 
68 #if defined(__LINUX__)
69  /* Linux on Digital Alpha needs an initialisation of the ieee
70  floating point control for IEEE compliant arithmetic (option
71  -mieee of GCC). Under Digital Unix this is done
72  automatically. */
73 
74  /* initialize floating point control */
75 
76  fpcw = ieee_get_fp_control();
77 
78  fpcw = fpcw
79  & ~IEEE_TRAP_ENABLE_INV
80  & ~IEEE_TRAP_ENABLE_DZE
81  /* We dont want underflow. */
82 /* & ~IEEE_TRAP_ENABLE_UNF */
83  & ~IEEE_TRAP_ENABLE_OVF;
84 
85 /* fpcw = fpcw */
86 /* | IEEE_TRAP_ENABLE_INV */
87 /* | IEEE_TRAP_ENABLE_DZE */
88 /* | IEEE_TRAP_ENABLE_OVF */
89 /* | IEEE_TRAP_ENABLE_UNF */
90 /* | IEEE_TRAP_ENABLE_INE */
91 /* | IEEE_TRAP_ENABLE_DNO; */
92 
93  ieee_set_fp_control(fpcw);
94 #endif
95 }
96 
97 
98 /* md_jit_method_patch_address *************************************************
99 
100  Gets the patch address of the currently compiled method. The offset
101  is extracted from the load instruction(s) before the jump and added
102  to the right base address (PV or REG_METHODPTR).
103 
104  INVOKESTATIC/SPECIAL:
105 
106  a77bffb8 ldq pv,-72(pv)
107  6b5b4000 jsr (pv)
108 
109  INVOKEVIRTUAL:
110 
111  a7900000 ldq at,0(a0)
112  a77c0000 ldq pv,0(at)
113  6b5b4000 jsr (pv)
114 
115  INVOKEINTERFACE:
116 
117  a7900000 ldq at,0(a0)
118  a79cff98 ldq at,-104(at)
119  a77c0018 ldq pv,24(at)
120  6b5b4000 jsr (pv)
121 
122 *******************************************************************************/
123 
124 void *md_jit_method_patch_address(void *pv, void *ra, void *mptr)
125 {
126  uint32_t *pc;
127  uint32_t mcode;
128  int opcode;
129  int base;
130  int32_t disp;
131  void *pa; /* patch address */
132 
133  /* Go back to the load instruction (2 instructions). */
134 
135  pc = ((uint32_t *) ra) - 2;
136 
137  /* Get first instruction word. */
138 
139  mcode = pc[0];
140 
141  /* Get opcode, base register and displacement. */
142 
143  opcode = M_MEM_GET_Opcode(mcode);
144  base = M_MEM_GET_Rb(mcode);
145  disp = M_MEM_GET_Memory_disp(mcode);
146 
147  /* Check for short or long load (2 instructions). */
148 
149  switch (opcode) {
150  case 0x29: /* LDQ: TODO use define */
151  switch (base) {
152  case REG_PV:
153  /* Calculate the data segment address. */
154 
155  pa = ((uint8_t *) pv) + disp;
156  break;
157 
158  case REG_METHODPTR:
159  /* Return NULL if no mptr was specified (used for
160  replacement). */
161 
162  if (mptr == NULL)
163  return NULL;
164 
165  /* Calculate the address in the vftbl. */
166 
167  pa = ((uint8_t *) mptr) + disp;
168  break;
169 
170  default:
171  vm_abort_disassemble(pc, 2, "md_jit_method_patch_address: unknown instruction %x", mcode);
172  return NULL;
173  }
174  break;
175 
176  case 0x09: /* LDAH: TODO use define */
177  /* XXX write a regression for this */
178 
179  vm_abort("md_jit_method_patch_address: IMPLEMENT ME!");
180 
181  pa = NULL;
182  break;
183 
184  default:
185  vm_abort_disassemble(pc, 2, "md_jit_method_patch_address: unknown instruction %x", mcode);
186  return NULL;
187  }
188 
189  return pa;
190 }
191 
192 
193 /**
194  * Decode the trap instruction at the given PC.
195  *
196  * @param trp information about trap to be filled
197  * @param sig signal number
198  * @param xpc exception PC
199  * @param es execution state of the machine
200  * @return true if trap was decoded successfully, false otherwise.
201  */
202 bool md_trap_decode(trapinfo_t* trp, int sig, void* xpc, executionstate_t* es)
203 {
204  // Get the exception-throwing instruction.
205  uint32_t mcode = *((uint32_t*) xpc);
206 
207  switch (sig) {
208  case TRAP_SIGILL:
209  // Check for valid trap instruction.
210  // TODO Check the whole instruction.
211  if (M_OP3_GET_Opcode(mcode) == 0x4) {
212  trp->type = TRAP_PATCHER;
213  trp->value = 0;
214  return true;
215  }
216  return false;
217 
218  case TRAP_SIGSEGV:
219  {
220  // Retrieve base address of instruction.
221  int32_t s1 = M_MEM_GET_Rb(mcode);
222  uintptr_t addr = es->intregs[s1];
223 
224  // Check for special-load.
225  if (s1 == REG_ZERO) {
226  int32_t d = M_MEM_GET_Ra(mcode);
227  int32_t disp = M_MEM_GET_Memory_disp(mcode);
228 
229  // We use the exception type as load displacement.
230  trp->type = disp;
231  trp->value = es->intregs[d];
232  return true;
233  }
234 
235  // Check for implicit NullPointerException.
236  if (addr == 0) {
238  trp->value = 0;
239  return true;
240  }
241 
242  return false;
243  }
244 
245  default:
246  return false;
247  }
248 }
249 
250 
251 /* md_patch_replacement_point **************************************************
252 
253  Patch the given replacement point.
254 
255 *******************************************************************************/
256 
257 #if defined(ENABLE_REPLACEMENT)
258 void md_patch_replacement_point(u1 *pc, u1 *savedmcode, bool revert)
259 {
260  u4 mcode;
261 
262  if (revert) {
263  /* restore the patched-over instruction */
264  *(u4*)(pc) = *(u4*)(savedmcode);
265  }
266  else {
267  /* save the current machine code */
268  *(u4*)(savedmcode) = *(u4*)(pc);
269 
270  /* build the machine code for the patch */
271  mcode = (0xa41f0000 | (TRAP_PATCHER));
272 
273  /* write the new machine code */
274  *(u4*)(pc) = mcode;
275  }
276 
277  /* flush instruction cache */
278  md_icacheflush(pc,4);
279 }
280 #endif /* defined(ENABLE_REPLACEMENT) */
281 
282 
283 /*
284  * These are local overrides for various environment variables in Emacs.
285  * Please do not remove this and leave it at the end of the file, where
286  * Emacs will automagically detect them.
287  * ---------------------------------------------------------------------
288  * Local variables:
289  * mode: c++
290  * indent-tabs-mode: t
291  * c-basic-offset: 4
292  * tab-width: 4
293  * End:
294  * vim:noexpandtab:sw=4:ts=4:
295  */
#define pv
Definition: md-asm.hpp:65
#define REG_PV
Definition: md-abi.hpp:42
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_MEM_GET_Opcode(x)
Definition: codegen.hpp:101
Contains information about a decoded trap instruction.
Definition: trap.hpp:42
bool has_ext_instr_set
Definition: md.cpp:40
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_MEM_GET_Memory_disp(x)
Definition: codegen.hpp:104
void * md_jit_method_patch_address(void *pv, void *ra, void *mptr)
Definition: md.cpp:83
uint32_t u4
Definition: types.hpp:46
#define M_MEM_GET_Rb(x)
Definition: codegen.hpp:103
#define M_MEM_GET_Ra(x)
Definition: codegen.hpp:102
#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
#define REG_METHODPTR
Definition: md-abi.hpp:43
int8_t s1
Definition: types.hpp:39
uintptr_t intregs[INT_REG_CNT]
#define REG_ZERO
Definition: md-abi.hpp:54
void vm_abort_disassemble(void *pc, int count, const char *text,...)
Definition: vm.cpp:2001
#define M_OP3_GET_Opcode(x)
Definition: codegen.hpp:142
void md_init(void)
Definition: md.cpp:48
static void md_icacheflush(void *addr, int nbytes)
Definition: md.hpp:151
s4 asm_md_init(void)