|
1 /* |
|
2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. |
|
3 * Copyright (c) 2016 SAP SE. All rights reserved. |
|
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
5 * |
|
6 * This code is free software; you can redistribute it and/or modify it |
|
7 * under the terms of the GNU General Public License version 2 only, as |
|
8 * published by the Free Software Foundation. |
|
9 * |
|
10 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
13 * version 2 for more details (a copy is included in the LICENSE file that |
|
14 * accompanied this code). |
|
15 * |
|
16 * You should have received a copy of the GNU General Public License version |
|
17 * 2 along with this work; if not, write to the Free Software Foundation, |
|
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
19 * |
|
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
21 * or visit www.oracle.com if you need additional information or have any |
|
22 * questions. |
|
23 * |
|
24 */ |
|
25 |
|
26 #ifndef CPU_S390_VM_MACROASSEMBLER_S390_INLINE_HPP |
|
27 #define CPU_S390_VM_MACROASSEMBLER_S390_INLINE_HPP |
|
28 |
|
29 #include "asm/assembler.inline.hpp" |
|
30 #include "asm/macroAssembler.hpp" |
|
31 #include "asm/codeBuffer.hpp" |
|
32 #include "code/codeCache.hpp" |
|
33 #include "runtime/thread.hpp" |
|
34 |
|
35 // Simplified shift operations for single register operands, constant shift amount. |
|
36 inline void MacroAssembler::lshift(Register r, int places, bool is_DW) { |
|
37 if (is_DW) { |
|
38 z_sllg(r, r, places); |
|
39 } else { |
|
40 z_sll(r, places); |
|
41 } |
|
42 } |
|
43 |
|
44 inline void MacroAssembler::rshift(Register r, int places, bool is_DW) { |
|
45 if (is_DW) { |
|
46 z_srlg(r, r, places); |
|
47 } else { |
|
48 z_srl(r, places); |
|
49 } |
|
50 } |
|
51 |
|
52 // *((int8_t*)(dst)) |= imm8 |
|
53 inline void MacroAssembler::or2mem_8(Address& dst, int64_t imm8) { |
|
54 if (Displacement::is_shortDisp(dst.disp())) { |
|
55 z_oi(dst, imm8); |
|
56 } else { |
|
57 z_oiy(dst, imm8); |
|
58 } |
|
59 } |
|
60 |
|
61 inline int MacroAssembler::store_const(const Address &dest, long imm, Register scratch, bool is_long) { |
|
62 unsigned int lm = is_long ? 8 : 4; |
|
63 unsigned int lc = is_long ? 8 : 4; |
|
64 return store_const(dest, imm, lm, lc, scratch); |
|
65 } |
|
66 |
|
67 // Do not rely on add2reg* emitter. |
|
68 // Depending on CmdLine switches and actual parameter values, |
|
69 // the generated code may alter the condition code, which is counter-intuitive |
|
70 // to the semantics of the "load address" (LA/LAY) instruction. |
|
71 // Generic address loading d <- base(a) + index(a) + disp(a) |
|
72 inline void MacroAssembler::load_address(Register d, const Address &a) { |
|
73 if (Displacement::is_shortDisp(a.disp())) { |
|
74 z_la(d, a.disp(), a.indexOrR0(), a.baseOrR0()); |
|
75 } else if (Displacement::is_validDisp(a.disp())) { |
|
76 z_lay(d, a.disp(), a.indexOrR0(), a.baseOrR0()); |
|
77 } else { |
|
78 guarantee(false, "displacement = " SIZE_FORMAT_HEX ", out of range for LA/LAY", a.disp()); |
|
79 } |
|
80 } |
|
81 |
|
82 inline void MacroAssembler::load_const(Register t, void* x) { |
|
83 load_const(t, (long)x); |
|
84 } |
|
85 |
|
86 // Load a 64 bit constant encoded by a `Label'. |
|
87 // Works for bound as well as unbound labels. For unbound labels, the |
|
88 // code will become patched as soon as the label gets bound. |
|
89 inline void MacroAssembler::load_const(Register t, Label& L) { |
|
90 load_const(t, target(L)); |
|
91 } |
|
92 |
|
93 inline void MacroAssembler::load_const(Register t, const AddressLiteral& a) { |
|
94 assert(t != Z_R0, "R0 not allowed"); |
|
95 // First relocate (we don't change the offset in the RelocationHolder, |
|
96 // just pass a.rspec()), then delegate to load_const(Register, long). |
|
97 relocate(a.rspec()); |
|
98 load_const(t, (long)a.value()); |
|
99 } |
|
100 |
|
101 inline void MacroAssembler::load_const_optimized(Register t, long x) { |
|
102 (void) load_const_optimized_rtn_len(t, x, true); |
|
103 } |
|
104 |
|
105 inline void MacroAssembler::load_const_optimized(Register t, void* a) { |
|
106 load_const_optimized(t, (long)a); |
|
107 } |
|
108 |
|
109 inline void MacroAssembler::load_const_optimized(Register t, Label& L) { |
|
110 load_const_optimized(t, target(L)); |
|
111 } |
|
112 |
|
113 inline void MacroAssembler::load_const_optimized(Register t, const AddressLiteral& a) { |
|
114 assert(t != Z_R0, "R0 not allowed"); |
|
115 assert((relocInfo::relocType)a.rspec().reloc()->type() == relocInfo::none, |
|
116 "cannot relocate optimized load_consts"); |
|
117 load_const_optimized(t, a.value()); |
|
118 } |
|
119 |
|
120 inline void MacroAssembler::set_oop(jobject obj, Register d) { |
|
121 load_const(d, allocate_oop_address(obj)); |
|
122 } |
|
123 |
|
124 inline void MacroAssembler::set_oop_constant(jobject obj, Register d) { |
|
125 load_const(d, constant_oop_address(obj)); |
|
126 } |
|
127 |
|
128 // Adds MetaData constant md to TOC and loads it from there. |
|
129 // md is added to the oop_recorder, but no relocation is added. |
|
130 inline bool MacroAssembler::set_metadata_constant(Metadata* md, Register d) { |
|
131 AddressLiteral a = constant_metadata_address(md); |
|
132 return load_const_from_toc(d, a, d); // Discards the relocation. |
|
133 } |
|
134 |
|
135 |
|
136 inline bool MacroAssembler::is_call_pcrelative_short(unsigned long inst) { |
|
137 return is_equal(inst, BRAS_ZOPC); // off 16, len 16 |
|
138 } |
|
139 |
|
140 inline bool MacroAssembler::is_call_pcrelative_long(unsigned long inst) { |
|
141 return is_equal(inst, BRASL_ZOPC); // off 16, len 32 |
|
142 } |
|
143 |
|
144 inline bool MacroAssembler::is_branch_pcrelative_short(unsigned long inst) { |
|
145 // Branch relative, 16-bit offset. |
|
146 return is_equal(inst, BRC_ZOPC); // off 16, len 16 |
|
147 } |
|
148 |
|
149 inline bool MacroAssembler::is_branch_pcrelative_long(unsigned long inst) { |
|
150 // Branch relative, 32-bit offset. |
|
151 return is_equal(inst, BRCL_ZOPC); // off 16, len 32 |
|
152 } |
|
153 |
|
154 inline bool MacroAssembler::is_compareandbranch_pcrelative_short(unsigned long inst) { |
|
155 // Compare and branch relative, 16-bit offset. |
|
156 return is_equal(inst, CRJ_ZOPC, CMPBRANCH_MASK) || is_equal(inst, CGRJ_ZOPC, CMPBRANCH_MASK) || |
|
157 is_equal(inst, CIJ_ZOPC, CMPBRANCH_MASK) || is_equal(inst, CGIJ_ZOPC, CMPBRANCH_MASK) || |
|
158 is_equal(inst, CLRJ_ZOPC, CMPBRANCH_MASK) || is_equal(inst, CLGRJ_ZOPC, CMPBRANCH_MASK) || |
|
159 is_equal(inst, CLIJ_ZOPC, CMPBRANCH_MASK) || is_equal(inst, CLGIJ_ZOPC, CMPBRANCH_MASK); |
|
160 } |
|
161 |
|
162 inline bool MacroAssembler::is_branchoncount_pcrelative_short(unsigned long inst) { |
|
163 // Branch relative on count, 16-bit offset. |
|
164 return is_equal(inst, BRCT_ZOPC) || is_equal(inst, BRCTG_ZOPC); // off 16, len 16 |
|
165 } |
|
166 |
|
167 inline bool MacroAssembler::is_branchonindex32_pcrelative_short(unsigned long inst) { |
|
168 // Branch relative on index (32bit), 16-bit offset. |
|
169 return is_equal(inst, BRXH_ZOPC) || is_equal(inst, BRXLE_ZOPC); // off 16, len 16 |
|
170 } |
|
171 |
|
172 inline bool MacroAssembler::is_branchonindex64_pcrelative_short(unsigned long inst) { |
|
173 // Branch relative on index (64bit), 16-bit offset. |
|
174 return is_equal(inst, BRXHG_ZOPC) || is_equal(inst, BRXLG_ZOPC); // off 16, len 16 |
|
175 } |
|
176 |
|
177 inline bool MacroAssembler::is_branchonindex_pcrelative_short(unsigned long inst) { |
|
178 return is_branchonindex32_pcrelative_short(inst) || |
|
179 is_branchonindex64_pcrelative_short(inst); |
|
180 } |
|
181 |
|
182 inline bool MacroAssembler::is_branch_pcrelative16(unsigned long inst) { |
|
183 return is_branch_pcrelative_short(inst) || |
|
184 is_compareandbranch_pcrelative_short(inst) || |
|
185 is_branchoncount_pcrelative_short(inst) || |
|
186 is_branchonindex_pcrelative_short(inst); |
|
187 } |
|
188 |
|
189 inline bool MacroAssembler::is_branch_pcrelative32(unsigned long inst) { |
|
190 return is_branch_pcrelative_long(inst); |
|
191 } |
|
192 |
|
193 inline bool MacroAssembler::is_branch_pcrelative(unsigned long inst) { |
|
194 return is_branch_pcrelative16(inst) || |
|
195 is_branch_pcrelative32(inst); |
|
196 } |
|
197 |
|
198 inline bool MacroAssembler::is_load_pcrelative_long(unsigned long inst) { |
|
199 // Load relative, 32-bit offset. |
|
200 return is_equal(inst, LRL_ZOPC, REL_LONG_MASK) || is_equal(inst, LGRL_ZOPC, REL_LONG_MASK); // off 16, len 32 |
|
201 } |
|
202 |
|
203 inline bool MacroAssembler::is_misc_pcrelative_long(unsigned long inst) { |
|
204 // Load address, execute relative, 32-bit offset. |
|
205 return is_equal(inst, LARL_ZOPC, REL_LONG_MASK) || is_equal(inst, EXRL_ZOPC, REL_LONG_MASK); // off 16, len 32 |
|
206 } |
|
207 |
|
208 inline bool MacroAssembler::is_pcrelative_short(unsigned long inst) { |
|
209 return is_branch_pcrelative16(inst) || |
|
210 is_call_pcrelative_short(inst); |
|
211 } |
|
212 |
|
213 inline bool MacroAssembler::is_pcrelative_long(unsigned long inst) { |
|
214 return is_branch_pcrelative32(inst) || |
|
215 is_call_pcrelative_long(inst) || |
|
216 is_load_pcrelative_long(inst) || |
|
217 is_misc_pcrelative_long(inst); |
|
218 } |
|
219 |
|
220 inline bool MacroAssembler::is_load_pcrelative_long(address iLoc) { |
|
221 unsigned long inst; |
|
222 unsigned int len = get_instruction(iLoc, &inst); |
|
223 return (len == 6) && is_load_pcrelative_long(inst); |
|
224 } |
|
225 |
|
226 inline bool MacroAssembler::is_pcrelative_short(address iLoc) { |
|
227 unsigned long inst; |
|
228 unsigned int len = get_instruction(iLoc, &inst); |
|
229 return ((len == 4) || (len == 6)) && is_pcrelative_short(inst); |
|
230 } |
|
231 |
|
232 inline bool MacroAssembler::is_pcrelative_long(address iLoc) { |
|
233 unsigned long inst; |
|
234 unsigned int len = get_instruction(iLoc, &inst); |
|
235 return (len == 6) && is_pcrelative_long(inst); |
|
236 } |
|
237 |
|
238 // Dynamic TOC. Test for any pc-relative instruction. |
|
239 inline bool MacroAssembler::is_pcrelative_instruction(address iloc) { |
|
240 unsigned long inst; |
|
241 get_instruction(iloc, &inst); |
|
242 return is_pcrelative_short(inst) || |
|
243 is_pcrelative_long(inst); |
|
244 } |
|
245 |
|
246 inline bool MacroAssembler::is_load_addr_pcrel(address a) { |
|
247 return is_equal(a, LARL_ZOPC, LARL_MASK); |
|
248 } |
|
249 |
|
250 // Save the return pc in the register that should be stored as the return pc |
|
251 // in the current frame (default is R14). |
|
252 inline void MacroAssembler::save_return_pc(Register pc) { |
|
253 z_stg(pc, _z_abi16(return_pc), Z_SP); |
|
254 } |
|
255 |
|
256 inline void MacroAssembler::restore_return_pc() { |
|
257 z_lg(Z_R14, _z_abi16(return_pc), Z_SP); |
|
258 } |
|
259 |
|
260 // Call a function with given entry. |
|
261 inline address MacroAssembler::call(Register function_entry) { |
|
262 assert(function_entry != Z_R0, "function_entry cannot be Z_R0"); |
|
263 |
|
264 Assembler::z_basr(Z_R14, function_entry); |
|
265 _last_calls_return_pc = pc(); |
|
266 |
|
267 return _last_calls_return_pc; |
|
268 } |
|
269 |
|
270 // Call a C function via a function entry. |
|
271 inline address MacroAssembler::call_c(Register function_entry) { |
|
272 return call(function_entry); |
|
273 } |
|
274 |
|
275 // Call a stub function via a function descriptor, but don't save TOC before |
|
276 // call, don't setup TOC and ENV for call, and don't restore TOC after call |
|
277 inline address MacroAssembler::call_stub(Register function_entry) { |
|
278 return call_c(function_entry); |
|
279 } |
|
280 |
|
281 inline address MacroAssembler::call_stub(address function_entry) { |
|
282 return call_c(function_entry); |
|
283 } |
|
284 |
|
285 // Get the pc where the last emitted call will return to. |
|
286 inline address MacroAssembler::last_calls_return_pc() { |
|
287 return _last_calls_return_pc; |
|
288 } |
|
289 |
|
290 inline void MacroAssembler::set_last_Java_frame(Register last_Java_sp, Register last_Java_pc) { |
|
291 set_last_Java_frame(last_Java_sp, last_Java_pc, true); |
|
292 } |
|
293 |
|
294 inline void MacroAssembler::set_last_Java_frame_static(Register last_Java_sp, Register last_Java_pc) { |
|
295 set_last_Java_frame(last_Java_sp, last_Java_pc, false); |
|
296 } |
|
297 |
|
298 inline void MacroAssembler::reset_last_Java_frame(void) { |
|
299 reset_last_Java_frame(true); |
|
300 } |
|
301 |
|
302 inline void MacroAssembler::reset_last_Java_frame_static(void) { |
|
303 reset_last_Java_frame(false); |
|
304 } |
|
305 |
|
306 inline void MacroAssembler::set_top_ijava_frame_at_SP_as_last_Java_frame(Register sp, Register tmp1) { |
|
307 set_top_ijava_frame_at_SP_as_last_Java_frame(sp, tmp1, true); |
|
308 } |
|
309 |
|
310 inline void MacroAssembler::set_top_ijava_frame_at_SP_as_last_Java_frame_static(Register sp, Register tmp1) { |
|
311 set_top_ijava_frame_at_SP_as_last_Java_frame(sp, tmp1, true); |
|
312 } |
|
313 |
|
314 #endif // CPU_S390_VM_MACROASSEMBLER_S390_INLINE_HPP |