Thu, 24 May 2018 19:49:50 +0800
some C1 fix
Contributed-by: chenhaoxuan, zhaixiang, aoqi
aoqi@1 | 1 | /* |
aoqi@1 | 2 | * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. |
aoqi@1 | 3 | * Copyright (c) 2015, 2016, Loongson Technology. All rights reserved. |
aoqi@1 | 4 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
aoqi@1 | 5 | * |
aoqi@1 | 6 | * This code is free software; you can redistribute it and/or modify it |
aoqi@1 | 7 | * under the terms of the GNU General Public License version 2 only, as |
aoqi@1 | 8 | * published by the Free Software Foundation. |
aoqi@1 | 9 | * |
aoqi@1 | 10 | * This code is distributed in the hope that it will be useful, but WITHOUT |
aoqi@1 | 11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
aoqi@1 | 12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
aoqi@1 | 13 | * version 2 for more details (a copy is included in the LICENSE file that |
aoqi@1 | 14 | * accompanied this code). |
aoqi@1 | 15 | * |
aoqi@1 | 16 | * You should have received a copy of the GNU General Public License version |
aoqi@1 | 17 | * 2 along with this work; if not, write to the Free Software Foundation, |
aoqi@1 | 18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
aoqi@1 | 19 | * |
aoqi@1 | 20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
aoqi@1 | 21 | * or visit www.oracle.com if you need additional information or have any |
aoqi@1 | 22 | * questions. |
aoqi@1 | 23 | * |
aoqi@1 | 24 | */ |
aoqi@1 | 25 | |
aoqi@1 | 26 | #include "precompiled.hpp" |
aoqi@1 | 27 | #include "asm/macroAssembler.hpp" |
aoqi@1 | 28 | #include "asm/macroAssembler.inline.hpp" |
aoqi@1 | 29 | #include "c1/c1_Compilation.hpp" |
aoqi@1 | 30 | #include "c1/c1_LIRAssembler.hpp" |
aoqi@1 | 31 | #include "c1/c1_MacroAssembler.hpp" |
aoqi@1 | 32 | #include "c1/c1_Runtime1.hpp" |
aoqi@1 | 33 | #include "c1/c1_ValueStack.hpp" |
aoqi@1 | 34 | #include "ci/ciArrayKlass.hpp" |
aoqi@1 | 35 | #include "ci/ciInstance.hpp" |
aoqi@1 | 36 | #include "gc_interface/collectedHeap.hpp" |
aoqi@1 | 37 | #include "memory/barrierSet.hpp" |
aoqi@1 | 38 | #include "memory/cardTableModRefBS.hpp" |
aoqi@1 | 39 | #include "nativeInst_mips.hpp" |
aoqi@1 | 40 | #include "oops/objArrayKlass.hpp" |
aoqi@1 | 41 | #include "runtime/sharedRuntime.hpp" |
aoqi@1 | 42 | #define __ _masm-> |
aoqi@1 | 43 | |
aoqi@1 | 44 | static void select_different_registers(Register preserve, |
aoqi@6880 | 45 | Register extra, |
aoqi@6880 | 46 | Register &tmp1, |
aoqi@6880 | 47 | Register &tmp2) { |
aoqi@6880 | 48 | if (tmp1 == preserve) { |
aoqi@6880 | 49 | assert_different_registers(tmp1, tmp2, extra); |
aoqi@6880 | 50 | tmp1 = extra; |
aoqi@6880 | 51 | } else if (tmp2 == preserve) { |
aoqi@6880 | 52 | assert_different_registers(tmp1, tmp2, extra); |
aoqi@6880 | 53 | tmp2 = extra; |
aoqi@6880 | 54 | } |
aoqi@6880 | 55 | assert_different_registers(preserve, tmp1, tmp2); |
aoqi@1 | 56 | } |
aoqi@1 | 57 | |
aoqi@1 | 58 | |
aoqi@1 | 59 | |
aoqi@1 | 60 | static void select_different_registers(Register preserve, |
aoqi@6880 | 61 | Register extra, |
aoqi@6880 | 62 | Register &tmp1, |
aoqi@6880 | 63 | Register &tmp2, |
aoqi@6880 | 64 | Register &tmp3) { |
aoqi@6880 | 65 | if (tmp1 == preserve) { |
aoqi@6880 | 66 | assert_different_registers(tmp1, tmp2, tmp3, extra); |
aoqi@6880 | 67 | tmp1 = extra; |
aoqi@6880 | 68 | } else if (tmp2 == preserve) { |
aoqi@6880 | 69 | tmp2 = extra; |
aoqi@6880 | 70 | } else if (tmp3 == preserve) { |
aoqi@6880 | 71 | assert_different_registers(tmp1, tmp2, tmp3, extra); |
aoqi@6880 | 72 | tmp3 = extra; |
aoqi@6880 | 73 | } |
aoqi@6880 | 74 | assert_different_registers(preserve, tmp1, tmp2, tmp3); |
aoqi@1 | 75 | } |
aoqi@1 | 76 | |
aoqi@1 | 77 | // need add method Assembler::is_simm16 in assembler_gs2.hpp |
aoqi@1 | 78 | bool LIR_Assembler::is_small_constant(LIR_Opr opr) { |
aoqi@6880 | 79 | if (opr->is_constant()) { |
aoqi@6880 | 80 | LIR_Const* constant = opr->as_constant_ptr(); |
aoqi@6880 | 81 | switch (constant->type()) { |
aoqi@6880 | 82 | case T_INT: { |
aoqi@6880 | 83 | jint value = constant->as_jint(); |
aoqi@6880 | 84 | return Assembler::is_simm16(value); |
aoqi@6880 | 85 | } |
aoqi@6880 | 86 | default: |
aoqi@6880 | 87 | return false; |
aoqi@6880 | 88 | } |
aoqi@6880 | 89 | } |
aoqi@6880 | 90 | return false; |
aoqi@1 | 91 | } |
aoqi@1 | 92 | |
aoqi@1 | 93 | //FIXME, which register should be used? |
aoqi@1 | 94 | LIR_Opr LIR_Assembler::receiverOpr() { |
aoqi@6880 | 95 | return FrameMap::_t0_oop_opr; |
aoqi@1 | 96 | } |
aoqi@1 | 97 | /* |
aoqi@1 | 98 | LIR_Opr LIR_Assembler::incomingReceiverOpr() { |
aoqi@6880 | 99 | return receiverOpr(); |
aoqi@1 | 100 | }*/ |
aoqi@1 | 101 | |
aoqi@1 | 102 | LIR_Opr LIR_Assembler::osrBufferPointer() { |
aoqi@1 | 103 | #ifdef _LP64 |
aoqi@1 | 104 | Register r = receiverOpr()->as_register(); |
aoqi@1 | 105 | return FrameMap::as_long_opr(r, r); |
aoqi@1 | 106 | #else |
aoqi@1 | 107 | return FrameMap::as_opr(receiverOpr()->as_register()); |
aoqi@1 | 108 | #endif |
aoqi@1 | 109 | } |
aoqi@1 | 110 | |
aoqi@1 | 111 | //--------------fpu register translations----------------------- |
aoqi@1 | 112 | // FIXME:I do not know what's to do for mips fpu |
aoqi@1 | 113 | |
aoqi@1 | 114 | address LIR_Assembler::float_constant(float f) { |
aoqi@6880 | 115 | address const_addr = __ float_constant(f); |
aoqi@6880 | 116 | if (const_addr == NULL) { |
aoqi@6880 | 117 | bailout("const section overflow"); |
aoqi@6880 | 118 | return __ code()->consts()->start(); |
aoqi@6880 | 119 | } else { |
aoqi@6880 | 120 | return const_addr; |
aoqi@6880 | 121 | } |
aoqi@1 | 122 | } |
aoqi@1 | 123 | |
aoqi@1 | 124 | |
aoqi@1 | 125 | address LIR_Assembler::double_constant(double d) { |
aoqi@6880 | 126 | address const_addr = __ double_constant(d); |
aoqi@6880 | 127 | if (const_addr == NULL) { |
aoqi@6880 | 128 | bailout("const section overflow"); |
aoqi@6880 | 129 | return __ code()->consts()->start(); |
aoqi@6880 | 130 | } else { |
aoqi@6880 | 131 | return const_addr; |
aoqi@6880 | 132 | } |
aoqi@1 | 133 | } |
aoqi@1 | 134 | |
aoqi@1 | 135 | |
aoqi@1 | 136 | |
aoqi@1 | 137 | |
aoqi@1 | 138 | |
aoqi@1 | 139 | void LIR_Assembler::reset_FPU() { |
aoqi@6880 | 140 | Unimplemented(); |
aoqi@1 | 141 | } |
aoqi@1 | 142 | |
aoqi@1 | 143 | |
aoqi@1 | 144 | void LIR_Assembler::set_24bit_FPU() { |
aoqi@6880 | 145 | Unimplemented(); |
aoqi@1 | 146 | } |
aoqi@1 | 147 | |
aoqi@1 | 148 | //FIXME. |
aoqi@1 | 149 | void LIR_Assembler::fpop() { |
aoqi@6880 | 150 | // do nothing |
aoqi@1 | 151 | } |
aoqi@1 | 152 | void LIR_Assembler::fxch(int i) { |
aoqi@6880 | 153 | // do nothing |
aoqi@1 | 154 | } |
aoqi@1 | 155 | void LIR_Assembler::fld(int i) { |
aoqi@6880 | 156 | // do nothing |
aoqi@1 | 157 | } |
aoqi@1 | 158 | void LIR_Assembler::ffree(int i) { |
aoqi@6880 | 159 | // do nothing |
aoqi@1 | 160 | } |
aoqi@1 | 161 | |
aoqi@1 | 162 | void LIR_Assembler::breakpoint() { |
aoqi@1 | 163 | __ brk(17); |
aoqi@1 | 164 | } |
aoqi@1 | 165 | //FIXME, opr can not be float? |
aoqi@1 | 166 | void LIR_Assembler::push(LIR_Opr opr) { |
aoqi@6880 | 167 | if (opr->is_single_cpu()) { |
aoqi@6880 | 168 | __ push_reg(opr->as_register()); |
aoqi@6880 | 169 | } else if (opr->is_double_cpu()) { |
aoqi@6880 | 170 | __ push_reg(opr->as_register_hi()); |
aoqi@6880 | 171 | __ push_reg(opr->as_register_lo()); |
aoqi@6880 | 172 | } else if (opr->is_stack()) { |
aoqi@6880 | 173 | __ push_addr(frame_map()->address_for_slot(opr->single_stack_ix())); |
aoqi@6880 | 174 | } else if (opr->is_constant()) { |
aoqi@6880 | 175 | LIR_Const* const_opr = opr->as_constant_ptr(); |
aoqi@6880 | 176 | if (const_opr->type() == T_OBJECT) { |
aoqi@6880 | 177 | __ push_oop(const_opr->as_jobject()); |
aoqi@6880 | 178 | } else if (const_opr->type() == T_INT) { |
aoqi@6880 | 179 | __ push_jint(const_opr->as_jint()); |
aoqi@6880 | 180 | } else { |
aoqi@6880 | 181 | ShouldNotReachHere(); |
aoqi@6880 | 182 | } |
aoqi@6880 | 183 | } else { |
aoqi@6880 | 184 | ShouldNotReachHere(); |
aoqi@6880 | 185 | } |
aoqi@1 | 186 | } |
aoqi@1 | 187 | |
aoqi@1 | 188 | void LIR_Assembler::pop(LIR_Opr opr) { |
aoqi@6880 | 189 | if (opr->is_single_cpu() ) { |
aoqi@6880 | 190 | __ pop(opr->as_register()); |
aoqi@6880 | 191 | } else { |
aoqi@6880 | 192 | assert(false, "Must be single word register or floating-point register"); |
aoqi@6880 | 193 | } |
aoqi@1 | 194 | } |
aoqi@1 | 195 | |
aoqi@1 | 196 | |
aoqi@1 | 197 | Address LIR_Assembler::as_Address(LIR_Address* addr) { |
aoqi@1 | 198 | #ifndef _LP64 |
aoqi@1 | 199 | Register reg = addr->base()->as_register(); |
aoqi@1 | 200 | #else |
aoqi@1 | 201 | //FIXME aoqi |
aoqi@1 | 202 | Register reg = addr->base()->is_single_cpu()? addr->base()->as_register() : addr->base()->as_register_lo(); |
aoqi@1 | 203 | #endif |
aoqi@1 | 204 | // now we need this for parameter pass |
aoqi@1 | 205 | return Address(reg, addr->disp()); |
aoqi@1 | 206 | } |
aoqi@1 | 207 | |
aoqi@1 | 208 | |
aoqi@1 | 209 | Address LIR_Assembler::as_Address_lo(LIR_Address* addr) { |
aoqi@1 | 210 | return as_Address(addr); |
aoqi@1 | 211 | } |
aoqi@1 | 212 | |
aoqi@1 | 213 | |
aoqi@1 | 214 | Address LIR_Assembler::as_Address_hi(LIR_Address* addr) { |
aoqi@6880 | 215 | Register reg = addr->base()->as_register(); |
aoqi@6880 | 216 | return Address(reg, addr->disp()+longSize/2); |
aoqi@1 | 217 | } |
aoqi@1 | 218 | |
aoqi@1 | 219 | |
aoqi@6880 | 220 | //void LIR_Assembler::osr_entry(IRScope* scope, int number_of_locks, Label* continuation, int osr_bci) { |
aoqi@6880 | 221 | void LIR_Assembler::osr_entry() { |
aoqi@6880 | 222 | // assert(scope->is_top_scope(), "inlined OSR not yet implemented"); |
aoqi@6880 | 223 | offsets()->set_value(CodeOffsets::OSR_Entry, code_offset()); |
aoqi@6880 | 224 | BlockBegin* osr_entry = compilation()->hir()->osr_entry(); |
aoqi@6880 | 225 | ValueStack* entry_state = osr_entry->state(); |
aoqi@6880 | 226 | int number_of_locks = entry_state->locks_size(); |
aoqi@6880 | 227 | |
aoqi@6880 | 228 | // we jump here if osr happens with the interpreter |
aoqi@6880 | 229 | // state set up to continue at the beginning of the |
aoqi@6880 | 230 | // loop that triggered osr - in particular, we have |
aoqi@6880 | 231 | // the following registers setup: |
aoqi@6880 | 232 | // |
aoqi@6880 | 233 | // S7: interpreter locals pointer |
aoqi@6880 | 234 | // V1: interpreter locks pointer |
aoqi@6880 | 235 | // RA: return address |
aoqi@6880 | 236 | //T0: OSR buffer |
aoqi@6880 | 237 | // build frame |
aoqi@6880 | 238 | // ciMethod* m = scope->method(); |
aoqi@6880 | 239 | ciMethod* m = compilation()->method(); |
aoqi@6880 | 240 | __ build_frame(initial_frame_size_in_bytes(), bang_size_in_bytes()); |
aoqi@1 | 241 | |
aoqi@1 | 242 | // OSR buffer is |
aoqi@1 | 243 | // |
aoqi@1 | 244 | // locals[nlocals-1..0] |
aoqi@1 | 245 | // monitors[0..number_of_locks] |
aoqi@1 | 246 | // |
aoqi@1 | 247 | // locals is a direct copy of the interpreter frame so in the osr buffer |
aoqi@1 | 248 | // so first slot in the local array is the last local from the interpreter |
aoqi@1 | 249 | // and last slot is local[0] (receiver) from the interpreter |
aoqi@1 | 250 | // |
aoqi@1 | 251 | // Similarly with locks. The first lock slot in the osr buffer is the nth lock |
aoqi@1 | 252 | // from the interpreter frame, the nth lock slot in the osr buffer is 0th lock |
aoqi@1 | 253 | // in the interpreter frame (the method lock if a sync method) |
aoqi@1 | 254 | |
aoqi@1 | 255 | // Initialize monitors in the compiled activation. |
aoqi@1 | 256 | // T0: pointer to osr buffer |
aoqi@1 | 257 | // |
aoqi@1 | 258 | // All other registers are dead at this point and the locals will be |
aoqi@1 | 259 | // copied into place by code emitted in the IR. |
aoqi@1 | 260 | |
aoqi@1 | 261 | Register OSR_buf = osrBufferPointer()->as_pointer_register(); |
aoqi@1 | 262 | |
aoqi@6880 | 263 | |
aoqi@1 | 264 | // note: we do osr only if the expression stack at the loop beginning is empty, |
aoqi@1 | 265 | // in which case the spill area is empty too and we don't have to setup |
aoqi@1 | 266 | // spilled locals |
aoqi@1 | 267 | // |
aoqi@1 | 268 | // copy monitors |
aoqi@1 | 269 | // V1: pointer to locks |
aoqi@6880 | 270 | { |
aoqi@6880 | 271 | assert(frame::interpreter_frame_monitor_size() == BasicObjectLock::size(), "adjust code below"); |
aoqi@6880 | 272 | int monitor_offset = BytesPerWord * method()->max_locals()+ |
aoqi@6880 | 273 | (BasicObjectLock::size() * BytesPerWord) * (number_of_locks - 1); |
aoqi@6880 | 274 | for (int i = 0; i < number_of_locks; i++) { |
aoqi@6880 | 275 | int slot_offset =monitor_offset - (i * BasicObjectLock::size())*BytesPerWord; |
aoqi@1 | 276 | #ifdef ASSERT |
aoqi@6880 | 277 | { |
aoqi@6880 | 278 | Label L; |
aoqi@6880 | 279 | //__ lw(AT, V1, slot_offset * BytesPerWord + BasicObjectLock::obj_offset_in_bytes()); |
aoqi@6880 | 280 | __ ld_ptr(AT, OSR_buf, slot_offset + BasicObjectLock::obj_offset_in_bytes()); |
aoqi@6880 | 281 | __ bne(AT, R0, L); |
aoqi@6880 | 282 | __ delayed()->nop(); |
aoqi@6880 | 283 | __ stop("locked object is NULL"); |
aoqi@6880 | 284 | __ bind(L); |
aoqi@6880 | 285 | } |
aoqi@1 | 286 | #endif |
aoqi@6880 | 287 | __ ld_ptr(AT, OSR_buf, slot_offset + BasicObjectLock::lock_offset_in_bytes()); |
aoqi@6880 | 288 | __ st_ptr(AT, frame_map()->address_for_monitor_lock(i)); |
aoqi@6880 | 289 | __ ld_ptr(AT, OSR_buf, slot_offset + BasicObjectLock::obj_offset_in_bytes()); |
aoqi@6880 | 290 | __ st_ptr(AT, frame_map()->address_for_monitor_object(i)); |
aoqi@6880 | 291 | } |
aoqi@1 | 292 | } |
aoqi@1 | 293 | } |
aoqi@1 | 294 | |
aoqi@1 | 295 | |
aoqi@1 | 296 | int LIR_Assembler::check_icache() { |
aoqi@6880 | 297 | Register receiver = FrameMap::receiver_opr->as_register(); |
aoqi@6880 | 298 | Register ic_klass = IC_Klass; |
aoqi@6880 | 299 | |
aoqi@6880 | 300 | /*const int ic_cmp_size = LP64_ONLY(10) NOT_LP64(9); |
aoqi@6880 | 301 | const bool do_post_padding = VerifyOops || UseCompressedOops; |
aoqi@6880 | 302 | if (!do_post_padding) { |
aoqi@6880 | 303 | // insert some nops so that the verified entry point is aligned on CodeEntryAlignment |
aoqi@6880 | 304 | while ((__ offset() + ic_cmp_size) % CodeEntryAlignment != 0) { |
aoqi@6880 | 305 | __ nop(); |
aoqi@6880 | 306 | } |
aoqi@6880 | 307 | }*/ |
aoqi@6880 | 308 | |
aoqi@6880 | 309 | int offset = __ offset(); |
aoqi@6880 | 310 | __ inline_cache_check(receiver, IC_Klass); |
aoqi@6880 | 311 | __ align(CodeEntryAlignment); |
aoqi@6880 | 312 | return offset; |
aoqi@1 | 313 | |
aoqi@1 | 314 | |
aoqi@1 | 315 | } |
aoqi@1 | 316 | |
aoqi@1 | 317 | void LIR_Assembler::jobject2reg_with_patching(Register reg, CodeEmitInfo* info) { |
aoqi@6880 | 318 | jobject o = NULL; |
aoqi@6880 | 319 | int oop_index = __ oop_recorder()->allocate_oop_index(o); |
aoqi@8865 | 320 | PatchingStub* patch = new PatchingStub(_masm, patching_id(info), oop_index); |
aoqi@6880 | 321 | RelocationHolder rspec = oop_Relocation::spec(oop_index); |
aoqi@6880 | 322 | __ relocate(rspec); |
aoqi@1 | 323 | #ifndef _LP64 |
aoqi@1 | 324 | //by_css |
aoqi@6880 | 325 | __ lui(reg, Assembler::split_high((int)o)); |
aoqi@6880 | 326 | __ addiu(reg, reg, Assembler::split_low((int)o)); |
aoqi@1 | 327 | #else |
aoqi@6880 | 328 | //li may not pass NativeMovConstReg::verify. see nativeMovConstReg_at(pc_start()); in PatchingStub::install. by aoqi |
aoqi@8865 | 329 | // __ li48(reg, (long)o); |
aoqi@6880 | 330 | __ li48(reg, (long)o); |
aoqi@1 | 331 | #endif |
aoqi@6880 | 332 | // patching_epilog(patch, LIR_Op1::patch_normal, noreg, info); |
aoqi@6880 | 333 | patching_epilog(patch, lir_patch_normal, reg, info); |
aoqi@1 | 334 | } |
aoqi@1 | 335 | |
aoqi@8865 | 336 | void LIR_Assembler::klass2reg_with_patching(Register reg, CodeEmitInfo* info) { |
aoqi@8865 | 337 | Metadata *o = NULL; |
aoqi@8865 | 338 | int index = __ oop_recorder()->allocate_metadata_index(o); |
aoqi@8865 | 339 | PatchingStub* patch = new PatchingStub(_masm, PatchingStub::load_klass_id, index); |
aoqi@8865 | 340 | RelocationHolder rspec = metadata_Relocation::spec(index); |
aoqi@8865 | 341 | __ relocate(rspec); |
aoqi@8865 | 342 | __ li48(reg, (long)o); |
aoqi@8865 | 343 | patching_epilog(patch, lir_patch_normal, reg, info); |
aoqi@1 | 344 | } |
aoqi@1 | 345 | |
aoqi@1 | 346 | // This specifies the esp decrement needed to build the frame |
aoqi@1 | 347 | int LIR_Assembler::initial_frame_size_in_bytes() const { |
aoqi@6880 | 348 | // if rounding, must let FrameMap know! |
aoqi@6880 | 349 | // return (frame_map()->framesize() - 2) * BytesPerWord; // subtract two words to account for return address and link |
aoqi@1 | 350 | return (frame_map()->framesize() - (2*VMRegImpl::slots_per_word)) * VMRegImpl::stack_slot_size; |
aoqi@1 | 351 | } |
aoqi@1 | 352 | |
aoqi@6880 | 353 | int LIR_Assembler::emit_exception_handler() { |
aoqi@1 | 354 | // if the last instruction is a call (typically to do a throw which |
aoqi@1 | 355 | // is coming at the end after block reordering) the return address |
aoqi@1 | 356 | // must still point into the code area in order to avoid assertion |
aoqi@1 | 357 | // failures when searching for the corresponding bci => add a nop |
aoqi@1 | 358 | // (was bug 5/14/1999 - gri) |
aoqi@1 | 359 | // Lazy deopt bug 4932387. If last instruction is a call then we |
aoqi@1 | 360 | // need an area to patch where we won't overwrite the exception |
aoqi@6880 | 361 | // handler. This means we need 5 bytes. Could use a fat_nop |
aoqi@1 | 362 | // but since this never gets executed it doesn't really make |
aoqi@1 | 363 | // much difference. |
aoqi@6880 | 364 | // |
aoqi@6880 | 365 | for (int i = 0; i < (NativeCall::instruction_size/BytesPerInstWord + 1) ; i++ ) { |
aoqi@6880 | 366 | __ nop(); |
aoqi@6880 | 367 | } |
aoqi@1 | 368 | |
aoqi@1 | 369 | // generate code for exception handler |
aoqi@6880 | 370 | address handler_base = __ start_a_stub(exception_handler_size); |
aoqi@6880 | 371 | if (handler_base == NULL) { |
aoqi@8865 | 372 | // no enough space |
aoqi@6880 | 373 | bailout("exception handler overflow"); |
aoqi@6880 | 374 | return -1; |
aoqi@6880 | 375 | } |
aoqi@6880 | 376 | |
aoqi@8865 | 377 | int offset = code_offset(); |
aoqi@8865 | 378 | |
aoqi@8865 | 379 | // the exception oop and pc are in V0, and V1 |
aoqi@6880 | 380 | // no other registers need to be preserved, so invalidate them |
aoqi@8865 | 381 | //__ invalidate_registers(false, true, true, false, true, true); |
aoqi@8865 | 382 | |
aoqi@6880 | 383 | // check that there is really an exception |
aoqi@6880 | 384 | __ verify_not_null_oop(V0); |
aoqi@8865 | 385 | |
aoqi@8865 | 386 | // search an exception handler (V0: exception oop, V1: throwing pc) |
aoqi@8865 | 387 | __ call(Runtime1::entry_for(Runtime1::handle_exception_from_callee_id)); |
aoqi@8865 | 388 | __ delayed()->nop(); |
aoqi@8865 | 389 | __ should_not_reach_here(); |
aoqi@8865 | 390 | guarantee(code_offset() - offset <= exception_handler_size, "overflow"); |
aoqi@8865 | 391 | __ end_a_stub(); |
aoqi@8865 | 392 | |
aoqi@8865 | 393 | return offset; |
aoqi@1 | 394 | } |
aoqi@1 | 395 | |
aoqi@1 | 396 | // Emit the code to remove the frame from the stack in the exception |
aoqi@6880 | 397 | // unwind path. |
aoqi@1 | 398 | int LIR_Assembler::emit_unwind_handler() { |
aoqi@1 | 399 | #ifndef PRODUCT |
aoqi@1 | 400 | if (CommentedAssembly) { |
aoqi@1 | 401 | _masm->block_comment("Unwind handler"); |
aoqi@1 | 402 | } |
aoqi@1 | 403 | #endif |
aoqi@1 | 404 | |
aoqi@1 | 405 | int offset = code_offset(); |
aoqi@8865 | 406 | // Fetch the exception from TLS and clear out exception related thread state |
aoqi@8865 | 407 | Register thread = TREG; |
aoqi@8865 | 408 | #ifndef OPT_THREAD |
aoqi@8865 | 409 | __ get_thread(thread); |
aoqi@8865 | 410 | #endif |
aoqi@8865 | 411 | __ ld_ptr(V0, Address(thread, JavaThread::exception_oop_offset())); |
aoqi@8865 | 412 | __ st_ptr(R0, Address(thread, JavaThread::exception_oop_offset())); |
aoqi@8865 | 413 | __ st_ptr(R0, Address(thread, JavaThread::exception_pc_offset())); |
aoqi@1 | 414 | |
aoqi@1 | 415 | __ bind(_unwind_handler_entry); |
aoqi@8865 | 416 | __ verify_not_null_oop(V0); |
aoqi@1 | 417 | if (method()->is_synchronized() || compilation()->env()->dtrace_method_probes()) { |
aoqi@8865 | 418 | __ move(S0, V0); // Preserve the exception (rbx is always callee-saved) |
aoqi@1 | 419 | } |
aoqi@8865 | 420 | |
aoqi@8865 | 421 | // Preform needed unlocking |
aoqi@8865 | 422 | MonitorExitStub* stub = NULL; |
aoqi@1 | 423 | if (method()->is_synchronized()) { |
aoqi@8865 | 424 | monitor_address(0, FrameMap::_v0_opr); |
aoqi@8865 | 425 | stub = new MonitorExitStub(FrameMap::_v0_opr, true, 0); |
aoqi@8865 | 426 | __ unlock_object(A0, A1, V0, *stub->entry()); |
aoqi@1 | 427 | __ bind(*stub->continuation()); |
aoqi@1 | 428 | } |
aoqi@1 | 429 | |
aoqi@1 | 430 | if (compilation()->env()->dtrace_method_probes()) { |
aoqi@8865 | 431 | __ move(A0, thread); |
aoqi@8865 | 432 | __ mov_metadata(A1, method()->constant_encoding()); |
aoqi@8865 | 433 | __ patchable_call(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_method_exit)); |
aoqi@1 | 434 | } |
aoqi@1 | 435 | |
aoqi@1 | 436 | if (method()->is_synchronized() || compilation()->env()->dtrace_method_probes()) { |
aoqi@8865 | 437 | __ move(V0, S0); // Restore the exception |
aoqi@1 | 438 | } |
aoqi@1 | 439 | |
aoqi@1 | 440 | // remove the activation and dispatch to the unwind handler |
aoqi@8865 | 441 | // leave activation of nmethod |
aoqi@8865 | 442 | __ remove_frame(initial_frame_size_in_bytes()); |
aoqi@8865 | 443 | |
aoqi@8865 | 444 | __ jmp(Runtime1::entry_for(Runtime1::unwind_exception_id)); |
aoqi@8865 | 445 | __ delayed()->nop(); |
aoqi@1 | 446 | |
aoqi@1 | 447 | // Emit the slow path assembly |
aoqi@8865 | 448 | if (stub != NULL) { |
aoqi@1 | 449 | stub->emit_code(this); |
aoqi@1 | 450 | } |
aoqi@8865 | 451 | |
aoqi@1 | 452 | return offset; |
aoqi@1 | 453 | } |
aoqi@1 | 454 | |
aoqi@1 | 455 | |
aoqi@1 | 456 | int LIR_Assembler::emit_deopt_handler() { |
aoqi@6880 | 457 | // if the last instruction is a call (typically to do a throw which |
aoqi@6880 | 458 | // is coming at the end after block reordering) the return address |
aoqi@6880 | 459 | // must still point into the code area in order to avoid assertion |
aoqi@6880 | 460 | // failures when searching for the corresponding bci => add a nop |
aoqi@6880 | 461 | // (was bug 5/14/1999 - gri) |
aoqi@6880 | 462 | |
aoqi@6880 | 463 | __ nop(); |
aoqi@6880 | 464 | |
aoqi@6880 | 465 | // generate code for exception handler |
aoqi@6880 | 466 | address handler_base = __ start_a_stub(deopt_handler_size); |
aoqi@6880 | 467 | if (handler_base == NULL) { |
aoqi@6880 | 468 | // not enough space left for the handler |
aoqi@6880 | 469 | bailout("deopt handler overflow"); |
aoqi@6880 | 470 | return -1; |
aoqi@6880 | 471 | } |
aoqi@6880 | 472 | int offset = code_offset(); |
aoqi@6880 | 473 | |
aoqi@6880 | 474 | // compilation()->offsets()->set_value(CodeOffsets::Deopt, code_offset()); |
aoqi@6880 | 475 | |
aoqi@6880 | 476 | __ call(SharedRuntime::deopt_blob()->unpack()); |
aoqi@6880 | 477 | __ delayed()->nop(); |
aoqi@6880 | 478 | |
aoqi@6880 | 479 | guarantee(code_offset() - offset <= deopt_handler_size, "overflow"); |
aoqi@6880 | 480 | __ end_a_stub(); |
aoqi@6880 | 481 | |
aoqi@6880 | 482 | return offset; |
aoqi@1 | 483 | |
aoqi@1 | 484 | } |
aoqi@1 | 485 | |
aoqi@1 | 486 | |
aoqi@1 | 487 | // Optimized Library calls |
aoqi@1 | 488 | // This is the fast version of java.lang.String.compare; it has not |
aoqi@1 | 489 | // OSR-entry and therefore, we generate a slow version for OSR's |
aoqi@1 | 490 | //void LIR_Assembler::emit_string_compare(IRScope* scope) { |
aoqi@1 | 491 | void LIR_Assembler::emit_string_compare(LIR_Opr arg0, LIR_Opr arg1, LIR_Opr dst, CodeEmitInfo* info) { |
aoqi@6880 | 492 | // get two string object in T0&T1 |
aoqi@6880 | 493 | //receiver already in T0 |
aoqi@6880 | 494 | __ ld_ptr(T1, arg1->as_register()); |
aoqi@6880 | 495 | //__ ld_ptr(T2, T0, java_lang_String::value_offset_in_bytes()); //value, T_CHAR array |
aoqi@6880 | 496 | __ load_heap_oop(T2, Address(T0, java_lang_String::value_offset_in_bytes())); |
aoqi@6880 | 497 | __ ld_ptr(AT, T0, java_lang_String::offset_offset_in_bytes()); //offset |
aoqi@6880 | 498 | __ shl(AT, 1); |
aoqi@6880 | 499 | __ add(T2, T2, AT); |
aoqi@6880 | 500 | __ addi(T2, T2, arrayOopDesc::base_offset_in_bytes(T_CHAR)); |
aoqi@6880 | 501 | // Now T2 is the address of the first char in first string(T0) |
aoqi@6880 | 502 | |
aoqi@6880 | 503 | add_debug_info_for_null_check_here(info); |
aoqi@6880 | 504 | //__ ld_ptr(T3, T1, java_lang_String::value_offset_in_bytes()); |
aoqi@6880 | 505 | __ load_heap_oop(T3, Address(T1, java_lang_String::value_offset_in_bytes())); |
aoqi@6880 | 506 | __ ld_ptr(AT, T1, java_lang_String::offset_offset_in_bytes()); |
aoqi@6880 | 507 | __ shl(AT, 1); |
aoqi@6880 | 508 | __ add(T3, T3, AT); |
aoqi@6880 | 509 | __ addi(T3, T3, arrayOopDesc::base_offset_in_bytes(T_CHAR)); |
aoqi@6880 | 510 | // Now T3 is the address of the first char in second string(T1) |
aoqi@1 | 511 | |
aoqi@1 | 512 | #ifndef _LP64 |
aoqi@1 | 513 | //by_css |
aoqi@6880 | 514 | // compute minimum length (in T4) and difference of lengths (V0) |
aoqi@6880 | 515 | Label L; |
aoqi@6880 | 516 | __ lw (T4, Address(T0, java_lang_String::count_offset_in_bytes())); |
aoqi@6880 | 517 | // the length of the first string(T0) |
aoqi@6880 | 518 | __ lw (T5, Address(T1, java_lang_String::count_offset_in_bytes())); |
aoqi@6880 | 519 | // the length of the second string(T1) |
aoqi@6880 | 520 | |
aoqi@6880 | 521 | __ subu(V0, T4, T5); |
aoqi@6880 | 522 | __ blez(V0, L); |
aoqi@6880 | 523 | __ delayed()->nop(); |
aoqi@6880 | 524 | __ move (T4, T5); |
aoqi@6880 | 525 | __ bind (L); |
aoqi@6880 | 526 | |
aoqi@6880 | 527 | Label Loop, haveResult, LoopEnd; |
aoqi@6880 | 528 | __ bind(Loop); |
aoqi@6880 | 529 | __ beq(T4, R0, LoopEnd); |
aoqi@6880 | 530 | __ delayed(); |
aoqi@6880 | 531 | |
aoqi@6880 | 532 | __ addi(T2, T2, 2); |
aoqi@6880 | 533 | |
aoqi@6880 | 534 | // compare current character |
aoqi@6880 | 535 | __ lhu(T5, T2, -2); |
aoqi@6880 | 536 | __ lhu(T6, T3, 0); |
aoqi@6880 | 537 | __ bne(T5, T6, haveResult); |
aoqi@6880 | 538 | __ delayed(); |
aoqi@6880 | 539 | |
aoqi@6880 | 540 | __ addi(T3, T3, 2); |
aoqi@6880 | 541 | |
aoqi@6880 | 542 | __ b(Loop); |
aoqi@6880 | 543 | __ delayed()->addi(T4, T4, -1); |
aoqi@6880 | 544 | |
aoqi@6880 | 545 | __ bind(haveResult); |
aoqi@6880 | 546 | __ subu(V0, T5, T6); |
aoqi@6880 | 547 | |
aoqi@6880 | 548 | __ bind(LoopEnd); |
aoqi@1 | 549 | #else |
aoqi@6880 | 550 | // compute minimum length (in T4) and difference of lengths (V0) |
aoqi@6880 | 551 | Label L; |
aoqi@6880 | 552 | __ lw (A4, Address(T0, java_lang_String::count_offset_in_bytes())); |
aoqi@6880 | 553 | // the length of the first string(T0) |
aoqi@6880 | 554 | __ lw (A5, Address(T1, java_lang_String::count_offset_in_bytes())); |
aoqi@6880 | 555 | // the length of the second string(T1) |
aoqi@6880 | 556 | |
aoqi@6880 | 557 | __ dsubu(V0, A4, A5); |
aoqi@6880 | 558 | __ blez(V0, L); |
aoqi@6880 | 559 | __ delayed()->nop(); |
aoqi@6880 | 560 | __ move (A4, A5); |
aoqi@6880 | 561 | __ bind (L); |
aoqi@6880 | 562 | |
aoqi@6880 | 563 | Label Loop, haveResult, LoopEnd; |
aoqi@6880 | 564 | __ bind(Loop); |
aoqi@6880 | 565 | __ beq(A4, R0, LoopEnd); |
aoqi@6880 | 566 | __ delayed(); |
aoqi@6880 | 567 | |
aoqi@6880 | 568 | __ daddi(T2, T2, 2); |
aoqi@6880 | 569 | |
aoqi@6880 | 570 | // compare current character |
aoqi@6880 | 571 | __ lhu(A5, T2, -2); |
aoqi@6880 | 572 | __ lhu(A6, T3, 0); |
aoqi@6880 | 573 | __ bne(A5, A6, haveResult); |
aoqi@6880 | 574 | __ delayed(); |
aoqi@6880 | 575 | |
aoqi@6880 | 576 | __ daddi(T3, T3, 2); |
aoqi@6880 | 577 | |
aoqi@6880 | 578 | __ b(Loop); |
aoqi@6880 | 579 | __ delayed()->addi(A4, A4, -1); |
aoqi@6880 | 580 | |
aoqi@6880 | 581 | __ bind(haveResult); |
aoqi@6880 | 582 | __ dsubu(V0, A5, A6); |
aoqi@6880 | 583 | |
aoqi@6880 | 584 | __ bind(LoopEnd); |
aoqi@1 | 585 | #endif |
aoqi@6880 | 586 | return_op(FrameMap::_v0_opr); |
aoqi@1 | 587 | } |
aoqi@1 | 588 | |
aoqi@1 | 589 | |
aoqi@1 | 590 | void LIR_Assembler::return_op(LIR_Opr result) { |
aoqi@1 | 591 | assert(result->is_illegal() || !result->is_single_cpu() || result->as_register() == V0, "word returns are in V0"); |
aoqi@1 | 592 | // Pop the stack before the safepoint code |
aoqi@8865 | 593 | __ remove_frame(initial_frame_size_in_bytes()); |
aoqi@1 | 594 | #ifndef _LP64 |
aoqi@1 | 595 | //by aoqi |
aoqi@6880 | 596 | __ lui(AT, Assembler::split_high((intptr_t)os::get_polling_page() |
aoqi@6880 | 597 | + (SafepointPollOffset % os::vm_page_size()))); |
aoqi@1 | 598 | __ relocate(relocInfo::poll_return_type); |
aoqi@6880 | 599 | __ lw(AT, AT, Assembler::split_low((intptr_t)os::get_polling_page() |
aoqi@6880 | 600 | + (SafepointPollOffset % os::vm_page_size()))); |
aoqi@1 | 601 | #else |
aoqi@1 | 602 | #ifndef OPT_SAFEPOINT |
aoqi@1 | 603 | // do not know how to handle relocate yet. do not know li or li64 should be used neither. by aoqi. 20111207 FIXME. |
aoqi@1 | 604 | __ li48(AT, (intptr_t)os::get_polling_page() + (SafepointPollOffset % os::vm_page_size())); |
aoqi@1 | 605 | __ relocate(relocInfo::poll_return_type); |
aoqi@6880 | 606 | __ lw(AT, AT, 0); |
aoqi@1 | 607 | #else |
aoqi@1 | 608 | __ lui(AT, Assembler::split_high((intptr_t)os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()))); |
aoqi@1 | 609 | __ relocate(relocInfo::poll_return_type); |
aoqi@1 | 610 | __ lw(AT, AT, Assembler::split_low((intptr_t)os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()))); |
aoqi@1 | 611 | #endif |
aoqi@1 | 612 | #endif |
aoqi@1 | 613 | |
aoqi@8865 | 614 | __ pop(RA); |
aoqi@1 | 615 | __ jr(RA); |
aoqi@1 | 616 | __ delayed()->nop(); |
aoqi@1 | 617 | } |
aoqi@1 | 618 | |
aoqi@1 | 619 | //read protect mem to R0 won't cause the exception only in godson-2e, So I modify R0 to AT .@jerome,11/25,2006 |
aoqi@1 | 620 | int LIR_Assembler::safepoint_poll(LIR_Opr tmp, CodeEmitInfo* info) { |
aoqi@1 | 621 | assert(info != NULL, "info must not be null for safepoint poll"); |
aoqi@1 | 622 | int offset = __ offset(); |
aoqi@1 | 623 | Register r = tmp->as_register(); |
aoqi@1 | 624 | #ifndef _LP64 |
aoqi@1 | 625 | //by aoqi |
aoqi@1 | 626 | __ lui(r, Assembler::split_high((intptr_t)os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()))); |
aoqi@1 | 627 | add_debug_info_for_branch(info); |
aoqi@1 | 628 | __ relocate(relocInfo::poll_type); |
aoqi@1 | 629 | __ lw(AT, r, Assembler::split_low((intptr_t)os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()))); |
aoqi@1 | 630 | #else |
aoqi@1 | 631 | #ifndef OPT_SAFEPOINT |
aoqi@1 | 632 | // do not know how to handle relocate yet. do not know li or li64 should be used neither. by aoqi. 20111207 FIXME. |
aoqi@1 | 633 | //__ lui(r, Assembler::split_high((intptr_t)os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()))); |
aoqi@1 | 634 | __ li48(r, (intptr_t)os::get_polling_page() + (SafepointPollOffset % os::vm_page_size())); |
aoqi@1 | 635 | add_debug_info_for_branch(info); |
aoqi@1 | 636 | __ relocate(relocInfo::poll_type); |
aoqi@1 | 637 | //__ lw(AT, r, Assembler::split_low((intptr_t)os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()))); |
aoqi@1 | 638 | __ lw(AT, r, 0); |
aoqi@1 | 639 | #else |
aoqi@1 | 640 | __ lui(r, Assembler::split_high((intptr_t)os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()))); |
aoqi@1 | 641 | add_debug_info_for_branch(info); |
aoqi@1 | 642 | __ relocate(relocInfo::poll_type); |
aoqi@1 | 643 | __ lw(AT, r, Assembler::split_low((intptr_t)os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()))); |
aoqi@1 | 644 | #endif |
aoqi@1 | 645 | #endif |
aoqi@6880 | 646 | return offset; |
aoqi@1 | 647 | } |
aoqi@1 | 648 | |
aoqi@1 | 649 | void LIR_Assembler::move_regs(Register from_reg, Register to_reg) { |
aoqi@6880 | 650 | if (from_reg != to_reg) __ move(to_reg, from_reg); |
aoqi@1 | 651 | } |
aoqi@1 | 652 | |
aoqi@1 | 653 | |
aoqi@1 | 654 | void LIR_Assembler::swap_reg(Register a, Register b) { |
aoqi@6880 | 655 | __ xorr(a, a, b); |
aoqi@6880 | 656 | __ xorr(b, a, b); |
aoqi@6880 | 657 | __ xorr(a, a, b); |
aoqi@1 | 658 | } |
aoqi@1 | 659 | |
aoqi@1 | 660 | void LIR_Assembler::const2reg(LIR_Opr src, LIR_Opr dest, LIR_PatchCode patch_code, CodeEmitInfo* info) { |
aoqi@1 | 661 | assert(src->is_constant(), "should not call otherwise"); |
aoqi@1 | 662 | assert(dest->is_register(), "should not call otherwise"); |
aoqi@1 | 663 | LIR_Const* c = src->as_constant_ptr(); |
aoqi@1 | 664 | switch (c->type()) { |
aoqi@8865 | 665 | case T_ADDRESS: { |
aoqi@8865 | 666 | assert(patch_code == lir_patch_none, "no patching handled here"); |
aoqi@8865 | 667 | __ move(dest->as_register(), c->as_jint()); // FIXME |
aoqi@8865 | 668 | break; |
aoqi@8865 | 669 | } |
aoqi@8865 | 670 | |
aoqi@6880 | 671 | case T_INT: { |
aoqi@8865 | 672 | assert(patch_code == lir_patch_none, "no patching handled here"); |
aoqi@8865 | 673 | __ move(dest->as_register(), c->as_jint()); |
aoqi@1 | 674 | break; |
aoqi@6880 | 675 | } |
aoqi@6880 | 676 | |
aoqi@6880 | 677 | case T_LONG: { |
aoqi@1 | 678 | #ifndef _LP64 |
aoqi@6880 | 679 | jlong con = c->as_jlong(); |
aoqi@6880 | 680 | jint* conhi = (jint*)&con + 1; |
aoqi@6880 | 681 | jint* conlow = (jint*)&con; |
aoqi@6880 | 682 | |
aoqi@6880 | 683 | if (dest->is_double_cpu()) { |
aoqi@6880 | 684 | __ move(dest->as_register_lo(), *conlow); |
aoqi@6880 | 685 | __ move(dest->as_register_hi(), *conhi); |
aoqi@6880 | 686 | } else { |
aoqi@6880 | 687 | // assert(dest->is_double(), "wrong register kind"); |
aoqi@6880 | 688 | __ move(AT, *conlow); |
aoqi@6880 | 689 | __ mtc1(AT, dest->as_double_reg()); |
aoqi@6880 | 690 | __ move(AT, *conhi); |
aoqi@6880 | 691 | __ mtc1(AT, dest->as_double_reg()+1); |
aoqi@6880 | 692 | } |
aoqi@1 | 693 | #else |
aoqi@6880 | 694 | if (dest->is_double_cpu()) { |
aoqi@6880 | 695 | __ li(dest->as_register_lo(), c->as_jlong()); |
aoqi@6880 | 696 | } else { |
aoqi@6880 | 697 | __ li(dest->as_register(), c->as_jlong()); |
aoqi@6880 | 698 | } |
aoqi@6880 | 699 | #endif |
aoqi@6880 | 700 | break; |
aoqi@6880 | 701 | } |
aoqi@6880 | 702 | |
aoqi@6880 | 703 | case T_OBJECT: { |
aoqi@6880 | 704 | if (patch_code == lir_patch_none) { |
aoqi@6880 | 705 | jobject2reg(c->as_jobject(), dest->as_register()); |
aoqi@6880 | 706 | } else { |
aoqi@6880 | 707 | jobject2reg_with_patching(dest->as_register(), info); |
aoqi@6880 | 708 | } |
aoqi@6880 | 709 | break; |
aoqi@6880 | 710 | } |
aoqi@6880 | 711 | |
aoqi@8865 | 712 | case T_METADATA: { |
aoqi@8865 | 713 | if (patch_code != lir_patch_none) { |
aoqi@8865 | 714 | klass2reg_with_patching(dest->as_register(), info); |
aoqi@8865 | 715 | } else { |
aoqi@8865 | 716 | __ mov_metadata(dest->as_register(), c->as_metadata()); |
aoqi@8865 | 717 | } |
aoqi@8865 | 718 | break; |
aoqi@8865 | 719 | } |
aoqi@8865 | 720 | |
aoqi@6880 | 721 | case T_FLOAT: { |
aoqi@6880 | 722 | address const_addr = float_constant(c->as_jfloat()); |
aoqi@6880 | 723 | assert (const_addr != NULL, "must create float constant in the constant table"); |
aoqi@6880 | 724 | |
aoqi@6880 | 725 | if (dest->is_single_fpu()) { |
aoqi@6880 | 726 | __ relocate(relocInfo::internal_pc_type); |
aoqi@6880 | 727 | #ifndef _LP64 |
aoqi@6880 | 728 | //by_css |
aoqi@6880 | 729 | __ lui(AT, Assembler::split_high((int)const_addr)); |
aoqi@6880 | 730 | __ addiu(AT, AT, Assembler::split_low((int)const_addr)); |
aoqi@6880 | 731 | #else |
aoqi@6880 | 732 | __ li48(AT, (long)const_addr); |
aoqi@6880 | 733 | #endif |
aoqi@6880 | 734 | __ lwc1(dest->as_float_reg(), AT, 0); |
aoqi@6880 | 735 | |
aoqi@6880 | 736 | } else { |
aoqi@6880 | 737 | assert(dest->is_single_cpu(), "Must be a cpu register."); |
aoqi@6880 | 738 | assert(dest->as_register() != AT, "AT can not be allocated."); |
aoqi@6880 | 739 | |
aoqi@6880 | 740 | __ relocate(relocInfo::internal_pc_type); |
aoqi@6880 | 741 | #ifndef _LP64 |
aoqi@6880 | 742 | //by_css |
aoqi@6880 | 743 | __ lui(AT, Assembler::split_high((int)const_addr)); |
aoqi@6880 | 744 | __ addiu(AT, AT, Assembler::split_low((int)const_addr)); |
aoqi@6880 | 745 | #else |
aoqi@6880 | 746 | __ li48(AT, (long)const_addr); |
aoqi@6880 | 747 | #endif |
aoqi@6880 | 748 | __ lw(dest->as_register(), AT, 0); |
aoqi@6880 | 749 | } |
aoqi@6880 | 750 | break; |
aoqi@6880 | 751 | } |
aoqi@6880 | 752 | |
aoqi@6880 | 753 | case T_DOUBLE: { |
aoqi@6880 | 754 | address const_addr = double_constant(c->as_jdouble()); |
aoqi@6880 | 755 | assert (const_addr != NULL, "must create double constant in the constant table"); |
aoqi@6880 | 756 | |
aoqi@6880 | 757 | if (dest->is_double_fpu()) { |
aoqi@6880 | 758 | __ relocate(relocInfo::internal_pc_type); |
aoqi@6880 | 759 | #ifndef _LP64 |
aoqi@6880 | 760 | //by_css |
aoqi@6880 | 761 | __ lui(AT, Assembler::split_high((int)const_addr)); |
aoqi@6880 | 762 | __ addiu(AT, AT, Assembler::split_low((int)const_addr)); |
aoqi@6880 | 763 | __ lwc1(dest->as_double_reg(), AT, 0); |
aoqi@6880 | 764 | __ lwc1(dest->as_double_reg()+1, AT, 4); |
aoqi@6880 | 765 | #else |
aoqi@6880 | 766 | __ li48(AT, (long)const_addr); |
aoqi@6880 | 767 | __ ldc1(dest->as_double_reg(), AT, 0); |
aoqi@6880 | 768 | #endif |
aoqi@6880 | 769 | } else { |
aoqi@6880 | 770 | assert(dest->as_register_lo() != AT, "AT can not be allocated."); |
aoqi@6880 | 771 | assert(dest->as_register_hi() != AT, "AT can not be allocated."); |
aoqi@6880 | 772 | |
aoqi@6880 | 773 | __ relocate(relocInfo::internal_pc_type); |
aoqi@6880 | 774 | #ifndef _LP64 |
aoqi@6880 | 775 | //by_css |
aoqi@6880 | 776 | __ lui(AT, Assembler::split_high((int)const_addr)); |
aoqi@6880 | 777 | __ addiu(AT, AT, Assembler::split_low((int)const_addr)); |
aoqi@6880 | 778 | __ lw(dest->as_register_lo(), AT, 0); |
aoqi@6880 | 779 | __ lw(dest->as_register_hi(), AT, 4); |
aoqi@6880 | 780 | #else |
aoqi@6880 | 781 | __ li48(AT, (long)const_addr); |
aoqi@6880 | 782 | __ ld(dest->as_register_lo(), AT, 0); |
aoqi@1 | 783 | #endif |
aoqi@1 | 784 | } |
aoqi@1 | 785 | break; |
aoqi@6880 | 786 | } |
aoqi@1 | 787 | |
aoqi@1 | 788 | default: |
aoqi@1 | 789 | ShouldNotReachHere(); |
aoqi@1 | 790 | } |
aoqi@1 | 791 | } |
aoqi@1 | 792 | |
aoqi@1 | 793 | void LIR_Assembler::const2stack(LIR_Opr src, LIR_Opr dest) { |
aoqi@1 | 794 | assert(src->is_constant(), "should not call otherwise"); |
aoqi@1 | 795 | assert(dest->is_stack(), "should not call otherwise"); |
aoqi@1 | 796 | LIR_Const* c = src->as_constant_ptr(); |
aoqi@1 | 797 | switch (c->type()) { |
aoqi@1 | 798 | case T_INT: // fall through |
aoqi@1 | 799 | case T_FLOAT: |
aoqi@1 | 800 | __ move(AT, c->as_jint_bits()); |
aoqi@1 | 801 | __ sw(AT, frame_map()->address_for_slot(dest->single_stack_ix())); |
aoqi@1 | 802 | break; |
aoqi@1 | 803 | |
aoqi@8865 | 804 | case T_ADDRESS: |
aoqi@8865 | 805 | __ move(AT, c->as_jint_bits()); |
aoqi@8865 | 806 | __ st_ptr(AT, frame_map()->address_for_slot(dest->single_stack_ix())); |
aoqi@8865 | 807 | break; |
aoqi@8865 | 808 | |
aoqi@1 | 809 | case T_OBJECT: |
aoqi@1 | 810 | if (c->as_jobject() == NULL) { |
aoqi@6880 | 811 | __ st_ptr(R0, frame_map()->address_for_slot(dest->single_stack_ix())); |
aoqi@1 | 812 | } else { |
aoqi@6880 | 813 | int oop_index = __ oop_recorder()->find_index(c->as_jobject()); |
aoqi@6880 | 814 | RelocationHolder rspec = oop_Relocation::spec(oop_index); |
aoqi@6880 | 815 | __ relocate(rspec); |
aoqi@1 | 816 | #ifndef _LP64 |
aoqi@6880 | 817 | //by_css |
aoqi@6880 | 818 | __ lui(AT, Assembler::split_high((int)c->as_jobject())); |
aoqi@6880 | 819 | __ addiu(AT, AT, Assembler::split_low((int)c->as_jobject())); |
aoqi@1 | 820 | #else |
aoqi@6880 | 821 | __ li48(AT, (long)c->as_jobject()); |
aoqi@1 | 822 | #endif |
aoqi@6880 | 823 | __ st_ptr(AT, frame_map()->address_for_slot(dest->single_stack_ix())); |
aoqi@1 | 824 | } |
aoqi@1 | 825 | break; |
aoqi@1 | 826 | case T_LONG: // fall through |
aoqi@1 | 827 | case T_DOUBLE: |
aoqi@1 | 828 | #ifndef _LP64 |
aoqi@1 | 829 | __ move(AT, c->as_jint_lo_bits()); |
aoqi@1 | 830 | __ sw(AT, frame_map()->address_for_slot(dest->double_stack_ix(), |
aoqi@6880 | 831 | lo_word_offset_in_bytes)); |
aoqi@1 | 832 | __ move(AT, c->as_jint_hi_bits()); |
aoqi@1 | 833 | __ sw(AT, frame_map()->address_for_slot(dest->double_stack_ix(), |
aoqi@6880 | 834 | hi_word_offset_in_bytes)); |
aoqi@1 | 835 | #else |
aoqi@1 | 836 | __ move(AT, c->as_jlong_bits()); |
aoqi@1 | 837 | __ sd(AT, frame_map()->address_for_slot(dest->double_stack_ix(), |
aoqi@6880 | 838 | lo_word_offset_in_bytes)); |
aoqi@1 | 839 | #endif |
aoqi@1 | 840 | break; |
aoqi@1 | 841 | default: |
aoqi@1 | 842 | ShouldNotReachHere(); |
aoqi@1 | 843 | } |
aoqi@1 | 844 | } |
aoqi@1 | 845 | |
aoqi@1 | 846 | void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info, bool wide) { |
aoqi@1 | 847 | assert(src->is_constant(), "should not call otherwise"); |
aoqi@1 | 848 | assert(dest->is_address(), "should not call otherwise"); |
aoqi@1 | 849 | LIR_Const* c = src->as_constant_ptr(); |
aoqi@1 | 850 | LIR_Address* addr = dest->as_address_ptr(); |
aoqi@1 | 851 | |
aoqi@1 | 852 | int null_check_here = code_offset(); |
aoqi@1 | 853 | switch (type) { |
aoqi@1 | 854 | case T_LONG: // fall through |
aoqi@1 | 855 | case T_DOUBLE: |
aoqi@1 | 856 | #ifndef _LP64 |
aoqi@1 | 857 | __ move(AT, c->as_jint_hi_bits()); |
aoqi@1 | 858 | __ sw(AT, as_Address_hi(addr)); |
aoqi@1 | 859 | __ move(AT, c->as_jint_lo_bits()); |
aoqi@1 | 860 | __ sw(AT, as_Address_lo(addr)); |
aoqi@1 | 861 | #else |
aoqi@6880 | 862 | if(c->as_jlong_bits() != 0) { |
aoqi@1 | 863 | /* DoublePrint: -0.0 |
aoqi@1 | 864 | * (gdb) print /x -9223372036854775808 |
aoqi@1 | 865 | * $1 = 0x8000000000000000 |
aoqi@1 | 866 | */ |
aoqi@1 | 867 | __ li64(AT, c->as_jlong_bits()); |
aoqi@1 | 868 | __ sd(AT, as_Address_lo(addr)); |
aoqi@6880 | 869 | } else |
aoqi@1 | 870 | __ sd(R0, as_Address(addr)); |
aoqi@1 | 871 | #endif |
aoqi@6880 | 872 | break; |
aoqi@1 | 873 | case T_OBJECT: // fall through |
aoqi@6880 | 874 | case T_ARRAY: |
aoqi@1 | 875 | if (c->as_jobject() == NULL){ |
aoqi@6880 | 876 | if (UseCompressedOops && !wide) { |
aoqi@6880 | 877 | __ sw(R0, as_Address(addr)); |
aoqi@6880 | 878 | } else { |
aoqi@6880 | 879 | __ st_ptr(R0, as_Address(addr)); |
aoqi@6880 | 880 | } |
aoqi@1 | 881 | } else { |
aoqi@6880 | 882 | int oop_index = __ oop_recorder()->find_index(c->as_jobject()); |
aoqi@6880 | 883 | RelocationHolder rspec = oop_Relocation::spec(oop_index); |
aoqi@6880 | 884 | __ relocate(rspec); |
aoqi@1 | 885 | #ifndef _LP64 |
aoqi@6880 | 886 | __ lui(AT, Assembler::split_high((int)c->as_jobject())); |
aoqi@6880 | 887 | __ addiu(AT, AT, Assembler::split_low((int)c->as_jobject())); |
aoqi@6880 | 888 | __ st_ptr(AT, as_Address(addr)); |
aoqi@6880 | 889 | null_check_here = code_offset(); |
aoqi@1 | 890 | #else |
aoqi@6880 | 891 | //by_css |
aoqi@6880 | 892 | __ li64(AT, (long)c->as_jobject()); |
aoqi@6880 | 893 | if (UseCompressedOops && !wide) { |
aoqi@6880 | 894 | __ encode_heap_oop(AT); |
aoqi@6880 | 895 | null_check_here = code_offset(); |
aoqi@6880 | 896 | __ sw(AT, as_Address(addr)); |
aoqi@6880 | 897 | } else { |
aoqi@6880 | 898 | __ st_ptr(AT, as_Address(addr)); |
aoqi@6880 | 899 | } |
aoqi@1 | 900 | #endif |
aoqi@1 | 901 | } |
aoqi@1 | 902 | break; |
aoqi@1 | 903 | case T_INT: // fall through |
aoqi@6880 | 904 | case T_FLOAT: |
aoqi@6880 | 905 | if(c->as_jint_bits() != 0) { |
aoqi@1 | 906 | __ move(AT, c->as_jint_bits()); |
aoqi@1 | 907 | __ sw(AT, as_Address(addr)); |
aoqi@6880 | 908 | } else |
aoqi@1 | 909 | __ sw(R0, as_Address(addr)); |
aoqi@1 | 910 | break; |
aoqi@8865 | 911 | case T_ADDRESS: |
aoqi@8865 | 912 | __ move(AT, c->as_jint_bits()); |
aoqi@8865 | 913 | __ st_ptr(AT, as_Address(addr)); |
aoqi@8865 | 914 | break; |
aoqi@1 | 915 | case T_BOOLEAN: // fall through |
aoqi@6880 | 916 | case T_BYTE: |
aoqi@6880 | 917 | if(c->as_jint() != 0) { |
aoqi@1 | 918 | __ move(AT, c->as_jint()); |
aoqi@1 | 919 | __ sb(AT, as_Address(addr)); |
aoqi@1 | 920 | } |
aoqi@1 | 921 | else |
aoqi@1 | 922 | __ sb(R0, as_Address(addr)); |
aoqi@1 | 923 | break; |
aoqi@1 | 924 | case T_CHAR: // fall through |
aoqi@6880 | 925 | case T_SHORT: |
aoqi@6880 | 926 | if(c->as_jint() != 0) { |
aoqi@1 | 927 | __ move(AT, c->as_jint()); |
aoqi@1 | 928 | __ sh(AT, as_Address(addr)); |
aoqi@1 | 929 | } |
aoqi@1 | 930 | else |
aoqi@1 | 931 | __ sh(R0, as_Address(addr)); |
aoqi@1 | 932 | break; |
aoqi@1 | 933 | default: ShouldNotReachHere(); |
aoqi@1 | 934 | }; |
aoqi@1 | 935 | if (info != NULL) add_debug_info_for_null_check(null_check_here, info); |
aoqi@1 | 936 | } |
aoqi@1 | 937 | |
aoqi@1 | 938 | void LIR_Assembler::reg2reg(LIR_Opr src, LIR_Opr dest) { |
aoqi@1 | 939 | assert(src->is_register(), "should not call otherwise"); |
aoqi@1 | 940 | assert(dest->is_register(), "should not call otherwise"); |
aoqi@1 | 941 | if (dest->is_float_kind() && src->is_float_kind()) { |
aoqi@1 | 942 | // float to float moves |
aoqi@1 | 943 | if (dest->is_single_fpu()) { |
aoqi@1 | 944 | assert(src->is_single_fpu(), "must both be float"); |
aoqi@1 | 945 | __ mov_s(dest->as_float_reg(), src->as_float_reg()); |
aoqi@1 | 946 | } else { |
aoqi@1 | 947 | assert(src->is_double_fpu(), "must bothe be double"); |
aoqi@1 | 948 | __ mov_d( dest->as_double_reg(),src->as_double_reg()); |
aoqi@1 | 949 | } |
aoqi@1 | 950 | } else if (!dest->is_float_kind() && !src->is_float_kind()) { |
aoqi@1 | 951 | // int to int moves |
aoqi@1 | 952 | if (dest->is_single_cpu()) { |
aoqi@1 | 953 | #ifdef _LP64 |
aoqi@1 | 954 | //FIXME aoqi: copy from x86 |
aoqi@1 | 955 | if (src->type() == T_LONG) { |
aoqi@6880 | 956 | // Can do LONG -> OBJECT |
aoqi@6880 | 957 | move_regs(src->as_register_lo(), dest->as_register()); |
aoqi@6880 | 958 | return; |
aoqi@1 | 959 | } |
aoqi@1 | 960 | #endif |
aoqi@1 | 961 | assert(src->is_single_cpu(), "must match"); |
aoqi@1 | 962 | if (dest->type() == T_INT) { |
aoqi@6880 | 963 | __ move_u32(dest->as_register(), src->as_register()); |
aoqi@6880 | 964 | } else |
aoqi@6880 | 965 | move_regs(src->as_register(), dest->as_register()); |
aoqi@6880 | 966 | } else if (dest->is_double_cpu()) { |
aoqi@1 | 967 | #ifdef _LP64 |
aoqi@1 | 968 | if (src->type() == T_OBJECT || src->type() == T_ARRAY) { |
aoqi@6880 | 969 | // Surprising to me but we can see move of a long to t_object |
aoqi@6880 | 970 | __ verify_oop(src->as_register()); |
aoqi@6880 | 971 | move_regs(src->as_register(), dest->as_register_lo()); |
aoqi@6880 | 972 | return; |
aoqi@1 | 973 | } |
aoqi@1 | 974 | #endif |
aoqi@1 | 975 | Register f_lo; |
aoqi@1 | 976 | Register f_hi; |
aoqi@1 | 977 | Register t_lo; |
aoqi@1 | 978 | Register t_hi; |
aoqi@1 | 979 | |
aoqi@6880 | 980 | if (src->is_single_cpu()) { |
aoqi@1 | 981 | f_lo = src->as_register(); |
aoqi@1 | 982 | t_lo = dest->as_register_lo(); |
aoqi@6880 | 983 | } else { |
aoqi@1 | 984 | f_lo = src->as_register_lo(); |
aoqi@1 | 985 | f_hi = src->as_register_hi(); |
aoqi@1 | 986 | t_lo = dest->as_register_lo(); |
aoqi@1 | 987 | t_hi = dest->as_register_hi(); |
aoqi@1 | 988 | assert(f_hi == f_lo, "must be same"); |
aoqi@1 | 989 | assert(t_hi == t_lo, "must be same"); |
aoqi@1 | 990 | } |
aoqi@1 | 991 | #ifdef _LP64 |
aoqi@1 | 992 | move_regs(f_lo, t_lo); |
aoqi@1 | 993 | #else |
aoqi@1 | 994 | /* |
aoqi@6880 | 995 | if (src->as_register_hi() != dest->as_register_lo()) { |
aoqi@6880 | 996 | move_regs(src->as_register_lo(), dest->as_register_lo()); |
aoqi@6880 | 997 | move_regs(src->as_register_hi(), dest->as_register_hi()); |
aoqi@6880 | 998 | } else if (src->as_register_lo() != dest->as_register_hi()) { |
aoqi@6880 | 999 | move_regs(src->as_register_hi(), dest->as_register_hi()); |
aoqi@6880 | 1000 | move_regs(src->as_register_lo(), dest->as_register_lo()); |
aoqi@6880 | 1001 | } else { |
aoqi@6880 | 1002 | swap_reg(src->as_register_lo(), src->as_register_hi()); |
aoqi@6880 | 1003 | } |
aoqi@1 | 1004 | */ |
aoqi@1 | 1005 | assert(f_lo != f_hi && t_lo != t_hi, "invalid register allocation"); |
aoqi@1 | 1006 | |
aoqi@1 | 1007 | if (f_lo == t_hi && f_hi == t_lo) { |
aoqi@6880 | 1008 | swap_reg(f_lo, f_hi); |
aoqi@1 | 1009 | } else if (f_hi == t_lo) { |
aoqi@6880 | 1010 | assert(f_lo != t_hi, "overwriting register"); |
aoqi@6880 | 1011 | move_regs(f_hi, t_hi); |
aoqi@6880 | 1012 | move_regs(f_lo, t_lo); |
aoqi@1 | 1013 | } else { |
aoqi@6880 | 1014 | assert(f_hi != t_lo, "overwriting register"); |
aoqi@6880 | 1015 | move_regs(f_lo, t_lo); |
aoqi@6880 | 1016 | move_regs(f_hi, t_hi); |
aoqi@1 | 1017 | } |
aoqi@1 | 1018 | #endif // LP64 |
aoqi@1 | 1019 | } |
aoqi@1 | 1020 | } else { |
aoqi@1 | 1021 | // float to int or int to float moves |
aoqi@1 | 1022 | if (dest->is_double_cpu()) { |
aoqi@1 | 1023 | assert(src->is_double_fpu(), "must match"); |
aoqi@1 | 1024 | __ mfc1(dest->as_register_lo(), src->as_double_reg()); |
aoqi@1 | 1025 | #ifndef _LP64 |
aoqi@1 | 1026 | __ mfc1(dest->as_register_hi(), src->as_double_reg() + 1); |
aoqi@1 | 1027 | #endif |
aoqi@1 | 1028 | } else if (dest->is_single_cpu()) { |
aoqi@1 | 1029 | assert(src->is_single_fpu(), "must match"); |
aoqi@1 | 1030 | __ mfc1(dest->as_register(), src->as_float_reg()); |
aoqi@1 | 1031 | } else if (dest->is_double_fpu()) { |
aoqi@1 | 1032 | assert(src->is_double_cpu(), "must match"); |
aoqi@1 | 1033 | __ mtc1(src->as_register_lo(), dest->as_double_reg()); |
aoqi@1 | 1034 | #ifndef _LP64 |
aoqi@1 | 1035 | __ mtc1(src->as_register_hi(), dest->as_double_reg() + 1); |
aoqi@1 | 1036 | #endif |
aoqi@1 | 1037 | } else if (dest->is_single_fpu()) { |
aoqi@1 | 1038 | assert(src->is_single_cpu(), "must match"); |
aoqi@1 | 1039 | __ mtc1(src->as_register(), dest->as_float_reg()); |
aoqi@1 | 1040 | } |
aoqi@1 | 1041 | } |
aoqi@1 | 1042 | } |
aoqi@1 | 1043 | |
aoqi@1 | 1044 | |
aoqi@1 | 1045 | void LIR_Assembler::reg2stack(LIR_Opr src, LIR_Opr dest, BasicType type,bool pop_fpu_stack) { |
aoqi@1 | 1046 | assert(src->is_register(), "should not call otherwise"); |
aoqi@1 | 1047 | assert(dest->is_stack(), "should not call otherwise"); |
aoqi@1 | 1048 | |
aoqi@1 | 1049 | if (src->is_single_cpu()) { |
aoqi@1 | 1050 | Address dst = frame_map()->address_for_slot(dest->single_stack_ix()); |
aoqi@1 | 1051 | if (type == T_OBJECT || type == T_ARRAY) { |
aoqi@1 | 1052 | __ verify_oop(src->as_register()); |
aoqi@1 | 1053 | } |
aoqi@1 | 1054 | #ifdef _LP64 |
aoqi@1 | 1055 | if (type == T_INT) |
aoqi@6880 | 1056 | __ sw(src->as_register(),dst); |
aoqi@1 | 1057 | else |
aoqi@1 | 1058 | #endif |
aoqi@6880 | 1059 | __ st_ptr(src->as_register(),dst); |
aoqi@1 | 1060 | } else if (src->is_double_cpu()) { |
aoqi@1 | 1061 | Address dstLO = frame_map()->address_for_slot(dest->double_stack_ix(), lo_word_offset_in_bytes); |
aoqi@1 | 1062 | Address dstHI = frame_map()->address_for_slot(dest->double_stack_ix(), hi_word_offset_in_bytes); |
aoqi@1 | 1063 | __ st_ptr(src->as_register_lo(),dstLO); |
aoqi@1 | 1064 | NOT_LP64(__ st_ptr(src->as_register_hi(),dstHI)); |
aoqi@1 | 1065 | }else if (src->is_single_fpu()) { |
aoqi@1 | 1066 | Address dst_addr = frame_map()->address_for_slot(dest->single_stack_ix()); |
aoqi@1 | 1067 | __ swc1(src->as_float_reg(), dst_addr); |
aoqi@1 | 1068 | |
aoqi@1 | 1069 | } else if (src->is_double_fpu()) { |
aoqi@1 | 1070 | Address dst_addr = frame_map()->address_for_slot(dest->double_stack_ix()); |
aoqi@1 | 1071 | #ifndef _LP64 |
aoqi@1 | 1072 | __ swc1(src->as_double_reg(), dst_addr); |
aoqi@1 | 1073 | __ swc1(src->as_double_reg() + 1, dst_addr.base(), dst_addr.disp() + 4); |
aoqi@1 | 1074 | #else |
aoqi@1 | 1075 | __ sdc1(src->as_double_reg(), dst_addr); |
aoqi@1 | 1076 | #endif |
aoqi@1 | 1077 | |
aoqi@1 | 1078 | } else { |
aoqi@1 | 1079 | ShouldNotReachHere(); |
aoqi@1 | 1080 | } |
aoqi@1 | 1081 | } |
aoqi@1 | 1082 | |
aoqi@1 | 1083 | //FIXME |
aoqi@1 | 1084 | void LIR_Assembler::reg2mem(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info,bool pop_fpu_stack, bool wide, bool/*unaliged*/) { |
aoqi@1 | 1085 | LIR_Address* to_addr = dest->as_address_ptr(); |
aoqi@6880 | 1086 | //Register dest_reg = to_addr->base()->as_register(); |
aoqi@1 | 1087 | // FIXME aoqi |
aoqi@1 | 1088 | Register dest_reg = to_addr->base()->is_single_cpu()? to_addr->base()->as_register() : to_addr->base()->as_register_lo(); |
aoqi@1 | 1089 | PatchingStub* patch = NULL; |
aoqi@1 | 1090 | bool needs_patching = (patch_code != lir_patch_none); |
aoqi@1 | 1091 | Register disp_reg = NOREG; |
aoqi@1 | 1092 | int disp_value = to_addr->disp(); |
aoqi@1 | 1093 | /* |
aoqi@1 | 1094 | the start position of patch template is labeled by "new PatchingStub(...)" |
aoqi@1 | 1095 | during patch, T9 will be changed and not restore |
aoqi@1 | 1096 | that's why we use S7 but not T9 as compressed_src here |
aoqi@1 | 1097 | */ |
aoqi@1 | 1098 | Register compressed_src = S7; |
aoqi@1 | 1099 | |
aoqi@1 | 1100 | if (type == T_ARRAY || type == T_OBJECT) { |
aoqi@1 | 1101 | __ verify_oop(src->as_register()); |
aoqi@1 | 1102 | #ifdef _LP64 |
aoqi@1 | 1103 | if (UseCompressedOops && !wide) { |
aoqi@6880 | 1104 | __ move(compressed_src, src->as_register()); |
aoqi@6880 | 1105 | __ encode_heap_oop(compressed_src); |
aoqi@1 | 1106 | } |
aoqi@1 | 1107 | #endif |
aoqi@1 | 1108 | } |
aoqi@1 | 1109 | |
aoqi@1 | 1110 | if (needs_patching) { |
aoqi@1 | 1111 | patch = new PatchingStub(_masm, PatchingStub::access_field_id); |
aoqi@6880 | 1112 | assert(!src->is_double_cpu() || |
aoqi@6880 | 1113 | patch_code == lir_patch_none || |
aoqi@6880 | 1114 | patch_code == lir_patch_normal, |
aoqi@6880 | 1115 | "patching doesn't match register"); |
aoqi@1 | 1116 | Address toa = as_Address(to_addr); |
aoqi@1 | 1117 | assert(toa.disp() != 0, "must have"); |
aoqi@1 | 1118 | } |
aoqi@1 | 1119 | |
aoqi@1 | 1120 | if (info != NULL) { |
aoqi@1 | 1121 | add_debug_info_for_null_check_here(info); |
aoqi@1 | 1122 | } |
aoqi@1 | 1123 | if (needs_patching) { |
aoqi@1 | 1124 | disp_reg = AT; |
aoqi@1 | 1125 | __ lui(AT, Assembler::split_high(disp_value)); |
aoqi@1 | 1126 | __ addiu(AT, AT, Assembler::split_low(disp_value)); |
aoqi@6880 | 1127 | } else if (!Assembler::is_simm16(disp_value)) { |
aoqi@1 | 1128 | disp_reg = AT; |
aoqi@1 | 1129 | __ lui(AT, Assembler::split_high(disp_value)); |
aoqi@1 | 1130 | } |
aoqi@1 | 1131 | int offset = code_offset(); |
aoqi@1 | 1132 | |
aoqi@1 | 1133 | switch(type) { |
aoqi@1 | 1134 | case T_DOUBLE: |
aoqi@1 | 1135 | assert(src->is_double_fpu(), "just check"); |
aoqi@1 | 1136 | if (disp_reg == noreg) { |
aoqi@1 | 1137 | #ifndef _LP64 |
aoqi@6880 | 1138 | __ swc1(src->as_double_reg(), dest_reg, disp_value); |
aoqi@6880 | 1139 | __ swc1(src->as_double_reg()+1, dest_reg, disp_value+4); |
aoqi@1 | 1140 | #else |
aoqi@6880 | 1141 | __ sdc1(src->as_double_reg(), dest_reg, disp_value); |
aoqi@1 | 1142 | #endif |
aoqi@1 | 1143 | } else if (needs_patching) { |
aoqi@6880 | 1144 | __ add(AT, dest_reg, disp_reg); |
aoqi@1 | 1145 | #ifndef _LP64 |
aoqi@6880 | 1146 | __ swc1(src->as_double_reg(), AT, 0); |
aoqi@6880 | 1147 | __ swc1(src->as_double_reg()+1, AT, 4); |
aoqi@1 | 1148 | #else |
aoqi@6880 | 1149 | __ sdc1(src->as_double_reg(), AT, 0); |
aoqi@1 | 1150 | #endif |
aoqi@1 | 1151 | } else { |
aoqi@6880 | 1152 | __ add(AT, dest_reg, disp_reg); |
aoqi@1 | 1153 | #ifndef _LP64 |
aoqi@6880 | 1154 | __ swc1(src->as_double_reg(), AT, Assembler::split_low(disp_value)); |
aoqi@6880 | 1155 | __ swc1(src->as_double_reg()+1, AT, Assembler::split_low(disp_value) + 4); |
aoqi@1 | 1156 | #else |
aoqi@6880 | 1157 | __ sdc1(src->as_double_reg(), AT, Assembler::split_low(disp_value)); |
aoqi@1 | 1158 | #endif |
aoqi@1 | 1159 | } |
aoqi@1 | 1160 | break; |
aoqi@1 | 1161 | |
aoqi@1 | 1162 | case T_FLOAT: |
aoqi@1 | 1163 | if (disp_reg == noreg) { |
aoqi@6880 | 1164 | __ swc1(src->as_float_reg(), dest_reg, disp_value); |
aoqi@1 | 1165 | } else if(needs_patching) { |
aoqi@6880 | 1166 | __ add(AT, dest_reg, disp_reg); |
aoqi@6880 | 1167 | __ swc1(src->as_float_reg(), AT, 0); |
aoqi@1 | 1168 | } else { |
aoqi@6880 | 1169 | __ add(AT, dest_reg, disp_reg); |
aoqi@6880 | 1170 | __ swc1(src->as_float_reg(), AT, Assembler::split_low(disp_value)); |
aoqi@1 | 1171 | } |
aoqi@1 | 1172 | break; |
aoqi@1 | 1173 | |
aoqi@1 | 1174 | case T_LONG: { |
aoqi@8865 | 1175 | Register from_lo = src->as_register_lo(); |
aoqi@6880 | 1176 | Register from_hi = src->as_register_hi(); |
aoqi@1 | 1177 | #ifdef _LP64 |
aoqi@6880 | 1178 | if (needs_patching) { |
aoqi@6880 | 1179 | __ add(AT, dest_reg, disp_reg); |
aoqi@6880 | 1180 | __ st_ptr(from_lo, AT, 0); |
aoqi@6880 | 1181 | } else { |
aoqi@6880 | 1182 | __ st_ptr(from_lo, as_Address_lo(to_addr)); |
aoqi@6880 | 1183 | } |
aoqi@1 | 1184 | #else |
aoqi@6880 | 1185 | Register base = to_addr->base()->as_register(); |
aoqi@6880 | 1186 | Register index = noreg; |
aoqi@6880 | 1187 | if (to_addr->index()->is_register()) { |
aoqi@6880 | 1188 | index = to_addr->index()->as_register(); |
aoqi@6880 | 1189 | } |
aoqi@6880 | 1190 | if (base == from_lo || index == from_lo) { |
aoqi@6880 | 1191 | assert(base != from_hi, "can't be"); |
aoqi@6880 | 1192 | assert(index == noreg || (index != base && index != from_hi), "can't handle this"); |
aoqi@6880 | 1193 | if (needs_patching) { |
aoqi@6880 | 1194 | __ add(AT, dest_reg, disp_reg); |
aoqi@6880 | 1195 | NOT_LP64(__ st_ptr(from_hi, AT, longSize/2);) |
aoqi@6880 | 1196 | __ st_ptr(from_lo, AT, 0); |
aoqi@6880 | 1197 | } else { |
aoqi@6880 | 1198 | __ st_ptr(from_hi, as_Address_hi(to_addr)); |
aoqi@6880 | 1199 | __ st_ptr(from_lo, as_Address_lo(to_addr)); |
aoqi@6880 | 1200 | } |
aoqi@6880 | 1201 | } else { |
aoqi@6880 | 1202 | assert(index == noreg || (index != base && index != from_lo), "can't handle this"); |
aoqi@6880 | 1203 | if (needs_patching) { |
aoqi@6880 | 1204 | __ add(AT, dest_reg, disp_reg); |
aoqi@6880 | 1205 | __ st_ptr(from_lo, AT, 0); |
aoqi@6880 | 1206 | __ st_ptr(from_hi, AT, longSize/2); |
aoqi@6880 | 1207 | } else { |
aoqi@6880 | 1208 | __ st_ptr(from_lo, as_Address_lo(to_addr)); |
aoqi@6880 | 1209 | __ st_ptr(from_hi, as_Address_hi(to_addr)); |
aoqi@6880 | 1210 | } |
aoqi@6880 | 1211 | } |
aoqi@1 | 1212 | #endif |
aoqi@6880 | 1213 | break; |
aoqi@6880 | 1214 | } |
aoqi@1 | 1215 | case T_ARRAY: |
aoqi@1 | 1216 | case T_OBJECT: |
aoqi@1 | 1217 | #ifdef _LP64 |
aoqi@6880 | 1218 | if (UseCompressedOops && !wide) { |
aoqi@6880 | 1219 | if (disp_reg == noreg) { |
aoqi@6880 | 1220 | __ sw(compressed_src, dest_reg, disp_value); |
aoqi@6880 | 1221 | } else if (needs_patching) { |
aoqi@6880 | 1222 | __ add(AT, dest_reg, disp_reg); |
aoqi@6880 | 1223 | __ sw(compressed_src, AT, 0); |
aoqi@6880 | 1224 | } else { |
aoqi@6880 | 1225 | __ add(AT, dest_reg, disp_reg); |
aoqi@6880 | 1226 | __ sw(compressed_src, AT, Assembler::split_low(disp_value)); |
aoqi@6880 | 1227 | } |
aoqi@6880 | 1228 | } else { |
aoqi@6880 | 1229 | if (disp_reg == noreg) { |
aoqi@6880 | 1230 | __ st_ptr(src->as_register(), dest_reg, disp_value); |
aoqi@6880 | 1231 | } else if (needs_patching) { |
aoqi@6880 | 1232 | __ add(AT, dest_reg, disp_reg); |
aoqi@6880 | 1233 | __ st_ptr(src->as_register(), AT, 0); |
aoqi@6880 | 1234 | } else { |
aoqi@6880 | 1235 | __ add(AT, dest_reg, disp_reg); |
aoqi@6880 | 1236 | __ st_ptr(src->as_register(), AT, Assembler::split_low(disp_value)); |
aoqi@6880 | 1237 | } |
aoqi@6880 | 1238 | } |
aoqi@6880 | 1239 | break; |
aoqi@1 | 1240 | #endif |
aoqi@1 | 1241 | case T_ADDRESS: |
aoqi@1 | 1242 | #ifdef _LP64 |
aoqi@6880 | 1243 | if (disp_reg == noreg) { |
aoqi@6880 | 1244 | __ st_ptr(src->as_register(), dest_reg, disp_value); |
aoqi@6880 | 1245 | } else if (needs_patching) { |
aoqi@6880 | 1246 | __ add(AT, dest_reg, disp_reg); |
aoqi@6880 | 1247 | __ st_ptr(src->as_register(), AT, 0); |
aoqi@6880 | 1248 | } else { |
aoqi@6880 | 1249 | __ add(AT, dest_reg, disp_reg); |
aoqi@6880 | 1250 | __ st_ptr(src->as_register(), AT, Assembler::split_low(disp_value)); |
aoqi@6880 | 1251 | } |
aoqi@6880 | 1252 | break; |
aoqi@1 | 1253 | #endif |
aoqi@1 | 1254 | case T_INT: |
aoqi@6880 | 1255 | if (disp_reg == noreg) { |
aoqi@6880 | 1256 | __ sw(src->as_register(), dest_reg, disp_value); |
aoqi@6880 | 1257 | } else if (needs_patching) { |
aoqi@6880 | 1258 | __ add(AT, dest_reg, disp_reg); |
aoqi@6880 | 1259 | __ sw(src->as_register(), AT, 0); |
aoqi@6880 | 1260 | } else { |
aoqi@6880 | 1261 | __ add(AT, dest_reg, disp_reg); |
aoqi@6880 | 1262 | __ sw(src->as_register(), AT, Assembler::split_low(disp_value)); |
aoqi@6880 | 1263 | } |
aoqi@6880 | 1264 | break; |
aoqi@1 | 1265 | |
aoqi@1 | 1266 | case T_CHAR: |
aoqi@1 | 1267 | case T_SHORT: |
aoqi@6880 | 1268 | if (disp_reg == noreg) { |
aoqi@6880 | 1269 | __ sh(src->as_register(), dest_reg, disp_value); |
aoqi@6880 | 1270 | } else if (needs_patching) { |
aoqi@6880 | 1271 | __ add(AT, dest_reg, disp_reg); |
aoqi@6880 | 1272 | __ sh(src->as_register(), AT, 0); |
aoqi@6880 | 1273 | } else { |
aoqi@6880 | 1274 | __ add(AT, dest_reg, disp_reg); |
aoqi@6880 | 1275 | __ sh(src->as_register(), AT, Assembler::split_low(disp_value)); |
aoqi@6880 | 1276 | } |
aoqi@6880 | 1277 | break; |
aoqi@1 | 1278 | |
aoqi@1 | 1279 | case T_BYTE: |
aoqi@1 | 1280 | case T_BOOLEAN: |
aoqi@6880 | 1281 | assert(src->is_single_cpu(), "just check"); |
aoqi@6880 | 1282 | |
aoqi@6880 | 1283 | if (disp_reg == noreg) { |
aoqi@6880 | 1284 | __ sb(src->as_register(), dest_reg, disp_value); |
aoqi@6880 | 1285 | } else if (needs_patching) { |
aoqi@6880 | 1286 | __ add(AT, dest_reg, disp_reg); |
aoqi@6880 | 1287 | __ sb(src->as_register(), AT, 0); |
aoqi@6880 | 1288 | } else { |
aoqi@6880 | 1289 | __ add(AT, dest_reg, disp_reg); |
aoqi@6880 | 1290 | __ sb(src->as_register(), AT, Assembler::split_low(disp_value)); |
aoqi@6880 | 1291 | } |
aoqi@6880 | 1292 | break; |
aoqi@1 | 1293 | |
aoqi@1 | 1294 | default: |
aoqi@6880 | 1295 | ShouldNotReachHere(); |
aoqi@1 | 1296 | } |
aoqi@1 | 1297 | |
aoqi@1 | 1298 | |
aoqi@1 | 1299 | if (needs_patching) { |
aoqi@1 | 1300 | patching_epilog(patch, patch_code, to_addr->base()->as_register(), info); |
aoqi@1 | 1301 | } |
aoqi@1 | 1302 | } |
aoqi@1 | 1303 | |
aoqi@1 | 1304 | |
aoqi@1 | 1305 | |
aoqi@1 | 1306 | void LIR_Assembler::stack2reg(LIR_Opr src, LIR_Opr dest, BasicType type) { |
aoqi@1 | 1307 | assert(src->is_stack(), "should not call otherwise"); |
aoqi@1 | 1308 | assert(dest->is_register(), "should not call otherwise"); |
aoqi@6880 | 1309 | |
aoqi@1 | 1310 | if (dest->is_single_cpu()) { |
aoqi@1 | 1311 | #ifdef _LP64 |
aoqi@1 | 1312 | if (type == T_INT) |
aoqi@1 | 1313 | __ lw(dest->as_register(), frame_map()->address_for_slot(src->single_stack_ix())); |
aoqi@1 | 1314 | else |
aoqi@1 | 1315 | #endif |
aoqi@1 | 1316 | __ ld_ptr(dest->as_register(), frame_map()->address_for_slot(src->single_stack_ix())); |
aoqi@1 | 1317 | if (type == T_ARRAY || type == T_OBJECT) { |
aoqi@1 | 1318 | __ verify_oop(dest->as_register()); |
aoqi@1 | 1319 | } |
aoqi@1 | 1320 | } else if (dest->is_double_cpu()) { |
aoqi@1 | 1321 | #ifdef _LP64 |
aoqi@1 | 1322 | /* java.util.concurrent.locks.ReentrantReadWriteLock$Sync::tryAcquire |
aoqi@1 | 1323 | |
aoqi@6880 | 1324 | 88 move [stack:2|L] [a5a5|J] |
aoqi@1 | 1325 | OpenJDK 64-Bit Client VM warning: /mnt/openjdk6-mips/hotspot/src/share/c1/c1_LIR.hpp, 397 , assert(is_double_stack() && !is_virtual(),"type check") |
aoqi@1 | 1326 | OpenJDK 64-Bit Client VM warning: /mnt/openjdk6-mips/hotspot/src/share/c1/c1_LIR.hpp, 397 , assert(is_double_stack() && !is_virtual(),"type check") |
aoqi@1 | 1327 | 0x000000556197af8c: ld a5, 0x50(sp) |
aoqi@1 | 1328 | */ |
aoqi@1 | 1329 | Address src_addr_LO; |
aoqi@1 | 1330 | if (src->is_single_stack()) |
aoqi@1 | 1331 | src_addr_LO = frame_map()->address_for_slot(src->single_stack_ix(),lo_word_offset_in_bytes); |
aoqi@1 | 1332 | else if (src->is_double_stack()) |
aoqi@1 | 1333 | src_addr_LO = frame_map()->address_for_slot(src->double_stack_ix(),lo_word_offset_in_bytes); |
aoqi@1 | 1334 | else |
aoqi@1 | 1335 | ShouldNotReachHere(); |
aoqi@1 | 1336 | #else |
aoqi@1 | 1337 | Address src_addr_LO = frame_map()->address_for_slot(src->double_stack_ix(),lo_word_offset_in_bytes); |
aoqi@1 | 1338 | Address src_addr_HI = frame_map()->address_for_slot(src->double_stack_ix(), hi_word_offset_in_bytes); |
aoqi@1 | 1339 | #endif |
aoqi@1 | 1340 | #ifdef _LP64 |
aoqi@1 | 1341 | if (src->type() == T_INT) |
aoqi@1 | 1342 | __ lw(dest->as_register_lo(), src_addr_LO); |
aoqi@1 | 1343 | else |
aoqi@1 | 1344 | #endif |
aoqi@1 | 1345 | __ ld_ptr(dest->as_register_lo(), src_addr_LO); |
aoqi@1 | 1346 | NOT_LP64(__ ld_ptr(dest->as_register_hi(), src_addr_HI)); |
aoqi@1 | 1347 | }else if (dest->is_single_fpu()) { |
aoqi@1 | 1348 | Address addr = frame_map()->address_for_slot(src->single_stack_ix()); |
aoqi@1 | 1349 | __ lwc1(dest->as_float_reg(), addr); |
aoqi@1 | 1350 | } else if (dest->is_double_fpu()) { |
aoqi@1 | 1351 | Address src_addr_LO = frame_map()->address_for_slot(src->double_stack_ix(),lo_word_offset_in_bytes); |
aoqi@1 | 1352 | #ifndef _LP64 |
aoqi@1 | 1353 | Address src_addr_HI = frame_map()->address_for_slot(src->double_stack_ix(), hi_word_offset_in_bytes); |
aoqi@1 | 1354 | __ lwc1(dest->as_double_reg(), src_addr_LO); |
aoqi@1 | 1355 | __ lwc1(dest->as_double_reg()+1, src_addr_HI); |
aoqi@1 | 1356 | #else |
aoqi@1 | 1357 | __ ldc1(dest->as_double_reg(), src_addr_LO); |
aoqi@1 | 1358 | #endif |
aoqi@1 | 1359 | } else { |
aoqi@1 | 1360 | ShouldNotReachHere(); |
aoqi@1 | 1361 | /* |
aoqi@1 | 1362 | assert(dest->is_single_cpu(), "cannot be anything else but a single cpu"); |
aoqi@1 | 1363 | assert(type!= T_ILLEGAL, "Bad type in stack2reg") |
aoqi@1 | 1364 | Address addr = frame_map()->address_for_slot(src->single_stack_ix()); |
aoqi@1 | 1365 | __ lw(dest->as_register(), addr); |
aoqi@1 | 1366 | */ |
aoqi@1 | 1367 | } |
aoqi@1 | 1368 | } |
aoqi@1 | 1369 | |
aoqi@1 | 1370 | void LIR_Assembler::stack2stack(LIR_Opr src, LIR_Opr dest, BasicType type) { |
aoqi@1 | 1371 | if (src->is_single_stack()) { |
aoqi@6880 | 1372 | /* |
aoqi@6880 | 1373 | * 2012/5/23 Jin: YozoOffice(-Xcomp) corrupts in "New File -> word" |
aoqi@6880 | 1374 | * |
aoqi@6880 | 1375 | * [b.q.e.a.z::bw()] |
aoqi@6880 | 1376 | * move [stack:15|L] [stack:17|L] |
aoqi@6880 | 1377 | * 0x00000055584e7cf4: lw at, 0x78(sp) <--- error! |
aoqi@6880 | 1378 | * 0x00000055584e7cf8: sw at, 0x88(sp) |
aoqi@6880 | 1379 | */ |
aoqi@6880 | 1380 | if (type == T_OBJECT ) |
aoqi@6880 | 1381 | { |
aoqi@6880 | 1382 | __ ld(AT, frame_map()->address_for_slot(src ->single_stack_ix())); |
aoqi@6880 | 1383 | __ sd(AT, frame_map()->address_for_slot(dest->single_stack_ix())); |
aoqi@6880 | 1384 | } |
aoqi@6880 | 1385 | else |
aoqi@6880 | 1386 | { |
aoqi@6880 | 1387 | __ lw(AT, frame_map()->address_for_slot(src ->single_stack_ix())); |
aoqi@6880 | 1388 | __ sw(AT, frame_map()->address_for_slot(dest->single_stack_ix())); |
aoqi@6880 | 1389 | } |
aoqi@1 | 1390 | } else if (src->is_double_stack()) { |
aoqi@1 | 1391 | #ifndef _LP64 |
aoqi@6880 | 1392 | __ lw(AT, frame_map()->address_for_slot(src ->double_stack_ix())); |
aoqi@6880 | 1393 | __ sw(AT, frame_map()->address_for_slot(dest->double_stack_ix())); |
aoqi@6880 | 1394 | __ lw(AT, frame_map()->address_for_slot(src ->double_stack_ix(),4)); |
aoqi@6880 | 1395 | __ sw(AT, frame_map()->address_for_slot(dest ->double_stack_ix(),4)); |
aoqi@1 | 1396 | #else |
aoqi@6880 | 1397 | __ ld_ptr(AT, frame_map()->address_for_slot(src ->double_stack_ix())); |
aoqi@6880 | 1398 | __ st_ptr(AT, frame_map()->address_for_slot(dest->double_stack_ix())); |
aoqi@1 | 1399 | #endif |
aoqi@1 | 1400 | } else { |
aoqi@1 | 1401 | ShouldNotReachHere(); |
aoqi@1 | 1402 | } |
aoqi@1 | 1403 | } |
aoqi@1 | 1404 | |
aoqi@1 | 1405 | // if patching needed, be sure the instruction at offset is a MoveMemReg |
aoqi@1 | 1406 | void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_PatchCode patch_code, CodeEmitInfo* info, bool wide, bool) { |
aoqi@1 | 1407 | assert(src->is_address(), "should not call otherwise"); |
aoqi@1 | 1408 | assert(dest->is_register(), "should not call otherwise"); |
aoqi@1 | 1409 | LIR_Address* addr = src->as_address_ptr(); |
aoqi@1 | 1410 | //Address from_addr = as_Address(addr); |
aoqi@1 | 1411 | |
aoqi@1 | 1412 | //Register src_reg = addr->base()->as_register(); |
aoqi@1 | 1413 | // FIXME aoqi |
aoqi@1 | 1414 | Register src_reg = addr->base()->is_single_cpu()? addr->base()->as_register() : addr->base()->as_register_lo(); |
aoqi@1 | 1415 | Register disp_reg = noreg; |
aoqi@1 | 1416 | int disp_value = addr->disp(); |
aoqi@1 | 1417 | bool needs_patching = (patch_code != lir_patch_none); |
aoqi@1 | 1418 | |
aoqi@1 | 1419 | PatchingStub* patch = NULL; |
aoqi@1 | 1420 | if (needs_patching) { |
aoqi@1 | 1421 | patch = new PatchingStub(_masm, PatchingStub::access_field_id); |
aoqi@1 | 1422 | } |
aoqi@1 | 1423 | |
aoqi@6880 | 1424 | // we must use lui&addiu, |
aoqi@1 | 1425 | if (needs_patching) { |
aoqi@1 | 1426 | disp_reg = AT; |
aoqi@1 | 1427 | __ lui(AT, Assembler::split_high(disp_value)); |
aoqi@1 | 1428 | __ addiu(AT, AT, Assembler::split_low(disp_value)); |
aoqi@1 | 1429 | } else if (!Assembler::is_simm16(disp_value)) { |
aoqi@1 | 1430 | disp_reg = AT; |
aoqi@1 | 1431 | __ lui(AT, Assembler::split_high(disp_value)); |
aoqi@1 | 1432 | } |
aoqi@1 | 1433 | |
aoqi@1 | 1434 | // remember the offset of the load. The patching_epilog must be done |
aoqi@1 | 1435 | // before the call to add_debug_info, otherwise the PcDescs don't get |
aoqi@1 | 1436 | // entered in increasing order. |
aoqi@1 | 1437 | int offset = code_offset(); |
aoqi@1 | 1438 | |
aoqi@1 | 1439 | switch(type) { |
aoqi@1 | 1440 | case T_BOOLEAN: |
aoqi@1 | 1441 | case T_BYTE: { |
aoqi@6880 | 1442 | //assert(to_reg.is_word(), "just check"); |
aoqi@6880 | 1443 | if (disp_reg == noreg) { |
aoqi@6880 | 1444 | __ lb(dest->as_register(), src_reg, disp_value); |
aoqi@6880 | 1445 | } else if (needs_patching) { |
aoqi@6880 | 1446 | __ add(AT, src_reg, disp_reg); |
aoqi@6880 | 1447 | offset = code_offset(); |
aoqi@6880 | 1448 | __ lb(dest->as_register(), AT, 0); |
aoqi@6880 | 1449 | } else { |
aoqi@6880 | 1450 | __ add(AT, src_reg, disp_reg); |
aoqi@6880 | 1451 | offset = code_offset(); |
aoqi@6880 | 1452 | __ lb(dest->as_register(), AT, Assembler::split_low(disp_value)); |
aoqi@6880 | 1453 | } |
aoqi@6880 | 1454 | } |
aoqi@6880 | 1455 | break; |
aoqi@1 | 1456 | |
aoqi@1 | 1457 | case T_CHAR: { |
aoqi@6880 | 1458 | //assert(to_reg.is_word(), "just check"); |
aoqi@6880 | 1459 | if (disp_reg == noreg) { |
aoqi@6880 | 1460 | __ lhu(dest->as_register(), src_reg, disp_value); |
aoqi@6880 | 1461 | } else if (needs_patching) { |
aoqi@6880 | 1462 | __ add(AT, src_reg, disp_reg); |
aoqi@6880 | 1463 | offset = code_offset(); |
aoqi@6880 | 1464 | __ lhu(dest->as_register(), AT, 0); |
aoqi@6880 | 1465 | } else { |
aoqi@6880 | 1466 | __ add(AT, src_reg, disp_reg); |
aoqi@6880 | 1467 | offset = code_offset(); |
aoqi@6880 | 1468 | __ lhu(dest->as_register(), AT, Assembler::split_low(disp_value)); |
aoqi@6880 | 1469 | } |
aoqi@6880 | 1470 | } |
aoqi@6880 | 1471 | break; |
aoqi@1 | 1472 | |
aoqi@1 | 1473 | case T_SHORT: { |
aoqi@6880 | 1474 | // assert(to_reg.is_word(), "just check"); |
aoqi@6880 | 1475 | if (disp_reg == noreg) { |
aoqi@6880 | 1476 | __ lh(dest->as_register(), src_reg, disp_value); |
aoqi@6880 | 1477 | } else if (needs_patching) { |
aoqi@6880 | 1478 | __ add(AT, src_reg, disp_reg); |
aoqi@6880 | 1479 | offset = code_offset(); |
aoqi@6880 | 1480 | __ lh(dest->as_register(), AT, 0); |
aoqi@6880 | 1481 | } else { |
aoqi@6880 | 1482 | __ add(AT, src_reg, disp_reg); |
aoqi@6880 | 1483 | offset = code_offset(); |
aoqi@6880 | 1484 | __ lh(dest->as_register(), AT, Assembler::split_low(disp_value)); |
aoqi@6880 | 1485 | } |
aoqi@6880 | 1486 | } |
aoqi@6880 | 1487 | break; |
aoqi@1 | 1488 | |
aoqi@1 | 1489 | case T_OBJECT: |
aoqi@6880 | 1490 | case T_ARRAY: |
aoqi@6880 | 1491 | if (UseCompressedOops && !wide) { |
aoqi@6880 | 1492 | if (disp_reg == noreg) { |
aoqi@8865 | 1493 | __ lwu(dest->as_register(), src_reg, disp_value); |
aoqi@6880 | 1494 | } else if (needs_patching) { |
aoqi@8865 | 1495 | __ dadd(AT, src_reg, disp_reg); |
aoqi@8865 | 1496 | offset = code_offset(); |
aoqi@8865 | 1497 | __ lwu(dest->as_register(), AT, 0); |
aoqi@6880 | 1498 | } else { |
aoqi@8865 | 1499 | __ dadd(AT, src_reg, disp_reg); |
aoqi@8865 | 1500 | offset = code_offset(); |
aoqi@8865 | 1501 | __ lwu(dest->as_register(), AT, Assembler::split_low(disp_value)); |
aoqi@6880 | 1502 | } |
aoqi@6880 | 1503 | } else { |
aoqi@6880 | 1504 | if (disp_reg == noreg) { |
aoqi@8865 | 1505 | __ ld_ptr(dest->as_register(), src_reg, disp_value); |
aoqi@6880 | 1506 | } else if (needs_patching) { |
aoqi@8865 | 1507 | __ dadd(AT, src_reg, disp_reg); |
aoqi@8865 | 1508 | offset = code_offset(); |
aoqi@8865 | 1509 | __ ld_ptr(dest->as_register(), AT, 0); |
aoqi@6880 | 1510 | } else { |
aoqi@8865 | 1511 | __ dadd(AT, src_reg, disp_reg); |
aoqi@8865 | 1512 | offset = code_offset(); |
aoqi@8865 | 1513 | __ ld_ptr(dest->as_register(), AT, Assembler::split_low(disp_value)); |
aoqi@6880 | 1514 | } |
aoqi@6880 | 1515 | } |
aoqi@6880 | 1516 | break; |
aoqi@1 | 1517 | case T_ADDRESS: |
aoqi@8865 | 1518 | if (UseCompressedClassPointers && addr->disp() == oopDesc::klass_offset_in_bytes()) { |
aoqi@8865 | 1519 | if (disp_reg == noreg) { |
aoqi@8865 | 1520 | __ lwu(dest->as_register(), src_reg, disp_value); |
aoqi@8865 | 1521 | } else if (needs_patching) { |
aoqi@8865 | 1522 | __ dadd(AT, src_reg, disp_reg); |
aoqi@8865 | 1523 | offset = code_offset(); |
aoqi@8865 | 1524 | __ lwu(dest->as_register(), AT, 0); |
aoqi@8865 | 1525 | } else { |
aoqi@8865 | 1526 | __ dadd(AT, src_reg, disp_reg); |
aoqi@8865 | 1527 | offset = code_offset(); |
aoqi@8865 | 1528 | __ lwu(dest->as_register(), AT, Assembler::split_low(disp_value)); |
aoqi@8865 | 1529 | } |
aoqi@8865 | 1530 | } else { |
aoqi@8865 | 1531 | if (disp_reg == noreg) { |
aoqi@6880 | 1532 | __ ld_ptr(dest->as_register(), src_reg, disp_value); |
aoqi@8865 | 1533 | } else if (needs_patching) { |
aoqi@6880 | 1534 | __ dadd(AT, src_reg, disp_reg); |
aoqi@6880 | 1535 | offset = code_offset(); |
aoqi@6880 | 1536 | __ ld_ptr(dest->as_register(), AT, 0); |
aoqi@8865 | 1537 | } else { |
aoqi@6880 | 1538 | __ dadd(AT, src_reg, disp_reg); |
aoqi@6880 | 1539 | offset = code_offset(); |
aoqi@6880 | 1540 | __ ld_ptr(dest->as_register(), AT, Assembler::split_low(disp_value)); |
aoqi@8865 | 1541 | } |
aoqi@6880 | 1542 | } |
aoqi@6880 | 1543 | break; |
aoqi@6880 | 1544 | case T_INT: { |
aoqi@6880 | 1545 | //assert(to_reg.is_word(), "just check"); |
aoqi@6880 | 1546 | if (disp_reg == noreg) { |
aoqi@6880 | 1547 | __ lw(dest->as_register(), src_reg, disp_value); |
aoqi@6880 | 1548 | } else if (needs_patching) { |
aoqi@6880 | 1549 | __ add(AT, src_reg, disp_reg); |
aoqi@6880 | 1550 | offset = code_offset(); |
aoqi@6880 | 1551 | __ lw(dest->as_register(), AT, 0); |
aoqi@6880 | 1552 | } else { |
aoqi@6880 | 1553 | __ add(AT, src_reg, disp_reg); |
aoqi@6880 | 1554 | offset = code_offset(); |
aoqi@6880 | 1555 | __ lw(dest->as_register(), AT, Assembler::split_low(disp_value)); |
aoqi@6880 | 1556 | } |
aoqi@6880 | 1557 | } |
aoqi@6880 | 1558 | break; |
aoqi@1 | 1559 | |
aoqi@1 | 1560 | case T_LONG: { |
aoqi@6880 | 1561 | Register to_lo = dest->as_register_lo(); |
aoqi@6880 | 1562 | Register to_hi = dest->as_register_hi(); |
aoqi@1 | 1563 | #ifdef _LP64 |
aoqi@6880 | 1564 | if (needs_patching) { |
aoqi@6880 | 1565 | __ add(AT, src_reg, disp_reg); |
aoqi@6880 | 1566 | __ ld_ptr(to_lo, AT, 0); |
aoqi@6880 | 1567 | } else { |
aoqi@6880 | 1568 | __ ld_ptr(to_lo, as_Address_lo(addr)); |
aoqi@6880 | 1569 | } |
aoqi@1 | 1570 | #else |
aoqi@6880 | 1571 | Register base = addr->base()->as_register(); |
aoqi@6880 | 1572 | Register index = noreg; |
aoqi@6880 | 1573 | if (addr->index()->is_register()) { |
aoqi@6880 | 1574 | index = addr->index()->as_register(); |
aoqi@6880 | 1575 | } |
aoqi@6880 | 1576 | if ((base == to_lo && index == to_hi) ||(base == to_hi && index == to_lo)) { |
aoqi@6880 | 1577 | // addresses with 2 registers are only formed as a result of |
aoqi@6880 | 1578 | // array access so this code will never have to deal with |
aoqi@6880 | 1579 | // patches or null checks. |
aoqi@6880 | 1580 | assert(info == NULL && patch == NULL, "must be"); |
aoqi@6880 | 1581 | __ lea(to_hi, as_Address(addr)); |
aoqi@6880 | 1582 | __ lw(to_lo, Address(to_hi)); |
aoqi@6880 | 1583 | __ lw(to_hi, Address(to_hi, BytesPerWord)); |
aoqi@6880 | 1584 | } else if (base == to_lo || index == to_lo) { |
aoqi@6880 | 1585 | assert(base != to_hi, "can't be"); |
aoqi@6880 | 1586 | assert(index == noreg || (index != base && index != to_hi), "can't handle this"); |
aoqi@6880 | 1587 | if (needs_patching) { |
aoqi@6880 | 1588 | __ add(AT, src_reg, disp_reg); |
aoqi@6880 | 1589 | offset = code_offset(); |
aoqi@6880 | 1590 | __ lw(to_hi, AT, longSize/2); |
aoqi@6880 | 1591 | __ lw(to_lo, AT, 0); |
aoqi@6880 | 1592 | } else { |
aoqi@6880 | 1593 | __ lw(to_hi, as_Address_hi(addr)); |
aoqi@6880 | 1594 | __ lw(to_lo, as_Address_lo(addr)); |
aoqi@6880 | 1595 | } |
aoqi@6880 | 1596 | } else { |
aoqi@6880 | 1597 | assert(index == noreg || (index != base && index != to_lo), "can't handle this"); |
aoqi@6880 | 1598 | if (needs_patching) { |
aoqi@6880 | 1599 | __ add(AT, src_reg, disp_reg); |
aoqi@6880 | 1600 | offset = code_offset(); |
aoqi@6880 | 1601 | __ lw(to_lo, AT, 0); |
aoqi@6880 | 1602 | __ lw(to_hi, AT, longSize/2); |
aoqi@6880 | 1603 | } else { |
aoqi@6880 | 1604 | __ lw(to_lo, as_Address_lo(addr)); |
aoqi@6880 | 1605 | __ lw(to_hi, as_Address_hi(addr)); |
aoqi@6880 | 1606 | } |
aoqi@6880 | 1607 | } |
aoqi@1 | 1608 | #endif |
aoqi@6880 | 1609 | } |
aoqi@6880 | 1610 | break; |
aoqi@1 | 1611 | |
aoqi@1 | 1612 | case T_FLOAT: { |
aoqi@6880 | 1613 | //assert(to_reg.is_float(), "just check"); |
aoqi@6880 | 1614 | if (disp_reg == noreg) { |
aoqi@6880 | 1615 | __ lwc1(dest->as_float_reg(), src_reg, disp_value); |
aoqi@6880 | 1616 | } else if (needs_patching) { |
aoqi@6880 | 1617 | __ add(AT, src_reg, disp_reg); |
aoqi@6880 | 1618 | offset = code_offset(); |
aoqi@6880 | 1619 | __ lwc1(dest->as_float_reg(), AT, 0); |
aoqi@6880 | 1620 | } else { |
aoqi@6880 | 1621 | __ add(AT, src_reg, disp_reg); |
aoqi@6880 | 1622 | offset = code_offset(); |
aoqi@6880 | 1623 | __ lwc1(dest->as_float_reg(), AT, Assembler::split_low(disp_value)); |
aoqi@6880 | 1624 | } |
aoqi@6880 | 1625 | } |
aoqi@6880 | 1626 | break; |
aoqi@1 | 1627 | |
aoqi@1 | 1628 | case T_DOUBLE: { |
aoqi@6880 | 1629 | //assert(to_reg.is_double(), "just check"); |
aoqi@6880 | 1630 | |
aoqi@6880 | 1631 | if (disp_reg == noreg) { |
aoqi@1 | 1632 | #ifndef _LP64 |
aoqi@6880 | 1633 | __ lwc1(dest->as_double_reg(), src_reg, disp_value); |
aoqi@6880 | 1634 | __ lwc1(dest->as_double_reg()+1, src_reg, disp_value+4); |
aoqi@1 | 1635 | #else |
aoqi@6880 | 1636 | __ ldc1(dest->as_double_reg(), src_reg, disp_value); |
aoqi@1 | 1637 | #endif |
aoqi@6880 | 1638 | } else if (needs_patching) { |
aoqi@6880 | 1639 | __ add(AT, src_reg, disp_reg); |
aoqi@6880 | 1640 | offset = code_offset(); |
aoqi@1 | 1641 | #ifndef _LP64 |
aoqi@6880 | 1642 | __ lwc1(dest->as_double_reg(), AT, 0); |
aoqi@6880 | 1643 | __ lwc1(dest->as_double_reg()+1, AT, 4); |
aoqi@1 | 1644 | #else |
aoqi@6880 | 1645 | __ ldc1(dest->as_double_reg(), AT, 0); |
aoqi@1 | 1646 | #endif |
aoqi@6880 | 1647 | } else { |
aoqi@6880 | 1648 | __ add(AT, src_reg, disp_reg); |
aoqi@6880 | 1649 | offset = code_offset(); |
aoqi@1 | 1650 | #ifndef _LP64 |
aoqi@6880 | 1651 | __ lwc1(dest->as_double_reg(), AT, Assembler::split_low(disp_value)); |
aoqi@6880 | 1652 | __ lwc1(dest->as_double_reg()+1, AT, Assembler::split_low(disp_value) + 4); |
aoqi@1 | 1653 | #else |
aoqi@6880 | 1654 | __ ldc1(dest->as_double_reg(), AT, Assembler::split_low(disp_value)); |
aoqi@1 | 1655 | #endif |
aoqi@6880 | 1656 | } |
aoqi@6880 | 1657 | } |
aoqi@6880 | 1658 | break; |
aoqi@1 | 1659 | |
aoqi@1 | 1660 | default: |
aoqi@6880 | 1661 | ShouldNotReachHere(); |
aoqi@1 | 1662 | } |
aoqi@1 | 1663 | |
aoqi@1 | 1664 | if (needs_patching) { |
aoqi@1 | 1665 | patching_epilog(patch, patch_code, src_reg, info); |
aoqi@1 | 1666 | } |
aoqi@1 | 1667 | |
aoqi@1 | 1668 | if (type == T_ARRAY || type == T_OBJECT) { |
aoqi@1 | 1669 | #ifdef _LP64 |
aoqi@1 | 1670 | if (UseCompressedOops && !wide) { |
aoqi@6880 | 1671 | __ decode_heap_oop(dest->as_register()); |
aoqi@1 | 1672 | } |
aoqi@1 | 1673 | #endif |
aoqi@1 | 1674 | __ verify_oop(dest->as_register()); |
aoqi@8865 | 1675 | } else if (type == T_ADDRESS && addr->disp() == oopDesc::klass_offset_in_bytes()) { |
aoqi@8865 | 1676 | if (UseCompressedClassPointers) { |
aoqi@8865 | 1677 | __ decode_klass_not_null(dest->as_register()); |
aoqi@8865 | 1678 | } |
aoqi@1 | 1679 | } |
aoqi@1 | 1680 | if (info != NULL) add_debug_info_for_null_check(offset, info); |
aoqi@1 | 1681 | } |
aoqi@1 | 1682 | |
aoqi@1 | 1683 | |
aoqi@1 | 1684 | void LIR_Assembler::prefetchr(LIR_Opr src) { |
aoqi@1 | 1685 | LIR_Address* addr = src->as_address_ptr(); |
aoqi@1 | 1686 | Address from_addr = as_Address(addr); |
aoqi@1 | 1687 | } |
aoqi@1 | 1688 | |
aoqi@1 | 1689 | |
aoqi@1 | 1690 | void LIR_Assembler::prefetchw(LIR_Opr src) { |
aoqi@1 | 1691 | } |
aoqi@1 | 1692 | |
aoqi@6880 | 1693 | NEEDS_CLEANUP; // This could be static? |
aoqi@1 | 1694 | Address::ScaleFactor LIR_Assembler::array_element_size(BasicType type) const { |
aoqi@1 | 1695 | int elem_size = type2aelembytes(type); |
aoqi@1 | 1696 | switch (elem_size) { |
aoqi@1 | 1697 | case 1: return Address::times_1; |
aoqi@1 | 1698 | case 2: return Address::times_2; |
aoqi@1 | 1699 | case 4: return Address::times_4; |
aoqi@1 | 1700 | case 8: return Address::times_8; |
aoqi@1 | 1701 | } |
aoqi@1 | 1702 | ShouldNotReachHere(); |
aoqi@1 | 1703 | return Address::no_scale; |
aoqi@1 | 1704 | } |
aoqi@1 | 1705 | |
aoqi@1 | 1706 | |
aoqi@1 | 1707 | void LIR_Assembler::emit_op3(LIR_Op3* op) { |
aoqi@1 | 1708 | switch (op->code()) { |
aoqi@1 | 1709 | case lir_frem: |
aoqi@1 | 1710 | arithmetic_frem( |
aoqi@1 | 1711 | op->code(), |
aoqi@1 | 1712 | op->in_opr1(), |
aoqi@1 | 1713 | op->in_opr2(), |
aoqi@1 | 1714 | op->in_opr3(), |
aoqi@1 | 1715 | op->result_opr(), |
aoqi@1 | 1716 | op->info()); |
aoqi@1 | 1717 | break; |
aoqi@1 | 1718 | |
aoqi@1 | 1719 | case lir_idiv: |
aoqi@1 | 1720 | case lir_irem: |
aoqi@1 | 1721 | arithmetic_idiv( |
aoqi@1 | 1722 | op->code(), |
aoqi@1 | 1723 | op->in_opr1(), |
aoqi@1 | 1724 | op->in_opr2(), |
aoqi@1 | 1725 | op->in_opr3(), |
aoqi@1 | 1726 | op->result_opr(), |
aoqi@1 | 1727 | op->info()); |
aoqi@1 | 1728 | break; |
aoqi@1 | 1729 | default: ShouldNotReachHere(); break; |
aoqi@1 | 1730 | } |
aoqi@1 | 1731 | } |
aoqi@1 | 1732 | |
aoqi@1 | 1733 | void LIR_Assembler::emit_opBranch(LIR_OpBranch* op) { |
aoqi@1 | 1734 | LIR_Opr opr1 = op->left(); |
aoqi@1 | 1735 | LIR_Opr opr2 = op->right(); |
aoqi@1 | 1736 | LIR_Condition condition = op->cond(); |
aoqi@1 | 1737 | #ifdef ASSERT |
aoqi@1 | 1738 | assert(op->block() == NULL || op->block()->label() == op->label(), "wrong label"); |
aoqi@1 | 1739 | if (op->block() != NULL) _branch_target_blocks.append(op->block()); |
aoqi@1 | 1740 | if (op->ublock() != NULL) _branch_target_blocks.append(op->ublock()); |
aoqi@6880 | 1741 | #endif |
aoqi@1 | 1742 | if (op->cond() == lir_cond_always) { |
aoqi@1 | 1743 | if(op->label()==NULL) //by liaob1 |
aoqi@6880 | 1744 | __ b(*op->label()); |
aoqi@6880 | 1745 | else |
aoqi@6880 | 1746 | __ b_far(*op->label()); |
aoqi@1 | 1747 | __ delayed()->nop(); |
aoqi@1 | 1748 | return; |
aoqi@1 | 1749 | } |
aoqi@1 | 1750 | if (opr1->is_single_cpu()) { |
aoqi@1 | 1751 | Register reg_op1 = opr1->as_register(); |
aoqi@1 | 1752 | if (opr2->is_single_cpu()) { |
aoqi@1 | 1753 | #ifdef OPT_RANGECHECK |
aoqi@1 | 1754 | assert(!op->check(), "just check"); |
aoqi@1 | 1755 | #endif |
aoqi@1 | 1756 | Register reg_op2 = opr2->as_register(); |
aoqi@1 | 1757 | switch (condition) { |
aoqi@6880 | 1758 | case lir_cond_equal: |
aoqi@6880 | 1759 | __ beq(reg_op1, reg_op2, *op->label()); |
aoqi@6880 | 1760 | break; |
aoqi@6880 | 1761 | case lir_cond_notEqual: |
aoqi@6880 | 1762 | if(op->label()==NULL) |
aoqi@6880 | 1763 | __ bne(reg_op1, reg_op2, *op->label());//liaobin1 |
aoqi@6880 | 1764 | else |
aoqi@6880 | 1765 | __ bne_far(reg_op1, reg_op2, *op->label());//liaobin1 |
aoqi@6880 | 1766 | break; |
aoqi@6880 | 1767 | case lir_cond_less: |
aoqi@6880 | 1768 | // AT = 1 TRUE |
aoqi@6880 | 1769 | __ slt(AT, reg_op1, reg_op2); |
aoqi@6880 | 1770 | __ bne_far(AT, R0, *op->label()); |
aoqi@6880 | 1771 | break; |
aoqi@6880 | 1772 | case lir_cond_lessEqual: |
aoqi@6880 | 1773 | // AT = 0 TRUE |
aoqi@6880 | 1774 | __ slt(AT, reg_op2, reg_op1); |
aoqi@6880 | 1775 | __ beq_far(AT, R0, *op->label()); |
aoqi@6880 | 1776 | break; |
aoqi@6880 | 1777 | case lir_cond_belowEqual: |
aoqi@6880 | 1778 | // AT = 0 TRUE |
aoqi@6880 | 1779 | __ sltu(AT, reg_op2, reg_op1); |
aoqi@6880 | 1780 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 1781 | break; |
aoqi@6880 | 1782 | case lir_cond_greaterEqual: |
aoqi@6880 | 1783 | // AT = 0 TRUE |
aoqi@6880 | 1784 | __ slt(AT, reg_op1, reg_op2); |
aoqi@6880 | 1785 | __ beq_far(AT, R0, *op->label()); |
aoqi@6880 | 1786 | break; |
aoqi@6880 | 1787 | case lir_cond_aboveEqual: |
aoqi@6880 | 1788 | // AT = 0 TRUE |
aoqi@6880 | 1789 | __ sltu(AT, reg_op1, reg_op2); |
aoqi@6880 | 1790 | __ beq_far(AT, R0, *op->label()); |
aoqi@6880 | 1791 | break; |
aoqi@6880 | 1792 | case lir_cond_greater: |
aoqi@6880 | 1793 | // AT = 1 TRUE |
aoqi@6880 | 1794 | __ slt(AT, reg_op2, reg_op1); |
aoqi@6880 | 1795 | __ bne_far(AT, R0, *op->label()); |
aoqi@6880 | 1796 | break; |
aoqi@6880 | 1797 | default: ShouldNotReachHere(); |
aoqi@1 | 1798 | } |
aoqi@1 | 1799 | } else if (opr2->is_constant()) { |
aoqi@1 | 1800 | NOT_LP64(jint) LP64_ONLY(jlong) temp_value; |
aoqi@1 | 1801 | bool is_object = false; |
aoqi@1 | 1802 | if (opr2->pointer()->as_constant()->type() == T_INT) { |
aoqi@6880 | 1803 | temp_value = (jint)(opr2->as_jint()); |
aoqi@1 | 1804 | } else if (opr2->pointer()->as_constant()->type() == T_LONG) { |
aoqi@6880 | 1805 | temp_value = (jlong)(opr2->as_jlong()); |
aoqi@1 | 1806 | } else if (opr2->pointer()->as_constant()->type() == T_OBJECT) { |
aoqi@6880 | 1807 | is_object = true; |
aoqi@6880 | 1808 | temp_value = NOT_LP64((jint)) LP64_ONLY((jlong))(opr2->as_jobject()); |
aoqi@1 | 1809 | } else { |
aoqi@6880 | 1810 | ShouldNotReachHere(); |
aoqi@1 | 1811 | } |
aoqi@1 | 1812 | |
aoqi@1 | 1813 | switch (condition) { |
aoqi@6880 | 1814 | case lir_cond_equal: |
aoqi@1 | 1815 | #ifdef OPT_RANGECHECK |
aoqi@6880 | 1816 | assert(!op->check(), "just check"); |
aoqi@1 | 1817 | #endif |
aoqi@6880 | 1818 | if (temp_value) { |
aoqi@6880 | 1819 | if (is_object) { |
aoqi@6880 | 1820 | int oop_index = __ oop_recorder()->allocate_oop_index((jobject)temp_value); |
aoqi@6880 | 1821 | RelocationHolder rspec = oop_Relocation::spec(oop_index); |
aoqi@6880 | 1822 | __ relocate(rspec); |
aoqi@6880 | 1823 | } |
aoqi@6880 | 1824 | __ li(AT, temp_value); |
aoqi@6880 | 1825 | __ beq_far(reg_op1, AT, *op->label()); |
aoqi@6880 | 1826 | } else { |
aoqi@6880 | 1827 | __ beq_far(reg_op1, R0, *op->label()); |
aoqi@6880 | 1828 | } |
aoqi@6880 | 1829 | break; |
aoqi@6880 | 1830 | |
aoqi@6880 | 1831 | case lir_cond_notEqual: |
aoqi@1 | 1832 | #ifdef OPT_RANGECHECK |
aoqi@6880 | 1833 | assert(!op->check(), "just check"); |
aoqi@1 | 1834 | #endif |
aoqi@6880 | 1835 | if (temp_value) { |
aoqi@6880 | 1836 | if (is_object) { |
aoqi@6880 | 1837 | int oop_index = __ oop_recorder()->allocate_oop_index((jobject)temp_value); |
aoqi@6880 | 1838 | RelocationHolder rspec = oop_Relocation::spec(oop_index); |
aoqi@6880 | 1839 | __ relocate(rspec); |
aoqi@6880 | 1840 | } |
aoqi@6880 | 1841 | __ li(AT, temp_value); |
aoqi@6880 | 1842 | __ bne_far(reg_op1, AT, *op->label()); |
aoqi@6880 | 1843 | } else { |
aoqi@6880 | 1844 | __ bne_far(reg_op1, R0, *op->label()); |
aoqi@6880 | 1845 | } |
aoqi@6880 | 1846 | break; |
aoqi@6880 | 1847 | |
aoqi@6880 | 1848 | case lir_cond_less: |
aoqi@1 | 1849 | #ifdef OPT_RANGECHECK |
aoqi@6880 | 1850 | assert(!op->check(), "just check"); |
aoqi@1 | 1851 | #endif |
aoqi@6880 | 1852 | // AT = 1 TRUE |
aoqi@6880 | 1853 | if (Assembler::is_simm16(temp_value)) { |
aoqi@6880 | 1854 | __ slti(AT, reg_op1, temp_value); |
aoqi@6880 | 1855 | } else { |
aoqi@6880 | 1856 | __ move(AT, temp_value); |
aoqi@6880 | 1857 | __ slt(AT, reg_op1, AT); |
aoqi@6880 | 1858 | } |
aoqi@6880 | 1859 | __ bne_far(AT, R0, *op->label()); |
aoqi@6880 | 1860 | break; |
aoqi@6880 | 1861 | |
aoqi@6880 | 1862 | case lir_cond_lessEqual: |
aoqi@1 | 1863 | #ifdef OPT_RANGECHECK |
aoqi@6880 | 1864 | assert(!op->check(), "just check"); |
aoqi@1 | 1865 | #endif |
aoqi@6880 | 1866 | // AT = 0 TRUE |
aoqi@6880 | 1867 | __ li(AT, temp_value); |
aoqi@6880 | 1868 | __ slt(AT, AT, reg_op1); |
aoqi@6880 | 1869 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 1870 | break; |
aoqi@6880 | 1871 | |
aoqi@6880 | 1872 | case lir_cond_belowEqual: |
aoqi@6880 | 1873 | // AT = 0 TRUE |
aoqi@1 | 1874 | #ifdef OPT_RANGECHECK |
aoqi@6880 | 1875 | if (op->check()) { |
aoqi@6880 | 1876 | __ li(AT, temp_value); |
aoqi@6880 | 1877 | add_debug_info_for_range_check_here(op->info(), temp_value); |
aoqi@6880 | 1878 | __ tgeu(AT, reg_op1, 29); |
aoqi@6880 | 1879 | } else { |
aoqi@1 | 1880 | #endif |
aoqi@6880 | 1881 | __ li(AT, temp_value); |
aoqi@6880 | 1882 | __ sltu(AT, AT, reg_op1); |
aoqi@6880 | 1883 | __ beq(AT, R0, *op->label()); |
aoqi@1 | 1884 | #ifdef OPT_RANGECHECK |
aoqi@6880 | 1885 | } |
aoqi@1 | 1886 | #endif |
aoqi@6880 | 1887 | break; |
aoqi@6880 | 1888 | |
aoqi@6880 | 1889 | case lir_cond_greaterEqual: |
aoqi@1 | 1890 | #ifdef OPT_RANGECHECK |
aoqi@6880 | 1891 | assert(!op->check(), "just check"); |
aoqi@1 | 1892 | #endif |
aoqi@6880 | 1893 | // AT = 0 TRUE |
aoqi@6880 | 1894 | if (Assembler::is_simm16(temp_value)) { |
aoqi@6880 | 1895 | __ slti(AT, reg_op1, temp_value); |
aoqi@6880 | 1896 | } else { |
aoqi@6880 | 1897 | __ li(AT, temp_value); |
aoqi@6880 | 1898 | __ slt(AT, reg_op1, AT); |
aoqi@6880 | 1899 | } |
aoqi@6880 | 1900 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 1901 | break; |
aoqi@6880 | 1902 | |
aoqi@6880 | 1903 | case lir_cond_aboveEqual: |
aoqi@1 | 1904 | #ifdef OPT_RANGECHECK |
aoqi@6880 | 1905 | assert(!op->check(), "just check"); |
aoqi@1 | 1906 | #endif |
aoqi@6880 | 1907 | // AT = 0 TRUE |
aoqi@6880 | 1908 | if (Assembler::is_simm16(temp_value)) { |
aoqi@6880 | 1909 | __ sltiu(AT, reg_op1, temp_value); |
aoqi@6880 | 1910 | } else { |
aoqi@6880 | 1911 | __ li(AT, temp_value); |
aoqi@6880 | 1912 | __ sltu(AT, reg_op1, AT); |
aoqi@6880 | 1913 | } |
aoqi@6880 | 1914 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 1915 | break; |
aoqi@6880 | 1916 | |
aoqi@6880 | 1917 | case lir_cond_greater: |
aoqi@1 | 1918 | #ifdef OPT_RANGECHECK |
aoqi@6880 | 1919 | assert(!op->check(), "just check"); |
aoqi@1 | 1920 | #endif |
aoqi@6880 | 1921 | // AT = 1 TRUE |
aoqi@6880 | 1922 | __ li(AT, temp_value); |
aoqi@6880 | 1923 | __ slt(AT, AT, reg_op1); |
aoqi@6880 | 1924 | __ bne_far(AT, R0, *op->label()); |
aoqi@6880 | 1925 | break; |
aoqi@6880 | 1926 | |
aoqi@6880 | 1927 | default: ShouldNotReachHere(); |
aoqi@1 | 1928 | } |
aoqi@1 | 1929 | |
aoqi@1 | 1930 | } else { |
aoqi@1 | 1931 | if (opr2->is_address()) { |
aoqi@6880 | 1932 | //FIXME. aoqi lw or ld_ptr? |
aoqi@6880 | 1933 | if (op->type() == T_INT) |
aoqi@6880 | 1934 | __ lw(AT, as_Address(opr2->pointer()->as_address())); |
aoqi@6880 | 1935 | else |
aoqi@6880 | 1936 | __ ld_ptr(AT, as_Address(opr2->pointer()->as_address())); |
aoqi@1 | 1937 | } else if (opr2->is_stack()) { |
aoqi@6880 | 1938 | //FIXME. aoqi |
aoqi@6880 | 1939 | __ ld_ptr(AT, frame_map()->address_for_slot(opr2->single_stack_ix())); |
aoqi@1 | 1940 | } else { |
aoqi@6880 | 1941 | ShouldNotReachHere(); |
aoqi@1 | 1942 | } |
aoqi@1 | 1943 | switch (condition) { |
aoqi@6880 | 1944 | case lir_cond_equal: |
aoqi@1 | 1945 | #ifdef OPT_RANGECHECK |
aoqi@6880 | 1946 | assert(!op->check(), "just check"); |
aoqi@1 | 1947 | #endif |
aoqi@6880 | 1948 | __ beq(reg_op1, AT, *op->label()); |
aoqi@6880 | 1949 | break; |
aoqi@6880 | 1950 | case lir_cond_notEqual: |
aoqi@1 | 1951 | #ifdef OPT_RANGECHECK |
aoqi@6880 | 1952 | assert(!op->check(), "just check"); |
aoqi@1 | 1953 | #endif |
aoqi@6880 | 1954 | __ bne_far(reg_op1, AT, *op->label()); |
aoqi@6880 | 1955 | break; |
aoqi@6880 | 1956 | case lir_cond_less: |
aoqi@1 | 1957 | #ifdef OPT_RANGECHECK |
aoqi@6880 | 1958 | assert(!op->check(), "just check"); |
aoqi@1 | 1959 | #endif |
aoqi@6880 | 1960 | // AT = 1 TRUE |
aoqi@6880 | 1961 | __ slt(AT, reg_op1, AT); |
aoqi@6880 | 1962 | __ bne_far(AT, R0, *op->label()); |
aoqi@6880 | 1963 | break; |
aoqi@6880 | 1964 | case lir_cond_lessEqual: |
aoqi@1 | 1965 | #ifdef OPT_RANGECHECK |
aoqi@6880 | 1966 | assert(!op->check(), "just check"); |
aoqi@1 | 1967 | #endif |
aoqi@6880 | 1968 | // AT = 0 TRUE |
aoqi@6880 | 1969 | __ slt(AT, AT, reg_op1); |
aoqi@6880 | 1970 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 1971 | break; |
aoqi@6880 | 1972 | case lir_cond_belowEqual: |
aoqi@1 | 1973 | #ifdef OPT_RANGECHECK |
aoqi@6880 | 1974 | assert(!op->check(), "just check"); |
aoqi@1 | 1975 | #endif |
aoqi@6880 | 1976 | // AT = 0 TRUE |
aoqi@6880 | 1977 | __ sltu(AT, AT, reg_op1); |
aoqi@6880 | 1978 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 1979 | break; |
aoqi@6880 | 1980 | case lir_cond_greaterEqual: |
aoqi@1 | 1981 | #ifdef OPT_RANGECHECK |
aoqi@6880 | 1982 | assert(!op->check(), "just check"); |
aoqi@1 | 1983 | #endif |
aoqi@6880 | 1984 | // AT = 0 TRUE |
aoqi@6880 | 1985 | __ slt(AT, reg_op1, AT); |
aoqi@6880 | 1986 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 1987 | break; |
aoqi@6880 | 1988 | case lir_cond_aboveEqual: |
aoqi@6880 | 1989 | // AT = 0 TRUE |
aoqi@1 | 1990 | #ifdef OPT_RANGECHECK |
aoqi@6880 | 1991 | if (op->check()) { |
aoqi@6880 | 1992 | add_debug_info_for_range_check_here(op->info(), opr1->rinfo()); |
aoqi@6880 | 1993 | __ tgeu(reg_op1, AT, 29); |
aoqi@6880 | 1994 | } else { |
aoqi@1 | 1995 | #endif |
aoqi@6880 | 1996 | __ sltu(AT, reg_op1, AT); |
aoqi@6880 | 1997 | __ beq_far(AT, R0, *op->label()); |
aoqi@1 | 1998 | #ifdef OPT_RANGECHECK |
aoqi@6880 | 1999 | } |
aoqi@1 | 2000 | #endif |
aoqi@6880 | 2001 | break; |
aoqi@6880 | 2002 | case lir_cond_greater: |
aoqi@1 | 2003 | #ifdef OPT_RANGECHECK |
aoqi@6880 | 2004 | assert(!op->check(), "just check"); |
aoqi@1 | 2005 | #endif |
aoqi@6880 | 2006 | // AT = 1 TRUE |
aoqi@6880 | 2007 | __ slt(AT, AT, reg_op1); |
aoqi@6880 | 2008 | __ bne_far(AT, R0, *op->label()); |
aoqi@6880 | 2009 | break; |
aoqi@6880 | 2010 | default: ShouldNotReachHere(); |
aoqi@1 | 2011 | } |
aoqi@1 | 2012 | } |
aoqi@1 | 2013 | #ifdef OPT_RANGECHECK |
aoqi@1 | 2014 | if (!op->check()) |
aoqi@1 | 2015 | #endif |
aoqi@1 | 2016 | __ delayed()->nop(); |
aoqi@1 | 2017 | |
aoqi@1 | 2018 | } else if(opr1->is_address() || opr1->is_stack()) { |
aoqi@1 | 2019 | #ifdef OPT_RANGECHECK |
aoqi@1 | 2020 | assert(!op->check(), "just check"); |
aoqi@1 | 2021 | #endif |
aoqi@1 | 2022 | if (opr2->is_constant()) { |
aoqi@1 | 2023 | NOT_LP64(jint) LP64_ONLY(jlong) temp_value; |
aoqi@1 | 2024 | if (opr2->as_constant_ptr()->type() == T_INT) { |
aoqi@6880 | 2025 | temp_value = (jint)opr2->as_constant_ptr()->as_jint(); |
aoqi@1 | 2026 | } else if (opr2->as_constant_ptr()->type() == T_OBJECT) { |
aoqi@6880 | 2027 | temp_value = NOT_LP64((jint)) LP64_ONLY((jlong))(opr2->as_constant_ptr()->as_jobject()); |
aoqi@1 | 2028 | } else { |
aoqi@6880 | 2029 | ShouldNotReachHere(); |
aoqi@1 | 2030 | } |
aoqi@1 | 2031 | |
aoqi@1 | 2032 | if (Assembler::is_simm16(temp_value)) { |
aoqi@6880 | 2033 | if (opr1->is_address()) { |
aoqi@6880 | 2034 | __ lw(AT, as_Address(opr1->pointer()->as_address())); |
aoqi@6880 | 2035 | } else { |
aoqi@6880 | 2036 | __ lw(AT, frame_map()->address_for_slot(opr1->single_stack_ix())); |
aoqi@6880 | 2037 | } |
aoqi@6880 | 2038 | |
aoqi@6880 | 2039 | switch(condition) { |
aoqi@6880 | 2040 | |
aoqi@6880 | 2041 | case lir_cond_equal: |
aoqi@6880 | 2042 | __ addi(AT, AT, -(int)temp_value); |
aoqi@6880 | 2043 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 2044 | break; |
aoqi@6880 | 2045 | case lir_cond_notEqual: |
aoqi@6880 | 2046 | __ addi(AT, AT, -(int)temp_value); |
aoqi@6880 | 2047 | __ bne_far(AT, R0, *op->label()); |
aoqi@6880 | 2048 | break; |
aoqi@6880 | 2049 | case lir_cond_less: |
aoqi@6880 | 2050 | // AT = 1 TRUE |
aoqi@6880 | 2051 | __ slti(AT, AT, temp_value); |
aoqi@6880 | 2052 | __ bne_far(AT, R0, *op->label()); |
aoqi@6880 | 2053 | break; |
aoqi@6880 | 2054 | case lir_cond_lessEqual: |
aoqi@6880 | 2055 | // AT = 0 TRUE |
aoqi@6880 | 2056 | __ addi(AT, AT, -temp_value); |
aoqi@6880 | 2057 | __ slt(AT, R0, AT); |
aoqi@6880 | 2058 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 2059 | break; |
aoqi@6880 | 2060 | case lir_cond_belowEqual: |
aoqi@6880 | 2061 | // AT = 0 TRUE |
aoqi@6880 | 2062 | __ addiu(AT, AT, -temp_value); |
aoqi@6880 | 2063 | __ sltu(AT, R0, AT); |
aoqi@6880 | 2064 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 2065 | break; |
aoqi@6880 | 2066 | case lir_cond_greaterEqual: |
aoqi@6880 | 2067 | // AT = 0 TRUE |
aoqi@6880 | 2068 | __ slti(AT, AT, temp_value); |
aoqi@6880 | 2069 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 2070 | break; |
aoqi@6880 | 2071 | case lir_cond_aboveEqual: |
aoqi@6880 | 2072 | // AT = 0 TRUE |
aoqi@6880 | 2073 | __ sltiu(AT, AT, temp_value); |
aoqi@6880 | 2074 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 2075 | break; |
aoqi@6880 | 2076 | case lir_cond_greater: |
aoqi@6880 | 2077 | // AT = 1 TRUE |
aoqi@6880 | 2078 | __ addi(AT, AT, -temp_value); |
aoqi@6880 | 2079 | __ slt(AT, R0, AT); |
aoqi@6880 | 2080 | __ bne_far(AT, R0, *op->label()); |
aoqi@6880 | 2081 | break; |
aoqi@6880 | 2082 | |
aoqi@6880 | 2083 | default: |
aoqi@6880 | 2084 | Unimplemented(); |
aoqi@6880 | 2085 | } |
aoqi@1 | 2086 | } else { |
aoqi@6880 | 2087 | Unimplemented(); |
aoqi@1 | 2088 | } |
aoqi@1 | 2089 | } else { |
aoqi@1 | 2090 | Unimplemented(); |
aoqi@1 | 2091 | } |
aoqi@1 | 2092 | __ delayed()->nop(); |
aoqi@1 | 2093 | |
aoqi@1 | 2094 | } else if(opr1->is_double_cpu()) { |
aoqi@1 | 2095 | #ifdef OPT_RANGECHECK |
aoqi@1 | 2096 | assert(!op->check(), "just check"); |
aoqi@1 | 2097 | #endif |
aoqi@1 | 2098 | Register opr1_lo = opr1->as_register_lo(); |
aoqi@1 | 2099 | Register opr1_hi = opr1->as_register_hi(); |
aoqi@1 | 2100 | |
aoqi@1 | 2101 | if (opr2->is_double_cpu()) { |
aoqi@1 | 2102 | Register opr2_lo = opr2->as_register_lo(); |
aoqi@1 | 2103 | Register opr2_hi = opr2->as_register_hi(); |
aoqi@1 | 2104 | switch (condition) { |
aoqi@6880 | 2105 | case lir_cond_equal: { |
aoqi@6880 | 2106 | Label L; |
aoqi@1 | 2107 | #ifndef _LP64 |
aoqi@6880 | 2108 | __ bne(opr1_lo, opr2_lo, L); |
aoqi@6880 | 2109 | __ delayed()->nop(); |
aoqi@6880 | 2110 | __ beq(opr1_hi, opr2_hi, *op->label()); |
aoqi@1 | 2111 | #else |
aoqi@6880 | 2112 | /* static jobject java.lang.Long.toString(jlong) |
aoqi@6880 | 2113 | |
aoqi@6880 | 2114 | 10 move [t0t0|J] [a4a4|J] |
aoqi@6880 | 2115 | 12 move [lng:-9223372036854775808|J] [a6a6|J] |
aoqi@6880 | 2116 | 14 branch [EQ] [a4a4|J] [a6a6|J] [B1] |
aoqi@6880 | 2117 | 0x000000555e8532e4: bne a4, a6, 0x000000555e8532e4 <-- error |
aoqi@6880 | 2118 | 0x000000555e8532e8: sll zero, zero, 0 |
aoqi@1 | 2119 | */ |
aoqi@6880 | 2120 | __ beq(opr1_lo, opr2_lo, *op->label()); |
aoqi@1 | 2121 | #endif |
aoqi@6880 | 2122 | __ delayed()->nop(); |
aoqi@6880 | 2123 | __ bind(L); |
aoqi@6880 | 2124 | } |
aoqi@6880 | 2125 | break; |
aoqi@6880 | 2126 | |
aoqi@6880 | 2127 | case lir_cond_notEqual: |
aoqi@6880 | 2128 | if (op->label()==NULL) |
aoqi@6880 | 2129 | __ bne(opr1_lo, opr2_lo, *op->label());//by liaobin2 |
aoqi@6880 | 2130 | else |
aoqi@6880 | 2131 | __ bne_far(opr1_lo, opr2_lo, *op->label());//by liaobin2 |
aoqi@6880 | 2132 | __ delayed()->nop(); |
aoqi@6880 | 2133 | if (op->label()==NULL) |
aoqi@6880 | 2134 | NOT_LP64(__ bne(opr1_hi, opr2_hi, *op->label()));//by liaobin3 |
aoqi@6880 | 2135 | else |
aoqi@6880 | 2136 | NOT_LP64(__ bne_far(opr1_hi, opr2_hi, *op->label()));//by liaobin3 |
aoqi@6880 | 2137 | NOT_LP64(__ delayed()->nop()); |
aoqi@6880 | 2138 | break; |
aoqi@6880 | 2139 | |
aoqi@6880 | 2140 | case lir_cond_less: { |
aoqi@1 | 2141 | #ifdef _LP64 |
aoqi@6880 | 2142 | __ slt(AT, opr1_lo, opr2_lo); |
aoqi@6880 | 2143 | __ bne_far(AT, R0, *op->label()); |
aoqi@6880 | 2144 | __ delayed()->nop(); |
aoqi@1 | 2145 | #else |
aoqi@6880 | 2146 | Label L; |
aoqi@6880 | 2147 | |
aoqi@6880 | 2148 | // if hi less then jump |
aoqi@6880 | 2149 | __ slt(AT, opr1_hi, opr2_hi); |
aoqi@6880 | 2150 | __ bne(AT, R0, *op->label()); |
aoqi@6880 | 2151 | __ delayed()->nop(); |
aoqi@6880 | 2152 | |
aoqi@6880 | 2153 | // if hi great then fail |
aoqi@6880 | 2154 | __ bne(opr1_hi, opr2_hi, L); |
aoqi@6880 | 2155 | __ delayed(); |
aoqi@6880 | 2156 | |
aoqi@6880 | 2157 | // now just comp lo as unsigned |
aoqi@6880 | 2158 | __ sltu(AT, opr1_lo, opr2_lo); |
aoqi@6880 | 2159 | __ bne_far(AT, R0, *op->label()); |
aoqi@6880 | 2160 | __ delayed()->nop(); |
aoqi@6880 | 2161 | |
aoqi@6880 | 2162 | __ bind(L); |
aoqi@1 | 2163 | #endif |
aoqi@6880 | 2164 | } |
aoqi@6880 | 2165 | break; |
aoqi@6880 | 2166 | |
aoqi@6880 | 2167 | case lir_cond_lessEqual: { |
aoqi@1 | 2168 | #ifdef _LP64 |
aoqi@6880 | 2169 | __ slt(AT, opr2_lo, opr1_lo); |
aoqi@6880 | 2170 | __ beq_far(AT, R0, *op->label()); |
aoqi@6880 | 2171 | __ delayed()->nop(); |
aoqi@1 | 2172 | #else |
aoqi@6880 | 2173 | Label L; |
aoqi@6880 | 2174 | |
aoqi@6880 | 2175 | // if hi great then fail |
aoqi@6880 | 2176 | __ slt(AT, opr2_hi, opr1_hi); |
aoqi@6880 | 2177 | __ bne(AT, R0, L); |
aoqi@6880 | 2178 | __ delayed()->nop(); |
aoqi@6880 | 2179 | |
aoqi@6880 | 2180 | // if hi less then jump |
aoqi@6880 | 2181 | if(op->label()==NULL) |
aoqi@6880 | 2182 | __ bne(opr2_hi, opr1_hi, *op->label());//by liaobin4 |
aoqi@6880 | 2183 | else |
aoqi@6880 | 2184 | __ bne_far(opr2_hi, opr1_hi, *op->label());//by liaobin4 |
aoqi@6880 | 2185 | __ delayed(); |
aoqi@6880 | 2186 | |
aoqi@6880 | 2187 | // now just comp lo as unsigned |
aoqi@6880 | 2188 | __ sltu(AT, opr2_lo, opr1_lo); |
aoqi@6880 | 2189 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 2190 | __ delayed()->nop(); |
aoqi@6880 | 2191 | |
aoqi@6880 | 2192 | __ bind(L); |
aoqi@1 | 2193 | #endif |
aoqi@6880 | 2194 | } |
aoqi@6880 | 2195 | break; |
aoqi@6880 | 2196 | |
aoqi@6880 | 2197 | case lir_cond_belowEqual: { |
aoqi@1 | 2198 | #ifdef _LP64 |
aoqi@6880 | 2199 | __ sltu(AT, opr2_lo, opr1_lo); |
aoqi@6880 | 2200 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 2201 | __ delayed()->nop(); |
aoqi@1 | 2202 | #else |
aoqi@6880 | 2203 | Label L; |
aoqi@6880 | 2204 | |
aoqi@6880 | 2205 | // if hi great then fail |
aoqi@6880 | 2206 | __ sltu(AT, opr2_hi, opr1_hi); |
aoqi@6880 | 2207 | __ bne_far(AT, R0, L); |
aoqi@6880 | 2208 | __ delayed()->nop(); |
aoqi@6880 | 2209 | |
aoqi@6880 | 2210 | // if hi less then jump |
aoqi@6880 | 2211 | if(op->label()==NULL) |
aoqi@6880 | 2212 | __ bne(opr2_hi, opr1_hi, *op->label());//by liaobin5 |
aoqi@6880 | 2213 | else |
aoqi@6880 | 2214 | __ bne_far(opr2_hi, opr1_hi, *op->label());//by liaobin5 |
aoqi@6880 | 2215 | __ delayed(); |
aoqi@6880 | 2216 | |
aoqi@6880 | 2217 | // now just comp lo as unsigned |
aoqi@6880 | 2218 | __ sltu(AT, opr2_lo, opr1_lo); |
aoqi@6880 | 2219 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 2220 | __ delayed()->nop(); |
aoqi@6880 | 2221 | |
aoqi@6880 | 2222 | __ bind(L); |
aoqi@1 | 2223 | #endif |
aoqi@6880 | 2224 | } |
aoqi@6880 | 2225 | break; |
aoqi@6880 | 2226 | |
aoqi@6880 | 2227 | case lir_cond_greaterEqual: { |
aoqi@1 | 2228 | #ifdef _LP64 |
aoqi@6880 | 2229 | __ slt(AT, opr1_lo, opr2_lo); |
aoqi@6880 | 2230 | __ beq_far(AT, R0, *op->label()); |
aoqi@6880 | 2231 | __ delayed()->nop(); |
aoqi@1 | 2232 | #else |
aoqi@6880 | 2233 | Label L; |
aoqi@6880 | 2234 | |
aoqi@6880 | 2235 | // if hi less then fail |
aoqi@6880 | 2236 | __ slt(AT, opr1_hi, opr2_hi); |
aoqi@6880 | 2237 | __ bne_far(AT, R0, L); |
aoqi@6880 | 2238 | __ delayed()->nop(); |
aoqi@6880 | 2239 | |
aoqi@6880 | 2240 | // if hi great then jump |
aoqi@6880 | 2241 | if(op->label()==NULL) |
aoqi@6880 | 2242 | __ bne(opr2_hi, opr1_hi, *op->label());//by liaobin6 |
aoqi@6880 | 2243 | else |
aoqi@6880 | 2244 | __ bne_far(opr2_hi, opr1_hi, *op->label());//by liaobin6 |
aoqi@6880 | 2245 | __ delayed(); |
aoqi@6880 | 2246 | |
aoqi@6880 | 2247 | // now just comp lo as unsigned |
aoqi@6880 | 2248 | __ sltu(AT, opr1_lo, opr2_lo); |
aoqi@6880 | 2249 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 2250 | __ delayed()->nop(); |
aoqi@6880 | 2251 | |
aoqi@6880 | 2252 | __ bind(L); |
aoqi@1 | 2253 | #endif |
aoqi@6880 | 2254 | } |
aoqi@6880 | 2255 | break; |
aoqi@6880 | 2256 | |
aoqi@6880 | 2257 | case lir_cond_aboveEqual: { |
aoqi@1 | 2258 | #ifdef _LP64 |
aoqi@6880 | 2259 | __ sltu(AT, opr1_lo, opr2_lo); |
aoqi@6880 | 2260 | __ beq_far(AT, R0, *op->label()); |
aoqi@6880 | 2261 | __ delayed()->nop(); |
aoqi@1 | 2262 | #else |
aoqi@6880 | 2263 | Label L; |
aoqi@6880 | 2264 | |
aoqi@6880 | 2265 | // if hi less then fail |
aoqi@6880 | 2266 | __ sltu(AT, opr1_hi, opr2_hi); |
aoqi@6880 | 2267 | __ bne(AT, R0, L); |
aoqi@6880 | 2268 | __ delayed()->nop(); |
aoqi@6880 | 2269 | |
aoqi@6880 | 2270 | // if hi great then jump |
aoqi@6880 | 2271 | if(op->label()==NULL) |
aoqi@6880 | 2272 | __ bne(opr2_hi, opr1_hi, *op->label());//by liaobin7 |
aoqi@6880 | 2273 | else |
aoqi@6880 | 2274 | __ bne_far(opr2_hi, opr1_hi, *op->label());//by liaobin7 |
aoqi@6880 | 2275 | __ delayed(); |
aoqi@6880 | 2276 | |
aoqi@6880 | 2277 | // now just comp lo as unsigned |
aoqi@6880 | 2278 | __ sltu(AT, opr1_lo, opr2_lo); |
aoqi@6880 | 2279 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 2280 | __ delayed()->nop(); |
aoqi@6880 | 2281 | |
aoqi@6880 | 2282 | __ bind(L); |
aoqi@1 | 2283 | #endif |
aoqi@6880 | 2284 | } |
aoqi@6880 | 2285 | break; |
aoqi@6880 | 2286 | |
aoqi@6880 | 2287 | case lir_cond_greater: { |
aoqi@1 | 2288 | #ifdef _LP64 |
aoqi@6880 | 2289 | __ slt(AT, opr2_lo, opr1_lo); |
aoqi@6880 | 2290 | __ bne_far(AT, R0, *op->label()); |
aoqi@6880 | 2291 | __ delayed()->nop(); |
aoqi@1 | 2292 | #else |
aoqi@6880 | 2293 | Label L; |
aoqi@6880 | 2294 | |
aoqi@6880 | 2295 | // if hi great then jump |
aoqi@6880 | 2296 | __ slt(AT, opr2_hi, opr1_hi); |
aoqi@6880 | 2297 | __ bne(AT, R0, *op->label()); |
aoqi@6880 | 2298 | __ delayed()->nop(); |
aoqi@6880 | 2299 | |
aoqi@6880 | 2300 | // if hi less then fail |
aoqi@6880 | 2301 | __ bne(opr2_hi, opr1_hi, L); |
aoqi@6880 | 2302 | __ delayed(); |
aoqi@6880 | 2303 | |
aoqi@6880 | 2304 | // now just comp lo as unsigned |
aoqi@6880 | 2305 | __ sltu(AT, opr2_lo, opr1_lo); |
aoqi@6880 | 2306 | __ bne(AT, R0, *op->label()); |
aoqi@6880 | 2307 | __ delayed()->nop(); |
aoqi@6880 | 2308 | |
aoqi@6880 | 2309 | __ bind(L); |
aoqi@1 | 2310 | #endif |
aoqi@6880 | 2311 | } |
aoqi@6880 | 2312 | break; |
aoqi@6880 | 2313 | |
aoqi@6880 | 2314 | default: ShouldNotReachHere(); |
aoqi@1 | 2315 | } |
aoqi@1 | 2316 | |
aoqi@1 | 2317 | } else if(opr2->is_constant()) { |
aoqi@1 | 2318 | jlong lv = opr2->as_jlong(); |
aoqi@1 | 2319 | #ifndef _LP64 |
aoqi@1 | 2320 | jint iv_lo = (jint)lv; |
aoqi@1 | 2321 | jint iv_hi = (jint)(lv>>32); |
aoqi@1 | 2322 | bool is_zero = (lv==0); |
aoqi@1 | 2323 | #endif |
aoqi@1 | 2324 | |
aoqi@1 | 2325 | switch (condition) { |
aoqi@6880 | 2326 | case lir_cond_equal: |
aoqi@1 | 2327 | #ifdef _LP64 |
aoqi@6880 | 2328 | __ li(T8, lv); |
aoqi@6880 | 2329 | __ beq(opr1_lo, T8, *op->label()); |
aoqi@6880 | 2330 | __ delayed()->nop(); |
aoqi@1 | 2331 | #else |
aoqi@6880 | 2332 | if (is_zero) { |
aoqi@6880 | 2333 | __ orr(AT, opr1_lo, opr1_hi); |
aoqi@6880 | 2334 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 2335 | __ delayed()->nop(); |
aoqi@6880 | 2336 | } else { |
aoqi@6880 | 2337 | Label L; |
aoqi@6880 | 2338 | __ move(T8, iv_lo); |
aoqi@6880 | 2339 | __ bne(opr1_lo, T8, L); |
aoqi@6880 | 2340 | __ delayed(); |
aoqi@6880 | 2341 | __ move(T8, iv_hi); |
aoqi@6880 | 2342 | __ beq(opr1_hi, T8, *op->label()); |
aoqi@6880 | 2343 | __ delayed()->nop(); |
aoqi@6880 | 2344 | __ bind(L); |
aoqi@6880 | 2345 | } |
aoqi@1 | 2346 | #endif |
aoqi@6880 | 2347 | break; |
aoqi@6880 | 2348 | |
aoqi@6880 | 2349 | case lir_cond_notEqual: |
aoqi@1 | 2350 | #ifdef _LP64 |
aoqi@6880 | 2351 | __ li(T8, lv); |
aoqi@6880 | 2352 | __ bne(opr1_lo, T8, *op->label()); |
aoqi@6880 | 2353 | __ delayed()->nop(); |
aoqi@1 | 2354 | #else |
aoqi@6880 | 2355 | if (is_zero) { |
aoqi@6880 | 2356 | __ orr(AT, opr1_lo, opr1_hi); |
aoqi@6880 | 2357 | __ bne(AT, R0, *op->label()); |
aoqi@6880 | 2358 | __ delayed()->nop(); |
aoqi@6880 | 2359 | } else { |
aoqi@6880 | 2360 | __ move(T8, iv_lo); |
aoqi@6880 | 2361 | __ bne(opr1_lo, T8, *op->label()); |
aoqi@6880 | 2362 | __ delayed(); |
aoqi@6880 | 2363 | __ move(T8, iv_hi); |
aoqi@6880 | 2364 | __ bne(opr1_hi, T8, *op->label()); |
aoqi@6880 | 2365 | __ delayed()->nop(); |
aoqi@6880 | 2366 | } |
aoqi@1 | 2367 | #endif |
aoqi@6880 | 2368 | break; |
aoqi@6880 | 2369 | |
aoqi@6880 | 2370 | case lir_cond_less: |
aoqi@1 | 2371 | #ifdef _LP64 |
aoqi@6880 | 2372 | __ li(T8, lv); |
aoqi@6880 | 2373 | __ slt(AT, opr1_lo, T8); |
aoqi@6880 | 2374 | __ bne_far(AT, R0, *op->label()); |
aoqi@6880 | 2375 | __ delayed()->nop(); |
aoqi@1 | 2376 | #else |
aoqi@6880 | 2377 | if (is_zero) { |
aoqi@6880 | 2378 | __ bltz(opr1_hi, *op->label()); |
aoqi@6880 | 2379 | __ bltz(opr1_lo, *op->label()); |
aoqi@6880 | 2380 | __ delayed()->nop(); |
aoqi@6880 | 2381 | } else { |
aoqi@6880 | 2382 | Label L; |
aoqi@6880 | 2383 | |
aoqi@6880 | 2384 | // if hi less then jump |
aoqi@6880 | 2385 | __ move(T8, iv_hi); |
aoqi@6880 | 2386 | __ slt(AT, opr1_hi, T8); |
aoqi@6880 | 2387 | __ bne_far(AT, R0, *op->label()); |
aoqi@6880 | 2388 | __ delayed()->nop(); |
aoqi@6880 | 2389 | |
aoqi@6880 | 2390 | // if hi great then fail |
aoqi@6880 | 2391 | __ bne(opr1_hi, T8, L); |
aoqi@6880 | 2392 | __ delayed(); |
aoqi@6880 | 2393 | |
aoqi@6880 | 2394 | // now just comp lo as unsigned |
aoqi@6880 | 2395 | if (Assembler::is_simm16(iv_lo)) { |
aoqi@6880 | 2396 | __ sltiu(AT, opr1_lo, iv_lo); |
aoqi@6880 | 2397 | } else { |
aoqi@6880 | 2398 | __ move(T8, iv_lo); |
aoqi@6880 | 2399 | __ sltu(AT, opr1_lo, T8); |
aoqi@6880 | 2400 | } |
aoqi@6880 | 2401 | __ bne(AT, R0, *op->label()); |
aoqi@6880 | 2402 | __ delayed()->nop(); |
aoqi@6880 | 2403 | |
aoqi@6880 | 2404 | __ bind(L); |
aoqi@6880 | 2405 | } |
aoqi@1 | 2406 | #endif |
aoqi@6880 | 2407 | break; |
aoqi@6880 | 2408 | |
aoqi@6880 | 2409 | case lir_cond_lessEqual: |
aoqi@1 | 2410 | #ifdef _LP64 |
aoqi@6880 | 2411 | __ li(T8, lv); |
aoqi@6880 | 2412 | __ slt(AT, T8, opr1_lo); |
aoqi@6880 | 2413 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 2414 | __ delayed()->nop(); |
aoqi@1 | 2415 | #else |
aoqi@6880 | 2416 | if (is_zero) { |
aoqi@6880 | 2417 | __ bltz(opr1_hi, *op->label()); |
aoqi@6880 | 2418 | __ delayed()->nop(); |
aoqi@6880 | 2419 | __ orr(AT, opr1_hi, opr1_lo); |
aoqi@6880 | 2420 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 2421 | __ delayed(); |
aoqi@6880 | 2422 | } else { |
aoqi@6880 | 2423 | Label L; |
aoqi@6880 | 2424 | |
aoqi@6880 | 2425 | // if hi great then fail |
aoqi@6880 | 2426 | __ move(T8, iv_hi); |
aoqi@6880 | 2427 | __ slt(AT, T8, opr1_hi); |
aoqi@6880 | 2428 | __ bne(AT, R0, L); |
aoqi@6880 | 2429 | __ delayed()->nop(); |
aoqi@6880 | 2430 | |
aoqi@6880 | 2431 | // if hi less then jump |
aoqi@6880 | 2432 | __ bne(T8, opr1_hi, *op->label()); |
aoqi@6880 | 2433 | __ delayed(); |
aoqi@6880 | 2434 | |
aoqi@6880 | 2435 | // now just comp lo as unsigned |
aoqi@6880 | 2436 | __ move(T8, iv_lo); |
aoqi@6880 | 2437 | __ sltu(AT, T8, opr1_lo); |
aoqi@6880 | 2438 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 2439 | __ delayed()->nop(); |
aoqi@6880 | 2440 | |
aoqi@6880 | 2441 | __ bind(L); |
aoqi@6880 | 2442 | } |
aoqi@1 | 2443 | #endif |
aoqi@6880 | 2444 | break; |
aoqi@6880 | 2445 | |
aoqi@6880 | 2446 | case lir_cond_belowEqual: |
aoqi@1 | 2447 | #ifdef _LP64 |
aoqi@6880 | 2448 | __ li(T8, lv); |
aoqi@6880 | 2449 | __ sltu(AT, T8, opr1_lo); |
aoqi@6880 | 2450 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 2451 | __ delayed()->nop(); |
aoqi@1 | 2452 | #else |
aoqi@6880 | 2453 | if (is_zero) { |
aoqi@6880 | 2454 | __ orr(AT, opr1_hi, opr1_lo); |
aoqi@6880 | 2455 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 2456 | __ delayed()->nop(); |
aoqi@6880 | 2457 | } else { |
aoqi@6880 | 2458 | Label L; |
aoqi@6880 | 2459 | |
aoqi@6880 | 2460 | // if hi great then fail |
aoqi@6880 | 2461 | __ move(T8, iv_hi); |
aoqi@6880 | 2462 | __ sltu(AT, T8, opr1_hi); |
aoqi@6880 | 2463 | __ bne(AT, R0, L); |
aoqi@6880 | 2464 | __ delayed()->nop(); |
aoqi@6880 | 2465 | |
aoqi@6880 | 2466 | // if hi less then jump |
aoqi@6880 | 2467 | __ bne(T8, opr1_hi, *op->label()); |
aoqi@6880 | 2468 | __ delayed(); |
aoqi@6880 | 2469 | |
aoqi@6880 | 2470 | // now just comp lo as unsigned |
aoqi@6880 | 2471 | __ move(T8, iv_lo); |
aoqi@6880 | 2472 | __ sltu(AT, T8, opr1_lo); |
aoqi@6880 | 2473 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 2474 | __ delayed()->nop(); |
aoqi@6880 | 2475 | |
aoqi@6880 | 2476 | __ bind(L); |
aoqi@6880 | 2477 | } |
aoqi@1 | 2478 | #endif |
aoqi@6880 | 2479 | break; |
aoqi@6880 | 2480 | |
aoqi@6880 | 2481 | case lir_cond_greaterEqual: |
aoqi@1 | 2482 | #ifdef _LP64 |
aoqi@6880 | 2483 | __ li(T8, lv); |
aoqi@6880 | 2484 | __ slt(AT, opr1_lo, T8); |
aoqi@6880 | 2485 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 2486 | __ delayed()->nop(); |
aoqi@1 | 2487 | #else |
aoqi@6880 | 2488 | if (is_zero) { |
aoqi@6880 | 2489 | __ bgez(opr1_hi, *op->label()); |
aoqi@6880 | 2490 | __ delayed()->nop(); |
aoqi@6880 | 2491 | } else { |
aoqi@6880 | 2492 | Label L; |
aoqi@6880 | 2493 | |
aoqi@6880 | 2494 | // if hi less then fail |
aoqi@6880 | 2495 | __ move(T8, iv_hi); |
aoqi@6880 | 2496 | __ slt(AT, opr1_hi, T8); |
aoqi@6880 | 2497 | __ bne(AT, R0, L); |
aoqi@6880 | 2498 | __ delayed()->nop(); |
aoqi@6880 | 2499 | |
aoqi@6880 | 2500 | // if hi great then jump |
aoqi@6880 | 2501 | __ bne(T8, opr1_hi, *op->label()); |
aoqi@6880 | 2502 | __ delayed(); |
aoqi@6880 | 2503 | |
aoqi@6880 | 2504 | // now just comp lo as unsigned |
aoqi@6880 | 2505 | if (Assembler::is_simm16(iv_lo)) { |
aoqi@6880 | 2506 | __ sltiu(AT, opr1_lo, iv_lo); |
aoqi@6880 | 2507 | } else { |
aoqi@6880 | 2508 | __ move(T8, iv_lo); |
aoqi@6880 | 2509 | __ sltu(AT, opr1_lo, T8); |
aoqi@6880 | 2510 | } |
aoqi@6880 | 2511 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 2512 | __ delayed()->nop(); |
aoqi@6880 | 2513 | |
aoqi@6880 | 2514 | __ bind(L); |
aoqi@6880 | 2515 | } |
aoqi@1 | 2516 | #endif |
aoqi@6880 | 2517 | break; |
aoqi@6880 | 2518 | |
aoqi@6880 | 2519 | case lir_cond_aboveEqual: |
aoqi@1 | 2520 | #ifdef _LP64 |
aoqi@6880 | 2521 | __ li(T8, lv); |
aoqi@6880 | 2522 | __ sltu(AT, opr1_lo, T8); |
aoqi@6880 | 2523 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 2524 | __ delayed()->nop(); |
aoqi@1 | 2525 | #else |
aoqi@6880 | 2526 | if (is_zero) { |
aoqi@1 | 2527 | if(op->label()==NULL) //by liaob2 |
aoqi@6880 | 2528 | __ b(*op->label()); |
aoqi@6880 | 2529 | else |
aoqi@6880 | 2530 | __ b_far(*op->label()); |
aoqi@6880 | 2531 | __ delayed()->nop(); |
aoqi@6880 | 2532 | } else { |
aoqi@6880 | 2533 | Label L; |
aoqi@6880 | 2534 | |
aoqi@6880 | 2535 | // if hi less then fail |
aoqi@6880 | 2536 | __ move(T8, iv_hi); |
aoqi@6880 | 2537 | __ sltu(AT, opr1_hi, T8); |
aoqi@6880 | 2538 | __ bne(AT, R0, L); |
aoqi@6880 | 2539 | __ delayed()->nop(); |
aoqi@6880 | 2540 | |
aoqi@6880 | 2541 | // if hi great then jump |
aoqi@6880 | 2542 | __ bne(T8, opr1_hi, *op->label()); |
aoqi@6880 | 2543 | __ delayed(); |
aoqi@6880 | 2544 | |
aoqi@6880 | 2545 | // now just comp lo as unsigned |
aoqi@6880 | 2546 | if (Assembler::is_simm16(iv_lo)) { |
aoqi@6880 | 2547 | __ sltiu(AT, opr1_lo, iv_lo); |
aoqi@6880 | 2548 | } else { |
aoqi@6880 | 2549 | __ move(T8, iv_lo); |
aoqi@6880 | 2550 | __ sltu(AT, opr1_lo, T8); |
aoqi@6880 | 2551 | } |
aoqi@6880 | 2552 | __ beq(AT, R0, *op->label()); |
aoqi@6880 | 2553 | __ delayed()->nop(); |
aoqi@6880 | 2554 | |
aoqi@6880 | 2555 | __ bind(L); |
aoqi@6880 | 2556 | } |
aoqi@1 | 2557 | #endif |
aoqi@6880 | 2558 | break; |
aoqi@6880 | 2559 | |
aoqi@6880 | 2560 | case lir_cond_greater: |
aoqi@1 | 2561 | #ifdef _LP64 |
aoqi@6880 | 2562 | __ li(T8, lv); |
aoqi@6880 | 2563 | __ slt(AT, T8, opr1_lo); |
aoqi@6880 | 2564 | __ bne_far(AT, R0, *op->label()); |
aoqi@6880 | 2565 | __ delayed()->nop(); |
aoqi@1 | 2566 | #else |
aoqi@6880 | 2567 | if (is_zero) { |
aoqi@6880 | 2568 | Label L; |
aoqi@6880 | 2569 | __ bgtz(opr1_hi, *op->label()); |
aoqi@6880 | 2570 | __ delayed()->nop(); |
aoqi@6880 | 2571 | __ bne(opr1_hi, R0, L); |
aoqi@6880 | 2572 | __ delayed()->nop(); |
aoqi@6880 | 2573 | __ bne(opr1_lo, R0, *op->label()); |
aoqi@6880 | 2574 | __ delayed()->nop(); |
aoqi@6880 | 2575 | __ bind(L); |
aoqi@6880 | 2576 | } else { |
aoqi@6880 | 2577 | Label L; |
aoqi@6880 | 2578 | |
aoqi@6880 | 2579 | // if hi great then jump |
aoqi@6880 | 2580 | __ move(T8, iv_hi); |
aoqi@6880 | 2581 | __ slt(AT, T8, opr1_hi); |
aoqi@6880 | 2582 | __ bne(AT, R0, *op->label()); |
aoqi@6880 | 2583 | __ delayed()->nop(); |
aoqi@6880 | 2584 | |
aoqi@6880 | 2585 | // if hi less then fail |
aoqi@6880 | 2586 | __ bne(T8, opr1_hi, L); |
aoqi@6880 | 2587 | __ delayed(); |
aoqi@6880 | 2588 | |
aoqi@6880 | 2589 | // now just comp lo as unsigned |
aoqi@6880 | 2590 | __ move(T8, iv_lo); |
aoqi@6880 | 2591 | __ sltu(AT, T8, opr1_lo); |
aoqi@6880 | 2592 | __ bne(AT, R0, *op->label()); |
aoqi@6880 | 2593 | __ delayed()->nop(); |
aoqi@6880 | 2594 | |
aoqi@6880 | 2595 | __ bind(L); |
aoqi@6880 | 2596 | } |
aoqi@1 | 2597 | #endif |
aoqi@6880 | 2598 | break; |
aoqi@6880 | 2599 | |
aoqi@6880 | 2600 | default: |
aoqi@6880 | 2601 | ShouldNotReachHere(); |
aoqi@1 | 2602 | } |
aoqi@1 | 2603 | } else { |
aoqi@1 | 2604 | Unimplemented(); |
aoqi@1 | 2605 | } |
aoqi@1 | 2606 | } else if (opr1->is_single_fpu()) { |
aoqi@1 | 2607 | #ifdef OPT_RANGECHECK |
aoqi@1 | 2608 | assert(!op->check(), "just check"); |
aoqi@1 | 2609 | #endif |
aoqi@1 | 2610 | assert(opr2->is_single_fpu(), "change the code"); |
aoqi@1 | 2611 | |
aoqi@1 | 2612 | FloatRegister reg_op1 = opr1->as_float_reg(); |
aoqi@1 | 2613 | FloatRegister reg_op2 = opr2->as_float_reg(); |
aoqi@6880 | 2614 | // bool un_ls |
aoqi@1 | 2615 | bool un_jump = (op->ublock()->label()==op->label()); |
aoqi@1 | 2616 | |
aoqi@1 | 2617 | Label& L = *op->label(); |
aoqi@1 | 2618 | |
aoqi@1 | 2619 | switch (condition) { |
aoqi@1 | 2620 | case lir_cond_equal: |
aoqi@6880 | 2621 | if (un_jump) |
aoqi@6880 | 2622 | __ c_ueq_s(reg_op1, reg_op2); |
aoqi@6880 | 2623 | else |
aoqi@6880 | 2624 | __ c_eq_s(reg_op1, reg_op2); |
aoqi@6880 | 2625 | __ bc1t(L); |
aoqi@6880 | 2626 | |
aoqi@6880 | 2627 | break; |
aoqi@1 | 2628 | |
aoqi@1 | 2629 | case lir_cond_notEqual: |
aoqi@6880 | 2630 | if (un_jump) |
aoqi@6880 | 2631 | __ c_eq_s(reg_op1, reg_op2); |
aoqi@6880 | 2632 | else |
aoqi@6880 | 2633 | __ c_ueq_s(reg_op1, reg_op2); |
aoqi@6880 | 2634 | __ bc1f(L); |
aoqi@6880 | 2635 | |
aoqi@6880 | 2636 | break; |
aoqi@1 | 2637 | |
aoqi@1 | 2638 | case lir_cond_less: |
aoqi@6880 | 2639 | if (un_jump) |
aoqi@6880 | 2640 | __ c_ult_s(reg_op1, reg_op2); |
aoqi@6880 | 2641 | else |
aoqi@6880 | 2642 | __ c_olt_s(reg_op1, reg_op2); |
aoqi@6880 | 2643 | __ bc1t(L); |
aoqi@6880 | 2644 | |
aoqi@6880 | 2645 | break; |
aoqi@1 | 2646 | |
aoqi@1 | 2647 | case lir_cond_lessEqual: |
aoqi@1 | 2648 | case lir_cond_belowEqual: |
aoqi@6880 | 2649 | if (un_jump) |
aoqi@6880 | 2650 | __ c_ule_s(reg_op1, reg_op2); |
aoqi@6880 | 2651 | else |
aoqi@6880 | 2652 | __ c_ole_s(reg_op1, reg_op2); |
aoqi@6880 | 2653 | __ bc1t(L); |
aoqi@6880 | 2654 | |
aoqi@6880 | 2655 | break; |
aoqi@1 | 2656 | |
aoqi@1 | 2657 | case lir_cond_greaterEqual: |
aoqi@1 | 2658 | case lir_cond_aboveEqual: |
aoqi@6880 | 2659 | if (un_jump) |
aoqi@6880 | 2660 | __ c_olt_s(reg_op1, reg_op2); |
aoqi@6880 | 2661 | else |
aoqi@6880 | 2662 | __ c_ult_s(reg_op1, reg_op2); |
aoqi@6880 | 2663 | __ bc1f(L); |
aoqi@6880 | 2664 | |
aoqi@6880 | 2665 | break; |
aoqi@1 | 2666 | |
aoqi@1 | 2667 | case lir_cond_greater: |
aoqi@6880 | 2668 | if (un_jump) |
aoqi@6880 | 2669 | __ c_ole_s(reg_op1, reg_op2); |
aoqi@6880 | 2670 | else |
aoqi@6880 | 2671 | __ c_ule_s(reg_op1, reg_op2); |
aoqi@6880 | 2672 | __ bc1f(L); |
aoqi@6880 | 2673 | |
aoqi@6880 | 2674 | break; |
aoqi@6880 | 2675 | |
aoqi@6880 | 2676 | default: |
aoqi@6880 | 2677 | ShouldNotReachHere(); |
aoqi@1 | 2678 | } |
aoqi@1 | 2679 | __ delayed()->nop(); |
aoqi@1 | 2680 | } else if (opr1->is_double_fpu()) { |
aoqi@1 | 2681 | #ifdef OPT_RANGECHECK |
aoqi@1 | 2682 | assert(!op->check(), "just check"); |
aoqi@1 | 2683 | #endif |
aoqi@1 | 2684 | assert(opr2->is_double_fpu(), "change the code"); |
aoqi@1 | 2685 | |
aoqi@1 | 2686 | FloatRegister reg_op1 = opr1->as_double_reg(); |
aoqi@1 | 2687 | FloatRegister reg_op2 = opr2->as_double_reg(); |
aoqi@1 | 2688 | bool un_jump = (op->ublock()->label()==op->label()); |
aoqi@1 | 2689 | Label& L = *op->label(); |
aoqi@1 | 2690 | |
aoqi@1 | 2691 | switch (condition) { |
aoqi@1 | 2692 | case lir_cond_equal: |
aoqi@6880 | 2693 | if (un_jump) |
aoqi@6880 | 2694 | __ c_ueq_d(reg_op1, reg_op2); |
aoqi@6880 | 2695 | else |
aoqi@6880 | 2696 | __ c_eq_d(reg_op1, reg_op2); |
aoqi@6880 | 2697 | __ bc1t(L); |
aoqi@6880 | 2698 | |
aoqi@6880 | 2699 | break; |
aoqi@1 | 2700 | |
aoqi@1 | 2701 | case lir_cond_notEqual: |
aoqi@6880 | 2702 | if (un_jump) |
aoqi@6880 | 2703 | __ c_eq_d(reg_op1, reg_op2); |
aoqi@6880 | 2704 | else |
aoqi@6880 | 2705 | __ c_ueq_d(reg_op1, reg_op2); |
aoqi@6880 | 2706 | __ bc1f(L); |
aoqi@6880 | 2707 | |
aoqi@6880 | 2708 | break; |
aoqi@1 | 2709 | |
aoqi@1 | 2710 | case lir_cond_less: |
aoqi@6880 | 2711 | if (un_jump) |
aoqi@6880 | 2712 | __ c_ult_d(reg_op1, reg_op2); |
aoqi@6880 | 2713 | else |
aoqi@6880 | 2714 | __ c_olt_d(reg_op1, reg_op2); |
aoqi@6880 | 2715 | __ bc1t(L); |
aoqi@6880 | 2716 | |
aoqi@6880 | 2717 | break; |
aoqi@1 | 2718 | |
aoqi@1 | 2719 | case lir_cond_lessEqual: |
aoqi@1 | 2720 | case lir_cond_belowEqual: |
aoqi@6880 | 2721 | if (un_jump) |
aoqi@6880 | 2722 | __ c_ule_d(reg_op1, reg_op2); |
aoqi@6880 | 2723 | else |
aoqi@6880 | 2724 | __ c_ole_d(reg_op1, reg_op2); |
aoqi@6880 | 2725 | __ bc1t(L); |
aoqi@6880 | 2726 | |
aoqi@6880 | 2727 | break; |
aoqi@1 | 2728 | |
aoqi@1 | 2729 | case lir_cond_greaterEqual: |
aoqi@1 | 2730 | case lir_cond_aboveEqual: |
aoqi@6880 | 2731 | if (un_jump) |
aoqi@6880 | 2732 | __ c_olt_d(reg_op1, reg_op2); |
aoqi@6880 | 2733 | else |
aoqi@6880 | 2734 | __ c_ult_d(reg_op1, reg_op2); |
aoqi@6880 | 2735 | __ bc1f(L); |
aoqi@6880 | 2736 | |
aoqi@6880 | 2737 | break; |
aoqi@1 | 2738 | |
aoqi@1 | 2739 | case lir_cond_greater: |
aoqi@6880 | 2740 | if (un_jump) |
aoqi@6880 | 2741 | __ c_ole_d(reg_op1, reg_op2); |
aoqi@6880 | 2742 | else |
aoqi@6880 | 2743 | __ c_ule_d(reg_op1, reg_op2); |
aoqi@6880 | 2744 | __ bc1f(L); |
aoqi@6880 | 2745 | |
aoqi@6880 | 2746 | break; |
aoqi@6880 | 2747 | |
aoqi@6880 | 2748 | default: |
aoqi@6880 | 2749 | ShouldNotReachHere(); |
aoqi@1 | 2750 | } |
aoqi@1 | 2751 | __ delayed()->nop(); |
aoqi@1 | 2752 | } else { |
aoqi@1 | 2753 | Unimplemented(); |
aoqi@1 | 2754 | } |
aoqi@1 | 2755 | } |
aoqi@1 | 2756 | |
aoqi@1 | 2757 | |
aoqi@1 | 2758 | void LIR_Assembler::emit_opConvert(LIR_OpConvert* op) { |
aoqi@1 | 2759 | LIR_Opr value = op->in_opr(); |
aoqi@1 | 2760 | LIR_Opr src = op->in_opr(); |
aoqi@1 | 2761 | LIR_Opr dest = op->result_opr(); |
aoqi@1 | 2762 | Bytecodes::Code code = op->bytecode(); |
aoqi@1 | 2763 | |
aoqi@1 | 2764 | switch (code) { |
aoqi@6880 | 2765 | case Bytecodes::_i2l: |
aoqi@1 | 2766 | move_regs(src->as_register(), dest->as_register_lo()); |
aoqi@1 | 2767 | NOT_LP64(__ sra (dest->as_register_hi(), dest->as_register_lo(), 31)); |
aoqi@1 | 2768 | break; |
aoqi@1 | 2769 | |
aoqi@1 | 2770 | case Bytecodes::_l2i: |
aoqi@1 | 2771 | #ifndef _LP64 |
aoqi@1 | 2772 | move_regs (src->as_register_lo(), dest->as_register()); |
aoqi@1 | 2773 | #else |
aoqi@1 | 2774 | __ dsll32(dest->as_register(), src->as_register_lo(), 0); |
aoqi@1 | 2775 | __ dsra32(dest->as_register(), dest->as_register(), 0); |
aoqi@1 | 2776 | #endif |
aoqi@1 | 2777 | break; |
aoqi@1 | 2778 | |
aoqi@1 | 2779 | case Bytecodes::_i2b: |
aoqi@1 | 2780 | #ifndef _LP64 |
aoqi@1 | 2781 | move_regs (src->as_register(), dest->as_register()); |
aoqi@1 | 2782 | __ sign_extend_byte(dest->as_register()); |
aoqi@1 | 2783 | #else |
aoqi@1 | 2784 | __ dsll32(dest->as_register(), src->as_register(), 24); |
aoqi@1 | 2785 | __ dsra32(dest->as_register(), dest->as_register(), 24); |
aoqi@1 | 2786 | #endif |
aoqi@1 | 2787 | break; |
aoqi@1 | 2788 | |
aoqi@1 | 2789 | case Bytecodes::_i2c: |
aoqi@1 | 2790 | __ andi(dest->as_register(), src->as_register(), 0xFFFF); |
aoqi@1 | 2791 | break; |
aoqi@1 | 2792 | |
aoqi@1 | 2793 | case Bytecodes::_i2s: |
aoqi@1 | 2794 | #ifndef _LP64 |
aoqi@1 | 2795 | move_regs (src->as_register(), dest->as_register()); |
aoqi@1 | 2796 | __ sign_extend_short(dest->as_register()); |
aoqi@1 | 2797 | #else |
aoqi@1 | 2798 | __ dsll32(dest->as_register(), src->as_register(), 16); |
aoqi@1 | 2799 | __ dsra32(dest->as_register(), dest->as_register(), 16); |
aoqi@1 | 2800 | #endif |
aoqi@1 | 2801 | break; |
aoqi@1 | 2802 | |
aoqi@1 | 2803 | case Bytecodes::_f2d: |
aoqi@1 | 2804 | __ cvt_d_s(dest->as_double_reg(), src->as_float_reg()); |
aoqi@1 | 2805 | break; |
aoqi@1 | 2806 | |
aoqi@1 | 2807 | case Bytecodes::_d2f: |
aoqi@1 | 2808 | __ cvt_s_d(dest->as_float_reg(), src->as_double_reg()); |
aoqi@1 | 2809 | break; |
aoqi@1 | 2810 | case Bytecodes::_i2f: { |
aoqi@6880 | 2811 | FloatRegister df = dest->as_float_reg(); |
aoqi@6880 | 2812 | if(src->is_single_cpu()) { |
aoqi@6880 | 2813 | __ mtc1(src->as_register(), df); |
aoqi@6880 | 2814 | __ cvt_s_w(df, df); |
aoqi@6880 | 2815 | } else if (src->is_stack()) { |
aoqi@6880 | 2816 | Address src_addr = src->is_single_stack() |
aoqi@6880 | 2817 | ? frame_map()->address_for_slot(src->single_stack_ix()) |
aoqi@6880 | 2818 | : frame_map()->address_for_slot(src->double_stack_ix()); |
aoqi@6880 | 2819 | __ lw(AT, src_addr); |
aoqi@6880 | 2820 | __ mtc1(AT, df); |
aoqi@6880 | 2821 | __ cvt_s_w(df, df); |
aoqi@6880 | 2822 | } else { |
aoqi@6880 | 2823 | Unimplemented(); |
aoqi@6880 | 2824 | } |
aoqi@6880 | 2825 | break; |
aoqi@6880 | 2826 | } |
aoqi@6880 | 2827 | case Bytecodes::_i2d: { |
aoqi@6880 | 2828 | FloatRegister dd = dest->as_double_reg(); |
aoqi@6880 | 2829 | if (src->is_single_cpu()) { |
aoqi@6880 | 2830 | __ mtc1(src->as_register(), dd); |
aoqi@6880 | 2831 | __ cvt_d_w(dd, dd); |
aoqi@6880 | 2832 | } else if (src->is_stack()) { |
aoqi@6880 | 2833 | Address src_addr = src->is_single_stack() |
aoqi@6880 | 2834 | ? frame_map()->address_for_slot(value->single_stack_ix()) |
aoqi@6880 | 2835 | : frame_map()->address_for_slot(value->double_stack_ix()); |
aoqi@6880 | 2836 | __ lw(AT, src_addr); |
aoqi@6880 | 2837 | __ mtc1(AT, dd); |
aoqi@6880 | 2838 | __ cvt_d_w(dd, dd); |
aoqi@6880 | 2839 | } else { |
aoqi@6880 | 2840 | Unimplemented(); |
aoqi@6880 | 2841 | } |
aoqi@6880 | 2842 | break; |
aoqi@6880 | 2843 | } |
aoqi@1 | 2844 | case Bytecodes::_f2i: { |
aoqi@6880 | 2845 | FloatRegister fval = src->as_float_reg(); |
aoqi@6880 | 2846 | Register dreg = dest->as_register(); |
aoqi@6880 | 2847 | |
aoqi@6880 | 2848 | Label L; |
aoqi@6880 | 2849 | __ c_un_s(fval, fval); //NaN? |
aoqi@6880 | 2850 | __ bc1t(L); |
aoqi@6880 | 2851 | __ delayed(); |
aoqi@6880 | 2852 | __ move(dreg, R0); |
aoqi@6880 | 2853 | |
aoqi@6880 | 2854 | __ trunc_w_s(F30, fval); |
aoqi@6880 | 2855 | |
aoqi@6880 | 2856 | /* Call SharedRuntime:f2i() to do valid convention */ |
aoqi@6880 | 2857 | __ cfc1(AT, 31); |
aoqi@6880 | 2858 | __ li(T9, 0x10000); |
aoqi@6880 | 2859 | __ andr(AT, AT, T9); |
aoqi@6880 | 2860 | __ beq(AT, R0, L); |
aoqi@6880 | 2861 | __ delayed()->mfc1(dreg, F30); |
aoqi@6880 | 2862 | |
aoqi@6880 | 2863 | __ mov_s(F12, fval); |
aoqi@6880 | 2864 | __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::f2i), 1); |
aoqi@6880 | 2865 | __ move(dreg, V0); |
aoqi@6880 | 2866 | __ bind(L); |
aoqi@6880 | 2867 | break; |
aoqi@6880 | 2868 | } |
aoqi@1 | 2869 | case Bytecodes::_d2i: { |
aoqi@6880 | 2870 | FloatRegister dval = src->as_double_reg(); |
aoqi@6880 | 2871 | Register dreg = dest->as_register(); |
aoqi@6880 | 2872 | |
aoqi@6880 | 2873 | Label L; |
aoqi@1 | 2874 | #ifndef _LP64 |
aoqi@6880 | 2875 | __ c_un_d(dval, dval); //NaN? |
aoqi@6880 | 2876 | __ bc1t(L); |
aoqi@6880 | 2877 | __ delayed(); |
aoqi@6880 | 2878 | __ move(dreg, R0); |
aoqi@1 | 2879 | #endif |
aoqi@1 | 2880 | |
aoqi@6880 | 2881 | __ trunc_w_d(F30, dval); |
aoqi@6880 | 2882 | __ cfc1(AT, 31); |
aoqi@6880 | 2883 | __ li(T9, 0x10000); |
aoqi@6880 | 2884 | __ andr(AT, AT, T9); |
aoqi@6880 | 2885 | __ beq(AT, R0, L); |
aoqi@6880 | 2886 | __ delayed()->mfc1(dreg, F30); |
aoqi@6880 | 2887 | |
aoqi@6880 | 2888 | __ mov_d(F12, dval); |
aoqi@6880 | 2889 | __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::d2i), 1); |
aoqi@6880 | 2890 | __ move(dreg, V0); |
aoqi@6880 | 2891 | __ bind(L); |
aoqi@6880 | 2892 | break; |
aoqi@6880 | 2893 | } |
aoqi@1 | 2894 | case Bytecodes::_l2f: { |
aoqi@6880 | 2895 | FloatRegister ldf = dest->as_float_reg(); |
aoqi@6880 | 2896 | if (src->is_double_cpu()) { |
aoqi@1 | 2897 | #ifndef _LP64 |
aoqi@6880 | 2898 | __ mtc1(src->as_register_lo(), ldf); |
aoqi@6880 | 2899 | __ mtc1(src->as_register_hi(), ldf + 1); |
aoqi@6880 | 2900 | __ cvt_s_l(ldf, ldf); |
aoqi@1 | 2901 | #else |
aoqi@6880 | 2902 | __ dmtc1(src->as_register_lo(), ldf); |
aoqi@6880 | 2903 | __ cvt_s_l(ldf, ldf); |
aoqi@1 | 2904 | #endif |
aoqi@6880 | 2905 | } else if (src->is_double_stack()) { |
aoqi@6880 | 2906 | Address src_addr=frame_map()->address_for_slot(value->double_stack_ix()); |
aoqi@1 | 2907 | #ifndef _LP64 |
aoqi@6880 | 2908 | __ lw(AT, src_addr); |
aoqi@6880 | 2909 | __ mtc1(AT, ldf); |
aoqi@6880 | 2910 | __ lw(AT, src_addr.base(), src_addr.disp() + 4); |
aoqi@6880 | 2911 | __ mtc1(AT, ldf + 1); |
aoqi@6880 | 2912 | __ cvt_s_l(ldf, ldf); |
aoqi@1 | 2913 | #else |
aoqi@6880 | 2914 | __ ld(AT, src_addr); |
aoqi@6880 | 2915 | __ dmtc1(AT, ldf); |
aoqi@6880 | 2916 | __ cvt_s_l(ldf, ldf); |
aoqi@1 | 2917 | #endif |
aoqi@6880 | 2918 | } else { |
aoqi@6880 | 2919 | Unimplemented(); |
aoqi@6880 | 2920 | } |
aoqi@6880 | 2921 | break; |
aoqi@6880 | 2922 | } |
aoqi@1 | 2923 | case Bytecodes::_l2d: { |
aoqi@6880 | 2924 | FloatRegister ldd = dest->as_double_reg(); |
aoqi@6880 | 2925 | if (src->is_double_cpu()) { |
aoqi@1 | 2926 | #ifndef _LP64 |
aoqi@6880 | 2927 | __ mtc1(src->as_register_lo(), ldd); |
aoqi@6880 | 2928 | __ mtc1(src->as_register_hi(), ldd + 1); |
aoqi@6880 | 2929 | __ cvt_d_l(ldd, ldd); |
aoqi@1 | 2930 | #else |
aoqi@6880 | 2931 | __ dmtc1(src->as_register_lo(), ldd); |
aoqi@6880 | 2932 | __ cvt_d_l(ldd, ldd); |
aoqi@1 | 2933 | #endif |
aoqi@6880 | 2934 | } else if (src->is_double_stack()) { |
aoqi@6880 | 2935 | Address src_addr = frame_map()->address_for_slot(src->double_stack_ix()); |
aoqi@1 | 2936 | #ifndef _LP64 |
aoqi@6880 | 2937 | __ lw(AT, src_addr); |
aoqi@6880 | 2938 | __ mtc1(AT, ldd); |
aoqi@6880 | 2939 | __ lw(AT, src_addr.base(), src_addr.disp() + 4); |
aoqi@6880 | 2940 | __ mtc1(AT, ldd + 1); |
aoqi@6880 | 2941 | __ cvt_d_l(ldd, ldd); |
aoqi@1 | 2942 | #else |
aoqi@6880 | 2943 | __ ld(AT, src_addr); |
aoqi@6880 | 2944 | __ dmtc1(AT, ldd); |
aoqi@6880 | 2945 | __ cvt_d_l(ldd, ldd); |
aoqi@1 | 2946 | #endif |
aoqi@6880 | 2947 | } else { |
aoqi@6880 | 2948 | Unimplemented(); |
aoqi@6880 | 2949 | } |
aoqi@6880 | 2950 | break; |
aoqi@6880 | 2951 | } |
aoqi@1 | 2952 | |
aoqi@1 | 2953 | case Bytecodes::_f2l: { |
aoqi@6880 | 2954 | FloatRegister fval = src->as_float_reg(); |
aoqi@6880 | 2955 | Register dlo = dest->as_register_lo(); |
aoqi@6880 | 2956 | Register dhi = dest->as_register_hi(); |
aoqi@6880 | 2957 | |
aoqi@6880 | 2958 | Label L; |
aoqi@6880 | 2959 | __ move(dhi, R0); |
aoqi@6880 | 2960 | __ c_un_s(fval, fval); //NaN? |
aoqi@6880 | 2961 | __ bc1t(L); |
aoqi@6880 | 2962 | __ delayed(); |
aoqi@6880 | 2963 | __ move(dlo, R0); |
aoqi@6880 | 2964 | |
aoqi@6880 | 2965 | __ trunc_l_s(F30, fval); |
aoqi@1 | 2966 | #ifdef _LP64 |
aoqi@6880 | 2967 | __ cfc1(AT, 31); |
aoqi@6880 | 2968 | __ li(T9, 0x10000); |
aoqi@6880 | 2969 | __ andr(AT, AT, T9); |
aoqi@6880 | 2970 | __ beq(AT, R0, L); |
aoqi@6880 | 2971 | __ delayed()->dmfc1(dlo, F30); |
aoqi@6880 | 2972 | |
aoqi@6880 | 2973 | __ mov_s(F12, fval); |
aoqi@6880 | 2974 | __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::f2l), 1); |
aoqi@6880 | 2975 | __ move(dlo, V0); |
aoqi@1 | 2976 | #else |
aoqi@6880 | 2977 | __ mfc1(dlo, F30); |
aoqi@1 | 2978 | #endif |
aoqi@6880 | 2979 | NOT_LP64(__ mfc1(dhi, F31)); |
aoqi@6880 | 2980 | __ bind(L); |
aoqi@6880 | 2981 | break; |
aoqi@6880 | 2982 | } |
aoqi@1 | 2983 | case Bytecodes::_d2l: { |
aoqi@6880 | 2984 | FloatRegister dval = src->as_double_reg(); |
aoqi@6880 | 2985 | Register dlo = dest->as_register_lo(); |
aoqi@6880 | 2986 | Register dhi = dest->as_register_hi(); |
aoqi@6880 | 2987 | |
aoqi@6880 | 2988 | Label L; |
aoqi@6880 | 2989 | __ move(dhi, R0); |
aoqi@6880 | 2990 | __ c_un_d(dval, dval); //NaN? |
aoqi@6880 | 2991 | __ bc1t(L); |
aoqi@6880 | 2992 | __ delayed(); |
aoqi@6880 | 2993 | __ move(dlo, R0); |
aoqi@6880 | 2994 | |
aoqi@6880 | 2995 | __ trunc_l_d(F30, dval); |
aoqi@1 | 2996 | #ifdef _LP64 |
aoqi@6880 | 2997 | __ cfc1(AT, 31); |
aoqi@6880 | 2998 | __ li(T9, 0x10000); |
aoqi@6880 | 2999 | __ andr(AT, AT, T9); |
aoqi@6880 | 3000 | __ beq(AT, R0, L); |
aoqi@6880 | 3001 | __ delayed()->dmfc1(dlo, F30); |
aoqi@6880 | 3002 | |
aoqi@6880 | 3003 | __ mov_d(F12, dval); |
aoqi@6880 | 3004 | __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::d2l), 1); |
aoqi@6880 | 3005 | __ move(dlo, V0); |
aoqi@1 | 3006 | #else |
aoqi@6880 | 3007 | __ mfc1(dlo, F30); |
aoqi@6880 | 3008 | __ mfc1(dhi, F31); |
aoqi@1 | 3009 | #endif |
aoqi@6880 | 3010 | __ bind(L); |
aoqi@6880 | 3011 | break; |
aoqi@6880 | 3012 | } |
aoqi@1 | 3013 | |
aoqi@1 | 3014 | default: ShouldNotReachHere(); |
aoqi@1 | 3015 | } |
aoqi@1 | 3016 | } |
aoqi@1 | 3017 | |
aoqi@1 | 3018 | void LIR_Assembler::emit_alloc_obj(LIR_OpAllocObj* op) { |
aoqi@1 | 3019 | if (op->init_check()) { |
aoqi@1 | 3020 | add_debug_info_for_null_check_here(op->stub()->info()); |
aoqi@1 | 3021 | __ lw(AT,Address(op->klass()->as_register(), |
aoqi@6880 | 3022 | InstanceKlass::init_state_offset())); |
aoqi@6880 | 3023 | __ addi(AT, AT, -InstanceKlass::fully_initialized); |
aoqi@1 | 3024 | __ bne_far(AT, R0,*op->stub()->entry()); |
aoqi@1 | 3025 | __ delayed()->nop(); |
aoqi@1 | 3026 | } |
aoqi@1 | 3027 | __ allocate_object( |
aoqi@6880 | 3028 | op->obj()->as_register(), |
aoqi@1 | 3029 | op->tmp1()->as_register(), |
aoqi@1 | 3030 | op->tmp2()->as_register(), |
aoqi@1 | 3031 | op->header_size(), |
aoqi@1 | 3032 | op->object_size(), |
aoqi@1 | 3033 | op->klass()->as_register(), |
aoqi@1 | 3034 | *op->stub()->entry()); |
aoqi@1 | 3035 | |
aoqi@1 | 3036 | __ bind(*op->stub()->continuation()); |
aoqi@1 | 3037 | } |
aoqi@1 | 3038 | |
aoqi@1 | 3039 | void LIR_Assembler::emit_alloc_array(LIR_OpAllocArray* op) { |
aoqi@6880 | 3040 | if (UseSlowPath || |
aoqi@6880 | 3041 | (!UseFastNewObjectArray && (op->type() == T_OBJECT || op->type() == T_ARRAY)) || |
aoqi@6880 | 3042 | (!UseFastNewTypeArray && (op->type() != T_OBJECT && op->type() != T_ARRAY))) { |
aoqi@6880 | 3043 | __ b_far(*op->stub()->entry()); |
aoqi@6880 | 3044 | __ delayed()->nop(); |
aoqi@6880 | 3045 | } else { |
aoqi@6880 | 3046 | Register len = op->len()->as_register(); |
aoqi@6880 | 3047 | Register tmp1 = op->tmp1()->as_register(); |
aoqi@6880 | 3048 | Register tmp2 = op->tmp2()->as_register(); |
aoqi@6880 | 3049 | Register tmp3 = op->tmp3()->as_register(); |
aoqi@6880 | 3050 | __ allocate_array(op->obj()->as_register(), |
aoqi@6880 | 3051 | len, |
aoqi@6880 | 3052 | tmp1, |
aoqi@6880 | 3053 | tmp2, |
aoqi@6880 | 3054 | tmp3, |
aoqi@6880 | 3055 | arrayOopDesc::header_size(op->type()), |
aoqi@6880 | 3056 | array_element_size(op->type()), |
aoqi@6880 | 3057 | op->klass()->as_register(), |
aoqi@6880 | 3058 | *op->stub()->entry()); |
aoqi@6880 | 3059 | } |
aoqi@6880 | 3060 | __ bind(*op->stub()->continuation()); |
aoqi@1 | 3061 | } |
aoqi@1 | 3062 | |
aoqi@8865 | 3063 | void LIR_Assembler::type_profile_helper(Register mdo, |
aoqi@8865 | 3064 | ciMethodData *md, ciProfileData *data, |
aoqi@8865 | 3065 | Register recv, Label* update_done) { |
aoqi@8865 | 3066 | for (uint i = 0; i < ReceiverTypeData::row_limit(); i++) { |
aoqi@8865 | 3067 | Label next_test; |
aoqi@8865 | 3068 | // See if the receiver is receiver[n]. |
aoqi@8865 | 3069 | __ ld_ptr(AT, Address(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i)))); |
aoqi@8865 | 3070 | __ bne(AT, recv, next_test); |
aoqi@8865 | 3071 | __ delayed()->nop(); |
aoqi@8865 | 3072 | Address data_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i))); |
aoqi@8865 | 3073 | __ ld_ptr(AT, data_addr); |
aoqi@8865 | 3074 | __ addi(AT, AT, DataLayout::counter_increment); |
aoqi@8865 | 3075 | __ st_ptr(AT, data_addr); |
aoqi@8865 | 3076 | __ b(*update_done); |
aoqi@8865 | 3077 | __ delayed()->nop(); |
aoqi@8865 | 3078 | __ bind(next_test); |
aoqi@8865 | 3079 | } |
aoqi@8865 | 3080 | |
aoqi@8865 | 3081 | // Didn't find receiver; find next empty slot and fill it in |
aoqi@8865 | 3082 | for (uint i = 0; i < ReceiverTypeData::row_limit(); i++) { |
aoqi@8865 | 3083 | Label next_test; |
aoqi@8865 | 3084 | Address recv_addr(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_offset(i))); |
aoqi@8865 | 3085 | __ ld_ptr(AT, recv_addr); |
aoqi@8865 | 3086 | __ bne(AT, R0, next_test); |
aoqi@8865 | 3087 | __ delayed()->nop(); |
aoqi@8865 | 3088 | __ st_ptr(recv, recv_addr); |
aoqi@8865 | 3089 | __ move(AT, DataLayout::counter_increment); |
aoqi@8865 | 3090 | __ st_ptr(AT, Address(mdo, md->byte_offset_of_slot(data, ReceiverTypeData::receiver_count_offset(i)))); |
aoqi@8865 | 3091 | __ b(*update_done); |
aoqi@8865 | 3092 | __ delayed()->nop(); |
aoqi@8865 | 3093 | __ bind(next_test); |
aoqi@8865 | 3094 | } |
aoqi@8865 | 3095 | } |
aoqi@8865 | 3096 | |
aoqi@8865 | 3097 | void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, Label* failure, Label* obj_is_null) { |
aoqi@8865 | 3098 | // we always need a stub for the failure case. |
aoqi@8865 | 3099 | CodeStub* stub = op->stub(); |
aoqi@8865 | 3100 | Register obj = op->object()->as_register(); |
aoqi@8865 | 3101 | Register k_RInfo = op->tmp1()->as_register(); |
aoqi@8865 | 3102 | Register klass_RInfo = op->tmp2()->as_register(); |
aoqi@8865 | 3103 | Register dst = op->result_opr()->as_register(); |
aoqi@8865 | 3104 | ciKlass* k = op->klass(); |
aoqi@8865 | 3105 | Register Rtmp1 = noreg; |
aoqi@8865 | 3106 | |
aoqi@8865 | 3107 | // check if it needs to be profiled |
aoqi@8865 | 3108 | ciMethodData* md; |
aoqi@8865 | 3109 | ciProfileData* data; |
aoqi@8865 | 3110 | |
aoqi@8865 | 3111 | if (op->should_profile()) { |
aoqi@8865 | 3112 | ciMethod* method = op->profiled_method(); |
aoqi@8865 | 3113 | assert(method != NULL, "Should have method"); |
aoqi@8865 | 3114 | int bci = op->profiled_bci(); |
aoqi@8865 | 3115 | md = method->method_data_or_null(); |
aoqi@8865 | 3116 | assert(md != NULL, "Sanity"); |
aoqi@8865 | 3117 | data = md->bci_to_data(bci); |
aoqi@8865 | 3118 | assert(data != NULL, "need data for type check"); |
aoqi@8865 | 3119 | assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check"); |
aoqi@8865 | 3120 | } |
aoqi@8865 | 3121 | Label profile_cast_success, profile_cast_failure; |
aoqi@8865 | 3122 | Label *success_target = op->should_profile() ? &profile_cast_success : success; |
aoqi@8865 | 3123 | Label *failure_target = op->should_profile() ? &profile_cast_failure : failure; |
aoqi@8865 | 3124 | |
aoqi@8865 | 3125 | if (obj == k_RInfo) { |
aoqi@8865 | 3126 | k_RInfo = dst; |
aoqi@8865 | 3127 | } else if (obj == klass_RInfo) { |
aoqi@8865 | 3128 | klass_RInfo = dst; |
aoqi@8865 | 3129 | } |
aoqi@8865 | 3130 | if (k->is_loaded() && !UseCompressedClassPointers) { |
aoqi@8865 | 3131 | select_different_registers(obj, dst, k_RInfo, klass_RInfo); |
aoqi@8865 | 3132 | } else { |
aoqi@8865 | 3133 | Rtmp1 = op->tmp3()->as_register(); |
aoqi@8865 | 3134 | select_different_registers(obj, dst, k_RInfo, klass_RInfo, Rtmp1); |
aoqi@8865 | 3135 | } |
aoqi@8865 | 3136 | |
aoqi@8865 | 3137 | assert_different_registers(obj, k_RInfo, klass_RInfo); |
aoqi@8865 | 3138 | |
aoqi@8865 | 3139 | if (op->should_profile()) { |
aoqi@8865 | 3140 | Label not_null; |
aoqi@8865 | 3141 | __ bne(obj, R0, not_null); |
aoqi@8865 | 3142 | __ delayed()->nop(); |
aoqi@8865 | 3143 | // Object is null; update MDO and exit |
aoqi@8865 | 3144 | Register mdo = klass_RInfo; |
aoqi@8865 | 3145 | __ mov_metadata(mdo, md->constant_encoding()); |
aoqi@8865 | 3146 | Address data_addr(mdo, md->byte_offset_of_slot(data, DataLayout::header_offset())); |
aoqi@8865 | 3147 | int header_bits = DataLayout::flag_mask_to_header_mask(BitData::null_seen_byte_constant()); |
aoqi@8865 | 3148 | __ lw(AT, data_addr); |
aoqi@8865 | 3149 | __ ori(AT, AT, header_bits); |
aoqi@8865 | 3150 | __ sw(AT,data_addr); |
aoqi@8865 | 3151 | __ b(*obj_is_null); |
aoqi@8865 | 3152 | __ delayed()->nop(); |
aoqi@8865 | 3153 | __ bind(not_null); |
aoqi@8865 | 3154 | } else { |
aoqi@8865 | 3155 | __ beq(obj, R0, *obj_is_null); |
aoqi@8865 | 3156 | __ delayed()->nop(); |
aoqi@8865 | 3157 | } |
aoqi@8865 | 3158 | |
aoqi@8865 | 3159 | if (!k->is_loaded()) { |
aoqi@8865 | 3160 | klass2reg_with_patching(k_RInfo, op->info_for_patch()); |
aoqi@8865 | 3161 | } else { |
aoqi@8865 | 3162 | #ifdef _LP64 |
aoqi@8865 | 3163 | __ mov_metadata(k_RInfo, k->constant_encoding()); |
aoqi@8865 | 3164 | #endif // _LP64 |
aoqi@8865 | 3165 | } |
aoqi@8865 | 3166 | __ verify_oop(obj); |
aoqi@8865 | 3167 | |
aoqi@8865 | 3168 | if (op->fast_check()) { |
aoqi@8865 | 3169 | // get object class |
aoqi@8865 | 3170 | // not a safepoint as obj null check happens earlier |
aoqi@8865 | 3171 | if (UseCompressedClassPointers) { |
aoqi@8865 | 3172 | __ load_klass(Rtmp1, obj); |
aoqi@8865 | 3173 | __ bne(k_RInfo, Rtmp1, *failure_target); |
aoqi@8865 | 3174 | __ delayed()->nop(); |
aoqi@8865 | 3175 | } else { |
aoqi@8865 | 3176 | __ ld(AT, Address(obj, oopDesc::klass_offset_in_bytes())); |
aoqi@8865 | 3177 | __ bne(k_RInfo, AT, *failure_target); |
aoqi@8865 | 3178 | __ delayed()->nop(); |
aoqi@8865 | 3179 | } |
aoqi@8865 | 3180 | // successful cast, fall through to profile or jump |
aoqi@8865 | 3181 | } else { |
aoqi@8865 | 3182 | // get object class |
aoqi@8865 | 3183 | // not a safepoint as obj null check happens earlier |
aoqi@8865 | 3184 | __ load_klass(klass_RInfo, obj); |
aoqi@8865 | 3185 | if (k->is_loaded()) { |
aoqi@8865 | 3186 | // See if we get an immediate positive hit |
aoqi@8865 | 3187 | __ ld(AT, Address(klass_RInfo, k->super_check_offset())); |
aoqi@8865 | 3188 | if ((juint)in_bytes(Klass::secondary_super_cache_offset()) != k->super_check_offset()) { |
aoqi@8865 | 3189 | __ bne(k_RInfo, AT, *failure_target); |
aoqi@8865 | 3190 | __ delayed()->nop(); |
aoqi@8865 | 3191 | // successful cast, fall through to profile or jump |
aoqi@8865 | 3192 | } else { |
aoqi@8865 | 3193 | // See if we get an immediate positive hit |
aoqi@8865 | 3194 | __ beq(k_RInfo, AT, *success_target); |
aoqi@8865 | 3195 | __ delayed()->nop(); |
aoqi@8865 | 3196 | // check for self |
aoqi@8865 | 3197 | __ beq(k_RInfo, klass_RInfo, *success_target); |
aoqi@8865 | 3198 | __ delayed()->nop(); |
aoqi@8865 | 3199 | |
aoqi@8865 | 3200 | __ push(klass_RInfo); |
aoqi@8865 | 3201 | __ push(k_RInfo); |
aoqi@8865 | 3202 | __ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type); |
aoqi@8865 | 3203 | __ pop(klass_RInfo); |
aoqi@8865 | 3204 | __ pop(klass_RInfo); |
aoqi@8865 | 3205 | // result is a boolean |
aoqi@8865 | 3206 | __ beq(klass_RInfo, R0, *failure_target); |
aoqi@8865 | 3207 | __ delayed()->nop(); |
aoqi@8865 | 3208 | // successful cast, fall through to profile or jump |
aoqi@8865 | 3209 | } |
aoqi@8865 | 3210 | } else { |
aoqi@8865 | 3211 | // perform the fast part of the checking logic |
aoqi@8865 | 3212 | __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, Rtmp1, success_target, failure_target, NULL); |
aoqi@8865 | 3213 | // call out-of-line instance of __ check_klass_subtype_slow_path(...): |
aoqi@8865 | 3214 | __ push(klass_RInfo); |
aoqi@8865 | 3215 | __ push(k_RInfo); |
aoqi@8865 | 3216 | __ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type); |
aoqi@8865 | 3217 | __ pop(klass_RInfo); |
aoqi@8865 | 3218 | __ pop(k_RInfo); |
aoqi@8865 | 3219 | // result is a boolean |
aoqi@8865 | 3220 | __ beq(k_RInfo, R0, *failure_target); |
aoqi@8865 | 3221 | __ delayed()->nop(); |
aoqi@8865 | 3222 | // successful cast, fall through to profile or jump |
aoqi@8865 | 3223 | } |
aoqi@8865 | 3224 | } |
aoqi@8865 | 3225 | if (op->should_profile()) { |
aoqi@8865 | 3226 | Register mdo = klass_RInfo, recv = k_RInfo; |
aoqi@8865 | 3227 | __ bind(profile_cast_success); |
aoqi@8865 | 3228 | __ mov_metadata(mdo, md->constant_encoding()); |
aoqi@8865 | 3229 | __ load_klass(recv, obj); |
aoqi@8865 | 3230 | Label update_done; |
aoqi@8865 | 3231 | type_profile_helper(mdo, md, data, recv, success); |
aoqi@8865 | 3232 | __ b(*success); |
aoqi@8865 | 3233 | __ delayed()->nop(); |
aoqi@8865 | 3234 | |
aoqi@8865 | 3235 | __ bind(profile_cast_failure); |
aoqi@8865 | 3236 | __ mov_metadata(mdo, md->constant_encoding()); |
aoqi@8865 | 3237 | Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset())); |
aoqi@8865 | 3238 | __ ld_ptr(AT, counter_addr); |
aoqi@8865 | 3239 | __ addi(AT, AT, -DataLayout::counter_increment); |
aoqi@8865 | 3240 | __ st_ptr(AT, counter_addr); |
aoqi@8865 | 3241 | |
aoqi@8865 | 3242 | __ b(*failure); |
aoqi@8865 | 3243 | __ delayed()->nop(); |
aoqi@8865 | 3244 | } |
aoqi@8865 | 3245 | __ b(*success); |
aoqi@8865 | 3246 | __ delayed()->nop(); |
aoqi@8865 | 3247 | } |
aoqi@8865 | 3248 | |
aoqi@1 | 3249 | |
aoqi@1 | 3250 | |
aoqi@1 | 3251 | void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { |
aoqi@1 | 3252 | LIR_Code code = op->code(); |
aoqi@8865 | 3253 | if (code == lir_store_check) { |
aoqi@1 | 3254 | Register value = op->object()->as_register(); |
aoqi@1 | 3255 | Register array = op->array()->as_register(); |
aoqi@1 | 3256 | Register k_RInfo = op->tmp1()->as_register(); |
aoqi@1 | 3257 | Register klass_RInfo = op->tmp2()->as_register(); |
aoqi@1 | 3258 | Register tmp = op->tmp3()->as_register(); |
aoqi@1 | 3259 | |
aoqi@1 | 3260 | CodeStub* stub = op->stub(); |
aoqi@8865 | 3261 | |
aoqi@1 | 3262 | //check if it needs to be profiled |
aoqi@1 | 3263 | ciMethodData* md; |
aoqi@1 | 3264 | ciProfileData* data; |
aoqi@8865 | 3265 | |
aoqi@1 | 3266 | if (op->should_profile()) { |
aoqi@1 | 3267 | ciMethod* method = op->profiled_method(); |
aoqi@1 | 3268 | assert(method != NULL, "Should have method"); |
aoqi@8865 | 3269 | int bci = op->profiled_bci(); |
aoqi@1 | 3270 | md = method->method_data_or_null(); |
aoqi@1 | 3271 | assert(md != NULL, "Sanity"); |
aoqi@1 | 3272 | data = md->bci_to_data(bci); |
aoqi@8865 | 3273 | assert(data != NULL, "need data for type check"); |
aoqi@1 | 3274 | assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check"); |
aoqi@1 | 3275 | } |
aoqi@1 | 3276 | Label profile_cast_success, profile_cast_failure, done; |
aoqi@1 | 3277 | Label *success_target = op->should_profile() ? &profile_cast_success : &done; |
aoqi@8865 | 3278 | Label *failure_target = op->should_profile() ? &profile_cast_failure : stub->entry(); |
aoqi@8865 | 3279 | |
aoqi@1 | 3280 | if(op->should_profile()) { |
aoqi@8865 | 3281 | Label not_null; |
aoqi@8865 | 3282 | __ bne(value, R0, not_null); |
aoqi@8865 | 3283 | __ delayed()->nop(); |
aoqi@8865 | 3284 | |
aoqi@8865 | 3285 | Register mdo = klass_RInfo; |
aoqi@8865 | 3286 | __ mov_metadata(mdo, md->constant_encoding()); |
aoqi@8865 | 3287 | Address data_addr(mdo, md->byte_offset_of_slot(data, DataLayout::header_offset())); |
aoqi@8865 | 3288 | int header_bits = DataLayout::flag_mask_to_header_mask(BitData::null_seen_byte_constant()); |
aoqi@8865 | 3289 | __ lw(AT, data_addr); |
aoqi@8865 | 3290 | __ ori(AT, AT, header_bits); |
aoqi@8865 | 3291 | __ sw(AT,data_addr); |
aoqi@8865 | 3292 | __ b(done); |
aoqi@8865 | 3293 | __ delayed()->nop(); |
aoqi@8865 | 3294 | __ bind(not_null); |
aoqi@8865 | 3295 | } else { |
aoqi@8865 | 3296 | __ beq(value, R0, done); |
aoqi@8865 | 3297 | __ delayed()->nop(); |
aoqi@8865 | 3298 | } |
aoqi@8865 | 3299 | |
aoqi@1 | 3300 | add_debug_info_for_null_check_here(op->info_for_exception()); |
aoqi@1 | 3301 | __ load_klass(k_RInfo, array); |
aoqi@1 | 3302 | __ load_klass(klass_RInfo, value); |
aoqi@8865 | 3303 | // get instance klass (it's already uncompressed) |
aoqi@8865 | 3304 | __ ld_ptr(k_RInfo, Address(k_RInfo, ObjArrayKlass::element_klass_offset())); |
aoqi@8865 | 3305 | // perform the fast part of the checking logic |
aoqi@8865 | 3306 | __ check_klass_subtype_fast_path(klass_RInfo, k_RInfo, tmp, success_target, failure_target, NULL); |
aoqi@8865 | 3307 | __ push(klass_RInfo); |
aoqi@8865 | 3308 | __ push(k_RInfo); |
aoqi@8865 | 3309 | __ call(Runtime1::entry_for(Runtime1::slow_subtype_check_id), relocInfo::runtime_call_type); |
aoqi@8865 | 3310 | __ pop(klass_RInfo); |
aoqi@8865 | 3311 | __ pop(k_RInfo); |
aoqi@8865 | 3312 | // result is a boolean |
aoqi@8865 | 3313 | __ beq(k_RInfo, R0, *failure_target); |
aoqi@8865 | 3314 | __ delayed()->nop(); |
aoqi@8865 | 3315 | // fall through to the success case |
aoqi@8865 | 3316 | |
aoqi@8865 | 3317 | if (op->should_profile()) { |
aoqi@8865 | 3318 | Register mdo = klass_RInfo, recv = k_RInfo; |
aoqi@8865 | 3319 | __ bind(profile_cast_success); |
aoqi@8865 | 3320 | __ mov_metadata(mdo, md->constant_encoding()); |
aoqi@8865 | 3321 | __ load_klass(recv, value); |
aoqi@8865 | 3322 | Label update_done; |
aoqi@8865 | 3323 | type_profile_helper(mdo, md, data, recv, &done); |
aoqi@8865 | 3324 | __ b(done); |
aoqi@8865 | 3325 | __ delayed()->nop(); |
aoqi@8865 | 3326 | |
aoqi@8865 | 3327 | __ bind(profile_cast_failure); |
aoqi@8865 | 3328 | __ mov_metadata(mdo, md->constant_encoding()); |
aoqi@8865 | 3329 | Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset())); |
aoqi@8865 | 3330 | __ ld_ptr(AT, counter_addr); |
aoqi@8865 | 3331 | __ addi(AT, AT, -DataLayout::counter_increment); |
aoqi@8865 | 3332 | __ st_ptr(AT, counter_addr); |
aoqi@8865 | 3333 | __ b(*stub->entry()); |
aoqi@8865 | 3334 | __ delayed()->nop(); |
aoqi@8865 | 3335 | } |
aoqi@8865 | 3336 | |
aoqi@8865 | 3337 | __ bind(done); |
aoqi@8865 | 3338 | } else if (code == lir_checkcast) { |
aoqi@8865 | 3339 | Register obj = op->object()->as_register(); |
aoqi@8865 | 3340 | Register dst = op->result_opr()->as_register(); |
aoqi@8865 | 3341 | Label success; |
aoqi@8865 | 3342 | emit_typecheck_helper(op, &success, op->stub()->entry(), &success); |
aoqi@8865 | 3343 | __ bind(success); |
aoqi@8865 | 3344 | if (dst != obj) { |
aoqi@8865 | 3345 | __ move(dst, obj); |
aoqi@8865 | 3346 | } |
aoqi@8865 | 3347 | } else if (code == lir_instanceof) { |
aoqi@8865 | 3348 | Register obj = op->object()->as_register(); |
aoqi@8865 | 3349 | Register dst = op->result_opr()->as_register(); |
aoqi@8865 | 3350 | Label success, failure, done; |
aoqi@8865 | 3351 | emit_typecheck_helper(op, &success, &failure, &failure); |
aoqi@8865 | 3352 | __ bind(failure); |
aoqi@8865 | 3353 | __ move(dst, R0); |
aoqi@8865 | 3354 | __ b(done); |
aoqi@8865 | 3355 | __ delayed()->nop(); |
aoqi@8865 | 3356 | __ bind(success); |
aoqi@8865 | 3357 | __ addi(dst, R0, 1); |
aoqi@8865 | 3358 | __ bind(done); |
aoqi@8865 | 3359 | } else { |
aoqi@8865 | 3360 | ShouldNotReachHere(); |
aoqi@8865 | 3361 | } |
aoqi@1 | 3362 | } |
aoqi@1 | 3363 | |
aoqi@1 | 3364 | void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) { |
aoqi@1 | 3365 | if (op->code() == lir_cas_long) { |
aoqi@1 | 3366 | #ifdef _LP64 |
aoqi@1 | 3367 | Register addr = (op->addr()->is_single_cpu() ? op->addr()->as_register() : op->addr()->as_register_lo()); |
aoqi@1 | 3368 | Register newval = (op->new_value()->is_single_cpu() ? op->new_value()->as_register() : op->new_value()->as_register_lo()); |
aoqi@1 | 3369 | Register cmpval = (op->cmp_value()->is_single_cpu() ? op->cmp_value()->as_register() : op->cmp_value()->as_register_lo()); |
aoqi@1 | 3370 | assert(newval != NULL, "new val must be register"); |
aoqi@1 | 3371 | assert(cmpval != newval, "cmp and new values must be in different registers"); |
aoqi@1 | 3372 | assert(cmpval != addr, "cmp and addr must be in different registers"); |
aoqi@1 | 3373 | assert(newval != addr, "new value and addr must be in different registers"); |
aoqi@6880 | 3374 | if (os::is_MP()) {} |
aoqi@6880 | 3375 | __ cmpxchg(newval, addr, cmpval); // 64-bit test-and-set |
aoqi@1 | 3376 | #else |
aoqi@1 | 3377 | Register addr = op->addr()->as_register(); |
aoqi@6880 | 3378 | if (os::is_MP()) {} |
aoqi@6880 | 3379 | __ cmpxchg8(op->new_value()->as_register_lo(), |
aoqi@6880 | 3380 | op->new_value()->as_register_hi(), |
aoqi@6880 | 3381 | addr, |
aoqi@6880 | 3382 | op->cmp_value()->as_register_lo(), |
aoqi@6880 | 3383 | op->cmp_value()->as_register_hi()) |
aoqi@1 | 3384 | #endif |
aoqi@1 | 3385 | } else if (op->code() == lir_cas_int || op->code() == lir_cas_obj) { |
aoqi@1 | 3386 | NOT_LP64(assert(op->addr()->is_single_cpu(), "must be single");) |
aoqi@1 | 3387 | Register addr = (op->addr()->is_single_cpu() ? op->addr()->as_register() : op->addr()->as_register_lo()); |
aoqi@1 | 3388 | Register newval = op->new_value()->as_register(); |
aoqi@1 | 3389 | Register cmpval = op->cmp_value()->as_register(); |
aoqi@1 | 3390 | assert(newval != NULL, "new val must be register"); |
aoqi@1 | 3391 | assert(cmpval != newval, "cmp and new values must be in different registers"); |
aoqi@1 | 3392 | assert(cmpval != addr, "cmp and addr must be in different registers"); |
aoqi@1 | 3393 | assert(newval != addr, "new value and addr must be in different registers"); |
aoqi@1 | 3394 | if (op->code() == lir_cas_obj) { |
aoqi@1 | 3395 | #ifdef _LP64 |
aoqi@6880 | 3396 | if (UseCompressedOops) { |
aoqi@6880 | 3397 | Register tmp_reg = S7; |
aoqi@6880 | 3398 | __ push(cmpval); |
aoqi@6880 | 3399 | __ encode_heap_oop(cmpval); |
aoqi@6880 | 3400 | __ move(tmp_reg, newval); |
aoqi@6880 | 3401 | __ encode_heap_oop(tmp_reg); |
aoqi@6880 | 3402 | if (os::is_MP()) {} |
aoqi@6880 | 3403 | __ cmpxchg32(tmp_reg, addr, cmpval); // 32-bit test-and-set |
aoqi@6880 | 3404 | __ pop(cmpval); |
aoqi@6880 | 3405 | } else |
aoqi@6880 | 3406 | { |
aoqi@6880 | 3407 | if (os::is_MP()) {} |
aoqi@6880 | 3408 | __ cmpxchg(newval, addr, cmpval); // 64-bit test-and-set |
aoqi@6880 | 3409 | } |
aoqi@6880 | 3410 | } else |
aoqi@1 | 3411 | #endif |
aoqi@1 | 3412 | { |
aoqi@6880 | 3413 | __ cmpxchg32(newval, addr, cmpval); // 32-bit test-and-set |
aoqi@1 | 3414 | } |
aoqi@1 | 3415 | } else { |
aoqi@1 | 3416 | Unimplemented(); |
aoqi@1 | 3417 | } |
aoqi@1 | 3418 | } |
aoqi@1 | 3419 | #ifndef MIPS64 |
aoqi@1 | 3420 | void LIR_Assembler::cmove(LIR_Condition condition, LIR_Opr opr1, LIR_Opr opr2, LIR_Opr result) { |
aoqi@1 | 3421 | Unimplemented(); |
aoqi@1 | 3422 | } |
aoqi@1 | 3423 | #endif |
aoqi@1 | 3424 | void LIR_Assembler::arith_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dest, CodeEmitInfo* info,bool pop_fpu_stack) { |
aoqi@1 | 3425 | assert(info == NULL || ((code == lir_rem || code == lir_div || code == lir_sub) && right->is_double_cpu()), "info is only for ldiv/lrem"); |
aoqi@1 | 3426 | if (left->is_single_cpu()) { |
aoqi@1 | 3427 | // left may not be equal to dest on mips. |
aoqi@1 | 3428 | //assert(left == dest, "left and dest must be equal"); |
aoqi@1 | 3429 | Register lreg = left->as_register(); |
aoqi@1 | 3430 | |
aoqi@1 | 3431 | if (right->is_cpu_register()) { |
aoqi@1 | 3432 | // cpu register - cpu register |
aoqi@6880 | 3433 | Register rreg, res; |
aoqi@1 | 3434 | if (right->is_single_cpu()) { |
aoqi@6880 | 3435 | rreg = right->as_register(); |
aoqi@1 | 3436 | #ifdef _LP64 |
aoqi@6880 | 3437 | if(dest->is_double_cpu()) |
aoqi@6880 | 3438 | res = dest->as_register_lo(); |
aoqi@6880 | 3439 | else |
aoqi@1 | 3440 | #endif |
aoqi@6880 | 3441 | res = dest->as_register(); |
aoqi@1 | 3442 | } else if (right->is_double_cpu()) { |
aoqi@6880 | 3443 | assert(right->is_double_cpu(),"right must be long"); |
aoqi@6880 | 3444 | rreg = right->as_register_lo(); |
aoqi@6880 | 3445 | res = dest->as_register_lo(); |
aoqi@1 | 3446 | } else { |
aoqi@6880 | 3447 | ShouldNotReachHere(); |
aoqi@1 | 3448 | } |
aoqi@1 | 3449 | switch (code) { |
aoqi@6880 | 3450 | case lir_add: |
aoqi@1 | 3451 | #ifdef _LP64 |
aoqi@6880 | 3452 | if (dest->type() == T_INT) |
aoqi@6880 | 3453 | __ addu32(res, lreg, rreg); |
aoqi@6880 | 3454 | else |
aoqi@1 | 3455 | #endif |
aoqi@6880 | 3456 | __ addu(res, lreg, rreg); |
aoqi@6880 | 3457 | break; |
aoqi@6880 | 3458 | |
aoqi@6880 | 3459 | case lir_mul: |
aoqi@1 | 3460 | #ifndef _LP64 |
aoqi@6880 | 3461 | //by aoqi |
aoqi@6880 | 3462 | __ mult(lreg, rreg); |
aoqi@1 | 3463 | #else |
aoqi@6880 | 3464 | __ dmult(lreg, rreg); |
aoqi@1 | 3465 | #endif |
aoqi@6880 | 3466 | __ nop(); |
aoqi@6880 | 3467 | __ nop(); |
aoqi@6880 | 3468 | __ mflo(res); |
aoqi@1 | 3469 | #ifdef _LP64 |
aoqi@6880 | 3470 | /* Jin: if res < 0, it must be sign-extended. Otherwise it will be a 64-bit positive number. |
aoqi@1 | 3471 | * |
aoqi@1 | 3472 | * Example: java.net.URLClassLoader::string2int() |
aoqi@1 | 3473 | * a6: 0xcafebab |
aoqi@1 | 3474 | * s0: 16 |
aoqi@6880 | 3475 | * |
aoqi@1 | 3476 | * 104 mul [a6|I] [s0|I] [t0|I] |
aoqi@6880 | 3477 | 0x00000055655e3728: dmult a6, s0 |
aoqi@6880 | 3478 | 0x00000055655e372c: sll zero, zero, 0 |
aoqi@6880 | 3479 | 0x00000055655e3730: sll zero, zero, 0 |
aoqi@6880 | 3480 | 0x00000055655e3734: mflo t0 <-- error |
aoqi@6880 | 3481 | * |
aoqi@6880 | 3482 | * t0: 0xFFFFFFFFcafebab0 (Right) |
aoqi@6880 | 3483 | * t0: 0x00000000cafebab0 (Wrong) |
aoqi@6880 | 3484 | */ |
aoqi@6880 | 3485 | if (dest->type() == T_INT) |
aoqi@6880 | 3486 | __ sll(res, res, 0); |
aoqi@1 | 3487 | #endif |
aoqi@6880 | 3488 | break; |
aoqi@6880 | 3489 | |
aoqi@6880 | 3490 | case lir_sub: |
aoqi@1 | 3491 | #ifdef _LP64 |
aoqi@6880 | 3492 | if (dest->type() == T_INT) |
aoqi@6880 | 3493 | __ subu32(res, lreg, rreg); |
aoqi@6880 | 3494 | else |
aoqi@1 | 3495 | #endif |
aoqi@6880 | 3496 | __ subu(res, lreg, rreg); |
aoqi@6880 | 3497 | break; |
aoqi@6880 | 3498 | |
aoqi@6880 | 3499 | default: |
aoqi@6880 | 3500 | ShouldNotReachHere(); |
aoqi@1 | 3501 | } |
aoqi@1 | 3502 | } else if (right->is_stack()) { |
aoqi@1 | 3503 | // cpu register - stack |
aoqi@1 | 3504 | Unimplemented(); |
aoqi@1 | 3505 | } else if (right->is_constant()) { |
aoqi@1 | 3506 | // cpu register - constant |
aoqi@8865 | 3507 | Register res; |
aoqi@8865 | 3508 | if (dest->is_double_cpu()) { |
aoqi@8865 | 3509 | res = dest->as_register_lo(); |
aoqi@8865 | 3510 | } else { |
aoqi@8865 | 3511 | res = dest->as_register(); |
aoqi@8865 | 3512 | } |
aoqi@8865 | 3513 | jint c; |
aoqi@8865 | 3514 | if (right->type() == T_INT) { |
aoqi@8865 | 3515 | c = right->as_constant_ptr()->as_jint(); |
aoqi@8865 | 3516 | } else { |
aoqi@8865 | 3517 | c = right->as_constant_ptr()->as_jlong(); |
aoqi@8865 | 3518 | } |
aoqi@1 | 3519 | |
aoqi@1 | 3520 | switch (code) { |
aoqi@6880 | 3521 | case lir_mul_strictfp: |
aoqi@6880 | 3522 | case lir_mul: |
aoqi@6880 | 3523 | __ move(AT, c); |
aoqi@1 | 3524 | #ifndef _LP64 |
aoqi@6880 | 3525 | //by aoqi |
aoqi@6880 | 3526 | __ mult(lreg, AT); |
aoqi@1 | 3527 | #else |
aoqi@6880 | 3528 | __ dmult(lreg, AT); |
aoqi@1 | 3529 | #endif |
aoqi@6880 | 3530 | __ nop(); |
aoqi@6880 | 3531 | __ nop(); |
aoqi@6880 | 3532 | __ mflo(res); |
aoqi@1 | 3533 | #ifdef _LP64 |
aoqi@6880 | 3534 | /* Jin: if res < 0, it must be sign-extended. Otherwise it will be a 64-bit positive number. |
aoqi@1 | 3535 | * |
aoqi@1 | 3536 | * Example: java.net.URLClassLoader::string2int() |
aoqi@1 | 3537 | * a6: 0xcafebab |
aoqi@1 | 3538 | * s0: 16 |
aoqi@6880 | 3539 | * |
aoqi@1 | 3540 | * 104 mul [a6|I] [s0|I] [t0|I] |
aoqi@6880 | 3541 | 0x00000055655e3728: dmult a6, s0 |
aoqi@6880 | 3542 | 0x00000055655e372c: sll zero, zero, 0 |
aoqi@6880 | 3543 | 0x00000055655e3730: sll zero, zero, 0 |
aoqi@6880 | 3544 | 0x00000055655e3734: mflo t0 <-- error |
aoqi@6880 | 3545 | * |
aoqi@6880 | 3546 | * t0: 0xFFFFFFFFcafebab0 (Right) |
aoqi@6880 | 3547 | * t0: 0x00000000cafebab0 (Wrong) |
aoqi@6880 | 3548 | */ |
aoqi@6880 | 3549 | if (dest->type() == T_INT) |
aoqi@6880 | 3550 | __ sll(res, res, 0); |
aoqi@1 | 3551 | #endif |
aoqi@6880 | 3552 | break; |
aoqi@6880 | 3553 | |
aoqi@6880 | 3554 | case lir_add: |
aoqi@6880 | 3555 | if (Assembler::is_simm16(c)) { |
aoqi@6880 | 3556 | __ addiu(res, lreg, c); |
aoqi@6880 | 3557 | } else { |
aoqi@6880 | 3558 | __ move(AT, c); |
aoqi@6880 | 3559 | __ addu(res, lreg, AT); |
aoqi@6880 | 3560 | } |
aoqi@6880 | 3561 | break; |
aoqi@6880 | 3562 | |
aoqi@6880 | 3563 | case lir_sub: |
aoqi@6880 | 3564 | if (Assembler::is_simm16(-c)) { |
aoqi@6880 | 3565 | __ addi(res, lreg, -c); |
aoqi@6880 | 3566 | } else { |
aoqi@6880 | 3567 | __ move(AT, c); |
aoqi@6880 | 3568 | __ subu(res, lreg, AT); |
aoqi@6880 | 3569 | } |
aoqi@6880 | 3570 | break; |
aoqi@6880 | 3571 | |
aoqi@6880 | 3572 | default: |
aoqi@6880 | 3573 | ShouldNotReachHere(); |
aoqi@1 | 3574 | } |
aoqi@1 | 3575 | } else { |
aoqi@1 | 3576 | ShouldNotReachHere(); |
aoqi@1 | 3577 | } |
aoqi@1 | 3578 | |
aoqi@1 | 3579 | } else if (left->is_double_cpu()) { |
aoqi@1 | 3580 | Register op1_lo = left->as_register_lo(); |
aoqi@1 | 3581 | Register op1_hi = left->as_register_hi(); |
aoqi@1 | 3582 | Register op2_lo; |
aoqi@1 | 3583 | Register op2_hi; |
aoqi@1 | 3584 | Register dst_lo; |
aoqi@1 | 3585 | Register dst_hi; |
aoqi@1 | 3586 | |
aoqi@1 | 3587 | if(dest->is_single_cpu()) |
aoqi@1 | 3588 | { |
aoqi@1 | 3589 | dst_lo = dest->as_register(); |
aoqi@1 | 3590 | } |
aoqi@1 | 3591 | else |
aoqi@1 | 3592 | { |
aoqi@1 | 3593 | #ifdef _LP64 |
aoqi@1 | 3594 | dst_lo = dest->as_register_lo(); |
aoqi@1 | 3595 | #else |
aoqi@1 | 3596 | dst_lo = dest->as_register_lo(); |
aoqi@1 | 3597 | dst_hi = dest->as_register_hi(); |
aoqi@1 | 3598 | #endif |
aoqi@1 | 3599 | } |
aoqi@1 | 3600 | if (right->is_constant()) { |
aoqi@1 | 3601 | op2_lo = AT; |
aoqi@1 | 3602 | op2_hi = R0; |
aoqi@1 | 3603 | #ifndef _LP64 |
aoqi@1 | 3604 | __ li(AT, right->as_constant_ptr()->as_jint()); |
aoqi@1 | 3605 | #else |
aoqi@1 | 3606 | __ li(AT, right->as_constant_ptr()->as_jlong_bits()); |
aoqi@1 | 3607 | #endif |
aoqi@1 | 3608 | } else if (right->is_double_cpu()) { // Double cpu |
aoqi@1 | 3609 | assert(right->is_double_cpu(),"right must be long"); |
aoqi@1 | 3610 | assert(dest->is_double_cpu(), "dest must be long"); |
aoqi@1 | 3611 | op2_lo = right->as_register_lo(); |
aoqi@1 | 3612 | op2_hi = right->as_register_hi(); |
aoqi@1 | 3613 | } else { |
aoqi@1 | 3614 | #ifdef _LP64 |
aoqi@1 | 3615 | op2_lo = right->as_register(); |
aoqi@1 | 3616 | #else |
aoqi@1 | 3617 | ShouldNotReachHere(); |
aoqi@1 | 3618 | #endif |
aoqi@1 | 3619 | } |
aoqi@1 | 3620 | |
aoqi@1 | 3621 | NOT_LP64(assert_different_registers(op1_lo, op1_hi, op2_lo, op2_hi)); |
aoqi@1 | 3622 | // Jin: Why? |
aoqi@1 | 3623 | // LP64_ONLY(assert_different_registers(op1_lo, op2_lo)); |
aoqi@1 | 3624 | |
aoqi@1 | 3625 | switch (code) { |
aoqi@1 | 3626 | case lir_add: |
aoqi@1 | 3627 | #ifndef _LP64 |
aoqi@6880 | 3628 | //by aoqi |
aoqi@6880 | 3629 | __ addu(dst_lo, op1_lo, op2_lo); |
aoqi@6880 | 3630 | __ sltu(AT, dst_lo, op2_lo); |
aoqi@6880 | 3631 | __ addu(dst_hi, op1_hi, op2_hi); |
aoqi@6880 | 3632 | __ addu(dst_hi, dst_hi, AT); |
aoqi@1 | 3633 | #else |
aoqi@6880 | 3634 | __ addu(dst_lo, op1_lo, op2_lo); |
aoqi@1 | 3635 | #endif |
aoqi@6880 | 3636 | break; |
aoqi@1 | 3637 | |
aoqi@1 | 3638 | case lir_sub: |
aoqi@1 | 3639 | #ifndef _LP64 |
aoqi@6880 | 3640 | //by aoqi |
aoqi@6880 | 3641 | __ subu(dst_lo, op1_lo, op2_lo); |
aoqi@6880 | 3642 | __ sltu(AT, op1_lo, dst_lo); |
aoqi@6880 | 3643 | __ subu(dst_hi, op1_hi, op2_hi); |
aoqi@6880 | 3644 | __ subu(dst_hi, dst_hi, AT); |
aoqi@1 | 3645 | #else |
aoqi@6880 | 3646 | __ subu(dst_lo, op1_lo, op2_lo); |
aoqi@1 | 3647 | #endif |
aoqi@6880 | 3648 | break; |
aoqi@1 | 3649 | |
aoqi@1 | 3650 | case lir_mul: |
aoqi@6880 | 3651 | { |
aoqi@1 | 3652 | |
aoqi@1 | 3653 | #ifndef _LP64 |
aoqi@6880 | 3654 | //by aoqi |
aoqi@6880 | 3655 | Label zero, quick, done; |
aoqi@6880 | 3656 | //zero? |
aoqi@6880 | 3657 | __ orr(AT, op2_lo, op1_lo); |
aoqi@6880 | 3658 | __ beq(AT, R0, zero); |
aoqi@6880 | 3659 | __ delayed(); |
aoqi@6880 | 3660 | __ move(dst_hi, R0); |
aoqi@6880 | 3661 | |
aoqi@6880 | 3662 | //quick? |
aoqi@6880 | 3663 | __ orr(AT, op2_hi, op1_hi); |
aoqi@6880 | 3664 | __ beq(AT, R0, quick); |
aoqi@6880 | 3665 | __ delayed()->nop(); |
aoqi@6880 | 3666 | |
aoqi@6880 | 3667 | __ multu(op2_lo, op1_hi); |
aoqi@6880 | 3668 | __ nop(); |
aoqi@6880 | 3669 | __ nop(); |
aoqi@6880 | 3670 | __ mflo(dst_hi); |
aoqi@6880 | 3671 | __ multu(op2_hi, op1_lo); |
aoqi@6880 | 3672 | __ nop(); |
aoqi@6880 | 3673 | __ nop(); |
aoqi@6880 | 3674 | __ mflo(AT); |
aoqi@6880 | 3675 | |
aoqi@6880 | 3676 | __ bind(quick); |
aoqi@6880 | 3677 | __ multu(op2_lo, op1_lo); |
aoqi@6880 | 3678 | __ addu(dst_hi, dst_hi, AT); |
aoqi@6880 | 3679 | __ nop(); |
aoqi@6880 | 3680 | __ mflo(dst_lo); |
aoqi@6880 | 3681 | __ mfhi(AT); |
aoqi@6880 | 3682 | __ b(done); |
aoqi@6880 | 3683 | __ delayed()->addu(dst_hi, dst_hi, AT); |
aoqi@6880 | 3684 | |
aoqi@6880 | 3685 | __ bind(zero); |
aoqi@6880 | 3686 | __ move(dst_lo, R0); |
aoqi@6880 | 3687 | __ bind(done); |
aoqi@1 | 3688 | #else |
aoqi@6880 | 3689 | Label zero, done; |
aoqi@6880 | 3690 | //zero? |
aoqi@6880 | 3691 | __ orr(AT, op2_lo, op1_lo); |
aoqi@6880 | 3692 | __ beq(AT, R0, zero); |
aoqi@6880 | 3693 | __ delayed(); |
aoqi@6880 | 3694 | __ move(dst_hi, R0); |
aoqi@1 | 3695 | |
aoqi@1 | 3696 | #ifdef ASSERT |
aoqi@6880 | 3697 | //op1_hi, op2_hi should be 0 |
aoqi@6880 | 3698 | { |
aoqi@6880 | 3699 | Label L; |
aoqi@6880 | 3700 | __ beq(op1_hi, R0, L); |
aoqi@6880 | 3701 | __ delayed()->nop(); |
aoqi@6880 | 3702 | __ stop("wrong register, lir_mul"); |
aoqi@6880 | 3703 | __ bind(L); |
aoqi@6880 | 3704 | } |
aoqi@6880 | 3705 | { |
aoqi@6880 | 3706 | Label L; |
aoqi@6880 | 3707 | __ beq(op2_hi, R0, L); |
aoqi@6880 | 3708 | __ delayed()->nop(); |
aoqi@6880 | 3709 | __ stop("wrong register, lir_mul"); |
aoqi@6880 | 3710 | __ bind(L); |
aoqi@6880 | 3711 | } |
aoqi@1 | 3712 | #endif |
aoqi@1 | 3713 | |
aoqi@6880 | 3714 | __ multu(op2_lo, op1_lo); |
aoqi@6880 | 3715 | __ nop(); |
aoqi@6880 | 3716 | __ nop(); |
aoqi@6880 | 3717 | __ mflo(dst_lo); |
aoqi@6880 | 3718 | __ b(done); |
aoqi@6880 | 3719 | __ delayed()->nop(); |
aoqi@6880 | 3720 | |
aoqi@6880 | 3721 | __ bind(zero); |
aoqi@6880 | 3722 | __ move(dst_lo, R0); |
aoqi@6880 | 3723 | __ bind(done); |
aoqi@6880 | 3724 | #endif //_LP64 |
aoqi@6880 | 3725 | } |
aoqi@6880 | 3726 | break; |
aoqi@1 | 3727 | |
aoqi@1 | 3728 | default: |
aoqi@6880 | 3729 | ShouldNotReachHere(); |
aoqi@1 | 3730 | } |
aoqi@1 | 3731 | |
aoqi@1 | 3732 | |
aoqi@1 | 3733 | } else if (left->is_single_fpu()) { |
aoqi@1 | 3734 | assert(right->is_single_fpu(),"right must be float"); |
aoqi@1 | 3735 | assert(dest->is_single_fpu(), "dest must be float"); |
aoqi@1 | 3736 | |
aoqi@1 | 3737 | FloatRegister lreg = left->as_float_reg(); |
aoqi@1 | 3738 | FloatRegister rreg = right->as_float_reg(); |
aoqi@1 | 3739 | FloatRegister res = dest->as_float_reg(); |
aoqi@1 | 3740 | |
aoqi@1 | 3741 | switch (code) { |
aoqi@6880 | 3742 | case lir_add: |
aoqi@6880 | 3743 | __ add_s(res, lreg, rreg); |
aoqi@6880 | 3744 | break; |
aoqi@6880 | 3745 | case lir_sub: |
aoqi@6880 | 3746 | __ sub_s(res, lreg, rreg); |
aoqi@6880 | 3747 | break; |
aoqi@6880 | 3748 | case lir_mul: |
aoqi@1 | 3749 | case lir_mul_strictfp: |
aoqi@6880 | 3750 | // i dont think we need special handling of this. FIXME |
aoqi@6880 | 3751 | __ mul_s(res, lreg, rreg); |
aoqi@6880 | 3752 | break; |
aoqi@6880 | 3753 | case lir_div: |
aoqi@1 | 3754 | case lir_div_strictfp: |
aoqi@6880 | 3755 | __ div_s(res, lreg, rreg); |
aoqi@6880 | 3756 | break; |
aoqi@1 | 3757 | default : ShouldNotReachHere(); |
aoqi@1 | 3758 | } |
aoqi@1 | 3759 | } else if (left->is_double_fpu()) { |
aoqi@1 | 3760 | assert(right->is_double_fpu(),"right must be double"); |
aoqi@1 | 3761 | assert(dest->is_double_fpu(), "dest must be double"); |
aoqi@1 | 3762 | |
aoqi@1 | 3763 | FloatRegister lreg = left->as_double_reg(); |
aoqi@1 | 3764 | FloatRegister rreg = right->as_double_reg(); |
aoqi@1 | 3765 | FloatRegister res = dest->as_double_reg(); |
aoqi@1 | 3766 | |
aoqi@1 | 3767 | switch (code) { |
aoqi@6880 | 3768 | case lir_add: |
aoqi@6880 | 3769 | __ add_d(res, lreg, rreg); |
aoqi@6880 | 3770 | break; |
aoqi@6880 | 3771 | case lir_sub: |
aoqi@6880 | 3772 | __ sub_d(res, lreg, rreg); |
aoqi@6880 | 3773 | break; |
aoqi@6880 | 3774 | case lir_mul: |
aoqi@1 | 3775 | case lir_mul_strictfp: |
aoqi@6880 | 3776 | // i dont think we need special handling of this. FIXME |
aoqi@6880 | 3777 | // by yjl 9/13/2005 |
aoqi@6880 | 3778 | __ mul_d(res, lreg, rreg); |
aoqi@6880 | 3779 | break; |
aoqi@6880 | 3780 | case lir_div: |
aoqi@1 | 3781 | case lir_div_strictfp: |
aoqi@6880 | 3782 | __ div_d(res, lreg, rreg); |
aoqi@6880 | 3783 | break; |
aoqi@6880 | 3784 | // case lir_rem: |
aoqi@6880 | 3785 | // __ rem_d(res, lreg, rreg); |
aoqi@6880 | 3786 | // break; |
aoqi@1 | 3787 | default : ShouldNotReachHere(); |
aoqi@1 | 3788 | } |
aoqi@1 | 3789 | } |
aoqi@1 | 3790 | else if (left->is_single_stack() || left->is_address()) { |
aoqi@1 | 3791 | assert(left == dest, "left and dest must be equal"); |
aoqi@1 | 3792 | |
aoqi@1 | 3793 | Address laddr; |
aoqi@1 | 3794 | if (left->is_single_stack()) { |
aoqi@1 | 3795 | laddr = frame_map()->address_for_slot(left->single_stack_ix()); |
aoqi@1 | 3796 | } else if (left->is_address()) { |
aoqi@1 | 3797 | laddr = as_Address(left->as_address_ptr()); |
aoqi@1 | 3798 | } else { |
aoqi@1 | 3799 | ShouldNotReachHere(); |
aoqi@1 | 3800 | } |
aoqi@1 | 3801 | |
aoqi@1 | 3802 | if (right->is_single_cpu()) { |
aoqi@1 | 3803 | Register rreg = right->as_register(); |
aoqi@1 | 3804 | switch (code) { |
aoqi@6880 | 3805 | case lir_add: |
aoqi@1 | 3806 | #ifndef _LP64 |
aoqi@6880 | 3807 | //by aoqi |
aoqi@6880 | 3808 | __ lw(AT, laddr); |
aoqi@6880 | 3809 | __ add(AT, AT, rreg); |
aoqi@6880 | 3810 | __ sw(AT, laddr); |
aoqi@1 | 3811 | #else |
aoqi@6880 | 3812 | __ ld(AT, laddr); |
aoqi@6880 | 3813 | __ dadd(AT, AT, rreg); |
aoqi@6880 | 3814 | __ sd(AT, laddr); |
aoqi@1 | 3815 | #endif |
aoqi@6880 | 3816 | break; |
aoqi@6880 | 3817 | case lir_sub: |
aoqi@1 | 3818 | #ifndef _LP64 |
aoqi@6880 | 3819 | //by aoqi |
aoqi@6880 | 3820 | __ lw(AT, laddr); |
aoqi@6880 | 3821 | __ sub(AT,AT,rreg); |
aoqi@6880 | 3822 | __ sw(AT, laddr); |
aoqi@1 | 3823 | #else |
aoqi@6880 | 3824 | __ ld(AT, laddr); |
aoqi@6880 | 3825 | __ dsub(AT,AT,rreg); |
aoqi@6880 | 3826 | __ sd(AT, laddr); |
aoqi@1 | 3827 | #endif |
aoqi@6880 | 3828 | break; |
aoqi@6880 | 3829 | default: ShouldNotReachHere(); |
aoqi@1 | 3830 | } |
aoqi@1 | 3831 | } else if (right->is_constant()) { |
aoqi@1 | 3832 | #ifndef _LP64 |
aoqi@1 | 3833 | jint c = right->as_constant_ptr()->as_jint(); |
aoqi@1 | 3834 | #else |
aoqi@1 | 3835 | jlong c = right->as_constant_ptr()->as_jlong_bits(); |
aoqi@1 | 3836 | #endif |
aoqi@1 | 3837 | switch (code) { |
aoqi@6880 | 3838 | case lir_add: { |
aoqi@6880 | 3839 | __ ld_ptr(AT, laddr); |
aoqi@1 | 3840 | #ifndef _LP64 |
aoqi@6880 | 3841 | __ addi(AT, AT, c); |
aoqi@1 | 3842 | #else |
aoqi@6880 | 3843 | __ li(T8, c); |
aoqi@6880 | 3844 | __ add(AT, AT, T8); |
aoqi@1 | 3845 | #endif |
aoqi@6880 | 3846 | __ st_ptr(AT, laddr); |
aoqi@6880 | 3847 | break; |
aoqi@6880 | 3848 | } |
aoqi@6880 | 3849 | case lir_sub: { |
aoqi@6880 | 3850 | __ ld_ptr(AT, laddr); |
aoqi@1 | 3851 | #ifndef _LP64 |
aoqi@6880 | 3852 | __ addi(AT, AT, -c); |
aoqi@1 | 3853 | #else |
aoqi@6880 | 3854 | __ li(T8, -c); |
aoqi@6880 | 3855 | __ add(AT, AT, T8); |
aoqi@1 | 3856 | #endif |
aoqi@6880 | 3857 | __ st_ptr(AT, laddr); |
aoqi@6880 | 3858 | break; |
aoqi@6880 | 3859 | } |
aoqi@6880 | 3860 | default: ShouldNotReachHere(); |
aoqi@1 | 3861 | } |
aoqi@1 | 3862 | } else { |
aoqi@1 | 3863 | ShouldNotReachHere(); |
aoqi@1 | 3864 | } |
aoqi@1 | 3865 | } else { |
aoqi@1 | 3866 | ShouldNotReachHere(); |
aoqi@1 | 3867 | } |
aoqi@1 | 3868 | } |
aoqi@1 | 3869 | |
aoqi@1 | 3870 | void LIR_Assembler::intrinsic_op(LIR_Code code, LIR_Opr value, LIR_Opr unused, LIR_Opr dest, LIR_Op *op) { |
aoqi@1 | 3871 | //FIXME,lir_log, lir_log10,lir_abs,lir_sqrt,so many new lir instruction @jerome |
aoqi@1 | 3872 | if (value->is_double_fpu()) { |
aoqi@1 | 3873 | // assert(value->fpu_regnrLo() == 0 && dest->fpu_regnrLo() == 0, "both must be on TOS"); |
aoqi@1 | 3874 | switch(code) { |
aoqi@1 | 3875 | case lir_log : //__ flog() ; break; |
aoqi@6880 | 3876 | case lir_log10 : //__ flog10() ; |
aoqi@1 | 3877 | Unimplemented(); |
aoqi@6880 | 3878 | break; |
aoqi@1 | 3879 | case lir_abs : __ abs_d(dest->as_double_reg(), value->as_double_reg()) ; break; |
aoqi@1 | 3880 | case lir_sqrt : __ sqrt_d(dest->as_double_reg(), value->as_double_reg()); break; |
aoqi@1 | 3881 | case lir_sin : |
aoqi@1 | 3882 | // Should consider not saving ebx if not necessary |
aoqi@1 | 3883 | __ trigfunc('s', 0); |
aoqi@1 | 3884 | break; |
aoqi@1 | 3885 | case lir_cos : |
aoqi@1 | 3886 | // Should consider not saving ebx if not necessary |
aoqi@1 | 3887 | // assert(op->as_Op2()->fpu_stack_size() <= 6, "sin and cos need two free stack slots"); |
aoqi@1 | 3888 | __ trigfunc('c', 0); |
aoqi@1 | 3889 | break; |
aoqi@1 | 3890 | case lir_tan : |
aoqi@1 | 3891 | // Should consider not saving ebx if not necessary |
aoqi@1 | 3892 | __ trigfunc('t', 0); |
aoqi@1 | 3893 | break; |
aoqi@1 | 3894 | default : ShouldNotReachHere(); |
aoqi@1 | 3895 | } |
aoqi@1 | 3896 | } else { |
aoqi@1 | 3897 | Unimplemented(); |
aoqi@1 | 3898 | } |
aoqi@1 | 3899 | } |
aoqi@6880 | 3900 | |
aoqi@1 | 3901 | //FIXME, if right is on the stack! |
aoqi@1 | 3902 | void LIR_Assembler::logic_op(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dst) { |
aoqi@1 | 3903 | if (left->is_single_cpu()) { |
aoqi@1 | 3904 | Register dstreg = dst->as_register(); |
aoqi@1 | 3905 | Register reg = left->as_register(); |
aoqi@1 | 3906 | if (right->is_constant()) { |
aoqi@1 | 3907 | int val = right->as_constant_ptr()->as_jint(); |
aoqi@1 | 3908 | __ move(AT, val); |
aoqi@1 | 3909 | switch (code) { |
aoqi@8865 | 3910 | case lir_logic_and: |
aoqi@8865 | 3911 | __ andr (dstreg, reg, AT); |
aoqi@8865 | 3912 | break; |
aoqi@8865 | 3913 | case lir_logic_or: |
aoqi@8865 | 3914 | __ orr(dstreg, reg, AT); |
aoqi@8865 | 3915 | break; |
aoqi@8865 | 3916 | case lir_logic_xor: |
aoqi@8865 | 3917 | __ xorr(dstreg, reg, AT); |
aoqi@8865 | 3918 | break; |
aoqi@8865 | 3919 | default: ShouldNotReachHere(); |
aoqi@1 | 3920 | } |
aoqi@1 | 3921 | } else if (right->is_stack()) { |
aoqi@1 | 3922 | // added support for stack operands |
aoqi@1 | 3923 | Address raddr = frame_map()->address_for_slot(right->single_stack_ix()); |
aoqi@1 | 3924 | switch (code) { |
aoqi@8865 | 3925 | case lir_logic_and: |
aoqi@8865 | 3926 | //FIXME. lw or ld_ptr? |
aoqi@8865 | 3927 | __ lw(AT, raddr); |
aoqi@8865 | 3928 | __ andr(reg, reg,AT); |
aoqi@8865 | 3929 | break; |
aoqi@8865 | 3930 | case lir_logic_or: |
aoqi@8865 | 3931 | __ lw(AT, raddr); |
aoqi@8865 | 3932 | __ orr(reg, reg, AT); |
aoqi@8865 | 3933 | break; |
aoqi@8865 | 3934 | case lir_logic_xor: |
aoqi@8865 | 3935 | __ lw(AT, raddr); |
aoqi@8865 | 3936 | __ xorr(reg, reg, AT); |
aoqi@8865 | 3937 | break; |
aoqi@8865 | 3938 | default: ShouldNotReachHere(); |
aoqi@1 | 3939 | } |
aoqi@1 | 3940 | } else { |
aoqi@1 | 3941 | Register rright = right->as_register(); |
aoqi@1 | 3942 | switch (code) { |
aoqi@8865 | 3943 | case lir_logic_and: __ andr (dstreg, reg, rright); break; |
aoqi@8865 | 3944 | case lir_logic_or : __ orr (dstreg, reg, rright); break; |
aoqi@8865 | 3945 | case lir_logic_xor: __ xorr (dstreg, reg, rright); break; |
aoqi@8865 | 3946 | default: ShouldNotReachHere(); |
aoqi@1 | 3947 | } |
aoqi@1 | 3948 | } |
aoqi@1 | 3949 | } else { |
aoqi@1 | 3950 | Register l_lo = left->as_register_lo(); |
aoqi@1 | 3951 | Register dst_lo = dst->as_register_lo(); |
aoqi@1 | 3952 | #ifndef _LP64 |
aoqi@1 | 3953 | Register l_hi = left->as_register_hi(); |
aoqi@1 | 3954 | Register dst_hi = dst->as_register_hi(); |
aoqi@1 | 3955 | #endif |
aoqi@1 | 3956 | |
aoqi@1 | 3957 | if (right->is_constant()) { |
aoqi@1 | 3958 | #ifndef _LP64 |
aoqi@1 | 3959 | |
aoqi@1 | 3960 | int r_lo = right->as_constant_ptr()->as_jint_lo(); |
aoqi@1 | 3961 | int r_hi = right->as_constant_ptr()->as_jint_hi(); |
aoqi@1 | 3962 | |
aoqi@1 | 3963 | switch (code) { |
aoqi@8865 | 3964 | case lir_logic_and: |
aoqi@8865 | 3965 | __ move(AT, r_lo); |
aoqi@8865 | 3966 | __ andr(dst_lo, l_lo, AT); |
aoqi@8865 | 3967 | __ move(AT, r_hi); |
aoqi@8865 | 3968 | __ andr(dst_hi, l_hi, AT); |
aoqi@8865 | 3969 | break; |
aoqi@8865 | 3970 | |
aoqi@8865 | 3971 | case lir_logic_or: |
aoqi@8865 | 3972 | __ move(AT, r_lo); |
aoqi@8865 | 3973 | __ orr(dst_lo, l_lo, AT); |
aoqi@8865 | 3974 | __ move(AT, r_hi); |
aoqi@8865 | 3975 | __ orr(dst_hi, l_hi, AT); |
aoqi@8865 | 3976 | break; |
aoqi@8865 | 3977 | |
aoqi@8865 | 3978 | case lir_logic_xor: |
aoqi@8865 | 3979 | __ move(AT, r_lo); |
aoqi@8865 | 3980 | __ xorr(dst_lo, l_lo, AT); |
aoqi@8865 | 3981 | __ move(AT, r_hi); |
aoqi@8865 | 3982 | __ xorr(dst_hi, l_hi, AT); |
aoqi@8865 | 3983 | break; |
aoqi@8865 | 3984 | |
aoqi@8865 | 3985 | default: ShouldNotReachHere(); |
aoqi@1 | 3986 | } |
aoqi@1 | 3987 | #else |
aoqi@1 | 3988 | __ li(AT, right->as_constant_ptr()->as_jlong()); |
aoqi@1 | 3989 | |
aoqi@1 | 3990 | switch (code) { |
aoqi@8865 | 3991 | case lir_logic_and: |
aoqi@8865 | 3992 | __ andr(dst_lo, l_lo, AT); |
aoqi@8865 | 3993 | break; |
aoqi@8865 | 3994 | |
aoqi@8865 | 3995 | case lir_logic_or: |
aoqi@8865 | 3996 | __ orr(dst_lo, l_lo, AT); |
aoqi@8865 | 3997 | break; |
aoqi@8865 | 3998 | |
aoqi@8865 | 3999 | case lir_logic_xor: |
aoqi@8865 | 4000 | __ xorr(dst_lo, l_lo, AT); |
aoqi@8865 | 4001 | break; |
aoqi@8865 | 4002 | |
aoqi@8865 | 4003 | default: ShouldNotReachHere(); |
aoqi@1 | 4004 | } |
aoqi@1 | 4005 | #endif |
aoqi@1 | 4006 | |
aoqi@1 | 4007 | } else { |
aoqi@1 | 4008 | Register r_lo = right->as_register_lo(); |
aoqi@1 | 4009 | Register r_hi = right->as_register_hi(); |
aoqi@1 | 4010 | |
aoqi@1 | 4011 | switch (code) { |
aoqi@8865 | 4012 | case lir_logic_and: |
aoqi@8865 | 4013 | __ andr(dst_lo, l_lo, r_lo); |
aoqi@8865 | 4014 | NOT_LP64(__ andr(dst_hi, l_hi, r_hi);) |
aoqi@8865 | 4015 | break; |
aoqi@8865 | 4016 | case lir_logic_or: |
aoqi@8865 | 4017 | __ orr(dst_lo, l_lo, r_lo); |
aoqi@8865 | 4018 | NOT_LP64(__ orr(dst_hi, l_hi, r_hi);) |
aoqi@8865 | 4019 | break; |
aoqi@8865 | 4020 | case lir_logic_xor: |
aoqi@8865 | 4021 | __ xorr(dst_lo, l_lo, r_lo); |
aoqi@8865 | 4022 | NOT_LP64(__ xorr(dst_hi, l_hi, r_hi);) |
aoqi@8865 | 4023 | break; |
aoqi@8865 | 4024 | default: ShouldNotReachHere(); |
aoqi@1 | 4025 | } |
aoqi@1 | 4026 | } |
aoqi@1 | 4027 | } |
aoqi@1 | 4028 | } |
aoqi@1 | 4029 | |
aoqi@1 | 4030 | //done here. aoqi. 12-12 22:25 |
aoqi@1 | 4031 | // we assume that eax and edx can be overwritten |
aoqi@1 | 4032 | void LIR_Assembler::arithmetic_idiv(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr temp, LIR_Opr result, CodeEmitInfo* info) { |
aoqi@1 | 4033 | |
aoqi@1 | 4034 | assert(left->is_single_cpu(), "left must be register"); |
aoqi@1 | 4035 | assert(right->is_single_cpu() || right->is_constant(), "right must be register or constant"); |
aoqi@1 | 4036 | assert(result->is_single_cpu(), "result must be register"); |
aoqi@1 | 4037 | |
aoqi@1 | 4038 | Register lreg = left->as_register(); |
aoqi@1 | 4039 | Register dreg = result->as_register(); |
aoqi@1 | 4040 | |
aoqi@1 | 4041 | if (right->is_constant()) { |
aoqi@1 | 4042 | int divisor = right->as_constant_ptr()->as_jint(); |
aoqi@1 | 4043 | assert(divisor!=0, "must be nonzero"); |
aoqi@1 | 4044 | #ifndef _LP64 |
aoqi@1 | 4045 | __ move(AT, divisor); |
aoqi@1 | 4046 | __ div(lreg, AT); |
aoqi@1 | 4047 | #else |
aoqi@1 | 4048 | __ li(AT, divisor); |
aoqi@1 | 4049 | __ ddiv(lreg, AT); |
aoqi@1 | 4050 | #endif |
aoqi@1 | 4051 | int idivl_offset = code_offset(); |
aoqi@1 | 4052 | |
aoqi@1 | 4053 | /* 2012/4/21 Jin: In MIPS, div does not cause exception. |
aoqi@6880 | 4054 | We must trap an exception manually. */ |
aoqi@1 | 4055 | __ teq(R0, AT, 0x7); |
aoqi@1 | 4056 | __ nop(); |
aoqi@1 | 4057 | __ nop(); |
aoqi@1 | 4058 | add_debug_info_for_div0(idivl_offset, info); |
aoqi@1 | 4059 | } else { |
aoqi@1 | 4060 | Register rreg = right->as_register(); |
aoqi@1 | 4061 | #ifndef _LP64 |
aoqi@1 | 4062 | __ div(lreg, rreg); |
aoqi@1 | 4063 | #else |
aoqi@1 | 4064 | __ ddiv(lreg, rreg); |
aoqi@1 | 4065 | #endif |
aoqi@1 | 4066 | |
aoqi@1 | 4067 | int idivl_offset = code_offset(); |
aoqi@1 | 4068 | __ teq(R0, rreg, 0x7); |
aoqi@1 | 4069 | __ nop(); |
aoqi@1 | 4070 | __ nop(); |
aoqi@1 | 4071 | add_debug_info_for_div0(idivl_offset, info); |
aoqi@1 | 4072 | } |
aoqi@1 | 4073 | |
aoqi@1 | 4074 | // get the result |
aoqi@1 | 4075 | if (code == lir_irem) { |
aoqi@1 | 4076 | __ mfhi(dreg); |
aoqi@1 | 4077 | #ifdef _LP64 |
aoqi@1 | 4078 | if (result->type() == T_INT) |
aoqi@1 | 4079 | __ sll(dreg, dreg, 0); |
aoqi@1 | 4080 | #endif |
aoqi@1 | 4081 | } else if (code == lir_idiv) { |
aoqi@1 | 4082 | __ mflo(dreg); |
aoqi@1 | 4083 | } else { |
aoqi@1 | 4084 | ShouldNotReachHere(); |
aoqi@1 | 4085 | } |
aoqi@1 | 4086 | } |
aoqi@1 | 4087 | |
aoqi@1 | 4088 | void LIR_Assembler::arithmetic_frem(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr temp, LIR_Opr result, CodeEmitInfo* info) { |
aoqi@1 | 4089 | if (left->is_single_fpu()) { |
aoqi@1 | 4090 | assert(right->is_single_fpu(),"right must be float"); |
aoqi@1 | 4091 | assert(result->is_single_fpu(), "dest must be float"); |
aoqi@1 | 4092 | assert(temp->is_single_fpu(), "dest must be float"); |
aoqi@1 | 4093 | |
aoqi@1 | 4094 | FloatRegister lreg = left->as_float_reg(); |
aoqi@1 | 4095 | FloatRegister rreg = right->as_float_reg(); |
aoqi@1 | 4096 | FloatRegister res = result->as_float_reg(); |
aoqi@1 | 4097 | FloatRegister tmp = temp->as_float_reg(); |
aoqi@1 | 4098 | |
aoqi@1 | 4099 | switch (code) { |
aoqi@6880 | 4100 | case lir_frem: |
aoqi@6880 | 4101 | __ rem_s(res, lreg, rreg, tmp); |
aoqi@6880 | 4102 | break; |
aoqi@1 | 4103 | default : ShouldNotReachHere(); |
aoqi@1 | 4104 | } |
aoqi@1 | 4105 | } else if (left->is_double_fpu()) { |
aoqi@1 | 4106 | assert(right->is_double_fpu(),"right must be double"); |
aoqi@1 | 4107 | assert(result->is_double_fpu(), "dest must be double"); |
aoqi@1 | 4108 | assert(temp->is_double_fpu(), "dest must be double"); |
aoqi@1 | 4109 | |
aoqi@1 | 4110 | FloatRegister lreg = left->as_double_reg(); |
aoqi@1 | 4111 | FloatRegister rreg = right->as_double_reg(); |
aoqi@1 | 4112 | FloatRegister res = result->as_double_reg(); |
aoqi@1 | 4113 | FloatRegister tmp = temp->as_double_reg(); |
aoqi@1 | 4114 | |
aoqi@1 | 4115 | switch (code) { |
aoqi@6880 | 4116 | case lir_frem: |
aoqi@6880 | 4117 | __ rem_d(res, lreg, rreg, tmp); |
aoqi@6880 | 4118 | break; |
aoqi@1 | 4119 | default : ShouldNotReachHere(); |
aoqi@1 | 4120 | } |
aoqi@1 | 4121 | } |
aoqi@1 | 4122 | } |
aoqi@1 | 4123 | |
aoqi@1 | 4124 | void LIR_Assembler::comp_fl2i(LIR_Code code, LIR_Opr left, LIR_Opr right, LIR_Opr dst,LIR_Op2 * op) { |
aoqi@1 | 4125 | Register dstreg = dst->as_register(); |
aoqi@1 | 4126 | if (code == lir_cmp_fd2i) { |
aoqi@6880 | 4127 | if (left->is_single_fpu()) { |
aoqi@1 | 4128 | FloatRegister leftreg = left->as_float_reg(); |
aoqi@1 | 4129 | FloatRegister rightreg = right->as_float_reg(); |
aoqi@1 | 4130 | |
aoqi@1 | 4131 | Label done; |
aoqi@1 | 4132 | // equal? |
aoqi@1 | 4133 | __ c_eq_s(leftreg, rightreg); |
aoqi@1 | 4134 | __ bc1t(done); |
aoqi@1 | 4135 | __ delayed(); |
aoqi@1 | 4136 | __ move(dstreg, R0); |
aoqi@1 | 4137 | // less? |
aoqi@6880 | 4138 | __ c_olt_s(leftreg, rightreg); |
aoqi@1 | 4139 | __ bc1t(done); |
aoqi@1 | 4140 | __ delayed(); |
aoqi@1 | 4141 | __ move(dstreg, -1); |
aoqi@1 | 4142 | // great |
aoqi@1 | 4143 | __ move(dstreg, 1); |
aoqi@1 | 4144 | |
aoqi@6880 | 4145 | __ bind(done); |
aoqi@1 | 4146 | } else { |
aoqi@1 | 4147 | assert(left->is_double_fpu(), "Must double"); |
aoqi@1 | 4148 | FloatRegister leftreg = left->as_double_reg(); |
aoqi@1 | 4149 | FloatRegister rightreg = right->as_double_reg(); |
aoqi@1 | 4150 | |
aoqi@1 | 4151 | Label done; |
aoqi@1 | 4152 | // equal? |
aoqi@1 | 4153 | __ c_eq_d(leftreg, rightreg); |
aoqi@1 | 4154 | __ bc1t(done); |
aoqi@1 | 4155 | __ delayed(); |
aoqi@1 | 4156 | __ move(dstreg, R0); |
aoqi@1 | 4157 | // less? |
aoqi@1 | 4158 | __ c_olt_d(leftreg, rightreg); |
aoqi@1 | 4159 | __ bc1t(done); |
aoqi@1 | 4160 | __ delayed(); |
aoqi@1 | 4161 | __ move(dstreg, -1); |
aoqi@1 | 4162 | // great |
aoqi@1 | 4163 | __ move(dstreg, 1); |
aoqi@1 | 4164 | |
aoqi@6880 | 4165 | __ bind(done); |
aoqi@1 | 4166 | } |
aoqi@1 | 4167 | } else if (code == lir_ucmp_fd2i) { |
aoqi@6880 | 4168 | if (left->is_single_fpu()) { |
aoqi@1 | 4169 | FloatRegister leftreg = left->as_float_reg(); |
aoqi@1 | 4170 | FloatRegister rightreg = right->as_float_reg(); |
aoqi@1 | 4171 | |
aoqi@1 | 4172 | Label done; |
aoqi@1 | 4173 | // equal? |
aoqi@1 | 4174 | __ c_eq_s(leftreg, rightreg); |
aoqi@1 | 4175 | __ bc1t(done); |
aoqi@1 | 4176 | __ delayed(); |
aoqi@1 | 4177 | __ move(dstreg, R0); |
aoqi@1 | 4178 | // less? |
aoqi@6880 | 4179 | __ c_ult_s(leftreg, rightreg); |
aoqi@1 | 4180 | __ bc1t(done); |
aoqi@1 | 4181 | __ delayed(); |
aoqi@1 | 4182 | __ move(dstreg, -1); |
aoqi@1 | 4183 | // great |
aoqi@1 | 4184 | __ move(dstreg, 1); |
aoqi@1 | 4185 | |
aoqi@6880 | 4186 | __ bind(done); |
aoqi@1 | 4187 | } else { |
aoqi@1 | 4188 | assert(left->is_double_fpu(), "Must double"); |
aoqi@1 | 4189 | FloatRegister leftreg = left->as_double_reg(); |
aoqi@1 | 4190 | FloatRegister rightreg = right->as_double_reg(); |
aoqi@1 | 4191 | |
aoqi@1 | 4192 | Label done; |
aoqi@1 | 4193 | // equal? |
aoqi@1 | 4194 | __ c_eq_d(leftreg, rightreg); |
aoqi@1 | 4195 | __ bc1t(done); |
aoqi@1 | 4196 | __ delayed(); |
aoqi@1 | 4197 | __ move(dstreg, R0); |
aoqi@1 | 4198 | // less? |
aoqi@1 | 4199 | __ c_ult_d(leftreg, rightreg); |
aoqi@1 | 4200 | __ bc1t(done); |
aoqi@1 | 4201 | __ delayed(); |
aoqi@1 | 4202 | __ move(dstreg, -1); |
aoqi@1 | 4203 | // great |
aoqi@1 | 4204 | __ move(dstreg, 1); |
aoqi@1 | 4205 | |
aoqi@6880 | 4206 | __ bind(done); |
aoqi@1 | 4207 | } |
aoqi@1 | 4208 | } else { |
aoqi@1 | 4209 | assert(code == lir_cmp_l2i, "check"); |
aoqi@1 | 4210 | Register l_lo, l_hi, r_lo, r_hi, d_lo, d_hi; |
aoqi@1 | 4211 | l_lo = left->as_register_lo(); |
aoqi@1 | 4212 | l_hi = left->as_register_hi(); |
aoqi@1 | 4213 | r_lo = right->as_register_lo(); |
aoqi@1 | 4214 | r_hi = right->as_register_hi(); |
aoqi@1 | 4215 | |
aoqi@1 | 4216 | Label done; |
aoqi@1 | 4217 | #ifndef _LP64 |
aoqi@1 | 4218 | // less? |
aoqi@6880 | 4219 | __ slt(AT, l_hi, r_hi); |
aoqi@1 | 4220 | __ bne(AT, R0, done); |
aoqi@1 | 4221 | __ delayed(); |
aoqi@1 | 4222 | __ move(dstreg, -1); |
aoqi@1 | 4223 | // great? |
aoqi@1 | 4224 | __ slt(AT, r_hi, l_hi); |
aoqi@1 | 4225 | __ bne(AT, R0, done); |
aoqi@1 | 4226 | __ delayed(); |
aoqi@1 | 4227 | __ move(dstreg, 1); |
aoqi@1 | 4228 | #endif |
aoqi@1 | 4229 | |
aoqi@1 | 4230 | // now compare low 32 bits |
aoqi@1 | 4231 | // below? |
aoqi@1 | 4232 | #ifndef _LP64 |
aoqi@1 | 4233 | __ sltu(AT, l_lo, r_lo); |
aoqi@1 | 4234 | #else |
aoqi@1 | 4235 | __ slt(AT, l_lo, r_lo); |
aoqi@1 | 4236 | #endif |
aoqi@1 | 4237 | __ bne(AT, R0, done); |
aoqi@1 | 4238 | __ delayed(); |
aoqi@1 | 4239 | __ move(dstreg, -1); |
aoqi@1 | 4240 | // above? |
aoqi@1 | 4241 | #ifndef _LP64 |
aoqi@1 | 4242 | __ sltu(AT, r_lo, l_lo); |
aoqi@1 | 4243 | #else |
aoqi@1 | 4244 | __ slt(AT, r_lo, l_lo); |
aoqi@1 | 4245 | #endif |
aoqi@1 | 4246 | __ bne(AT, R0, done); |
aoqi@1 | 4247 | __ delayed(); |
aoqi@1 | 4248 | __ move(dstreg, 1); |
aoqi@1 | 4249 | // equal |
aoqi@1 | 4250 | __ move(dstreg, R0); |
aoqi@1 | 4251 | |
aoqi@1 | 4252 | __ bind(done); |
aoqi@1 | 4253 | } |
aoqi@1 | 4254 | } |
aoqi@1 | 4255 | |
aoqi@1 | 4256 | |
aoqi@1 | 4257 | void LIR_Assembler::align_call(LIR_Code code) { |
aoqi@1 | 4258 | } |
aoqi@1 | 4259 | |
aoqi@1 | 4260 | |
aoqi@1 | 4261 | void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) { |
aoqi@1 | 4262 | //assert(!os::is_MP() || (__ offset() + NativeCall::displacement_offset) % BytesPerWord == 0, "must be aligned"); |
aoqi@1 | 4263 | __ call(op->addr(), rtype); |
aoqi@1 | 4264 | __ delayed()->nop(); |
aoqi@1 | 4265 | add_call_info(code_offset(), op->info()); |
aoqi@1 | 4266 | } |
aoqi@1 | 4267 | |
aoqi@1 | 4268 | |
aoqi@1 | 4269 | void LIR_Assembler::ic_call(LIR_OpJavaCall* op) { |
aoqi@8865 | 4270 | __ ic_call(op->addr()); |
aoqi@8865 | 4271 | add_call_info(code_offset(), op->info()); |
aoqi@1 | 4272 | } |
aoqi@1 | 4273 | |
aoqi@1 | 4274 | |
aoqi@1 | 4275 | /* Currently, vtable-dispatch is only enabled for sparc platforms */ |
aoqi@1 | 4276 | void LIR_Assembler::vtable_call(LIR_OpJavaCall* op) { |
aoqi@1 | 4277 | ShouldNotReachHere(); |
aoqi@1 | 4278 | } |
aoqi@1 | 4279 | |
aoqi@1 | 4280 | |
aoqi@1 | 4281 | |
aoqi@1 | 4282 | void LIR_Assembler::emit_static_call_stub() { |
aoqi@1 | 4283 | address call_pc = __ pc(); |
aoqi@1 | 4284 | address stub = __ start_a_stub(call_stub_size); |
aoqi@1 | 4285 | if (stub == NULL) { |
aoqi@1 | 4286 | bailout("static call stub overflow"); |
aoqi@1 | 4287 | return; |
aoqi@1 | 4288 | } |
aoqi@1 | 4289 | int start = __ offset(); |
aoqi@1 | 4290 | __ relocate(static_stub_Relocation::spec(call_pc)); |
aoqi@8865 | 4291 | |
aoqi@8865 | 4292 | Metadata *o = NULL; |
aoqi@8865 | 4293 | int index = __ oop_recorder()->allocate_metadata_index(o); |
aoqi@8865 | 4294 | RelocationHolder rspec = metadata_Relocation::spec(index); |
aoqi@1 | 4295 | __ relocate(rspec); |
aoqi@1 | 4296 | //see set_to_interpreted |
aoqi@8865 | 4297 | __ patchable_set48(Rmethod, (long)o); |
aoqi@8865 | 4298 | |
aoqi@8865 | 4299 | __ patchable_set48(AT, (long)-1); |
aoqi@1 | 4300 | __ jr(AT); |
aoqi@1 | 4301 | __ delayed()->nop(); |
aoqi@1 | 4302 | assert(__ offset() - start <= call_stub_size, "stub too big"); |
aoqi@1 | 4303 | __ end_a_stub(); |
aoqi@1 | 4304 | } |
aoqi@1 | 4305 | |
aoqi@1 | 4306 | |
aoqi@1 | 4307 | void LIR_Assembler::throw_op(LIR_Opr exceptionPC, LIR_Opr exceptionOop, CodeEmitInfo* info) { |
aoqi@6880 | 4308 | assert(exceptionOop->as_register()== V0, "must match"); |
aoqi@6880 | 4309 | assert(exceptionPC->as_register()== V1, "must match"); |
aoqi@6880 | 4310 | |
aoqi@6880 | 4311 | // exception object is not added to oop map by LinearScan |
aoqi@6880 | 4312 | // (LinearScan assumes that no oops are in fixed registers) |
aoqi@6880 | 4313 | |
aoqi@6880 | 4314 | info->add_register_oop(exceptionOop); |
aoqi@8865 | 4315 | long pc_for_athrow = (long)__ pc(); |
aoqi@8865 | 4316 | int pc_for_athrow_offset = __ offset(); |
aoqi@8865 | 4317 | Register epc = exceptionPC->as_register(); |
aoqi@8865 | 4318 | __ relocate(relocInfo::internal_pc_type); |
aoqi@8865 | 4319 | __ li48(epc, pc_for_athrow); |
aoqi@8865 | 4320 | add_call_info(pc_for_athrow_offset, info); // for exception handler |
aoqi@8865 | 4321 | __ verify_not_null_oop(V0); |
aoqi@8865 | 4322 | // search an exception handler (eax: exception oop, edx: throwing pc) |
aoqi@8865 | 4323 | if (compilation()->has_fpu_code()) { |
aoqi@8865 | 4324 | __ call(Runtime1::entry_for(Runtime1::handle_exception_id), |
aoqi@8865 | 4325 | relocInfo::runtime_call_type); |
aoqi@8865 | 4326 | } else { |
aoqi@8865 | 4327 | __ call(Runtime1::entry_for(Runtime1::handle_exception_nofpu_id), |
aoqi@8865 | 4328 | relocInfo::runtime_call_type); |
aoqi@8865 | 4329 | } |
aoqi@6880 | 4330 | __ delayed()->nop(); |
aoqi@1 | 4331 | } |
aoqi@1 | 4332 | |
aoqi@8865 | 4333 | void LIR_Assembler::unwind_op(LIR_Opr exceptionOop) { |
aoqi@8865 | 4334 | assert(exceptionOop->as_register()== FSR, "must match"); |
aoqi@8865 | 4335 | __ b(_unwind_handler_entry); |
aoqi@8865 | 4336 | __ delayed()->nop(); |
aoqi@8865 | 4337 | } |
aoqi@1 | 4338 | |
aoqi@1 | 4339 | void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, LIR_Opr count, LIR_Opr dest, LIR_Opr tmp) { |
aoqi@1 | 4340 | // optimized version for linear scan: |
aoqi@1 | 4341 | // * tmp must be unused |
aoqi@1 | 4342 | assert(tmp->is_illegal(), "wasting a register if tmp is allocated"); |
aoqi@1 | 4343 | |
aoqi@1 | 4344 | #ifdef _LP64 |
aoqi@1 | 4345 | Register count_reg = count->as_register(); |
aoqi@1 | 4346 | Register value_reg; |
aoqi@1 | 4347 | Register dest_reg; |
aoqi@1 | 4348 | if (left->is_single_cpu()) { |
aoqi@1 | 4349 | value_reg = left->as_register(); |
aoqi@1 | 4350 | dest_reg = dest->as_register(); |
aoqi@1 | 4351 | |
aoqi@1 | 4352 | } else if (left->is_double_cpu()) { |
aoqi@1 | 4353 | value_reg = left->as_register_lo(); |
aoqi@6880 | 4354 | dest_reg = dest->as_register_lo(); |
aoqi@1 | 4355 | } else { |
aoqi@1 | 4356 | ShouldNotReachHere(); |
aoqi@1 | 4357 | } |
aoqi@1 | 4358 | assert_different_registers(count_reg, value_reg); |
aoqi@1 | 4359 | switch (code) { |
aoqi@6880 | 4360 | case lir_shl: |
aoqi@8865 | 4361 | if (dest->type() == T_INT) |
aoqi@8865 | 4362 | __ sllv(dest_reg, value_reg, count_reg); |
aoqi@8865 | 4363 | else |
aoqi@8865 | 4364 | __ dsllv(dest_reg, value_reg, count_reg); |
aoqi@8865 | 4365 | break; |
aoqi@1 | 4366 | case lir_shr: __ dsrav(dest_reg, value_reg, count_reg); break; |
aoqi@6880 | 4367 | case lir_ushr: |
aoqi@1 | 4368 | #if 1 |
aoqi@1 | 4369 | /* |
aoqi@1 | 4370 | Jin: in java, ushift_right requires 32-bit UNSIGNED operation! |
aoqi@1 | 4371 | However, dsrl will shift in company with the highest 32 bits. |
aoqi@6880 | 4372 | Thus, if the source register contains a negative value, |
aoqi@1 | 4373 | the resulti is incorrect. |
aoqi@1 | 4374 | * DoubleCvt.java |
aoqi@1 | 4375 | * |
aoqi@6880 | 4376 | * static int inp (int shift) |
aoqi@1 | 4377 | * { |
aoqi@1 | 4378 | * return -1 >>> (32 - shift); |
aoqi@1 | 4379 | * } |
aoqi@1 | 4380 | * |
aoqi@1 | 4381 | * 26 ushift_right [t0|I] [a4|I] [a6|I] |
aoqi@1 | 4382 | * 0x00000055616d2a98: dsrl a6, t0, a4 <-- error |
aoqi@1 | 4383 | */ |
aoqi@1 | 4384 | |
aoqi@1 | 4385 | // java.math.MutableBigInteger::primitiveRightShift |
aoqi@1 | 4386 | // |
aoqi@1 | 4387 | // 108 ushift_right [a6|I] [a4|I] [a4|I] |
aoqi@6880 | 4388 | // 0x00000055646d2f70: dsll32 a4, a6, 0 \ |
aoqi@8865 | 4389 | // 0x00000055646d2f74: dsrl32 a4, a4, 0 |- error! |
aoqi@8865 | 4390 | // 0x00000055646d2f78: dsrl a4, a4, a4 / |
aoqi@8865 | 4391 | if (left->type() == T_INT && dest->type() == T_INT) { |
aoqi@8865 | 4392 | __ dsll32(AT, value_reg, 0); // Omit the high 32 bits |
aoqi@8865 | 4393 | __ dsrl32(AT, AT, 0); |
aoqi@8865 | 4394 | __ dsrlv(dest_reg, AT, count_reg); // Unsigned right shift |
aoqi@8865 | 4395 | break; |
aoqi@8865 | 4396 | } |
aoqi@1 | 4397 | #endif |
aoqi@1 | 4398 | __ dsrlv(dest_reg, value_reg, count_reg); break; |
aoqi@1 | 4399 | default: ShouldNotReachHere(); |
aoqi@1 | 4400 | } |
aoqi@1 | 4401 | #else |
aoqi@1 | 4402 | if (left->is_single_cpu()) { |
aoqi@1 | 4403 | Register value_reg = left->as_register(); |
aoqi@1 | 4404 | Register count_reg = count->as_register(); |
aoqi@1 | 4405 | Register dest_reg = dest->as_register(); |
aoqi@1 | 4406 | assert_different_registers(count_reg, value_reg); |
aoqi@1 | 4407 | |
aoqi@1 | 4408 | switch (code) { |
aoqi@1 | 4409 | case lir_shl: __ sllv(dest_reg, value_reg, count_reg); break; |
aoqi@1 | 4410 | case lir_shr: __ srav(dest_reg, value_reg, count_reg); break; |
aoqi@1 | 4411 | case lir_ushr: __ srlv(dest_reg, value_reg, count_reg); break; |
aoqi@1 | 4412 | default: ShouldNotReachHere(); |
aoqi@1 | 4413 | } |
aoqi@1 | 4414 | |
aoqi@1 | 4415 | } else if (left->is_double_cpu()) { |
aoqi@1 | 4416 | Register creg = count->as_register(); |
aoqi@1 | 4417 | Register lo = left->as_register_lo(); |
aoqi@1 | 4418 | Register hi = left->as_register_hi(); |
aoqi@6880 | 4419 | Register dlo = dest->as_register_lo(); |
aoqi@6880 | 4420 | Register dhi = dest->as_register_hi(); |
aoqi@1 | 4421 | |
aoqi@1 | 4422 | __ andi(creg, creg, 0x3f); |
aoqi@1 | 4423 | switch (code) { |
aoqi@1 | 4424 | case lir_shl: |
aoqi@6880 | 4425 | { |
aoqi@6880 | 4426 | Label normal, done, notzero; |
aoqi@6880 | 4427 | |
aoqi@6880 | 4428 | //count=0 |
aoqi@6880 | 4429 | __ bne(creg, R0, notzero); |
aoqi@6880 | 4430 | __ delayed()->nop(); |
aoqi@6880 | 4431 | __ move(dlo, lo); |
aoqi@6880 | 4432 | __ b(done); |
aoqi@6880 | 4433 | __ delayed(); |
aoqi@6880 | 4434 | __ move(dhi, hi); |
aoqi@6880 | 4435 | |
aoqi@6880 | 4436 | //count>=32 |
aoqi@6880 | 4437 | __ bind(notzero); |
aoqi@6880 | 4438 | __ sltiu(AT, creg, BitsPerWord); |
aoqi@6880 | 4439 | __ bne(AT, R0, normal); |
aoqi@6880 | 4440 | __ delayed(); |
aoqi@6880 | 4441 | __ addiu(AT, creg, (-1) * BitsPerWord); |
aoqi@6880 | 4442 | __ sllv(dhi, lo, AT); |
aoqi@6880 | 4443 | __ b(done); |
aoqi@6880 | 4444 | __ delayed(); |
aoqi@6880 | 4445 | __ move(dlo, R0); |
aoqi@6880 | 4446 | |
aoqi@6880 | 4447 | //count<32 |
aoqi@6880 | 4448 | __ bind(normal); |
aoqi@6880 | 4449 | __ sllv(dhi, hi, creg); |
aoqi@6880 | 4450 | __ move(AT, BitsPerWord); |
aoqi@6880 | 4451 | __ sub(AT, AT, creg); |
aoqi@6880 | 4452 | __ srlv(AT, lo, AT); |
aoqi@6880 | 4453 | __ orr(dhi, dhi, AT); |
aoqi@6880 | 4454 | __ sllv(dlo, lo, creg); |
aoqi@6880 | 4455 | __ bind(done); |
aoqi@6880 | 4456 | } |
aoqi@6880 | 4457 | break; |
aoqi@1 | 4458 | case lir_shr: |
aoqi@6880 | 4459 | { |
aoqi@6880 | 4460 | Label normal, done, notzero; |
aoqi@6880 | 4461 | |
aoqi@6880 | 4462 | //count=0 |
aoqi@6880 | 4463 | __ bne(creg, R0, notzero); |
aoqi@6880 | 4464 | __ delayed()->nop(); |
aoqi@6880 | 4465 | __ move(dhi, hi); |
aoqi@6880 | 4466 | __ b(done); |
aoqi@6880 | 4467 | __ delayed(); |
aoqi@6880 | 4468 | __ move(dlo, lo); |
aoqi@6880 | 4469 | |
aoqi@6880 | 4470 | //count>=32 |
aoqi@6880 | 4471 | __ bind(notzero); |
aoqi@6880 | 4472 | __ sltiu(AT, creg, BitsPerWord); |
aoqi@6880 | 4473 | __ bne(AT, R0, normal); |
aoqi@6880 | 4474 | __ delayed(); |
aoqi@6880 | 4475 | __ addiu(AT, creg, (-1) * BitsPerWord); |
aoqi@6880 | 4476 | __ srav(dlo, hi, AT); |
aoqi@6880 | 4477 | __ b(done); |
aoqi@6880 | 4478 | __ delayed(); |
aoqi@6880 | 4479 | __ sra(dhi, hi, BitsPerWord - 1); |
aoqi@6880 | 4480 | |
aoqi@6880 | 4481 | //count<32 |
aoqi@6880 | 4482 | __ bind(normal); |
aoqi@6880 | 4483 | __ srlv(dlo, lo, creg); |
aoqi@6880 | 4484 | __ move(AT, BitsPerWord); |
aoqi@6880 | 4485 | __ sub(AT, AT, creg); |
aoqi@6880 | 4486 | __ sllv(AT, hi, AT); |
aoqi@6880 | 4487 | __ orr(dlo, dlo, AT); |
aoqi@6880 | 4488 | __ srav(dhi, hi, creg); |
aoqi@6880 | 4489 | __ bind(done); |
aoqi@6880 | 4490 | } |
aoqi@6880 | 4491 | break; |
aoqi@1 | 4492 | case lir_ushr: |
aoqi@6880 | 4493 | { |
aoqi@6880 | 4494 | Label normal, done, notzero; |
aoqi@6880 | 4495 | |
aoqi@6880 | 4496 | //count=zero |
aoqi@6880 | 4497 | __ bne(creg, R0, notzero); |
aoqi@6880 | 4498 | __ delayed()->nop(); |
aoqi@6880 | 4499 | __ move(dhi, hi); |
aoqi@6880 | 4500 | __ b(done); |
aoqi@6880 | 4501 | __ delayed(); |
aoqi@6880 | 4502 | __ move(dlo, lo); |
aoqi@6880 | 4503 | |
aoqi@6880 | 4504 | //count>=32 |
aoqi@6880 | 4505 | __ bind(notzero); |
aoqi@6880 | 4506 | __ sltiu(AT, creg, BitsPerWord); |
aoqi@6880 | 4507 | __ bne(AT, R0, normal); |
aoqi@6880 | 4508 | __ delayed(); |
aoqi@6880 | 4509 | __ addi(AT, creg, (-1) * BitsPerWord); |
aoqi@6880 | 4510 | __ srlv(dlo, hi, AT); |
aoqi@6880 | 4511 | __ b(done); |
aoqi@6880 | 4512 | __ delayed(); |
aoqi@6880 | 4513 | __ move(dhi, R0); |
aoqi@6880 | 4514 | |
aoqi@6880 | 4515 | //count<32 |
aoqi@6880 | 4516 | __ bind(normal); |
aoqi@6880 | 4517 | __ srlv(dlo, lo, creg); |
aoqi@6880 | 4518 | __ move(AT, BitsPerWord); |
aoqi@6880 | 4519 | __ sub(AT, AT, creg); |
aoqi@6880 | 4520 | __ sllv(AT, hi, AT); |
aoqi@6880 | 4521 | __ orr(dlo, dlo, AT); |
aoqi@6880 | 4522 | __ srlv(dhi, hi, creg); |
aoqi@6880 | 4523 | __ bind(done); |
aoqi@6880 | 4524 | } |
aoqi@6880 | 4525 | break; |
aoqi@6880 | 4526 | default: ShouldNotReachHere(); |
aoqi@1 | 4527 | } |
aoqi@1 | 4528 | } else { |
aoqi@1 | 4529 | ShouldNotReachHere(); |
aoqi@1 | 4530 | } |
aoqi@1 | 4531 | #endif |
aoqi@1 | 4532 | |
aoqi@1 | 4533 | } |
aoqi@1 | 4534 | |
aoqi@1 | 4535 | void LIR_Assembler::shift_op(LIR_Code code, LIR_Opr left, jint count, LIR_Opr dest) { |
aoqi@1 | 4536 | if (dest->is_single_cpu()) { |
aoqi@6880 | 4537 | /* In WebClient, |
aoqi@1 | 4538 | * virtual jboolean java.util.concurrent.atomic.AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl.compareAndSet |
aoqi@1 | 4539 | * |
aoqi@1 | 4540 | * 130 ushift_right [a4a4|J] [int:9|I] [a4|L] |
aoqi@1 | 4541 | */ |
aoqi@1 | 4542 | Register value_reg = left->is_single_cpu() ? left->as_register() : left->as_register_lo(); |
aoqi@1 | 4543 | Register dest_reg = dest->as_register(); |
aoqi@1 | 4544 | count = count & 0x1F; // Java spec |
aoqi@1 | 4545 | |
aoqi@1 | 4546 | switch (code) { |
aoqi@1 | 4547 | #ifdef _LP64 |
aoqi@6880 | 4548 | case lir_shl: |
aoqi@1 | 4549 | if (dest->type() == T_INT) |
aoqi@1 | 4550 | __ sll(dest_reg, value_reg, count); |
aoqi@1 | 4551 | else |
aoqi@1 | 4552 | __ dsll(dest_reg, value_reg, count); |
aoqi@1 | 4553 | break; |
aoqi@1 | 4554 | case lir_shr: __ dsra(dest_reg, value_reg, count); break; |
aoqi@6880 | 4555 | case lir_ushr: |
aoqi@1 | 4556 | #if 1 |
aoqi@8865 | 4557 | if (left->type() == T_INT && dest->type() == T_INT) { |
aoqi@1 | 4558 | /* Jin: in java, ushift_right requires 32-bit UNSIGNED operation! |
aoqi@1 | 4559 | However, dsrl will shift in company with the highest 32 bits. |
aoqi@6880 | 4560 | Thus, if the source register contains a negative value, |
aoqi@1 | 4561 | the resulti is incorrect. |
aoqi@6880 | 4562 | |
aoqi@1 | 4563 | Example: in java.util.HashMap.get() |
aoqi@1 | 4564 | |
aoqi@1 | 4565 | 68 ushift_right [t0|I] [int:20|I] [a4|I] |
aoqi@1 | 4566 | dsrl a4, t0, 20 |
aoqi@6880 | 4567 | |
aoqi@1 | 4568 | t0: 0xFFFFFFFF87654321 (64bits for 0x87654321) |
aoqi@1 | 4569 | |
aoqi@1 | 4570 | ushift_right t0, 16 -> a4 |
aoqi@6880 | 4571 | |
aoqi@1 | 4572 | a4: 00000000 00008765 (right) |
aoqi@1 | 4573 | a4: FFFFFFFF FFFF8765 (wrong) |
aoqi@1 | 4574 | */ |
aoqi@6880 | 4575 | __ dsll32(dest_reg, value_reg, 0); // Omit the high 32 bits |
aoqi@1 | 4576 | __ dsrl32(dest_reg, dest_reg, count); // Unsigned right shift |
aoqi@1 | 4577 | break; |
aoqi@1 | 4578 | } |
aoqi@1 | 4579 | #endif |
aoqi@1 | 4580 | |
aoqi@1 | 4581 | __ dsrl(dest_reg, value_reg, count); |
aoqi@1 | 4582 | break; |
aoqi@1 | 4583 | #else |
aoqi@1 | 4584 | case lir_shl: __ sll(dest_reg, value_reg, count); break; |
aoqi@1 | 4585 | case lir_shr: __ sra(dest_reg, value_reg, count); break; |
aoqi@1 | 4586 | case lir_ushr: __ srl(dest_reg, value_reg, count); break; |
aoqi@1 | 4587 | #endif |
aoqi@1 | 4588 | default: ShouldNotReachHere(); |
aoqi@1 | 4589 | } |
aoqi@1 | 4590 | |
aoqi@1 | 4591 | } else if (dest->is_double_cpu()) { |
aoqi@1 | 4592 | Register valuelo = left->is_single_cpu() ? left->as_register() : left->as_register_lo(); |
aoqi@1 | 4593 | Register destlo = dest->as_register_lo(); |
aoqi@1 | 4594 | count = count & 0x3f; |
aoqi@1 | 4595 | #ifdef _LP64 |
aoqi@1 | 4596 | switch (code) { |
aoqi@1 | 4597 | case lir_shl: __ dsll(destlo, valuelo, count); break; |
aoqi@1 | 4598 | case lir_shr: __ dsra(destlo, valuelo, count); break; |
aoqi@1 | 4599 | case lir_ushr: __ dsrl(destlo, valuelo, count); break; |
aoqi@1 | 4600 | default: ShouldNotReachHere(); |
aoqi@1 | 4601 | } |
aoqi@1 | 4602 | #else |
aoqi@1 | 4603 | Register desthi = dest->as_register_hi(); |
aoqi@1 | 4604 | Register valuehi = left->as_register_hi(); |
aoqi@1 | 4605 | assert_different_registers(destlo, valuehi, desthi); |
aoqi@1 | 4606 | switch (code) { |
aoqi@1 | 4607 | case lir_shl: |
aoqi@6880 | 4608 | if (count==0) { |
aoqi@6880 | 4609 | __ move(destlo, valuelo); |
aoqi@6880 | 4610 | __ move(desthi, valuehi); |
aoqi@6880 | 4611 | } else if (count>=32) { |
aoqi@6880 | 4612 | __ sll(desthi, valuelo, count-32); |
aoqi@6880 | 4613 | __ move(destlo, R0); |
aoqi@6880 | 4614 | } else { |
aoqi@6880 | 4615 | __ srl(AT, valuelo, 32 - count); |
aoqi@6880 | 4616 | __ sll(destlo, valuelo, count); |
aoqi@6880 | 4617 | __ sll(desthi, valuehi, count); |
aoqi@6880 | 4618 | __ orr(desthi, desthi, AT); |
aoqi@6880 | 4619 | } |
aoqi@6880 | 4620 | break; |
aoqi@1 | 4621 | |
aoqi@1 | 4622 | case lir_shr: |
aoqi@6880 | 4623 | if (count==0) { |
aoqi@6880 | 4624 | __ move(destlo, valuelo); |
aoqi@6880 | 4625 | __ move(desthi, valuehi); |
aoqi@6880 | 4626 | } else if (count>=32) { |
aoqi@6880 | 4627 | __ sra(destlo, valuehi, count-32); |
aoqi@6880 | 4628 | __ sra(desthi, valuehi, 31); |
aoqi@6880 | 4629 | } else { |
aoqi@6880 | 4630 | __ sll(AT, valuehi, 32 - count); |
aoqi@6880 | 4631 | __ sra(desthi, valuehi, count); |
aoqi@6880 | 4632 | __ srl(destlo, valuelo, count); |
aoqi@6880 | 4633 | __ orr(destlo, destlo, AT); |
aoqi@6880 | 4634 | } |
aoqi@6880 | 4635 | break; |
aoqi@1 | 4636 | |
aoqi@1 | 4637 | case lir_ushr: |
aoqi@6880 | 4638 | if (count==0) { |
aoqi@6880 | 4639 | __ move(destlo, valuelo); |
aoqi@6880 | 4640 | __ move(desthi, valuehi); |
aoqi@6880 | 4641 | } else if (count>=32) { |
aoqi@6880 | 4642 | __ sra(destlo, valuehi, count-32); |
aoqi@6880 | 4643 | __ move(desthi, R0); |
aoqi@6880 | 4644 | } else { |
aoqi@6880 | 4645 | __ sll(AT, valuehi, 32 - count); |
aoqi@6880 | 4646 | __ srl(desthi, valuehi, count); |
aoqi@6880 | 4647 | __ srl(destlo, valuelo, count); |
aoqi@6880 | 4648 | __ orr(destlo, destlo, AT); |
aoqi@6880 | 4649 | } |
aoqi@6880 | 4650 | break; |
aoqi@1 | 4651 | |
aoqi@1 | 4652 | default: ShouldNotReachHere(); |
aoqi@6880 | 4653 | } |
aoqi@1 | 4654 | #endif |
aoqi@1 | 4655 | } else { |
aoqi@1 | 4656 | ShouldNotReachHere(); |
aoqi@1 | 4657 | } |
aoqi@1 | 4658 | } |
aoqi@1 | 4659 | |
aoqi@1 | 4660 | void LIR_Assembler::store_parameter(Register r, int offset_from_esp_in_words) { |
aoqi@1 | 4661 | assert(offset_from_esp_in_words >= 0, "invalid offset from esp"); |
aoqi@1 | 4662 | int offset_from_sp_in_bytes = offset_from_esp_in_words * BytesPerWord; |
aoqi@1 | 4663 | assert(offset_from_esp_in_words < frame_map()->reserved_argument_area_size(), "invalid offset"); |
aoqi@1 | 4664 | __ st_ptr(r, SP, offset_from_sp_in_bytes); |
aoqi@1 | 4665 | } |
aoqi@1 | 4666 | |
aoqi@1 | 4667 | |
aoqi@1 | 4668 | void LIR_Assembler::store_parameter(jint c, int offset_from_esp_in_words) { |
aoqi@1 | 4669 | assert(offset_from_esp_in_words >= 0, "invalid offset from esp"); |
aoqi@1 | 4670 | int offset_from_sp_in_bytes = offset_from_esp_in_words * BytesPerWord; |
aoqi@1 | 4671 | assert(offset_from_esp_in_words < frame_map()->reserved_argument_area_size(), "invalid offset"); |
aoqi@1 | 4672 | __ move(AT, c); |
aoqi@1 | 4673 | __ st_ptr(AT, SP, offset_from_sp_in_bytes); |
aoqi@1 | 4674 | } |
aoqi@1 | 4675 | |
aoqi@1 | 4676 | void LIR_Assembler::store_parameter(jobject o, int offset_from_esp_in_words) { |
aoqi@1 | 4677 | assert(offset_from_esp_in_words >= 0, "invalid offset from esp"); |
aoqi@1 | 4678 | int offset_from_sp_in_bytes = offset_from_esp_in_words * BytesPerWord; |
aoqi@1 | 4679 | assert(offset_from_sp_in_bytes < frame_map()->reserved_argument_area_size(), "invalid offset"); |
aoqi@1 | 4680 | int oop_index = __ oop_recorder()->find_index(o); |
aoqi@1 | 4681 | RelocationHolder rspec = oop_Relocation::spec(oop_index); |
aoqi@1 | 4682 | __ relocate(rspec); |
aoqi@1 | 4683 | #ifndef _LP64 |
aoqi@1 | 4684 | //by_css |
aoqi@1 | 4685 | __ lui(AT, Assembler::split_high((int)o)); |
aoqi@1 | 4686 | __ addiu(AT, AT, Assembler::split_low((int)o)); |
aoqi@1 | 4687 | #else |
aoqi@1 | 4688 | __ li48(AT, (long)o); |
aoqi@1 | 4689 | #endif |
aoqi@1 | 4690 | |
aoqi@1 | 4691 | __ st_ptr(AT, SP, offset_from_sp_in_bytes); |
aoqi@1 | 4692 | |
aoqi@1 | 4693 | } |
aoqi@1 | 4694 | |
aoqi@1 | 4695 | |
aoqi@6880 | 4696 | // This code replaces a call to arraycopy; no exception may |
aoqi@1 | 4697 | // be thrown in this code, they must be thrown in the System.arraycopy |
aoqi@1 | 4698 | // activation frame; we could save some checks if this would not be the case |
aoqi@1 | 4699 | void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { |
aoqi@1 | 4700 | |
aoqi@1 | 4701 | |
aoqi@1 | 4702 | ciArrayKlass* default_type = op->expected_type(); |
aoqi@1 | 4703 | Register src = op->src()->as_register(); |
aoqi@1 | 4704 | Register dst = op->dst()->as_register(); |
aoqi@1 | 4705 | Register src_pos = op->src_pos()->as_register(); |
aoqi@1 | 4706 | Register dst_pos = op->dst_pos()->as_register(); |
aoqi@1 | 4707 | Register length = op->length()->as_register(); |
aoqi@1 | 4708 | Register tmp = T8; |
aoqi@1 | 4709 | #ifndef OPT_THREAD |
aoqi@1 | 4710 | Register java_thread = T8; |
aoqi@1 | 4711 | #else |
aoqi@1 | 4712 | Register java_thread = TREG; |
aoqi@1 | 4713 | #endif |
aoqi@1 | 4714 | CodeStub* stub = op->stub(); |
aoqi@1 | 4715 | |
aoqi@1 | 4716 | int flags = op->flags(); |
aoqi@1 | 4717 | BasicType basic_type = default_type != NULL ? default_type->element_type()->basic_type() : T_ILLEGAL; |
aoqi@1 | 4718 | if (basic_type == T_ARRAY) basic_type = T_OBJECT; |
aoqi@1 | 4719 | |
aoqi@1 | 4720 | // if we don't know anything or it's an object array, just go through the generic arraycopy |
aoqi@1 | 4721 | if (default_type == NULL) { |
aoqi@1 | 4722 | Label done; |
aoqi@1 | 4723 | // save outgoing arguments on stack in case call to System.arraycopy is needed |
aoqi@1 | 4724 | // HACK ALERT. This code used to push the parameters in a hardwired fashion |
aoqi@1 | 4725 | // for interpreter calling conventions. Now we have to do it in new style conventions. |
aoqi@1 | 4726 | // For the moment until C1 gets the new register allocator I just force all the |
aoqi@1 | 4727 | // args to the right place (except the register args) and then on the back side |
aoqi@1 | 4728 | // reload the register args properly if we go slow path. Yuck |
aoqi@1 | 4729 | |
aoqi@1 | 4730 | // this is saved in the caller's reserved argument area |
aoqi@6880 | 4731 | //FIXME, maybe It will change something in the stack; |
aoqi@1 | 4732 | // These are proper for the calling convention |
aoqi@1 | 4733 | //store_parameter(length, 2); |
aoqi@1 | 4734 | //store_parameter(dst_pos, 1); |
aoqi@1 | 4735 | //store_parameter(dst, 0); |
aoqi@1 | 4736 | |
aoqi@1 | 4737 | // these are just temporary placements until we need to reload |
aoqi@1 | 4738 | //store_parameter(src_pos, 3); |
aoqi@1 | 4739 | //store_parameter(src, 4); |
aoqi@1 | 4740 | assert(src == T0 && src_pos == A0, "mismatch in calling convention"); |
aoqi@1 | 4741 | // pass arguments: may push as this is not a safepoint; SP must be fix at each safepoint |
aoqi@1 | 4742 | |
aoqi@1 | 4743 | __ push(src); |
aoqi@1 | 4744 | __ push(dst); |
aoqi@1 | 4745 | __ push(src_pos); |
aoqi@1 | 4746 | __ push(dst_pos); |
aoqi@1 | 4747 | __ push(length); |
aoqi@1 | 4748 | |
aoqi@1 | 4749 | |
aoqi@1 | 4750 | // save SP and align |
aoqi@1 | 4751 | #ifndef OPT_THREAD |
aoqi@1 | 4752 | __ get_thread(java_thread); |
aoqi@1 | 4753 | #endif |
aoqi@1 | 4754 | __ st_ptr(SP, java_thread, in_bytes(JavaThread::last_Java_sp_offset())); |
aoqi@1 | 4755 | #ifndef _LP64 |
aoqi@1 | 4756 | __ addi(SP, SP, (-5) * wordSize); |
aoqi@1 | 4757 | __ move(AT, -(StackAlignmentInBytes)); |
aoqi@1 | 4758 | __ andr(SP, SP, AT); |
aoqi@1 | 4759 | // push argument |
aoqi@1 | 4760 | __ sw(length, SP, 4 * wordSize); |
aoqi@1 | 4761 | #else |
aoqi@1 | 4762 | __ move(A4, length); |
aoqi@1 | 4763 | #endif |
aoqi@1 | 4764 | __ move(A3, dst_pos); |
aoqi@1 | 4765 | __ move(A2, dst); |
aoqi@1 | 4766 | __ move(A1, src_pos); |
aoqi@1 | 4767 | __ move(A0, src); |
aoqi@1 | 4768 | // make call |
aoqi@1 | 4769 | address entry = CAST_FROM_FN_PTR(address, Runtime1::arraycopy); |
aoqi@6880 | 4770 | __ call(entry, relocInfo::runtime_call_type); |
aoqi@1 | 4771 | __ delayed()->nop(); |
aoqi@1 | 4772 | // restore SP |
aoqi@1 | 4773 | #ifndef OPT_THREAD |
aoqi@1 | 4774 | __ get_thread(java_thread); |
aoqi@1 | 4775 | #endif |
aoqi@1 | 4776 | __ ld_ptr(SP, java_thread, in_bytes(JavaThread::last_Java_sp_offset())); |
aoqi@6880 | 4777 | __ super_pop(length); |
aoqi@1 | 4778 | __ super_pop(dst_pos); |
aoqi@1 | 4779 | __ super_pop(src_pos); |
aoqi@1 | 4780 | __ super_pop(dst); |
aoqi@1 | 4781 | __ super_pop(src); |
aoqi@1 | 4782 | |
aoqi@1 | 4783 | __ beq_far(V0, R0, *stub->continuation()); |
aoqi@1 | 4784 | __ delayed()->nop(); |
aoqi@1 | 4785 | |
aoqi@1 | 4786 | |
aoqi@1 | 4787 | __ b_far(*stub->entry()); |
aoqi@6880 | 4788 | __ delayed()->nop(); |
aoqi@1 | 4789 | __ bind(*stub->continuation()); |
aoqi@1 | 4790 | return; |
aoqi@1 | 4791 | } |
aoqi@6880 | 4792 | assert(default_type != NULL |
aoqi@6880 | 4793 | && default_type->is_array_klass() |
aoqi@6880 | 4794 | && default_type->is_loaded(), |
aoqi@1 | 4795 | "must be true at this point"); |
aoqi@1 | 4796 | |
aoqi@1 | 4797 | int elem_size = type2aelembytes(basic_type); |
aoqi@1 | 4798 | int shift_amount; |
aoqi@1 | 4799 | switch (elem_size) { |
aoqi@1 | 4800 | case 1 :shift_amount = 0; break; |
aoqi@1 | 4801 | case 2 :shift_amount = 1; break; |
aoqi@1 | 4802 | case 4 :shift_amount = 2; break; |
aoqi@1 | 4803 | case 8 :shift_amount = 3; break; |
aoqi@1 | 4804 | default:ShouldNotReachHere(); |
aoqi@1 | 4805 | } |
aoqi@1 | 4806 | |
aoqi@1 | 4807 | Address src_length_addr = Address(src, arrayOopDesc::length_offset_in_bytes()); |
aoqi@1 | 4808 | Address dst_length_addr = Address(dst, arrayOopDesc::length_offset_in_bytes()); |
aoqi@1 | 4809 | Address src_klass_addr = Address(src, oopDesc::klass_offset_in_bytes()); |
aoqi@1 | 4810 | Address dst_klass_addr = Address(dst, oopDesc::klass_offset_in_bytes()); |
aoqi@1 | 4811 | |
aoqi@1 | 4812 | // test for NULL |
aoqi@1 | 4813 | if (flags & LIR_OpArrayCopy::src_null_check) { |
aoqi@1 | 4814 | __ beq_far(src, R0, *stub->entry()); |
aoqi@1 | 4815 | __ delayed()->nop(); |
aoqi@1 | 4816 | } |
aoqi@1 | 4817 | if (flags & LIR_OpArrayCopy::dst_null_check) { |
aoqi@1 | 4818 | __ beq_far(dst, R0, *stub->entry()); |
aoqi@1 | 4819 | __ delayed()->nop(); |
aoqi@1 | 4820 | } |
aoqi@1 | 4821 | |
aoqi@1 | 4822 | // check if negative |
aoqi@1 | 4823 | if (flags & LIR_OpArrayCopy::src_pos_positive_check) { |
aoqi@1 | 4824 | __ bltz(src_pos, *stub->entry()); |
aoqi@1 | 4825 | __ delayed()->nop(); |
aoqi@1 | 4826 | } |
aoqi@1 | 4827 | if (flags & LIR_OpArrayCopy::dst_pos_positive_check) { |
aoqi@1 | 4828 | __ bltz(dst_pos, *stub->entry()); |
aoqi@1 | 4829 | __ delayed()->nop(); |
aoqi@1 | 4830 | } |
aoqi@1 | 4831 | if (flags & LIR_OpArrayCopy::length_positive_check) { |
aoqi@1 | 4832 | __ bltz(length, *stub->entry()); |
aoqi@1 | 4833 | __ delayed()->nop(); |
aoqi@1 | 4834 | } |
aoqi@1 | 4835 | |
aoqi@1 | 4836 | if (flags & LIR_OpArrayCopy::src_range_check) { |
aoqi@1 | 4837 | __ add(AT, src_pos, length); |
aoqi@1 | 4838 | __ lw(tmp, src_length_addr); |
aoqi@1 | 4839 | __ sltu(AT, tmp, AT); |
aoqi@1 | 4840 | __ bne_far(AT, R0, *stub->entry()); |
aoqi@1 | 4841 | __ delayed()->nop(); |
aoqi@1 | 4842 | } |
aoqi@1 | 4843 | if (flags & LIR_OpArrayCopy::dst_range_check) { |
aoqi@1 | 4844 | __ add(AT, dst_pos, length); |
aoqi@1 | 4845 | __ lw(tmp, dst_length_addr); |
aoqi@1 | 4846 | __ sltu(AT, tmp, AT); |
aoqi@1 | 4847 | __ bne_far(AT, R0, *stub->entry()); |
aoqi@1 | 4848 | __ delayed()->nop(); |
aoqi@1 | 4849 | } |
aoqi@1 | 4850 | |
aoqi@1 | 4851 | if (flags & LIR_OpArrayCopy::type_check) { |
aoqi@8865 | 4852 | if (UseCompressedClassPointers) { |
aoqi@8865 | 4853 | __ lw(AT, src_klass_addr); |
aoqi@8865 | 4854 | __ lw(tmp, dst_klass_addr); |
aoqi@8865 | 4855 | } else { |
aoqi@8865 | 4856 | __ ld(AT, src_klass_addr); __ ld(tmp, dst_klass_addr); |
aoqi@8865 | 4857 | } |
aoqi@1 | 4858 | __ bne_far(AT, tmp, *stub->entry()); |
aoqi@1 | 4859 | __ delayed()->nop(); |
aoqi@1 | 4860 | } |
aoqi@1 | 4861 | |
aoqi@1 | 4862 | #ifdef ASSERT |
aoqi@1 | 4863 | if (basic_type != T_OBJECT || !(flags & LIR_OpArrayCopy::type_check)) { |
aoqi@1 | 4864 | // Sanity check the known type with the incoming class. For the |
aoqi@1 | 4865 | // primitive case the types must match exactly. For the object array |
aoqi@1 | 4866 | // case, if no type check is needed then the dst type must match the |
aoqi@1 | 4867 | // expected type and the src type is so subtype which we can't check. If |
aoqi@1 | 4868 | // a type check i needed then at this point the classes are known to be |
aoqi@1 | 4869 | // the same but again which don't know which type so we can't check them. |
aoqi@1 | 4870 | Label known_ok, halt; |
aoqi@8865 | 4871 | __ mov_metadata(tmp, default_type->constant_encoding()); |
aoqi@1 | 4872 | #ifdef _LP64 |
aoqi@8865 | 4873 | if (UseCompressedClassPointers) { |
aoqi@8865 | 4874 | __ encode_klass_not_null(tmp); |
aoqi@8865 | 4875 | } |
aoqi@1 | 4876 | #endif |
aoqi@1 | 4877 | if (basic_type != T_OBJECT) { |
aoqi@8865 | 4878 | if (UseCompressedClassPointers) { |
aoqi@8865 | 4879 | __ lw(AT, dst_klass_addr); |
aoqi@8865 | 4880 | } else { |
aoqi@8865 | 4881 | __ ld(AT, dst_klass_addr); |
aoqi@8865 | 4882 | } |
aoqi@1 | 4883 | __ bne(AT, tmp, halt); |
aoqi@1 | 4884 | __ delayed()->nop(); |
aoqi@8865 | 4885 | if (UseCompressedClassPointers) { |
aoqi@8865 | 4886 | __ lw(AT, src_klass_addr); |
aoqi@6880 | 4887 | } else { |
aoqi@8865 | 4888 | __ ld(AT, src_klass_addr); |
aoqi@6880 | 4889 | } |
aoqi@1 | 4890 | __ beq(AT, tmp, known_ok); |
aoqi@1 | 4891 | __ delayed()->nop(); |
aoqi@1 | 4892 | } else { |
aoqi@8865 | 4893 | if (UseCompressedClassPointers) { |
aoqi@8865 | 4894 | __ lw(AT, dst_klass_addr); |
aoqi@8865 | 4895 | } else { |
aoqi@8865 | 4896 | __ ld(AT, dst_klass_addr); |
aoqi@8865 | 4897 | } |
aoqi@8865 | 4898 | __ beq(AT, tmp, known_ok); |
aoqi@8865 | 4899 | __ delayed()->nop(); |
aoqi@8865 | 4900 | __ beq(src, dst, known_ok); |
aoqi@8865 | 4901 | __ delayed()->nop(); |
aoqi@1 | 4902 | } |
aoqi@1 | 4903 | __ bind(halt); |
aoqi@1 | 4904 | __ stop("incorrect type information in arraycopy"); |
aoqi@1 | 4905 | __ bind(known_ok); |
aoqi@1 | 4906 | } |
aoqi@1 | 4907 | #endif |
aoqi@1 | 4908 | __ push(src); |
aoqi@1 | 4909 | __ push(dst); |
aoqi@1 | 4910 | __ push(src_pos); |
aoqi@1 | 4911 | __ push(dst_pos); |
aoqi@1 | 4912 | __ push(length); |
aoqi@1 | 4913 | |
aoqi@1 | 4914 | |
aoqi@1 | 4915 | assert(A0 != A1 && |
aoqi@1 | 4916 | A0 != length && |
aoqi@1 | 4917 | A1 != length, "register checks"); |
aoqi@1 | 4918 | __ move(AT, dst_pos); |
aoqi@1 | 4919 | if (shift_amount > 0 && basic_type != T_OBJECT) { |
aoqi@1 | 4920 | #ifndef _LP64 |
aoqi@1 | 4921 | __ sll(A2, length, shift_amount); |
aoqi@1 | 4922 | #else |
aoqi@1 | 4923 | __ dsll(A2, length, shift_amount); |
aoqi@1 | 4924 | #endif |
aoqi@1 | 4925 | } else { |
aoqi@1 | 4926 | if (length!=A2) |
aoqi@1 | 4927 | __ move(A2, length); |
aoqi@1 | 4928 | } |
aoqi@6880 | 4929 | __ move(A3, src_pos ); |
aoqi@1 | 4930 | assert(A0 != dst_pos && |
aoqi@1 | 4931 | A0 != dst && |
aoqi@1 | 4932 | dst_pos != dst, "register checks"); |
aoqi@1 | 4933 | |
aoqi@1 | 4934 | assert_different_registers(A0, dst_pos, dst); |
aoqi@1 | 4935 | #ifndef _LP64 |
aoqi@1 | 4936 | __ sll(AT, AT, shift_amount); |
aoqi@1 | 4937 | #else |
aoqi@1 | 4938 | __ dsll(AT, AT, shift_amount); |
aoqi@1 | 4939 | #endif |
aoqi@1 | 4940 | __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(basic_type)); |
aoqi@1 | 4941 | __ add(A1, dst, AT); |
aoqi@1 | 4942 | |
aoqi@1 | 4943 | #ifndef _LP64 |
aoqi@1 | 4944 | __ sll(AT, A3, shift_amount); |
aoqi@1 | 4945 | #else |
aoqi@1 | 4946 | __ dsll(AT, A3, shift_amount); |
aoqi@1 | 4947 | #endif |
aoqi@1 | 4948 | __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(basic_type)); |
aoqi@1 | 4949 | __ add(A0, src, AT); |
aoqi@1 | 4950 | |
aoqi@1 | 4951 | |
aoqi@1 | 4952 | |
aoqi@1 | 4953 | if (basic_type == T_OBJECT) { |
aoqi@1 | 4954 | __ call_VM_leaf(CAST_FROM_FN_PTR(address, Runtime1::oop_arraycopy), 3); |
aoqi@1 | 4955 | } else { |
aoqi@1 | 4956 | __ call_VM_leaf(CAST_FROM_FN_PTR(address, Runtime1::primitive_arraycopy), 3); |
aoqi@1 | 4957 | } |
aoqi@6880 | 4958 | __ super_pop(length); |
aoqi@1 | 4959 | __ super_pop(dst_pos); |
aoqi@1 | 4960 | __ super_pop(src_pos); |
aoqi@1 | 4961 | __ super_pop(dst); |
aoqi@1 | 4962 | __ super_pop(src); |
aoqi@1 | 4963 | |
aoqi@1 | 4964 | __ bind(*stub->continuation()); |
aoqi@1 | 4965 | } |
aoqi@1 | 4966 | |
aoqi@1 | 4967 | void LIR_Assembler::emit_updatecrc32(LIR_OpUpdateCRC32* op) { |
aoqi@6880 | 4968 | tty->print_cr("LIR_Assembler::emit_updatecrc32 unimplemented yet !"); |
aoqi@6880 | 4969 | Unimplemented(); |
aoqi@1 | 4970 | } |
aoqi@1 | 4971 | |
aoqi@1 | 4972 | void LIR_Assembler::emit_lock(LIR_OpLock* op) { |
aoqi@6880 | 4973 | Register obj = op->obj_opr()->as_register(); // may not be an oop |
aoqi@6880 | 4974 | Register hdr = op->hdr_opr()->as_register(); |
aoqi@6880 | 4975 | Register lock = op->lock_opr()->is_single_cpu() ? op->lock_opr()->as_register(): op->lock_opr()->as_register_lo(); |
aoqi@6880 | 4976 | if (!UseFastLocking) { |
aoqi@6880 | 4977 | __ b_far(*op->stub()->entry()); |
aoqi@8865 | 4978 | __ delayed()->nop(); |
aoqi@6880 | 4979 | } else if (op->code() == lir_lock) { |
aoqi@6880 | 4980 | Register scratch = noreg; |
aoqi@6880 | 4981 | if (UseBiasedLocking) { |
aoqi@6880 | 4982 | scratch = op->scratch_opr()->as_register(); |
aoqi@6880 | 4983 | } |
aoqi@6880 | 4984 | assert(BasicLock::displaced_header_offset_in_bytes() == 0, |
aoqi@6880 | 4985 | "lock_reg must point to the displaced header"); |
aoqi@6880 | 4986 | // add debug info for NullPointerException only if one is possible |
aoqi@6880 | 4987 | int null_check_offset = __ lock_object(hdr, obj, lock, scratch, *op->stub()->entry()); |
aoqi@6880 | 4988 | if (op->info() != NULL) { |
aoqi@6880 | 4989 | //add_debug_info_for_null_check_here(op->info()); |
aoqi@6880 | 4990 | add_debug_info_for_null_check(null_check_offset,op->info()); |
aoqi@6880 | 4991 | } |
aoqi@6880 | 4992 | // done |
aoqi@6880 | 4993 | } else if (op->code() == lir_unlock) { |
aoqi@6880 | 4994 | assert(BasicLock::displaced_header_offset_in_bytes() == 0, |
aoqi@6880 | 4995 | "lock_reg must point to the displaced header"); |
aoqi@6880 | 4996 | __ unlock_object(hdr, obj, lock, *op->stub()->entry()); |
aoqi@6880 | 4997 | } else { |
aoqi@6880 | 4998 | Unimplemented(); |
aoqi@6880 | 4999 | } |
aoqi@6880 | 5000 | __ bind(*op->stub()->continuation()); |
aoqi@1 | 5001 | } |
aoqi@1 | 5002 | |
aoqi@1 | 5003 | |
aoqi@1 | 5004 | |
aoqi@1 | 5005 | void LIR_Assembler::emit_profile_call(LIR_OpProfileCall* op) { |
aoqi@1 | 5006 | ciMethod* method = op->profiled_method(); |
aoqi@1 | 5007 | int bci = op->profiled_bci(); |
aoqi@1 | 5008 | ciMethod* callee = op->profiled_callee(); |
aoqi@1 | 5009 | // Update counter for all call types |
aoqi@1 | 5010 | ciMethodData* md = method->method_data(); |
aoqi@1 | 5011 | if (md == NULL) { |
aoqi@1 | 5012 | bailout("out of memory building methodDataOop"); |
aoqi@1 | 5013 | return; |
aoqi@1 | 5014 | } |
aoqi@1 | 5015 | ciProfileData* data = md->bci_to_data(bci); |
aoqi@1 | 5016 | assert(data->is_CounterData(), "need CounterData for calls"); |
aoqi@1 | 5017 | assert(op->mdo()->is_single_cpu(), "mdo must be allocated"); |
aoqi@1 | 5018 | Register mdo = op->mdo()->as_register(); |
aoqi@1 | 5019 | |
aoqi@8865 | 5020 | __ mov_metadata(mdo, md->constant_encoding()); |
aoqi@1 | 5021 | |
aoqi@1 | 5022 | Address counter_addr(mdo, md->byte_offset_of_slot(data, CounterData::count_offset())); |
aoqi@8865 | 5023 | __ ld_ptr(AT, counter_addr); |
aoqi@8865 | 5024 | __ addi(AT, AT, DataLayout::counter_increment); |
aoqi@8865 | 5025 | __ st_ptr(AT, counter_addr); |
aoqi@1 | 5026 | |
aoqi@1 | 5027 | Bytecodes::Code bc = method->java_code_at_bci(bci); |
aoqi@1 | 5028 | const bool callee_is_static = callee->is_loaded() && callee->is_static(); |
aoqi@1 | 5029 | // Perform additional virtual call profiling for invokevirtual and |
aoqi@1 | 5030 | // invokeinterface bytecodes |
aoqi@1 | 5031 | if ((bc == Bytecodes::_invokevirtual || bc == Bytecodes::_invokeinterface) && |
aoqi@1 | 5032 | !callee_is_static && //required for optimized MH invokes |
aoqi@1 | 5033 | C1ProfileVirtualCalls) { |
aoqi@8865 | 5034 | assert(op->recv()->is_single_cpu(), "recv must be allocated"); |
aoqi@8865 | 5035 | Register recv = op->recv()->as_register(); |
aoqi@8865 | 5036 | assert_different_registers(mdo, recv); |
aoqi@8865 | 5037 | assert(data->is_VirtualCallData(), "need VirtualCallData for virtual calls"); |
aoqi@8865 | 5038 | ciKlass* known_klass = op->known_holder(); |
aoqi@1 | 5039 | if (C1OptimizeVirtualCallProfiling && known_klass != NULL) { |
aoqi@1 | 5040 | // We know the type that will be seen at this call site; we can |
aoqi@1 | 5041 | // statically update the methodDataOop rather than needing to do |
aoqi@1 | 5042 | // dynamic tests on the receiver type |
aoqi@1 | 5043 | |
aoqi@1 | 5044 | // NOTE: we should probably put a lock around this search to |
aoqi@1 | 5045 | // avoid collisions by concurrent compilations |
aoqi@1 | 5046 | ciVirtualCallData* vc_data = (ciVirtualCallData*) data; |
aoqi@1 | 5047 | uint i; |
aoqi@1 | 5048 | for (i = 0; i < VirtualCallData::row_limit(); i++) { |
aoqi@8865 | 5049 | ciKlass* receiver = vc_data->receiver(i); |
aoqi@8865 | 5050 | if (known_klass->equals(receiver)) { |
aoqi@8865 | 5051 | Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i))); |
aoqi@8865 | 5052 | __ ld_ptr(AT, data_addr); |
aoqi@8865 | 5053 | __ addi(AT, AT, DataLayout::counter_increment); |
aoqi@8865 | 5054 | __ st_ptr(AT, data_addr); |
aoqi@8865 | 5055 | return; |
aoqi@8865 | 5056 | } |
aoqi@1 | 5057 | } |
aoqi@1 | 5058 | |
aoqi@1 | 5059 | // Receiver type not found in profile data; select an empty slot |
aoqi@1 | 5060 | |
aoqi@1 | 5061 | // Note that this is less efficient than it should be because it |
aoqi@1 | 5062 | // always does a write to the receiver part of the |
aoqi@1 | 5063 | // VirtualCallData rather than just the first time |
aoqi@1 | 5064 | for (i = 0; i < VirtualCallData::row_limit(); i++) { |
aoqi@8865 | 5065 | ciKlass* receiver = vc_data->receiver(i); |
aoqi@8865 | 5066 | if (receiver == NULL) { |
aoqi@8865 | 5067 | Address recv_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i))); |
aoqi@8865 | 5068 | __ mov_metadata(AT, known_klass->constant_encoding()); |
aoqi@8865 | 5069 | __ st_ptr(AT,recv_addr); |
aoqi@8865 | 5070 | Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i))); |
aoqi@8865 | 5071 | __ ld_ptr(AT, data_addr); |
aoqi@8865 | 5072 | __ addi(AT, AT, DataLayout::counter_increment); |
aoqi@8865 | 5073 | __ st_ptr(AT, data_addr); |
aoqi@8865 | 5074 | return; |
aoqi@8865 | 5075 | } |
aoqi@1 | 5076 | } |
aoqi@1 | 5077 | } else { |
aoqi@1 | 5078 | //__ ld_ptr(recv, Address(recv, oopDesc::klass_offset_in_bytes())); |
aoqi@8865 | 5079 | __ load_klass(recv, recv); |
aoqi@8865 | 5080 | Label update_done; |
aoqi@8865 | 5081 | uint i; |
aoqi@8865 | 5082 | for (i = 0; i < VirtualCallData::row_limit(); i++) { |
aoqi@8865 | 5083 | Label next_test; |
aoqi@6880 | 5084 | // See if the receiver is receiver[n]. |
aoqi@8865 | 5085 | __ ld_ptr(AT, Address(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i)))); |
aoqi@8865 | 5086 | __ bne(recv,AT,next_test); |
aoqi@8865 | 5087 | __ delayed()->nop(); |
aoqi@8865 | 5088 | Address data_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i))); |
aoqi@8865 | 5089 | __ ld_ptr(AT, data_addr); |
aoqi@8865 | 5090 | __ addi(AT, AT, DataLayout::counter_increment); |
aoqi@8865 | 5091 | __ st_ptr(AT, data_addr); |
aoqi@8865 | 5092 | __ b(update_done); |
aoqi@8865 | 5093 | __ delayed()->nop(); |
aoqi@8865 | 5094 | __ bind(next_test); |
aoqi@8865 | 5095 | } |
aoqi@1 | 5096 | |
aoqi@1 | 5097 | // Didn't find receiver; find next empty slot and fill it in |
aoqi@8865 | 5098 | for (i = 0; i < VirtualCallData::row_limit(); i++) { |
aoqi@8865 | 5099 | Label next_test; |
aoqi@8865 | 5100 | Address recv_addr(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_offset(i))); |
aoqi@8865 | 5101 | __ ld_ptr(AT, recv_addr); |
aoqi@8865 | 5102 | __ bne(AT, R0, next_test); |
aoqi@8865 | 5103 | __ delayed()->nop(); |
aoqi@8865 | 5104 | __ st_ptr(recv, recv_addr); |
aoqi@8865 | 5105 | __ move(AT, DataLayout::counter_increment); |
aoqi@8865 | 5106 | __ st_ptr(AT, Address(mdo, md->byte_offset_of_slot(data, VirtualCallData::receiver_count_offset(i)))); |
aoqi@8865 | 5107 | if (i < (VirtualCallData::row_limit() - 1)) { |
aoqi@8865 | 5108 | __ b(update_done); |
aoqi@8865 | 5109 | __ delayed()->nop(); |
aoqi@8865 | 5110 | } |
aoqi@8865 | 5111 | __ bind(next_test); |
aoqi@8865 | 5112 | } |
aoqi@8865 | 5113 | __ bind(update_done); |
aoqi@1 | 5114 | } |
aoqi@1 | 5115 | } |
aoqi@1 | 5116 | } |
aoqi@1 | 5117 | |
aoqi@1 | 5118 | void LIR_Assembler::emit_profile_type(LIR_OpProfileType* op) { |
aoqi@1 | 5119 | // Newly added in OpenJDK 8 |
aoqi@1 | 5120 | Unimplemented(); |
aoqi@1 | 5121 | } |
aoqi@1 | 5122 | |
aoqi@1 | 5123 | void LIR_Assembler::emit_delay(LIR_OpDelay*) { |
aoqi@6880 | 5124 | Unimplemented(); |
aoqi@1 | 5125 | } |
aoqi@1 | 5126 | |
aoqi@1 | 5127 | |
aoqi@1 | 5128 | void LIR_Assembler::monitor_address(int monitor_no, LIR_Opr dst) { |
aoqi@1 | 5129 | if (dst->is_single_cpu()) |
aoqi@1 | 5130 | __ lea(dst->as_register(), frame_map()->address_for_monitor_lock(monitor_no)); |
aoqi@1 | 5131 | else if (dst->is_double_cpu()) |
aoqi@1 | 5132 | __ lea(dst->as_register_lo(), frame_map()->address_for_monitor_lock(monitor_no)); |
aoqi@1 | 5133 | } |
aoqi@1 | 5134 | |
aoqi@1 | 5135 | void LIR_Assembler::align_backward_branch_target() { |
aoqi@8865 | 5136 | __ align(BytesPerWord); |
aoqi@1 | 5137 | } |
aoqi@1 | 5138 | |
aoqi@1 | 5139 | |
aoqi@1 | 5140 | void LIR_Assembler::negate(LIR_Opr left, LIR_Opr dest) { |
aoqi@6880 | 5141 | if (left->is_single_cpu()) { |
aoqi@6880 | 5142 | __ subu(dest->as_register(), R0, left->as_register()); |
aoqi@6880 | 5143 | } else if (left->is_double_cpu()) { |
aoqi@1 | 5144 | #ifndef _LP64 |
aoqi@6880 | 5145 | Register lo = left->as_register_lo(); |
aoqi@6880 | 5146 | Register hi = left->as_register_hi(); |
aoqi@6880 | 5147 | Register dlo = dest->as_register_lo(); |
aoqi@6880 | 5148 | Register dhi = dest->as_register_hi(); |
aoqi@1 | 5149 | assert(dlo != hi, "register checks"); |
aoqi@6880 | 5150 | __ nor(dlo, R0, lo); |
aoqi@6880 | 5151 | __ addiu(dlo, dlo, 1); |
aoqi@6880 | 5152 | __ sltiu(AT, dlo, 1); |
aoqi@6880 | 5153 | __ nor(dhi, R0, hi); |
aoqi@6880 | 5154 | __ addu(dhi, dhi, AT); |
aoqi@1 | 5155 | #else |
aoqi@6880 | 5156 | __ subu(dest->as_register_lo(), R0, left->as_register_lo()); |
aoqi@1 | 5157 | #endif |
aoqi@6880 | 5158 | } else if (left->is_single_fpu()) { |
aoqi@6880 | 5159 | //for mips , does it required ? |
aoqi@6880 | 5160 | __ neg_s(dest->as_float_reg(), left->as_float_reg()); |
aoqi@6880 | 5161 | } else if (left->is_double_fpu()) { |
aoqi@6880 | 5162 | //for mips , does it required ? |
aoqi@6880 | 5163 | __ neg_d(dest->as_double_reg(), left->as_double_reg()); |
aoqi@6880 | 5164 | }else { |
aoqi@6880 | 5165 | ShouldNotReachHere(); |
aoqi@6880 | 5166 | } |
aoqi@1 | 5167 | } |
aoqi@1 | 5168 | |
aoqi@1 | 5169 | void LIR_Assembler::leal(LIR_Opr addr, LIR_Opr dest) { |
aoqi@6880 | 5170 | assert(addr->is_address() && dest->is_register(), "check"); |
aoqi@8865 | 5171 | Register reg; |
aoqi@8865 | 5172 | reg = dest->as_pointer_register(); |
aoqi@8865 | 5173 | __ lea(reg, as_Address(addr->as_address_ptr())); |
aoqi@1 | 5174 | } |
aoqi@1 | 5175 | |
aoqi@1 | 5176 | |
aoqi@1 | 5177 | void LIR_Assembler::jobject2reg(jobject o, Register reg) { |
aoqi@6880 | 5178 | if (o == NULL) { |
aoqi@6880 | 5179 | // This seems wrong as we do not emit relocInfo |
aoqi@6880 | 5180 | // for classes that are not loaded yet, i.e., they will be |
aoqi@6880 | 5181 | // never GC'd |
aoqi@1 | 5182 | #ifndef _LP64 |
aoqi@1 | 5183 | //by_css |
aoqi@6880 | 5184 | __ lui(reg, Assembler::split_high((int)o)); |
aoqi@6880 | 5185 | __ addiu(reg, reg, Assembler::split_low((int)o)); |
aoqi@1 | 5186 | #else |
aoqi@8865 | 5187 | __ li48(reg, (long)o); |
aoqi@8865 | 5188 | //__ patchable_set48(reg, (long)o); |
aoqi@1 | 5189 | #endif |
aoqi@6880 | 5190 | } else { |
aoqi@6880 | 5191 | int oop_index = __ oop_recorder()->find_index(o); |
aoqi@6880 | 5192 | RelocationHolder rspec = oop_Relocation::spec(oop_index); |
aoqi@6880 | 5193 | __ relocate(rspec); |
aoqi@1 | 5194 | #ifndef _LP64 |
aoqi@1 | 5195 | //by_css |
aoqi@6880 | 5196 | __ lui(reg, Assembler::split_high((int)o)); |
aoqi@6880 | 5197 | __ addiu(reg, reg, Assembler::split_low((int)o)); |
aoqi@1 | 5198 | #else |
aoqi@8865 | 5199 | __ li48(reg, (long)o); |
aoqi@8865 | 5200 | //__ patchable_set48(reg, (long)o); |
aoqi@1 | 5201 | #endif |
aoqi@6880 | 5202 | } |
aoqi@1 | 5203 | } |
aoqi@1 | 5204 | |
aoqi@1 | 5205 | void LIR_Assembler::rt_call(LIR_Opr result, address dest, const LIR_OprList* args, LIR_Opr tmp, CodeEmitInfo* info) { |
aoqi@6880 | 5206 | assert(!tmp->is_valid(), "don't need temporary"); |
aoqi@1 | 5207 | __ call(dest, relocInfo::runtime_call_type); |
aoqi@6880 | 5208 | __ delayed()->nop(); |
aoqi@1 | 5209 | if (info != NULL) { |
aoqi@6880 | 5210 | add_call_info_here(info); |
aoqi@1 | 5211 | } |
aoqi@1 | 5212 | } |
aoqi@1 | 5213 | |
aoqi@1 | 5214 | /* by yyq 7/22/2009 |
aoqi@1 | 5215 | * i don't know the register allocator will allocate long or double in two consecutive registers |
aoqi@1 | 5216 | * if the allocator do like this, the lws below should be removed and lds be used. |
aoqi@1 | 5217 | */ |
aoqi@1 | 5218 | |
aoqi@1 | 5219 | void LIR_Assembler::volatile_move_op(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info) { |
aoqi@1 | 5220 | assert(type == T_LONG, "only for volatile long fields"); |
aoqi@1 | 5221 | if (info != NULL) { |
aoqi@1 | 5222 | add_debug_info_for_null_check_here(info); |
aoqi@1 | 5223 | } |
aoqi@1 | 5224 | |
aoqi@1 | 5225 | if(src->is_register() && dest->is_address()) { |
aoqi@1 | 5226 | if(src->is_double_cpu()) { |
aoqi@1 | 5227 | #ifdef _LP64 |
aoqi@1 | 5228 | __ sd(src->as_register_lo(), as_Address(dest->as_address_ptr())); |
aoqi@1 | 5229 | #else |
aoqi@1 | 5230 | __ sw(src->as_register_lo(), as_Address(dest->as_address_ptr())); |
aoqi@6880 | 5231 | __ sw(src->as_register_hi(), as_Address(dest->as_address_ptr()).base(), |
aoqi@6880 | 5232 | as_Address(dest->as_address_ptr()).disp() +4); |
aoqi@1 | 5233 | #endif |
aoqi@1 | 5234 | } else if (src->is_double_fpu()) { |
aoqi@1 | 5235 | #ifdef _LP64 |
aoqi@1 | 5236 | __ sdc1(src->as_fpu_lo(), as_Address(dest->as_address_ptr())); |
aoqi@1 | 5237 | #else |
aoqi@1 | 5238 | __ swc1(src->as_fpu_lo(), as_Address(dest->as_address_ptr())); |
aoqi@6880 | 5239 | __ swc1(src->as_fpu_hi(), as_Address(dest->as_address_ptr()).base(), |
aoqi@6880 | 5240 | as_Address(dest->as_address_ptr()).disp() +4); |
aoqi@1 | 5241 | #endif |
aoqi@1 | 5242 | } else { |
aoqi@1 | 5243 | ShouldNotReachHere(); |
aoqi@1 | 5244 | } |
aoqi@1 | 5245 | } else if (src->is_address() && dest->is_register()){ |
aoqi@1 | 5246 | if(dest->is_double_cpu()) { |
aoqi@1 | 5247 | #ifdef _LP64 |
aoqi@1 | 5248 | __ ld(dest->as_register_lo(), as_Address(src->as_address_ptr())); |
aoqi@1 | 5249 | #else |
aoqi@1 | 5250 | __ lw(dest->as_register_lo(), as_Address(src->as_address_ptr())); |
aoqi@6880 | 5251 | __ lw(dest->as_register_hi(), as_Address(src->as_address_ptr()).base(), |
aoqi@6880 | 5252 | as_Address(src->as_address_ptr()).disp() +4); |
aoqi@1 | 5253 | #endif |
aoqi@1 | 5254 | } else if (dest->is_double_fpu()) { |
aoqi@1 | 5255 | #ifdef _LP64 |
aoqi@1 | 5256 | __ ldc1(dest->as_fpu_lo(), as_Address(src->as_address_ptr())); |
aoqi@1 | 5257 | #else |
aoqi@1 | 5258 | __ lwc1(dest->as_fpu_lo(), as_Address(src->as_address_ptr())); |
aoqi@6880 | 5259 | __ lwc1(dest->as_fpu_hi(), as_Address(src->as_address_ptr()).base(), |
aoqi@6880 | 5260 | as_Address(src->as_address_ptr()).disp() +4); |
aoqi@1 | 5261 | #endif |
aoqi@1 | 5262 | } else { |
aoqi@1 | 5263 | ShouldNotReachHere(); |
aoqi@1 | 5264 | } |
aoqi@1 | 5265 | } else { |
aoqi@1 | 5266 | ShouldNotReachHere(); |
aoqi@1 | 5267 | } |
aoqi@1 | 5268 | } |
aoqi@1 | 5269 | |
aoqi@1 | 5270 | #ifdef ASSERT |
aoqi@1 | 5271 | // emit run-time assertion |
aoqi@1 | 5272 | void LIR_Assembler::emit_assert(LIR_OpAssert* op) { |
aoqi@1 | 5273 | tty->print_cr("LIR_Assembler::emit_assert unimplemented yet!"); |
aoqi@1 | 5274 | Unimplemented(); |
aoqi@1 | 5275 | } |
aoqi@1 | 5276 | #endif |
aoqi@1 | 5277 | |
aoqi@1 | 5278 | void LIR_Assembler::membar() { |
aoqi@6880 | 5279 | __ sync(); |
aoqi@1 | 5280 | } |
aoqi@1 | 5281 | |
aoqi@1 | 5282 | void LIR_Assembler::membar_acquire() { |
aoqi@6880 | 5283 | __ sync(); |
aoqi@1 | 5284 | } |
aoqi@1 | 5285 | |
aoqi@1 | 5286 | void LIR_Assembler::membar_release() { |
aoqi@6880 | 5287 | __ sync(); |
aoqi@1 | 5288 | } |
aoqi@1 | 5289 | |
aoqi@1 | 5290 | void LIR_Assembler::membar_loadload() { |
aoqi@1 | 5291 | // no-op |
aoqi@1 | 5292 | // //__ membar(Assembler::Membar_mask_bits(Assembler::loadload)); |
aoqi@1 | 5293 | } |
aoqi@6880 | 5294 | |
aoqi@1 | 5295 | void LIR_Assembler::membar_storestore() { |
aoqi@1 | 5296 | // no-op |
aoqi@1 | 5297 | // //__ membar(Assembler::Membar_mask_bits(Assembler::storestore)); |
aoqi@1 | 5298 | } |
aoqi@1 | 5299 | |
aoqi@1 | 5300 | void LIR_Assembler::membar_loadstore() { |
aoqi@1 | 5301 | // no-op |
aoqi@1 | 5302 | // //__ membar(Assembler::Membar_mask_bits(Assembler::loadstore)); |
aoqi@1 | 5303 | } |
aoqi@1 | 5304 | |
aoqi@1 | 5305 | void LIR_Assembler::membar_storeload() { |
aoqi@1 | 5306 | //__ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad)); |
aoqi@1 | 5307 | } |
aoqi@1 | 5308 | |
aoqi@1 | 5309 | |
aoqi@1 | 5310 | void LIR_Assembler::get_thread(LIR_Opr result_reg) { |
aoqi@6880 | 5311 | assert(result_reg->is_register(), "check"); |
aoqi@1 | 5312 | #ifndef OPT_THREAD |
aoqi@6880 | 5313 | __ get_thread(NOT_LP64(result_reg->as_register()) LP64_ONLY(result_reg->as_register_lo())); |
aoqi@1 | 5314 | #else |
aoqi@6880 | 5315 | __ move(NOT_LP64(result_reg->as_register()) LP64_ONLY(result_reg->as_register_lo()), TREG); |
aoqi@1 | 5316 | #endif |
aoqi@1 | 5317 | } |
aoqi@1 | 5318 | |
aoqi@1 | 5319 | void LIR_Assembler::peephole(LIR_List*) { |
aoqi@6880 | 5320 | // do nothing for now |
aoqi@1 | 5321 | } |
aoqi@1 | 5322 | |
aoqi@1 | 5323 | void LIR_Assembler::atomic_op(LIR_Code code, LIR_Opr src, LIR_Opr data, LIR_Opr dest, LIR_Opr tmp) { |
aoqi@1 | 5324 | /* assert(data == dest, "xchg/xadd uses only 2 operands"); |
aoqi@1 | 5325 | |
aoqi@1 | 5326 | if (data->type() == T_INT) { |
aoqi@1 | 5327 | if (code == lir_xadd) { |
aoqi@1 | 5328 | if (os::is_MP()) { |
aoqi@1 | 5329 | __ lock(); |
aoqi@1 | 5330 | } |
aoqi@1 | 5331 | __ xaddl(as_Address(src->as_address_ptr()), data->as_register()); |
aoqi@1 | 5332 | } else { |
aoqi@1 | 5333 | __ xchgl(data->as_register(), as_Address(src->as_address_ptr())); |
aoqi@1 | 5334 | } |
aoqi@1 | 5335 | } else if (data->is_oop()) { |
aoqi@1 | 5336 | assert (code == lir_xchg, "xadd for oops"); |
aoqi@1 | 5337 | Register obj = data->as_register(); |
aoqi@1 | 5338 | #ifdef _LP64 |
aoqi@1 | 5339 | if (UseCompressedOops) { |
aoqi@1 | 5340 | __ encode_heap_oop(obj); |
aoqi@1 | 5341 | __ xchgl(obj, as_Address(src->as_address_ptr())); |
aoqi@1 | 5342 | __ decode_heap_oop(obj); |
aoqi@1 | 5343 | } else { |
aoqi@1 | 5344 | __ xchgptr(obj, as_Address(src->as_address_ptr())); |
aoqi@1 | 5345 | } |
aoqi@1 | 5346 | #else |
aoqi@1 | 5347 | __ xchgl(obj, as_Address(src->as_address_ptr())); |
aoqi@1 | 5348 | #endif |
aoqi@1 | 5349 | } else if (data->type() == T_LONG) { |
aoqi@1 | 5350 | #ifdef _LP64 |
aoqi@1 | 5351 | assert(data->as_register_lo() == data->as_register_hi(), "should be a single register"); |
aoqi@1 | 5352 | if (code == lir_xadd) { |
aoqi@1 | 5353 | if (os::is_MP()) { |
aoqi@1 | 5354 | __ lock(); |
aoqi@1 | 5355 | } |
aoqi@1 | 5356 | __ xaddq(as_Address(src->as_address_ptr()), data->as_register_lo()); |
aoqi@1 | 5357 | } else { |
aoqi@1 | 5358 | __ xchgq(data->as_register_lo(), as_Address(src->as_address_ptr())); |
aoqi@1 | 5359 | } |
aoqi@1 | 5360 | #else |
aoqi@1 | 5361 | ShouldNotReachHere(); |
aoqi@1 | 5362 | #endif |
aoqi@1 | 5363 | } else { |
aoqi@1 | 5364 | ShouldNotReachHere(); |
aoqi@1 | 5365 | }*/ |
aoqi@8865 | 5366 | ShouldNotReachHere(); |
aoqi@1 | 5367 | } |
aoqi@1 | 5368 | |
aoqi@6880 | 5369 | #undef __ |