1 /*
2 * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved.
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 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "assembler_arm.inline.hpp"
27 #include "code/codeCache.hpp"
28 #include "memory/resourceArea.hpp"
29 #include "nativeInst_arm.hpp"
30 #include "oops/compressedOops.inline.hpp"
31 #include "oops/klass.inline.hpp"
32 #include "oops/oop.hpp"
33 #include "runtime/handles.hpp"
34 #include "runtime/sharedRuntime.hpp"
35 #include "runtime/stubRoutines.hpp"
36 #include "utilities/ostream.hpp"
37 #ifdef COMPILER1
38 #include "c1/c1_Runtime1.hpp"
39 #endif
40
verify()41 void RawNativeInstruction::verify() {
42 // make sure code pattern is actually an instruction address
43 address addr = instruction_address();
44 if (addr == NULL || ((intptr_t)addr & (instruction_size - 1)) != 0) {
45 fatal("not an instruction address");
46 }
47 }
48
set_offset(int x)49 void NativeMovRegMem::set_offset(int x) {
50 int scale = get_offset_scale();
51 assert((x & right_n_bits(scale)) == 0, "offset should be aligned");
52 guarantee((x >> 24) == 0, "encoding constraint");
53
54 if (Assembler::is_unsigned_imm_in_range(x, 12, scale)) {
55 set_unsigned_imm(x, 12, get_offset_scale(), 10);
56 return;
57 }
58
59 // If offset is too large to be placed into single ldr/str instruction, we replace
60 // ldr/str Rt, [Rn, #offset]
61 // nop
62 // with
63 // add LR, Rn, #offset_hi
64 // ldr/str Rt, [LR, #offset_lo]
65
66 // Note: Rtemp cannot be used as a temporary register as it could be used
67 // for value being stored (see LIR_Assembler::reg2mem).
68 // Patchable NativeMovRegMem instructions are generated in LIR_Assembler::mem2reg and LIR_Assembler::reg2mem
69 // which do not use LR, so it is free. Also, it does not conflict with LR usages in c1_LIRGenerator_arm.cpp.
70 const int tmp = LR->encoding();
71 const int rn = (encoding() >> 5) & 0x1f;
72
73 NativeInstruction* next = nativeInstruction_at(next_raw_instruction_address());
74 assert(next->is_nop(), "must be");
75
76 next->set_encoding((encoding() & 0xffc0001f) | Assembler::encode_unsigned_imm((x & 0xfff), 12, scale, 10) | tmp << 5);
77 this->set_encoding(0x91400000 | Assembler::encode_unsigned_imm((x >> 12), 12, 0, 10) | rn << 5 | tmp);
78 }
79
_data() const80 intptr_t NativeMovConstReg::_data() const {
81 #ifdef COMPILER2
82 if (is_movz()) {
83 // narrow constant or ic call cached value
84 RawNativeInstruction* ni = next_raw();
85 assert(ni->is_movk(), "movz;movk expected");
86 uint lo16 = (encoding() >> 5) & 0xffff;
87 intptr_t hi = 0;
88 int i = 0;
89 while (ni->is_movk() && i < 3) {
90 uint hi16 = (ni->encoding() >> 5) & 0xffff;
91 int shift = ((ni->encoding() >> 21) & 0x3) << 4;
92 hi |= (intptr_t)hi16 << shift;
93 ni = ni->next_raw();
94 ++i;
95 }
96 return lo16 | hi;
97 }
98 #endif
99 return (intptr_t)(nativeLdrLiteral_at(instruction_address())->literal_value());
100 }
101
raw_set_data(RawNativeInstruction * si,intptr_t x,oop * oop_addr,Metadata ** metadata_addr)102 static void raw_set_data(RawNativeInstruction* si, intptr_t x, oop* oop_addr, Metadata** metadata_addr) {
103 #ifdef COMPILER2
104 if (si->is_movz()) {
105 // narrow constant or ic call cached value
106 uintptr_t nx = 0;
107 int val_size = 32;
108 if (oop_addr != NULL) {
109 narrowOop encoded_oop = CompressedOops::encode(*oop_addr);
110 nx = encoded_oop;
111 } else if (metadata_addr != NULL) {
112 assert((*metadata_addr)->is_klass(), "expected Klass");
113 narrowKlass encoded_k = Klass::encode_klass((Klass *)*metadata_addr);
114 nx = encoded_k;
115 } else {
116 nx = x;
117 val_size = 64;
118 }
119 RawNativeInstruction* ni = si->next_raw();
120 uint lo16 = nx & 0xffff;
121 int shift = 16;
122 int imm16 = 0xffff << 5;
123 si->set_encoding((si->encoding() & ~imm16) | (lo16 << 5));
124 while (shift < val_size) {
125 assert(ni->is_movk(), "movk expected");
126 assert((((ni->encoding() >> 21) & 0x3) << 4) == shift, "wrong shift");
127 uint hi16 = (nx >> shift) & 0xffff;
128 ni->set_encoding((ni->encoding() & ~imm16) | (hi16 << 5));
129 shift += 16;
130 ni = ni->next_raw();
131 }
132 return;
133 }
134 #endif
135
136 assert(si->is_ldr_literal(), "should be");
137
138 if (oop_addr == NULL && metadata_addr == NULL) {
139 // A static ldr_literal without oop_relocation
140 nativeLdrLiteral_at(si->instruction_address())->set_literal_value((address)x);
141 } else {
142 // Oop is loaded from oops section
143 address addr = oop_addr != NULL ? (address)oop_addr : (address)metadata_addr;
144 int offset = addr - si->instruction_address();
145
146 assert((((intptr_t)addr) & 0x7) == 0, "target address should be aligned");
147 assert((offset & 0x3) == 0, "offset should be aligned");
148
149 guarantee(Assembler::is_offset_in_range(offset, 19), "offset is not in range");
150 nativeLdrLiteral_at(si->instruction_address())->set_literal_address(si->instruction_address() + offset);
151 }
152 }
153
set_data(intptr_t x)154 void NativeMovConstReg::set_data(intptr_t x) {
155 // Find and replace the oop corresponding to this instruction in oops section
156 oop* oop_addr = NULL;
157 Metadata** metadata_addr = NULL;
158 CodeBlob* cb = CodeCache::find_blob(instruction_address());
159 {
160 nmethod* nm = cb->as_nmethod_or_null();
161 if (nm != NULL) {
162 RelocIterator iter(nm, instruction_address(), next_raw()->instruction_address());
163 while (iter.next()) {
164 if (iter.type() == relocInfo::oop_type) {
165 oop_addr = iter.oop_reloc()->oop_addr();
166 *oop_addr = cast_to_oop(x);
167 break;
168 } else if (iter.type() == relocInfo::metadata_type) {
169 metadata_addr = iter.metadata_reloc()->metadata_addr();
170 *metadata_addr = (Metadata*)x;
171 break;
172 }
173 }
174 }
175 }
176 raw_set_data(adjust(this), x, oop_addr, metadata_addr);
177 }
178
check_verified_entry_alignment(address entry,address verified_entry)179 void NativeJump::check_verified_entry_alignment(address entry, address verified_entry) {
180 }
181
patch_verified_entry(address entry,address verified_entry,address dest)182 void NativeJump::patch_verified_entry(address entry, address verified_entry, address dest) {
183 assert(dest == SharedRuntime::get_handle_wrong_method_stub(), "should be");
184
185 NativeInstruction* instr = nativeInstruction_at(verified_entry);
186 assert(instr->is_nop() || instr->encoding() == zombie_illegal_instruction, "required for MT-safe patching");
187 instr->set_encoding(zombie_illegal_instruction);
188 }
189
replace_mt_safe(address instr_addr,address code_buffer)190 void NativeGeneralJump::replace_mt_safe(address instr_addr, address code_buffer) {
191 assert (nativeInstruction_at(instr_addr)->is_b(), "MT-safe patching of arbitrary instructions is not allowed");
192 assert (nativeInstruction_at(code_buffer)->is_nop(), "MT-safe patching of arbitrary instructions is not allowed");
193 nativeInstruction_at(instr_addr)->set_encoding(*(int*)code_buffer);
194 }
195
insert_unconditional(address code_pos,address entry)196 void NativeGeneralJump::insert_unconditional(address code_pos, address entry) {
197 // Insert at code_pos unconditional B instruction jumping to entry
198 intx offset = entry - code_pos;
199 assert (Assembler::is_offset_in_range(offset, 26), "offset is out of range");
200
201 NativeInstruction* instr = nativeInstruction_at(code_pos);
202 assert (instr->is_b() || instr->is_nop(), "MT-safe patching of arbitrary instructions is not allowed");
203
204 instr->set_encoding(0x5 << 26 | Assembler::encode_offset(offset, 26, 0));
205 }
206
call_for(address return_address)207 static address call_for(address return_address) {
208 CodeBlob* cb = CodeCache::find_blob(return_address);
209 nmethod* nm = cb->as_nmethod_or_null();
210 if (nm == NULL) {
211 ShouldNotReachHere();
212 return NULL;
213 }
214
215 // Look back 8 instructions (for LIR_Assembler::ic_call and MacroAssembler::patchable_call)
216 address begin = return_address - 8*NativeInstruction::instruction_size;
217 if (begin < nm->code_begin()) {
218 begin = nm->code_begin();
219 }
220 RelocIterator iter(nm, begin, return_address);
221 while (iter.next()) {
222 Relocation* reloc = iter.reloc();
223 if (reloc->is_call()) {
224 address call = reloc->addr();
225 if (nativeInstruction_at(call)->is_call()) {
226 if (nativeCall_at(call)->return_address() == return_address) {
227 return call;
228 }
229 }
230 }
231 }
232
233 return NULL;
234 }
235
is_call_before(address return_address)236 bool NativeCall::is_call_before(address return_address) {
237 return (call_for(return_address) != NULL);
238 }
239
nativeCall_before(address return_address)240 NativeCall* nativeCall_before(address return_address) {
241 assert(NativeCall::is_call_before(return_address), "must be");
242 return nativeCall_at(call_for(return_address));
243 }
244