CACAO
md.cpp
Go to the documentation of this file.
1 /* src/vm/jit/aarch64/md.cpp - machine dependent Aarch64 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 
33 #include "vm/jit/aarch64/md.hpp"
34 
35 #include "vm/jit/asmpart.hpp"
36 #include "vm/jit/disass.hpp"
37 #include "vm/jit/jit.hpp"
38 #include "vm/jit/trap.hpp"
39 
40 bool has_ext_instr_set = false;
41 
42 /* md_init *********************************************************************
43 
44  Do some machine dependent initialization.
45 
46 *******************************************************************************/
47 
48 void md_init(void)
49 {
50  /* do nothing on aarch64 */
51 }
52 
53 
54 /* md_jit_method_patch_address *************************************************
55 
56  Gets the patch address of the currently compiled method. The offset
57  is extracted from the load instruction(s) before the jump and added
58  to the right base address (PV or REG_METHODPTR).
59 
60  INVOKESTATIC/SPECIAL:
61 
62  a77bffb8 ldq pv,-72(pv)
63  6b5b4000 jsr (pv)
64 
65  INVOKEVIRTUAL:
66 
67  a7900000 ldq at,0(a0)
68  a77c0000 ldq pv,0(at)
69  6b5b4000 jsr (pv)
70 
71  INVOKEINTERFACE:
72 
73  <patched call position>
74  mov x9, <interfacetable index>
75  mov x10, <method offset>
76  ldr x16, [x0, _]
77  ldr x16, [x16, x9]
78  ldr x17, [x16, x10]
79  blr x17
80 
81 *******************************************************************************/
82 
83 void *md_jit_method_patch_address(void *pv, void *ra, void *mptr)
84 {
85  uint32_t *pc;
86  uint32_t mcode;
87  int base;
88  int32_t disp;
89  void *pa; /* patch address */
90  u2 msb10; /* most significant 10 bits */
91  u2 msb11; /* most significant 11 bits */
92  bool invokeinterface = false;
93 
94  /* Go back to the load instruction (2 instructions). */
95  pc = ((uint32_t *) ra) - 3;
96 
97  /* Get first instruction word. */
98  mcode = pc[1];
99 
100  if (mcode == 0xd503201f)
101  mcode = pc[0];
102 
103  /* Get base register */
104  base = (mcode >> 5) & 0x1f;
105 
106 
107  /* Check for LDR or LDUR */
108  msb10 = (mcode >> 22) & 0x3ff;
109  msb11 = (mcode >> 21) & 0x7ff;
110 
111  if (msb10 == 0x3e5) { /* unsigned offset (LDR) */
112  disp = (mcode >> 10) & 0xfff;
113  disp *= 8; /* imm is encoded as imm/8 */
114  } else if (msb11 == 0x7c2) { /* unscaled immediate (LDUR) */
115  disp = (mcode >> 12) & 0xff;
116  if ((mcode >> 12) & 0x100) /* negative offset */
117  disp |= 0xffffff00;
118  } else if (msb11 == 0x7c3) { /* LDR from register --> previous instruction was a MOV */
119  /* if the instruction beforehand is a ldr as well, we have a invokeinterface */
120  if (((pc[0] >> 21) & 0x7ff) == 0x7c3)
121  invokeinterface = true;
122 
123  /* do nothing, offset is encoded in the previous MOVN instruction */
124  disp = 0;
125  } else {
126  vm_abort_disassemble(pc, 2, "md_jit_method_patch_address: unknown instruction %x", mcode);
127  return NULL;
128  }
129 
130  /* if negative offset is too big, we had to use a SUB or MOV beforehand */
131  if (disp == 0 && (msb11 == 0x7c2 || msb11 == 0x7c3)) {
132  uint32_t subcode = pc[0];
133  u1 high = (subcode >> 24) & 0xff;
134  if (high == 0xD1 && msb11 == 0x7c2) { /* Check for SUB */
135  // TODO: check that the target register is the same, as the one used by the LDR
136  int32_t offset = (subcode >> 10) & 0xfff;
137  disp = -offset;
138  } else if (high == 0x92 && msb11 == 0x7c3) { /* Check for MOVN */
139  int32_t offset = (subcode >> 5) & 0xffff;
140  disp = -offset - 1;
141  } else if (invokeinterface) {
142  uint32_t *movncode = ((uint32_t *) ra) - 4;
143  mcode = movncode[0];
144  high = (mcode >> 24) & 0xff;
145  if (high == 0x92) { /* check for MOVN */
146  int32_t offset = (mcode >> 5) & 0xffff;
147  disp = -offset - 1;
148  } else if (high == 0xd2) { /* check foir MOVZ */
149  int32_t offset = (mcode >> 5) & 0xffff;
150  disp = offset;
151  }
152  }
153  }
154 
155 
156  switch(base) {
157  case REG_PV:
158  /* Calculate the data segment address. */
159 
160  pa = ((uint8_t *) pv) + disp;
161  break;
162 
163  case REG_METHODPTR:
164  /* Return NULL if no mptr was specified (used for
165  replacement). */
166 
167  if (mptr == NULL)
168  return NULL;
169 
170  /* Calculate the address in the vftbl. */
171  pa = ((uint8_t *) mptr) + disp;
172  break;
173 
174  default:
175  vm_abort_disassemble(pc, 2, "md_jit_method_patch_address: unsupported base register %x", mcode);
176  return NULL;
177  }
178 
179  return pa;
180 }
181 
182 
183 /**
184  * Decode the trap instruction at the given PC.
185  *
186  * @param trp information about trap to be filled
187  * @param sig signal number
188  * @param xpc exception PC
189  * @param es execution state of the machine
190  * @return true if trap was decoded successfully, false otherwise.
191  */
192 bool md_trap_decode(trapinfo_t* trp, int sig, void* xpc, executionstate_t* es)
193 {
194  // Get the exception-throwing instruction.
195  uint32_t mcode = *((uint32_t*) xpc);
196 
197  switch (sig) {
198  case TRAP_SIGILL:
199  // Check for the mark
200  if ((mcode & 0xFF000000) == 0xE7000000) {
201  trp->type = (mcode >> 8) & 0xff;
202  u1 reg = mcode & 0xff;
203  trp->value = es->intregs[reg];
204  return true;
205  }
206 
207  return false;
208 
209  case TRAP_SIGSEGV:
210  {
211  // Retrieve base address of instruction.
212  u2 reg = (mcode >> 5) & 0x1f;
213  uintptr_t addr = es->intregs[reg];
214 
215  // Check for implicit NullPointerException.
216  if (addr == 0) {
218  trp->value = 0;
219  return true;
220  }
221 
222  return false;
223  }
224 
225  default:
226  vm_abort_disassemble(xpc, 1, "md_trap_decode: Unexpected signal: %d", sig);
227  return false;
228  }
229 }
230 
231 
232 /* md_patch_replacement_point **************************************************
233 
234  Patch the given replacement point.
235 
236 *******************************************************************************/
237 
238 #if defined(ENABLE_REPLACEMENT)
239 void md_patch_replacement_point(u1 *pc, u1 *savedmcode, bool revert)
240 {
241  os::abort("md_patch_replacement_point: NOT IMPLEMENTED!");
242 }
243 #endif /* defined(ENABLE_REPLACEMENT) */
244 
245 
246 /*
247  * These are local overrides for various environment variables in Emacs.
248  * Please do not remove this and leave it at the end of the file, where
249  * Emacs will automagically detect them.
250  * ---------------------------------------------------------------------
251  * Local variables:
252  * mode: c++
253  * indent-tabs-mode: t
254  * c-basic-offset: 4
255  * tab-width: 4
256  * End:
257  * vim:noexpandtab:sw=4:ts=4:
258  */
#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
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
#define xpc
Definition: md-asm.hpp:51
uint16_t u2
Definition: types.hpp:43
int type
Specific trap type (see md-trap.h).
Definition: trap.hpp:43
static void abort()
Definition: os.hpp:196
void * md_jit_method_patch_address(void *pv, void *ra, void *mptr)
Definition: md.cpp:83
#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
uintptr_t intregs[INT_REG_CNT]
void vm_abort_disassemble(void *pc, int count, const char *text,...)
Definition: vm.cpp:2001
void md_init(void)
Definition: md.cpp:48