Mercurial > hg > graal-compiler
annotate src/cpu/sparc/vm/nativeInst_sparc.hpp @ 6812:988bf00cc564
7200261: G1: Liveness counting inconsistencies during marking verification
Summary: The clipping code in the routine that sets the bits for a range of cards, in the liveness accounting verification code was incorrect. It set all the bits in the card bitmap from the given starting index which would lead to spurious marking verification failures.
Reviewed-by: brutisso, jwilhelm, jmasa
author | johnc |
---|---|
date | Thu, 27 Sep 2012 15:44:01 -0700 |
parents | da91efe96a93 |
children | f0c2369fda5a |
rev | line source |
---|---|
0 | 1 /* |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
2426
diff
changeset
|
2 * Copyright (c) 1997, 2012, 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 | |
28 #include "asm/assembler.hpp" | |
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); } | |
58 bool is_sethi() { return (is_op2(long_at(0), Assembler::sethi_op2) | |
59 && inv_rd(long_at(0)) != G0); } | |
60 | |
61 bool sets_cc() { | |
62 // conservative (returns true for some instructions that do not set the | |
63 // the condition code, such as, "save". | |
64 // Does not return true for the deprecated tagged instructions, such as, TADDcc | |
65 int x = long_at(0); | |
66 return (is_op(x, Assembler::arith_op) && | |
67 (inv_op3(x) & Assembler::cc_bit_op3) == Assembler::cc_bit_op3); | |
68 } | |
69 bool is_illegal(); | |
70 bool is_zombie() { | |
71 int x = long_at(0); | |
72 return is_op3(x, | |
73 VM_Version::v9_instructions_work() ? | |
74 Assembler::ldsw_op3 : Assembler::lduw_op3, | |
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); } | |
197 static int branch_destination_offset(int x) { return Assembler::branch_destination(x, 0); } | |
198 static int patch_branch_destination_offset(int dest_offset, int x) { | |
199 return Assembler::patched_branch(dest_offset, x, 0); | |
200 } | |
201 void set_annul_bit() { set_long_at(0, long_at(0) | Assembler::annul(true)); } | |
202 | |
203 // utility for checking if x is either of 2 small constants | |
204 static bool is_either(int x, int k1, int k2) { | |
205 // return x == k1 || x == k2; | |
206 return (1 << x) & (1 << k1 | 1 << k2); | |
207 } | |
208 | |
209 // utility for checking overflow of signed instruction fields | |
210 static bool fits_in_simm(int x, int nbits) { | |
211 // cf. Assembler::assert_signed_range() | |
212 // return -(1 << nbits-1) <= x && x < ( 1 << nbits-1), | |
213 return (unsigned)(x + (1 << nbits-1)) < (unsigned)(1 << nbits); | |
214 } | |
215 | |
216 // set a signed immediate field | |
217 static int set_simm(int insn, int imm, int nbits) { | |
218 return (insn &~ Assembler::simm(-1, nbits)) | Assembler::simm(imm, nbits); | |
219 } | |
220 | |
221 // set a wdisp field (disp should be the difference of two addresses) | |
222 static int set_wdisp(int insn, intptr_t disp, int nbits) { | |
223 return (insn &~ Assembler::wdisp((intptr_t)-4, (intptr_t)0, nbits)) | Assembler::wdisp(disp, 0, nbits); | |
224 } | |
225 | |
226 static int set_wdisp16(int insn, intptr_t disp) { | |
227 return (insn &~ Assembler::wdisp16((intptr_t)-4, 0)) | Assembler::wdisp16(disp, 0); | |
228 } | |
229 | |
230 // get a simm13 field from an arithmetic or memory instruction | |
231 static int get_simm13(int insn) { | |
232 assert(is_either(Assembler::inv_op(insn), | |
233 Assembler::arith_op, Assembler::ldst_op) && | |
234 (insn & Assembler::immed(true)), "must have a simm13 field"); | |
235 return Assembler::inv_simm(insn, 13); | |
236 } | |
237 | |
238 // set the simm13 field of an arithmetic or memory instruction | |
239 static bool set_simm13(int insn, int imm) { | |
240 get_simm13(insn); // tickle the assertion check | |
241 return set_simm(insn, imm, 13); | |
242 } | |
243 | |
244 // combine the fields of a sethi stream (7 instructions ) and an add, jmp or ld/st | |
245 static intptr_t data64( address pc, int arith_insn ) { | |
246 assert(is_op2(*(unsigned int *)pc, Assembler::sethi_op2), "must be sethi"); | |
247 intptr_t hi = (intptr_t)gethi( (unsigned int *)pc ); | |
248 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
|
249 assert((unsigned)lo < (1 << 10), "offset field of set_metadata must be 10 bits"); |
0 | 250 return hi | lo; |
251 } | |
252 | |
253 // Regenerate the instruction sequence that performs the 64 bit | |
254 // sethi. This only does the sethi. The disp field (bottom 10 bits) | |
605 | 255 // must be handled separately. |
0 | 256 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
|
257 static void verify_data64_sethi(address instaddr, intptr_t x); |
0 | 258 |
259 // combine the fields of a sethi/simm13 pair (simm13 = or, add, jmpl, ld/st) | |
260 static int data32(int sethi_insn, int arith_insn) { | |
261 assert(is_op2(sethi_insn, Assembler::sethi_op2), "must be sethi"); | |
262 int hi = Assembler::inv_hi22(sethi_insn); | |
263 int lo = get_simm13(arith_insn); | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
2426
diff
changeset
|
264 assert((unsigned)lo < (1 << 10), "offset field of set_metadata must be 10 bits"); |
0 | 265 return hi | lo; |
266 } | |
267 | |
268 static int set_data32_sethi(int sethi_insn, int imm) { | |
269 // note that Assembler::hi22 clips the low 10 bits for us | |
270 assert(is_op2(sethi_insn, Assembler::sethi_op2), "must be sethi"); | |
271 return (sethi_insn &~ Assembler::hi22(-1)) | Assembler::hi22(imm); | |
272 } | |
273 | |
274 static int set_data32_simm13(int arith_insn, int imm) { | |
275 get_simm13(arith_insn); // tickle the assertion check | |
276 int imm10 = Assembler::low10(imm); | |
277 return (arith_insn &~ Assembler::simm(-1, 13)) | Assembler::simm(imm10, 13); | |
278 } | |
279 | |
280 static int low10(int imm) { | |
281 return Assembler::low10(imm); | |
282 } | |
283 | |
284 // Perform the inverse of the LP64 Macroassembler::sethi | |
285 // routine. Extracts the 54 bits of address from the instruction | |
286 // stream. This routine must agree with the sethi routine in | |
287 // assembler_inline_sparc.hpp | |
288 static address gethi( unsigned int *pc ) { | |
289 int i = 0; | |
290 uintptr_t adr; | |
291 // We first start out with the real sethi instruction | |
292 assert(is_op2(*pc, Assembler::sethi_op2), "in gethi - must be sethi"); | |
293 adr = (unsigned int)Assembler::inv_hi22( *(pc++) ); | |
294 i++; | |
295 while ( i < 7 ) { | |
296 // We're done if we hit a nop | |
297 if ( (int)*pc == nop_instruction() ) break; | |
298 assert ( Assembler::inv_op(*pc) == Assembler::arith_op, "in gethi - must be arith_op" ); | |
299 switch ( Assembler::inv_op3(*pc) ) { | |
300 case Assembler::xor_op3: | |
301 adr ^= (intptr_t)get_simm13( *pc ); | |
302 return ( (address)adr ); | |
303 break; | |
304 case Assembler::sll_op3: | |
305 adr <<= ( *pc & 0x3f ); | |
306 break; | |
307 case Assembler::or_op3: | |
308 adr |= (intptr_t)get_simm13( *pc ); | |
309 break; | |
310 default: | |
311 assert ( 0, "in gethi - Should not reach here" ); | |
312 break; | |
313 } | |
314 pc++; | |
315 i++; | |
316 } | |
317 return ( (address)adr ); | |
318 } | |
319 | |
320 public: | |
321 void verify(); | |
322 void print(); | |
323 | |
324 // unit test stuff | |
325 static void test() {} // override for testing | |
326 | |
327 inline friend NativeInstruction* nativeInstruction_at(address address); | |
328 }; | |
329 | |
330 inline NativeInstruction* nativeInstruction_at(address address) { | |
331 NativeInstruction* inst = (NativeInstruction*)address; | |
332 #ifdef ASSERT | |
333 inst->verify(); | |
334 #endif | |
335 return inst; | |
336 } | |
337 | |
338 | |
339 | |
340 //----------------------------------------------------------------------------- | |
341 | |
342 // The NativeCall is an abstraction for accessing/manipulating native call imm32 instructions. | |
343 // (used to manipulate inline caches, primitive & dll calls, etc.) | |
344 inline NativeCall* nativeCall_at(address instr); | |
345 inline NativeCall* nativeCall_overwriting_at(address instr, | |
346 address destination); | |
347 inline NativeCall* nativeCall_before(address return_address); | |
348 class NativeCall: public NativeInstruction { | |
349 public: | |
350 enum Sparc_specific_constants { | |
351 instruction_size = 8, | |
352 return_address_offset = 8, | |
353 call_displacement_width = 30, | |
354 displacement_offset = 0, | |
355 instruction_offset = 0 | |
356 }; | |
357 address instruction_address() const { return addr_at(0); } | |
358 address next_instruction_address() const { return addr_at(instruction_size); } | |
359 address return_address() const { return addr_at(return_address_offset); } | |
360 | |
361 address destination() const { return inv_wdisp(long_at(0), call_displacement_width) + instruction_address(); } | |
362 address displacement_address() const { return addr_at(displacement_offset); } | |
363 void set_destination(address dest) { set_long_at(0, set_wdisp(long_at(0), dest - instruction_address(), call_displacement_width)); } | |
364 void set_destination_mt_safe(address dest); | |
365 | |
366 void verify_alignment() {} // do nothing on sparc | |
367 void verify(); | |
368 void print(); | |
369 | |
370 // unit test stuff | |
371 static void test(); | |
372 | |
373 // Creation | |
374 friend inline NativeCall* nativeCall_at(address instr); | |
375 friend NativeCall* nativeCall_overwriting_at(address instr, address destination = NULL) { | |
376 // insert a "blank" call: | |
377 NativeCall* call = (NativeCall*)instr; | |
378 call->set_long_at(0 * BytesPerInstWord, call_instruction(destination, instr)); | |
379 call->set_long_at(1 * BytesPerInstWord, nop_instruction()); | |
380 assert(call->addr_at(2 * BytesPerInstWord) - instr == instruction_size, "instruction size"); | |
381 // check its structure now: | |
382 assert(nativeCall_at(instr)->destination() == destination, "correct call destination"); | |
383 return call; | |
384 } | |
385 | |
386 friend inline NativeCall* nativeCall_before(address return_address) { | |
387 NativeCall* call = (NativeCall*)(return_address - return_address_offset); | |
388 #ifdef ASSERT | |
389 call->verify(); | |
390 #endif | |
391 return call; | |
392 } | |
393 | |
394 static bool is_call_at(address instr) { | |
395 return nativeInstruction_at(instr)->is_call(); | |
396 } | |
397 | |
398 static bool is_call_before(address instr) { | |
399 return nativeInstruction_at(instr - return_address_offset)->is_call(); | |
400 } | |
401 | |
402 static bool is_call_to(address instr, address target) { | |
403 return nativeInstruction_at(instr)->is_call() && | |
404 nativeCall_at(instr)->destination() == target; | |
405 } | |
406 | |
407 // MT-safe patching of a call instruction. | |
408 static void insert(address code_pos, address entry) { | |
409 (void)nativeCall_overwriting_at(code_pos, entry); | |
410 } | |
411 | |
412 static void replace_mt_safe(address instr_addr, address code_buffer); | |
413 }; | |
414 inline NativeCall* nativeCall_at(address instr) { | |
415 NativeCall* call = (NativeCall*)instr; | |
416 #ifdef ASSERT | |
417 call->verify(); | |
418 #endif | |
419 return call; | |
420 } | |
421 | |
422 // The NativeFarCall is an abstraction for accessing/manipulating native call-anywhere | |
423 // instructions in the sparcv9 vm. Used to call native methods which may be loaded | |
424 // anywhere in the address space, possibly out of reach of a call instruction. | |
425 | |
426 #ifndef _LP64 | |
427 | |
428 // On 32-bit systems, a far call is the same as a near one. | |
429 class NativeFarCall; | |
430 inline NativeFarCall* nativeFarCall_at(address instr); | |
431 class NativeFarCall : public NativeCall { | |
432 public: | |
433 friend inline NativeFarCall* nativeFarCall_at(address instr) { return (NativeFarCall*)nativeCall_at(instr); } | |
434 friend NativeFarCall* nativeFarCall_overwriting_at(address instr, address destination = NULL) | |
435 { return (NativeFarCall*)nativeCall_overwriting_at(instr, destination); } | |
436 friend NativeFarCall* nativeFarCall_before(address return_address) | |
437 { return (NativeFarCall*)nativeCall_before(return_address); } | |
438 }; | |
439 | |
440 #else | |
441 | |
442 // The format of this extended-range call is: | |
443 // jumpl_to addr, lreg | |
444 // == sethi %hi54(addr), O7 ; jumpl O7, %lo10(addr), O7 ; <delay> | |
445 // That is, it is essentially the same as a NativeJump. | |
446 class NativeFarCall; | |
447 inline NativeFarCall* nativeFarCall_overwriting_at(address instr, address destination); | |
448 inline NativeFarCall* nativeFarCall_at(address instr); | |
449 class NativeFarCall: public NativeInstruction { | |
450 public: | |
451 enum Sparc_specific_constants { | |
452 // instruction_size includes the delay slot instruction. | |
453 instruction_size = 9 * BytesPerInstWord, | |
454 return_address_offset = 9 * BytesPerInstWord, | |
455 jmpl_offset = 7 * BytesPerInstWord, | |
456 displacement_offset = 0, | |
457 instruction_offset = 0 | |
458 }; | |
459 address instruction_address() const { return addr_at(0); } | |
460 address next_instruction_address() const { return addr_at(instruction_size); } | |
461 address return_address() const { return addr_at(return_address_offset); } | |
462 | |
463 address destination() const { | |
464 return (address) data64(addr_at(0), long_at(jmpl_offset)); | |
465 } | |
466 address displacement_address() const { return addr_at(displacement_offset); } | |
467 void set_destination(address dest); | |
468 | |
469 bool destination_is_compiled_verified_entry_point(); | |
470 | |
471 void verify(); | |
472 void print(); | |
473 | |
474 // unit test stuff | |
475 static void test(); | |
476 | |
477 // Creation | |
478 friend inline NativeFarCall* nativeFarCall_at(address instr) { | |
479 NativeFarCall* call = (NativeFarCall*)instr; | |
480 #ifdef ASSERT | |
481 call->verify(); | |
482 #endif | |
483 return call; | |
484 } | |
485 | |
486 friend inline NativeFarCall* nativeFarCall_overwriting_at(address instr, address destination = NULL) { | |
487 Unimplemented(); | |
488 NativeFarCall* call = (NativeFarCall*)instr; | |
489 return call; | |
490 } | |
491 | |
492 friend NativeFarCall* nativeFarCall_before(address return_address) { | |
493 NativeFarCall* call = (NativeFarCall*)(return_address - return_address_offset); | |
494 #ifdef ASSERT | |
495 call->verify(); | |
496 #endif | |
497 return call; | |
498 } | |
499 | |
500 static bool is_call_at(address instr); | |
501 | |
502 // MT-safe patching of a call instruction. | |
503 static void insert(address code_pos, address entry) { | |
504 (void)nativeFarCall_overwriting_at(code_pos, entry); | |
505 } | |
506 static void replace_mt_safe(address instr_addr, address code_buffer); | |
507 }; | |
508 | |
509 #endif // _LP64 | |
510 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
2426
diff
changeset
|
511 // An interface for accessing/manipulating native set_metadata imm, reg instructions. |
0 | 512 // (used to manipulate inlined data references, etc.) |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
2426
diff
changeset
|
513 // set_metadata imm, reg |
0 | 514 // == sethi %hi22(imm), reg ; add reg, %lo10(imm), reg |
515 class NativeMovConstReg; | |
516 inline NativeMovConstReg* nativeMovConstReg_at(address address); | |
517 class NativeMovConstReg: public NativeInstruction { | |
518 public: | |
519 enum Sparc_specific_constants { | |
520 sethi_offset = 0, | |
521 #ifdef _LP64 | |
522 add_offset = 7 * BytesPerInstWord, | |
523 instruction_size = 8 * BytesPerInstWord | |
524 #else | |
525 add_offset = 4, | |
526 instruction_size = 8 | |
527 #endif | |
528 }; | |
529 | |
530 address instruction_address() const { return addr_at(0); } | |
531 address next_instruction_address() const { return addr_at(instruction_size); } | |
532 | |
533 // (The [set_]data accessor respects oop_type relocs also.) | |
534 intptr_t data() const; | |
535 void set_data(intptr_t x); | |
536 | |
537 // report the destination register | |
538 Register destination() { return inv_rd(long_at(sethi_offset)); } | |
539 | |
540 void verify(); | |
541 void print(); | |
542 | |
543 // unit test stuff | |
544 static void test(); | |
545 | |
546 // Creation | |
547 friend inline NativeMovConstReg* nativeMovConstReg_at(address address) { | |
548 NativeMovConstReg* test = (NativeMovConstReg*)address; | |
549 #ifdef ASSERT | |
550 test->verify(); | |
551 #endif | |
552 return test; | |
553 } | |
554 | |
555 | |
556 friend NativeMovConstReg* nativeMovConstReg_before(address address) { | |
557 NativeMovConstReg* test = (NativeMovConstReg*)(address - instruction_size); | |
558 #ifdef ASSERT | |
559 test->verify(); | |
560 #endif | |
561 return test; | |
562 } | |
563 | |
564 }; | |
565 | |
566 | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
2426
diff
changeset
|
567 // An interface for accessing/manipulating native set_metadata imm, reg instructions. |
0 | 568 // (used to manipulate inlined data references, etc.) |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
2426
diff
changeset
|
569 // set_metadata imm, reg |
0 | 570 // == sethi %hi22(imm), reg; nop; add reg, %lo10(imm), reg |
571 // | |
572 // Note that it is identical to NativeMovConstReg with the exception of a nop between the | |
573 // sethi and the add. The nop is required to be in the delay slot of the call instruction | |
574 // which overwrites the sethi during patching. | |
575 class NativeMovConstRegPatching; | |
576 inline NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address);class NativeMovConstRegPatching: public NativeInstruction { | |
577 public: | |
578 enum Sparc_specific_constants { | |
579 sethi_offset = 0, | |
580 #ifdef _LP64 | |
581 nop_offset = 7 * BytesPerInstWord, | |
582 #else | |
583 nop_offset = sethi_offset + BytesPerInstWord, | |
584 #endif | |
585 add_offset = nop_offset + BytesPerInstWord, | |
586 instruction_size = add_offset + BytesPerInstWord | |
587 }; | |
588 | |
589 address instruction_address() const { return addr_at(0); } | |
590 address next_instruction_address() const { return addr_at(instruction_size); } | |
591 | |
592 // (The [set_]data accessor respects oop_type relocs also.) | |
593 int data() const; | |
594 void set_data(int x); | |
595 | |
596 // report the destination register | |
597 Register destination() { return inv_rd(long_at(sethi_offset)); } | |
598 | |
599 void verify(); | |
600 void print(); | |
601 | |
602 // unit test stuff | |
603 static void test(); | |
604 | |
605 // Creation | |
606 friend inline NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address) { | |
607 NativeMovConstRegPatching* test = (NativeMovConstRegPatching*)address; | |
608 #ifdef ASSERT | |
609 test->verify(); | |
610 #endif | |
611 return test; | |
612 } | |
613 | |
614 | |
615 friend NativeMovConstRegPatching* nativeMovConstRegPatching_before(address address) { | |
616 NativeMovConstRegPatching* test = (NativeMovConstRegPatching*)(address - instruction_size); | |
617 #ifdef ASSERT | |
618 test->verify(); | |
619 #endif | |
620 return test; | |
621 } | |
622 | |
623 }; | |
624 | |
625 | |
626 // An interface for accessing/manipulating native memory ops | |
627 // ld* [reg + offset], reg | |
628 // st* reg, [reg + offset] | |
629 // sethi %hi(imm), reg; add reg, %lo(imm), reg; ld* [reg1 + reg], reg2 | |
630 // sethi %hi(imm), reg; add reg, %lo(imm), reg; st* reg2, [reg1 + reg] | |
631 // Ops covered: {lds,ldu,st}{w,b,h}, {ld,st}{d,x} | |
632 // | |
633 class NativeMovRegMem; | |
634 inline NativeMovRegMem* nativeMovRegMem_at (address address); | |
635 class NativeMovRegMem: public NativeInstruction { | |
636 public: | |
637 enum Sparc_specific_constants { | |
638 op3_mask_ld = 1 << Assembler::lduw_op3 | | |
639 1 << Assembler::ldub_op3 | | |
640 1 << Assembler::lduh_op3 | | |
641 1 << Assembler::ldd_op3 | | |
642 1 << Assembler::ldsw_op3 | | |
643 1 << Assembler::ldsb_op3 | | |
644 1 << Assembler::ldsh_op3 | | |
645 1 << Assembler::ldx_op3, | |
646 op3_mask_st = 1 << Assembler::stw_op3 | | |
647 1 << Assembler::stb_op3 | | |
648 1 << Assembler::sth_op3 | | |
649 1 << Assembler::std_op3 | | |
650 1 << Assembler::stx_op3, | |
651 op3_ldst_int_limit = Assembler::ldf_op3, | |
652 op3_mask_ldf = 1 << (Assembler::ldf_op3 - op3_ldst_int_limit) | | |
653 1 << (Assembler::lddf_op3 - op3_ldst_int_limit), | |
654 op3_mask_stf = 1 << (Assembler::stf_op3 - op3_ldst_int_limit) | | |
655 1 << (Assembler::stdf_op3 - op3_ldst_int_limit), | |
656 | |
657 offset_width = 13, | |
658 sethi_offset = 0, | |
659 #ifdef _LP64 | |
660 add_offset = 7 * BytesPerInstWord, | |
661 #else | |
662 add_offset = 4, | |
663 #endif | |
664 ldst_offset = add_offset + BytesPerInstWord | |
665 }; | |
666 bool is_immediate() const { | |
667 // check if instruction is ld* [reg + offset], reg or st* reg, [reg + offset] | |
668 int i0 = long_at(0); | |
669 return (is_op(i0, Assembler::ldst_op)); | |
670 } | |
671 | |
672 address instruction_address() const { return addr_at(0); } | |
673 address next_instruction_address() const { | |
674 #ifdef _LP64 | |
675 return addr_at(is_immediate() ? 4 : (7 * BytesPerInstWord)); | |
676 #else | |
677 return addr_at(is_immediate() ? 4 : 12); | |
678 #endif | |
679 } | |
680 intptr_t offset() const { | |
681 return is_immediate()? inv_simm(long_at(0), offset_width) : | |
682 nativeMovConstReg_at(addr_at(0))->data(); | |
683 } | |
684 void set_offset(intptr_t x) { | |
685 if (is_immediate()) { | |
686 guarantee(fits_in_simm(x, offset_width), "data block offset overflow"); | |
687 set_long_at(0, set_simm(long_at(0), x, offset_width)); | |
688 } else | |
689 nativeMovConstReg_at(addr_at(0))->set_data(x); | |
690 } | |
691 | |
692 void add_offset_in_bytes(intptr_t radd_offset) { | |
693 set_offset (offset() + radd_offset); | |
694 } | |
695 | |
696 void copy_instruction_to(address new_instruction_address); | |
697 | |
698 void verify(); | |
699 void print (); | |
700 | |
701 // unit test stuff | |
702 static void test(); | |
703 | |
704 private: | |
705 friend inline NativeMovRegMem* nativeMovRegMem_at (address address) { | |
706 NativeMovRegMem* test = (NativeMovRegMem*)address; | |
707 #ifdef ASSERT | |
708 test->verify(); | |
709 #endif | |
710 return test; | |
711 } | |
712 }; | |
713 | |
714 | |
715 // An interface for accessing/manipulating native memory ops | |
716 // ld* [reg + offset], reg | |
717 // st* reg, [reg + offset] | |
718 // sethi %hi(imm), reg; nop; add reg, %lo(imm), reg; ld* [reg1 + reg], reg2 | |
719 // sethi %hi(imm), reg; nop; add reg, %lo(imm), reg; st* reg2, [reg1 + reg] | |
720 // Ops covered: {lds,ldu,st}{w,b,h}, {ld,st}{d,x} | |
721 // | |
722 // Note that it is identical to NativeMovRegMem with the exception of a nop between the | |
723 // sethi and the add. The nop is required to be in the delay slot of the call instruction | |
724 // which overwrites the sethi during patching. | |
725 class NativeMovRegMemPatching; | |
726 inline NativeMovRegMemPatching* nativeMovRegMemPatching_at (address address); | |
727 class NativeMovRegMemPatching: public NativeInstruction { | |
728 public: | |
729 enum Sparc_specific_constants { | |
730 op3_mask_ld = 1 << Assembler::lduw_op3 | | |
731 1 << Assembler::ldub_op3 | | |
732 1 << Assembler::lduh_op3 | | |
733 1 << Assembler::ldd_op3 | | |
734 1 << Assembler::ldsw_op3 | | |
735 1 << Assembler::ldsb_op3 | | |
736 1 << Assembler::ldsh_op3 | | |
737 1 << Assembler::ldx_op3, | |
738 op3_mask_st = 1 << Assembler::stw_op3 | | |
739 1 << Assembler::stb_op3 | | |
740 1 << Assembler::sth_op3 | | |
741 1 << Assembler::std_op3 | | |
742 1 << Assembler::stx_op3, | |
743 op3_ldst_int_limit = Assembler::ldf_op3, | |
744 op3_mask_ldf = 1 << (Assembler::ldf_op3 - op3_ldst_int_limit) | | |
745 1 << (Assembler::lddf_op3 - op3_ldst_int_limit), | |
746 op3_mask_stf = 1 << (Assembler::stf_op3 - op3_ldst_int_limit) | | |
747 1 << (Assembler::stdf_op3 - op3_ldst_int_limit), | |
748 | |
749 offset_width = 13, | |
750 sethi_offset = 0, | |
751 #ifdef _LP64 | |
752 nop_offset = 7 * BytesPerInstWord, | |
753 #else | |
754 nop_offset = 4, | |
755 #endif | |
756 add_offset = nop_offset + BytesPerInstWord, | |
757 ldst_offset = add_offset + BytesPerInstWord | |
758 }; | |
759 bool is_immediate() const { | |
760 // check if instruction is ld* [reg + offset], reg or st* reg, [reg + offset] | |
761 int i0 = long_at(0); | |
762 return (is_op(i0, Assembler::ldst_op)); | |
763 } | |
764 | |
765 address instruction_address() const { return addr_at(0); } | |
766 address next_instruction_address() const { | |
767 return addr_at(is_immediate()? 4 : 16); | |
768 } | |
769 int offset() const { | |
770 return is_immediate()? inv_simm(long_at(0), offset_width) : | |
771 nativeMovConstRegPatching_at(addr_at(0))->data(); | |
772 } | |
773 void set_offset(int x) { | |
774 if (is_immediate()) { | |
775 guarantee(fits_in_simm(x, offset_width), "data block offset overflow"); | |
776 set_long_at(0, set_simm(long_at(0), x, offset_width)); | |
777 } | |
778 else | |
779 nativeMovConstRegPatching_at(addr_at(0))->set_data(x); | |
780 } | |
781 | |
782 void add_offset_in_bytes(intptr_t radd_offset) { | |
783 set_offset (offset() + radd_offset); | |
784 } | |
785 | |
786 void copy_instruction_to(address new_instruction_address); | |
787 | |
788 void verify(); | |
789 void print (); | |
790 | |
791 // unit test stuff | |
792 static void test(); | |
793 | |
794 private: | |
795 friend inline NativeMovRegMemPatching* nativeMovRegMemPatching_at (address address) { | |
796 NativeMovRegMemPatching* test = (NativeMovRegMemPatching*)address; | |
797 #ifdef ASSERT | |
798 test->verify(); | |
799 #endif | |
800 return test; | |
801 } | |
802 }; | |
803 | |
804 | |
805 // An interface for accessing/manipulating native jumps | |
806 // jump_to addr | |
807 // == sethi %hi22(addr), temp ; jumpl reg, %lo10(addr), G0 ; <delay> | |
808 // jumpl_to addr, lreg | |
809 // == sethi %hi22(addr), temp ; jumpl reg, %lo10(addr), lreg ; <delay> | |
810 class NativeJump; | |
811 inline NativeJump* nativeJump_at(address address); | |
812 class NativeJump: public NativeInstruction { | |
813 private: | |
814 void guarantee_displacement(int disp, int width) { | |
815 guarantee(fits_in_simm(disp, width + 2), "branch displacement overflow"); | |
816 } | |
817 | |
818 public: | |
819 enum Sparc_specific_constants { | |
820 sethi_offset = 0, | |
821 #ifdef _LP64 | |
822 jmpl_offset = 7 * BytesPerInstWord, | |
823 instruction_size = 9 * BytesPerInstWord // includes delay slot | |
824 #else | |
825 jmpl_offset = 1 * BytesPerInstWord, | |
826 instruction_size = 3 * BytesPerInstWord // includes delay slot | |
827 #endif | |
828 }; | |
829 | |
830 address instruction_address() const { return addr_at(0); } | |
831 address next_instruction_address() const { return addr_at(instruction_size); } | |
832 | |
833 #ifdef _LP64 | |
834 address jump_destination() const { | |
835 return (address) data64(instruction_address(), long_at(jmpl_offset)); | |
836 } | |
837 void set_jump_destination(address dest) { | |
838 set_data64_sethi( instruction_address(), (intptr_t)dest); | |
839 set_long_at(jmpl_offset, set_data32_simm13( long_at(jmpl_offset), (intptr_t)dest)); | |
840 } | |
841 #else | |
842 address jump_destination() const { | |
843 return (address) data32(long_at(sethi_offset), long_at(jmpl_offset)); | |
844 } | |
845 void set_jump_destination(address dest) { | |
846 set_long_at(sethi_offset, set_data32_sethi( long_at(sethi_offset), (intptr_t)dest)); | |
847 set_long_at(jmpl_offset, set_data32_simm13( long_at(jmpl_offset), (intptr_t)dest)); | |
848 } | |
849 #endif | |
850 | |
851 // Creation | |
852 friend inline NativeJump* nativeJump_at(address address) { | |
853 NativeJump* jump = (NativeJump*)address; | |
854 #ifdef ASSERT | |
855 jump->verify(); | |
856 #endif | |
857 return jump; | |
858 } | |
859 | |
860 void verify(); | |
861 void print(); | |
862 | |
863 // Unit testing stuff | |
864 static void test(); | |
865 | |
866 // Insertion of native jump instruction | |
867 static void insert(address code_pos, address entry); | |
868 // MT-safe insertion of native jump at verified method entry | |
869 static void check_verified_entry_alignment(address entry, address verified_entry) { | |
870 // nothing to do for sparc. | |
871 } | |
872 static void patch_verified_entry(address entry, address verified_entry, address dest); | |
873 }; | |
874 | |
875 | |
876 | |
877 // Despite the name, handles only simple branches. | |
878 class NativeGeneralJump; | |
879 inline NativeGeneralJump* nativeGeneralJump_at(address address); | |
880 class NativeGeneralJump: public NativeInstruction { | |
881 public: | |
882 enum Sparc_specific_constants { | |
883 instruction_size = 8 | |
884 }; | |
885 | |
886 address instruction_address() const { return addr_at(0); } | |
887 address jump_destination() const { return addr_at(0) + branch_destination_offset(long_at(0)); } | |
888 void set_jump_destination(address dest) { | |
889 int patched_instr = patch_branch_destination_offset(dest - addr_at(0), long_at(0)); | |
890 set_long_at(0, patched_instr); | |
891 } | |
892 void set_annul() { set_annul_bit(); } | |
893 NativeInstruction *delay_slot_instr() { return nativeInstruction_at(addr_at(4));} | |
894 void fill_delay_slot(int instr) { set_long_at(4, instr);} | |
895 Assembler::Condition condition() { | |
896 int x = long_at(0); | |
897 return (Assembler::Condition) Assembler::inv_cond(x); | |
898 } | |
899 | |
900 // Creation | |
901 friend inline NativeGeneralJump* nativeGeneralJump_at(address address) { | |
902 NativeGeneralJump* jump = (NativeGeneralJump*)(address); | |
903 #ifdef ASSERT | |
904 jump->verify(); | |
905 #endif | |
906 return jump; | |
907 } | |
908 | |
909 // Insertion of native general jump instruction | |
910 static void insert_unconditional(address code_pos, address entry); | |
911 static void replace_mt_safe(address instr_addr, address code_buffer); | |
912 | |
913 void verify(); | |
914 }; | |
915 | |
916 | |
917 class NativeIllegalInstruction: public NativeInstruction { | |
918 public: | |
919 enum Sparc_specific_constants { | |
920 instruction_size = 4 | |
921 }; | |
922 | |
923 // Insert illegal opcode as specific address | |
924 static void insert(address code_pos); | |
925 }; | |
1972 | 926 |
927 #endif // CPU_SPARC_VM_NATIVEINST_SPARC_HPP |