CACAO
md.cpp
Go to the documentation of this file.
1 /* src/vm/jit/sparc64/md.cpp - machine dependent SPARC64 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 
34 
35 #include "vm/jit/asmpart.hpp"
37 #include "vm/jit/jit.hpp"
38 
39 
40 /* assembler function prototypes **********************************************/
41 void asm_store_fp_state_reg(u8 *mem);
42 void asm_load_fp_state_reg(u8 *mem);
43 
44 
45 /* NOP is defined as a SETHI instruction with rd and imm. set to zero */
46 /* therefore we check if the 22-bit immediate is zero */
47 #define IS_SETHI(instr) \
48  (((instr & 0xc1c00000) == 0x01000000) \
49  && ((instr & 0x3fffff) != 0x0))
50 
51 #define IS_LDX_IMM(instr) \
52  (((instr >> 13) & 0x60fc1) == 0x602c1)
53 
54 #define IS_SUB(instr) \
55  (((instr >> 13) & 0x60fc0) == 0x40100)
56 
57 inline s2 decode_13bit_imm(u4 instr) {
58  s2 imm;
59 
60  /* mask everything else in the instruction */
61  imm = instr & 0x00001fff;
62 
63  /* sign extend 13-bit to 16-bit */
64  imm <<= 3;
65  imm >>= 3;
66 
67  return imm;
68 }
69 
70 /* md_init *********************************************************************
71 
72  Do some machine dependent initialization.
73 
74 *******************************************************************************/
75 
76 void md_init(void)
77 {
78  /* do nothing */
79 }
80 
81 
82 /* md_jit_method_patch_address *************************************************
83 
84  Gets the patch address of the currently compiled method. The offset
85  is extracted from the load instruction(s) before the jump and added
86  to the right base address (PV or REG_METHODPTR).
87 
88  INVOKESTATIC/SPECIAL:
89 
90  ???????? ldx [i5 - 72],o5
91  ???????? jmp o5 <-- ra
92  ???????? nop
93 
94  w/ sethi (mptr in dseg out of 13-bit simm range)
95 
96  ???????? sethi hi(0x2000),o5
97  ???????? sub i5,o5,o5
98  ???????? ldx [o5 - 72],o5
99  ???????? jmp o5 <-- ra
100  ???????? nop
101 
102  INVOKEVIRTUAL:
103 
104  ???????? ldx [o0 + 0},g2
105  ???????? ldx [g2 + 0],o5
106  ???????? jmp o5 <-- ra
107  ???????? nop
108 
109  INVOKEINTERFACE:
110 
111  ???????? ldx [o0 + 0},g2
112  ???????? ldx [g2 - 112],g2
113  ???????? ldx [g2 + 24],o5
114  ???????? jmp o5 <-- ra
115  ???????? nop
116 
117 *******************************************************************************/
118 
119 void *md_jit_method_patch_address(void *pv, void *ra, void *mptr)
120 {
121  uint32_t *pc;
122  uint32_t mcode, mcode_sethi, mcode_masked;
123  int32_t disp;
124  uint8_t *iptr;
125  void *pa;
126 
127  /* Go back to the location of a possible sethi (3 instruction
128  before jump). */
129 
130  pc = ((uint32_t *) ra) - 3;
131 
132  /* note: ra is the address of the jump instruction on SPARC */
133 
134  mcode_sethi = pc[0];
135 
136  /* check for sethi instruction */
137 
138  if (IS_SETHI(mcode_sethi)) {
139  u4 mcode_sub, mcode_ldx;
140 
141  mcode_sub = pc[1];
142  mcode_ldx = pc[2];
143 
144  /* make sure the sequence of instructions is a loadhi */
145  if ((IS_SUB(mcode_sub)) && (IS_LDX_IMM(mcode_ldx)))
146  {
147 
148 
149  /* get 22-bit immediate of sethi instruction */
150 
151  disp = (int32_t) (mcode_sethi & 0x3fffff);
152  disp = disp << 10;
153 
154  /* goto next instruction */
155 
156  /* make sure it's a sub instruction (pv - big_disp) */
157  assert(IS_SUB(mcode_sub));
158  disp = -disp;
159 
160  /* get displacement of load instruction */
161 
162  assert(IS_LDX_IMM(mcode_ldx));
163 
164  disp += decode_13bit_imm(mcode_ldx);
165 
166  pa = ((uint8_t *) pv) + disp;
167 
168  return pa;
169  }
170  }
171 
172  /* we didn't find a sethi, or it didn't belong to a loadhi */
173  /* check for simple (one-instruction) load */
174 
175  mcode = pc[2];
176 
177  /* shift and mask rd */
178 
179  mcode_masked = (mcode >> 13) & 0x060fff;
180 
181  /* get the offset from the instruction */
182 
183  disp = decode_13bit_imm(mcode);
184 
185  /* check for call with rs1 == REG_METHODPTR: ldx [g2+x],pv_caller */
186 
187  if (mcode_masked == 0x0602c5) {
188  /* in this case we use the passed method pointer */
189 
190  /* return NULL if no mptr was specified (used for replacement) */
191 
192  if (mptr == NULL)
193  return NULL;
194 
195  pa = ((uint8_t *) mptr) + disp;
196 
197  } else {
198  /* in the normal case we check for a `ldx [i5+x],pv_caller' instruction */
199 
200  assert(mcode_masked == 0x0602fb);
201 
202  /* and get the final data segment address */
203 
204  pa = ((uint8_t *) pv) + disp;
205  }
206 
207  return pa;
208 }
209 
210 
211 /* md_patch_replacement_point **************************************************
212 
213  Patch the given replacement point.
214 
215 *******************************************************************************/
216 
217 #if defined(ENABLE_REPLACEMENT)
218 void md_patch_replacement_point(u1 *pc, u1 *savedmcode, bool revert)
219 {
220  u4 mcode;
221 
222  if (revert) {
223  /* restore the patched-over instruction */
224  *(u4*)(pc) = *(u4*)(savedmcode);
225  }
226  else {
227  /* save the current machine code */
228  *(u4*)(savedmcode) = *(u4*)(pc);
229 
230  /* build the machine code for the patch */
231  assert(0); /* XXX build trap instruction below */
232  mcode = 0;
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  * These are local overrides for various environment variables in Emacs.
245  * Please do not remove this and leave it at the end of the file, where
246  * Emacs will automagically detect them.
247  * ---------------------------------------------------------------------
248  * Local variables:
249  * mode: c++
250  * indent-tabs-mode: t
251  * c-basic-offset: 4
252  * tab-width: 4
253  * End:
254  * vim:noexpandtab:sw=4:ts=4:
255  */
#define pv
Definition: md-asm.hpp:65
#define mptr
Definition: md-asm.hpp:66
void asm_store_fp_state_reg(u8 *mem)
s2 decode_13bit_imm(u4 instr)
Definition: md.cpp:57
#define ra
Definition: md-asm.hpp:62
void asm_load_fp_state_reg(u8 *mem)
uint8_t u1
Definition: types.hpp:40
#define IS_LDX_IMM(instr)
Definition: md.cpp:51
uint64_t u8
Definition: types.hpp:49
#define IS_SUB(instr)
Definition: md.cpp:54
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
int16_t s2
Definition: types.hpp:42
void md_init(void)
Definition: md.cpp:48
#define IS_SETHI(instr)
Definition: md.cpp:47