assembler_sparc.inline.hpp revision 710:e5b0439ef4ae
1/* 2 * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any questions. 22 * 23 */ 24 25inline void MacroAssembler::pd_patch_instruction(address branch, address target) { 26 jint& stub_inst = *(jint*) branch; 27 stub_inst = patched_branch(target - branch, stub_inst, 0); 28} 29 30#ifndef PRODUCT 31inline void MacroAssembler::pd_print_patched_instruction(address branch) { 32 jint stub_inst = *(jint*) branch; 33 print_instruction(stub_inst); 34 ::tty->print("%s", " (unresolved)"); 35} 36#endif // PRODUCT 37 38inline bool Address::is_simm13(int offset) { return Assembler::is_simm13(disp() + offset); } 39 40 41// inlines for SPARC assembler -- dmu 5/97 42 43inline void Assembler::check_delay() { 44# ifdef CHECK_DELAY 45 guarantee( delay_state != at_delay_slot, "must say delayed() when filling delay slot"); 46 delay_state = no_delay; 47# endif 48} 49 50inline void Assembler::emit_long(int x) { 51 check_delay(); 52 AbstractAssembler::emit_long(x); 53} 54 55inline void Assembler::emit_data(int x, relocInfo::relocType rtype) { 56 relocate(rtype); 57 emit_long(x); 58} 59 60inline void Assembler::emit_data(int x, RelocationHolder const& rspec) { 61 relocate(rspec); 62 emit_long(x); 63} 64 65 66inline void Assembler::add( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | rs2(s2) ); } 67inline void Assembler::add( Register s1, int simm13a, Register d, relocInfo::relocType rtype ) { emit_data( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rtype ); } 68inline void Assembler::add( Register s1, int simm13a, Register d, RelocationHolder const& rspec ) { emit_data( op(arith_op) | rd(d) | op3(add_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rspec ); } 69inline void Assembler::add( const Address& a, Register d, int offset) { add( a.base(), a.disp() + offset, d, a.rspec(offset)); } 70 71inline void Assembler::bpr( RCondition c, bool a, Predict p, Register s1, address d, relocInfo::relocType rt ) { v9_only(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(bpr_op2) | wdisp16(intptr_t(d), intptr_t(pc())) | predict(p) | rs1(s1), rt); has_delay_slot(); } 72inline void Assembler::bpr( RCondition c, bool a, Predict p, Register s1, Label& L) { bpr( c, a, p, s1, target(L)); } 73 74inline void Assembler::fb( Condition c, bool a, address d, relocInfo::relocType rt ) { v9_dep(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(fb_op2) | wdisp(intptr_t(d), intptr_t(pc()), 22), rt); has_delay_slot(); } 75inline void Assembler::fb( Condition c, bool a, Label& L ) { fb(c, a, target(L)); } 76 77inline void Assembler::fbp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt ) { v9_only(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(fbp_op2) | branchcc(cc) | predict(p) | wdisp(intptr_t(d), intptr_t(pc()), 19), rt); has_delay_slot(); } 78inline void Assembler::fbp( Condition c, bool a, CC cc, Predict p, Label& L ) { fbp(c, a, cc, p, target(L)); } 79 80inline void Assembler::cb( Condition c, bool a, address d, relocInfo::relocType rt ) { v8_only(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(cb_op2) | wdisp(intptr_t(d), intptr_t(pc()), 22), rt); has_delay_slot(); } 81inline void Assembler::cb( Condition c, bool a, Label& L ) { cb(c, a, target(L)); } 82 83inline void Assembler::br( Condition c, bool a, address d, relocInfo::relocType rt ) { v9_dep(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(br_op2) | wdisp(intptr_t(d), intptr_t(pc()), 22), rt); has_delay_slot(); } 84inline void Assembler::br( Condition c, bool a, Label& L ) { br(c, a, target(L)); } 85 86inline void Assembler::bp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt ) { v9_only(); emit_data( op(branch_op) | annul(a) | cond(c) | op2(bp_op2) | branchcc(cc) | predict(p) | wdisp(intptr_t(d), intptr_t(pc()), 19), rt); has_delay_slot(); } 87inline void Assembler::bp( Condition c, bool a, CC cc, Predict p, Label& L ) { bp(c, a, cc, p, target(L)); } 88 89inline void Assembler::call( address d, relocInfo::relocType rt ) { emit_data( op(call_op) | wdisp(intptr_t(d), intptr_t(pc()), 30), rt); has_delay_slot(); assert(rt != relocInfo::virtual_call_type, "must use virtual_call_Relocation::spec"); } 90inline void Assembler::call( Label& L, relocInfo::relocType rt ) { call( target(L), rt); } 91 92inline void Assembler::flush( Register s1, Register s2) { emit_long( op(arith_op) | op3(flush_op3) | rs1(s1) | rs2(s2)); } 93inline void Assembler::flush( Register s1, int simm13a) { emit_data( op(arith_op) | op3(flush_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 94 95inline void Assembler::jmpl( Register s1, Register s2, Register d ) { emit_long( op(arith_op) | rd(d) | op3(jmpl_op3) | rs1(s1) | rs2(s2)); has_delay_slot(); } 96inline void Assembler::jmpl( Register s1, int simm13a, Register d, RelocationHolder const& rspec ) { emit_data( op(arith_op) | rd(d) | op3(jmpl_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rspec); has_delay_slot(); } 97 98inline void Assembler::jmpl( Address& a, Register d, int offset) { jmpl( a.base(), a.disp() + offset, d, a.rspec(offset)); } 99 100 101inline void Assembler::ldf( FloatRegisterImpl::Width w, Register s1, Register s2, FloatRegister d) { emit_long( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3, w) | rs1(s1) | rs2(s2) ); } 102inline void Assembler::ldf( FloatRegisterImpl::Width w, Register s1, int simm13a, FloatRegister d) { emit_data( op(ldst_op) | fd(d, w) | alt_op3(ldf_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 103 104inline void Assembler::ldf( FloatRegisterImpl::Width w, const Address& a, FloatRegister d, int offset) { relocate(a.rspec(offset)); ldf( w, a.base(), a.disp() + offset, d); } 105 106inline void Assembler::ldfsr( Register s1, Register s2) { v9_dep(); emit_long( op(ldst_op) | op3(ldfsr_op3) | rs1(s1) | rs2(s2) ); } 107inline void Assembler::ldfsr( Register s1, int simm13a) { v9_dep(); emit_data( op(ldst_op) | op3(ldfsr_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 108inline void Assembler::ldxfsr( Register s1, Register s2) { v9_only(); emit_long( op(ldst_op) | rd(G1) | op3(ldfsr_op3) | rs1(s1) | rs2(s2) ); } 109inline void Assembler::ldxfsr( Register s1, int simm13a) { v9_only(); emit_data( op(ldst_op) | rd(G1) | op3(ldfsr_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 110 111inline void Assembler::ldc( Register s1, Register s2, int crd) { v8_only(); emit_long( op(ldst_op) | fcn(crd) | op3(ldc_op3 ) | rs1(s1) | rs2(s2) ); } 112inline void Assembler::ldc( Register s1, int simm13a, int crd) { v8_only(); emit_data( op(ldst_op) | fcn(crd) | op3(ldc_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 113inline void Assembler::lddc( Register s1, Register s2, int crd) { v8_only(); emit_long( op(ldst_op) | fcn(crd) | op3(lddc_op3 ) | rs1(s1) | rs2(s2) ); } 114inline void Assembler::lddc( Register s1, int simm13a, int crd) { v8_only(); emit_data( op(ldst_op) | fcn(crd) | op3(lddc_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 115inline void Assembler::ldcsr( Register s1, Register s2, int crd) { v8_only(); emit_long( op(ldst_op) | fcn(crd) | op3(ldcsr_op3) | rs1(s1) | rs2(s2) ); } 116inline void Assembler::ldcsr( Register s1, int simm13a, int crd) { v8_only(); emit_data( op(ldst_op) | fcn(crd) | op3(ldcsr_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 117 118inline void Assembler::ldsb( Register s1, Register s2, Register d) { emit_long( op(ldst_op) | rd(d) | op3(ldsb_op3) | rs1(s1) | rs2(s2) ); } 119inline void Assembler::ldsb( Register s1, int simm13a, Register d) { emit_data( op(ldst_op) | rd(d) | op3(ldsb_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 120 121inline void Assembler::ldsh( Register s1, Register s2, Register d) { emit_long( op(ldst_op) | rd(d) | op3(ldsh_op3) | rs1(s1) | rs2(s2) ); } 122inline void Assembler::ldsh( Register s1, int simm13a, Register d) { emit_data( op(ldst_op) | rd(d) | op3(ldsh_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 123inline void Assembler::ldsw( Register s1, Register s2, Register d) { emit_long( op(ldst_op) | rd(d) | op3(ldsw_op3) | rs1(s1) | rs2(s2) ); } 124inline void Assembler::ldsw( Register s1, int simm13a, Register d) { emit_data( op(ldst_op) | rd(d) | op3(ldsw_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 125inline void Assembler::ldub( Register s1, Register s2, Register d) { emit_long( op(ldst_op) | rd(d) | op3(ldub_op3) | rs1(s1) | rs2(s2) ); } 126inline void Assembler::ldub( Register s1, int simm13a, Register d) { emit_data( op(ldst_op) | rd(d) | op3(ldub_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 127inline void Assembler::lduh( Register s1, Register s2, Register d) { emit_long( op(ldst_op) | rd(d) | op3(lduh_op3) | rs1(s1) | rs2(s2) ); } 128inline void Assembler::lduh( Register s1, int simm13a, Register d) { emit_data( op(ldst_op) | rd(d) | op3(lduh_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 129inline void Assembler::lduw( Register s1, Register s2, Register d) { emit_long( op(ldst_op) | rd(d) | op3(lduw_op3) | rs1(s1) | rs2(s2) ); } 130inline void Assembler::lduw( Register s1, int simm13a, Register d) { emit_data( op(ldst_op) | rd(d) | op3(lduw_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 131 132inline void Assembler::ldx( Register s1, Register s2, Register d) { v9_only(); emit_long( op(ldst_op) | rd(d) | op3(ldx_op3) | rs1(s1) | rs2(s2) ); } 133inline void Assembler::ldx( Register s1, int simm13a, Register d) { v9_only(); emit_data( op(ldst_op) | rd(d) | op3(ldx_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 134inline void Assembler::ldd( Register s1, Register s2, Register d) { v9_dep(); assert(d->is_even(), "not even"); emit_long( op(ldst_op) | rd(d) | op3(ldd_op3) | rs1(s1) | rs2(s2) ); } 135inline void Assembler::ldd( Register s1, int simm13a, Register d) { v9_dep(); assert(d->is_even(), "not even"); emit_data( op(ldst_op) | rd(d) | op3(ldd_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 136 137#ifdef _LP64 138// Make all 32 bit loads signed so 64 bit registers maintain proper sign 139inline void Assembler::ld( Register s1, Register s2, Register d) { ldsw( s1, s2, d); } 140inline void Assembler::ld( Register s1, int simm13a, Register d) { ldsw( s1, simm13a, d); } 141#else 142inline void Assembler::ld( Register s1, Register s2, Register d) { lduw( s1, s2, d); } 143inline void Assembler::ld( Register s1, int simm13a, Register d) { lduw( s1, simm13a, d); } 144#endif 145 146inline void Assembler::ldub( Register s1, RegisterOrConstant s2, Register d) { 147 if (s2.is_register()) ldsb(s1, s2.as_register(), d); 148 else ldsb(s1, s2.as_constant(), d); 149} 150inline void Assembler::ldsb( Register s1, RegisterOrConstant s2, Register d) { 151 if (s2.is_register()) ldsb(s1, s2.as_register(), d); 152 else ldsb(s1, s2.as_constant(), d); 153} 154inline void Assembler::lduh( Register s1, RegisterOrConstant s2, Register d) { 155 if (s2.is_register()) ldsh(s1, s2.as_register(), d); 156 else ldsh(s1, s2.as_constant(), d); 157} 158inline void Assembler::ldsh( Register s1, RegisterOrConstant s2, Register d) { 159 if (s2.is_register()) ldsh(s1, s2.as_register(), d); 160 else ldsh(s1, s2.as_constant(), d); 161} 162inline void Assembler::lduw( Register s1, RegisterOrConstant s2, Register d) { 163 if (s2.is_register()) ldsw(s1, s2.as_register(), d); 164 else ldsw(s1, s2.as_constant(), d); 165} 166inline void Assembler::ldsw( Register s1, RegisterOrConstant s2, Register d) { 167 if (s2.is_register()) ldsw(s1, s2.as_register(), d); 168 else ldsw(s1, s2.as_constant(), d); 169} 170inline void Assembler::ldx( Register s1, RegisterOrConstant s2, Register d) { 171 if (s2.is_register()) ldx(s1, s2.as_register(), d); 172 else ldx(s1, s2.as_constant(), d); 173} 174inline void Assembler::ld( Register s1, RegisterOrConstant s2, Register d) { 175 if (s2.is_register()) ld(s1, s2.as_register(), d); 176 else ld(s1, s2.as_constant(), d); 177} 178inline void Assembler::ldd( Register s1, RegisterOrConstant s2, Register d) { 179 if (s2.is_register()) ldd(s1, s2.as_register(), d); 180 else ldd(s1, s2.as_constant(), d); 181} 182 183// form effective addresses this way: 184inline void Assembler::add( Register s1, RegisterOrConstant s2, Register d, int offset) { 185 if (s2.is_register()) add(s1, s2.as_register(), d); 186 else { add(s1, s2.as_constant() + offset, d); offset = 0; } 187 if (offset != 0) add(d, offset, d); 188} 189 190inline void Assembler::ld( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); ld( a.base(), a.disp() + offset, d ); } 191inline void Assembler::ldsb( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); ldsb( a.base(), a.disp() + offset, d ); } 192inline void Assembler::ldsh( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); ldsh( a.base(), a.disp() + offset, d ); } 193inline void Assembler::ldsw( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); ldsw( a.base(), a.disp() + offset, d ); } 194inline void Assembler::ldub( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); ldub( a.base(), a.disp() + offset, d ); } 195inline void Assembler::lduh( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); lduh( a.base(), a.disp() + offset, d ); } 196inline void Assembler::lduw( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); lduw( a.base(), a.disp() + offset, d ); } 197inline void Assembler::ldd( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); ldd( a.base(), a.disp() + offset, d ); } 198inline void Assembler::ldx( const Address& a, Register d, int offset ) { relocate(a.rspec(offset)); ldx( a.base(), a.disp() + offset, d ); } 199 200 201inline void Assembler::ldstub( Register s1, Register s2, Register d) { emit_long( op(ldst_op) | rd(d) | op3(ldstub_op3) | rs1(s1) | rs2(s2) ); } 202inline void Assembler::ldstub( Register s1, int simm13a, Register d) { emit_data( op(ldst_op) | rd(d) | op3(ldstub_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 203 204 205inline void Assembler::prefetch(Register s1, Register s2, PrefetchFcn f) { v9_only(); emit_long( op(ldst_op) | fcn(f) | op3(prefetch_op3) | rs1(s1) | rs2(s2) ); } 206inline void Assembler::prefetch(Register s1, int simm13a, PrefetchFcn f) { v9_only(); emit_data( op(ldst_op) | fcn(f) | op3(prefetch_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 207 208inline void Assembler::prefetch(const Address& a, PrefetchFcn f, int offset) { v9_only(); relocate(a.rspec(offset)); prefetch(a.base(), a.disp() + offset, f); } 209 210 211inline void Assembler::rett( Register s1, Register s2 ) { emit_long( op(arith_op) | op3(rett_op3) | rs1(s1) | rs2(s2)); has_delay_slot(); } 212inline void Assembler::rett( Register s1, int simm13a, relocInfo::relocType rt) { emit_data( op(arith_op) | op3(rett_op3) | rs1(s1) | immed(true) | simm(simm13a, 13), rt); has_delay_slot(); } 213 214inline void Assembler::sethi( int imm22a, Register d, RelocationHolder const& rspec ) { emit_data( op(branch_op) | rd(d) | op2(sethi_op2) | hi22(imm22a), rspec); } 215 216 // pp 222 217 218inline void Assembler::stf( FloatRegisterImpl::Width w, FloatRegister d, Register s1, Register s2) { emit_long( op(ldst_op) | fd(d, w) | alt_op3(stf_op3, w) | rs1(s1) | rs2(s2) ); } 219inline void Assembler::stf( FloatRegisterImpl::Width w, FloatRegister d, Register s1, int simm13a) { emit_data( op(ldst_op) | fd(d, w) | alt_op3(stf_op3, w) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 220 221inline void Assembler::stf( FloatRegisterImpl::Width w, FloatRegister d, const Address& a, int offset) { relocate(a.rspec(offset)); stf(w, d, a.base(), a.disp() + offset); } 222 223inline void Assembler::stfsr( Register s1, Register s2) { v9_dep(); emit_long( op(ldst_op) | op3(stfsr_op3) | rs1(s1) | rs2(s2) ); } 224inline void Assembler::stfsr( Register s1, int simm13a) { v9_dep(); emit_data( op(ldst_op) | op3(stfsr_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 225inline void Assembler::stxfsr( Register s1, Register s2) { v9_only(); emit_long( op(ldst_op) | rd(G1) | op3(stfsr_op3) | rs1(s1) | rs2(s2) ); } 226inline void Assembler::stxfsr( Register s1, int simm13a) { v9_only(); emit_data( op(ldst_op) | rd(G1) | op3(stfsr_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 227 228 // p 226 229 230inline void Assembler::stb( Register d, Register s1, Register s2) { emit_long( op(ldst_op) | rd(d) | op3(stb_op3) | rs1(s1) | rs2(s2) ); } 231inline void Assembler::stb( Register d, Register s1, int simm13a) { emit_data( op(ldst_op) | rd(d) | op3(stb_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 232inline void Assembler::sth( Register d, Register s1, Register s2) { emit_long( op(ldst_op) | rd(d) | op3(sth_op3) | rs1(s1) | rs2(s2) ); } 233inline void Assembler::sth( Register d, Register s1, int simm13a) { emit_data( op(ldst_op) | rd(d) | op3(sth_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 234inline void Assembler::stw( Register d, Register s1, Register s2) { emit_long( op(ldst_op) | rd(d) | op3(stw_op3) | rs1(s1) | rs2(s2) ); } 235inline void Assembler::stw( Register d, Register s1, int simm13a) { emit_data( op(ldst_op) | rd(d) | op3(stw_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 236 237 238inline void Assembler::stx( Register d, Register s1, Register s2) { v9_only(); emit_long( op(ldst_op) | rd(d) | op3(stx_op3) | rs1(s1) | rs2(s2) ); } 239inline void Assembler::stx( Register d, Register s1, int simm13a) { v9_only(); emit_data( op(ldst_op) | rd(d) | op3(stx_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 240inline void Assembler::std( Register d, Register s1, Register s2) { v9_dep(); assert(d->is_even(), "not even"); emit_long( op(ldst_op) | rd(d) | op3(std_op3) | rs1(s1) | rs2(s2) ); } 241inline void Assembler::std( Register d, Register s1, int simm13a) { v9_dep(); assert(d->is_even(), "not even"); emit_data( op(ldst_op) | rd(d) | op3(std_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 242 243inline void Assembler::st( Register d, Register s1, Register s2) { stw(d, s1, s2); } 244inline void Assembler::st( Register d, Register s1, int simm13a) { stw(d, s1, simm13a); } 245 246inline void Assembler::stb( Register d, Register s1, RegisterOrConstant s2) { 247 if (s2.is_register()) stb(d, s1, s2.as_register()); 248 else stb(d, s1, s2.as_constant()); 249} 250inline void Assembler::sth( Register d, Register s1, RegisterOrConstant s2) { 251 if (s2.is_register()) sth(d, s1, s2.as_register()); 252 else sth(d, s1, s2.as_constant()); 253} 254inline void Assembler::stx( Register d, Register s1, RegisterOrConstant s2) { 255 if (s2.is_register()) stx(d, s1, s2.as_register()); 256 else stx(d, s1, s2.as_constant()); 257} 258inline void Assembler::std( Register d, Register s1, RegisterOrConstant s2) { 259 if (s2.is_register()) std(d, s1, s2.as_register()); 260 else std(d, s1, s2.as_constant()); 261} 262inline void Assembler::st( Register d, Register s1, RegisterOrConstant s2) { 263 if (s2.is_register()) st(d, s1, s2.as_register()); 264 else st(d, s1, s2.as_constant()); 265} 266 267inline void Assembler::stb( Register d, const Address& a, int offset) { relocate(a.rspec(offset)); stb( d, a.base(), a.disp() + offset); } 268inline void Assembler::sth( Register d, const Address& a, int offset) { relocate(a.rspec(offset)); sth( d, a.base(), a.disp() + offset); } 269inline void Assembler::stw( Register d, const Address& a, int offset) { relocate(a.rspec(offset)); stw( d, a.base(), a.disp() + offset); } 270inline void Assembler::st( Register d, const Address& a, int offset) { relocate(a.rspec(offset)); st( d, a.base(), a.disp() + offset); } 271inline void Assembler::std( Register d, const Address& a, int offset) { relocate(a.rspec(offset)); std( d, a.base(), a.disp() + offset); } 272inline void Assembler::stx( Register d, const Address& a, int offset) { relocate(a.rspec(offset)); stx( d, a.base(), a.disp() + offset); } 273 274// v8 p 99 275 276inline void Assembler::stc( int crd, Register s1, Register s2) { v8_only(); emit_long( op(ldst_op) | fcn(crd) | op3(stc_op3 ) | rs1(s1) | rs2(s2) ); } 277inline void Assembler::stc( int crd, Register s1, int simm13a) { v8_only(); emit_data( op(ldst_op) | fcn(crd) | op3(stc_op3 ) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 278inline void Assembler::stdc( int crd, Register s1, Register s2) { v8_only(); emit_long( op(ldst_op) | fcn(crd) | op3(stdc_op3) | rs1(s1) | rs2(s2) ); } 279inline void Assembler::stdc( int crd, Register s1, int simm13a) { v8_only(); emit_data( op(ldst_op) | fcn(crd) | op3(stdc_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 280inline void Assembler::stcsr( int crd, Register s1, Register s2) { v8_only(); emit_long( op(ldst_op) | fcn(crd) | op3(stcsr_op3) | rs1(s1) | rs2(s2) ); } 281inline void Assembler::stcsr( int crd, Register s1, int simm13a) { v8_only(); emit_data( op(ldst_op) | fcn(crd) | op3(stcsr_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 282inline void Assembler::stdcq( int crd, Register s1, Register s2) { v8_only(); emit_long( op(ldst_op) | fcn(crd) | op3(stdcq_op3) | rs1(s1) | rs2(s2) ); } 283inline void Assembler::stdcq( int crd, Register s1, int simm13a) { v8_only(); emit_data( op(ldst_op) | fcn(crd) | op3(stdcq_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 284 285 286// pp 231 287 288inline void Assembler::swap( Register s1, Register s2, Register d) { v9_dep(); emit_long( op(ldst_op) | rd(d) | op3(swap_op3) | rs1(s1) | rs2(s2) ); } 289inline void Assembler::swap( Register s1, int simm13a, Register d) { v9_dep(); emit_data( op(ldst_op) | rd(d) | op3(swap_op3) | rs1(s1) | immed(true) | simm(simm13a, 13)); } 290 291inline void Assembler::swap( Address& a, Register d, int offset ) { relocate(a.rspec(offset)); swap( a.base(), a.disp() + offset, d ); } 292 293 294// Use the right loads/stores for the platform 295inline void MacroAssembler::ld_ptr( Register s1, Register s2, Register d ) { 296#ifdef _LP64 297 Assembler::ldx( s1, s2, d); 298#else 299 Assembler::ld( s1, s2, d); 300#endif 301} 302 303inline void MacroAssembler::ld_ptr( Register s1, int simm13a, Register d ) { 304#ifdef _LP64 305 Assembler::ldx( s1, simm13a, d); 306#else 307 Assembler::ld( s1, simm13a, d); 308#endif 309} 310 311inline void MacroAssembler::ld_ptr( Register s1, RegisterOrConstant s2, Register d ) { 312#ifdef _LP64 313 Assembler::ldx( s1, s2, d); 314#else 315 Assembler::ld( s1, s2, d); 316#endif 317} 318 319inline void MacroAssembler::ld_ptr( const Address& a, Register d, int offset ) { 320#ifdef _LP64 321 Assembler::ldx( a, d, offset ); 322#else 323 Assembler::ld( a, d, offset ); 324#endif 325} 326 327inline void MacroAssembler::st_ptr( Register d, Register s1, Register s2 ) { 328#ifdef _LP64 329 Assembler::stx( d, s1, s2); 330#else 331 Assembler::st( d, s1, s2); 332#endif 333} 334 335inline void MacroAssembler::st_ptr( Register d, Register s1, int simm13a ) { 336#ifdef _LP64 337 Assembler::stx( d, s1, simm13a); 338#else 339 Assembler::st( d, s1, simm13a); 340#endif 341} 342 343inline void MacroAssembler::st_ptr( Register d, Register s1, RegisterOrConstant s2 ) { 344#ifdef _LP64 345 Assembler::stx( d, s1, s2); 346#else 347 Assembler::st( d, s1, s2); 348#endif 349} 350 351inline void MacroAssembler::st_ptr( Register d, const Address& a, int offset) { 352#ifdef _LP64 353 Assembler::stx( d, a, offset); 354#else 355 Assembler::st( d, a, offset); 356#endif 357} 358 359// Use the right loads/stores for the platform 360inline void MacroAssembler::ld_long( Register s1, Register s2, Register d ) { 361#ifdef _LP64 362 Assembler::ldx(s1, s2, d); 363#else 364 Assembler::ldd(s1, s2, d); 365#endif 366} 367 368inline void MacroAssembler::ld_long( Register s1, int simm13a, Register d ) { 369#ifdef _LP64 370 Assembler::ldx(s1, simm13a, d); 371#else 372 Assembler::ldd(s1, simm13a, d); 373#endif 374} 375 376inline void MacroAssembler::ld_long( Register s1, RegisterOrConstant s2, Register d ) { 377#ifdef _LP64 378 Assembler::ldx(s1, s2, d); 379#else 380 Assembler::ldd(s1, s2, d); 381#endif 382} 383 384inline void MacroAssembler::ld_long( const Address& a, Register d, int offset ) { 385#ifdef _LP64 386 Assembler::ldx(a, d, offset ); 387#else 388 Assembler::ldd(a, d, offset ); 389#endif 390} 391 392inline void MacroAssembler::st_long( Register d, Register s1, Register s2 ) { 393#ifdef _LP64 394 Assembler::stx(d, s1, s2); 395#else 396 Assembler::std(d, s1, s2); 397#endif 398} 399 400inline void MacroAssembler::st_long( Register d, Register s1, int simm13a ) { 401#ifdef _LP64 402 Assembler::stx(d, s1, simm13a); 403#else 404 Assembler::std(d, s1, simm13a); 405#endif 406} 407 408inline void MacroAssembler::st_long( Register d, Register s1, RegisterOrConstant s2 ) { 409#ifdef _LP64 410 Assembler::stx(d, s1, s2); 411#else 412 Assembler::std(d, s1, s2); 413#endif 414} 415 416inline void MacroAssembler::st_long( Register d, const Address& a, int offset ) { 417#ifdef _LP64 418 Assembler::stx(d, a, offset); 419#else 420 Assembler::std(d, a, offset); 421#endif 422} 423 424// Functions for isolating 64 bit shifts for LP64 425 426inline void MacroAssembler::sll_ptr( Register s1, Register s2, Register d ) { 427#ifdef _LP64 428 Assembler::sllx(s1, s2, d); 429#else 430 Assembler::sll(s1, s2, d); 431#endif 432} 433 434inline void MacroAssembler::sll_ptr( Register s1, int imm6a, Register d ) { 435#ifdef _LP64 436 Assembler::sllx(s1, imm6a, d); 437#else 438 Assembler::sll(s1, imm6a, d); 439#endif 440} 441 442inline void MacroAssembler::srl_ptr( Register s1, Register s2, Register d ) { 443#ifdef _LP64 444 Assembler::srlx(s1, s2, d); 445#else 446 Assembler::srl(s1, s2, d); 447#endif 448} 449 450inline void MacroAssembler::srl_ptr( Register s1, int imm6a, Register d ) { 451#ifdef _LP64 452 Assembler::srlx(s1, imm6a, d); 453#else 454 Assembler::srl(s1, imm6a, d); 455#endif 456} 457 458inline void MacroAssembler::sll_ptr( Register s1, RegisterOrConstant s2, Register d ) { 459 if (s2.is_register()) sll_ptr(s1, s2.as_register(), d); 460 else sll_ptr(s1, s2.as_constant(), d); 461} 462 463// Use the right branch for the platform 464 465inline void MacroAssembler::br( Condition c, bool a, Predict p, address d, relocInfo::relocType rt ) { 466 if (VM_Version::v9_instructions_work()) 467 Assembler::bp(c, a, icc, p, d, rt); 468 else 469 Assembler::br(c, a, d, rt); 470} 471 472inline void MacroAssembler::br( Condition c, bool a, Predict p, Label& L ) { 473 br(c, a, p, target(L)); 474} 475 476 477// Branch that tests either xcc or icc depending on the 478// architecture compiled (LP64 or not) 479inline void MacroAssembler::brx( Condition c, bool a, Predict p, address d, relocInfo::relocType rt ) { 480#ifdef _LP64 481 Assembler::bp(c, a, xcc, p, d, rt); 482#else 483 MacroAssembler::br(c, a, p, d, rt); 484#endif 485} 486 487inline void MacroAssembler::brx( Condition c, bool a, Predict p, Label& L ) { 488 brx(c, a, p, target(L)); 489} 490 491inline void MacroAssembler::ba( bool a, Label& L ) { 492 br(always, a, pt, L); 493} 494 495// Warning: V9 only functions 496inline void MacroAssembler::bp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt ) { 497 Assembler::bp(c, a, cc, p, d, rt); 498} 499 500inline void MacroAssembler::bp( Condition c, bool a, CC cc, Predict p, Label& L ) { 501 Assembler::bp(c, a, cc, p, L); 502} 503 504inline void MacroAssembler::fb( Condition c, bool a, Predict p, address d, relocInfo::relocType rt ) { 505 if (VM_Version::v9_instructions_work()) 506 fbp(c, a, fcc0, p, d, rt); 507 else 508 Assembler::fb(c, a, d, rt); 509} 510 511inline void MacroAssembler::fb( Condition c, bool a, Predict p, Label& L ) { 512 fb(c, a, p, target(L)); 513} 514 515inline void MacroAssembler::fbp( Condition c, bool a, CC cc, Predict p, address d, relocInfo::relocType rt ) { 516 Assembler::fbp(c, a, cc, p, d, rt); 517} 518 519inline void MacroAssembler::fbp( Condition c, bool a, CC cc, Predict p, Label& L ) { 520 Assembler::fbp(c, a, cc, p, L); 521} 522 523inline void MacroAssembler::jmp( Register s1, Register s2 ) { jmpl( s1, s2, G0 ); } 524inline void MacroAssembler::jmp( Register s1, int simm13a, RelocationHolder const& rspec ) { jmpl( s1, simm13a, G0, rspec); } 525 526// Call with a check to see if we need to deal with the added 527// expense of relocation and if we overflow the displacement 528// of the quick call instruction./ 529// Check to see if we have to deal with relocations 530inline void MacroAssembler::call( address d, relocInfo::relocType rt ) { 531#ifdef _LP64 532 intptr_t disp; 533 // NULL is ok because it will be relocated later. 534 // Must change NULL to a reachable address in order to 535 // pass asserts here and in wdisp. 536 if ( d == NULL ) 537 d = pc(); 538 539 // Is this address within range of the call instruction? 540 // If not, use the expensive instruction sequence 541 disp = (intptr_t)d - (intptr_t)pc(); 542 if ( disp != (intptr_t)(int32_t)disp ) { 543 relocate(rt); 544 Address dest(O7, (address)d); 545 sethi(dest, /*ForceRelocatable=*/ true); 546 jmpl(dest, O7); 547 } 548 else { 549 Assembler::call( d, rt ); 550 } 551#else 552 Assembler::call( d, rt ); 553#endif 554} 555 556inline void MacroAssembler::call( Label& L, relocInfo::relocType rt ) { 557 MacroAssembler::call( target(L), rt); 558} 559 560 561 562inline void MacroAssembler::callr( Register s1, Register s2 ) { jmpl( s1, s2, O7 ); } 563inline void MacroAssembler::callr( Register s1, int simm13a, RelocationHolder const& rspec ) { jmpl( s1, simm13a, O7, rspec); } 564 565// prefetch instruction 566inline void MacroAssembler::iprefetch( address d, relocInfo::relocType rt ) { 567 if (VM_Version::v9_instructions_work()) 568 Assembler::bp( never, true, xcc, pt, d, rt ); 569} 570inline void MacroAssembler::iprefetch( Label& L) { iprefetch( target(L) ); } 571 572 573// clobbers o7 on V8!! 574// returns delta from gotten pc to addr after 575inline int MacroAssembler::get_pc( Register d ) { 576 int x = offset(); 577 if (VM_Version::v9_instructions_work()) 578 rdpc(d); 579 else { 580 Label lbl; 581 Assembler::call(lbl, relocInfo::none); // No relocation as this is call to pc+0x8 582 if (d == O7) delayed()->nop(); 583 else delayed()->mov(O7, d); 584 bind(lbl); 585 } 586 return offset() - x; 587} 588 589 590// Note: All MacroAssembler::set_foo functions are defined out-of-line. 591 592 593// Loads the current PC of the following instruction as an immediate value in 594// 2 instructions. All PCs in the CodeCache are within 2 Gig of each other. 595inline intptr_t MacroAssembler::load_pc_address( Register reg, int bytes_to_skip ) { 596 intptr_t thepc = (intptr_t)pc() + 2*BytesPerInstWord + bytes_to_skip; 597#ifdef _LP64 598 Unimplemented(); 599#else 600 Assembler::sethi( thepc & ~0x3ff, reg, internal_word_Relocation::spec((address)thepc)); 601 Assembler::add(reg,thepc & 0x3ff, reg, internal_word_Relocation::spec((address)thepc)); 602#endif 603 return thepc; 604} 605 606inline void MacroAssembler::load_address( Address& a, int offset ) { 607 assert_not_delayed(); 608#ifdef _LP64 609 sethi(a); 610 add(a, a.base(), offset); 611#else 612 if (a.hi() == 0 && a.rtype() == relocInfo::none) { 613 set(a.disp() + offset, a.base()); 614 } 615 else { 616 sethi(a); 617 add(a, a.base(), offset); 618 } 619#endif 620} 621 622 623inline void MacroAssembler::split_disp( Address& a, Register temp ) { 624 assert_not_delayed(); 625 a = a.split_disp(); 626 Assembler::sethi(a.hi(), temp, a.rspec()); 627 add(a.base(), temp, a.base()); 628} 629 630 631inline void MacroAssembler::load_contents( Address& a, Register d, int offset ) { 632 assert_not_delayed(); 633 sethi(a); 634 ld(a, d, offset); 635} 636 637 638inline void MacroAssembler::load_ptr_contents( Address& a, Register d, int offset ) { 639 assert_not_delayed(); 640 sethi(a); 641 ld_ptr(a, d, offset); 642} 643 644 645inline void MacroAssembler::store_contents( Register s, Address& a, int offset ) { 646 assert_not_delayed(); 647 sethi(a); 648 st(s, a, offset); 649} 650 651 652inline void MacroAssembler::store_ptr_contents( Register s, Address& a, int offset ) { 653 assert_not_delayed(); 654 sethi(a); 655 st_ptr(s, a, offset); 656} 657 658 659// This code sequence is relocatable to any address, even on LP64. 660inline void MacroAssembler::jumpl_to( Address& a, Register d, int offset ) { 661 assert_not_delayed(); 662 // Force fixed length sethi because NativeJump and NativeFarCall don't handle 663 // variable length instruction streams. 664 sethi(a, /*ForceRelocatable=*/ true); 665 jmpl(a, d, offset); 666} 667 668 669inline void MacroAssembler::jump_to( Address& a, int offset ) { 670 jumpl_to( a, G0, offset ); 671} 672 673 674inline void MacroAssembler::jump_indirect_to( Address& a, Register temp, 675 int ld_offset, int jmp_offset ) { 676 assert_not_delayed(); 677 //sethi(a); // sethi is caller responsibility for this one 678 ld_ptr(a, temp, ld_offset); 679 jmp(temp, jmp_offset); 680} 681 682 683inline void MacroAssembler::set_oop( jobject obj, Register d ) { 684 set_oop(allocate_oop_address(obj, d)); 685} 686 687 688inline void MacroAssembler::set_oop_constant( jobject obj, Register d ) { 689 set_oop(constant_oop_address(obj, d)); 690} 691 692 693inline void MacroAssembler::set_oop( Address obj_addr ) { 694 assert(obj_addr.rspec().type()==relocInfo::oop_type, "must be an oop reloc"); 695 load_address(obj_addr); 696} 697 698 699inline void MacroAssembler::load_argument( Argument& a, Register d ) { 700 if (a.is_register()) 701 mov(a.as_register(), d); 702 else 703 ld (a.as_address(), d); 704} 705 706inline void MacroAssembler::store_argument( Register s, Argument& a ) { 707 if (a.is_register()) 708 mov(s, a.as_register()); 709 else 710 st_ptr (s, a.as_address()); // ABI says everything is right justified. 711} 712 713inline void MacroAssembler::store_ptr_argument( Register s, Argument& a ) { 714 if (a.is_register()) 715 mov(s, a.as_register()); 716 else 717 st_ptr (s, a.as_address()); 718} 719 720 721#ifdef _LP64 722inline void MacroAssembler::store_float_argument( FloatRegister s, Argument& a ) { 723 if (a.is_float_register()) 724// V9 ABI has F1, F3, F5 are used to pass instead of O0, O1, O2 725 fmov(FloatRegisterImpl::S, s, a.as_float_register() ); 726 else 727 // Floats are stored in the high half of the stack entry 728 // The low half is undefined per the ABI. 729 stf(FloatRegisterImpl::S, s, a.as_address(), sizeof(jfloat)); 730} 731 732inline void MacroAssembler::store_double_argument( FloatRegister s, Argument& a ) { 733 if (a.is_float_register()) 734// V9 ABI has D0, D2, D4 are used to pass instead of O0, O1, O2 735 fmov(FloatRegisterImpl::D, s, a.as_double_register() ); 736 else 737 stf(FloatRegisterImpl::D, s, a.as_address()); 738} 739 740inline void MacroAssembler::store_long_argument( Register s, Argument& a ) { 741 if (a.is_register()) 742 mov(s, a.as_register()); 743 else 744 stx(s, a.as_address()); 745} 746#endif 747 748inline void MacroAssembler::clrb( Register s1, Register s2) { stb( G0, s1, s2 ); } 749inline void MacroAssembler::clrh( Register s1, Register s2) { sth( G0, s1, s2 ); } 750inline void MacroAssembler::clr( Register s1, Register s2) { stw( G0, s1, s2 ); } 751inline void MacroAssembler::clrx( Register s1, Register s2) { stx( G0, s1, s2 ); } 752 753inline void MacroAssembler::clrb( Register s1, int simm13a) { stb( G0, s1, simm13a); } 754inline void MacroAssembler::clrh( Register s1, int simm13a) { sth( G0, s1, simm13a); } 755inline void MacroAssembler::clr( Register s1, int simm13a) { stw( G0, s1, simm13a); } 756inline void MacroAssembler::clrx( Register s1, int simm13a) { stx( G0, s1, simm13a); } 757 758// returns if membar generates anything, obviously this code should mirror 759// membar below. 760inline bool MacroAssembler::membar_has_effect( Membar_mask_bits const7a ) { 761 if( !os::is_MP() ) return false; // Not needed on single CPU 762 if( VM_Version::v9_instructions_work() ) { 763 const Membar_mask_bits effective_mask = 764 Membar_mask_bits(const7a & ~(LoadLoad | LoadStore | StoreStore)); 765 return (effective_mask != 0); 766 } else { 767 return true; 768 } 769} 770 771inline void MacroAssembler::membar( Membar_mask_bits const7a ) { 772 // Uniprocessors do not need memory barriers 773 if (!os::is_MP()) return; 774 // Weakened for current Sparcs and TSO. See the v9 manual, sections 8.4.3, 775 // 8.4.4.3, a.31 and a.50. 776 if( VM_Version::v9_instructions_work() ) { 777 // Under TSO, setting bit 3, 2, or 0 is redundant, so the only value 778 // of the mmask subfield of const7a that does anything that isn't done 779 // implicitly is StoreLoad. 780 const Membar_mask_bits effective_mask = 781 Membar_mask_bits(const7a & ~(LoadLoad | LoadStore | StoreStore)); 782 if ( effective_mask != 0 ) { 783 Assembler::membar( effective_mask ); 784 } 785 } else { 786 // stbar is the closest there is on v8. Equivalent to membar(StoreStore). We 787 // do not issue the stbar because to my knowledge all v8 machines implement TSO, 788 // which guarantees that all stores behave as if an stbar were issued just after 789 // each one of them. On these machines, stbar ought to be a nop. There doesn't 790 // appear to be an equivalent of membar(StoreLoad) on v8: TSO doesn't require it, 791 // it can't be specified by stbar, nor have I come up with a way to simulate it. 792 // 793 // Addendum. Dave says that ldstub guarantees a write buffer flush to coherent 794 // space. Put one here to be on the safe side. 795 Assembler::ldstub(SP, 0, G0); 796 } 797} 798