1 /*
2 * Copyright (c) 2008, 2026, 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 #ifndef CPU_ARM_MACROASSEMBLER_ARM_HPP
26 #define CPU_ARM_MACROASSEMBLER_ARM_HPP
27
28 #include "code/relocInfo.hpp"
29 #include "utilities/powerOfTwo.hpp"
30
31 class ciInlineKlass;
32 class SigEntry;
33 class VMRegPair;
34
35 // Introduced AddressLiteral and its subclasses to ease portability from
36 // x86 and avoid relocation issues
37 class AddressLiteral {
38 RelocationHolder _rspec;
39 // Typically we use AddressLiterals we want to use their rval
40 // However in some situations we want the lval (effect address) of the item.
41 // We provide a special factory for making those lvals.
42 bool _is_lval;
43
44 address _target;
45
46 private:
47 static relocInfo::relocType reloc_for_target(address target) {
48 // Used for ExternalAddress or when the type is not specified
49 // Sometimes ExternalAddress is used for values which aren't
50 // exactly addresses, like the card table base.
51 // external_word_type can't be used for values in the first page
52 // so just skip the reloc in that case.
53 return external_word_Relocation::can_be_relocated(target) ? relocInfo::external_word_type : relocInfo::none;
54 }
55
56 void set_rspec(relocInfo::relocType rtype);
57
58 protected:
59 // creation
60 AddressLiteral()
61 : _is_lval(false),
62 _target(nullptr)
63 {}
64
65 public:
66
67 AddressLiteral(address target, relocInfo::relocType rtype) {
68 _is_lval = false;
69 _target = target;
70 set_rspec(rtype);
71 }
72
73 AddressLiteral(address target, RelocationHolder const& rspec)
74 : _rspec(rspec),
75 _is_lval(false),
76 _target(target)
77 {}
78
79 AddressLiteral(address target) {
80 _is_lval = false;
81 _target = target;
82 set_rspec(reloc_for_target(target));
83 }
84
85 AddressLiteral addr() {
86 AddressLiteral ret = *this;
87 ret._is_lval = true;
88 return ret;
89 }
90
91 private:
92
93 address target() { return _target; }
94 bool is_lval() { return _is_lval; }
95
96 relocInfo::relocType reloc() const { return _rspec.type(); }
97 const RelocationHolder& rspec() const { return _rspec; }
98
99 friend class Assembler;
100 friend class MacroAssembler;
101 friend class Address;
102 friend class LIR_Assembler;
103 friend class InlinedAddress;
104 };
105
106 class ExternalAddress: public AddressLiteral {
107
108 public:
109
110 ExternalAddress(address target) : AddressLiteral(target) {}
111
112 };
113
114 class InternalAddress: public AddressLiteral {
115
116 public:
117
118 InternalAddress(address target) : AddressLiteral(target, relocInfo::internal_word_type) {}
119
120 };
121
122 // Inlined constants, for use with ldr_literal / bind_literal
123 // Note: InlinedInteger not supported (use move_slow(Register,int[,cond]))
124 class InlinedLiteral: StackObj {
125 public:
126 Label label; // need to be public for direct access with &
127 InlinedLiteral() {
128 }
129 };
130
131 class InlinedMetadata: public InlinedLiteral {
132 private:
133 Metadata *_data;
134
135 public:
136 InlinedMetadata(Metadata *data): InlinedLiteral() {
137 _data = data;
138 }
139 Metadata *data() { return _data; }
140 };
141
142 // Currently unused
143 // class InlinedOop: public InlinedLiteral {
144 // private:
145 // jobject _jobject;
146 //
147 // public:
148 // InlinedOop(jobject target): InlinedLiteral() {
149 // _jobject = target;
150 // }
151 // jobject jobject() { return _jobject; }
152 // };
153
154 class InlinedAddress: public InlinedLiteral {
155 private:
156 AddressLiteral _literal;
157
158 public:
159
160 InlinedAddress(jobject object): InlinedLiteral(), _literal((address)object, relocInfo::oop_type) {
161 ShouldNotReachHere(); // use mov_oop (or implement InlinedOop)
162 }
163
164 InlinedAddress(Metadata *data): InlinedLiteral(), _literal((address)data, relocInfo::metadata_type) {
165 ShouldNotReachHere(); // use InlinedMetadata or mov_metadata
166 }
167
168 InlinedAddress(address target, const RelocationHolder &rspec): InlinedLiteral(), _literal(target, rspec) {
169 assert(rspec.type() != relocInfo::oop_type, "Do not use InlinedAddress for oops");
170 assert(rspec.type() != relocInfo::metadata_type, "Do not use InlinedAddress for metadatas");
171 }
172
173 InlinedAddress(address target, relocInfo::relocType rtype): InlinedLiteral(), _literal(target, rtype) {
174 assert(rtype != relocInfo::oop_type, "Do not use InlinedAddress for oops");
175 assert(rtype != relocInfo::metadata_type, "Do not use InlinedAddress for metadatas");
176 }
177
178 // Note: default is relocInfo::none for InlinedAddress
179 InlinedAddress(address target): InlinedLiteral(), _literal(target, relocInfo::none) {
180 }
181
182 address target() { return _literal.target(); }
183
184 const RelocationHolder& rspec() const { return _literal.rspec(); }
185 };
186
187 class InlinedString: public InlinedLiteral {
188 private:
189 const char* _msg;
190
191 public:
192 InlinedString(const char* msg): InlinedLiteral() {
193 _msg = msg;
194 }
195 const char* msg() { return _msg; }
196 };
197
198 class MacroAssembler: public Assembler {
199 protected:
200
201 // Support for VM calls
202 //
203
204 // This is the base routine called by the different versions of call_VM_leaf.
205 void call_VM_leaf_helper(address entry_point, int number_of_arguments);
206
207 // This is the base routine called by the different versions of call_VM. The interpreter
208 // may customize this version by overriding it for its purposes (e.g., to save/restore
209 // additional registers when doing a VM call).
210 virtual void call_VM_helper(Register oop_result, address entry_point, int number_of_arguments, bool check_exceptions);
211 public:
212
213 MacroAssembler(CodeBuffer* code) : Assembler(code) {}
214
215 // These routines should emit JVMTI PopFrame and ForceEarlyReturn handling code.
216 // The implementation is only non-empty for the InterpreterMacroAssembler,
217 // as only the interpreter handles PopFrame and ForceEarlyReturn requests.
218 virtual void check_and_handle_popframe() {}
219 virtual void check_and_handle_earlyret() {}
220
221 // By default, we do not need relocation information for non
222 // patchable absolute addresses. However, when needed by some
223 // extensions, ignore_non_patchable_relocations can be modified,
224 // returning false to preserve all relocation information.
225 inline bool ignore_non_patchable_relocations() { return true; }
226
227 void align(int modulus);
228 void align(int modulus, int target);
229
230 // Support for VM calls
231 //
232 // It is imperative that all calls into the VM are handled via the call_VM methods.
233 // They make sure that the stack linkage is setup correctly. call_VM's correspond
234 // to ENTRY/ENTRY_X entry points while call_VM_leaf's correspond to LEAF entry points.
235
236 void call_VM(Register oop_result, address entry_point, bool check_exceptions = true);
237 void call_VM(Register oop_result, address entry_point, Register arg_1, bool check_exceptions = true);
238 void call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, bool check_exceptions = true);
239 void call_VM(Register oop_result, address entry_point, Register arg_1, Register arg_2, Register arg_3, bool check_exceptions = true);
240
241 // The following methods are required by templateTable.cpp,
242 // but not used on ARM.
243 void call_VM(Register oop_result, Register last_java_sp, address entry_point, int number_of_arguments = 0, bool check_exceptions = true);
244 void call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, bool check_exceptions = true);
245 void call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, bool check_exceptions = true);
246 void call_VM(Register oop_result, Register last_java_sp, address entry_point, Register arg_1, Register arg_2, Register arg_3, bool check_exceptions = true);
247
248 // Note: The super_call_VM calls are not used on ARM
249
250 // Raw call, without saving/restoring registers, exception handling, etc.
251 // Mainly used from various stubs.
252 // Note: if 'save_R9_if_scratched' is true, call_VM may on some
253 // platforms save values on the stack. Set it to false (and handle
254 // R9 in the callers) if the top of the stack must not be modified
255 // by call_VM.
256 void call_VM(address entry_point, bool save_R9_if_scratched);
257
258 void call_VM_leaf(address entry_point);
259 void call_VM_leaf(address entry_point, Register arg_1);
260 void call_VM_leaf(address entry_point, Register arg_1, Register arg_2);
261 void call_VM_leaf(address entry_point, Register arg_1, Register arg_2, Register arg_3);
262 void call_VM_leaf(address entry_point, Register arg_1, Register arg_2, Register arg_3, Register arg_4);
263
264 void get_vm_result_oop(Register oop_result, Register tmp);
265 void get_vm_result_metadata(Register metadata_result, Register tmp);
266
267 // Always sets/resets sp, which default to SP if (last_sp == noreg)
268 // Optionally sets/resets fp (use noreg to avoid setting it)
269 // Optionally sets/resets pc depending on save_last_java_pc flag
270 // Note: when saving PC, set_last_Java_frame returns PC's offset in the code section
271 // (for oop_maps offset computation)
272 int set_last_Java_frame(Register last_sp, Register last_fp, bool save_last_java_pc, Register tmp);
273 void reset_last_Java_frame(Register tmp);
274 // status set in set_last_Java_frame for reset_last_Java_frame
275 bool _fp_saved;
276 bool _pc_saved;
277
278 #ifdef PRODUCT
279 #define BLOCK_COMMENT(str) /* nothing */
280 #define STOP(error) __ stop(error)
281 #else
282 #define BLOCK_COMMENT(str) __ block_comment(str)
283 #define STOP(error) __ block_comment(error); __ stop(error)
284 #endif
285
286 void lookup_virtual_method(Register recv_klass,
287 Register vtable_index,
288 Register method_result);
289
290 // Test sub_klass against super_klass, with fast and slow paths.
291
292 // The fast path produces a tri-state answer: yes / no / maybe-slow.
293 // One of the three labels can be null, meaning take the fall-through.
294 // No registers are killed, except temp_regs.
295 void check_klass_subtype_fast_path(Register sub_klass,
296 Register super_klass,
297 Register temp_reg,
298 Register temp_reg2,
299 Label* L_success,
300 Label* L_failure,
301 Label* L_slow_path);
302
303 // The rest of the type check; must be wired to a corresponding fast path.
304 // It does not repeat the fast path logic, so don't use it standalone.
305 // temp_reg3 can be noreg, if no temps are available.
306 // Updates the sub's secondary super cache as necessary.
307 // If set_cond_codes:
308 // - condition codes will be Z on success, NZ on failure.
309 // - temp_reg will be 0 on success, non-0 on failure
310 void check_klass_subtype_slow_path(Register sub_klass,
311 Register super_klass,
312 Register temp_reg,
313 Register temp_reg2,
314 Register temp_reg3, // auto assigned if noreg
315 Label* L_success,
316 Label* L_failure,
317 bool set_cond_codes = false);
318
319 // Simplified, combined version, good for typical uses.
320 // temp_reg3 can be noreg, if no temps are available. It is used only on slow path.
321 // Falls through on failure.
322 void check_klass_subtype(Register sub_klass,
323 Register super_klass,
324 Register temp_reg,
325 Register temp_reg2,
326 Register temp_reg3, // auto assigned on slow path if noreg
327 Label& L_success);
328
329 // Returns address of receiver parameter, using tmp as base register. tmp and params_count can be the same.
330 Address receiver_argument_address(Register params_base, Register params_count, Register tmp);
331
332 void _verify_oop(Register reg, const char* s, const char* file, int line);
333 void _verify_oop_addr(Address addr, const char * s, const char* file, int line);
334
335 // TODO: verify method and klass metadata (compare against vptr?)
336 void _verify_method_ptr(Register reg, const char * msg, const char * file, int line) {}
337 void _verify_klass_ptr(Register reg, const char * msg, const char * file, int line) {}
338
339 #define verify_oop(reg) _verify_oop(reg, "broken oop " #reg, __FILE__, __LINE__)
340 #define verify_oop_addr(addr) _verify_oop_addr(addr, "broken oop ", __FILE__, __LINE__)
341 #define verify_method_ptr(reg) _verify_method_ptr(reg, "broken method " #reg, __FILE__, __LINE__)
342 #define verify_klass_ptr(reg) _verify_klass_ptr(reg, "broken klass " #reg, __FILE__, __LINE__)
343
344 void null_check(Register reg, Register tmp, int offset = -1);
345 inline void null_check(Register reg) { null_check(reg, noreg, -1); } // for C1 lir_null_check
346
347 // Puts address of allocated object into register `obj` and end of allocated object into register `obj_end`.
348 void tlab_allocate(Register obj, Register obj_end, Register tmp1,
349 RegisterOrConstant size_expression, Label& slow_case);
350
351 void zero_memory(Register start, Register end, Register tmp);
352
353 static bool needs_explicit_null_check(intptr_t offset);
354 static bool uses_implicit_null_check(void* address);
355
356 void arm_stack_overflow_check(int frame_size_in_bytes, Register tmp);
357 void arm_stack_overflow_check(Register Rsize, Register tmp);
358
359 void bang_stack_with_offset(int offset) {
360 ShouldNotReachHere();
361 }
362
363 void resolve_jobject(Register value, Register tmp1, Register tmp2);
364 void resolve_global_jobject(Register value, Register tmp1, Register tmp2);
365
366 void nop() {
367 mov(R0, R0);
368 }
369
370 void push(Register rd, AsmCondition cond = al) {
371 assert(rd != SP, "unpredictable instruction");
372 str(rd, Address(SP, -wordSize, pre_indexed), cond);
373 }
374
375 void push(RegisterSet reg_set, AsmCondition cond = al) {
376 assert(!reg_set.contains(SP), "unpredictable instruction");
377 stmdb(SP, reg_set, writeback, cond);
378 }
379
380 void pop(Register rd, AsmCondition cond = al) {
381 assert(rd != SP, "unpredictable instruction");
382 ldr(rd, Address(SP, wordSize, post_indexed), cond);
383 }
384
385 void pop(RegisterSet reg_set, AsmCondition cond = al) {
386 assert(!reg_set.contains(SP), "unpredictable instruction");
387 ldmia(SP, reg_set, writeback, cond);
388 }
389
390 void fpushd(FloatRegister fd, AsmCondition cond = al) {
391 fstmdbd(SP, FloatRegisterSet(fd), writeback, cond);
392 }
393
394 void fpushs(FloatRegister fd, AsmCondition cond = al) {
395 fstmdbs(SP, FloatRegisterSet(fd), writeback, cond);
396 }
397
398 void fpopd(FloatRegister fd, AsmCondition cond = al) {
399 fldmiad(SP, FloatRegisterSet(fd), writeback, cond);
400 }
401
402 void fpops(FloatRegister fd, AsmCondition cond = al) {
403 fldmias(SP, FloatRegisterSet(fd), writeback, cond);
404 }
405
406 void fpush(FloatRegisterSet reg_set) {
407 fstmdbd(SP, reg_set, writeback);
408 }
409
410 void fpop(FloatRegisterSet reg_set) {
411 fldmiad(SP, reg_set, writeback);
412 }
413
414 void fpush_hardfp(FloatRegisterSet reg_set) {
415 #ifndef __SOFTFP__
416 fpush(reg_set);
417 #endif
418 }
419
420 void fpop_hardfp(FloatRegisterSet reg_set) {
421 #ifndef __SOFTFP__
422 fpop(reg_set);
423 #endif
424 }
425
426 // Order access primitives
427 enum Membar_mask_bits {
428 StoreStore = 1 << 3,
429 LoadStore = 1 << 2,
430 StoreLoad = 1 << 1,
431 LoadLoad = 1 << 0
432 };
433
434 void membar(Membar_mask_bits mask,
435 Register tmp,
436 bool preserve_flags = true,
437 Register load_tgt = noreg);
438
439 void breakpoint(AsmCondition cond = al);
440 void stop(const char* msg);
441 // prints msg and continues
442 void warn(const char* msg);
443 void unimplemented(const char* what = "");
444 void should_not_reach_here() { stop("should not reach here"); }
445 static void debug(const char* msg, const intx* registers);
446
447 // Create a walkable frame to help tracking down who called this code.
448 // Returns the frame size in words.
449 int should_not_call_this() {
450 raw_push(FP, LR);
451 should_not_reach_here();
452 flush();
453 return 2; // frame_size_in_words (FP+LR)
454 }
455
456 int save_all_registers();
457 void restore_all_registers();
458 int save_caller_save_registers();
459 void restore_caller_save_registers();
460
461 void add_rc(Register dst, Register arg1, RegisterOrConstant arg2);
462
463 // add_slow and mov_slow are used to manipulate offsets larger than 1024,
464 // these functions are not expected to handle all possible constants,
465 // only those that can really occur during compilation
466 void add_slow(Register rd, Register rn, int c);
467 void sub_slow(Register rd, Register rn, int c);
468
469
470 void mov_slow(Register rd, intptr_t c, AsmCondition cond = al);
471 void mov_slow(Register rd, const char *string);
472 void mov_slow(Register rd, address addr);
473
474 void patchable_mov_oop(Register rd, jobject o, int oop_index) {
475 mov_oop(rd, o, oop_index);
476 }
477 void mov_oop(Register rd, jobject o, int index = 0, AsmCondition cond = al);
478
479 void patchable_mov_metadata(Register rd, Metadata* o, int index) {
480 mov_metadata(rd, o, index);
481 }
482 void mov_metadata(Register rd, Metadata* o, int index = 0);
483
484 void mov_float(FloatRegister fd, jfloat c, AsmCondition cond = al);
485 void mov_double(FloatRegister fd, jdouble c, AsmCondition cond = al);
486
487
488 // Note: this variant of mov_address assumes the address moves with
489 // the code. Do *not* implement it with non-relocated instructions,
490 // unless PC-relative.
491 void mov_relative_address(Register rd, address addr, AsmCondition cond = al) {
492 int offset = addr - pc() - 8;
493 assert((offset & 3) == 0, "bad alignment");
494 if (offset >= 0) {
495 assert(AsmOperand::is_rotated_imm(offset), "addr too far");
496 add(rd, PC, offset, cond);
497 } else {
498 assert(AsmOperand::is_rotated_imm(-offset), "addr too far");
499 sub(rd, PC, -offset, cond);
500 }
501 }
502
503 // Runtime address that may vary from one execution to another.
504 // Warning: do not implement as a PC relative address.
505 void mov_address(Register rd, address addr) {
506 mov_address(rd, addr, RelocationHolder::none);
507 }
508
509 // rspec can be RelocationHolder::none (for ignored symbolic Relocation).
510 // In that case, the address is absolute and the generated code need
511 // not be relocable.
512 void mov_address(Register rd, address addr, RelocationHolder const& rspec) {
513 assert(rspec.type() != relocInfo::runtime_call_type, "do not use mov_address for runtime calls");
514 assert(rspec.type() != relocInfo::static_call_type, "do not use mov_address for relocable calls");
515 if (rspec.type() == relocInfo::none) {
516 // absolute address, relocation not needed
517 mov_slow(rd, (intptr_t)addr);
518 return;
519 }
520 if (VM_Version::supports_movw()) {
521 relocate(rspec);
522 int c = (int)addr;
523 movw(rd, c & 0xffff);
524 if ((unsigned int)c >> 16) {
525 movt(rd, (unsigned int)c >> 16);
526 }
527 return;
528 }
529 Label skip_literal;
530 InlinedAddress addr_literal(addr, rspec);
531 ldr_literal(rd, addr_literal);
532 b(skip_literal);
533 bind_literal(addr_literal);
534 bind(skip_literal);
535 }
536
537 // Note: Do not define mov_address for a Label
538 //
539 // Load from addresses potentially within the code are now handled
540 // InlinedLiteral subclasses (to allow more flexibility on how the
541 // ldr_literal is performed).
542
543 void ldr_literal(Register rd, InlinedAddress& L) {
544 assert(L.rspec().type() != relocInfo::runtime_call_type, "avoid ldr_literal for calls");
545 assert(L.rspec().type() != relocInfo::static_call_type, "avoid ldr_literal for calls");
546 relocate(L.rspec());
547 ldr(rd, Address(PC, target(L.label) - pc() - 8));
548 }
549
550 void ldr_literal(Register rd, InlinedString& L) {
551 const char* msg = L.msg();
552 if (code()->consts()->contains((address)msg)) {
553 // string address moves with the code
554 ldr(rd, Address(PC, ((address)msg) - pc() - 8));
555 return;
556 }
557 // Warning: use external strings with care. They are not relocated
558 // if the code moves. If needed, use code_string to move them
559 // to the consts section.
560 ldr(rd, Address(PC, target(L.label) - pc() - 8));
561 }
562
563 void ldr_literal(Register rd, InlinedMetadata& L) {
564 // relocation done in the bind_literal for metadatas
565 ldr(rd, Address(PC, target(L.label) - pc() - 8));
566 }
567
568 void bind_literal(InlinedAddress& L) {
569 bind(L.label);
570 assert(L.rspec().type() != relocInfo::metadata_type, "Must use InlinedMetadata");
571 // We currently do not use oop 'bound' literals.
572 // If the code evolves and the following assert is triggered,
573 // we need to implement InlinedOop (see InlinedMetadata).
574 assert(L.rspec().type() != relocInfo::oop_type, "Inlined oops not supported");
575 // Note: relocation is handled by relocate calls in ldr_literal
576 AbstractAssembler::emit_address((address)L.target());
577 }
578
579 void bind_literal(InlinedString& L) {
580 const char* msg = L.msg();
581 if (code()->consts()->contains((address)msg)) {
582 // The Label should not be used; avoid binding it
583 // to detect errors.
584 return;
585 }
586 bind(L.label);
587 AbstractAssembler::emit_address((address)L.msg());
588 }
589
590 void bind_literal(InlinedMetadata& L) {
591 bind(L.label);
592 relocate(metadata_Relocation::spec_for_immediate());
593 AbstractAssembler::emit_address((address)L.data());
594 }
595
596 void ldr_label(Register rd, Label& L) {
597 ldr(rd, Address(PC, target(L) - pc() - 8));
598 }
599
600 void resolve_oop_handle(Register result);
601 void load_mirror(Register mirror, Register method, Register tmp);
602
603 void enter() {
604 raw_push(FP, LR);
605 mov(FP, SP);
606 }
607
608 void leave() {
609 mov(SP, FP);
610 raw_pop(FP, LR);
611 }
612
613 #define ARM_INSTR_1(common_mnemonic, arm32_mnemonic, arg_type) \
614 void common_mnemonic(arg_type arg) { \
615 arm32_mnemonic(arg); \
616 }
617
618 #define ARM_INSTR_2(common_mnemonic, arm32_mnemonic, arg1_type, arg2_type) \
619 void common_mnemonic(arg1_type arg1, arg2_type arg2) { \
620 arm32_mnemonic(arg1, arg2); \
621 }
622
623 #define ARM_INSTR_3(common_mnemonic, arm32_mnemonic, arg1_type, arg2_type, arg3_type) \
624 void common_mnemonic(arg1_type arg1, arg2_type arg2, arg3_type arg3) { \
625 arm32_mnemonic(arg1, arg2, arg3); \
626 }
627
628 ARM_INSTR_1(jump, bx, Register)
629 ARM_INSTR_1(call, blx, Register)
630
631 ARM_INSTR_2(cbz_32, cbz, Register, Label&)
632 ARM_INSTR_2(cbnz_32, cbnz, Register, Label&)
633
634 ARM_INSTR_2(ldr_u32, ldr, Register, Address)
635 ARM_INSTR_2(ldr_s32, ldr, Register, Address)
636 ARM_INSTR_2(str_32, str, Register, Address)
637
638 ARM_INSTR_2(mvn_32, mvn, Register, Register)
639 ARM_INSTR_2(cmp_32, cmp, Register, Register)
640 ARM_INSTR_2(neg_32, neg, Register, Register)
641 ARM_INSTR_2(clz_32, clz, Register, Register)
642 ARM_INSTR_2(rbit_32, rbit, Register, Register)
643
644 ARM_INSTR_2(cmp_32, cmp, Register, int)
645 ARM_INSTR_2(cmn_32, cmn, Register, int)
646
647 ARM_INSTR_3(add_32, add, Register, Register, Register)
648 ARM_INSTR_3(sub_32, sub, Register, Register, Register)
649 ARM_INSTR_3(subs_32, subs, Register, Register, Register)
650 ARM_INSTR_3(mul_32, mul, Register, Register, Register)
651 ARM_INSTR_3(and_32, andr, Register, Register, Register)
652 ARM_INSTR_3(orr_32, orr, Register, Register, Register)
653 ARM_INSTR_3(eor_32, eor, Register, Register, Register)
654
655 ARM_INSTR_3(add_32, add, Register, Register, AsmOperand)
656 ARM_INSTR_3(sub_32, sub, Register, Register, AsmOperand)
657 ARM_INSTR_3(orr_32, orr, Register, Register, AsmOperand)
658 ARM_INSTR_3(eor_32, eor, Register, Register, AsmOperand)
659 ARM_INSTR_3(and_32, andr, Register, Register, AsmOperand)
660
661
662 ARM_INSTR_3(add_32, add, Register, Register, int)
663 ARM_INSTR_3(adds_32, adds, Register, Register, int)
664 ARM_INSTR_3(sub_32, sub, Register, Register, int)
665 ARM_INSTR_3(subs_32, subs, Register, Register, int)
666
667 ARM_INSTR_2(tst_32, tst, Register, unsigned int)
668 ARM_INSTR_2(tst_32, tst, Register, AsmOperand)
669
670 ARM_INSTR_3(and_32, andr, Register, Register, uint)
671 ARM_INSTR_3(orr_32, orr, Register, Register, uint)
672 ARM_INSTR_3(eor_32, eor, Register, Register, uint)
673
674 ARM_INSTR_1(cmp_zero_float, fcmpzs, FloatRegister)
675 ARM_INSTR_1(cmp_zero_double, fcmpzd, FloatRegister)
676
677 ARM_INSTR_2(ldr_float, flds, FloatRegister, Address)
678 ARM_INSTR_2(str_float, fsts, FloatRegister, Address)
679 ARM_INSTR_2(mov_float, fcpys, FloatRegister, FloatRegister)
680 ARM_INSTR_2(neg_float, fnegs, FloatRegister, FloatRegister)
681 ARM_INSTR_2(abs_float, fabss, FloatRegister, FloatRegister)
682 ARM_INSTR_2(sqrt_float, fsqrts, FloatRegister, FloatRegister)
683 ARM_INSTR_2(cmp_float, fcmps, FloatRegister, FloatRegister)
684
685 ARM_INSTR_3(add_float, fadds, FloatRegister, FloatRegister, FloatRegister)
686 ARM_INSTR_3(sub_float, fsubs, FloatRegister, FloatRegister, FloatRegister)
687 ARM_INSTR_3(mul_float, fmuls, FloatRegister, FloatRegister, FloatRegister)
688 ARM_INSTR_3(div_float, fdivs, FloatRegister, FloatRegister, FloatRegister)
689
690 ARM_INSTR_2(ldr_double, fldd, FloatRegister, Address)
691 ARM_INSTR_2(str_double, fstd, FloatRegister, Address)
692 ARM_INSTR_2(mov_double, fcpyd, FloatRegister, FloatRegister)
693 ARM_INSTR_2(neg_double, fnegd, FloatRegister, FloatRegister)
694 ARM_INSTR_2(cmp_double, fcmpd, FloatRegister, FloatRegister)
695 ARM_INSTR_2(abs_double, fabsd, FloatRegister, FloatRegister)
696 ARM_INSTR_2(sqrt_double, fsqrtd, FloatRegister, FloatRegister)
697
698 ARM_INSTR_3(add_double, faddd, FloatRegister, FloatRegister, FloatRegister)
699 ARM_INSTR_3(sub_double, fsubd, FloatRegister, FloatRegister, FloatRegister)
700 ARM_INSTR_3(mul_double, fmuld, FloatRegister, FloatRegister, FloatRegister)
701 ARM_INSTR_3(div_double, fdivd, FloatRegister, FloatRegister, FloatRegister)
702
703 ARM_INSTR_2(convert_f2d, fcvtds, FloatRegister, FloatRegister)
704 ARM_INSTR_2(convert_d2f, fcvtsd, FloatRegister, FloatRegister)
705
706 ARM_INSTR_2(mov_fpr2gpr_float, fmrs, Register, FloatRegister)
707
708 #undef ARM_INSTR_1
709 #undef ARM_INSTR_2
710 #undef ARM_INSTR_3
711
712
713
714 void tbz(Register rt, int bit, Label& L) {
715 assert(0 <= bit && bit < BitsPerWord, "bit number is out of range");
716 tst(rt, 1 << bit);
717 b(L, eq);
718 }
719
720 void tbnz(Register rt, int bit, Label& L) {
721 assert(0 <= bit && bit < BitsPerWord, "bit number is out of range");
722 tst(rt, 1 << bit);
723 b(L, ne);
724 }
725
726 void cbz(Register rt, Label& L) {
727 cmp(rt, 0);
728 b(L, eq);
729 }
730
731 void cbz(Register rt, address target) {
732 cmp(rt, 0);
733 b(target, eq);
734 }
735
736 void cbnz(Register rt, Label& L) {
737 cmp(rt, 0);
738 b(L, ne);
739 }
740
741 void ret(Register dst = LR) {
742 bx(dst);
743 }
744
745
746 Register zero_register(Register tmp) {
747 mov(tmp, 0);
748 return tmp;
749 }
750
751 void logical_shift_left(Register dst, Register src, int shift) {
752 mov(dst, AsmOperand(src, lsl, shift));
753 }
754
755 void logical_shift_left_32(Register dst, Register src, int shift) {
756 mov(dst, AsmOperand(src, lsl, shift));
757 }
758
759 void logical_shift_right(Register dst, Register src, int shift) {
760 mov(dst, AsmOperand(src, lsr, shift));
761 }
762
763 void arith_shift_right(Register dst, Register src, int shift) {
764 mov(dst, AsmOperand(src, asr, shift));
765 }
766
767 void asr_32(Register dst, Register src, int shift) {
768 mov(dst, AsmOperand(src, asr, shift));
769 }
770
771 // If <cond> holds, compares r1 and r2. Otherwise, flags are set so that <cond> does not hold.
772 void cond_cmp(Register r1, Register r2, AsmCondition cond) {
773 cmp(r1, r2, cond);
774 }
775
776 // If <cond> holds, compares r and imm. Otherwise, flags are set so that <cond> does not hold.
777 void cond_cmp(Register r, int imm, AsmCondition cond) {
778 cmp(r, imm, cond);
779 }
780
781 void align_reg(Register dst, Register src, int align) {
782 assert (is_power_of_2(align), "should be");
783 bic(dst, src, align-1);
784 }
785
786 void prefetch_read(Address addr) {
787 pld(addr);
788 }
789
790 void raw_push(Register r1, Register r2) {
791 assert(r1->encoding() < r2->encoding(), "should be ordered");
792 push(RegisterSet(r1) | RegisterSet(r2));
793 }
794
795 void raw_pop(Register r1, Register r2) {
796 assert(r1->encoding() < r2->encoding(), "should be ordered");
797 pop(RegisterSet(r1) | RegisterSet(r2));
798 }
799
800 void raw_push(Register r1, Register r2, Register r3) {
801 assert(r1->encoding() < r2->encoding() && r2->encoding() < r3->encoding(), "should be ordered");
802 push(RegisterSet(r1) | RegisterSet(r2) | RegisterSet(r3));
803 }
804
805 void raw_pop(Register r1, Register r2, Register r3) {
806 assert(r1->encoding() < r2->encoding() && r2->encoding() < r3->encoding(), "should be ordered");
807 pop(RegisterSet(r1) | RegisterSet(r2) | RegisterSet(r3));
808 }
809
810 // Restores registers r1 and r2 previously saved by raw_push(r1, r2, ret_addr) and returns by ret_addr. Clobbers LR.
811 void raw_pop_and_ret(Register r1, Register r2) {
812 raw_pop(r1, r2, PC);
813 }
814
815 void indirect_jump(Address addr, Register scratch) {
816 ldr(PC, addr);
817 }
818
819 void indirect_jump(InlinedAddress& literal, Register scratch) {
820 ldr_literal(PC, literal);
821 }
822
823 void neg(Register dst, Register src) {
824 rsb(dst, src, 0);
825 }
826
827 void branch_if_negative_32(Register r, Label& L) {
828 // TODO: This function and branch_if_any_negative_32 could possibly
829 // be revised after the aarch64 removal.
830 // tbnz is not used instead of tst & b.mi because destination may be out of tbnz range (+-32KB)
831 // since these methods are used in LIR_Assembler::emit_arraycopy() to jump to stub entry.
832 tst_32(r, r);
833 b(L, mi);
834 }
835
836 void branch_if_any_negative_32(Register r1, Register r2, Register tmp, Label& L) {
837 orrs(tmp, r1, r2);
838 b(L, mi);
839 }
840
841 void branch_if_any_negative_32(Register r1, Register r2, Register r3, Register tmp, Label& L) {
842 orr_32(tmp, r1, r2);
843 orrs(tmp, tmp, r3);
844 b(L, mi);
845 }
846
847 void add_ptr_scaled_int32(Register dst, Register r1, Register r2, int shift) {
848 add(dst, r1, AsmOperand(r2, lsl, shift));
849 }
850
851 void sub_ptr_scaled_int32(Register dst, Register r1, Register r2, int shift) {
852 sub(dst, r1, AsmOperand(r2, lsl, shift));
853 }
854
855 // C 'boolean' to Java boolean: x == 0 ? 0 : 1
856 void c2bool(Register x);
857
858 // klass oop manipulations if compressed
859
860 void load_klass(Register dst_klass, Register src_oop, AsmCondition cond = al);
861
862 void store_klass(Register src_klass, Register dst_oop);
863
864
865 // oop manipulations
866
867 void load_heap_oop(Register dst, Address src, Register tmp1 = noreg, Register tmp2 = noreg, Register tmp3 = noreg, DecoratorSet decorators = 0);
868 void store_heap_oop(Address obj, Register new_val, Register tmp1 = noreg, Register tmp2 = noreg, Register tmp3 = noreg, DecoratorSet decorators = 0);
869 void store_heap_oop_null(Address obj, Register new_val, Register tmp1 = noreg, Register tmp2 = noreg, Register tmp3 = noreg, DecoratorSet decorators = 0);
870
871 void access_load_at(BasicType type, DecoratorSet decorators, Address src, Register dst, Register tmp1, Register tmp2, Register tmp3);
872 void access_store_at(BasicType type, DecoratorSet decorators, Address obj, Register new_val, Register tmp1, Register tmp2, Register tmp3, bool is_null);
873
874 void ldr_global_ptr(Register reg, address address_of_global);
875 void ldr_global_s32(Register reg, address address_of_global);
876 void ldrb_global(Register reg, address address_of_global);
877
878 // address_placeholder_instruction is invalid instruction and is used
879 // as placeholder in code for address of label
880 enum { address_placeholder_instruction = 0xFFFFFFFF };
881
882 void emit_address(Label& L) {
883 assert(!L.is_bound(), "otherwise address will not be patched");
884 target(L); // creates relocation which will be patched later
885
886 assert ((offset() & (wordSize-1)) == 0, "should be aligned by word size");
887
888 AbstractAssembler::emit_address((address)address_placeholder_instruction);
889 }
890
891 void b(address target, AsmCondition cond = al) {
892 Assembler::b(target, cond); \
893 }
894 void b(Label& L, AsmCondition cond = al) {
895 // internal jumps
896 Assembler::b(target(L), cond);
897 }
898
899 void bl(address target, AsmCondition cond = al) {
900 Assembler::bl(target, cond);
901 }
902 void bl(Label& L, AsmCondition cond = al) {
903 // internal calls
904 Assembler::bl(target(L), cond);
905 }
906
907 void adr(Register dest, Label& L, AsmCondition cond = al) {
908 int delta = target(L) - pc() - 8;
909 if (delta >= 0) {
910 add(dest, PC, delta, cond);
911 } else {
912 sub(dest, PC, -delta, cond);
913 }
914 }
915
916 // Variable-length jump and calls. We now distinguish only the
917 // patchable case from the other cases. Patchable must be
918 // distinguised from relocable. Relocable means the generated code
919 // containing the jump/call may move. Patchable means that the
920 // targeted address may be changed later.
921
922 // Non patchable versions.
923 // - used only for relocInfo::runtime_call_type and relocInfo::none
924 // - may use relative or absolute format (do not use relocInfo::none
925 // if the generated code may move)
926 // - the implementation takes into account switch to THUMB mode if the
927 // destination is a THUMB address
928 // - the implementation supports far targets
929 //
930 // To reduce regression risk, scratch still defaults to noreg on
931 // arm32. This results in patchable instructions. However, if
932 // patching really matters, the call sites should be modified and
933 // use patchable_call or patchable_jump. If patching is not required
934 // and if a register can be cloberred, it should be explicitly
935 // specified to allow future optimizations.
936 void jump(address target,
937 relocInfo::relocType rtype = relocInfo::runtime_call_type,
938 Register scratch = noreg, AsmCondition cond = al);
939
940 void call(address target,
941 RelocationHolder rspec, AsmCondition cond = al);
942
943 void call(address target,
944 relocInfo::relocType rtype = relocInfo::runtime_call_type,
945 AsmCondition cond = al) {
946 call(target, Relocation::spec_simple(rtype), cond);
947 }
948
949 void jump(AddressLiteral dest) {
950 jump(dest.target(), dest.reloc());
951 }
952 void jump(address dest, relocInfo::relocType rtype, AsmCondition cond) {
953 jump(dest, rtype, Rtemp, cond);
954 }
955
956 void call(AddressLiteral dest) {
957 call(dest.target(), dest.reloc());
958 }
959
960 // Patchable version:
961 // - set_destination can be used to atomically change the target
962 //
963 // The targets for patchable_jump and patchable_call must be in the
964 // code cache.
965 // [ including possible extensions of the code cache, like AOT code ]
966 //
967 // To reduce regression risk, scratch still defaults to noreg on
968 // arm32. If a register can be cloberred, it should be explicitly
969 // specified to allow future optimizations.
970 void patchable_jump(address target,
971 relocInfo::relocType rtype = relocInfo::runtime_call_type,
972 Register scratch = noreg, AsmCondition cond = al
973 );
974
975 // patchable_call may scratch Rtemp
976 int patchable_call(address target,
977 RelocationHolder const& rspec,
978 bool c2 = false);
979
980 int patchable_call(address target,
981 relocInfo::relocType rtype,
982 bool c2 = false) {
983 return patchable_call(target, Relocation::spec_simple(rtype), c2);
984 }
985
986
987 static bool _reachable_from_cache(address target);
988 static bool _cache_fully_reachable();
989 bool cache_fully_reachable();
990 bool reachable_from_cache(address target);
991
992 void zero_extend(Register rd, Register rn, int bits);
993 void sign_extend(Register rd, Register rn, int bits);
994
995 inline void zap_high_non_significant_bits(Register r) {
996 }
997
998 void cmpoop(Register obj1, Register obj2);
999
1000 void long_move(Register rd_lo, Register rd_hi,
1001 Register rn_lo, Register rn_hi,
1002 AsmCondition cond = al);
1003 void long_shift(Register rd_lo, Register rd_hi,
1004 Register rn_lo, Register rn_hi,
1005 AsmShift shift, Register count);
1006 void long_shift(Register rd_lo, Register rd_hi,
1007 Register rn_lo, Register rn_hi,
1008 AsmShift shift, int count);
1009
1010 void atomic_cas(Register tmpreg1, Register tmpreg2, Register oldval, Register newval, Register base, int offset);
1011 void atomic_cas_bool(Register oldval, Register newval, Register base, int offset, Register tmpreg);
1012 void atomic_cas64(Register temp_lo, Register temp_hi, Register temp_result, Register oldval_lo, Register oldval_hi, Register newval_lo, Register newval_hi, Register base, int offset);
1013
1014 void cas_for_lock_acquire(Register oldval, Register newval, Register base, Register tmp, Label &slow_case, bool allow_fallthrough_on_failure = false, bool one_shot = false);
1015 void cas_for_lock_release(Register oldval, Register newval, Register base, Register tmp, Label &slow_case, bool allow_fallthrough_on_failure = false, bool one_shot = false);
1016
1017 // Attempt to fast-lock an object
1018 // Registers:
1019 // - obj: the object to be locked
1020 // - t1, t2, t3: temp registers. If corresponding bit in savemask is set, they get saved, otherwise blown.
1021 // Result:
1022 // - Success: fallthrough
1023 // - Error: break to slow, Z cleared.
1024 void fast_lock(Register obj, Register t1, Register t2, Register t3, unsigned savemask, Label& slow);
1025
1026 // Attempt to fast-unlock an object
1027 // Registers:
1028 // - obj: the object to be unlocked
1029 // - t1, t2, t3: temp registers. If corresponding bit in savemask is set, they get saved, otherwise blown.
1030 // Result:
1031 // - Success: fallthrough
1032 // - Error: break to slow, Z cleared.
1033 void fast_unlock(Register obj, Register t1, Register t2, Register t3, unsigned savemask, Label& slow);
1034
1035 #ifndef PRODUCT
1036 // Preserves flags and all registers.
1037 // On SMP the updated value might not be visible to external observers without a synchronization barrier
1038 void cond_atomic_inc32(AsmCondition cond, int* counter_addr);
1039 #endif // !PRODUCT
1040
1041 // unconditional non-atomic increment
1042 void inc_counter(address counter_addr, Register tmpreg1, Register tmpreg2);
1043 void inc_counter(uint* counter_addr, Register tmpreg1, Register tmpreg2) {
1044 inc_counter((address) counter_addr, tmpreg1, tmpreg2);
1045 }
1046
1047 void pd_patch_instruction(address branch, address target, const char* file, int line);
1048
1049 // Loading and storing values by size and signed-ness;
1050 // size must not exceed wordSize (i.e. 8-byte values are not supported on 32-bit ARM);
1051 // each of these calls generates exactly one load or store instruction,
1052 // so src can be pre- or post-indexed address.
1053 // 32-bit ARM variants also support conditional execution
1054 void load_sized_value(Register dst, Address src, size_t size_in_bytes, bool is_signed, AsmCondition cond = al);
1055 void store_sized_value(Register src, Address dst, size_t size_in_bytes, AsmCondition cond = al);
1056
1057 void lookup_interface_method(Register recv_klass,
1058 Register intf_klass,
1059 RegisterOrConstant itable_index,
1060 Register method_result,
1061 Register temp_reg1,
1062 Register temp_reg2,
1063 Label& L_no_such_interface);
1064
1065
1066 void floating_cmp(Register dst);
1067
1068 // improved x86 portability (minimizing source code changes)
1069
1070 void ldr_literal(Register rd, AddressLiteral addr) {
1071 relocate(addr.rspec());
1072 ldr(rd, Address(PC, addr.target() - pc() - 8));
1073 }
1074
1075 void lea(Register Rd, AddressLiteral addr) {
1076 // Never dereferenced, as on x86 (lval status ignored)
1077 mov_address(Rd, addr.target(), addr.rspec());
1078 }
1079
1080 void restore_default_fp_mode();
1081
1082 void safepoint_poll(Register tmp1, Label& slow_path);
1083 void get_polling_page(Register dest);
1084 void read_polling_page(Register dest, relocInfo::relocType rtype);
1085
1086 static int ic_check_size();
1087 int ic_check(int end_alignment);
1088
1089 // Inline type specific methods
1090 #include "asm/macroAssembler_common.hpp"
1091
1092 void remove_frame(int initial_framesize);
1093 };
1094
1095
1096 // The purpose of this class is to build several code fragments of the same size
1097 // in order to allow fast table branch.
1098
1099 class FixedSizeCodeBlock {
1100 public:
1101 FixedSizeCodeBlock(MacroAssembler* masm, int size_in_instrs, bool enabled);
1102 ~FixedSizeCodeBlock();
1103
1104 private:
1105 MacroAssembler* _masm;
1106 address _start;
1107 int _size_in_instrs;
1108 bool _enabled;
1109 };
1110
1111
1112 #endif // CPU_ARM_MACROASSEMBLER_ARM_HPP