Mercurial > hg > graal-jvmci-8
annotate src/cpu/sparc/vm/nativeInst_sparc.hpp @ 23660:b5f3a471e646
Merge.
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Wed, 01 Jun 2016 00:11:44 +0200 |
parents | 3da4f19cf93b |
children |
rev | line source |
---|---|
0 | 1 /* |
17524 | 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. |
0 | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | |
5 * This code is free software; you can redistribute it and/or modify it | |
6 * under the terms of the GNU General Public License version 2 only, as | |
7 * published by the Free Software Foundation. | |
8 * | |
9 * This code is distributed in the hope that it will be useful, but WITHOUT | |
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 * version 2 for more details (a copy is included in the LICENSE file that | |
13 * accompanied this code). | |
14 * | |
15 * You should have received a copy of the GNU General Public License version | |
16 * 2 along with this work; if not, write to the Free Software Foundation, | |
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
18 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
605
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
605
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
605
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #ifndef CPU_SPARC_VM_NATIVEINST_SPARC_HPP |
26 #define CPU_SPARC_VM_NATIVEINST_SPARC_HPP | |
27 | |
7204
f0c2369fda5a
8003250: SPARC: move MacroAssembler into separate file
twisti
parents:
6725
diff
changeset
|
28 #include "asm/macroAssembler.hpp" |
1972 | 29 #include "memory/allocation.hpp" |
30 #include "runtime/icache.hpp" | |
31 #include "runtime/os.hpp" | |
32 #include "utilities/top.hpp" | |
33 | |
0 | 34 // We have interface for the following instructions: |
35 // - NativeInstruction | |
36 // - - NativeCall | |
37 // - - NativeFarCall | |
38 // - - NativeMovConstReg | |
39 // - - NativeMovConstRegPatching | |
40 // - - NativeMovRegMem | |
41 // - - NativeMovRegMemPatching | |
42 // - - NativeJump | |
43 // - - NativeGeneralJump | |
44 // - - NativeIllegalInstruction | |
45 // The base class for different kinds of native instruction abstractions. | |
46 // Provides the primitive operations to manipulate code relative to this. | |
47 class NativeInstruction VALUE_OBJ_CLASS_SPEC { | |
48 friend class Relocation; | |
49 | |
50 public: | |
51 enum Sparc_specific_constants { | |
52 nop_instruction_size = 4 | |
53 }; | |
54 | |
116
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
55 bool is_dtrace_trap(); |
0 | 56 bool is_nop() { return long_at(0) == nop_instruction(); } |
57 bool is_call() { return is_op(long_at(0), Assembler::call_op); } | |
11233 | 58 bool is_call_reg() { return is_op(long_at(0), Assembler::arith_op); } |
0 | 59 bool is_sethi() { return (is_op2(long_at(0), Assembler::sethi_op2) |
60 && inv_rd(long_at(0)) != G0); } | |
61 | |
62 bool sets_cc() { | |
63 // conservative (returns true for some instructions that do not set the | |
64 // the condition code, such as, "save". | |
65 // Does not return true for the deprecated tagged instructions, such as, TADDcc | |
66 int x = long_at(0); | |
67 return (is_op(x, Assembler::arith_op) && | |
68 (inv_op3(x) & Assembler::cc_bit_op3) == Assembler::cc_bit_op3); | |
69 } | |
70 bool is_illegal(); | |
71 bool is_zombie() { | |
72 int x = long_at(0); | |
73 return is_op3(x, | |
10997 | 74 Assembler::ldsw_op3, |
0 | 75 Assembler::ldst_op) |
76 && Assembler::inv_rs1(x) == G0 | |
77 && Assembler::inv_rd(x) == O7; | |
78 } | |
79 bool is_ic_miss_trap(); // Inline-cache uses a trap to detect a miss | |
80 bool is_return() { | |
81 // is it the output of MacroAssembler::ret or MacroAssembler::retl? | |
82 int x = long_at(0); | |
83 const int pc_return_offset = 8; // see frame_sparc.hpp | |
84 return is_op3(x, Assembler::jmpl_op3, Assembler::arith_op) | |
85 && (inv_rs1(x) == I7 || inv_rs1(x) == O7) | |
86 && inv_immed(x) && inv_simm(x, 13) == pc_return_offset | |
87 && inv_rd(x) == G0; | |
88 } | |
89 bool is_int_jump() { | |
90 // is it the output of MacroAssembler::b? | |
91 int x = long_at(0); | |
92 return is_op2(x, Assembler::bp_op2) || is_op2(x, Assembler::br_op2); | |
93 } | |
94 bool is_float_jump() { | |
95 // is it the output of MacroAssembler::fb? | |
96 int x = long_at(0); | |
97 return is_op2(x, Assembler::fbp_op2) || is_op2(x, Assembler::fb_op2); | |
98 } | |
99 bool is_jump() { | |
100 return is_int_jump() || is_float_jump(); | |
101 } | |
102 bool is_cond_jump() { | |
103 int x = long_at(0); | |
104 return (is_int_jump() && Assembler::inv_cond(x) != Assembler::always) || | |
105 (is_float_jump() && Assembler::inv_cond(x) != Assembler::f_always); | |
106 } | |
107 | |
108 bool is_stack_bang() { | |
109 int x = long_at(0); | |
110 return is_op3(x, Assembler::stw_op3, Assembler::ldst_op) && | |
111 (inv_rd(x) == G0) && (inv_rs1(x) == SP) && (inv_rs2(x) == G3_scratch); | |
112 } | |
113 | |
114 bool is_prefetch() { | |
115 int x = long_at(0); | |
116 return is_op3(x, Assembler::prefetch_op3, Assembler::ldst_op); | |
117 } | |
118 | |
119 bool is_membar() { | |
120 int x = long_at(0); | |
121 return is_op3(x, Assembler::membar_op3, Assembler::arith_op) && | |
122 (inv_rd(x) == G0) && (inv_rs1(x) == O7); | |
123 } | |
124 | |
125 bool is_safepoint_poll() { | |
126 int x = long_at(0); | |
127 #ifdef _LP64 | |
128 return is_op3(x, Assembler::ldx_op3, Assembler::ldst_op) && | |
129 #else | |
130 return is_op3(x, Assembler::lduw_op3, Assembler::ldst_op) && | |
131 #endif | |
132 (inv_rd(x) == G0) && (inv_immed(x) ? Assembler::inv_simm13(x) == 0 : inv_rs2(x) == G0); | |
133 } | |
134 | |
135 bool is_zero_test(Register ®); | |
136 bool is_load_store_with_small_offset(Register reg); | |
137 | |
138 public: | |
139 #ifdef ASSERT | |
140 static int rdpc_instruction() { return Assembler::op(Assembler::arith_op ) | Assembler::op3(Assembler::rdreg_op3) | Assembler::u_field(5, 18, 14) | Assembler::rd(O7); } | |
141 #else | |
142 // Temporary fix: in optimized mode, u_field is a macro for efficiency reasons (see Assembler::u_field) - needs to be fixed | |
143 static int rdpc_instruction() { return Assembler::op(Assembler::arith_op ) | Assembler::op3(Assembler::rdreg_op3) | u_field(5, 18, 14) | Assembler::rd(O7); } | |
144 #endif | |
145 static int nop_instruction() { return Assembler::op(Assembler::branch_op) | Assembler::op2(Assembler::sethi_op2); } | |
146 static int illegal_instruction(); // the output of __ breakpoint_trap() | |
147 static int call_instruction(address destination, address pc) { return Assembler::op(Assembler::call_op) | Assembler::wdisp((intptr_t)destination, (intptr_t)pc, 30); } | |
148 | |
149 static int branch_instruction(Assembler::op2s op2val, Assembler::Condition c, bool a) { | |
150 return Assembler::op(Assembler::branch_op) | Assembler::op2(op2val) | Assembler::annul(a) | Assembler::cond(c); | |
151 } | |
152 | |
153 static int op3_instruction(Assembler::ops opval, Register rd, Assembler::op3s op3val, Register rs1, int simm13a) { | |
154 return Assembler::op(opval) | Assembler::rd(rd) | Assembler::op3(op3val) | Assembler::rs1(rs1) | Assembler::immed(true) | Assembler::simm(simm13a, 13); | |
155 } | |
156 | |
157 static int sethi_instruction(Register rd, int imm22a) { | |
158 return Assembler::op(Assembler::branch_op) | Assembler::rd(rd) | Assembler::op2(Assembler::sethi_op2) | Assembler::hi22(imm22a); | |
159 } | |
160 | |
161 protected: | |
162 address addr_at(int offset) const { return address(this) + offset; } | |
163 int long_at(int offset) const { return *(int*)addr_at(offset); } | |
164 void set_long_at(int offset, int i); /* deals with I-cache */ | |
165 void set_jlong_at(int offset, jlong i); /* deals with I-cache */ | |
166 void set_addr_at(int offset, address x); /* deals with I-cache */ | |
167 | |
168 address instruction_address() const { return addr_at(0); } | |
169 address next_instruction_address() const { return addr_at(BytesPerInstWord); } | |
170 | |
171 static bool is_op( int x, Assembler::ops opval) { | |
172 return Assembler::inv_op(x) == opval; | |
173 } | |
174 static bool is_op2(int x, Assembler::op2s op2val) { | |
175 return Assembler::inv_op(x) == Assembler::branch_op && Assembler::inv_op2(x) == op2val; | |
176 } | |
177 static bool is_op3(int x, Assembler::op3s op3val, Assembler::ops opval) { | |
178 return Assembler::inv_op(x) == opval && Assembler::inv_op3(x) == op3val; | |
179 } | |
180 | |
181 // utilities to help subclasses decode: | |
182 static Register inv_rd( int x ) { return Assembler::inv_rd( x); } | |
183 static Register inv_rs1( int x ) { return Assembler::inv_rs1(x); } | |
184 static Register inv_rs2( int x ) { return Assembler::inv_rs2(x); } | |
185 | |
186 static bool inv_immed( int x ) { return Assembler::inv_immed(x); } | |
187 static bool inv_annul( int x ) { return (Assembler::annul(true) & x) != 0; } | |
188 static int inv_cond( int x ) { return Assembler::inv_cond(x); } | |
189 | |
190 static int inv_op( int x ) { return Assembler::inv_op( x); } | |
191 static int inv_op2( int x ) { return Assembler::inv_op2(x); } | |
192 static int inv_op3( int x ) { return Assembler::inv_op3(x); } | |
193 | |
194 static int inv_simm( int x, int nbits ) { return Assembler::inv_simm(x, nbits); } | |
195 static intptr_t inv_wdisp( int x, int nbits ) { return Assembler::inv_wdisp( x, 0, nbits); } | |
196 static intptr_t inv_wdisp16( int x ) { return Assembler::inv_wdisp16(x, 0); } | |
7204
f0c2369fda5a
8003250: SPARC: move MacroAssembler into separate file
twisti
parents:
6725
diff
changeset
|
197 static int branch_destination_offset(int x) { return MacroAssembler::branch_destination(x, 0); } |
0 | 198 static int patch_branch_destination_offset(int dest_offset, int x) { |
7204
f0c2369fda5a
8003250: SPARC: move MacroAssembler into separate file
twisti
parents:
6725
diff
changeset
|
199 return MacroAssembler::patched_branch(dest_offset, x, 0); |
0 | 200 } |
201 | |
202 // utility for checking if x is either of 2 small constants | |
203 static bool is_either(int x, int k1, int k2) { | |
204 // return x == k1 || x == k2; | |
205 return (1 << x) & (1 << k1 | 1 << k2); | |
206 } | |
207 | |
208 // utility for checking overflow of signed instruction fields | |
209 static bool fits_in_simm(int x, int nbits) { | |
210 // cf. Assembler::assert_signed_range() | |
211 // return -(1 << nbits-1) <= x && x < ( 1 << nbits-1), | |
212 return (unsigned)(x + (1 << nbits-1)) < (unsigned)(1 << nbits); | |
213 } | |
214 | |
215 // set a signed immediate field | |
216 static int set_simm(int insn, int imm, int nbits) { | |
217 return (insn &~ Assembler::simm(-1, nbits)) | Assembler::simm(imm, nbits); | |
218 } | |
219 | |
220 // set a wdisp field (disp should be the difference of two addresses) | |
221 static int set_wdisp(int insn, intptr_t disp, int nbits) { | |
222 return (insn &~ Assembler::wdisp((intptr_t)-4, (intptr_t)0, nbits)) | Assembler::wdisp(disp, 0, nbits); | |
223 } | |
224 | |
225 static int set_wdisp16(int insn, intptr_t disp) { | |
226 return (insn &~ Assembler::wdisp16((intptr_t)-4, 0)) | Assembler::wdisp16(disp, 0); | |
227 } | |
228 | |
229 // get a simm13 field from an arithmetic or memory instruction | |
230 static int get_simm13(int insn) { | |
231 assert(is_either(Assembler::inv_op(insn), | |
232 Assembler::arith_op, Assembler::ldst_op) && | |
233 (insn & Assembler::immed(true)), "must have a simm13 field"); | |
234 return Assembler::inv_simm(insn, 13); | |
235 } | |
236 | |
237 // set the simm13 field of an arithmetic or memory instruction | |
238 static bool set_simm13(int insn, int imm) { | |
239 get_simm13(insn); // tickle the assertion check | |
240 return set_simm(insn, imm, 13); | |
241 } | |
242 | |
243 // combine the fields of a sethi stream (7 instructions ) and an add, jmp or ld/st | |
244 static intptr_t data64( address pc, int arith_insn ) { | |
245 assert(is_op2(*(unsigned int *)pc, Assembler::sethi_op2), "must be sethi"); | |
246 intptr_t hi = (intptr_t)gethi( (unsigned int *)pc ); | |
247 intptr_t lo = (intptr_t)get_simm13(arith_insn); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
2426
diff
changeset
|
248 assert((unsigned)lo < (1 << 10), "offset field of set_metadata must be 10 bits"); |
0 | 249 return hi | lo; |
250 } | |
251 | |
252 // Regenerate the instruction sequence that performs the 64 bit | |
253 // sethi. This only does the sethi. The disp field (bottom 10 bits) | |
605 | 254 // must be handled separately. |
0 | 255 static void set_data64_sethi(address instaddr, intptr_t x); |
2375
d673ef06fe96
7028374: race in fix_oop_relocations for scavengeable nmethods
never
parents:
1972
diff
changeset
|
256 static void verify_data64_sethi(address instaddr, intptr_t x); |
0 | 257 |
258 // combine the fields of a sethi/simm13 pair (simm13 = or, add, jmpl, ld/st) | |
259 static int data32(int sethi_insn, int arith_insn) { | |
260 assert(is_op2(sethi_insn, Assembler::sethi_op2), "must be sethi"); | |
261 int hi = Assembler::inv_hi22(sethi_insn); | |
262 int lo = get_simm13(arith_insn); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
2426
diff
changeset
|
263 assert((unsigned)lo < (1 << 10), "offset field of set_metadata must be 10 bits"); |
0 | 264 return hi | lo; |
265 } | |
266 | |
267 static int set_data32_sethi(int sethi_insn, int imm) { | |
268 // note that Assembler::hi22 clips the low 10 bits for us | |
269 assert(is_op2(sethi_insn, Assembler::sethi_op2), "must be sethi"); | |
270 return (sethi_insn &~ Assembler::hi22(-1)) | Assembler::hi22(imm); | |
271 } | |
272 | |
273 static int set_data32_simm13(int arith_insn, int imm) { | |
274 get_simm13(arith_insn); // tickle the assertion check | |
275 int imm10 = Assembler::low10(imm); | |
276 return (arith_insn &~ Assembler::simm(-1, 13)) | Assembler::simm(imm10, 13); | |
277 } | |
278 | |
279 static int low10(int imm) { | |
280 return Assembler::low10(imm); | |
281 } | |
282 | |
283 // Perform the inverse of the LP64 Macroassembler::sethi | |
284 // routine. Extracts the 54 bits of address from the instruction | |
285 // stream. This routine must agree with the sethi routine in | |
286 // assembler_inline_sparc.hpp | |
287 static address gethi( unsigned int *pc ) { | |
288 int i = 0; | |
289 uintptr_t adr; | |
290 // We first start out with the real sethi instruction | |
291 assert(is_op2(*pc, Assembler::sethi_op2), "in gethi - must be sethi"); | |
292 adr = (unsigned int)Assembler::inv_hi22( *(pc++) ); | |
293 i++; | |
294 while ( i < 7 ) { | |
295 // We're done if we hit a nop | |
296 if ( (int)*pc == nop_instruction() ) break; | |
297 assert ( Assembler::inv_op(*pc) == Assembler::arith_op, "in gethi - must be arith_op" ); | |
298 switch ( Assembler::inv_op3(*pc) ) { | |
299 case Assembler::xor_op3: | |
300 adr ^= (intptr_t)get_simm13( *pc ); | |
301 return ( (address)adr ); | |
302 break; | |
303 case Assembler::sll_op3: | |
304 adr <<= ( *pc & 0x3f ); | |
305 break; | |
306 case Assembler::or_op3: | |
307 adr |= (intptr_t)get_simm13( *pc ); | |
308 break; | |
309 default: | |
310 assert ( 0, "in gethi - Should not reach here" ); | |
311 break; | |
312 } | |
313 pc++; | |
314 i++; | |
315 } | |
316 return ( (address)adr ); | |
317 } | |
318 | |
319 public: | |
320 void verify(); | |
321 void print(); | |
322 | |
323 // unit test stuff | |
324 static void test() {} // override for testing | |
325 | |
326 inline friend NativeInstruction* nativeInstruction_at(address address); | |
327 }; | |
328 | |
329 inline NativeInstruction* nativeInstruction_at(address address) { | |
330 NativeInstruction* inst = (NativeInstruction*)address; | |
331 #ifdef ASSERT | |
332 inst->verify(); | |
333 #endif | |
334 return inst; | |
335 } | |
336 | |
337 | |
338 | |
339 //----------------------------------------------------------------------------- | |
340 | |
341 // The NativeCall is an abstraction for accessing/manipulating native call imm32 instructions. | |
342 // (used to manipulate inline caches, primitive & dll calls, etc.) | |
343 inline NativeCall* nativeCall_at(address instr); | |
344 inline NativeCall* nativeCall_overwriting_at(address instr, | |
345 address destination); | |
346 inline NativeCall* nativeCall_before(address return_address); | |
347 class NativeCall: public NativeInstruction { | |
348 public: | |
349 enum Sparc_specific_constants { | |
350 instruction_size = 8, | |
351 return_address_offset = 8, | |
352 call_displacement_width = 30, | |
353 displacement_offset = 0, | |
354 instruction_offset = 0 | |
355 }; | |
356 address instruction_address() const { return addr_at(0); } | |
357 address next_instruction_address() const { return addr_at(instruction_size); } | |
358 address return_address() const { return addr_at(return_address_offset); } | |
359 | |
360 address destination() const { return inv_wdisp(long_at(0), call_displacement_width) + instruction_address(); } | |
361 address displacement_address() const { return addr_at(displacement_offset); } | |
362 void set_destination(address dest) { set_long_at(0, set_wdisp(long_at(0), dest - instruction_address(), call_displacement_width)); } | |
363 void set_destination_mt_safe(address dest); | |
364 | |
365 void verify_alignment() {} // do nothing on sparc | |
366 void verify(); | |
367 void print(); | |
368 | |
369 // unit test stuff | |
370 static void test(); | |
371 | |
372 // Creation | |
373 friend inline NativeCall* nativeCall_at(address instr); | |
374 friend NativeCall* nativeCall_overwriting_at(address instr, address destination = NULL) { | |
375 // insert a "blank" call: | |
376 NativeCall* call = (NativeCall*)instr; | |
377 call->set_long_at(0 * BytesPerInstWord, call_instruction(destination, instr)); | |
378 call->set_long_at(1 * BytesPerInstWord, nop_instruction()); | |
379 assert(call->addr_at(2 * BytesPerInstWord) - instr == instruction_size, "instruction size"); | |
380 // check its structure now: | |
381 assert(nativeCall_at(instr)->destination() == destination, "correct call destination"); | |
382 return call; | |
383 } | |
384 | |
385 friend inline NativeCall* nativeCall_before(address return_address) { | |
386 NativeCall* call = (NativeCall*)(return_address - return_address_offset); | |
387 #ifdef ASSERT | |
388 call->verify(); | |
389 #endif | |
390 return call; | |
391 } | |
392 | |
393 static bool is_call_at(address instr) { | |
394 return nativeInstruction_at(instr)->is_call(); | |
395 } | |
396 | |
397 static bool is_call_before(address instr) { | |
398 return nativeInstruction_at(instr - return_address_offset)->is_call(); | |
399 } | |
400 | |
401 static bool is_call_to(address instr, address target) { | |
402 return nativeInstruction_at(instr)->is_call() && | |
403 nativeCall_at(instr)->destination() == target; | |
404 } | |
405 | |
406 // MT-safe patching of a call instruction. | |
407 static void insert(address code_pos, address entry) { | |
408 (void)nativeCall_overwriting_at(code_pos, entry); | |
409 } | |
410 | |
411 static void replace_mt_safe(address instr_addr, address code_buffer); | |
412 }; | |
413 inline NativeCall* nativeCall_at(address instr) { | |
414 NativeCall* call = (NativeCall*)instr; | |
415 #ifdef ASSERT | |
416 call->verify(); | |
417 #endif | |
418 return call; | |
419 } | |
420 | |
11233 | 421 class NativeCallReg: public NativeInstruction { |
422 public: | |
423 enum Sparc_specific_constants { | |
424 instruction_size = 8, | |
425 return_address_offset = 8, | |
426 instruction_offset = 0 | |
427 }; | |
428 | |
429 address next_instruction_address() const { | |
430 return addr_at(instruction_size); | |
431 } | |
432 }; | |
433 | |
0 | 434 // The NativeFarCall is an abstraction for accessing/manipulating native call-anywhere |
435 // instructions in the sparcv9 vm. Used to call native methods which may be loaded | |
436 // anywhere in the address space, possibly out of reach of a call instruction. | |
437 | |
438 #ifndef _LP64 | |
439 | |
440 // On 32-bit systems, a far call is the same as a near one. | |
441 class NativeFarCall; | |
442 inline NativeFarCall* nativeFarCall_at(address instr); | |
443 class NativeFarCall : public NativeCall { | |
444 public: | |
445 friend inline NativeFarCall* nativeFarCall_at(address instr) { return (NativeFarCall*)nativeCall_at(instr); } | |
446 friend NativeFarCall* nativeFarCall_overwriting_at(address instr, address destination = NULL) | |
447 { return (NativeFarCall*)nativeCall_overwriting_at(instr, destination); } | |
448 friend NativeFarCall* nativeFarCall_before(address return_address) | |
449 { return (NativeFarCall*)nativeCall_before(return_address); } | |
450 }; | |
451 | |
452 #else | |
453 | |
454 // The format of this extended-range call is: | |
455 // jumpl_to addr, lreg | |
456 // == sethi %hi54(addr), O7 ; jumpl O7, %lo10(addr), O7 ; <delay> | |
457 // That is, it is essentially the same as a NativeJump. | |
458 class NativeFarCall; | |
459 inline NativeFarCall* nativeFarCall_overwriting_at(address instr, address destination); | |
460 inline NativeFarCall* nativeFarCall_at(address instr); | |
461 class NativeFarCall: public NativeInstruction { | |
462 public: | |
463 enum Sparc_specific_constants { | |
464 // instruction_size includes the delay slot instruction. | |
465 instruction_size = 9 * BytesPerInstWord, | |
466 return_address_offset = 9 * BytesPerInstWord, | |
467 jmpl_offset = 7 * BytesPerInstWord, | |
468 displacement_offset = 0, | |
469 instruction_offset = 0 | |
470 }; | |
471 address instruction_address() const { return addr_at(0); } | |
472 address next_instruction_address() const { return addr_at(instruction_size); } | |
473 address return_address() const { return addr_at(return_address_offset); } | |
474 | |
475 address destination() const { | |
476 return (address) data64(addr_at(0), long_at(jmpl_offset)); | |
477 } | |
478 address displacement_address() const { return addr_at(displacement_offset); } | |
479 void set_destination(address dest); | |
480 | |
481 bool destination_is_compiled_verified_entry_point(); | |
482 | |
483 void verify(); | |
484 void print(); | |
485 | |
486 // unit test stuff | |
487 static void test(); | |
488 | |
489 // Creation | |
490 friend inline NativeFarCall* nativeFarCall_at(address instr) { | |
491 NativeFarCall* call = (NativeFarCall*)instr; | |
492 #ifdef ASSERT | |
493 call->verify(); | |
494 #endif | |
495 return call; | |
496 } | |
497 | |
498 friend inline NativeFarCall* nativeFarCall_overwriting_at(address instr, address destination = NULL) { | |
499 Unimplemented(); | |
500 NativeFarCall* call = (NativeFarCall*)instr; | |
501 return call; | |
502 } | |
503 | |
504 friend NativeFarCall* nativeFarCall_before(address return_address) { | |
505 NativeFarCall* call = (NativeFarCall*)(return_address - return_address_offset); | |
506 #ifdef ASSERT | |
507 call->verify(); | |
508 #endif | |
509 return call; | |
510 } | |
511 | |
512 static bool is_call_at(address instr); | |
513 | |
514 // MT-safe patching of a call instruction. | |
515 static void insert(address code_pos, address entry) { | |
516 (void)nativeFarCall_overwriting_at(code_pos, entry); | |
517 } | |
518 static void replace_mt_safe(address instr_addr, address code_buffer); | |
519 }; | |
520 | |
521 #endif // _LP64 | |
522 | |
22690
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
523 // An interface for accessing/manipulating 32 bit native set_metadata imm, reg instructions |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
524 // (used to manipulate inlined data references, etc.) |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
525 // set_metadata imm, reg |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
526 // == sethi %hi22(imm), reg ; add reg, %lo10(imm), reg |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
527 class NativeMovConstReg32; |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
528 inline NativeMovConstReg32* nativeMovConstReg32_at(address address); |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
529 class NativeMovConstReg32: public NativeInstruction { |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
530 public: |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
531 enum Sparc_specific_constants { |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
532 sethi_offset = 0, |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
533 add_offset = 4, |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
534 instruction_size = 8 |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
535 }; |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
536 |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
537 address instruction_address() const { return addr_at(0); } |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
538 address next_instruction_address() const { return addr_at(instruction_size); } |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
539 |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
540 // (The [set_]data accessor respects oop_type relocs also.) |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
541 intptr_t data() const; |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
542 void set_data(intptr_t x); |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
543 |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
544 // report the destination register |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
545 Register destination() { return inv_rd(long_at(sethi_offset)); } |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
546 |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
547 void verify(); |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
548 void print(); |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
549 |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
550 // unit test stuff |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
551 static void test(); |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
552 |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
553 // Creation |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
554 friend inline NativeMovConstReg32* nativeMovConstReg32_at(address address) { |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
555 NativeMovConstReg32* test = (NativeMovConstReg32*)address; |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
556 #ifdef ASSERT |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
557 test->verify(); |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
558 #endif |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
559 return test; |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
560 } |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
561 }; |
3da4f19cf93b
Implement inline metaspace constant patching for SPARC (Compressed/Uncompressed)
Stefan Anzinger <stefan.anzinger@oracle.com>
parents:
17524
diff
changeset
|
562 |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
2426
diff
changeset
|
563 // An interface for accessing/manipulating native set_metadata imm, reg instructions. |
0 | 564 // (used to manipulate inlined data references, etc.) |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
2426
diff
changeset
|
565 // set_metadata imm, reg |
0 | 566 // == sethi %hi22(imm), reg ; add reg, %lo10(imm), reg |
567 class NativeMovConstReg; | |
568 inline NativeMovConstReg* nativeMovConstReg_at(address address); | |
569 class NativeMovConstReg: public NativeInstruction { | |
570 public: | |
571 enum Sparc_specific_constants { | |
572 sethi_offset = 0, | |
573 #ifdef _LP64 | |
574 add_offset = 7 * BytesPerInstWord, | |
575 instruction_size = 8 * BytesPerInstWord | |
576 #else | |
577 add_offset = 4, | |
578 instruction_size = 8 | |
579 #endif | |
580 }; | |
581 | |
582 address instruction_address() const { return addr_at(0); } | |
583 address next_instruction_address() const { return addr_at(instruction_size); } | |
584 | |
585 // (The [set_]data accessor respects oop_type relocs also.) | |
586 intptr_t data() const; | |
587 void set_data(intptr_t x); | |
588 | |
589 // report the destination register | |
590 Register destination() { return inv_rd(long_at(sethi_offset)); } | |
591 | |
592 void verify(); | |
593 void print(); | |
594 | |
595 // unit test stuff | |
596 static void test(); | |
597 | |
598 // Creation | |
599 friend inline NativeMovConstReg* nativeMovConstReg_at(address address) { | |
600 NativeMovConstReg* test = (NativeMovConstReg*)address; | |
601 #ifdef ASSERT | |
602 test->verify(); | |
603 #endif | |
604 return test; | |
605 } | |
606 | |
607 | |
608 friend NativeMovConstReg* nativeMovConstReg_before(address address) { | |
609 NativeMovConstReg* test = (NativeMovConstReg*)(address - instruction_size); | |
610 #ifdef ASSERT | |
611 test->verify(); | |
612 #endif | |
613 return test; | |
614 } | |
615 | |
616 }; | |
617 | |
618 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
2426
diff
changeset
|
619 // An interface for accessing/manipulating native set_metadata imm, reg instructions. |
0 | 620 // (used to manipulate inlined data references, etc.) |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
2426
diff
changeset
|
621 // set_metadata imm, reg |
0 | 622 // == sethi %hi22(imm), reg; nop; add reg, %lo10(imm), reg |
623 // | |
624 // Note that it is identical to NativeMovConstReg with the exception of a nop between the | |
625 // sethi and the add. The nop is required to be in the delay slot of the call instruction | |
626 // which overwrites the sethi during patching. | |
627 class NativeMovConstRegPatching; | |
628 inline NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address);class NativeMovConstRegPatching: public NativeInstruction { | |
629 public: | |
630 enum Sparc_specific_constants { | |
631 sethi_offset = 0, | |
632 #ifdef _LP64 | |
633 nop_offset = 7 * BytesPerInstWord, | |
634 #else | |
635 nop_offset = sethi_offset + BytesPerInstWord, | |
636 #endif | |
637 add_offset = nop_offset + BytesPerInstWord, | |
638 instruction_size = add_offset + BytesPerInstWord | |
639 }; | |
640 | |
641 address instruction_address() const { return addr_at(0); } | |
642 address next_instruction_address() const { return addr_at(instruction_size); } | |
643 | |
644 // (The [set_]data accessor respects oop_type relocs also.) | |
645 int data() const; | |
646 void set_data(int x); | |
647 | |
648 // report the destination register | |
649 Register destination() { return inv_rd(long_at(sethi_offset)); } | |
650 | |
651 void verify(); | |
652 void print(); | |
653 | |
654 // unit test stuff | |
655 static void test(); | |
656 | |
657 // Creation | |
658 friend inline NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address) { | |
659 NativeMovConstRegPatching* test = (NativeMovConstRegPatching*)address; | |
660 #ifdef ASSERT | |
661 test->verify(); | |
662 #endif | |
663 return test; | |
664 } | |
665 | |
666 | |
667 friend NativeMovConstRegPatching* nativeMovConstRegPatching_before(address address) { | |
668 NativeMovConstRegPatching* test = (NativeMovConstRegPatching*)(address - instruction_size); | |
669 #ifdef ASSERT | |
670 test->verify(); | |
671 #endif | |
672 return test; | |
673 } | |
674 | |
675 }; | |
676 | |
677 | |
678 // An interface for accessing/manipulating native memory ops | |
679 // ld* [reg + offset], reg | |
680 // st* reg, [reg + offset] | |
681 // sethi %hi(imm), reg; add reg, %lo(imm), reg; ld* [reg1 + reg], reg2 | |
682 // sethi %hi(imm), reg; add reg, %lo(imm), reg; st* reg2, [reg1 + reg] | |
683 // Ops covered: {lds,ldu,st}{w,b,h}, {ld,st}{d,x} | |
684 // | |
685 class NativeMovRegMem; | |
686 inline NativeMovRegMem* nativeMovRegMem_at (address address); | |
687 class NativeMovRegMem: public NativeInstruction { | |
688 public: | |
689 enum Sparc_specific_constants { | |
690 op3_mask_ld = 1 << Assembler::lduw_op3 | | |
691 1 << Assembler::ldub_op3 | | |
692 1 << Assembler::lduh_op3 | | |
693 1 << Assembler::ldd_op3 | | |
694 1 << Assembler::ldsw_op3 | | |
695 1 << Assembler::ldsb_op3 | | |
696 1 << Assembler::ldsh_op3 | | |
697 1 << Assembler::ldx_op3, | |
698 op3_mask_st = 1 << Assembler::stw_op3 | | |
699 1 << Assembler::stb_op3 | | |
700 1 << Assembler::sth_op3 | | |
701 1 << Assembler::std_op3 | | |
702 1 << Assembler::stx_op3, | |
703 op3_ldst_int_limit = Assembler::ldf_op3, | |
704 op3_mask_ldf = 1 << (Assembler::ldf_op3 - op3_ldst_int_limit) | | |
705 1 << (Assembler::lddf_op3 - op3_ldst_int_limit), | |
706 op3_mask_stf = 1 << (Assembler::stf_op3 - op3_ldst_int_limit) | | |
707 1 << (Assembler::stdf_op3 - op3_ldst_int_limit), | |
708 | |
709 offset_width = 13, | |
710 sethi_offset = 0, | |
711 #ifdef _LP64 | |
712 add_offset = 7 * BytesPerInstWord, | |
713 #else | |
714 add_offset = 4, | |
715 #endif | |
716 ldst_offset = add_offset + BytesPerInstWord | |
717 }; | |
718 bool is_immediate() const { | |
719 // check if instruction is ld* [reg + offset], reg or st* reg, [reg + offset] | |
720 int i0 = long_at(0); | |
721 return (is_op(i0, Assembler::ldst_op)); | |
722 } | |
723 | |
724 address instruction_address() const { return addr_at(0); } | |
725 address next_instruction_address() const { | |
726 #ifdef _LP64 | |
727 return addr_at(is_immediate() ? 4 : (7 * BytesPerInstWord)); | |
728 #else | |
729 return addr_at(is_immediate() ? 4 : 12); | |
730 #endif | |
731 } | |
732 intptr_t offset() const { | |
733 return is_immediate()? inv_simm(long_at(0), offset_width) : | |
734 nativeMovConstReg_at(addr_at(0))->data(); | |
735 } | |
736 void set_offset(intptr_t x) { | |
737 if (is_immediate()) { | |
738 guarantee(fits_in_simm(x, offset_width), "data block offset overflow"); | |
739 set_long_at(0, set_simm(long_at(0), x, offset_width)); | |
740 } else | |
741 nativeMovConstReg_at(addr_at(0))->set_data(x); | |
742 } | |
743 | |
744 void add_offset_in_bytes(intptr_t radd_offset) { | |
745 set_offset (offset() + radd_offset); | |
746 } | |
747 | |
748 void copy_instruction_to(address new_instruction_address); | |
749 | |
750 void verify(); | |
751 void print (); | |
752 | |
753 // unit test stuff | |
754 static void test(); | |
755 | |
756 private: | |
757 friend inline NativeMovRegMem* nativeMovRegMem_at (address address) { | |
758 NativeMovRegMem* test = (NativeMovRegMem*)address; | |
759 #ifdef ASSERT | |
760 test->verify(); | |
761 #endif | |
762 return test; | |
763 } | |
764 }; | |
765 | |
766 | |
767 // An interface for accessing/manipulating native memory ops | |
768 // ld* [reg + offset], reg | |
769 // st* reg, [reg + offset] | |
770 // sethi %hi(imm), reg; nop; add reg, %lo(imm), reg; ld* [reg1 + reg], reg2 | |
771 // sethi %hi(imm), reg; nop; add reg, %lo(imm), reg; st* reg2, [reg1 + reg] | |
772 // Ops covered: {lds,ldu,st}{w,b,h}, {ld,st}{d,x} | |
773 // | |
774 // Note that it is identical to NativeMovRegMem with the exception of a nop between the | |
775 // sethi and the add. The nop is required to be in the delay slot of the call instruction | |
776 // which overwrites the sethi during patching. | |
777 class NativeMovRegMemPatching; | |
778 inline NativeMovRegMemPatching* nativeMovRegMemPatching_at (address address); | |
779 class NativeMovRegMemPatching: public NativeInstruction { | |
780 public: | |
781 enum Sparc_specific_constants { | |
782 op3_mask_ld = 1 << Assembler::lduw_op3 | | |
783 1 << Assembler::ldub_op3 | | |
784 1 << Assembler::lduh_op3 | | |
785 1 << Assembler::ldd_op3 | | |
786 1 << Assembler::ldsw_op3 | | |
787 1 << Assembler::ldsb_op3 | | |
788 1 << Assembler::ldsh_op3 | | |
789 1 << Assembler::ldx_op3, | |
790 op3_mask_st = 1 << Assembler::stw_op3 | | |
791 1 << Assembler::stb_op3 | | |
792 1 << Assembler::sth_op3 | | |
793 1 << Assembler::std_op3 | | |
794 1 << Assembler::stx_op3, | |
795 op3_ldst_int_limit = Assembler::ldf_op3, | |
796 op3_mask_ldf = 1 << (Assembler::ldf_op3 - op3_ldst_int_limit) | | |
797 1 << (Assembler::lddf_op3 - op3_ldst_int_limit), | |
798 op3_mask_stf = 1 << (Assembler::stf_op3 - op3_ldst_int_limit) | | |
799 1 << (Assembler::stdf_op3 - op3_ldst_int_limit), | |
800 | |
801 offset_width = 13, | |
802 sethi_offset = 0, | |
803 #ifdef _LP64 | |
804 nop_offset = 7 * BytesPerInstWord, | |
805 #else | |
806 nop_offset = 4, | |
807 #endif | |
808 add_offset = nop_offset + BytesPerInstWord, | |
809 ldst_offset = add_offset + BytesPerInstWord | |
810 }; | |
811 bool is_immediate() const { | |
812 // check if instruction is ld* [reg + offset], reg or st* reg, [reg + offset] | |
813 int i0 = long_at(0); | |
814 return (is_op(i0, Assembler::ldst_op)); | |
815 } | |
816 | |
817 address instruction_address() const { return addr_at(0); } | |
818 address next_instruction_address() const { | |
819 return addr_at(is_immediate()? 4 : 16); | |
820 } | |
821 int offset() const { | |
822 return is_immediate()? inv_simm(long_at(0), offset_width) : | |
823 nativeMovConstRegPatching_at(addr_at(0))->data(); | |
824 } | |
825 void set_offset(int x) { | |
826 if (is_immediate()) { | |
827 guarantee(fits_in_simm(x, offset_width), "data block offset overflow"); | |
828 set_long_at(0, set_simm(long_at(0), x, offset_width)); | |
829 } | |
830 else | |
831 nativeMovConstRegPatching_at(addr_at(0))->set_data(x); | |
832 } | |
833 | |
834 void add_offset_in_bytes(intptr_t radd_offset) { | |
835 set_offset (offset() + radd_offset); | |
836 } | |
837 | |
838 void copy_instruction_to(address new_instruction_address); | |
839 | |
840 void verify(); | |
841 void print (); | |
842 | |
843 // unit test stuff | |
844 static void test(); | |
845 | |
846 private: | |
847 friend inline NativeMovRegMemPatching* nativeMovRegMemPatching_at (address address) { | |
848 NativeMovRegMemPatching* test = (NativeMovRegMemPatching*)address; | |
849 #ifdef ASSERT | |
850 test->verify(); | |
851 #endif | |
852 return test; | |
853 } | |
854 }; | |
855 | |
856 | |
857 // An interface for accessing/manipulating native jumps | |
858 // jump_to addr | |
859 // == sethi %hi22(addr), temp ; jumpl reg, %lo10(addr), G0 ; <delay> | |
860 // jumpl_to addr, lreg | |
861 // == sethi %hi22(addr), temp ; jumpl reg, %lo10(addr), lreg ; <delay> | |
862 class NativeJump; | |
863 inline NativeJump* nativeJump_at(address address); | |
864 class NativeJump: public NativeInstruction { | |
865 private: | |
866 void guarantee_displacement(int disp, int width) { | |
867 guarantee(fits_in_simm(disp, width + 2), "branch displacement overflow"); | |
868 } | |
869 | |
870 public: | |
871 enum Sparc_specific_constants { | |
872 sethi_offset = 0, | |
873 #ifdef _LP64 | |
874 jmpl_offset = 7 * BytesPerInstWord, | |
875 instruction_size = 9 * BytesPerInstWord // includes delay slot | |
876 #else | |
877 jmpl_offset = 1 * BytesPerInstWord, | |
878 instruction_size = 3 * BytesPerInstWord // includes delay slot | |
879 #endif | |
880 }; | |
881 | |
882 address instruction_address() const { return addr_at(0); } | |
883 address next_instruction_address() const { return addr_at(instruction_size); } | |
884 | |
885 #ifdef _LP64 | |
886 address jump_destination() const { | |
887 return (address) data64(instruction_address(), long_at(jmpl_offset)); | |
888 } | |
889 void set_jump_destination(address dest) { | |
890 set_data64_sethi( instruction_address(), (intptr_t)dest); | |
891 set_long_at(jmpl_offset, set_data32_simm13( long_at(jmpl_offset), (intptr_t)dest)); | |
892 } | |
893 #else | |
894 address jump_destination() const { | |
895 return (address) data32(long_at(sethi_offset), long_at(jmpl_offset)); | |
896 } | |
897 void set_jump_destination(address dest) { | |
898 set_long_at(sethi_offset, set_data32_sethi( long_at(sethi_offset), (intptr_t)dest)); | |
899 set_long_at(jmpl_offset, set_data32_simm13( long_at(jmpl_offset), (intptr_t)dest)); | |
900 } | |
901 #endif | |
902 | |
903 // Creation | |
904 friend inline NativeJump* nativeJump_at(address address) { | |
905 NativeJump* jump = (NativeJump*)address; | |
906 #ifdef ASSERT | |
907 jump->verify(); | |
908 #endif | |
909 return jump; | |
910 } | |
911 | |
912 void verify(); | |
913 void print(); | |
914 | |
915 // Unit testing stuff | |
916 static void test(); | |
917 | |
918 // Insertion of native jump instruction | |
919 static void insert(address code_pos, address entry); | |
920 // MT-safe insertion of native jump at verified method entry | |
921 static void check_verified_entry_alignment(address entry, address verified_entry) { | |
922 // nothing to do for sparc. | |
923 } | |
924 static void patch_verified_entry(address entry, address verified_entry, address dest); | |
925 }; | |
926 | |
927 | |
928 | |
929 // Despite the name, handles only simple branches. | |
930 class NativeGeneralJump; | |
931 inline NativeGeneralJump* nativeGeneralJump_at(address address); | |
932 class NativeGeneralJump: public NativeInstruction { | |
933 public: | |
934 enum Sparc_specific_constants { | |
935 instruction_size = 8 | |
936 }; | |
937 | |
938 address instruction_address() const { return addr_at(0); } | |
939 address jump_destination() const { return addr_at(0) + branch_destination_offset(long_at(0)); } | |
940 void set_jump_destination(address dest) { | |
941 int patched_instr = patch_branch_destination_offset(dest - addr_at(0), long_at(0)); | |
942 set_long_at(0, patched_instr); | |
943 } | |
944 NativeInstruction *delay_slot_instr() { return nativeInstruction_at(addr_at(4));} | |
945 void fill_delay_slot(int instr) { set_long_at(4, instr);} | |
946 Assembler::Condition condition() { | |
947 int x = long_at(0); | |
948 return (Assembler::Condition) Assembler::inv_cond(x); | |
949 } | |
950 | |
951 // Creation | |
952 friend inline NativeGeneralJump* nativeGeneralJump_at(address address) { | |
953 NativeGeneralJump* jump = (NativeGeneralJump*)(address); | |
954 #ifdef ASSERT | |
955 jump->verify(); | |
956 #endif | |
957 return jump; | |
958 } | |
959 | |
960 // Insertion of native general jump instruction | |
961 static void insert_unconditional(address code_pos, address entry); | |
962 static void replace_mt_safe(address instr_addr, address code_buffer); | |
963 | |
964 void verify(); | |
965 }; | |
966 | |
967 | |
968 class NativeIllegalInstruction: public NativeInstruction { | |
969 public: | |
970 enum Sparc_specific_constants { | |
971 instruction_size = 4 | |
972 }; | |
973 | |
974 // Insert illegal opcode as specific address | |
975 static void insert(address code_pos); | |
976 }; | |
1972 | 977 |
978 #endif // CPU_SPARC_VM_NATIVEINST_SPARC_HPP |