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