annotate src/cpu/x86/vm/nativeInst_x86.hpp @ 15388:769fc3629f59

Add phase FlowSensitiveReductionPhase. It is possible to remove GuardingPiNodes, CheckCastNodes, and FixedGuards during HighTier under certain conditions (control-flow sensitive conditions). The phase added in this commit (FlowSensitiveReductionPhase) does that, and in addition replaces usages with "downcasting" PiNodes when possible thus resulting in more precise object stamps (e.g., non-null). Finally, usages of floating, side-effects free, expressions are also simplified (as per control-flow sensitive conditions). The newly added phase runs only during HighTier and can be deactivated using Graal option FlowSensitiveReduction (it is active by default).
author Miguel Garcia <miguel.m.garcia@oracle.com>
date Fri, 25 Apr 2014 16:50:52 +0200
parents 5335d65fec56
children 0dac22d266d8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
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
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
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
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
25 #ifndef CPU_X86_VM_NATIVEINST_X86_HPP
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
26 #define CPU_X86_VM_NATIVEINST_X86_HPP
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
27
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
28 #include "asm/assembler.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
29 #include "memory/allocation.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
30 #include "runtime/icache.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
31 #include "runtime/os.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
32 #include "utilities/top.hpp"
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
33
0
a61af66fc99e Initial load
duke
parents:
diff changeset
34 // We have interfaces for the following instructions:
a61af66fc99e Initial load
duke
parents:
diff changeset
35 // - NativeInstruction
a61af66fc99e Initial load
duke
parents:
diff changeset
36 // - - NativeCall
a61af66fc99e Initial load
duke
parents:
diff changeset
37 // - - NativeMovConstReg
a61af66fc99e Initial load
duke
parents:
diff changeset
38 // - - NativeMovConstRegPatching
a61af66fc99e Initial load
duke
parents:
diff changeset
39 // - - NativeMovRegMem
a61af66fc99e Initial load
duke
parents:
diff changeset
40 // - - NativeMovRegMemPatching
a61af66fc99e Initial load
duke
parents:
diff changeset
41 // - - NativeJump
a61af66fc99e Initial load
duke
parents:
diff changeset
42 // - - NativeIllegalOpCode
a61af66fc99e Initial load
duke
parents:
diff changeset
43 // - - NativeGeneralJump
a61af66fc99e Initial load
duke
parents:
diff changeset
44 // - - NativeReturn
a61af66fc99e Initial load
duke
parents:
diff changeset
45 // - - NativeReturnX (return with argument)
a61af66fc99e Initial load
duke
parents:
diff changeset
46 // - - NativePushConst
a61af66fc99e Initial load
duke
parents:
diff changeset
47 // - - NativeTstRegMem
a61af66fc99e Initial load
duke
parents:
diff changeset
48
a61af66fc99e Initial load
duke
parents:
diff changeset
49 // The base class for different kinds of native instruction abstractions.
a61af66fc99e Initial load
duke
parents:
diff changeset
50 // Provides the primitive operations to manipulate code relative to this.
a61af66fc99e Initial load
duke
parents:
diff changeset
51
a61af66fc99e Initial load
duke
parents:
diff changeset
52 class NativeInstruction VALUE_OBJ_CLASS_SPEC {
a61af66fc99e Initial load
duke
parents:
diff changeset
53 friend class Relocation;
a61af66fc99e Initial load
duke
parents:
diff changeset
54
a61af66fc99e Initial load
duke
parents:
diff changeset
55 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
56 enum Intel_specific_constants {
a61af66fc99e Initial load
duke
parents:
diff changeset
57 nop_instruction_code = 0x90,
a61af66fc99e Initial load
duke
parents:
diff changeset
58 nop_instruction_size = 1
a61af66fc99e Initial load
duke
parents:
diff changeset
59 };
a61af66fc99e Initial load
duke
parents:
diff changeset
60
a61af66fc99e Initial load
duke
parents:
diff changeset
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
a61af66fc99e Initial load
duke
parents:
diff changeset
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
a61af66fc99e Initial load
duke
parents:
diff changeset
65 inline bool is_illegal();
a61af66fc99e Initial load
duke
parents:
diff changeset
66 inline bool is_return();
a61af66fc99e Initial load
duke
parents:
diff changeset
67 inline bool is_jump();
a61af66fc99e Initial load
duke
parents:
diff changeset
68 inline bool is_cond_jump();
a61af66fc99e Initial load
duke
parents:
diff changeset
69 inline bool is_safepoint_poll();
a61af66fc99e Initial load
duke
parents:
diff changeset
70 inline bool is_mov_literal64();
a61af66fc99e Initial load
duke
parents:
diff changeset
71
a61af66fc99e Initial load
duke
parents:
diff changeset
72 protected:
a61af66fc99e Initial load
duke
parents:
diff changeset
73 address addr_at(int offset) const { return address(this) + offset; }
a61af66fc99e Initial load
duke
parents:
diff changeset
74
a61af66fc99e Initial load
duke
parents:
diff changeset
75 s_char sbyte_at(int offset) const { return *(s_char*) addr_at(offset); }
a61af66fc99e Initial load
duke
parents:
diff changeset
76 u_char ubyte_at(int offset) const { return *(u_char*) addr_at(offset); }
a61af66fc99e Initial load
duke
parents:
diff changeset
77
a61af66fc99e Initial load
duke
parents:
diff changeset
78 jint int_at(int offset) const { return *(jint*) addr_at(offset); }
a61af66fc99e Initial load
duke
parents:
diff changeset
79
a61af66fc99e Initial load
duke
parents:
diff changeset
80 intptr_t ptr_at(int offset) const { return *(intptr_t*) addr_at(offset); }
a61af66fc99e Initial load
duke
parents:
diff changeset
81
a61af66fc99e Initial load
duke
parents:
diff changeset
82 oop oop_at (int offset) const { return *(oop*) addr_at(offset); }
a61af66fc99e Initial load
duke
parents:
diff changeset
83
a61af66fc99e Initial load
duke
parents:
diff changeset
84
a61af66fc99e Initial load
duke
parents:
diff changeset
85 void set_char_at(int offset, char c) { *addr_at(offset) = (u_char)c; wrote(offset); }
a61af66fc99e Initial load
duke
parents:
diff changeset
86 void set_int_at(int offset, jint i) { *(jint*)addr_at(offset) = i; wrote(offset); }
a61af66fc99e Initial load
duke
parents:
diff changeset
87 void set_ptr_at (int offset, intptr_t ptr) { *(intptr_t*) addr_at(offset) = ptr; wrote(offset); }
a61af66fc99e Initial load
duke
parents:
diff changeset
88 void set_oop_at (int offset, oop o) { *(oop*) addr_at(offset) = o; wrote(offset); }
a61af66fc99e Initial load
duke
parents:
diff changeset
89
a61af66fc99e Initial load
duke
parents:
diff changeset
90 // This doesn't really do anything on Intel, but it is the place where
a61af66fc99e Initial load
duke
parents:
diff changeset
91 // cache invalidation belongs, generically:
a61af66fc99e Initial load
duke
parents:
diff changeset
92 void wrote(int offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
93
a61af66fc99e Initial load
duke
parents:
diff changeset
94 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
95
a61af66fc99e Initial load
duke
parents:
diff changeset
96 // unit test stuff
a61af66fc99e Initial load
duke
parents:
diff changeset
97 static void test() {} // override for testing
a61af66fc99e Initial load
duke
parents:
diff changeset
98
a61af66fc99e Initial load
duke
parents:
diff changeset
99 inline friend NativeInstruction* nativeInstruction_at(address address);
a61af66fc99e Initial load
duke
parents:
diff changeset
100 };
a61af66fc99e Initial load
duke
parents:
diff changeset
101
a61af66fc99e Initial load
duke
parents:
diff changeset
102 inline NativeInstruction* nativeInstruction_at(address address) {
a61af66fc99e Initial load
duke
parents:
diff changeset
103 NativeInstruction* inst = (NativeInstruction*)address;
a61af66fc99e Initial load
duke
parents:
diff changeset
104 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
105 //inst->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
106 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
107 return inst;
a61af66fc99e Initial load
duke
parents:
diff changeset
108 }
a61af66fc99e Initial load
duke
parents:
diff changeset
109
a61af66fc99e Initial load
duke
parents:
diff changeset
110 inline NativeCall* nativeCall_at(address address);
a61af66fc99e Initial load
duke
parents:
diff changeset
111 // The NativeCall is an abstraction for accessing/manipulating native call imm32/rel32off
a61af66fc99e Initial load
duke
parents:
diff changeset
112 // instructions (used to manipulate inline caches, primitive & dll calls, etc.).
a61af66fc99e Initial load
duke
parents:
diff changeset
113
a61af66fc99e Initial load
duke
parents:
diff changeset
114 class NativeCall: public NativeInstruction {
a61af66fc99e Initial load
duke
parents:
diff changeset
115 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
116 enum Intel_specific_constants {
a61af66fc99e Initial load
duke
parents:
diff changeset
117 instruction_code = 0xE8,
a61af66fc99e Initial load
duke
parents:
diff changeset
118 instruction_size = 5,
a61af66fc99e Initial load
duke
parents:
diff changeset
119 instruction_offset = 0,
a61af66fc99e Initial load
duke
parents:
diff changeset
120 displacement_offset = 1,
a61af66fc99e Initial load
duke
parents:
diff changeset
121 return_address_offset = 5
a61af66fc99e Initial load
duke
parents:
diff changeset
122 };
a61af66fc99e Initial load
duke
parents:
diff changeset
123
a61af66fc99e Initial load
duke
parents:
diff changeset
124 enum { cache_line_size = BytesPerWord }; // conservative estimate!
a61af66fc99e Initial load
duke
parents:
diff changeset
125
a61af66fc99e Initial load
duke
parents:
diff changeset
126 address instruction_address() const { return addr_at(instruction_offset); }
a61af66fc99e Initial load
duke
parents:
diff changeset
127 address next_instruction_address() const { return addr_at(return_address_offset); }
a61af66fc99e Initial load
duke
parents:
diff changeset
128 int displacement() const { return (jint) int_at(displacement_offset); }
a61af66fc99e Initial load
duke
parents:
diff changeset
129 address displacement_address() const { return addr_at(displacement_offset); }
a61af66fc99e Initial load
duke
parents:
diff changeset
130 address return_address() const { return addr_at(return_address_offset); }
a61af66fc99e Initial load
duke
parents:
diff changeset
131 address destination() const;
a61af66fc99e Initial load
duke
parents:
diff changeset
132 void set_destination(address dest) {
a61af66fc99e Initial load
duke
parents:
diff changeset
133 #ifdef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
134 assert((labs((intptr_t) dest - (intptr_t) return_address()) &
a61af66fc99e Initial load
duke
parents:
diff changeset
135 0xFFFFFFFF00000000) == 0,
a61af66fc99e Initial load
duke
parents:
diff changeset
136 "must be 32bit offset");
a61af66fc99e Initial load
duke
parents:
diff changeset
137 #endif // AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
138 set_int_at(displacement_offset, dest - return_address());
a61af66fc99e Initial load
duke
parents:
diff changeset
139 }
a61af66fc99e Initial load
duke
parents:
diff changeset
140 void set_destination_mt_safe(address dest);
a61af66fc99e Initial load
duke
parents:
diff changeset
141
a61af66fc99e Initial load
duke
parents:
diff changeset
142 void verify_alignment() { assert((intptr_t)addr_at(displacement_offset) % BytesPerInt == 0, "must be aligned"); }
a61af66fc99e Initial load
duke
parents:
diff changeset
143 void verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
144 void print();
a61af66fc99e Initial load
duke
parents:
diff changeset
145
a61af66fc99e Initial load
duke
parents:
diff changeset
146 // Creation
a61af66fc99e Initial load
duke
parents:
diff changeset
147 inline friend NativeCall* nativeCall_at(address address);
a61af66fc99e Initial load
duke
parents:
diff changeset
148 inline friend NativeCall* nativeCall_before(address return_address);
a61af66fc99e Initial load
duke
parents:
diff changeset
149
a61af66fc99e Initial load
duke
parents:
diff changeset
150 static bool is_call_at(address instr) {
a61af66fc99e Initial load
duke
parents:
diff changeset
151 return ((*instr) & 0xFF) == NativeCall::instruction_code;
a61af66fc99e Initial load
duke
parents:
diff changeset
152 }
a61af66fc99e Initial load
duke
parents:
diff changeset
153
a61af66fc99e Initial load
duke
parents:
diff changeset
154 static bool is_call_before(address return_address) {
a61af66fc99e Initial load
duke
parents:
diff changeset
155 return is_call_at(return_address - NativeCall::return_address_offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
156 }
a61af66fc99e Initial load
duke
parents:
diff changeset
157
a61af66fc99e Initial load
duke
parents:
diff changeset
158 static bool is_call_to(address instr, address target) {
a61af66fc99e Initial load
duke
parents:
diff changeset
159 return nativeInstruction_at(instr)->is_call() &&
a61af66fc99e Initial load
duke
parents:
diff changeset
160 nativeCall_at(instr)->destination() == target;
a61af66fc99e Initial load
duke
parents:
diff changeset
161 }
a61af66fc99e Initial load
duke
parents:
diff changeset
162
a61af66fc99e Initial load
duke
parents:
diff changeset
163 // MT-safe patching of a call instruction.
a61af66fc99e Initial load
duke
parents:
diff changeset
164 static void insert(address code_pos, address entry);
a61af66fc99e Initial load
duke
parents:
diff changeset
165
a61af66fc99e Initial load
duke
parents:
diff changeset
166 static void replace_mt_safe(address instr_addr, address code_buffer);
a61af66fc99e Initial load
duke
parents:
diff changeset
167 };
a61af66fc99e Initial load
duke
parents:
diff changeset
168
a61af66fc99e Initial load
duke
parents:
diff changeset
169 inline NativeCall* nativeCall_at(address address) {
a61af66fc99e Initial load
duke
parents:
diff changeset
170 NativeCall* call = (NativeCall*)(address - NativeCall::instruction_offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
171 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
172 call->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
173 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
174 return call;
a61af66fc99e Initial load
duke
parents:
diff changeset
175 }
a61af66fc99e Initial load
duke
parents:
diff changeset
176
a61af66fc99e Initial load
duke
parents:
diff changeset
177 inline NativeCall* nativeCall_before(address return_address) {
a61af66fc99e Initial load
duke
parents:
diff changeset
178 NativeCall* call = (NativeCall*)(return_address - NativeCall::return_address_offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
179 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
180 call->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
181 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
182 return call;
a61af66fc99e Initial load
duke
parents:
diff changeset
183 }
a61af66fc99e Initial load
duke
parents:
diff changeset
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_offset = 0,
5840
f565e8d4d200 parsing and patching of variable sized NativeCallReg instructions now works properly
Doug Simon <doug.simon@oracle.com>
parents: 5000
diff changeset
190 return_address_offset_norex = 2,
f565e8d4d200 parsing and patching of variable sized NativeCallReg instructions now works properly
Doug Simon <doug.simon@oracle.com>
parents: 5000
diff changeset
191 return_address_offset_rex = 3
5000
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
5840
f565e8d4d200 parsing and patching of variable sized NativeCallReg instructions now works properly
Doug Simon <doug.simon@oracle.com>
parents: 5000
diff changeset
194 int next_instruction_offset() const {
f565e8d4d200 parsing and patching of variable sized NativeCallReg instructions now works properly
Doug Simon <doug.simon@oracle.com>
parents: 5000
diff changeset
195 if (ubyte_at(0) == NativeCallReg::instruction_code) {
f565e8d4d200 parsing and patching of variable sized NativeCallReg instructions now works properly
Doug Simon <doug.simon@oracle.com>
parents: 5000
diff changeset
196 return return_address_offset_norex;
f565e8d4d200 parsing and patching of variable sized NativeCallReg instructions now works properly
Doug Simon <doug.simon@oracle.com>
parents: 5000
diff changeset
197 } else {
f565e8d4d200 parsing and patching of variable sized NativeCallReg instructions now works properly
Doug Simon <doug.simon@oracle.com>
parents: 5000
diff changeset
198 return return_address_offset_rex;
f565e8d4d200 parsing and patching of variable sized NativeCallReg instructions now works properly
Doug Simon <doug.simon@oracle.com>
parents: 5000
diff changeset
199 }
5000
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
0
a61af66fc99e Initial load
duke
parents:
diff changeset
203 // An interface for accessing/manipulating native mov reg, imm32 instructions.
a61af66fc99e Initial load
duke
parents:
diff changeset
204 // (used to manipulate inlined 32bit data dll calls, etc.)
a61af66fc99e Initial load
duke
parents:
diff changeset
205 class NativeMovConstReg: public NativeInstruction {
a61af66fc99e Initial load
duke
parents:
diff changeset
206 #ifdef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
207 static const bool has_rex = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
208 static const int rex_size = 1;
a61af66fc99e Initial load
duke
parents:
diff changeset
209 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
210 static const bool has_rex = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
211 static const int rex_size = 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
212 #endif // AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
213 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
214 enum Intel_specific_constants {
a61af66fc99e Initial load
duke
parents:
diff changeset
215 instruction_code = 0xB8,
a61af66fc99e Initial load
duke
parents:
diff changeset
216 instruction_size = 1 + rex_size + wordSize,
a61af66fc99e Initial load
duke
parents:
diff changeset
217 instruction_offset = 0,
a61af66fc99e Initial load
duke
parents:
diff changeset
218 data_offset = 1 + rex_size,
a61af66fc99e Initial load
duke
parents:
diff changeset
219 next_instruction_offset = instruction_size,
a61af66fc99e Initial load
duke
parents:
diff changeset
220 register_mask = 0x07
a61af66fc99e Initial load
duke
parents:
diff changeset
221 };
a61af66fc99e Initial load
duke
parents:
diff changeset
222
a61af66fc99e Initial load
duke
parents:
diff changeset
223 address instruction_address() const { return addr_at(instruction_offset); }
a61af66fc99e Initial load
duke
parents:
diff changeset
224 address next_instruction_address() const { return addr_at(next_instruction_offset); }
a61af66fc99e Initial load
duke
parents:
diff changeset
225 intptr_t data() const { return ptr_at(data_offset); }
a61af66fc99e Initial load
duke
parents:
diff changeset
226 void set_data(intptr_t x) { set_ptr_at(data_offset, x); }
a61af66fc99e Initial load
duke
parents:
diff changeset
227
a61af66fc99e Initial load
duke
parents:
diff changeset
228 void verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
229 void print();
a61af66fc99e Initial load
duke
parents:
diff changeset
230
a61af66fc99e Initial load
duke
parents:
diff changeset
231 // unit test stuff
a61af66fc99e Initial load
duke
parents:
diff changeset
232 static void test() {}
a61af66fc99e Initial load
duke
parents:
diff changeset
233
a61af66fc99e Initial load
duke
parents:
diff changeset
234 // Creation
a61af66fc99e Initial load
duke
parents:
diff changeset
235 inline friend NativeMovConstReg* nativeMovConstReg_at(address address);
a61af66fc99e Initial load
duke
parents:
diff changeset
236 inline friend NativeMovConstReg* nativeMovConstReg_before(address address);
a61af66fc99e Initial load
duke
parents:
diff changeset
237 };
a61af66fc99e Initial load
duke
parents:
diff changeset
238
a61af66fc99e Initial load
duke
parents:
diff changeset
239 inline NativeMovConstReg* nativeMovConstReg_at(address address) {
a61af66fc99e Initial load
duke
parents:
diff changeset
240 NativeMovConstReg* test = (NativeMovConstReg*)(address - NativeMovConstReg::instruction_offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
241 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
242 test->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
243 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
244 return test;
a61af66fc99e Initial load
duke
parents:
diff changeset
245 }
a61af66fc99e Initial load
duke
parents:
diff changeset
246
a61af66fc99e Initial load
duke
parents:
diff changeset
247 inline NativeMovConstReg* nativeMovConstReg_before(address address) {
a61af66fc99e Initial load
duke
parents:
diff changeset
248 NativeMovConstReg* test = (NativeMovConstReg*)(address - NativeMovConstReg::instruction_size - NativeMovConstReg::instruction_offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
249 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
250 test->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
251 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
252 return test;
a61af66fc99e Initial load
duke
parents:
diff changeset
253 }
a61af66fc99e Initial load
duke
parents:
diff changeset
254
a61af66fc99e Initial load
duke
parents:
diff changeset
255 class NativeMovConstRegPatching: public NativeMovConstReg {
a61af66fc99e Initial load
duke
parents:
diff changeset
256 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
257 friend NativeMovConstRegPatching* nativeMovConstRegPatching_at(address address) {
a61af66fc99e Initial load
duke
parents:
diff changeset
258 NativeMovConstRegPatching* test = (NativeMovConstRegPatching*)(address - instruction_offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
259 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
260 test->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
261 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
262 return test;
a61af66fc99e Initial load
duke
parents:
diff changeset
263 }
a61af66fc99e Initial load
duke
parents:
diff changeset
264 };
a61af66fc99e Initial load
duke
parents:
diff changeset
265
a61af66fc99e Initial load
duke
parents:
diff changeset
266 // An interface for accessing/manipulating native moves of the form:
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
267 // mov[b/w/l/q] [reg + offset], reg (instruction_code_reg2mem)
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
268 // mov[b/w/l/q] reg, [reg+offset] (instruction_code_mem2reg
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
269 // mov[s/z]x[w/b/q] [reg + offset], reg
0
a61af66fc99e Initial load
duke
parents:
diff changeset
270 // fld_s [reg+offset]
a61af66fc99e Initial load
duke
parents:
diff changeset
271 // fld_d [reg+offset]
a61af66fc99e Initial load
duke
parents:
diff changeset
272 // fstp_s [reg + offset]
a61af66fc99e Initial load
duke
parents:
diff changeset
273 // fstp_d [reg + offset]
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
274 // mov_literal64 scratch,<pointer> ; mov[b/w/l/q] 0(scratch),reg | mov[b/w/l/q] reg,0(scratch)
0
a61af66fc99e Initial load
duke
parents:
diff changeset
275 //
a61af66fc99e Initial load
duke
parents:
diff changeset
276 // Warning: These routines must be able to handle any instruction sequences
a61af66fc99e Initial load
duke
parents:
diff changeset
277 // that are generated as a result of the load/store byte,word,long
a61af66fc99e Initial load
duke
parents:
diff changeset
278 // macros. For example: The load_unsigned_byte instruction generates
a61af66fc99e Initial load
duke
parents:
diff changeset
279 // an xor reg,reg inst prior to generating the movb instruction. This
a61af66fc99e Initial load
duke
parents:
diff changeset
280 // class must skip the xor instruction.
a61af66fc99e Initial load
duke
parents:
diff changeset
281
a61af66fc99e Initial load
duke
parents:
diff changeset
282 class NativeMovRegMem: public NativeInstruction {
a61af66fc99e Initial load
duke
parents:
diff changeset
283 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
284 enum Intel_specific_constants {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
285 instruction_prefix_wide_lo = Assembler::REX,
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
286 instruction_prefix_wide_hi = Assembler::REX_WRXB,
0
a61af66fc99e Initial load
duke
parents:
diff changeset
287 instruction_code_xor = 0x33,
a61af66fc99e Initial load
duke
parents:
diff changeset
288 instruction_extended_prefix = 0x0F,
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
289 instruction_code_mem2reg_movslq = 0x63,
0
a61af66fc99e Initial load
duke
parents:
diff changeset
290 instruction_code_mem2reg_movzxb = 0xB6,
a61af66fc99e Initial load
duke
parents:
diff changeset
291 instruction_code_mem2reg_movsxb = 0xBE,
a61af66fc99e Initial load
duke
parents:
diff changeset
292 instruction_code_mem2reg_movzxw = 0xB7,
a61af66fc99e Initial load
duke
parents:
diff changeset
293 instruction_code_mem2reg_movsxw = 0xBF,
a61af66fc99e Initial load
duke
parents:
diff changeset
294 instruction_operandsize_prefix = 0x66,
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
295 instruction_code_reg2mem = 0x89,
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
296 instruction_code_mem2reg = 0x8b,
0
a61af66fc99e Initial load
duke
parents:
diff changeset
297 instruction_code_reg2memb = 0x88,
a61af66fc99e Initial load
duke
parents:
diff changeset
298 instruction_code_mem2regb = 0x8a,
a61af66fc99e Initial load
duke
parents:
diff changeset
299 instruction_code_float_s = 0xd9,
a61af66fc99e Initial load
duke
parents:
diff changeset
300 instruction_code_float_d = 0xdd,
a61af66fc99e Initial load
duke
parents:
diff changeset
301 instruction_code_long_volatile = 0xdf,
a61af66fc99e Initial load
duke
parents:
diff changeset
302 instruction_code_xmm_ss_prefix = 0xf3,
a61af66fc99e Initial load
duke
parents:
diff changeset
303 instruction_code_xmm_sd_prefix = 0xf2,
a61af66fc99e Initial load
duke
parents:
diff changeset
304 instruction_code_xmm_code = 0x0f,
a61af66fc99e Initial load
duke
parents:
diff changeset
305 instruction_code_xmm_load = 0x10,
a61af66fc99e Initial load
duke
parents:
diff changeset
306 instruction_code_xmm_store = 0x11,
a61af66fc99e Initial load
duke
parents:
diff changeset
307 instruction_code_xmm_lpd = 0x12,
a61af66fc99e Initial load
duke
parents:
diff changeset
308
4759
127b3692c168 7116452: Add support for AVX instructions
kvn
parents: 2404
diff changeset
309 instruction_VEX_prefix_2bytes = Assembler::VEX_2bytes,
127b3692c168 7116452: Add support for AVX instructions
kvn
parents: 2404
diff changeset
310 instruction_VEX_prefix_3bytes = Assembler::VEX_3bytes,
127b3692c168 7116452: Add support for AVX instructions
kvn
parents: 2404
diff changeset
311
0
a61af66fc99e Initial load
duke
parents:
diff changeset
312 instruction_size = 4,
a61af66fc99e Initial load
duke
parents:
diff changeset
313 instruction_offset = 0,
a61af66fc99e Initial load
duke
parents:
diff changeset
314 data_offset = 2,
a61af66fc99e Initial load
duke
parents:
diff changeset
315 next_instruction_offset = 4
a61af66fc99e Initial load
duke
parents:
diff changeset
316 };
a61af66fc99e Initial load
duke
parents:
diff changeset
317
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
318 // helper
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
319 int instruction_start() const;
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
320
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
321 address instruction_address() const;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
322
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
323 address next_instruction_address() const;
0
a61af66fc99e Initial load
duke
parents:
diff changeset
324
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
325 int offset() const;
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
326
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
327 void set_offset(int x);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
328
a61af66fc99e Initial load
duke
parents:
diff changeset
329 void add_offset_in_bytes(int add_offset) { set_offset ( ( offset() + add_offset ) ); }
a61af66fc99e Initial load
duke
parents:
diff changeset
330
a61af66fc99e Initial load
duke
parents:
diff changeset
331 void verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
332 void print ();
a61af66fc99e Initial load
duke
parents:
diff changeset
333
a61af66fc99e Initial load
duke
parents:
diff changeset
334 // unit test stuff
a61af66fc99e Initial load
duke
parents:
diff changeset
335 static void test() {}
a61af66fc99e Initial load
duke
parents:
diff changeset
336
a61af66fc99e Initial load
duke
parents:
diff changeset
337 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
338 inline friend NativeMovRegMem* nativeMovRegMem_at (address address);
a61af66fc99e Initial load
duke
parents:
diff changeset
339 };
a61af66fc99e Initial load
duke
parents:
diff changeset
340
a61af66fc99e Initial load
duke
parents:
diff changeset
341 inline NativeMovRegMem* nativeMovRegMem_at (address address) {
a61af66fc99e Initial load
duke
parents:
diff changeset
342 NativeMovRegMem* test = (NativeMovRegMem*)(address - NativeMovRegMem::instruction_offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
343 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
344 test->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
345 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
346 return test;
a61af66fc99e Initial load
duke
parents:
diff changeset
347 }
a61af66fc99e Initial load
duke
parents:
diff changeset
348
a61af66fc99e Initial load
duke
parents:
diff changeset
349 class NativeMovRegMemPatching: public NativeMovRegMem {
a61af66fc99e Initial load
duke
parents:
diff changeset
350 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
351 friend NativeMovRegMemPatching* nativeMovRegMemPatching_at (address address) {
a61af66fc99e Initial load
duke
parents:
diff changeset
352 NativeMovRegMemPatching* test = (NativeMovRegMemPatching*)(address - instruction_offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
353 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
354 test->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
355 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
356 return test;
a61af66fc99e Initial load
duke
parents:
diff changeset
357 }
a61af66fc99e Initial load
duke
parents:
diff changeset
358 };
a61af66fc99e Initial load
duke
parents:
diff changeset
359
a61af66fc99e Initial load
duke
parents:
diff changeset
360
a61af66fc99e Initial load
duke
parents:
diff changeset
361
a61af66fc99e Initial load
duke
parents:
diff changeset
362 // An interface for accessing/manipulating native leal instruction of form:
a61af66fc99e Initial load
duke
parents:
diff changeset
363 // leal reg, [reg + offset]
a61af66fc99e Initial load
duke
parents:
diff changeset
364
a61af66fc99e Initial load
duke
parents:
diff changeset
365 class NativeLoadAddress: public NativeMovRegMem {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
366 #ifdef AMD64
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
367 static const bool has_rex = true;
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
368 static const int rex_size = 1;
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
369 #else
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
370 static const bool has_rex = false;
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
371 static const int rex_size = 0;
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
372 #endif // AMD64
0
a61af66fc99e Initial load
duke
parents:
diff changeset
373 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
374 enum Intel_specific_constants {
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
375 instruction_prefix_wide = Assembler::REX_W,
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
376 instruction_prefix_wide_extended = Assembler::REX_WB,
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
377 lea_instruction_code = 0x8D,
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
378 mov64_instruction_code = 0xB8
0
a61af66fc99e Initial load
duke
parents:
diff changeset
379 };
a61af66fc99e Initial load
duke
parents:
diff changeset
380
a61af66fc99e Initial load
duke
parents:
diff changeset
381 void verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
382 void print ();
a61af66fc99e Initial load
duke
parents:
diff changeset
383
a61af66fc99e Initial load
duke
parents:
diff changeset
384 // unit test stuff
a61af66fc99e Initial load
duke
parents:
diff changeset
385 static void test() {}
a61af66fc99e Initial load
duke
parents:
diff changeset
386
a61af66fc99e Initial load
duke
parents:
diff changeset
387 private:
a61af66fc99e Initial load
duke
parents:
diff changeset
388 friend NativeLoadAddress* nativeLoadAddress_at (address address) {
a61af66fc99e Initial load
duke
parents:
diff changeset
389 NativeLoadAddress* test = (NativeLoadAddress*)(address - instruction_offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
390 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
391 test->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
392 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
393 return test;
a61af66fc99e Initial load
duke
parents:
diff changeset
394 }
a61af66fc99e Initial load
duke
parents:
diff changeset
395 };
a61af66fc99e Initial load
duke
parents:
diff changeset
396
a61af66fc99e Initial load
duke
parents:
diff changeset
397 // jump rel32off
a61af66fc99e Initial load
duke
parents:
diff changeset
398
a61af66fc99e Initial load
duke
parents:
diff changeset
399 class NativeJump: public NativeInstruction {
a61af66fc99e Initial load
duke
parents:
diff changeset
400 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
401 enum Intel_specific_constants {
a61af66fc99e Initial load
duke
parents:
diff changeset
402 instruction_code = 0xe9,
a61af66fc99e Initial load
duke
parents:
diff changeset
403 instruction_size = 5,
a61af66fc99e Initial load
duke
parents:
diff changeset
404 instruction_offset = 0,
a61af66fc99e Initial load
duke
parents:
diff changeset
405 data_offset = 1,
a61af66fc99e Initial load
duke
parents:
diff changeset
406 next_instruction_offset = 5
a61af66fc99e Initial load
duke
parents:
diff changeset
407 };
a61af66fc99e Initial load
duke
parents:
diff changeset
408
a61af66fc99e Initial load
duke
parents:
diff changeset
409 address instruction_address() const { return addr_at(instruction_offset); }
a61af66fc99e Initial load
duke
parents:
diff changeset
410 address next_instruction_address() const { return addr_at(next_instruction_offset); }
a61af66fc99e Initial load
duke
parents:
diff changeset
411 address jump_destination() const {
a61af66fc99e Initial load
duke
parents:
diff changeset
412 address dest = (int_at(data_offset)+next_instruction_address());
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
413 // 32bit used to encode unresolved jmp as jmp -1
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
414 // 64bit can't produce this so it used jump to self.
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
415 // Now 32bit and 64bit use jump to self as the unresolved address
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
416 // which the inline cache code (and relocs) know about
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
417
0
a61af66fc99e Initial load
duke
parents:
diff changeset
418 // return -1 if jump to self
a61af66fc99e Initial load
duke
parents:
diff changeset
419 dest = (dest == (address) this) ? (address) -1 : dest;
a61af66fc99e Initial load
duke
parents:
diff changeset
420 return dest;
a61af66fc99e Initial load
duke
parents:
diff changeset
421 }
a61af66fc99e Initial load
duke
parents:
diff changeset
422
a61af66fc99e Initial load
duke
parents:
diff changeset
423 void set_jump_destination(address dest) {
a61af66fc99e Initial load
duke
parents:
diff changeset
424 intptr_t val = dest - next_instruction_address();
314
3a26e9e4be71 6744422: incorrect handling of -1 in set_jump_destination
never
parents: 304
diff changeset
425 if (dest == (address) -1) {
3a26e9e4be71 6744422: incorrect handling of -1 in set_jump_destination
never
parents: 304
diff changeset
426 val = -5; // jump to self
3a26e9e4be71 6744422: incorrect handling of -1 in set_jump_destination
never
parents: 304
diff changeset
427 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
428 #ifdef AMD64
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
429 assert((labs(val) & 0xFFFFFFFF00000000) == 0 || dest == (address)-1, "must be 32bit offset or -1");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
430 #endif // AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
431 set_int_at(data_offset, (jint)val);
a61af66fc99e Initial load
duke
parents:
diff changeset
432 }
a61af66fc99e Initial load
duke
parents:
diff changeset
433
a61af66fc99e Initial load
duke
parents:
diff changeset
434 // Creation
a61af66fc99e Initial load
duke
parents:
diff changeset
435 inline friend NativeJump* nativeJump_at(address address);
a61af66fc99e Initial load
duke
parents:
diff changeset
436
a61af66fc99e Initial load
duke
parents:
diff changeset
437 void verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
438
a61af66fc99e Initial load
duke
parents:
diff changeset
439 // Unit testing stuff
a61af66fc99e Initial load
duke
parents:
diff changeset
440 static void test() {}
a61af66fc99e Initial load
duke
parents:
diff changeset
441
a61af66fc99e Initial load
duke
parents:
diff changeset
442 // Insertion of native jump instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
443 static void insert(address code_pos, address entry);
a61af66fc99e Initial load
duke
parents:
diff changeset
444 // MT-safe insertion of native jump at verified method entry
a61af66fc99e Initial load
duke
parents:
diff changeset
445 static void check_verified_entry_alignment(address entry, address verified_entry);
a61af66fc99e Initial load
duke
parents:
diff changeset
446 static void patch_verified_entry(address entry, address verified_entry, address dest);
a61af66fc99e Initial load
duke
parents:
diff changeset
447 };
a61af66fc99e Initial load
duke
parents:
diff changeset
448
a61af66fc99e Initial load
duke
parents:
diff changeset
449 inline NativeJump* nativeJump_at(address address) {
a61af66fc99e Initial load
duke
parents:
diff changeset
450 NativeJump* jump = (NativeJump*)(address - NativeJump::instruction_offset);
a61af66fc99e Initial load
duke
parents:
diff changeset
451 #ifdef ASSERT
a61af66fc99e Initial load
duke
parents:
diff changeset
452 jump->verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
453 #endif
a61af66fc99e Initial load
duke
parents:
diff changeset
454 return jump;
a61af66fc99e Initial load
duke
parents:
diff changeset
455 }
a61af66fc99e Initial load
duke
parents:
diff changeset
456
a61af66fc99e Initial load
duke
parents:
diff changeset
457 // Handles all kinds of jump on Intel. Long/far, conditional/unconditional
a61af66fc99e Initial load
duke
parents:
diff changeset
458 class NativeGeneralJump: public NativeInstruction {
a61af66fc99e Initial load
duke
parents:
diff changeset
459 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
460 enum Intel_specific_constants {
a61af66fc99e Initial load
duke
parents:
diff changeset
461 // Constants does not apply, since the lengths and offsets depends on the actual jump
a61af66fc99e Initial load
duke
parents:
diff changeset
462 // used
a61af66fc99e Initial load
duke
parents:
diff changeset
463 // Instruction codes:
a61af66fc99e Initial load
duke
parents:
diff changeset
464 // Unconditional jumps: 0xE9 (rel32off), 0xEB (rel8off)
a61af66fc99e Initial load
duke
parents:
diff changeset
465 // Conditional jumps: 0x0F8x (rel32off), 0x7x (rel8off)
a61af66fc99e Initial load
duke
parents:
diff changeset
466 unconditional_long_jump = 0xe9,
a61af66fc99e Initial load
duke
parents:
diff changeset
467 unconditional_short_jump = 0xeb,
a61af66fc99e Initial load
duke
parents:
diff changeset
468 instruction_size = 5
a61af66fc99e Initial load
duke
parents:
diff changeset
469 };
a61af66fc99e Initial load
duke
parents:
diff changeset
470
a61af66fc99e Initial load
duke
parents:
diff changeset
471 address instruction_address() const { return addr_at(0); }
a61af66fc99e Initial load
duke
parents:
diff changeset
472 address jump_destination() const;
a61af66fc99e Initial load
duke
parents:
diff changeset
473
a61af66fc99e Initial load
duke
parents:
diff changeset
474 // Creation
a61af66fc99e Initial load
duke
parents:
diff changeset
475 inline friend NativeGeneralJump* nativeGeneralJump_at(address address);
a61af66fc99e Initial load
duke
parents:
diff changeset
476
a61af66fc99e Initial load
duke
parents:
diff changeset
477 // Insertion of native general jump instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
478 static void insert_unconditional(address code_pos, address entry);
a61af66fc99e Initial load
duke
parents:
diff changeset
479 static void replace_mt_safe(address instr_addr, address code_buffer);
a61af66fc99e Initial load
duke
parents:
diff changeset
480
a61af66fc99e Initial load
duke
parents:
diff changeset
481 void verify();
a61af66fc99e Initial load
duke
parents:
diff changeset
482 };
a61af66fc99e Initial load
duke
parents:
diff changeset
483
a61af66fc99e Initial load
duke
parents:
diff changeset
484 inline NativeGeneralJump* nativeGeneralJump_at(address address) {
a61af66fc99e Initial load
duke
parents:
diff changeset
485 NativeGeneralJump* jump = (NativeGeneralJump*)(address);
a61af66fc99e Initial load
duke
parents:
diff changeset
486 debug_only(jump->verify();)
a61af66fc99e Initial load
duke
parents:
diff changeset
487 return jump;
a61af66fc99e Initial load
duke
parents:
diff changeset
488 }
a61af66fc99e Initial load
duke
parents:
diff changeset
489
a61af66fc99e Initial load
duke
parents:
diff changeset
490 class NativePopReg : public NativeInstruction {
a61af66fc99e Initial load
duke
parents:
diff changeset
491 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
492 enum Intel_specific_constants {
a61af66fc99e Initial load
duke
parents:
diff changeset
493 instruction_code = 0x58,
a61af66fc99e Initial load
duke
parents:
diff changeset
494 instruction_size = 1,
a61af66fc99e Initial load
duke
parents:
diff changeset
495 instruction_offset = 0,
a61af66fc99e Initial load
duke
parents:
diff changeset
496 data_offset = 1,
a61af66fc99e Initial load
duke
parents:
diff changeset
497 next_instruction_offset = 1
a61af66fc99e Initial load
duke
parents:
diff changeset
498 };
a61af66fc99e Initial load
duke
parents:
diff changeset
499
a61af66fc99e Initial load
duke
parents:
diff changeset
500 // Insert a pop instruction
a61af66fc99e Initial load
duke
parents:
diff changeset
501 static void insert(address code_pos, Register reg);
a61af66fc99e Initial load
duke
parents:
diff changeset
502 };
a61af66fc99e Initial load
duke
parents:
diff changeset
503
a61af66fc99e Initial load
duke
parents:
diff changeset
504
a61af66fc99e Initial load
duke
parents:
diff changeset
505 class NativeIllegalInstruction: public NativeInstruction {
a61af66fc99e Initial load
duke
parents:
diff changeset
506 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
507 enum Intel_specific_constants {
a61af66fc99e Initial load
duke
parents:
diff changeset
508 instruction_code = 0x0B0F, // Real byte order is: 0x0F, 0x0B
a61af66fc99e Initial load
duke
parents:
diff changeset
509 instruction_size = 2,
a61af66fc99e Initial load
duke
parents:
diff changeset
510 instruction_offset = 0,
a61af66fc99e Initial load
duke
parents:
diff changeset
511 next_instruction_offset = 2
a61af66fc99e Initial load
duke
parents:
diff changeset
512 };
a61af66fc99e Initial load
duke
parents:
diff changeset
513
a61af66fc99e Initial load
duke
parents:
diff changeset
514 // Insert illegal opcode as specific address
a61af66fc99e Initial load
duke
parents:
diff changeset
515 static void insert(address code_pos);
a61af66fc99e Initial load
duke
parents:
diff changeset
516 };
a61af66fc99e Initial load
duke
parents:
diff changeset
517
a61af66fc99e Initial load
duke
parents:
diff changeset
518 // return instruction that does not pop values of the stack
a61af66fc99e Initial load
duke
parents:
diff changeset
519 class NativeReturn: public NativeInstruction {
a61af66fc99e Initial load
duke
parents:
diff changeset
520 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
521 enum Intel_specific_constants {
a61af66fc99e Initial load
duke
parents:
diff changeset
522 instruction_code = 0xC3,
a61af66fc99e Initial load
duke
parents:
diff changeset
523 instruction_size = 1,
a61af66fc99e Initial load
duke
parents:
diff changeset
524 instruction_offset = 0,
a61af66fc99e Initial load
duke
parents:
diff changeset
525 next_instruction_offset = 1
a61af66fc99e Initial load
duke
parents:
diff changeset
526 };
a61af66fc99e Initial load
duke
parents:
diff changeset
527 };
a61af66fc99e Initial load
duke
parents:
diff changeset
528
a61af66fc99e Initial load
duke
parents:
diff changeset
529 // return instruction that does pop values of the stack
a61af66fc99e Initial load
duke
parents:
diff changeset
530 class NativeReturnX: public NativeInstruction {
a61af66fc99e Initial load
duke
parents:
diff changeset
531 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
532 enum Intel_specific_constants {
a61af66fc99e Initial load
duke
parents:
diff changeset
533 instruction_code = 0xC2,
a61af66fc99e Initial load
duke
parents:
diff changeset
534 instruction_size = 2,
a61af66fc99e Initial load
duke
parents:
diff changeset
535 instruction_offset = 0,
a61af66fc99e Initial load
duke
parents:
diff changeset
536 next_instruction_offset = 2
a61af66fc99e Initial load
duke
parents:
diff changeset
537 };
a61af66fc99e Initial load
duke
parents:
diff changeset
538 };
a61af66fc99e Initial load
duke
parents:
diff changeset
539
a61af66fc99e Initial load
duke
parents:
diff changeset
540 // Simple test vs memory
a61af66fc99e Initial load
duke
parents:
diff changeset
541 class NativeTstRegMem: public NativeInstruction {
a61af66fc99e Initial load
duke
parents:
diff changeset
542 public:
a61af66fc99e Initial load
duke
parents:
diff changeset
543 enum Intel_specific_constants {
2404
b40d4fa697bf 6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents: 1972
diff changeset
544 instruction_rex_prefix_mask = 0xF0,
b40d4fa697bf 6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents: 1972
diff changeset
545 instruction_rex_prefix = Assembler::REX,
b40d4fa697bf 6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents: 1972
diff changeset
546 instruction_code_memXregl = 0x85,
b40d4fa697bf 6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents: 1972
diff changeset
547 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
548 modrm_reg = 0x00 // rax
0
a61af66fc99e Initial load
duke
parents:
diff changeset
549 };
a61af66fc99e Initial load
duke
parents:
diff changeset
550 };
a61af66fc99e Initial load
duke
parents:
diff changeset
551
a61af66fc99e Initial load
duke
parents:
diff changeset
552 inline bool NativeInstruction::is_illegal() { return (short)int_at(0) == (short)NativeIllegalInstruction::instruction_code; }
a61af66fc99e Initial load
duke
parents:
diff changeset
553 inline bool NativeInstruction::is_call() { return ubyte_at(0) == NativeCall::instruction_code; }
5840
f565e8d4d200 parsing and patching of variable sized NativeCallReg instructions now works properly
Doug Simon <doug.simon@oracle.com>
parents: 5000
diff changeset
554 inline bool NativeInstruction::is_call_reg() { return ubyte_at(0) == NativeCallReg::instruction_code ||
f565e8d4d200 parsing and patching of variable sized NativeCallReg instructions now works properly
Doug Simon <doug.simon@oracle.com>
parents: 5000
diff changeset
555 (ubyte_at(1) == NativeCallReg::instruction_code &&
f565e8d4d200 parsing and patching of variable sized NativeCallReg instructions now works properly
Doug Simon <doug.simon@oracle.com>
parents: 5000
diff changeset
556 (ubyte_at(0) == Assembler::REX || ubyte_at(0) == Assembler::REX_B)); }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
557 inline bool NativeInstruction::is_return() { return ubyte_at(0) == NativeReturn::instruction_code ||
a61af66fc99e Initial load
duke
parents:
diff changeset
558 ubyte_at(0) == NativeReturnX::instruction_code; }
a61af66fc99e Initial load
duke
parents:
diff changeset
559 inline bool NativeInstruction::is_jump() { return ubyte_at(0) == NativeJump::instruction_code ||
a61af66fc99e Initial load
duke
parents:
diff changeset
560 ubyte_at(0) == 0xEB; /* short jump */ }
a61af66fc99e Initial load
duke
parents:
diff changeset
561 inline bool NativeInstruction::is_cond_jump() { return (int_at(0) & 0xF0FF) == 0x800F /* long jump */ ||
a61af66fc99e Initial load
duke
parents:
diff changeset
562 (ubyte_at(0) & 0xF0) == 0x70; /* short jump */ }
a61af66fc99e Initial load
duke
parents:
diff changeset
563 inline bool NativeInstruction::is_safepoint_poll() {
a61af66fc99e Initial load
duke
parents:
diff changeset
564 #ifdef AMD64
2404
b40d4fa697bf 6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents: 1972
diff changeset
565 if (Assembler::is_polling_page_far()) {
b40d4fa697bf 6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents: 1972
diff changeset
566 // 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
567 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
568 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
569 (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
570 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
571 (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
572 return true;
b40d4fa697bf 6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents: 1972
diff changeset
573 } else {
b40d4fa697bf 6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents: 1972
diff changeset
574 return false;
b40d4fa697bf 6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents: 1972
diff changeset
575 }
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
576 } else {
8151
b8f261ba79c6 Minimize diff to plain HotSpot version.
Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
parents: 7943
diff changeset
577 if (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl &&
b8f261ba79c6 Minimize diff to plain HotSpot version.
Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
parents: 7943
diff changeset
578 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
579 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
580 return os::is_poll_address(fault);
b40d4fa697bf 6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents: 1972
diff changeset
581 } else {
b40d4fa697bf 6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents: 1972
diff changeset
582 return false;
b40d4fa697bf 6964776: c2 should ensure the polling page is reachable on 64 bit
iveresov
parents: 1972
diff changeset
583 }
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
584 }
0
a61af66fc99e Initial load
duke
parents:
diff changeset
585 #else
304
dc7f315e41f7 5108146: Merge i486 and amd64 cpu directories
never
parents: 196
diff changeset
586 return ( ubyte_at(0) == NativeMovRegMem::instruction_code_mem2reg ||
0
a61af66fc99e Initial load
duke
parents:
diff changeset
587 ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl ) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
588 (ubyte_at(1)&0xC7) == 0x05 && /* Mod R/M == disp32 */
a61af66fc99e Initial load
duke
parents:
diff changeset
589 (os::is_poll_address((address)int_at(2)));
a61af66fc99e Initial load
duke
parents:
diff changeset
590 #endif // AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
591 }
a61af66fc99e Initial load
duke
parents:
diff changeset
592
a61af66fc99e Initial load
duke
parents:
diff changeset
593 inline bool NativeInstruction::is_mov_literal64() {
a61af66fc99e Initial load
duke
parents:
diff changeset
594 #ifdef AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
595 return ((ubyte_at(0) == Assembler::REX_W || ubyte_at(0) == Assembler::REX_WB) &&
a61af66fc99e Initial load
duke
parents:
diff changeset
596 (ubyte_at(1) & (0xff ^ NativeMovConstReg::register_mask)) == 0xB8);
a61af66fc99e Initial load
duke
parents:
diff changeset
597 #else
a61af66fc99e Initial load
duke
parents:
diff changeset
598 return false;
a61af66fc99e Initial load
duke
parents:
diff changeset
599 #endif // AMD64
a61af66fc99e Initial load
duke
parents:
diff changeset
600 }
1972
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
601
f95d63e2154a 6989984: Use standard include model for Hospot
stefank
parents: 1552
diff changeset
602 #endif // CPU_X86_VM_NATIVEINST_X86_HPP