Mercurial > hg > truffle
annotate src/cpu/x86/vm/nativeInst_x86.hpp @ 5736:915952ed97c0
fixed minor layout bug
author | Katrin Strassl <k.strassl@gmx.net> |
---|---|
date | Wed, 27 Jun 2012 11:48:26 +0200 |
parents | b5dc2403c1e7 |
children | f565e8d4d200 |
rev | line source |
---|---|
0 | 1 /* |
2404
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
1972
diff
changeset
|
2 * Copyright (c) 1997, 2011, 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:
314
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
314
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:
314
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
1972 | 25 #ifndef CPU_X86_VM_NATIVEINST_X86_HPP |
26 #define CPU_X86_VM_NATIVEINST_X86_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 interfaces for the following instructions: |
35 // - NativeInstruction | |
36 // - - NativeCall | |
37 // - - NativeMovConstReg | |
38 // - - NativeMovConstRegPatching | |
39 // - - NativeMovRegMem | |
40 // - - NativeMovRegMemPatching | |
41 // - - NativeJump | |
42 // - - NativeIllegalOpCode | |
43 // - - NativeGeneralJump | |
44 // - - NativeReturn | |
45 // - - NativeReturnX (return with argument) | |
46 // - - NativePushConst | |
47 // - - NativeTstRegMem | |
48 | |
49 // The base class for different kinds of native instruction abstractions. | |
50 // Provides the primitive operations to manipulate code relative to this. | |
51 | |
52 class NativeInstruction VALUE_OBJ_CLASS_SPEC { | |
53 friend class Relocation; | |
54 | |
55 public: | |
56 enum Intel_specific_constants { | |
57 nop_instruction_code = 0x90, | |
58 nop_instruction_size = 1 | |
59 }; | |
60 | |
61 bool is_nop() { return ubyte_at(0) == nop_instruction_code; } | |
116
018d5b58dd4f
6537506: Provide a mechanism for specifying Java-level USDT-like dtrace probes
kamg
parents:
0
diff
changeset
|
62 bool is_dtrace_trap(); |
0 | 63 inline bool is_call(); |
5000
b5dc2403c1e7
add option to inline VTable stubs
Lukas Stadler <lukas.stadler@jku.at>
parents:
4970
diff
changeset
|
64 inline bool is_call_reg(); |
0 | 65 inline bool is_illegal(); |
66 inline bool is_return(); | |
67 inline bool is_jump(); | |
68 inline bool is_cond_jump(); | |
69 inline bool is_safepoint_poll(); | |
70 inline bool is_mov_literal64(); | |
71 | |
72 protected: | |
73 address addr_at(int offset) const { return address(this) + offset; } | |
74 | |
75 s_char sbyte_at(int offset) const { return *(s_char*) addr_at(offset); } | |
76 u_char ubyte_at(int offset) const { return *(u_char*) addr_at(offset); } | |
77 | |
78 jint int_at(int offset) const { return *(jint*) addr_at(offset); } | |
79 | |
80 intptr_t ptr_at(int offset) const { return *(intptr_t*) addr_at(offset); } | |
81 | |
82 oop oop_at (int offset) const { return *(oop*) addr_at(offset); } | |
83 | |
84 | |
85 void set_char_at(int offset, char c) { *addr_at(offset) = (u_char)c; wrote(offset); } | |
86 void set_int_at(int offset, jint i) { *(jint*)addr_at(offset) = i; wrote(offset); } | |
87 void set_ptr_at (int offset, intptr_t ptr) { *(intptr_t*) addr_at(offset) = ptr; wrote(offset); } | |
88 void set_oop_at (int offset, oop o) { *(oop*) addr_at(offset) = o; wrote(offset); } | |
89 | |
90 // This doesn't really do anything on Intel, but it is the place where | |
91 // cache invalidation belongs, generically: | |
92 void wrote(int offset); | |
93 | |
94 public: | |
95 | |
96 // unit test stuff | |
97 static void test() {} // override for testing | |
98 | |
99 inline friend NativeInstruction* nativeInstruction_at(address address); | |
100 }; | |
101 | |
102 inline NativeInstruction* nativeInstruction_at(address address) { | |
103 NativeInstruction* inst = (NativeInstruction*)address; | |
104 #ifdef ASSERT | |
105 //inst->verify(); | |
106 #endif | |
107 return inst; | |
108 } | |
109 | |
110 inline NativeCall* nativeCall_at(address address); | |
111 // The NativeCall is an abstraction for accessing/manipulating native call imm32/rel32off | |
112 // instructions (used to manipulate inline caches, primitive & dll calls, etc.). | |
113 | |
114 class NativeCall: public NativeInstruction { | |
115 public: | |
116 enum Intel_specific_constants { | |
117 instruction_code = 0xE8, | |
118 instruction_size = 5, | |
119 instruction_offset = 0, | |
120 displacement_offset = 1, | |
121 return_address_offset = 5 | |
122 }; | |
123 | |
124 enum { cache_line_size = BytesPerWord }; // conservative estimate! | |
125 | |
126 address instruction_address() const { return addr_at(instruction_offset); } | |
127 address next_instruction_address() const { return addr_at(return_address_offset); } | |
128 int displacement() const { return (jint) int_at(displacement_offset); } | |
129 address displacement_address() const { return addr_at(displacement_offset); } | |
130 address return_address() const { return addr_at(return_address_offset); } | |
131 address destination() const; | |
132 void set_destination(address dest) { | |
133 #ifdef AMD64 | |
134 assert((labs((intptr_t) dest - (intptr_t) return_address()) & | |
135 0xFFFFFFFF00000000) == 0, | |
136 "must be 32bit offset"); | |
137 #endif // AMD64 | |
138 set_int_at(displacement_offset, dest - return_address()); | |
139 } | |
140 void set_destination_mt_safe(address dest); | |
141 | |
142 void verify_alignment() { assert((intptr_t)addr_at(displacement_offset) % BytesPerInt == 0, "must be aligned"); } | |
143 void verify(); | |
144 void print(); | |
145 | |
146 // Creation | |
147 inline friend NativeCall* nativeCall_at(address address); | |
148 inline friend NativeCall* nativeCall_before(address return_address); | |
149 | |
150 static bool is_call_at(address instr) { | |
151 return ((*instr) & 0xFF) == NativeCall::instruction_code; | |
152 } | |
153 | |
154 static bool is_call_before(address return_address) { | |
155 return is_call_at(return_address - NativeCall::return_address_offset); | |
156 } | |
157 | |
158 static bool is_call_to(address instr, address target) { | |
159 return nativeInstruction_at(instr)->is_call() && | |
160 nativeCall_at(instr)->destination() == target; | |
161 } | |
162 | |
163 // MT-safe patching of a call instruction. | |
164 static void insert(address code_pos, address entry); | |
165 | |
166 static void replace_mt_safe(address instr_addr, address code_buffer); | |
167 }; | |
168 | |
169 inline NativeCall* nativeCall_at(address address) { | |
170 NativeCall* call = (NativeCall*)(address - NativeCall::instruction_offset); | |
171 #ifdef ASSERT | |
172 call->verify(); | |
173 #endif | |
174 return call; | |
175 } | |
176 | |
177 inline NativeCall* nativeCall_before(address return_address) { | |
178 NativeCall* call = (NativeCall*)(return_address - NativeCall::return_address_offset); | |
179 #ifdef ASSERT | |
180 call->verify(); | |
181 #endif | |
182 return call; | |
183 } | |
184 | |
5000
b5dc2403c1e7
add option to inline VTable stubs
Lukas Stadler <lukas.stadler@jku.at>
parents:
4970
diff
changeset
|
185 class NativeCallReg: public NativeInstruction { |
b5dc2403c1e7
add option to inline VTable stubs
Lukas Stadler <lukas.stadler@jku.at>
parents:
4970
diff
changeset
|
186 public: |
b5dc2403c1e7
add option to inline VTable stubs
Lukas Stadler <lukas.stadler@jku.at>
parents:
4970
diff
changeset
|
187 enum Intel_specific_constants { |
b5dc2403c1e7
add option to inline VTable stubs
Lukas Stadler <lukas.stadler@jku.at>
parents:
4970
diff
changeset
|
188 instruction_code = 0xFF, |
b5dc2403c1e7
add option to inline VTable stubs
Lukas Stadler <lukas.stadler@jku.at>
parents:
4970
diff
changeset
|
189 instruction_size = 2, |
b5dc2403c1e7
add option to inline VTable stubs
Lukas Stadler <lukas.stadler@jku.at>
parents:
4970
diff
changeset
|
190 instruction_offset = 0, |
b5dc2403c1e7
add option to inline VTable stubs
Lukas Stadler <lukas.stadler@jku.at>
parents:
4970
diff
changeset
|
191 return_address_offset = 2 |
b5dc2403c1e7
add option to inline VTable stubs
Lukas Stadler <lukas.stadler@jku.at>
parents:
4970
diff
changeset
|
192 }; |
b5dc2403c1e7
add option to inline VTable stubs
Lukas Stadler <lukas.stadler@jku.at>
parents:
4970
diff
changeset
|
193 |
b5dc2403c1e7
add option to inline VTable stubs
Lukas Stadler <lukas.stadler@jku.at>
parents:
4970
diff
changeset
|
194 address instruction_address() const { return addr_at(instruction_offset); } |
b5dc2403c1e7
add option to inline VTable stubs
Lukas Stadler <lukas.stadler@jku.at>
parents:
4970
diff
changeset
|
195 address next_instruction_address() const { return addr_at(return_address_offset); } |
b5dc2403c1e7
add option to inline VTable stubs
Lukas Stadler <lukas.stadler@jku.at>
parents:
4970
diff
changeset
|
196 |
b5dc2403c1e7
add option to inline VTable stubs
Lukas Stadler <lukas.stadler@jku.at>
parents:
4970
diff
changeset
|
197 |
b5dc2403c1e7
add option to inline VTable stubs
Lukas Stadler <lukas.stadler@jku.at>
parents:
4970
diff
changeset
|
198 static bool is_call_reg_at(address instr) { |
b5dc2403c1e7
add option to inline VTable stubs
Lukas Stadler <lukas.stadler@jku.at>
parents:
4970
diff
changeset
|
199 return ((*instr) & 0xFF) == NativeCallReg::instruction_code; |
b5dc2403c1e7
add option to inline VTable stubs
Lukas Stadler <lukas.stadler@jku.at>
parents:
4970
diff
changeset
|
200 } |
b5dc2403c1e7
add option to inline VTable stubs
Lukas Stadler <lukas.stadler@jku.at>
parents:
4970
diff
changeset
|
201 |
b5dc2403c1e7
add option to inline VTable stubs
Lukas Stadler <lukas.stadler@jku.at>
parents:
4970
diff
changeset
|
202 static bool is_call_reg_before(address return_address) { |
b5dc2403c1e7
add option to inline VTable stubs
Lukas Stadler <lukas.stadler@jku.at>
parents:
4970
diff
changeset
|
203 return is_call_reg_at(return_address - NativeCallReg::return_address_offset); |
b5dc2403c1e7
add option to inline VTable stubs
Lukas Stadler <lukas.stadler@jku.at>
parents:
4970
diff
changeset
|
204 } |
b5dc2403c1e7
add option to inline VTable stubs
Lukas Stadler <lukas.stadler@jku.at>
parents:
4970
diff
changeset
|
205 }; |
b5dc2403c1e7
add option to inline VTable stubs
Lukas Stadler <lukas.stadler@jku.at>
parents:
4970
diff
changeset
|
206 |
0 | 207 // An interface for accessing/manipulating native mov reg, imm32 instructions. |
208 // (used to manipulate inlined 32bit data dll calls, etc.) | |
209 class NativeMovConstReg: public NativeInstruction { | |
210 #ifdef AMD64 | |
211 static const bool has_rex = true; | |
212 static const int rex_size = 1; | |
213 #else | |
214 static const bool has_rex = false; | |
215 static const int rex_size = 0; | |
216 #endif // AMD64 | |
217 public: | |
218 enum Intel_specific_constants { | |
219 instruction_code = 0xB8, | |
220 instruction_size = 1 + rex_size + wordSize, | |
221 instruction_offset = 0, | |
222 data_offset = 1 + rex_size, | |
223 next_instruction_offset = instruction_size, | |
224 register_mask = 0x07 | |
225 }; | |
226 | |
227 address instruction_address() const { return addr_at(instruction_offset); } | |
228 address next_instruction_address() const { return addr_at(next_instruction_offset); } | |
229 intptr_t data() const { return ptr_at(data_offset); } | |
230 void set_data(intptr_t x) { set_ptr_at(data_offset, x); } | |
231 | |
232 void verify(); | |
233 void print(); | |
234 | |
235 // unit test stuff | |
236 static void test() {} | |
237 | |
238 // Creation | |
239 inline friend NativeMovConstReg* nativeMovConstReg_at(address address); | |
240 inline friend NativeMovConstReg* nativeMovConstReg_before(address address); | |
241 }; | |
242 | |
243 inline NativeMovConstReg* nativeMovConstReg_at(address address) { | |
244 NativeMovConstReg* test = (NativeMovConstReg*)(address - NativeMovConstReg::instruction_offset); | |
245 #ifdef ASSERT | |
246 test->verify(); | |
247 #endif | |
248 return test; | |
249 } | |
250 | |
251 inline NativeMovConstReg* nativeMovConstReg_before(address address) { | |
252 NativeMovConstReg* test = (NativeMovConstReg*)(address - NativeMovConstReg::instruction_size - NativeMovConstReg::instruction_offset); | |
253 #ifdef ASSERT | |
254 test->verify(); | |
255 #endif | |
256 return test; | |
257 } | |
258 | |
259 class NativeMovConstRegPatching: public NativeMovConstReg { | |
260 private: | |
261 friend NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address) { | |
262 NativeMovConstRegPatching* test = (NativeMovConstRegPatching*)(address - instruction_offset); | |
263 #ifdef ASSERT | |
264 test->verify(); | |
265 #endif | |
266 return test; | |
267 } | |
268 }; | |
269 | |
270 // An interface for accessing/manipulating native moves of the form: | |
304 | 271 // mov[b/w/l/q] [reg + offset], reg (instruction_code_reg2mem) |
272 // mov[b/w/l/q] reg, [reg+offset] (instruction_code_mem2reg | |
273 // mov[s/z]x[w/b/q] [reg + offset], reg | |
0 | 274 // fld_s [reg+offset] |
275 // fld_d [reg+offset] | |
276 // fstp_s [reg + offset] | |
277 // fstp_d [reg + offset] | |
304 | 278 // mov_literal64 scratch,<pointer> ; mov[b/w/l/q] 0(scratch),reg | mov[b/w/l/q] reg,0(scratch) |
0 | 279 // |
280 // Warning: These routines must be able to handle any instruction sequences | |
281 // that are generated as a result of the load/store byte,word,long | |
282 // macros. For example: The load_unsigned_byte instruction generates | |
283 // an xor reg,reg inst prior to generating the movb instruction. This | |
284 // class must skip the xor instruction. | |
285 | |
286 class NativeMovRegMem: public NativeInstruction { | |
287 public: | |
288 enum Intel_specific_constants { | |
304 | 289 instruction_prefix_wide_lo = Assembler::REX, |
290 instruction_prefix_wide_hi = Assembler::REX_WRXB, | |
0 | 291 instruction_code_xor = 0x33, |
292 instruction_extended_prefix = 0x0F, | |
304 | 293 instruction_code_mem2reg_movslq = 0x63, |
0 | 294 instruction_code_mem2reg_movzxb = 0xB6, |
295 instruction_code_mem2reg_movsxb = 0xBE, | |
296 instruction_code_mem2reg_movzxw = 0xB7, | |
297 instruction_code_mem2reg_movsxw = 0xBF, | |
298 instruction_operandsize_prefix = 0x66, | |
304 | 299 instruction_code_reg2mem = 0x89, |
300 instruction_code_mem2reg = 0x8b, | |
0 | 301 instruction_code_reg2memb = 0x88, |
302 instruction_code_mem2regb = 0x8a, | |
303 instruction_code_float_s = 0xd9, | |
304 instruction_code_float_d = 0xdd, | |
305 instruction_code_long_volatile = 0xdf, | |
306 instruction_code_xmm_ss_prefix = 0xf3, | |
307 instruction_code_xmm_sd_prefix = 0xf2, | |
308 instruction_code_xmm_code = 0x0f, | |
309 instruction_code_xmm_load = 0x10, | |
310 instruction_code_xmm_store = 0x11, | |
311 instruction_code_xmm_lpd = 0x12, | |
312 | |
4759 | 313 instruction_VEX_prefix_2bytes = Assembler::VEX_2bytes, |
314 instruction_VEX_prefix_3bytes = Assembler::VEX_3bytes, | |
315 | |
0 | 316 instruction_size = 4, |
317 instruction_offset = 0, | |
318 data_offset = 2, | |
319 next_instruction_offset = 4 | |
320 }; | |
321 | |
304 | 322 // helper |
323 int instruction_start() const; | |
324 | |
325 address instruction_address() const; | |
0 | 326 |
304 | 327 address next_instruction_address() const; |
0 | 328 |
304 | 329 int offset() const; |
330 | |
331 void set_offset(int x); | |
0 | 332 |
333 void add_offset_in_bytes(int add_offset) { set_offset ( ( offset() + add_offset ) ); } | |
334 | |
335 void verify(); | |
336 void print (); | |
337 | |
338 // unit test stuff | |
339 static void test() {} | |
340 | |
341 private: | |
342 inline friend NativeMovRegMem* nativeMovRegMem_at (address address); | |
343 }; | |
344 | |
345 inline NativeMovRegMem* nativeMovRegMem_at (address address) { | |
346 NativeMovRegMem* test = (NativeMovRegMem*)(address - NativeMovRegMem::instruction_offset); | |
347 #ifdef ASSERT | |
348 test->verify(); | |
349 #endif | |
350 return test; | |
351 } | |
352 | |
353 class NativeMovRegMemPatching: public NativeMovRegMem { | |
354 private: | |
355 friend NativeMovRegMemPatching* nativeMovRegMemPatching_at (address address) { | |
356 NativeMovRegMemPatching* test = (NativeMovRegMemPatching*)(address - instruction_offset); | |
357 #ifdef ASSERT | |
358 test->verify(); | |
359 #endif | |
360 return test; | |
361 } | |
362 }; | |
363 | |
364 | |
365 | |
366 // An interface for accessing/manipulating native leal instruction of form: | |
367 // leal reg, [reg + offset] | |
368 | |
369 class NativeLoadAddress: public NativeMovRegMem { | |
304 | 370 #ifdef AMD64 |
371 static const bool has_rex = true; | |
372 static const int rex_size = 1; | |
373 #else | |
374 static const bool has_rex = false; | |
375 static const int rex_size = 0; | |
376 #endif // AMD64 | |
0 | 377 public: |
378 enum Intel_specific_constants { | |
304 | 379 instruction_prefix_wide = Assembler::REX_W, |
380 instruction_prefix_wide_extended = Assembler::REX_WB, | |
381 lea_instruction_code = 0x8D, | |
382 mov64_instruction_code = 0xB8 | |
0 | 383 }; |
384 | |
385 void verify(); | |
386 void print (); | |
387 | |
388 // unit test stuff | |
389 static void test() {} | |
390 | |
391 private: | |
392 friend NativeLoadAddress* nativeLoadAddress_at (address address) { | |
393 NativeLoadAddress* test = (NativeLoadAddress*)(address - instruction_offset); | |
394 #ifdef ASSERT | |
395 test->verify(); | |
396 #endif | |
397 return test; | |
398 } | |
399 }; | |
400 | |
401 // jump rel32off | |
402 | |
403 class NativeJump: public NativeInstruction { | |
404 public: | |
405 enum Intel_specific_constants { | |
406 instruction_code = 0xe9, | |
407 instruction_size = 5, | |
408 instruction_offset = 0, | |
409 data_offset = 1, | |
410 next_instruction_offset = 5 | |
411 }; | |
412 | |
413 address instruction_address() const { return addr_at(instruction_offset); } | |
414 address next_instruction_address() const { return addr_at(next_instruction_offset); } | |
415 address jump_destination() const { | |
416 address dest = (int_at(data_offset)+next_instruction_address()); | |
304 | 417 // 32bit used to encode unresolved jmp as jmp -1 |
418 // 64bit can't produce this so it used jump to self. | |
419 // Now 32bit and 64bit use jump to self as the unresolved address | |
420 // which the inline cache code (and relocs) know about | |
421 | |
0 | 422 // return -1 if jump to self |
423 dest = (dest == (address) this) ? (address) -1 : dest; | |
424 return dest; | |
425 } | |
426 | |
427 void set_jump_destination(address dest) { | |
428 intptr_t val = dest - next_instruction_address(); | |
314
3a26e9e4be71
6744422: incorrect handling of -1 in set_jump_destination
never
parents:
304
diff
changeset
|
429 if (dest == (address) -1) { |
3a26e9e4be71
6744422: incorrect handling of -1 in set_jump_destination
never
parents:
304
diff
changeset
|
430 val = -5; // jump to self |
3a26e9e4be71
6744422: incorrect handling of -1 in set_jump_destination
never
parents:
304
diff
changeset
|
431 } |
0 | 432 #ifdef AMD64 |
304 | 433 assert((labs(val) & 0xFFFFFFFF00000000) == 0 || dest == (address)-1, "must be 32bit offset or -1"); |
0 | 434 #endif // AMD64 |
435 set_int_at(data_offset, (jint)val); | |
436 } | |
437 | |
438 // Creation | |
439 inline friend NativeJump* nativeJump_at(address address); | |
440 | |
441 void verify(); | |
442 | |
443 // Unit testing stuff | |
444 static void test() {} | |
445 | |
446 // Insertion of native jump instruction | |
447 static void insert(address code_pos, address entry); | |
448 // MT-safe insertion of native jump at verified method entry | |
449 static void check_verified_entry_alignment(address entry, address verified_entry); | |
450 static void patch_verified_entry(address entry, address verified_entry, address dest); | |
451 }; | |
452 | |
453 inline NativeJump* nativeJump_at(address address) { | |
454 NativeJump* jump = (NativeJump*)(address - NativeJump::instruction_offset); | |
455 #ifdef ASSERT | |
456 jump->verify(); | |
457 #endif | |
458 return jump; | |
459 } | |
460 | |
461 // Handles all kinds of jump on Intel. Long/far, conditional/unconditional | |
462 class NativeGeneralJump: public NativeInstruction { | |
463 public: | |
464 enum Intel_specific_constants { | |
465 // Constants does not apply, since the lengths and offsets depends on the actual jump | |
466 // used | |
467 // Instruction codes: | |
468 // Unconditional jumps: 0xE9 (rel32off), 0xEB (rel8off) | |
469 // Conditional jumps: 0x0F8x (rel32off), 0x7x (rel8off) | |
470 unconditional_long_jump = 0xe9, | |
471 unconditional_short_jump = 0xeb, | |
472 instruction_size = 5 | |
473 }; | |
474 | |
475 address instruction_address() const { return addr_at(0); } | |
476 address jump_destination() const; | |
477 | |
478 // Creation | |
479 inline friend NativeGeneralJump* nativeGeneralJump_at(address address); | |
480 | |
481 // Insertion of native general jump instruction | |
482 static void insert_unconditional(address code_pos, address entry); | |
483 static void replace_mt_safe(address instr_addr, address code_buffer); | |
484 | |
485 void verify(); | |
486 }; | |
487 | |
488 inline NativeGeneralJump* nativeGeneralJump_at(address address) { | |
489 NativeGeneralJump* jump = (NativeGeneralJump*)(address); | |
490 debug_only(jump->verify();) | |
491 return jump; | |
492 } | |
493 | |
494 class NativePopReg : public NativeInstruction { | |
495 public: | |
496 enum Intel_specific_constants { | |
497 instruction_code = 0x58, | |
498 instruction_size = 1, | |
499 instruction_offset = 0, | |
500 data_offset = 1, | |
501 next_instruction_offset = 1 | |
502 }; | |
503 | |
504 // Insert a pop instruction | |
505 static void insert(address code_pos, Register reg); | |
506 }; | |
507 | |
508 | |
509 class NativeIllegalInstruction: public NativeInstruction { | |
510 public: | |
511 enum Intel_specific_constants { | |
512 instruction_code = 0x0B0F, // Real byte order is: 0x0F, 0x0B | |
513 instruction_size = 2, | |
514 instruction_offset = 0, | |
515 next_instruction_offset = 2 | |
516 }; | |
517 | |
518 // Insert illegal opcode as specific address | |
519 static void insert(address code_pos); | |
520 }; | |
521 | |
522 // return instruction that does not pop values of the stack | |
523 class NativeReturn: public NativeInstruction { | |
524 public: | |
525 enum Intel_specific_constants { | |
526 instruction_code = 0xC3, | |
527 instruction_size = 1, | |
528 instruction_offset = 0, | |
529 next_instruction_offset = 1 | |
530 }; | |
531 }; | |
532 | |
533 // return instruction that does pop values of the stack | |
534 class NativeReturnX: public NativeInstruction { | |
535 public: | |
536 enum Intel_specific_constants { | |
537 instruction_code = 0xC2, | |
538 instruction_size = 2, | |
539 instruction_offset = 0, | |
540 next_instruction_offset = 2 | |
541 }; | |
542 }; | |
543 | |
544 // Simple test vs memory | |
545 class NativeTstRegMem: public NativeInstruction { | |
546 public: | |
547 enum Intel_specific_constants { | |
2404
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
1972
diff
changeset
|
548 instruction_rex_prefix_mask = 0xF0, |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
1972
diff
changeset
|
549 instruction_rex_prefix = Assembler::REX, |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
1972
diff
changeset
|
550 instruction_code_memXregl = 0x85, |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
1972
diff
changeset
|
551 modrm_mask = 0x38, // select reg from the ModRM byte |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
1972
diff
changeset
|
552 modrm_reg = 0x00 // rax |
0 | 553 }; |
554 }; | |
555 | |
556 inline bool NativeInstruction::is_illegal() { return (short)int_at(0) == (short)NativeIllegalInstruction::instruction_code; } | |
557 inline bool NativeInstruction::is_call() { return ubyte_at(0) == NativeCall::instruction_code; } | |
5000
b5dc2403c1e7
add option to inline VTable stubs
Lukas Stadler <lukas.stadler@jku.at>
parents:
4970
diff
changeset
|
558 inline bool NativeInstruction::is_call_reg() { return ubyte_at(0) == NativeCallReg::instruction_code; } |
0 | 559 inline bool NativeInstruction::is_return() { return ubyte_at(0) == NativeReturn::instruction_code || |
560 ubyte_at(0) == NativeReturnX::instruction_code; } | |
561 inline bool NativeInstruction::is_jump() { return ubyte_at(0) == NativeJump::instruction_code || | |
562 ubyte_at(0) == 0xEB; /* short jump */ } | |
563 inline bool NativeInstruction::is_cond_jump() { return (int_at(0) & 0xF0FF) == 0x800F /* long jump */ || | |
564 (ubyte_at(0) & 0xF0) == 0x70; /* short jump */ } | |
565 inline bool NativeInstruction::is_safepoint_poll() { | |
566 #ifdef AMD64 | |
2404
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
1972
diff
changeset
|
567 if (Assembler::is_polling_page_far()) { |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
1972
diff
changeset
|
568 // two cases, depending on the choice of the base register in the address. |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
1972
diff
changeset
|
569 if (((ubyte_at(0) & NativeTstRegMem::instruction_rex_prefix_mask) == NativeTstRegMem::instruction_rex_prefix && |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
1972
diff
changeset
|
570 ubyte_at(1) == NativeTstRegMem::instruction_code_memXregl && |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
1972
diff
changeset
|
571 (ubyte_at(2) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) || |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
1972
diff
changeset
|
572 ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl && |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
1972
diff
changeset
|
573 (ubyte_at(1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) { |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
1972
diff
changeset
|
574 return true; |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
1972
diff
changeset
|
575 } else { |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
1972
diff
changeset
|
576 return false; |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
1972
diff
changeset
|
577 } |
304 | 578 } else { |
3564
f79b652d4437
let hotspot recognize graal's way of doing safepoints (mov instead of test)
Lukas Stadler <lukas.stadler@jku.at>
parents:
2404
diff
changeset
|
579 if (ubyte_at(0) == Assembler::REX_WR && ubyte_at(1) == NativeMovRegMem::instruction_code_mem2reg && ubyte_at(2) == 0x15) { // mov r10, rip[...] |
f79b652d4437
let hotspot recognize graal's way of doing safepoints (mov instead of test)
Lukas Stadler <lukas.stadler@jku.at>
parents:
2404
diff
changeset
|
580 address fault = addr_at(7) + int_at(3); |
f79b652d4437
let hotspot recognize graal's way of doing safepoints (mov instead of test)
Lukas Stadler <lukas.stadler@jku.at>
parents:
2404
diff
changeset
|
581 return os::is_poll_address(fault); |
f79b652d4437
let hotspot recognize graal's way of doing safepoints (mov instead of test)
Lukas Stadler <lukas.stadler@jku.at>
parents:
2404
diff
changeset
|
582 } else if (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl && ubyte_at(1) == 0x05) { // 00 rax 101 |
2404
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
1972
diff
changeset
|
583 address fault = addr_at(6) + int_at(2); |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
1972
diff
changeset
|
584 return os::is_poll_address(fault); |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
1972
diff
changeset
|
585 } else { |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
1972
diff
changeset
|
586 return false; |
b40d4fa697bf
6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents:
1972
diff
changeset
|
587 } |
304 | 588 } |
0 | 589 #else |
304 | 590 return ( ubyte_at(0) == NativeMovRegMem::instruction_code_mem2reg || |
0 | 591 ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl ) && |
592 (ubyte_at(1)&0xC7) == 0x05 && /* Mod R/M == disp32 */ | |
593 (os::is_poll_address((address)int_at(2))); | |
594 #endif // AMD64 | |
595 } | |
596 | |
597 inline bool NativeInstruction::is_mov_literal64() { | |
598 #ifdef AMD64 | |
599 return ((ubyte_at(0) == Assembler::REX_W || ubyte_at(0) == Assembler::REX_WB) && | |
600 (ubyte_at(1) & (0xff ^ NativeMovConstReg::register_mask)) == 0xB8); | |
601 #else | |
602 return false; | |
603 #endif // AMD64 | |
604 } | |
1972 | 605 |
606 #endif // CPU_X86_VM_NATIVEINST_X86_HPP |