Path: blob/master/src/hotspot/cpu/arm/c1_LIRAssembler_arm.cpp
64440 views
/*1* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "asm/macroAssembler.inline.hpp"26#include "c1/c1_Compilation.hpp"27#include "c1/c1_LIRAssembler.hpp"28#include "c1/c1_MacroAssembler.hpp"29#include "c1/c1_Runtime1.hpp"30#include "c1/c1_ValueStack.hpp"31#include "ci/ciArrayKlass.hpp"32#include "ci/ciInstance.hpp"33#include "gc/shared/collectedHeap.hpp"34#include "memory/universe.hpp"35#include "nativeInst_arm.hpp"36#include "oops/objArrayKlass.hpp"37#include "runtime/frame.inline.hpp"38#include "runtime/sharedRuntime.hpp"39#include "runtime/stubRoutines.hpp"40#include "utilities/powerOfTwo.hpp"41#include "vmreg_arm.inline.hpp"4243#define __ _masm->4445// Note: Rtemp usage is this file should not impact C2 and should be46// correct as long as it is not implicitly used in lower layers (the47// arm [macro]assembler) and used with care in the other C1 specific48// files.4950bool LIR_Assembler::is_small_constant(LIR_Opr opr) {51ShouldNotCallThis(); // Not used on ARM52return false;53}545556LIR_Opr LIR_Assembler::receiverOpr() {57// The first register in Java calling conventions58return FrameMap::R0_oop_opr;59}6061LIR_Opr LIR_Assembler::osrBufferPointer() {62return FrameMap::as_pointer_opr(R0);63}6465#ifndef PRODUCT66void LIR_Assembler::verify_reserved_argument_area_size(int args_count) {67assert(args_count * wordSize <= frame_map()->reserved_argument_area_size(), "not enough space for arguments");68}69#endif // !PRODUCT7071void LIR_Assembler::store_parameter(jint c, int offset_from_sp_in_words) {72assert(offset_from_sp_in_words >= 0, "invalid offset from sp");73int offset_from_sp_in_bytes = offset_from_sp_in_words * BytesPerWord;74assert(offset_from_sp_in_bytes < frame_map()->reserved_argument_area_size(), "not enough space");75__ mov_slow(Rtemp, c);76__ str(Rtemp, Address(SP, offset_from_sp_in_bytes));77}7879void LIR_Assembler::store_parameter(Metadata* m, int offset_from_sp_in_words) {80assert(offset_from_sp_in_words >= 0, "invalid offset from sp");81int offset_from_sp_in_bytes = offset_from_sp_in_words * BytesPerWord;82assert(offset_from_sp_in_bytes < frame_map()->reserved_argument_area_size(), "not enough space");83__ mov_metadata(Rtemp, m);84__ str(Rtemp, Address(SP, offset_from_sp_in_bytes));85}8687//--------------fpu register translations-----------------------888990void LIR_Assembler::breakpoint() {91__ breakpoint();92}9394void LIR_Assembler::push(LIR_Opr opr) {95Unimplemented();96}9798void LIR_Assembler::pop(LIR_Opr opr) {99Unimplemented();100}101102//-------------------------------------------103Address LIR_Assembler::as_Address(LIR_Address* addr) {104Register base = addr->base()->as_pointer_register();105106107if (addr->index()->is_illegal() || addr->index()->is_constant()) {108int offset = addr->disp();109if (addr->index()->is_constant()) {110offset += addr->index()->as_constant_ptr()->as_jint() << addr->scale();111}112113if ((offset <= -4096) || (offset >= 4096)) {114BAILOUT_("offset not in range", Address(base));115}116117return Address(base, offset);118119} else {120assert(addr->disp() == 0, "can't have both");121int scale = addr->scale();122123assert(addr->index()->is_single_cpu(), "should be");124return scale >= 0 ? Address(base, addr->index()->as_register(), lsl, scale) :125Address(base, addr->index()->as_register(), lsr, -scale);126}127}128129Address LIR_Assembler::as_Address_hi(LIR_Address* addr) {130Address base = as_Address(addr);131assert(base.index() == noreg, "must be");132if (base.disp() + BytesPerWord >= 4096) { BAILOUT_("offset not in range", Address(base.base(),0)); }133return Address(base.base(), base.disp() + BytesPerWord);134}135136Address LIR_Assembler::as_Address_lo(LIR_Address* addr) {137return as_Address(addr);138}139140141void LIR_Assembler::osr_entry() {142offsets()->set_value(CodeOffsets::OSR_Entry, code_offset());143BlockBegin* osr_entry = compilation()->hir()->osr_entry();144ValueStack* entry_state = osr_entry->end()->state();145int number_of_locks = entry_state->locks_size();146147__ build_frame(initial_frame_size_in_bytes(), bang_size_in_bytes());148Register OSR_buf = osrBufferPointer()->as_pointer_register();149150assert(frame::interpreter_frame_monitor_size() == BasicObjectLock::size(), "adjust code below");151int monitor_offset = (method()->max_locals() + 2 * (number_of_locks - 1)) * BytesPerWord;152for (int i = 0; i < number_of_locks; i++) {153int slot_offset = monitor_offset - (i * 2 * BytesPerWord);154__ ldr(R1, Address(OSR_buf, slot_offset + 0*BytesPerWord));155__ ldr(R2, Address(OSR_buf, slot_offset + 1*BytesPerWord));156__ str(R1, frame_map()->address_for_monitor_lock(i));157__ str(R2, frame_map()->address_for_monitor_object(i));158}159}160161162int LIR_Assembler::check_icache() {163Register receiver = LIR_Assembler::receiverOpr()->as_register();164int offset = __ offset();165__ inline_cache_check(receiver, Ricklass);166return offset;167}168169void LIR_Assembler::clinit_barrier(ciMethod* method) {170ShouldNotReachHere(); // not implemented171}172173void LIR_Assembler::jobject2reg_with_patching(Register reg, CodeEmitInfo* info) {174jobject o = (jobject)Universe::non_oop_word();175int index = __ oop_recorder()->allocate_oop_index(o);176177PatchingStub* patch = new PatchingStub(_masm, patching_id(info), index);178179__ patchable_mov_oop(reg, o, index);180patching_epilog(patch, lir_patch_normal, reg, info);181}182183184void LIR_Assembler::klass2reg_with_patching(Register reg, CodeEmitInfo* info) {185Metadata* o = (Metadata*)Universe::non_oop_word();186int index = __ oop_recorder()->allocate_metadata_index(o);187PatchingStub* patch = new PatchingStub(_masm, PatchingStub::load_klass_id, index);188189__ patchable_mov_metadata(reg, o, index);190patching_epilog(patch, lir_patch_normal, reg, info);191}192193194int LIR_Assembler::initial_frame_size_in_bytes() const {195// Subtracts two words to account for return address and link196return frame_map()->framesize()*VMRegImpl::stack_slot_size - 2*wordSize;197}198199200int LIR_Assembler::emit_exception_handler() {201// TODO: ARM202__ nop(); // See comments in other ports203204address handler_base = __ start_a_stub(exception_handler_size());205if (handler_base == NULL) {206bailout("exception handler overflow");207return -1;208}209210int offset = code_offset();211212// check that there is really an exception213__ verify_not_null_oop(Rexception_obj);214215__ call(Runtime1::entry_for(Runtime1::handle_exception_from_callee_id), relocInfo::runtime_call_type);216__ should_not_reach_here();217218assert(code_offset() - offset <= exception_handler_size(), "overflow");219__ end_a_stub();220221return offset;222}223224// Emit the code to remove the frame from the stack in the exception225// unwind path.226int LIR_Assembler::emit_unwind_handler() {227#ifndef PRODUCT228if (CommentedAssembly) {229_masm->block_comment("Unwind handler");230}231#endif232233int offset = code_offset();234235// Fetch the exception from TLS and clear out exception related thread state236Register zero = __ zero_register(Rtemp);237__ ldr(Rexception_obj, Address(Rthread, JavaThread::exception_oop_offset()));238__ str(zero, Address(Rthread, JavaThread::exception_oop_offset()));239__ str(zero, Address(Rthread, JavaThread::exception_pc_offset()));240241__ bind(_unwind_handler_entry);242__ verify_not_null_oop(Rexception_obj);243244// Preform needed unlocking245MonitorExitStub* stub = NULL;246if (method()->is_synchronized()) {247monitor_address(0, FrameMap::R0_opr);248stub = new MonitorExitStub(FrameMap::R0_opr, true, 0);249__ unlock_object(R2, R1, R0, Rtemp, *stub->entry());250__ bind(*stub->continuation());251}252253// remove the activation and dispatch to the unwind handler254__ remove_frame(initial_frame_size_in_bytes()); // restores FP and LR255__ jump(Runtime1::entry_for(Runtime1::unwind_exception_id), relocInfo::runtime_call_type, Rtemp);256257// Emit the slow path assembly258if (stub != NULL) {259stub->emit_code(this);260}261262return offset;263}264265266int LIR_Assembler::emit_deopt_handler() {267address handler_base = __ start_a_stub(deopt_handler_size());268if (handler_base == NULL) {269bailout("deopt handler overflow");270return -1;271}272273int offset = code_offset();274275__ mov_relative_address(LR, __ pc());276__ push(LR); // stub expects LR to be saved277__ jump(SharedRuntime::deopt_blob()->unpack(), relocInfo::runtime_call_type, noreg);278279assert(code_offset() - offset <= deopt_handler_size(), "overflow");280__ end_a_stub();281282return offset;283}284285286void LIR_Assembler::return_op(LIR_Opr result, C1SafepointPollStub* code_stub) {287// Pop the frame before safepoint polling288__ remove_frame(initial_frame_size_in_bytes());289__ read_polling_page(Rtemp, relocInfo::poll_return_type);290__ ret();291}292293int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) {294295int offset = __ offset();296__ get_polling_page(Rtemp);297__ relocate(relocInfo::poll_type);298add_debug_info_for_branch(info); // help pc_desc_at to find correct scope for current PC299__ ldr(Rtemp, Address(Rtemp));300301return offset;302}303304305void LIR_Assembler::move_regs(Register from_reg, Register to_reg) {306if (from_reg != to_reg) {307__ mov(to_reg, from_reg);308}309}310311void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_code, CodeEmitInfo* info) {312assert(src->is_constant() && dest->is_register(), "must be");313LIR_Const* c = src->as_constant_ptr();314315switch (c->type()) {316case T_ADDRESS:317case T_INT:318assert(patch_code == lir_patch_none, "no patching handled here");319__ mov_slow(dest->as_register(), c->as_jint());320break;321322case T_LONG:323assert(patch_code == lir_patch_none, "no patching handled here");324__ mov_slow(dest->as_register_lo(), c->as_jint_lo());325__ mov_slow(dest->as_register_hi(), c->as_jint_hi());326break;327328case T_OBJECT:329if (patch_code == lir_patch_none) {330__ mov_oop(dest->as_register(), c->as_jobject());331} else {332jobject2reg_with_patching(dest->as_register(), info);333}334break;335336case T_METADATA:337if (patch_code == lir_patch_none) {338__ mov_metadata(dest->as_register(), c->as_metadata());339} else {340klass2reg_with_patching(dest->as_register(), info);341}342break;343344case T_FLOAT:345if (dest->is_single_fpu()) {346__ mov_float(dest->as_float_reg(), c->as_jfloat());347} else {348// Simple getters can return float constant directly into r0349__ mov_slow(dest->as_register(), c->as_jint_bits());350}351break;352353case T_DOUBLE:354if (dest->is_double_fpu()) {355__ mov_double(dest->as_double_reg(), c->as_jdouble());356} else {357// Simple getters can return double constant directly into r1r0358__ mov_slow(dest->as_register_lo(), c->as_jint_lo_bits());359__ mov_slow(dest->as_register_hi(), c->as_jint_hi_bits());360}361break;362363default:364ShouldNotReachHere();365}366}367368void LIR_Assembler::const2stack(LIR_Opr src, LIR_Opr dest) {369assert(src->is_constant(), "must be");370assert(dest->is_stack(), "must be");371LIR_Const* c = src->as_constant_ptr();372373switch (c->type()) {374case T_INT: // fall through375case T_FLOAT:376__ mov_slow(Rtemp, c->as_jint_bits());377__ str_32(Rtemp, frame_map()->address_for_slot(dest->single_stack_ix()));378break;379380case T_ADDRESS:381__ mov_slow(Rtemp, c->as_jint());382__ str(Rtemp, frame_map()->address_for_slot(dest->single_stack_ix()));383break;384385case T_OBJECT:386__ mov_oop(Rtemp, c->as_jobject());387__ str(Rtemp, frame_map()->address_for_slot(dest->single_stack_ix()));388break;389390case T_LONG: // fall through391case T_DOUBLE:392__ mov_slow(Rtemp, c->as_jint_lo_bits());393__ str(Rtemp, frame_map()->address_for_slot(dest->double_stack_ix(), lo_word_offset_in_bytes));394if (c->as_jint_hi_bits() != c->as_jint_lo_bits()) {395__ mov_slow(Rtemp, c->as_jint_hi_bits());396}397__ str(Rtemp, frame_map()->address_for_slot(dest->double_stack_ix(), hi_word_offset_in_bytes));398break;399400default:401ShouldNotReachHere();402}403}404405void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type,406CodeEmitInfo* info, bool wide) {407assert((src->as_constant_ptr()->type() == T_OBJECT && src->as_constant_ptr()->as_jobject() == NULL),"cannot handle otherwise");408__ mov(Rtemp, 0);409410int null_check_offset = code_offset();411__ str(Rtemp, as_Address(dest->as_address_ptr()));412413if (info != NULL) {414assert(false, "arm32 didn't support this before, investigate if bug");415add_debug_info_for_null_check(null_check_offset, info);416}417}418419void LIR_Assembler::reg2reg(LIR_Opr src, LIR_Opr dest) {420assert(src->is_register() && dest->is_register(), "must be");421422if (src->is_single_cpu()) {423if (dest->is_single_cpu()) {424move_regs(src->as_register(), dest->as_register());425} else if (dest->is_single_fpu()) {426__ fmsr(dest->as_float_reg(), src->as_register());427} else {428ShouldNotReachHere();429}430} else if (src->is_double_cpu()) {431if (dest->is_double_cpu()) {432__ long_move(dest->as_register_lo(), dest->as_register_hi(), src->as_register_lo(), src->as_register_hi());433} else {434__ fmdrr(dest->as_double_reg(), src->as_register_lo(), src->as_register_hi());435}436} else if (src->is_single_fpu()) {437if (dest->is_single_fpu()) {438__ mov_float(dest->as_float_reg(), src->as_float_reg());439} else if (dest->is_single_cpu()) {440__ mov_fpr2gpr_float(dest->as_register(), src->as_float_reg());441} else {442ShouldNotReachHere();443}444} else if (src->is_double_fpu()) {445if (dest->is_double_fpu()) {446__ mov_double(dest->as_double_reg(), src->as_double_reg());447} else if (dest->is_double_cpu()) {448__ fmrrd(dest->as_register_lo(), dest->as_register_hi(), src->as_double_reg());449} else {450ShouldNotReachHere();451}452} else {453ShouldNotReachHere();454}455}456457void LIR_Assembler::reg2stack(LIR_Opr src, LIR_Opr dest, BasicType type, bool pop_fpu_stack) {458assert(src->is_register(), "should not call otherwise");459assert(dest->is_stack(), "should not call otherwise");460461Address addr = dest->is_single_word() ?462frame_map()->address_for_slot(dest->single_stack_ix()) :463frame_map()->address_for_slot(dest->double_stack_ix());464465assert(lo_word_offset_in_bytes == 0 && hi_word_offset_in_bytes == 4, "little ending");466if (src->is_single_fpu() || src->is_double_fpu()) {467if (addr.disp() >= 1024) { BAILOUT("Too exotic case to handle here"); }468}469470if (src->is_single_cpu()) {471switch (type) {472case T_OBJECT:473case T_ARRAY: __ verify_oop(src->as_register()); // fall through474case T_ADDRESS:475case T_METADATA: __ str(src->as_register(), addr); break;476case T_FLOAT: // used in intBitsToFloat intrinsic implementation, fall through477case T_INT: __ str_32(src->as_register(), addr); break;478default:479ShouldNotReachHere();480}481} else if (src->is_double_cpu()) {482__ str(src->as_register_lo(), addr);483__ str(src->as_register_hi(), frame_map()->address_for_slot(dest->double_stack_ix(), hi_word_offset_in_bytes));484} else if (src->is_single_fpu()) {485__ str_float(src->as_float_reg(), addr);486} else if (src->is_double_fpu()) {487__ str_double(src->as_double_reg(), addr);488} else {489ShouldNotReachHere();490}491}492493494void LIR_Assembler::reg2mem(LIR_Opr src, LIR_Opr dest, BasicType type,495LIR_PatchCode patch_code, CodeEmitInfo* info,496bool pop_fpu_stack, bool wide,497bool unaligned) {498LIR_Address* to_addr = dest->as_address_ptr();499Register base_reg = to_addr->base()->as_pointer_register();500const bool needs_patching = (patch_code != lir_patch_none);501502PatchingStub* patch = NULL;503if (needs_patching) {504patch = new PatchingStub(_masm, PatchingStub::access_field_id);505}506507int null_check_offset = code_offset();508509switch (type) {510case T_ARRAY:511case T_OBJECT:512if (UseCompressedOops && !wide) {513ShouldNotReachHere();514} else {515__ str(src->as_register(), as_Address(to_addr));516}517break;518519case T_ADDRESS:520__ str(src->as_pointer_register(), as_Address(to_addr));521break;522523case T_BYTE:524case T_BOOLEAN:525__ strb(src->as_register(), as_Address(to_addr));526break;527528case T_CHAR:529case T_SHORT:530__ strh(src->as_register(), as_Address(to_addr));531break;532533case T_INT:534#ifdef __SOFTFP__535case T_FLOAT:536#endif // __SOFTFP__537__ str_32(src->as_register(), as_Address(to_addr));538break;539540541#ifdef __SOFTFP__542case T_DOUBLE:543#endif // __SOFTFP__544case T_LONG: {545Register from_lo = src->as_register_lo();546Register from_hi = src->as_register_hi();547if (to_addr->index()->is_register()) {548assert(to_addr->scale() == LIR_Address::times_1,"Unexpected scaled register");549assert(to_addr->disp() == 0, "Not yet supporting both");550__ add(Rtemp, base_reg, to_addr->index()->as_register());551base_reg = Rtemp;552__ str(from_lo, Address(Rtemp));553if (patch != NULL) {554__ nop(); // see comment before patching_epilog for 2nd str555patching_epilog(patch, lir_patch_low, base_reg, info);556patch = new PatchingStub(_masm, PatchingStub::access_field_id);557patch_code = lir_patch_high;558}559__ str(from_hi, Address(Rtemp, BytesPerWord));560} else if (base_reg == from_lo) {561__ str(from_hi, as_Address_hi(to_addr));562if (patch != NULL) {563__ nop(); // see comment before patching_epilog for 2nd str564patching_epilog(patch, lir_patch_high, base_reg, info);565patch = new PatchingStub(_masm, PatchingStub::access_field_id);566patch_code = lir_patch_low;567}568__ str(from_lo, as_Address_lo(to_addr));569} else {570__ str(from_lo, as_Address_lo(to_addr));571if (patch != NULL) {572__ nop(); // see comment before patching_epilog for 2nd str573patching_epilog(patch, lir_patch_low, base_reg, info);574patch = new PatchingStub(_masm, PatchingStub::access_field_id);575patch_code = lir_patch_high;576}577__ str(from_hi, as_Address_hi(to_addr));578}579break;580}581582#ifndef __SOFTFP__583case T_FLOAT:584if (to_addr->index()->is_register()) {585assert(to_addr->scale() == LIR_Address::times_1,"Unexpected scaled register");586__ add(Rtemp, base_reg, to_addr->index()->as_register());587if ((to_addr->disp() <= -4096) || (to_addr->disp() >= 4096)) { BAILOUT("offset not in range"); }588__ fsts(src->as_float_reg(), Address(Rtemp, to_addr->disp()));589} else {590__ fsts(src->as_float_reg(), as_Address(to_addr));591}592break;593594case T_DOUBLE:595if (to_addr->index()->is_register()) {596assert(to_addr->scale() == LIR_Address::times_1,"Unexpected scaled register");597__ add(Rtemp, base_reg, to_addr->index()->as_register());598if ((to_addr->disp() <= -4096) || (to_addr->disp() >= 4096)) { BAILOUT("offset not in range"); }599__ fstd(src->as_double_reg(), Address(Rtemp, to_addr->disp()));600} else {601__ fstd(src->as_double_reg(), as_Address(to_addr));602}603break;604#endif // __SOFTFP__605606607default:608ShouldNotReachHere();609}610611if (info != NULL) {612add_debug_info_for_null_check(null_check_offset, info);613}614615if (patch != NULL) {616// Offset embedded into LDR/STR instruction may appear not enough617// to address a field. So, provide a space for one more instruction618// that will deal with larger offsets.619__ nop();620patching_epilog(patch, patch_code, base_reg, info);621}622}623624625void LIR_Assembler::stack2reg(LIR_Opr src, LIR_Opr dest, BasicType type) {626assert(src->is_stack(), "should not call otherwise");627assert(dest->is_register(), "should not call otherwise");628629Address addr = src->is_single_word() ?630frame_map()->address_for_slot(src->single_stack_ix()) :631frame_map()->address_for_slot(src->double_stack_ix());632633assert(lo_word_offset_in_bytes == 0 && hi_word_offset_in_bytes == 4, "little ending");634if (dest->is_single_fpu() || dest->is_double_fpu()) {635if (addr.disp() >= 1024) { BAILOUT("Too exotic case to handle here"); }636}637638if (dest->is_single_cpu()) {639switch (type) {640case T_OBJECT:641case T_ARRAY:642case T_ADDRESS:643case T_METADATA: __ ldr(dest->as_register(), addr); break;644case T_FLOAT: // used in floatToRawIntBits intrinsic implemenation645case T_INT: __ ldr_u32(dest->as_register(), addr); break;646default:647ShouldNotReachHere();648}649if ((type == T_OBJECT) || (type == T_ARRAY)) {650__ verify_oop(dest->as_register());651}652} else if (dest->is_double_cpu()) {653__ ldr(dest->as_register_lo(), addr);654__ ldr(dest->as_register_hi(), frame_map()->address_for_slot(src->double_stack_ix(), hi_word_offset_in_bytes));655} else if (dest->is_single_fpu()) {656__ ldr_float(dest->as_float_reg(), addr);657} else if (dest->is_double_fpu()) {658__ ldr_double(dest->as_double_reg(), addr);659} else {660ShouldNotReachHere();661}662}663664665void LIR_Assembler::stack2stack(LIR_Opr src, LIR_Opr dest, BasicType type) {666if (src->is_single_stack()) {667switch (src->type()) {668case T_OBJECT:669case T_ARRAY:670case T_ADDRESS:671case T_METADATA:672__ ldr(Rtemp, frame_map()->address_for_slot(src->single_stack_ix()));673__ str(Rtemp, frame_map()->address_for_slot(dest->single_stack_ix()));674break;675676case T_INT:677case T_FLOAT:678__ ldr_u32(Rtemp, frame_map()->address_for_slot(src->single_stack_ix()));679__ str_32(Rtemp, frame_map()->address_for_slot(dest->single_stack_ix()));680break;681682default:683ShouldNotReachHere();684}685} else {686assert(src->is_double_stack(), "must be");687__ ldr(Rtemp, frame_map()->address_for_slot(src->double_stack_ix(), lo_word_offset_in_bytes));688__ str(Rtemp, frame_map()->address_for_slot(dest->double_stack_ix(), lo_word_offset_in_bytes));689__ ldr(Rtemp, frame_map()->address_for_slot(src->double_stack_ix(), hi_word_offset_in_bytes));690__ str(Rtemp, frame_map()->address_for_slot(dest->double_stack_ix(), hi_word_offset_in_bytes));691}692}693694695void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type,696LIR_PatchCode patch_code, CodeEmitInfo* info,697bool wide, bool unaligned) {698assert(src->is_address(), "should not call otherwise");699assert(dest->is_register(), "should not call otherwise");700LIR_Address* addr = src->as_address_ptr();701702Register base_reg = addr->base()->as_pointer_register();703704PatchingStub* patch = NULL;705if (patch_code != lir_patch_none) {706patch = new PatchingStub(_masm, PatchingStub::access_field_id);707}708if (info != NULL) {709add_debug_info_for_null_check_here(info);710}711712switch (type) {713case T_OBJECT: // fall through714case T_ARRAY:715if (UseCompressedOops && !wide) {716__ ldr_u32(dest->as_register(), as_Address(addr));717} else {718__ ldr(dest->as_register(), as_Address(addr));719}720break;721722case T_ADDRESS:723if (UseCompressedClassPointers && addr->disp() == oopDesc::klass_offset_in_bytes()) {724__ ldr_u32(dest->as_pointer_register(), as_Address(addr));725} else {726__ ldr(dest->as_pointer_register(), as_Address(addr));727}728break;729730case T_INT:731#ifdef __SOFTFP__732case T_FLOAT:733#endif // __SOFTFP__734__ ldr(dest->as_pointer_register(), as_Address(addr));735break;736737case T_BOOLEAN:738__ ldrb(dest->as_register(), as_Address(addr));739break;740741case T_BYTE:742__ ldrsb(dest->as_register(), as_Address(addr));743break;744745case T_CHAR:746__ ldrh(dest->as_register(), as_Address(addr));747break;748749case T_SHORT:750__ ldrsh(dest->as_register(), as_Address(addr));751break;752753754#ifdef __SOFTFP__755case T_DOUBLE:756#endif // __SOFTFP__757case T_LONG: {758Register to_lo = dest->as_register_lo();759Register to_hi = dest->as_register_hi();760if (addr->index()->is_register()) {761assert(addr->scale() == LIR_Address::times_1,"Unexpected scaled register");762assert(addr->disp() == 0, "Not yet supporting both");763__ add(Rtemp, base_reg, addr->index()->as_register());764base_reg = Rtemp;765__ ldr(to_lo, Address(Rtemp));766if (patch != NULL) {767__ nop(); // see comment before patching_epilog for 2nd ldr768patching_epilog(patch, lir_patch_low, base_reg, info);769patch = new PatchingStub(_masm, PatchingStub::access_field_id);770patch_code = lir_patch_high;771}772__ ldr(to_hi, Address(Rtemp, BytesPerWord));773} else if (base_reg == to_lo) {774__ ldr(to_hi, as_Address_hi(addr));775if (patch != NULL) {776__ nop(); // see comment before patching_epilog for 2nd ldr777patching_epilog(patch, lir_patch_high, base_reg, info);778patch = new PatchingStub(_masm, PatchingStub::access_field_id);779patch_code = lir_patch_low;780}781__ ldr(to_lo, as_Address_lo(addr));782} else {783__ ldr(to_lo, as_Address_lo(addr));784if (patch != NULL) {785__ nop(); // see comment before patching_epilog for 2nd ldr786patching_epilog(patch, lir_patch_low, base_reg, info);787patch = new PatchingStub(_masm, PatchingStub::access_field_id);788patch_code = lir_patch_high;789}790__ ldr(to_hi, as_Address_hi(addr));791}792break;793}794795#ifndef __SOFTFP__796case T_FLOAT:797if (addr->index()->is_register()) {798assert(addr->scale() == LIR_Address::times_1,"Unexpected scaled register");799__ add(Rtemp, base_reg, addr->index()->as_register());800if ((addr->disp() <= -4096) || (addr->disp() >= 4096)) { BAILOUT("offset not in range"); }801__ flds(dest->as_float_reg(), Address(Rtemp, addr->disp()));802} else {803__ flds(dest->as_float_reg(), as_Address(addr));804}805break;806807case T_DOUBLE:808if (addr->index()->is_register()) {809assert(addr->scale() == LIR_Address::times_1,"Unexpected scaled register");810__ add(Rtemp, base_reg, addr->index()->as_register());811if ((addr->disp() <= -4096) || (addr->disp() >= 4096)) { BAILOUT("offset not in range"); }812__ fldd(dest->as_double_reg(), Address(Rtemp, addr->disp()));813} else {814__ fldd(dest->as_double_reg(), as_Address(addr));815}816break;817#endif // __SOFTFP__818819820default:821ShouldNotReachHere();822}823824if (patch != NULL) {825// Offset embedded into LDR/STR instruction may appear not enough826// to address a field. So, provide a space for one more instruction827// that will deal with larger offsets.828__ nop();829patching_epilog(patch, patch_code, base_reg, info);830}831832}833834835void LIR_Assembler::emit_op3(LIR_Op3* op) {836bool is_32 = op->result_opr()->is_single_cpu();837838if (op->code() == lir_idiv && op->in_opr2()->is_constant() && is_32) {839int c = op->in_opr2()->as_constant_ptr()->as_jint();840assert(is_power_of_2(c), "non power-of-2 constant should be put in a register");841842Register left = op->in_opr1()->as_register();843Register dest = op->result_opr()->as_register();844if (c == 1) {845__ mov(dest, left);846} else if (c == 2) {847__ add_32(dest, left, AsmOperand(left, lsr, 31));848__ asr_32(dest, dest, 1);849} else if (c != (int) 0x80000000) {850int power = log2i_exact(c);851__ asr_32(Rtemp, left, 31);852__ add_32(dest, left, AsmOperand(Rtemp, lsr, 32-power)); // dest = left + (left < 0 ? 2^power - 1 : 0);853__ asr_32(dest, dest, power); // dest = dest >>> power;854} else {855// x/0x80000000 is a special case, since dividend is a power of two, but is negative.856// The only possible result values are 0 and 1, with 1 only for dividend == divisor == 0x80000000.857__ cmp_32(left, c);858__ mov(dest, 0, ne);859__ mov(dest, 1, eq);860}861} else {862assert(op->code() == lir_idiv || op->code() == lir_irem, "unexpected op3");863__ call(StubRoutines::Arm::idiv_irem_entry(), relocInfo::runtime_call_type);864add_debug_info_for_div0_here(op->info());865}866}867868869void LIR_Assembler::emit_opBranch(LIR_OpBranch* op) {870#ifdef ASSERT871assert(op->block() == NULL || op->block()->label() == op->label(), "wrong label");872if (op->block() != NULL) _branch_target_blocks.append(op->block());873if (op->ublock() != NULL) _branch_target_blocks.append(op->ublock());874assert(op->info() == NULL, "CodeEmitInfo?");875#endif // ASSERT876877#ifdef __SOFTFP__878assert (op->code() != lir_cond_float_branch, "this should be impossible");879#else880if (op->code() == lir_cond_float_branch) {881__ fmstat();882__ b(*(op->ublock()->label()), vs);883}884#endif // __SOFTFP__885886AsmCondition acond = al;887switch (op->cond()) {888case lir_cond_equal: acond = eq; break;889case lir_cond_notEqual: acond = ne; break;890case lir_cond_less: acond = lt; break;891case lir_cond_lessEqual: acond = le; break;892case lir_cond_greaterEqual: acond = ge; break;893case lir_cond_greater: acond = gt; break;894case lir_cond_aboveEqual: acond = hs; break;895case lir_cond_belowEqual: acond = ls; break;896default: assert(op->cond() == lir_cond_always, "must be");897}898__ b(*(op->label()), acond);899}900901902void LIR_Assembler::emit_opConvert(LIR_OpConvert* op) {903LIR_Opr src = op->in_opr();904LIR_Opr dest = op->result_opr();905906switch (op->bytecode()) {907case Bytecodes::_i2l:908move_regs(src->as_register(), dest->as_register_lo());909__ mov(dest->as_register_hi(), AsmOperand(src->as_register(), asr, 31));910break;911case Bytecodes::_l2i:912move_regs(src->as_register_lo(), dest->as_register());913break;914case Bytecodes::_i2b:915__ sign_extend(dest->as_register(), src->as_register(), 8);916break;917case Bytecodes::_i2s:918__ sign_extend(dest->as_register(), src->as_register(), 16);919break;920case Bytecodes::_i2c:921__ zero_extend(dest->as_register(), src->as_register(), 16);922break;923case Bytecodes::_f2d:924__ convert_f2d(dest->as_double_reg(), src->as_float_reg());925break;926case Bytecodes::_d2f:927__ convert_d2f(dest->as_float_reg(), src->as_double_reg());928break;929case Bytecodes::_i2f:930__ fmsr(Stemp, src->as_register());931__ fsitos(dest->as_float_reg(), Stemp);932break;933case Bytecodes::_i2d:934__ fmsr(Stemp, src->as_register());935__ fsitod(dest->as_double_reg(), Stemp);936break;937case Bytecodes::_f2i:938__ ftosizs(Stemp, src->as_float_reg());939__ fmrs(dest->as_register(), Stemp);940break;941case Bytecodes::_d2i:942__ ftosizd(Stemp, src->as_double_reg());943__ fmrs(dest->as_register(), Stemp);944break;945default:946ShouldNotReachHere();947}948}949950951void LIR_Assembler::emit_alloc_obj(LIR_OpAllocObj* op) {952if (op->init_check()) {953Register tmp = op->tmp1()->as_register();954__ ldrb(tmp, Address(op->klass()->as_register(), InstanceKlass::init_state_offset()));955add_debug_info_for_null_check_here(op->stub()->info());956__ cmp(tmp, InstanceKlass::fully_initialized);957__ b(*op->stub()->entry(), ne);958}959__ allocate_object(op->obj()->as_register(),960op->tmp1()->as_register(),961op->tmp2()->as_register(),962op->tmp3()->as_register(),963op->header_size(),964op->object_size(),965op->klass()->as_register(),966*op->stub()->entry());967__ bind(*op->stub()->continuation());968}969970void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) {971if (UseSlowPath ||972(!UseFastNewObjectArray && (op->type() == T_OBJECT || op->type() == T_ARRAY)) ||973(!UseFastNewTypeArray && (op->type() != T_OBJECT && op->type() != T_ARRAY))) {974__ b(*op->stub()->entry());975} else {976__ allocate_array(op->obj()->as_register(),977op->len()->as_register(),978op->tmp1()->as_register(),979op->tmp2()->as_register(),980op->tmp3()->as_register(),981arrayOopDesc::header_size(op->type()),982type2aelembytes(op->type()),983op->klass()->as_register(),984*op->stub()->entry());985}986__ bind(*op->stub()->continuation());987}988989void LIR_Assembler::type_profile_helper(Register mdo, int mdo_offset_bias,990ciMethodData *md, ciProfileData *data,991Register recv, Register tmp1, Label* update_done) {992assert_different_registers(mdo, recv, tmp1);993uint i;994for (i = 0; i < VirtualCallData::row_limit(); i++) {995Label next_test;996// See if the receiver is receiver[n].997Address receiver_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i)) -998mdo_offset_bias);999__ ldr(tmp1, receiver_addr);1000__ verify_klass_ptr(tmp1);1001__ cmp(recv, tmp1);1002__ b(next_test, ne);1003Address data_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i)) -1004mdo_offset_bias);1005__ ldr(tmp1, data_addr);1006__ add(tmp1, tmp1, DataLayout::counter_increment);1007__ str(tmp1, data_addr);1008__ b(*update_done);1009__ bind(next_test);1010}10111012// Didn't find receiver; find next empty slot and fill it in1013for (i = 0; i < VirtualCallData::row_limit(); i++) {1014Label next_test;1015Address recv_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i)) -1016mdo_offset_bias);1017__ ldr(tmp1, recv_addr);1018__ cbnz(tmp1, next_test);1019__ str(recv, recv_addr);1020__ mov(tmp1, DataLayout::counter_increment);1021__ str(tmp1, Address(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i)) -1022mdo_offset_bias));1023__ b(*update_done);1024__ bind(next_test);1025}1026}10271028void LIR_Assembler::setup_md_access(ciMethod* method, int bci,1029ciMethodData*& md, ciProfileData*& data, int& mdo_offset_bias) {1030md = method->method_data_or_null();1031assert(md != NULL, "Sanity");1032data = md->bci_to_data(bci);1033assert(data != NULL, "need data for checkcast");1034assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check");1035if (md->byte_offset_of_slot(data, DataLayout::header_offset()) + data->size_in_bytes() >= 4096) {1036// The offset is large so bias the mdo by the base of the slot so1037// that the ldr can use an immediate offset to reference the slots of the data1038mdo_offset_bias = md->byte_offset_of_slot(data, DataLayout::header_offset());1039}1040}10411042// On 32-bit ARM, code before this helper should test obj for null (ZF should be set if obj is null).1043void LIR_Assembler::typecheck_profile_helper1(ciMethod* method, int bci,1044ciMethodData*& md, ciProfileData*& data, int& mdo_offset_bias,1045Register obj, Register mdo, Register data_val, Label* obj_is_null) {1046assert(method != NULL, "Should have method");1047assert_different_registers(obj, mdo, data_val);1048setup_md_access(method, bci, md, data, mdo_offset_bias);1049Label not_null;1050__ b(not_null, ne);1051__ mov_metadata(mdo, md->constant_encoding());1052if (mdo_offset_bias > 0) {1053__ mov_slow(data_val, mdo_offset_bias);1054__ add(mdo, mdo, data_val);1055}1056Address flags_addr(mdo, md->byte_offset_of_slot(data, DataLayout::flags_offset()) - mdo_offset_bias);1057__ ldrb(data_val, flags_addr);1058__ orr(data_val, data_val, (uint)BitData::null_seen_byte_constant());1059__ strb(data_val, flags_addr);1060__ b(*obj_is_null);1061__ bind(not_null);1062}10631064void LIR_Assembler::typecheck_profile_helper2(ciMethodData* md, ciProfileData* data, int mdo_offset_bias,1065Register mdo, Register recv, Register value, Register tmp1,1066Label* profile_cast_success, Label* profile_cast_failure,1067Label* success, Label* failure) {1068assert_different_registers(mdo, value, tmp1);1069__ bind(*profile_cast_success);1070__ mov_metadata(mdo, md->constant_encoding());1071if (mdo_offset_bias > 0) {1072__ mov_slow(tmp1, mdo_offset_bias);1073__ add(mdo, mdo, tmp1);1074}1075__ load_klass(recv, value);1076type_profile_helper(mdo, mdo_offset_bias, md, data, recv, tmp1, success);1077__ b(*success);1078// Cast failure case1079__ bind(*profile_cast_failure);1080__ mov_metadata(mdo, md->constant_encoding());1081if (mdo_offset_bias > 0) {1082__ mov_slow(tmp1, mdo_offset_bias);1083__ add(mdo, mdo, tmp1);1084}1085Address data_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset()) - mdo_offset_bias);1086__ ldr(tmp1, data_addr);1087__ sub(tmp1, tmp1, DataLayout::counter_increment);1088__ str(tmp1, data_addr);1089__ b(*failure);1090}10911092// Sets `res` to true, if `cond` holds.1093static void set_instanceof_result(MacroAssembler* _masm, Register res, AsmCondition cond) {1094__ mov(res, 1, cond);1095}109610971098void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) {1099// TODO: ARM - can be more effective with one more register1100switch (op->code()) {1101case lir_store_check: {1102CodeStub* stub = op->stub();1103Register value = op->object()->as_register();1104Register array = op->array()->as_register();1105Register klass_RInfo = op->tmp1()->as_register();1106Register k_RInfo = op->tmp2()->as_register();1107assert_different_registers(klass_RInfo, k_RInfo, Rtemp);1108if (op->should_profile()) {1109assert_different_registers(value, klass_RInfo, k_RInfo, Rtemp);1110}11111112// check if it needs to be profiled1113ciMethodData* md;1114ciProfileData* data;1115int mdo_offset_bias = 0;1116Label profile_cast_success, profile_cast_failure, done;1117Label *success_target = op->should_profile() ? &profile_cast_success : &done;1118Label *failure_target = op->should_profile() ? &profile_cast_failure : stub->entry();11191120if (op->should_profile()) {1121__ cmp(value, 0);1122typecheck_profile_helper1(op->profiled_method(), op->profiled_bci(), md, data, mdo_offset_bias, value, k_RInfo, Rtemp, &done);1123} else {1124__ cbz(value, done);1125}1126assert_different_registers(k_RInfo, value);1127add_debug_info_for_null_check_here(op->info_for_exception());1128__ load_klass(k_RInfo, array);1129__ load_klass(klass_RInfo, value);1130__ ldr(k_RInfo, Address(k_RInfo, ObjArrayKlass::element_klass_offset()));1131__ ldr_u32(Rtemp, Address(k_RInfo, Klass::super_check_offset_offset()));1132// check for immediate positive hit1133__ ldr(Rtemp, Address(klass_RInfo, Rtemp));1134__ cmp(klass_RInfo, k_RInfo);1135__ cond_cmp(Rtemp, k_RInfo, ne);1136__ b(*success_target, eq);1137// check for immediate negative hit1138__ ldr_u32(Rtemp, Address(k_RInfo, Klass::super_check_offset_offset()));1139__ cmp(Rtemp, in_bytes(Klass::secondary_super_cache_offset()));1140__ b(*failure_target, ne);1141// slow case1142assert(klass_RInfo == R0 && k_RInfo == R1, "runtime call setup");1143__ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type);1144__ cbz(R0, *failure_target);1145if (op->should_profile()) {1146Register mdo = klass_RInfo, recv = k_RInfo, tmp1 = Rtemp;1147if (mdo == value) {1148mdo = k_RInfo;1149recv = klass_RInfo;1150}1151typecheck_profile_helper2(md, data, mdo_offset_bias, mdo, recv, value, tmp1,1152&profile_cast_success, &profile_cast_failure,1153&done, stub->entry());1154}1155__ bind(done);1156break;1157}11581159case lir_checkcast: {1160CodeStub* stub = op->stub();1161Register obj = op->object()->as_register();1162Register res = op->result_opr()->as_register();1163Register klass_RInfo = op->tmp1()->as_register();1164Register k_RInfo = op->tmp2()->as_register();1165ciKlass* k = op->klass();1166assert_different_registers(res, k_RInfo, klass_RInfo, Rtemp);11671168if (stub->is_simple_exception_stub()) {1169// TODO: ARM - Late binding is used to prevent confusion of register allocator1170assert(stub->is_exception_throw_stub(), "must be");1171((SimpleExceptionStub*)stub)->set_obj(op->result_opr());1172}1173ciMethodData* md;1174ciProfileData* data;1175int mdo_offset_bias = 0;11761177Label done;11781179Label profile_cast_failure, profile_cast_success;1180Label *failure_target = op->should_profile() ? &profile_cast_failure : op->stub()->entry();1181Label *success_target = op->should_profile() ? &profile_cast_success : &done;118211831184__ movs(res, obj);1185if (op->should_profile()) {1186typecheck_profile_helper1(op->profiled_method(), op->profiled_bci(), md, data, mdo_offset_bias, res, klass_RInfo, Rtemp, &done);1187} else {1188__ b(done, eq);1189}1190if (k->is_loaded()) {1191__ mov_metadata(k_RInfo, k->constant_encoding());1192} else if (k_RInfo != obj) {1193klass2reg_with_patching(k_RInfo, op->info_for_patch());1194__ movs(res, obj);1195} else {1196// Patching doesn't update "res" register after GC, so do patching first1197klass2reg_with_patching(Rtemp, op->info_for_patch());1198__ movs(res, obj);1199__ mov(k_RInfo, Rtemp);1200}1201__ load_klass(klass_RInfo, res, ne);12021203if (op->fast_check()) {1204__ cmp(klass_RInfo, k_RInfo, ne);1205__ b(*failure_target, ne);1206} else if (k->is_loaded()) {1207__ b(*success_target, eq);1208__ ldr(Rtemp, Address(klass_RInfo, k->super_check_offset()));1209if (in_bytes(Klass::secondary_super_cache_offset()) != (int) k->super_check_offset()) {1210__ cmp(Rtemp, k_RInfo);1211__ b(*failure_target, ne);1212} else {1213__ cmp(klass_RInfo, k_RInfo);1214__ cmp(Rtemp, k_RInfo, ne);1215__ b(*success_target, eq);1216assert(klass_RInfo == R0 && k_RInfo == R1, "runtime call setup");1217__ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type);1218__ cbz(R0, *failure_target);1219}1220} else {1221__ ldr_u32(Rtemp, Address(k_RInfo, Klass::super_check_offset_offset()));1222__ b(*success_target, eq);1223// check for immediate positive hit1224__ ldr(Rtemp, Address(klass_RInfo, Rtemp));1225__ cmp(klass_RInfo, k_RInfo);1226__ cmp(Rtemp, k_RInfo, ne);1227__ b(*success_target, eq);1228// check for immediate negative hit1229__ ldr_u32(Rtemp, Address(k_RInfo, Klass::super_check_offset_offset()));1230__ cmp(Rtemp, in_bytes(Klass::secondary_super_cache_offset()));1231__ b(*failure_target, ne);1232// slow case1233assert(klass_RInfo == R0 && k_RInfo == R1, "runtime call setup");1234__ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type);1235__ cbz(R0, *failure_target);1236}12371238if (op->should_profile()) {1239Register mdo = klass_RInfo, recv = k_RInfo, tmp1 = Rtemp;1240typecheck_profile_helper2(md, data, mdo_offset_bias, mdo, recv, res, tmp1,1241&profile_cast_success, &profile_cast_failure,1242&done, stub->entry());1243}1244__ bind(done);1245break;1246}12471248case lir_instanceof: {1249Register obj = op->object()->as_register();1250Register res = op->result_opr()->as_register();1251Register klass_RInfo = op->tmp1()->as_register();1252Register k_RInfo = op->tmp2()->as_register();1253ciKlass* k = op->klass();1254assert_different_registers(res, klass_RInfo, k_RInfo, Rtemp);12551256ciMethodData* md;1257ciProfileData* data;1258int mdo_offset_bias = 0;12591260Label done;12611262Label profile_cast_failure, profile_cast_success;1263Label *failure_target = op->should_profile() ? &profile_cast_failure : &done;1264Label *success_target = op->should_profile() ? &profile_cast_success : &done;12651266__ movs(res, obj);12671268if (op->should_profile()) {1269typecheck_profile_helper1(op->profiled_method(), op->profiled_bci(), md, data, mdo_offset_bias, res, klass_RInfo, Rtemp, &done);1270} else {1271__ b(done, eq);1272}12731274if (k->is_loaded()) {1275__ mov_metadata(k_RInfo, k->constant_encoding());1276} else {1277op->info_for_patch()->add_register_oop(FrameMap::as_oop_opr(res));1278klass2reg_with_patching(k_RInfo, op->info_for_patch());1279}1280__ load_klass(klass_RInfo, res);12811282if (!op->should_profile()) {1283__ mov(res, 0);1284}12851286if (op->fast_check()) {1287__ cmp(klass_RInfo, k_RInfo);1288if (!op->should_profile()) {1289set_instanceof_result(_masm, res, eq);1290} else {1291__ b(profile_cast_failure, ne);1292}1293} else if (k->is_loaded()) {1294__ ldr(Rtemp, Address(klass_RInfo, k->super_check_offset()));1295if (in_bytes(Klass::secondary_super_cache_offset()) != (int) k->super_check_offset()) {1296__ cmp(Rtemp, k_RInfo);1297if (!op->should_profile()) {1298set_instanceof_result(_masm, res, eq);1299} else {1300__ b(profile_cast_failure, ne);1301}1302} else {1303__ cmp(klass_RInfo, k_RInfo);1304__ cond_cmp(Rtemp, k_RInfo, ne);1305if (!op->should_profile()) {1306set_instanceof_result(_masm, res, eq);1307}1308__ b(*success_target, eq);1309assert(klass_RInfo == R0 && k_RInfo == R1, "runtime call setup");1310__ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type);1311if (!op->should_profile()) {1312move_regs(R0, res);1313} else {1314__ cbz(R0, *failure_target);1315}1316}1317} else {1318__ ldr_u32(Rtemp, Address(k_RInfo, Klass::super_check_offset_offset()));1319// check for immediate positive hit1320__ cmp(klass_RInfo, k_RInfo);1321if (!op->should_profile()) {1322__ ldr(res, Address(klass_RInfo, Rtemp), ne);1323__ cond_cmp(res, k_RInfo, ne);1324set_instanceof_result(_masm, res, eq);1325} else {1326__ ldr(Rtemp, Address(klass_RInfo, Rtemp), ne);1327__ cond_cmp(Rtemp, k_RInfo, ne);1328}1329__ b(*success_target, eq);1330// check for immediate negative hit1331if (op->should_profile()) {1332__ ldr_u32(Rtemp, Address(k_RInfo, Klass::super_check_offset_offset()));1333}1334__ cmp(Rtemp, in_bytes(Klass::secondary_super_cache_offset()));1335if (!op->should_profile()) {1336__ mov(res, 0, ne);1337}1338__ b(*failure_target, ne);1339// slow case1340assert(klass_RInfo == R0 && k_RInfo == R1, "runtime call setup");1341__ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type);1342if (!op->should_profile()) {1343move_regs(R0, res);1344}1345if (op->should_profile()) {1346__ cbz(R0, *failure_target);1347}1348}13491350if (op->should_profile()) {1351Label done_ok, done_failure;1352Register mdo = klass_RInfo, recv = k_RInfo, tmp1 = Rtemp;1353typecheck_profile_helper2(md, data, mdo_offset_bias, mdo, recv, res, tmp1,1354&profile_cast_success, &profile_cast_failure,1355&done_ok, &done_failure);1356__ bind(done_failure);1357__ mov(res, 0);1358__ b(done);1359__ bind(done_ok);1360__ mov(res, 1);1361}1362__ bind(done);1363break;1364}1365default:1366ShouldNotReachHere();1367}1368}136913701371void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) {1372// if (*addr == cmpval) {1373// *addr = newval;1374// dest = 1;1375// } else {1376// dest = 0;1377// }1378// FIXME: membar_release1379__ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore | MacroAssembler::LoadStore), Rtemp);1380Register addr = op->addr()->is_register() ?1381op->addr()->as_pointer_register() :1382op->addr()->as_address_ptr()->base()->as_pointer_register();1383assert(op->addr()->is_register() || op->addr()->as_address_ptr()->disp() == 0, "unexpected disp");1384assert(op->addr()->is_register() || op->addr()->as_address_ptr()->index() == LIR_OprDesc::illegalOpr(), "unexpected index");1385if (op->code() == lir_cas_int || op->code() == lir_cas_obj) {1386Register cmpval = op->cmp_value()->as_register();1387Register newval = op->new_value()->as_register();1388Register dest = op->result_opr()->as_register();1389assert_different_registers(dest, addr, cmpval, newval, Rtemp);13901391__ atomic_cas_bool(cmpval, newval, addr, 0, Rtemp); // Rtemp free by default at C1 LIR layer1392__ mov(dest, 1, eq);1393__ mov(dest, 0, ne);1394} else if (op->code() == lir_cas_long) {1395assert(VM_Version::supports_cx8(), "wrong machine");1396Register cmp_value_lo = op->cmp_value()->as_register_lo();1397Register cmp_value_hi = op->cmp_value()->as_register_hi();1398Register new_value_lo = op->new_value()->as_register_lo();1399Register new_value_hi = op->new_value()->as_register_hi();1400Register dest = op->result_opr()->as_register();1401Register tmp_lo = op->tmp1()->as_register_lo();1402Register tmp_hi = op->tmp1()->as_register_hi();14031404assert_different_registers(tmp_lo, tmp_hi, cmp_value_lo, cmp_value_hi, dest, new_value_lo, new_value_hi, addr);1405assert(tmp_hi->encoding() == tmp_lo->encoding() + 1, "non aligned register pair");1406assert(new_value_hi->encoding() == new_value_lo->encoding() + 1, "non aligned register pair");1407assert((tmp_lo->encoding() & 0x1) == 0, "misaligned register pair");1408assert((new_value_lo->encoding() & 0x1) == 0, "misaligned register pair");1409__ atomic_cas64(tmp_lo, tmp_hi, dest, cmp_value_lo, cmp_value_hi,1410new_value_lo, new_value_hi, addr, 0);1411} else {1412Unimplemented();1413}1414// FIXME: is full membar really needed instead of just membar_acquire?1415__ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreLoad | MacroAssembler::StoreStore), Rtemp);1416}141714181419void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result, BasicType type) {1420AsmCondition acond = al;1421AsmCondition ncond = nv;1422if (opr1 != opr2) {1423switch (condition) {1424case lir_cond_equal: acond = eq; ncond = ne; break;1425case lir_cond_notEqual: acond = ne; ncond = eq; break;1426case lir_cond_less: acond = lt; ncond = ge; break;1427case lir_cond_lessEqual: acond = le; ncond = gt; break;1428case lir_cond_greaterEqual: acond = ge; ncond = lt; break;1429case lir_cond_greater: acond = gt; ncond = le; break;1430case lir_cond_aboveEqual: acond = hs; ncond = lo; break;1431case lir_cond_belowEqual: acond = ls; ncond = hi; break;1432default: ShouldNotReachHere();1433}1434}14351436for (;;) { // two iterations only1437if (opr1 == result) {1438// do nothing1439} else if (opr1->is_single_cpu()) {1440__ mov(result->as_register(), opr1->as_register(), acond);1441} else if (opr1->is_double_cpu()) {1442__ long_move(result->as_register_lo(), result->as_register_hi(),1443opr1->as_register_lo(), opr1->as_register_hi(), acond);1444} else if (opr1->is_single_stack()) {1445__ ldr(result->as_register(), frame_map()->address_for_slot(opr1->single_stack_ix()), acond);1446} else if (opr1->is_double_stack()) {1447__ ldr(result->as_register_lo(),1448frame_map()->address_for_slot(opr1->double_stack_ix(), lo_word_offset_in_bytes), acond);1449__ ldr(result->as_register_hi(),1450frame_map()->address_for_slot(opr1->double_stack_ix(), hi_word_offset_in_bytes), acond);1451} else if (opr1->is_illegal()) {1452// do nothing: this part of the cmove has been optimized away in the peephole optimizer1453} else {1454assert(opr1->is_constant(), "must be");1455LIR_Const* c = opr1->as_constant_ptr();14561457switch (c->type()) {1458case T_INT:1459__ mov_slow(result->as_register(), c->as_jint(), acond);1460break;1461case T_LONG:1462__ mov_slow(result->as_register_lo(), c->as_jint_lo(), acond);1463__ mov_slow(result->as_register_hi(), c->as_jint_hi(), acond);1464break;1465case T_OBJECT:1466__ mov_oop(result->as_register(), c->as_jobject(), 0, acond);1467break;1468case T_FLOAT:1469#ifdef __SOFTFP__1470// not generated now.1471__ mov_slow(result->as_register(), c->as_jint(), acond);1472#else1473__ mov_float(result->as_float_reg(), c->as_jfloat(), acond);1474#endif // __SOFTFP__1475break;1476case T_DOUBLE:1477#ifdef __SOFTFP__1478// not generated now.1479__ mov_slow(result->as_register_lo(), c->as_jint_lo(), acond);1480__ mov_slow(result->as_register_hi(), c->as_jint_hi(), acond);1481#else1482__ mov_double(result->as_double_reg(), c->as_jdouble(), acond);1483#endif // __SOFTFP__1484break;1485default:1486ShouldNotReachHere();1487}1488}14891490// Negate the condition and repeat the algorithm with the second operand1491if (opr1 == opr2) { break; }1492opr1 = opr2;1493acond = ncond;1494}1495}14961497#ifdef ASSERT1498static int reg_size(LIR_Opr op) {1499switch (op->type()) {1500case T_FLOAT:1501case T_INT: return BytesPerInt;1502case T_LONG:1503case T_DOUBLE: return BytesPerLong;1504case T_OBJECT:1505case T_ARRAY:1506case T_METADATA: return BytesPerWord;1507case T_ADDRESS:1508case T_ILLEGAL: // fall through1509default: ShouldNotReachHere(); return -1;1510}1511}1512#endif15131514void LIR_Assembler::arith_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest, CodeEmitInfo* info, bool pop_fpu_stack) {1515assert(info == NULL, "unused on this code path");1516assert(dest->is_register(), "wrong items state");15171518if (right->is_address()) {1519// special case for adding shifted/extended register1520const Register res = dest->as_pointer_register();1521const Register lreg = left->as_pointer_register();1522const LIR_Address* addr = right->as_address_ptr();15231524assert(addr->base()->as_pointer_register() == lreg && addr->index()->is_register() && addr->disp() == 0, "must be");15251526int scale = addr->scale();1527AsmShift shift = lsl;152815291530assert(reg_size(addr->base()) == reg_size(addr->index()), "should be");1531assert(reg_size(addr->base()) == reg_size(dest), "should be");1532assert(reg_size(dest) == wordSize, "should be");15331534AsmOperand operand(addr->index()->as_pointer_register(), shift, scale);1535switch (code) {1536case lir_add: __ add(res, lreg, operand); break;1537case lir_sub: __ sub(res, lreg, operand); break;1538default: ShouldNotReachHere();1539}15401541} else if (left->is_address()) {1542assert(code == lir_sub && right->is_single_cpu(), "special case used by strength_reduce_multiply()");1543const LIR_Address* addr = left->as_address_ptr();1544const Register res = dest->as_register();1545const Register rreg = right->as_register();1546assert(addr->base()->as_register() == rreg && addr->index()->is_register() && addr->disp() == 0, "must be");1547__ rsb(res, rreg, AsmOperand(addr->index()->as_register(), lsl, addr->scale()));15481549} else if (dest->is_single_cpu()) {1550assert(left->is_single_cpu(), "unexpected left operand");15511552const Register res = dest->as_register();1553const Register lreg = left->as_register();15541555if (right->is_single_cpu()) {1556const Register rreg = right->as_register();1557switch (code) {1558case lir_add: __ add_32(res, lreg, rreg); break;1559case lir_sub: __ sub_32(res, lreg, rreg); break;1560case lir_mul: __ mul_32(res, lreg, rreg); break;1561default: ShouldNotReachHere();1562}1563} else {1564assert(right->is_constant(), "must be");1565const jint c = right->as_constant_ptr()->as_jint();1566if (!Assembler::is_arith_imm_in_range(c)) {1567BAILOUT("illegal arithmetic operand");1568}1569switch (code) {1570case lir_add: __ add_32(res, lreg, c); break;1571case lir_sub: __ sub_32(res, lreg, c); break;1572default: ShouldNotReachHere();1573}1574}15751576} else if (dest->is_double_cpu()) {1577Register res_lo = dest->as_register_lo();1578Register res_hi = dest->as_register_hi();1579Register lreg_lo = left->as_register_lo();1580Register lreg_hi = left->as_register_hi();1581if (right->is_double_cpu()) {1582Register rreg_lo = right->as_register_lo();1583Register rreg_hi = right->as_register_hi();1584if (res_lo == lreg_hi || res_lo == rreg_hi) {1585res_lo = Rtemp;1586}1587switch (code) {1588case lir_add:1589__ adds(res_lo, lreg_lo, rreg_lo);1590__ adc(res_hi, lreg_hi, rreg_hi);1591break;1592case lir_sub:1593__ subs(res_lo, lreg_lo, rreg_lo);1594__ sbc(res_hi, lreg_hi, rreg_hi);1595break;1596default:1597ShouldNotReachHere();1598}1599} else {1600assert(right->is_constant(), "must be");1601assert((right->as_constant_ptr()->as_jlong() >> 32) == 0, "out of range");1602const jint c = (jint) right->as_constant_ptr()->as_jlong();1603if (res_lo == lreg_hi) {1604res_lo = Rtemp;1605}1606switch (code) {1607case lir_add:1608__ adds(res_lo, lreg_lo, c);1609__ adc(res_hi, lreg_hi, 0);1610break;1611case lir_sub:1612__ subs(res_lo, lreg_lo, c);1613__ sbc(res_hi, lreg_hi, 0);1614break;1615default:1616ShouldNotReachHere();1617}1618}1619move_regs(res_lo, dest->as_register_lo());16201621} else if (dest->is_single_fpu()) {1622assert(left->is_single_fpu(), "must be");1623assert(right->is_single_fpu(), "must be");1624const FloatRegister res = dest->as_float_reg();1625const FloatRegister lreg = left->as_float_reg();1626const FloatRegister rreg = right->as_float_reg();1627switch (code) {1628case lir_add: __ add_float(res, lreg, rreg); break;1629case lir_sub: __ sub_float(res, lreg, rreg); break;1630case lir_mul: __ mul_float(res, lreg, rreg); break;1631case lir_div: __ div_float(res, lreg, rreg); break;1632default: ShouldNotReachHere();1633}1634} else if (dest->is_double_fpu()) {1635assert(left->is_double_fpu(), "must be");1636assert(right->is_double_fpu(), "must be");1637const FloatRegister res = dest->as_double_reg();1638const FloatRegister lreg = left->as_double_reg();1639const FloatRegister rreg = right->as_double_reg();1640switch (code) {1641case lir_add: __ add_double(res, lreg, rreg); break;1642case lir_sub: __ sub_double(res, lreg, rreg); break;1643case lir_mul: __ mul_double(res, lreg, rreg); break;1644case lir_div: __ div_double(res, lreg, rreg); break;1645default: ShouldNotReachHere();1646}1647} else {1648ShouldNotReachHere();1649}1650}165116521653void LIR_Assembler::intrinsic_op(LIR_Code code, LIR_Opr value, LIR_Opr unused, LIR_Opr dest, LIR_Op* op) {1654switch (code) {1655case lir_abs:1656__ abs_double(dest->as_double_reg(), value->as_double_reg());1657break;1658case lir_sqrt:1659__ sqrt_double(dest->as_double_reg(), value->as_double_reg());1660break;1661default:1662ShouldNotReachHere();1663}1664}166516661667void LIR_Assembler::logic_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest) {1668assert(dest->is_register(), "wrong items state");1669assert(left->is_register(), "wrong items state");16701671if (dest->is_single_cpu()) {16721673const Register res = dest->as_register();1674const Register lreg = left->as_register();16751676if (right->is_single_cpu()) {1677const Register rreg = right->as_register();1678switch (code) {1679case lir_logic_and: __ and_32(res, lreg, rreg); break;1680case lir_logic_or: __ orr_32(res, lreg, rreg); break;1681case lir_logic_xor: __ eor_32(res, lreg, rreg); break;1682default: ShouldNotReachHere();1683}1684} else {1685assert(right->is_constant(), "must be");1686const uint c = (uint)right->as_constant_ptr()->as_jint();1687if (!Assembler::is_arith_imm_in_range(c)) {1688BAILOUT("illegal arithmetic operand");1689}1690switch (code) {1691case lir_logic_and: __ and_32(res, lreg, c); break;1692case lir_logic_or: __ orr_32(res, lreg, c); break;1693case lir_logic_xor: __ eor_32(res, lreg, c); break;1694default: ShouldNotReachHere();1695}1696}1697} else {1698assert(dest->is_double_cpu(), "should be");1699Register res_lo = dest->as_register_lo();17001701assert (dest->type() == T_LONG, "unexpected result type");1702assert (left->type() == T_LONG, "unexpected left type");1703assert (right->type() == T_LONG, "unexpected right type");17041705const Register res_hi = dest->as_register_hi();1706const Register lreg_lo = left->as_register_lo();1707const Register lreg_hi = left->as_register_hi();17081709if (right->is_register()) {1710const Register rreg_lo = right->as_register_lo();1711const Register rreg_hi = right->as_register_hi();1712if (res_lo == lreg_hi || res_lo == rreg_hi) {1713res_lo = Rtemp; // Temp register helps to avoid overlap between result and input1714}1715switch (code) {1716case lir_logic_and:1717__ andr(res_lo, lreg_lo, rreg_lo);1718__ andr(res_hi, lreg_hi, rreg_hi);1719break;1720case lir_logic_or:1721__ orr(res_lo, lreg_lo, rreg_lo);1722__ orr(res_hi, lreg_hi, rreg_hi);1723break;1724case lir_logic_xor:1725__ eor(res_lo, lreg_lo, rreg_lo);1726__ eor(res_hi, lreg_hi, rreg_hi);1727break;1728default:1729ShouldNotReachHere();1730}1731move_regs(res_lo, dest->as_register_lo());1732} else {1733assert(right->is_constant(), "must be");1734const jint c_lo = (jint) right->as_constant_ptr()->as_jlong();1735const jint c_hi = (jint) (right->as_constant_ptr()->as_jlong() >> 32);1736// Case for logic_or from do_ClassIDIntrinsic()1737if (c_hi == 0 && AsmOperand::is_rotated_imm(c_lo)) {1738switch (code) {1739case lir_logic_and:1740__ andr(res_lo, lreg_lo, c_lo);1741__ mov(res_hi, 0);1742break;1743case lir_logic_or:1744__ orr(res_lo, lreg_lo, c_lo);1745break;1746case lir_logic_xor:1747__ eor(res_lo, lreg_lo, c_lo);1748break;1749default:1750ShouldNotReachHere();1751}1752} else if (code == lir_logic_and &&1753c_hi == -1 &&1754(AsmOperand::is_rotated_imm(c_lo) ||1755AsmOperand::is_rotated_imm(~c_lo))) {1756// Another case which handles logic_and from do_ClassIDIntrinsic()1757if (AsmOperand::is_rotated_imm(c_lo)) {1758__ andr(res_lo, lreg_lo, c_lo);1759} else {1760__ bic(res_lo, lreg_lo, ~c_lo);1761}1762if (res_hi != lreg_hi) {1763__ mov(res_hi, lreg_hi);1764}1765} else {1766BAILOUT("64 bit constant cannot be inlined");1767}1768}1769}1770}1771177217731774void LIR_Assembler::comp_op(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Op2* op) {1775if (opr1->is_single_cpu()) {1776if (opr2->is_constant()) {1777switch (opr2->as_constant_ptr()->type()) {1778case T_INT: {1779const jint c = opr2->as_constant_ptr()->as_jint();1780if (Assembler::is_arith_imm_in_range(c)) {1781__ cmp_32(opr1->as_register(), c);1782} else if (Assembler::is_arith_imm_in_range(-c)) {1783__ cmn_32(opr1->as_register(), -c);1784} else {1785// This can happen when compiling lookupswitch1786__ mov_slow(Rtemp, c);1787__ cmp_32(opr1->as_register(), Rtemp);1788}1789break;1790}1791case T_OBJECT:1792assert(opr2->as_constant_ptr()->as_jobject() == NULL, "cannot handle otherwise");1793__ cmp(opr1->as_register(), 0);1794break;1795case T_METADATA:1796assert(condition == lir_cond_equal || condition == lir_cond_notEqual, "Only equality tests");1797assert(opr2->as_constant_ptr()->as_metadata() == NULL, "cannot handle otherwise");1798__ cmp(opr1->as_register(), 0);1799break;1800default:1801ShouldNotReachHere();1802}1803} else if (opr2->is_single_cpu()) {1804if (opr1->type() == T_OBJECT || opr1->type() == T_ARRAY) {1805assert(opr2->type() == T_OBJECT || opr2->type() == T_ARRAY, "incompatibe type");1806__ cmpoop(opr1->as_register(), opr2->as_register());1807} else if (opr1->type() == T_METADATA || opr1->type() == T_ADDRESS) {1808assert(opr2->type() == T_METADATA || opr2->type() == T_ADDRESS, "incompatibe type");1809__ cmp(opr1->as_register(), opr2->as_register());1810} else {1811assert(opr2->type() != T_OBJECT && opr2->type() != T_ARRAY && opr2->type() != T_METADATA && opr2->type() != T_ADDRESS, "incompatibe type");1812__ cmp_32(opr1->as_register(), opr2->as_register());1813}1814} else {1815ShouldNotReachHere();1816}1817} else if (opr1->is_double_cpu()) {1818Register xlo = opr1->as_register_lo();1819Register xhi = opr1->as_register_hi();1820if (opr2->is_constant() && opr2->as_jlong() == 0) {1821assert(condition == lir_cond_equal || condition == lir_cond_notEqual, "cannot handle otherwise");1822__ orrs(Rtemp, xlo, xhi);1823} else if (opr2->is_register()) {1824Register ylo = opr2->as_register_lo();1825Register yhi = opr2->as_register_hi();1826if (condition == lir_cond_equal || condition == lir_cond_notEqual) {1827__ teq(xhi, yhi);1828__ teq(xlo, ylo, eq);1829} else {1830__ subs(Rtemp, xlo, ylo);1831__ sbcs(Rtemp, xhi, yhi);1832}1833} else {1834ShouldNotReachHere();1835}1836} else if (opr1->is_single_fpu()) {1837if (opr2->is_constant()) {1838assert(opr2->as_jfloat() == 0.0f, "cannot handle otherwise");1839__ cmp_zero_float(opr1->as_float_reg());1840} else {1841__ cmp_float(opr1->as_float_reg(), opr2->as_float_reg());1842}1843} else if (opr1->is_double_fpu()) {1844if (opr2->is_constant()) {1845assert(opr2->as_jdouble() == 0.0, "cannot handle otherwise");1846__ cmp_zero_double(opr1->as_double_reg());1847} else {1848__ cmp_double(opr1->as_double_reg(), opr2->as_double_reg());1849}1850} else {1851ShouldNotReachHere();1852}1853}18541855void LIR_Assembler::comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dst, LIR_Op2* op) {1856const Register res = dst->as_register();1857if (code == lir_cmp_fd2i || code == lir_ucmp_fd2i) {1858comp_op(lir_cond_unknown, left, right, op);1859__ fmstat();1860if (code == lir_ucmp_fd2i) { // unordered is less1861__ mvn(res, 0, lt);1862__ mov(res, 1, ge);1863} else { // unordered is greater1864__ mov(res, 1, cs);1865__ mvn(res, 0, cc);1866}1867__ mov(res, 0, eq);18681869} else {1870assert(code == lir_cmp_l2i, "must be");18711872Label done;1873const Register xlo = left->as_register_lo();1874const Register xhi = left->as_register_hi();1875const Register ylo = right->as_register_lo();1876const Register yhi = right->as_register_hi();1877__ cmp(xhi, yhi);1878__ mov(res, 1, gt);1879__ mvn(res, 0, lt);1880__ b(done, ne);1881__ subs(res, xlo, ylo);1882__ mov(res, 1, hi);1883__ mvn(res, 0, lo);1884__ bind(done);1885}1886}188718881889void LIR_Assembler::align_call(LIR_Code code) {1890// Not needed1891}189218931894void LIR_Assembler::call(LIR_OpJavaCall *op, relocInfo::relocType rtype) {1895int ret_addr_offset = __ patchable_call(op->addr(), rtype);1896assert(ret_addr_offset == __ offset(), "embedded return address not allowed");1897add_call_info_here(op->info());1898}189919001901void LIR_Assembler::ic_call(LIR_OpJavaCall *op) {1902bool near_range = __ cache_fully_reachable();1903address oop_address = pc();19041905bool use_movw = VM_Version::supports_movw();19061907// Ricklass may contain something that is not a metadata pointer so1908// mov_metadata can't be used1909InlinedAddress value((address)Universe::non_oop_word());1910InlinedAddress addr(op->addr());1911if (use_movw) {1912__ movw(Ricklass, ((unsigned int)Universe::non_oop_word()) & 0xffff);1913__ movt(Ricklass, ((unsigned int)Universe::non_oop_word()) >> 16);1914} else {1915// No movw/movt, must be load a pc relative value but no1916// relocation so no metadata table to load from.1917// Use a b instruction rather than a bl, inline constant after the1918// branch, use a PC relative ldr to load the constant, arrange for1919// the call to return after the constant(s).1920__ ldr_literal(Ricklass, value);1921}1922__ relocate(virtual_call_Relocation::spec(oop_address));1923if (near_range && use_movw) {1924__ bl(op->addr());1925} else {1926Label call_return;1927__ adr(LR, call_return);1928if (near_range) {1929__ b(op->addr());1930} else {1931__ indirect_jump(addr, Rtemp);1932__ bind_literal(addr);1933}1934if (!use_movw) {1935__ bind_literal(value);1936}1937__ bind(call_return);1938}1939add_call_info(code_offset(), op->info());1940}19411942void LIR_Assembler::emit_static_call_stub() {1943address call_pc = __ pc();1944address stub = __ start_a_stub(call_stub_size());1945if (stub == NULL) {1946BAILOUT("static call stub overflow");1947}19481949DEBUG_ONLY(int offset = code_offset();)19501951InlinedMetadata metadata_literal(NULL);1952__ relocate(static_stub_Relocation::spec(call_pc));1953// If not a single instruction, NativeMovConstReg::next_instruction_address()1954// must jump over the whole following ldr_literal.1955// (See CompiledStaticCall::set_to_interpreted())1956#ifdef ASSERT1957address ldr_site = __ pc();1958#endif1959__ ldr_literal(Rmethod, metadata_literal);1960assert(nativeMovConstReg_at(ldr_site)->next_instruction_address() == __ pc(), "Fix ldr_literal or its parsing");1961bool near_range = __ cache_fully_reachable();1962InlinedAddress dest((address)-1);1963if (near_range) {1964address branch_site = __ pc();1965__ b(branch_site); // b to self maps to special NativeJump -1 destination1966} else {1967__ indirect_jump(dest, Rtemp);1968}1969__ bind_literal(metadata_literal); // includes spec_for_immediate reloc1970if (!near_range) {1971__ bind_literal(dest); // special NativeJump -1 destination1972}19731974assert(code_offset() - offset <= call_stub_size(), "overflow");1975__ end_a_stub();1976}19771978void LIR_Assembler::throw_op(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmitInfo* info) {1979assert(exceptionOop->as_register() == Rexception_obj, "must match");1980assert(exceptionPC->as_register() == Rexception_pc, "must match");1981info->add_register_oop(exceptionOop);19821983Runtime1::StubID handle_id = compilation()->has_fpu_code() ?1984Runtime1::handle_exception_id :1985Runtime1::handle_exception_nofpu_id;1986Label return_address;1987__ adr(Rexception_pc, return_address);1988__ call(Runtime1::entry_for(handle_id), relocInfo::runtime_call_type);1989__ bind(return_address);1990add_call_info_here(info); // for exception handler1991}19921993void LIR_Assembler::unwind_op(LIR_Opr exceptionOop) {1994assert(exceptionOop->as_register() == Rexception_obj, "must match");1995__ b(_unwind_handler_entry);1996}19971998void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, LIR_Opr count, LIR_Opr dest, LIR_Opr tmp) {1999AsmShift shift = lsl;2000switch (code) {2001case lir_shl: shift = lsl; break;2002case lir_shr: shift = asr; break;2003case lir_ushr: shift = lsr; break;2004default: ShouldNotReachHere();2005}20062007if (dest->is_single_cpu()) {2008__ andr(Rtemp, count->as_register(), 31);2009__ mov(dest->as_register(), AsmOperand(left->as_register(), shift, Rtemp));2010} else if (dest->is_double_cpu()) {2011Register dest_lo = dest->as_register_lo();2012Register dest_hi = dest->as_register_hi();2013Register src_lo = left->as_register_lo();2014Register src_hi = left->as_register_hi();2015Register Rcount = count->as_register();2016// Resolve possible register conflicts2017if (shift == lsl && dest_hi == src_lo) {2018dest_hi = Rtemp;2019} else if (shift != lsl && dest_lo == src_hi) {2020dest_lo = Rtemp;2021} else if (dest_lo == src_lo && dest_hi == src_hi) {2022dest_lo = Rtemp;2023} else if (dest_lo == Rcount || dest_hi == Rcount) {2024Rcount = Rtemp;2025}2026__ andr(Rcount, count->as_register(), 63);2027__ long_shift(dest_lo, dest_hi, src_lo, src_hi, shift, Rcount);2028move_regs(dest_lo, dest->as_register_lo());2029move_regs(dest_hi, dest->as_register_hi());2030} else {2031ShouldNotReachHere();2032}2033}203420352036void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, jint count, LIR_Opr dest) {2037AsmShift shift = lsl;2038switch (code) {2039case lir_shl: shift = lsl; break;2040case lir_shr: shift = asr; break;2041case lir_ushr: shift = lsr; break;2042default: ShouldNotReachHere();2043}20442045if (dest->is_single_cpu()) {2046count &= 31;2047if (count != 0) {2048__ mov(dest->as_register(), AsmOperand(left->as_register(), shift, count));2049} else {2050move_regs(left->as_register(), dest->as_register());2051}2052} else if (dest->is_double_cpu()) {2053count &= 63;2054if (count != 0) {2055Register dest_lo = dest->as_register_lo();2056Register dest_hi = dest->as_register_hi();2057Register src_lo = left->as_register_lo();2058Register src_hi = left->as_register_hi();2059// Resolve possible register conflicts2060if (shift == lsl && dest_hi == src_lo) {2061dest_hi = Rtemp;2062} else if (shift != lsl && dest_lo == src_hi) {2063dest_lo = Rtemp;2064}2065__ long_shift(dest_lo, dest_hi, src_lo, src_hi, shift, count);2066move_regs(dest_lo, dest->as_register_lo());2067move_regs(dest_hi, dest->as_register_hi());2068} else {2069__ long_move(dest->as_register_lo(), dest->as_register_hi(),2070left->as_register_lo(), left->as_register_hi());2071}2072} else {2073ShouldNotReachHere();2074}2075}207620772078// Saves 4 given registers in reserved argument area.2079void LIR_Assembler::save_in_reserved_area(Register r1, Register r2, Register r3, Register r4) {2080verify_reserved_argument_area_size(4);2081__ stmia(SP, RegisterSet(r1) | RegisterSet(r2) | RegisterSet(r3) | RegisterSet(r4));2082}20832084// Restores 4 given registers from reserved argument area.2085void LIR_Assembler::restore_from_reserved_area(Register r1, Register r2, Register r3, Register r4) {2086__ ldmia(SP, RegisterSet(r1) | RegisterSet(r2) | RegisterSet(r3) | RegisterSet(r4), no_writeback);2087}208820892090void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {2091ciArrayKlass* default_type = op->expected_type();2092Register src = op->src()->as_register();2093Register src_pos = op->src_pos()->as_register();2094Register dst = op->dst()->as_register();2095Register dst_pos = op->dst_pos()->as_register();2096Register length = op->length()->as_register();2097Register tmp = op->tmp()->as_register();2098Register tmp2 = Rtemp;20992100assert(src == R0 && src_pos == R1 && dst == R2 && dst_pos == R3, "code assumption");21012102CodeStub* stub = op->stub();21032104int flags = op->flags();2105BasicType basic_type = default_type != NULL ? default_type->element_type()->basic_type() : T_ILLEGAL;2106if (basic_type == T_ARRAY) basic_type = T_OBJECT;21072108// If we don't know anything or it's an object array, just go through the generic arraycopy2109if (default_type == NULL) {21102111// save arguments, because they will be killed by a runtime call2112save_in_reserved_area(R0, R1, R2, R3);21132114// pass length argument on SP[0]2115__ str(length, Address(SP, -2*wordSize, pre_indexed)); // 2 words for a proper stack alignment21162117address copyfunc_addr = StubRoutines::generic_arraycopy();2118assert(copyfunc_addr != NULL, "generic arraycopy stub required");2119#ifndef PRODUCT2120if (PrintC1Statistics) {2121__ inc_counter((address)&Runtime1::_generic_arraycopystub_cnt, tmp, tmp2);2122}2123#endif // !PRODUCT2124// the stub is in the code cache so close enough2125__ call(copyfunc_addr, relocInfo::runtime_call_type);21262127__ add(SP, SP, 2*wordSize);21282129__ cbz_32(R0, *stub->continuation());21302131__ mvn_32(tmp, R0);2132restore_from_reserved_area(R0, R1, R2, R3); // load saved arguments in slow case only2133__ sub_32(length, length, tmp);2134__ add_32(src_pos, src_pos, tmp);2135__ add_32(dst_pos, dst_pos, tmp);21362137__ b(*stub->entry());21382139__ bind(*stub->continuation());2140return;2141}21422143assert(default_type != NULL && default_type->is_array_klass() && default_type->is_loaded(),2144"must be true at this point");2145int elem_size = type2aelembytes(basic_type);2146int shift = exact_log2(elem_size);21472148// Check for NULL2149if (flags & LIR_OpArrayCopy::src_null_check) {2150if (flags & LIR_OpArrayCopy::dst_null_check) {2151__ cmp(src, 0);2152__ cond_cmp(dst, 0, ne); // make one instruction shorter if both checks are needed2153__ b(*stub->entry(), eq);2154} else {2155__ cbz(src, *stub->entry());2156}2157} else if (flags & LIR_OpArrayCopy::dst_null_check) {2158__ cbz(dst, *stub->entry());2159}21602161// If the compiler was not able to prove that exact type of the source or the destination2162// of the arraycopy is an array type, check at runtime if the source or the destination is2163// an instance type.2164if (flags & LIR_OpArrayCopy::type_check) {2165if (!(flags & LIR_OpArrayCopy::LIR_OpArrayCopy::dst_objarray)) {2166__ load_klass(tmp, dst);2167__ ldr_u32(tmp2, Address(tmp, in_bytes(Klass::layout_helper_offset())));2168__ mov_slow(tmp, Klass::_lh_neutral_value);2169__ cmp_32(tmp2, tmp);2170__ b(*stub->entry(), ge);2171}21722173if (!(flags & LIR_OpArrayCopy::LIR_OpArrayCopy::src_objarray)) {2174__ load_klass(tmp, src);2175__ ldr_u32(tmp2, Address(tmp, in_bytes(Klass::layout_helper_offset())));2176__ mov_slow(tmp, Klass::_lh_neutral_value);2177__ cmp_32(tmp2, tmp);2178__ b(*stub->entry(), ge);2179}2180}21812182// Check if negative2183const int all_positive_checks = LIR_OpArrayCopy::src_pos_positive_check |2184LIR_OpArrayCopy::dst_pos_positive_check |2185LIR_OpArrayCopy::length_positive_check;2186switch (flags & all_positive_checks) {2187case LIR_OpArrayCopy::src_pos_positive_check:2188__ branch_if_negative_32(src_pos, *stub->entry());2189break;2190case LIR_OpArrayCopy::dst_pos_positive_check:2191__ branch_if_negative_32(dst_pos, *stub->entry());2192break;2193case LIR_OpArrayCopy::length_positive_check:2194__ branch_if_negative_32(length, *stub->entry());2195break;2196case LIR_OpArrayCopy::src_pos_positive_check | LIR_OpArrayCopy::dst_pos_positive_check:2197__ branch_if_any_negative_32(src_pos, dst_pos, tmp, *stub->entry());2198break;2199case LIR_OpArrayCopy::src_pos_positive_check | LIR_OpArrayCopy::length_positive_check:2200__ branch_if_any_negative_32(src_pos, length, tmp, *stub->entry());2201break;2202case LIR_OpArrayCopy::dst_pos_positive_check | LIR_OpArrayCopy::length_positive_check:2203__ branch_if_any_negative_32(dst_pos, length, tmp, *stub->entry());2204break;2205case all_positive_checks:2206__ branch_if_any_negative_32(src_pos, dst_pos, length, tmp, *stub->entry());2207break;2208default:2209assert((flags & all_positive_checks) == 0, "the last option");2210}22112212// Range checks2213if (flags & LIR_OpArrayCopy::src_range_check) {2214__ ldr_s32(tmp2, Address(src, arrayOopDesc::length_offset_in_bytes()));2215__ add_32(tmp, src_pos, length);2216__ cmp_32(tmp, tmp2);2217__ b(*stub->entry(), hi);2218}2219if (flags & LIR_OpArrayCopy::dst_range_check) {2220__ ldr_s32(tmp2, Address(dst, arrayOopDesc::length_offset_in_bytes()));2221__ add_32(tmp, dst_pos, length);2222__ cmp_32(tmp, tmp2);2223__ b(*stub->entry(), hi);2224}22252226// Check if src and dst are of the same type2227if (flags & LIR_OpArrayCopy::type_check) {2228// We don't know the array types are compatible2229if (basic_type != T_OBJECT) {2230// Simple test for basic type arrays2231if (UseCompressedClassPointers) {2232// We don't need decode because we just need to compare2233__ ldr_u32(tmp, Address(src, oopDesc::klass_offset_in_bytes()));2234__ ldr_u32(tmp2, Address(dst, oopDesc::klass_offset_in_bytes()));2235__ cmp_32(tmp, tmp2);2236} else {2237__ load_klass(tmp, src);2238__ load_klass(tmp2, dst);2239__ cmp(tmp, tmp2);2240}2241__ b(*stub->entry(), ne);2242} else {2243// For object arrays, if src is a sub class of dst then we can2244// safely do the copy.2245Label cont, slow;22462247address copyfunc_addr = StubRoutines::checkcast_arraycopy();22482249__ load_klass(tmp, src);2250__ load_klass(tmp2, dst);22512252// We are at a call so all live registers are saved before we2253// get here2254assert_different_registers(tmp, tmp2, R6, altFP_7_11);22552256__ check_klass_subtype_fast_path(tmp, tmp2, R6, altFP_7_11, &cont, copyfunc_addr == NULL ? stub->entry() : &slow, NULL);22572258__ mov(R6, R0);2259__ mov(altFP_7_11, R1);2260__ mov(R0, tmp);2261__ mov(R1, tmp2);2262__ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type); // does not blow any registers except R0, LR and Rtemp2263__ cmp_32(R0, 0);2264__ mov(R0, R6);2265__ mov(R1, altFP_7_11);22662267if (copyfunc_addr != NULL) { // use stub if available2268// src is not a sub class of dst so we have to do a2269// per-element check.22702271__ b(cont, ne);22722273__ bind(slow);22742275int mask = LIR_OpArrayCopy::src_objarray|LIR_OpArrayCopy::dst_objarray;2276if ((flags & mask) != mask) {2277// Check that at least both of them object arrays.2278assert(flags & mask, "one of the two should be known to be an object array");22792280if (!(flags & LIR_OpArrayCopy::src_objarray)) {2281__ load_klass(tmp, src);2282} else if (!(flags & LIR_OpArrayCopy::dst_objarray)) {2283__ load_klass(tmp, dst);2284}2285int lh_offset = in_bytes(Klass::layout_helper_offset());22862287__ ldr_u32(tmp2, Address(tmp, lh_offset));22882289jint objArray_lh = Klass::array_layout_helper(T_OBJECT);2290__ mov_slow(tmp, objArray_lh);2291__ cmp_32(tmp, tmp2);2292__ b(*stub->entry(), ne);2293}22942295save_in_reserved_area(R0, R1, R2, R3);22962297Register src_ptr = R0;2298Register dst_ptr = R1;2299Register len = R2;2300Register chk_off = R3;2301Register super_k = tmp;23022303__ add(src_ptr, src, arrayOopDesc::base_offset_in_bytes(basic_type));2304__ add_ptr_scaled_int32(src_ptr, src_ptr, src_pos, shift);23052306__ add(dst_ptr, dst, arrayOopDesc::base_offset_in_bytes(basic_type));2307__ add_ptr_scaled_int32(dst_ptr, dst_ptr, dst_pos, shift);2308__ load_klass(tmp, dst);23092310int ek_offset = in_bytes(ObjArrayKlass::element_klass_offset());2311int sco_offset = in_bytes(Klass::super_check_offset_offset());23122313__ ldr(super_k, Address(tmp, ek_offset));23142315__ mov(len, length);2316__ ldr_u32(chk_off, Address(super_k, sco_offset));2317__ push(super_k);23182319__ call(copyfunc_addr, relocInfo::runtime_call_type);23202321#ifndef PRODUCT2322if (PrintC1Statistics) {2323Label failed;2324__ cbnz_32(R0, failed);2325__ inc_counter((address)&Runtime1::_arraycopy_checkcast_cnt, tmp, tmp2);2326__ bind(failed);2327}2328#endif // PRODUCT23292330__ add(SP, SP, wordSize); // Drop super_k argument23312332__ cbz_32(R0, *stub->continuation());2333__ mvn_32(tmp, R0);23342335// load saved arguments in slow case only2336restore_from_reserved_area(R0, R1, R2, R3);23372338__ sub_32(length, length, tmp);2339__ add_32(src_pos, src_pos, tmp);2340__ add_32(dst_pos, dst_pos, tmp);23412342#ifndef PRODUCT2343if (PrintC1Statistics) {2344__ inc_counter((address)&Runtime1::_arraycopy_checkcast_attempt_cnt, tmp, tmp2);2345}2346#endif23472348__ b(*stub->entry());23492350__ bind(cont);2351} else {2352__ b(*stub->entry(), eq);2353__ bind(cont);2354}2355}2356}23572358#ifndef PRODUCT2359if (PrintC1Statistics) {2360address counter = Runtime1::arraycopy_count_address(basic_type);2361__ inc_counter(counter, tmp, tmp2);2362}2363#endif // !PRODUCT23642365bool disjoint = (flags & LIR_OpArrayCopy::overlapping) == 0;2366bool aligned = (flags & LIR_OpArrayCopy::unaligned) == 0;2367const char *name;2368address entry = StubRoutines::select_arraycopy_function(basic_type, aligned, disjoint, name, false);23692370Register src_ptr = R0;2371Register dst_ptr = R1;2372Register len = R2;23732374__ add(src_ptr, src, arrayOopDesc::base_offset_in_bytes(basic_type));2375__ add_ptr_scaled_int32(src_ptr, src_ptr, src_pos, shift);23762377__ add(dst_ptr, dst, arrayOopDesc::base_offset_in_bytes(basic_type));2378__ add_ptr_scaled_int32(dst_ptr, dst_ptr, dst_pos, shift);23792380__ mov(len, length);23812382__ call(entry, relocInfo::runtime_call_type);23832384__ bind(*stub->continuation());2385}23862387#ifdef ASSERT2388// emit run-time assertion2389void LIR_Assembler::emit_assert(LIR_OpAssert* op) {2390assert(op->code() == lir_assert, "must be");23912392if (op->in_opr1()->is_valid()) {2393assert(op->in_opr2()->is_valid(), "both operands must be valid");2394comp_op(op->condition(), op->in_opr1(), op->in_opr2(), op);2395} else {2396assert(op->in_opr2()->is_illegal(), "both operands must be illegal");2397assert(op->condition() == lir_cond_always, "no other conditions allowed");2398}23992400Label ok;2401if (op->condition() != lir_cond_always) {2402AsmCondition acond = al;2403switch (op->condition()) {2404case lir_cond_equal: acond = eq; break;2405case lir_cond_notEqual: acond = ne; break;2406case lir_cond_less: acond = lt; break;2407case lir_cond_lessEqual: acond = le; break;2408case lir_cond_greaterEqual: acond = ge; break;2409case lir_cond_greater: acond = gt; break;2410case lir_cond_aboveEqual: acond = hs; break;2411case lir_cond_belowEqual: acond = ls; break;2412default: ShouldNotReachHere();2413}2414__ b(ok, acond);2415}2416if (op->halt()) {2417const char* str = __ code_string(op->msg());2418__ stop(str);2419} else {2420breakpoint();2421}2422__ bind(ok);2423}2424#endif // ASSERT24252426void LIR_Assembler::emit_updatecrc32(LIR_OpUpdateCRC32* op) {2427fatal("CRC32 intrinsic is not implemented on this platform");2428}24292430void LIR_Assembler::emit_lock(LIR_OpLock* op) {2431Register obj = op->obj_opr()->as_pointer_register();2432Register hdr = op->hdr_opr()->as_pointer_register();2433Register lock = op->lock_opr()->as_pointer_register();2434Register tmp = op->scratch_opr()->is_illegal() ? noreg :2435op->scratch_opr()->as_pointer_register();24362437if (!UseFastLocking) {2438__ b(*op->stub()->entry());2439} else if (op->code() == lir_lock) {2440assert(BasicLock::displaced_header_offset_in_bytes() == 0, "lock_reg must point to the displaced header");2441int null_check_offset = __ lock_object(hdr, obj, lock, tmp, *op->stub()->entry());2442if (op->info() != NULL) {2443add_debug_info_for_null_check(null_check_offset, op->info());2444}2445} else if (op->code() == lir_unlock) {2446__ unlock_object(hdr, obj, lock, tmp, *op->stub()->entry());2447} else {2448ShouldNotReachHere();2449}2450__ bind(*op->stub()->continuation());2451}245224532454void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) {2455ciMethod* method = op->profiled_method();2456int bci = op->profiled_bci();2457ciMethod* callee = op->profiled_callee();24582459// Update counter for all call types2460ciMethodData* md = method->method_data_or_null();2461assert(md != NULL, "Sanity");2462ciProfileData* data = md->bci_to_data(bci);2463assert(data != NULL && data->is_CounterData(), "need CounterData for calls");2464assert(op->mdo()->is_single_cpu(), "mdo must be allocated");2465Register mdo = op->mdo()->as_register();2466assert(op->tmp1()->is_register(), "tmp1 must be allocated");2467Register tmp1 = op->tmp1()->as_pointer_register();2468assert_different_registers(mdo, tmp1);2469__ mov_metadata(mdo, md->constant_encoding());2470int mdo_offset_bias = 0;2471int max_offset = 4096;2472if (md->byte_offset_of_slot(data, CounterData::count_offset()) + data->size_in_bytes() >= max_offset) {2473// The offset is large so bias the mdo by the base of the slot so2474// that the ldr can use an immediate offset to reference the slots of the data2475mdo_offset_bias = md->byte_offset_of_slot(data, CounterData::count_offset());2476__ mov_slow(tmp1, mdo_offset_bias);2477__ add(mdo, mdo, tmp1);2478}24792480Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset()) - mdo_offset_bias);2481// Perform additional virtual call profiling for invokevirtual and2482// invokeinterface bytecodes2483if (op->should_profile_receiver_type()) {2484assert(op->recv()->is_single_cpu(), "recv must be allocated");2485Register recv = op->recv()->as_register();2486assert_different_registers(mdo, tmp1, recv);2487assert(data->is_VirtualCallData(), "need VirtualCallData for virtual calls");2488ciKlass* known_klass = op->known_holder();2489if (C1OptimizeVirtualCallProfiling && known_klass != NULL) {2490// We know the type that will be seen at this call site; we can2491// statically update the MethodData* rather than needing to do2492// dynamic tests on the receiver type24932494// NOTE: we should probably put a lock around this search to2495// avoid collisions by concurrent compilations2496ciVirtualCallData* vc_data = (ciVirtualCallData*) data;2497uint i;2498for (i = 0; i < VirtualCallData::row_limit(); i++) {2499ciKlass* receiver = vc_data->receiver(i);2500if (known_klass->equals(receiver)) {2501Address data_addr(mdo, md->byte_offset_of_slot(data,2502VirtualCallData::receiver_count_offset(i)) -2503mdo_offset_bias);2504__ ldr(tmp1, data_addr);2505__ add(tmp1, tmp1, DataLayout::counter_increment);2506__ str(tmp1, data_addr);2507return;2508}2509}25102511// Receiver type not found in profile data; select an empty slot25122513// Note that this is less efficient than it should be because it2514// always does a write to the receiver part of the2515// VirtualCallData rather than just the first time2516for (i = 0; i < VirtualCallData::row_limit(); i++) {2517ciKlass* receiver = vc_data->receiver(i);2518if (receiver == NULL) {2519Address recv_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i)) -2520mdo_offset_bias);2521__ mov_metadata(tmp1, known_klass->constant_encoding());2522__ str(tmp1, recv_addr);2523Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)) -2524mdo_offset_bias);2525__ ldr(tmp1, data_addr);2526__ add(tmp1, tmp1, DataLayout::counter_increment);2527__ str(tmp1, data_addr);2528return;2529}2530}2531} else {2532__ load_klass(recv, recv);2533Label update_done;2534type_profile_helper(mdo, mdo_offset_bias, md, data, recv, tmp1, &update_done);2535// Receiver did not match any saved receiver and there is no empty row for it.2536// Increment total counter to indicate polymorphic case.2537__ ldr(tmp1, counter_addr);2538__ add(tmp1, tmp1, DataLayout::counter_increment);2539__ str(tmp1, counter_addr);25402541__ bind(update_done);2542}2543} else {2544// Static call2545__ ldr(tmp1, counter_addr);2546__ add(tmp1, tmp1, DataLayout::counter_increment);2547__ str(tmp1, counter_addr);2548}2549}25502551void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) {2552fatal("Type profiling not implemented on this platform");2553}25542555void LIR_Assembler::emit_delay(LIR_OpDelay*) {2556Unimplemented();2557}255825592560void LIR_Assembler::monitor_address(int monitor_no, LIR_Opr dst) {2561Address mon_addr = frame_map()->address_for_monitor_lock(monitor_no);2562__ add_slow(dst->as_pointer_register(), mon_addr.base(), mon_addr.disp());2563}256425652566void LIR_Assembler::align_backward_branch_target() {2567// Some ARM processors do better with 8-byte branch target alignment2568__ align(8);2569}257025712572void LIR_Assembler::negate(LIR_Opr left, LIR_Opr dest, LIR_Opr tmp) {2573// tmp must be unused2574assert(tmp->is_illegal(), "wasting a register if tmp is allocated");25752576if (left->is_single_cpu()) {2577assert (dest->type() == T_INT, "unexpected result type");2578assert (left->type() == T_INT, "unexpected left type");2579__ neg_32(dest->as_register(), left->as_register());2580} else if (left->is_double_cpu()) {2581Register dest_lo = dest->as_register_lo();2582Register dest_hi = dest->as_register_hi();2583Register src_lo = left->as_register_lo();2584Register src_hi = left->as_register_hi();2585if (dest_lo == src_hi) {2586dest_lo = Rtemp;2587}2588__ rsbs(dest_lo, src_lo, 0);2589__ rsc(dest_hi, src_hi, 0);2590move_regs(dest_lo, dest->as_register_lo());2591} else if (left->is_single_fpu()) {2592__ neg_float(dest->as_float_reg(), left->as_float_reg());2593} else if (left->is_double_fpu()) {2594__ neg_double(dest->as_double_reg(), left->as_double_reg());2595} else {2596ShouldNotReachHere();2597}2598}259926002601void LIR_Assembler::leal(LIR_Opr addr_opr, LIR_Opr dest, LIR_PatchCode patch_code, CodeEmitInfo* info) {2602assert(patch_code == lir_patch_none, "Patch code not supported");2603LIR_Address* addr = addr_opr->as_address_ptr();2604if (addr->index()->is_illegal()) {2605jint c = addr->disp();2606if (!Assembler::is_arith_imm_in_range(c)) {2607BAILOUT("illegal arithmetic operand");2608}2609__ add(dest->as_pointer_register(), addr->base()->as_pointer_register(), c);2610} else {2611assert(addr->disp() == 0, "cannot handle otherwise");2612__ add(dest->as_pointer_register(), addr->base()->as_pointer_register(),2613AsmOperand(addr->index()->as_pointer_register(), lsl, addr->scale()));2614}2615}261626172618void LIR_Assembler::rt_call(LIR_Opr result, address dest, const LIR_OprList* args, LIR_Opr tmp, CodeEmitInfo* info) {2619assert(!tmp->is_valid(), "don't need temporary");2620__ call(dest);2621if (info != NULL) {2622add_call_info_here(info);2623}2624}262526262627void LIR_Assembler::volatile_move_op(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info) {2628assert(src->is_double_cpu() && dest->is_address() ||2629src->is_address() && dest->is_double_cpu(),2630"Simple move_op is called for all other cases");26312632int null_check_offset;2633if (dest->is_address()) {2634// Store2635const LIR_Address* addr = dest->as_address_ptr();2636const Register src_lo = src->as_register_lo();2637const Register src_hi = src->as_register_hi();2638assert(addr->index()->is_illegal() && addr->disp() == 0, "The address is simple already");26392640if (src_lo < src_hi) {2641null_check_offset = __ offset();2642__ stmia(addr->base()->as_register(), RegisterSet(src_lo) | RegisterSet(src_hi));2643} else {2644assert(src_lo < Rtemp, "Rtemp is higher than any allocatable register");2645__ mov(Rtemp, src_hi);2646null_check_offset = __ offset();2647__ stmia(addr->base()->as_register(), RegisterSet(src_lo) | RegisterSet(Rtemp));2648}2649} else {2650// Load2651const LIR_Address* addr = src->as_address_ptr();2652const Register dest_lo = dest->as_register_lo();2653const Register dest_hi = dest->as_register_hi();2654assert(addr->index()->is_illegal() && addr->disp() == 0, "The address is simple already");26552656null_check_offset = __ offset();2657if (dest_lo < dest_hi) {2658__ ldmia(addr->base()->as_register(), RegisterSet(dest_lo) | RegisterSet(dest_hi));2659} else {2660assert(dest_lo < Rtemp, "Rtemp is higher than any allocatable register");2661__ ldmia(addr->base()->as_register(), RegisterSet(dest_lo) | RegisterSet(Rtemp));2662__ mov(dest_hi, Rtemp);2663}2664}26652666if (info != NULL) {2667add_debug_info_for_null_check(null_check_offset, info);2668}2669}267026712672void LIR_Assembler::membar() {2673__ membar(MacroAssembler::StoreLoad, Rtemp);2674}26752676void LIR_Assembler::membar_acquire() {2677__ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::LoadLoad | MacroAssembler::LoadStore), Rtemp);2678}26792680void LIR_Assembler::membar_release() {2681__ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore | MacroAssembler::LoadStore), Rtemp);2682}26832684void LIR_Assembler::membar_loadload() {2685__ membar(MacroAssembler::LoadLoad, Rtemp);2686}26872688void LIR_Assembler::membar_storestore() {2689__ membar(MacroAssembler::StoreStore, Rtemp);2690}26912692void LIR_Assembler::membar_loadstore() {2693__ membar(MacroAssembler::LoadStore, Rtemp);2694}26952696void LIR_Assembler::membar_storeload() {2697__ membar(MacroAssembler::StoreLoad, Rtemp);2698}26992700void LIR_Assembler::on_spin_wait() {2701Unimplemented();2702}27032704void LIR_Assembler::get_thread(LIR_Opr result_reg) {2705// Not used on ARM2706Unimplemented();2707}27082709void LIR_Assembler::peephole(LIR_List* lir) {2710LIR_OpList* inst = lir->instructions_list();2711const int inst_length = inst->length();2712for (int i = 0; i < inst_length; i++) {2713LIR_Op* op = inst->at(i);2714switch (op->code()) {2715case lir_cmp: {2716// Replace:2717// cmp rX, y2718// cmove [EQ] y, z, rX2719// with2720// cmp rX, y2721// cmove [EQ] illegalOpr, z, rX2722//2723// or2724// cmp rX, y2725// cmove [NE] z, y, rX2726// with2727// cmp rX, y2728// cmove [NE] z, illegalOpr, rX2729//2730// moves from illegalOpr should be removed when converting LIR to native assembly27312732LIR_Op2* cmp = op->as_Op2();2733assert(cmp != NULL, "cmp LIR instruction is not an op2");27342735if (i + 1 < inst_length) {2736LIR_Op2* cmove = inst->at(i + 1)->as_Op2();2737if (cmove != NULL && cmove->code() == lir_cmove) {2738LIR_Opr cmove_res = cmove->result_opr();2739bool res_is_op1 = cmove_res == cmp->in_opr1();2740bool res_is_op2 = cmove_res == cmp->in_opr2();2741LIR_Opr cmp_res, cmp_arg;2742if (res_is_op1) {2743cmp_res = cmp->in_opr1();2744cmp_arg = cmp->in_opr2();2745} else if (res_is_op2) {2746cmp_res = cmp->in_opr2();2747cmp_arg = cmp->in_opr1();2748} else {2749cmp_res = LIR_OprFact::illegalOpr;2750cmp_arg = LIR_OprFact::illegalOpr;2751}27522753if (cmp_res != LIR_OprFact::illegalOpr) {2754LIR_Condition cond = cmove->condition();2755if (cond == lir_cond_equal && cmove->in_opr1() == cmp_arg) {2756cmove->set_in_opr1(LIR_OprFact::illegalOpr);2757} else if (cond == lir_cond_notEqual && cmove->in_opr2() == cmp_arg) {2758cmove->set_in_opr2(LIR_OprFact::illegalOpr);2759}2760}2761}2762}2763break;2764}27652766default:2767break;2768}2769}2770}27712772void LIR_Assembler::atomic_op(LIR_Code code, LIR_Opr src, LIR_Opr data, LIR_Opr dest, LIR_Opr tmp) {2773assert(src->is_address(), "sanity");2774Address addr = as_Address(src->as_address_ptr());27752776if (code == lir_xchg) {2777} else {2778assert (!data->is_oop(), "xadd for oops");2779}27802781__ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore | MacroAssembler::LoadStore), Rtemp);27822783Label retry;2784__ bind(retry);27852786if (data->type() == T_INT || data->is_oop()) {2787Register dst = dest->as_register();2788Register new_val = noreg;2789__ ldrex(dst, addr);2790if (code == lir_xadd) {2791Register tmp_reg = tmp->as_register();2792if (data->is_constant()) {2793assert_different_registers(dst, tmp_reg);2794__ add_32(tmp_reg, dst, data->as_constant_ptr()->as_jint());2795} else {2796assert_different_registers(dst, tmp_reg, data->as_register());2797__ add_32(tmp_reg, dst, data->as_register());2798}2799new_val = tmp_reg;2800} else {2801if (UseCompressedOops && data->is_oop()) {2802new_val = tmp->as_pointer_register();2803} else {2804new_val = data->as_register();2805}2806assert_different_registers(dst, new_val);2807}2808__ strex(Rtemp, new_val, addr);28092810} else if (data->type() == T_LONG) {2811Register dst_lo = dest->as_register_lo();2812Register new_val_lo = noreg;2813Register dst_hi = dest->as_register_hi();28142815assert(dst_hi->encoding() == dst_lo->encoding() + 1, "non aligned register pair");2816assert((dst_lo->encoding() & 0x1) == 0, "misaligned register pair");28172818__ bind(retry);2819__ ldrexd(dst_lo, addr);2820if (code == lir_xadd) {2821Register tmp_lo = tmp->as_register_lo();2822Register tmp_hi = tmp->as_register_hi();28232824assert(tmp_hi->encoding() == tmp_lo->encoding() + 1, "non aligned register pair");2825assert((tmp_lo->encoding() & 0x1) == 0, "misaligned register pair");28262827if (data->is_constant()) {2828jlong c = data->as_constant_ptr()->as_jlong();2829assert((jlong)((jint)c) == c, "overflow");2830assert_different_registers(dst_lo, dst_hi, tmp_lo, tmp_hi);2831__ adds(tmp_lo, dst_lo, (jint)c);2832__ adc(tmp_hi, dst_hi, 0);2833} else {2834Register new_val_lo = data->as_register_lo();2835Register new_val_hi = data->as_register_hi();2836__ adds(tmp_lo, dst_lo, new_val_lo);2837__ adc(tmp_hi, dst_hi, new_val_hi);2838assert_different_registers(dst_lo, dst_hi, tmp_lo, tmp_hi, new_val_lo, new_val_hi);2839}2840new_val_lo = tmp_lo;2841} else {2842new_val_lo = data->as_register_lo();2843Register new_val_hi = data->as_register_hi();28442845assert_different_registers(dst_lo, dst_hi, new_val_lo, new_val_hi);2846assert(new_val_hi->encoding() == new_val_lo->encoding() + 1, "non aligned register pair");2847assert((new_val_lo->encoding() & 0x1) == 0, "misaligned register pair");2848}2849__ strexd(Rtemp, new_val_lo, addr);2850} else {2851ShouldNotReachHere();2852}28532854__ cbnz_32(Rtemp, retry);2855__ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreLoad | MacroAssembler::StoreStore), Rtemp);28562857}28582859#undef __286028612862