/* * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2021 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
inlinevoid MacroAssembler::round_to(Register r, int modulus) {
assert(is_power_of_2((jlong)modulus), "must be power of 2");
addi(r, r, modulus-1);
clrrdi(r, r, log2i_exact((jlong)modulus));
}
// Move register if destination register and target register are different. inlinevoid MacroAssembler::mr_if_needed(Register rd, Register rs) { if (rs != rd) mr(rd, rs);
} inlinevoid MacroAssembler::fmr_if_needed(FloatRegister rd, FloatRegister rs) { if (rs != rd) fmr(rd, rs);
} inlinevoid MacroAssembler::endgroup_if_needed(bool needed) { if (needed) {
endgroup();
}
}
inlinevoid MacroAssembler::membar(int bits) { // Comment: Usage of elemental_membar(bits) is not recommended for Power 8. // If elemental_membar(bits) is used, disable optimization of acquire-release // (Matcher::post_membar_release where we use PPC64_ONLY(xop == Op_MemBarRelease ||))! if (bits & StoreLoad) { sync(); } elseif (bits) { lwsync(); }
} inlinevoid MacroAssembler::release() { membar(LoadStore | StoreStore); } inlinevoid MacroAssembler::acquire() { membar(LoadLoad | LoadStore); } inlinevoid MacroAssembler::fence() { membar(LoadLoad | LoadStore | StoreLoad | StoreStore); }
// Address of the global TOC. inline address MacroAssembler::global_toc() { return CodeCache::low_bound();
}
// Offset of given address to the global TOC. inlineint MacroAssembler::offset_to_global_toc(const address addr) {
intptr_t offset = (intptr_t)addr - (intptr_t)MacroAssembler::global_toc();
assert(Assembler::is_uimm((long)offset, 31), "must be in range"); return (int)offset;
}
// Address of current method's TOC. inline address MacroAssembler::method_toc() { return code()->consts()->start();
}
// Offset of given address to current method's TOC. inlineint MacroAssembler::offset_to_method_toc(address addr) {
intptr_t offset = (intptr_t)addr - (intptr_t)method_toc();
assert(Assembler::is_uimm((long)offset, 31), "must be in range"); return (int)offset;
}
#ifdef _LP64 // Detect narrow oop constants. inlinebool MacroAssembler::is_set_narrow_oop(address a, address bound) { const address inst2_addr = a; constint inst2 = *(int *)a; // The relocation points to the second instruction, the ori. if (!is_ori(inst2)) returnfalse;
// The ori reads and writes the same register dst. constint dst = inv_rta_field(inst2); if (inv_rs_field(inst2) != dst) returnfalse;
// Now, find the preceding addis which writes to dst. int inst1 = 0;
address inst1_addr = inst2_addr - BytesPerInstWord; while (inst1_addr >= bound) {
inst1 = *(int *) inst1_addr; if (is_lis(inst1) && inv_rs_field(inst1) == dst) returntrue;
inst1_addr -= BytesPerInstWord;
} returnfalse;
} #endif
inlinebool MacroAssembler::is_load_const_at(address a) { constint* p_inst = (int *) a; bool b = is_lis(*p_inst++); if (is_ori(*p_inst)) {
p_inst++;
b = b && is_rldicr(*p_inst++); // TODO: could be made more precise: `sldi'!
b = b && is_oris(*p_inst++);
b = b && is_ori(*p_inst);
} elseif (is_lis(*p_inst)) {
p_inst++;
b = b && is_ori(*p_inst++);
b = b && is_ori(*p_inst); // TODO: could enhance reliability by adding is_insrdi
} elsereturnfalse; return b;
}
// Relocation for conditional branches inlinebool MacroAssembler::is_bc_far_variant3_at(address instruction_addr) { // Variant 3, far cond branch to the next instruction, already patched to nops: // // nop // endgroup // SKIP/DEST: // constint instruction_1 = *(int*)(instruction_addr); constint instruction_2 = *(int*)(instruction_addr + 4); return is_nop(instruction_1) &&
is_endgroup(instruction_2);
}
// set dst to -1, 0, +1 as follows: if CCR0bi is "greater than", dst is set to 1, // if CCR0bi is "equal", dst is set to 0, otherwise it's set to -1. inlinevoid MacroAssembler::set_cmp3(Register dst) {
assert_different_registers(dst, R0); // P10, prefer using setbc instructions if (VM_Version::has_brw()) {
setbc(R0, CCR0, Assembler::greater); // Set 1 to R0 if CCR0bi is "greater than", otherwise 0
setnbc(dst, CCR0, Assembler::less); // Set -1 to dst if CCR0bi is "less than", otherwise 0
} else {
mfcr(R0); // copy CR register to R0
srwi(dst, R0, 30); // copy the first two bits to dst
srawi(R0, R0, 31); // move the first bit to last position - sign extended
}
orr(dst, dst, R0); // dst | R0 will be -1, 0, or +1
}
// set dst to (treat_unordered_like_less ? -1 : +1) inlinevoid MacroAssembler::set_cmpu3(Register dst, bool treat_unordered_like_less) { if (treat_unordered_like_less) {
cror(CCR0, Assembler::less, CCR0, Assembler::summary_overflow); // treat unordered like less
} else {
cror(CCR0, Assembler::greater, CCR0, Assembler::summary_overflow); // treat unordered like greater
}
set_cmp3(dst);
}
// Get the pc where the last emitted call will return to. inline address MacroAssembler::last_calls_return_pc() { return _last_calls_return_pc;
}
// Read from the polling page, its address is already in a register. inlinevoid MacroAssembler::load_from_polling_page(Register polling_page_address, int offset) { if (USE_POLL_BIT_ONLY) { int encoding = SafepointMechanism::poll_bit();
tdi(traptoGreaterThanUnsigned | traptoEqual, polling_page_address, encoding);
} else {
ld(R0, offset, polling_page_address);
}
}
inlinevoid MacroAssembler::trap_ic_miss_check(Register a, Register b) {
td(traptoGreaterThanUnsigned | traptoLessThanUnsigned, a, b);
}
// Do an explicit null check if access to a+offset will not raise a SIGSEGV. // Either issue a trap instruction that raises SIGTRAP, or do a compare that // branches to exception_entry. // No support for compressed oops (base page of heap). Does not distinguish // loads and stores. inlinevoid MacroAssembler::null_check_throw(Register a, int offset, Register temp_reg,
address exception_entry) { if (!ImplicitNullChecks || needs_explicit_null_check(offset) || !os::zero_page_read_protected()) { if (TrapBasedNullChecks) {
assert(UseSIGTRAP, "sanity");
trap_null_check(a);
} else {
Label ok;
cmpdi(CCR0, a, 0);
bne(CCR0, ok);
load_const_optimized(temp_reg, exception_entry);
mtctr(temp_reg);
bctr();
bind(ok);
}
}
}
inlinevoid MacroAssembler::null_check(Register a, int offset, Label *Lis_null) { if (!ImplicitNullChecks || needs_explicit_null_check(offset) || !os::zero_page_read_protected()) { if (TrapBasedNullChecks) {
assert(UseSIGTRAP, "sanity");
trap_null_check(a);
} elseif (Lis_null){
Label ok;
cmpdi(CCR0, a, 0);
beq(CCR0, *Lis_null);
}
}
}
inlineRegister MacroAssembler::encode_heap_oop_not_null(Register d, Register src) { Register current = (src != noreg) ? src : d; // Oop to be compressed is in d if no src provided. if (CompressedOops::base_overlaps()) {
sub_const_optimized(d, current, CompressedOops::base(), R0);
current = d;
} if (CompressedOops::shift() != 0) {
rldicl(d, current, 64-CompressedOops::shift(), 32); // Clears the upper bits.
current = d;
} return current; // Encoded oop is in this register.
}
Register current = (src != noreg) ? src : d; // Compressed oop is in d if no src provided. if (CompressedOops::shift() != 0) {
sldi(d, current, CompressedOops::shift());
current = d;
} if (CompressedOops::base() != NULL) {
add_const_optimized(d, current, CompressedOops::base(), R0);
current = d;
} return current; // Decoded oop is in this register.
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.