Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.inline.hpp
32285 views
/*1* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.2* Copyright 2012, 2014 SAP AG. 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 it6* under the terms of the GNU General Public License version 2 only, as7* published by the Free Software Foundation.8*9* This code is distributed in the hope that it will be useful, but WITHOUT10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License12* version 2 for more details (a copy is included in the LICENSE file that13* accompanied this code).14*15* You should have received a copy of the GNU General Public License version16* 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 USA20* or visit www.oracle.com if you need additional information or have any21* questions.22*23*/2425#ifndef CPU_PPC_VM_MACROASSEMBLER_PPC_INLINE_HPP26#define CPU_PPC_VM_MACROASSEMBLER_PPC_INLINE_HPP2728#include "asm/assembler.inline.hpp"29#include "asm/macroAssembler.hpp"30#include "asm/codeBuffer.hpp"31#include "code/codeCache.hpp"3233inline bool MacroAssembler::is_ld_largeoffset(address a) {34const int inst1 = *(int *)a;35const int inst2 = *(int *)(a+4);36return (is_ld(inst1)) ||37(is_addis(inst1) && is_ld(inst2) && inv_ra_field(inst2) == inv_rt_field(inst1));38}3940inline int MacroAssembler::get_ld_largeoffset_offset(address a) {41assert(MacroAssembler::is_ld_largeoffset(a), "must be ld with large offset");4243const int inst1 = *(int *)a;44if (is_ld(inst1)) {45return inv_d1_field(inst1);46} else {47const int inst2 = *(int *)(a+4);48return (inv_d1_field(inst1) << 16) + inv_d1_field(inst2);49}50}5152inline void MacroAssembler::round_to(Register r, int modulus) {53assert(is_power_of_2_long((jlong)modulus), "must be power of 2");54addi(r, r, modulus-1);55clrrdi(r, r, log2_long((jlong)modulus));56}5758// Move register if destination register and target register are different.59inline void MacroAssembler::mr_if_needed(Register rd, Register rs) {60if (rs != rd) mr(rd, rs);61}62inline void MacroAssembler::fmr_if_needed(FloatRegister rd, FloatRegister rs) {63if (rs != rd) fmr(rd, rs);64}65inline void MacroAssembler::endgroup_if_needed(bool needed) {66if (needed) {67endgroup();68}69}7071inline void MacroAssembler::membar(int bits) {72// TODO: use elemental_membar(bits) for Power 8 and disable optimization of acquire-release73// (Matcher::post_membar_release where we use PPC64_ONLY(xop == Op_MemBarRelease ||))74if (bits & StoreLoad) sync(); else lwsync();75}76inline void MacroAssembler::release() { membar(LoadStore | StoreStore); }77inline void MacroAssembler::acquire() { membar(LoadLoad | LoadStore); }78inline void MacroAssembler::fence() { membar(LoadLoad | LoadStore | StoreLoad | StoreStore); }7980// Address of the global TOC.81inline address MacroAssembler::global_toc() {82return CodeCache::low_bound();83}8485// Offset of given address to the global TOC.86inline int MacroAssembler::offset_to_global_toc(const address addr) {87intptr_t offset = (intptr_t)addr - (intptr_t)MacroAssembler::global_toc();88assert(Assembler::is_simm((long)offset, 31) && offset >= 0, "must be in range");89return (int)offset;90}9192// Address of current method's TOC.93inline address MacroAssembler::method_toc() {94return code()->consts()->start();95}9697// Offset of given address to current method's TOC.98inline int MacroAssembler::offset_to_method_toc(address addr) {99intptr_t offset = (intptr_t)addr - (intptr_t)method_toc();100assert(is_simm((long)offset, 31) && offset >= 0, "must be in range");101return (int)offset;102}103104inline bool MacroAssembler::is_calculate_address_from_global_toc_at(address a, address bound) {105const address inst2_addr = a;106const int inst2 = *(int *) a;107108// The relocation points to the second instruction, the addi.109if (!is_addi(inst2)) return false;110111// The addi reads and writes the same register dst.112const int dst = inv_rt_field(inst2);113if (inv_ra_field(inst2) != dst) return false;114115// Now, find the preceding addis which writes to dst.116int inst1 = 0;117address inst1_addr = inst2_addr - BytesPerInstWord;118while (inst1_addr >= bound) {119inst1 = *(int *) inst1_addr;120if (is_addis(inst1) && inv_rt_field(inst1) == dst) {121// stop, found the addis which writes dst122break;123}124inst1_addr -= BytesPerInstWord;125}126127if (!(inst1 == 0 || inv_ra_field(inst1) == 29 /* R29 */)) return false;128return is_addis(inst1);129}130131#ifdef _LP64132// Detect narrow oop constants.133inline bool MacroAssembler::is_set_narrow_oop(address a, address bound) {134const address inst2_addr = a;135const int inst2 = *(int *)a;136// The relocation points to the second instruction, the ori.137if (!is_ori(inst2)) return false;138139// The ori reads and writes the same register dst.140const int dst = inv_rta_field(inst2);141if (inv_rs_field(inst2) != dst) return false;142143// Now, find the preceding addis which writes to dst.144int inst1 = 0;145address inst1_addr = inst2_addr - BytesPerInstWord;146while (inst1_addr >= bound) {147inst1 = *(int *) inst1_addr;148if (is_lis(inst1) && inv_rs_field(inst1) == dst) return true;149inst1_addr -= BytesPerInstWord;150}151return false;152}153#endif154155156inline bool MacroAssembler::is_load_const_at(address a) {157const int* p_inst = (int *) a;158bool b = is_lis(*p_inst++);159if (is_ori(*p_inst)) {160p_inst++;161b = b && is_rldicr(*p_inst++); // TODO: could be made more precise: `sldi'!162b = b && is_oris(*p_inst++);163b = b && is_ori(*p_inst);164} else if (is_lis(*p_inst)) {165p_inst++;166b = b && is_ori(*p_inst++);167b = b && is_ori(*p_inst);168// TODO: could enhance reliability by adding is_insrdi169} else return false;170return b;171}172173inline void MacroAssembler::set_oop_constant(jobject obj, Register d) {174set_oop(constant_oop_address(obj), d);175}176177inline void MacroAssembler::set_oop(AddressLiteral obj_addr, Register d) {178assert(obj_addr.rspec().type() == relocInfo::oop_type, "must be an oop reloc");179load_const(d, obj_addr);180}181182inline void MacroAssembler::pd_patch_instruction(address branch, address target) {183jint& stub_inst = *(jint*) branch;184stub_inst = patched_branch(target - branch, stub_inst, 0);185}186187// Relocation of conditional far branches.188inline bool MacroAssembler::is_bc_far_variant1_at(address instruction_addr) {189// Variant 1, the 1st instruction contains the destination address:190//191// bcxx DEST192// endgroup193//194const int instruction_1 = *(int*)(instruction_addr);195const int instruction_2 = *(int*)(instruction_addr + 4);196return is_bcxx(instruction_1) &&197(inv_bd_field(instruction_1, (intptr_t)instruction_addr) != (intptr_t)(instruction_addr + 2*4)) &&198is_endgroup(instruction_2);199}200201// Relocation of conditional far branches.202inline bool MacroAssembler::is_bc_far_variant2_at(address instruction_addr) {203// Variant 2, the 2nd instruction contains the destination address:204//205// b!cxx SKIP206// bxx DEST207// SKIP:208//209const int instruction_1 = *(int*)(instruction_addr);210const int instruction_2 = *(int*)(instruction_addr + 4);211return is_bcxx(instruction_1) &&212(inv_bd_field(instruction_1, (intptr_t)instruction_addr) == (intptr_t)(instruction_addr + 2*4)) &&213is_bxx(instruction_2);214}215216// Relocation for conditional branches217inline bool MacroAssembler::is_bc_far_variant3_at(address instruction_addr) {218// Variant 3, far cond branch to the next instruction, already patched to nops:219//220// nop221// endgroup222// SKIP/DEST:223//224const int instruction_1 = *(int*)(instruction_addr);225const int instruction_2 = *(int*)(instruction_addr + 4);226return is_nop(instruction_1) &&227is_endgroup(instruction_2);228}229230231// Convenience bc_far versions232inline void MacroAssembler::blt_far(ConditionRegister crx, Label& L, int optimize) { MacroAssembler::bc_far(bcondCRbiIs1, bi0(crx, less), L, optimize); }233inline void MacroAssembler::bgt_far(ConditionRegister crx, Label& L, int optimize) { MacroAssembler::bc_far(bcondCRbiIs1, bi0(crx, greater), L, optimize); }234inline void MacroAssembler::beq_far(ConditionRegister crx, Label& L, int optimize) { MacroAssembler::bc_far(bcondCRbiIs1, bi0(crx, equal), L, optimize); }235inline void MacroAssembler::bso_far(ConditionRegister crx, Label& L, int optimize) { MacroAssembler::bc_far(bcondCRbiIs1, bi0(crx, summary_overflow), L, optimize); }236inline void MacroAssembler::bge_far(ConditionRegister crx, Label& L, int optimize) { MacroAssembler::bc_far(bcondCRbiIs0, bi0(crx, less), L, optimize); }237inline void MacroAssembler::ble_far(ConditionRegister crx, Label& L, int optimize) { MacroAssembler::bc_far(bcondCRbiIs0, bi0(crx, greater), L, optimize); }238inline void MacroAssembler::bne_far(ConditionRegister crx, Label& L, int optimize) { MacroAssembler::bc_far(bcondCRbiIs0, bi0(crx, equal), L, optimize); }239inline void MacroAssembler::bns_far(ConditionRegister crx, Label& L, int optimize) { MacroAssembler::bc_far(bcondCRbiIs0, bi0(crx, summary_overflow), L, optimize); }240241inline address MacroAssembler::call_stub(Register function_entry) {242mtctr(function_entry);243bctrl();244return pc();245}246247inline void MacroAssembler::call_stub_and_return_to(Register function_entry, Register return_pc) {248assert_different_registers(function_entry, return_pc);249mtlr(return_pc);250mtctr(function_entry);251bctr();252}253254// Get the pc where the last emitted call will return to.255inline address MacroAssembler::last_calls_return_pc() {256return _last_calls_return_pc;257}258259// Read from the polling page, its address is already in a register.260inline void MacroAssembler::load_from_polling_page(Register polling_page_address, int offset) {261ld(R0, offset, polling_page_address);262}263264// Trap-instruction-based checks.265266inline void MacroAssembler::trap_null_check(Register a, trap_to_bits cmp) {267assert(TrapBasedNullChecks, "sanity");268tdi(cmp, a/*reg a*/, 0);269}270inline void MacroAssembler::trap_zombie_not_entrant() {271tdi(traptoUnconditional, 0/*reg 0*/, 1);272}273inline void MacroAssembler::trap_should_not_reach_here() {274tdi_unchecked(traptoUnconditional, 0/*reg 0*/, 2);275}276277inline void MacroAssembler::trap_ic_miss_check(Register a, Register b) {278td(traptoGreaterThanUnsigned | traptoLessThanUnsigned, a, b);279}280281// Do an explicit null check if access to a+offset will not raise a SIGSEGV.282// Either issue a trap instruction that raises SIGTRAP, or do a compare that283// branches to exception_entry.284// No support for compressed oops (base page of heap). Does not distinguish285// loads and stores.286inline void MacroAssembler::null_check_throw(Register a, int offset, Register temp_reg,287address exception_entry) {288if (!ImplicitNullChecks || needs_explicit_null_check(offset) || !os::zero_page_read_protected()) {289if (TrapBasedNullChecks) {290assert(UseSIGTRAP, "sanity");291trap_null_check(a);292} else {293Label ok;294cmpdi(CCR0, a, 0);295bne(CCR0, ok);296load_const_optimized(temp_reg, exception_entry);297mtctr(temp_reg);298bctr();299bind(ok);300}301}302}303304inline void MacroAssembler::load_with_trap_null_check(Register d, int si16, Register s1) {305if (!os::zero_page_read_protected()) {306if (TrapBasedNullChecks) {307trap_null_check(s1);308}309}310ld(d, si16, s1);311}312313inline void MacroAssembler::load_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1) {314if (UseCompressedOops) {315lwz(d, offs, s1);316// Attention: no null check here!317decode_heap_oop_not_null(d);318} else {319ld(d, offs, s1);320}321}322323inline void MacroAssembler::store_heap_oop_not_null(Register d, RegisterOrConstant offs, Register s1, Register tmp) {324if (UseCompressedOops) {325Register compressedOop = encode_heap_oop_not_null((tmp != noreg) ? tmp : d, d);326stw(compressedOop, offs, s1);327} else {328std(d, offs, s1);329}330}331332inline void MacroAssembler::load_heap_oop(Register d, RegisterOrConstant offs, Register s1) {333if (UseCompressedOops) {334lwz(d, offs, s1);335decode_heap_oop(d);336} else {337ld(d, offs, s1);338}339}340341inline Register MacroAssembler::encode_heap_oop_not_null(Register d, Register src) {342Register current = (src!=noreg) ? src : d; // Compressed oop is in d if no src provided.343if (Universe::narrow_oop_base() != NULL) {344sub(d, current, R30);345current = d;346}347if (Universe::narrow_oop_shift() != 0) {348srdi(d, current, LogMinObjAlignmentInBytes);349current = d;350}351return current; // Encoded oop is in this register.352}353354inline void MacroAssembler::decode_heap_oop_not_null(Register d) {355if (Universe::narrow_oop_shift() != 0) {356assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong");357sldi(d, d, LogMinObjAlignmentInBytes);358}359if (Universe::narrow_oop_base() != NULL) {360add(d, d, R30);361}362}363364inline void MacroAssembler::decode_heap_oop(Register d) {365Label isNull;366if (Universe::narrow_oop_base() != NULL) {367cmpwi(CCR0, d, 0);368beq(CCR0, isNull);369}370if (Universe::narrow_oop_shift() != 0) {371assert (LogMinObjAlignmentInBytes == Universe::narrow_oop_shift(), "decode alg wrong");372sldi(d, d, LogMinObjAlignmentInBytes);373}374if (Universe::narrow_oop_base() != NULL) {375add(d, d, R30);376}377bind(isNull);378}379380// SIGTRAP-based range checks for arrays.381inline void MacroAssembler::trap_range_check_l(Register a, Register b) {382tw (traptoLessThanUnsigned, a/*reg a*/, b/*reg b*/);383}384inline void MacroAssembler::trap_range_check_l(Register a, int si16) {385twi(traptoLessThanUnsigned, a/*reg a*/, si16);386}387inline void MacroAssembler::trap_range_check_le(Register a, int si16) {388twi(traptoEqual | traptoLessThanUnsigned, a/*reg a*/, si16);389}390inline void MacroAssembler::trap_range_check_g(Register a, int si16) {391twi(traptoGreaterThanUnsigned, a/*reg a*/, si16);392}393inline void MacroAssembler::trap_range_check_ge(Register a, Register b) {394tw (traptoEqual | traptoGreaterThanUnsigned, a/*reg a*/, b/*reg b*/);395}396inline void MacroAssembler::trap_range_check_ge(Register a, int si16) {397twi(traptoEqual | traptoGreaterThanUnsigned, a/*reg a*/, si16);398}399400#if defined(ABI_ELFv2)401inline address MacroAssembler::function_entry() { return pc(); }402#else403inline address MacroAssembler::function_entry() { return emit_fd(); }404#endif405406#endif // CPU_PPC_VM_MACROASSEMBLER_PPC_INLINE_HPP407408409