src/cpu/mips/vm/templateTable_mips_64.cpp

Tue, 24 Oct 2017 14:04:09 +0800

author
fujie
date
Tue, 24 Oct 2017 14:04:09 +0800
changeset 8001
76b73e112cb7
parent 7998
367db633bbea
child 8003
8363e2ada4b5
permissions
-rw-r--r--

[Assembler] Complex address modes support for Assembler::lea(Register rt, Address src), Assembler::sd(Register rt, Address dst) and Assembler::sw(Register rt, Address dst)

aoqi@1 1 /*
aoqi@1 2 * Copyright (c) 2003, 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 "interpreter/interpreter.hpp"
aoqi@1 29 #include "interpreter/interpreterRuntime.hpp"
aoqi@1 30 #include "interpreter/templateTable.hpp"
aoqi@1 31 #include "memory/universe.inline.hpp"
aoqi@1 32 #include "oops/methodData.hpp"
aoqi@1 33 #include "oops/objArrayKlass.hpp"
aoqi@1 34 #include "oops/oop.inline.hpp"
aoqi@1 35 #include "prims/methodHandles.hpp"
aoqi@1 36 #include "runtime/sharedRuntime.hpp"
aoqi@1 37 #include "runtime/stubRoutines.hpp"
aoqi@1 38 #include "runtime/synchronizer.hpp"
aoqi@1 39
aoqi@1 40
aoqi@1 41 #ifndef CC_INTERP
aoqi@1 42
aoqi@1 43 #define __ _masm->
aoqi@1 44
aoqi@1 45 // Platform-dependent initialization
aoqi@1 46
aoqi@1 47 void TemplateTable::pd_initialize() {
aoqi@1 48 // No mips specific initialization
aoqi@1 49 }
aoqi@1 50
aoqi@1 51 // Address computation: local variables
aoqi@6880 52
aoqi@1 53 static inline Address iaddress(int n) {
aoqi@1 54 return Address(LVP, Interpreter::local_offset_in_bytes(n));
aoqi@1 55 }
aoqi@1 56
aoqi@1 57 static inline Address laddress(int n) {
aoqi@1 58 return iaddress(n + 1);
aoqi@1 59 }
aoqi@1 60
aoqi@1 61 static inline Address faddress(int n) {
aoqi@1 62 return iaddress(n);
aoqi@1 63 }
aoqi@1 64
aoqi@1 65 static inline Address daddress(int n) {
aoqi@1 66 return laddress(n);
aoqi@1 67 }
aoqi@1 68
aoqi@1 69 static inline Address aaddress(int n) {
aoqi@1 70 return iaddress(n);
aoqi@1 71 }
aoqi@1 72 static inline Address haddress(int n) { return iaddress(n + 0); }
aoqi@1 73
aoqi@6880 74
aoqi@6880 75 static inline Address at_sp() { return Address(SP, 0); }
aoqi@1 76 static inline Address at_sp_p1() { return Address(SP, 1 * wordSize); }
aoqi@1 77 static inline Address at_sp_p2() { return Address(SP, 2 * wordSize); }
aoqi@1 78
aoqi@1 79 // At top of Java expression stack which may be different than esp(). It
aoqi@1 80 // isn't for category 1 objects.
aoqi@1 81 static inline Address at_tos () {
aoqi@1 82 Address tos = Address(SP, Interpreter::expr_offset_in_bytes(0));
aoqi@1 83 return tos;
aoqi@1 84 }
aoqi@1 85
aoqi@1 86 static inline Address at_tos_p1() {
aoqi@1 87 return Address(SP, Interpreter::expr_offset_in_bytes(1));
aoqi@1 88 }
aoqi@1 89
aoqi@1 90 static inline Address at_tos_p2() {
aoqi@1 91 return Address(SP, Interpreter::expr_offset_in_bytes(2));
aoqi@1 92 }
aoqi@1 93
aoqi@1 94 static inline Address at_tos_p3() {
aoqi@1 95 return Address(SP, Interpreter::expr_offset_in_bytes(3));
aoqi@1 96 }
aoqi@1 97
aoqi@6880 98 // we use S0 as bcp, be sure you have bcp in S0 before you call any of the Template generator
aoqi@1 99 Address TemplateTable::at_bcp(int offset) {
aoqi@1 100 assert(_desc->uses_bcp(), "inconsistent uses_bcp information");
aoqi@1 101 return Address(BCP, offset);
aoqi@1 102 }
aoqi@1 103
fujie@8001 104 // Miscelaneous helper routines
fujie@8001 105 // Store an oop (or NULL) at the address described by obj.
fujie@8001 106 // If val == noreg this means store a NULL
fujie@8001 107
fujie@8001 108 static void do_oop_store(InterpreterMacroAssembler* _masm,
fujie@8001 109 Address obj,
fujie@8001 110 Register val,
fujie@8001 111 BarrierSet::Name barrier,
fujie@8001 112 bool precise) {
fujie@8001 113 assert(val == noreg || val == V0, "parameter is just for looks");
fujie@8001 114 switch (barrier) {
fujie@8001 115 #if INCLUDE_ALL_GCS
fujie@8001 116 // case BarrierSet::G1SATBCT:
fujie@8001 117 // case BarrierSet::G1SATBCTLogging:
fujie@8001 118 // {
fujie@8001 119 // // flatten object address if needed
fujie@8001 120 // if (obj.index() == noreg && obj.disp() == 0) {
fujie@8001 121 // if (obj.base() != rdx) {
fujie@8001 122 // __ movq(rdx, obj.base());
fujie@8001 123 // }
fujie@8001 124 // } else {
fujie@8001 125 // __ leaq(rdx, obj);
fujie@8001 126 // }
fujie@8001 127 // __ g1_write_barrier_pre(rdx /* obj */,
fujie@8001 128 // rbx /* pre_val */,
fujie@8001 129 // r15_thread /* thread */,
fujie@8001 130 // r8 /* tmp */,
fujie@8001 131 // val != noreg /* tosca_live */,
fujie@8001 132 // false /* expand_call */);
fujie@8001 133 // if (val == noreg) {
fujie@8001 134 // __ store_heap_oop_null(Address(rdx, 0));
fujie@8001 135 // } else {
fujie@8001 136 // // G1 barrier needs uncompressed oop for region cross check.
fujie@8001 137 // Register new_val = val;
fujie@8001 138 // if (UseCompressedOops) {
fujie@8001 139 // new_val = rbx;
fujie@8001 140 // __ movptr(new_val, val);
fujie@8001 141 // }
fujie@8001 142 // __ store_heap_oop(Address(rdx, 0), val);
fujie@8001 143 // __ g1_write_barrier_post(rdx /* store_adr */,
fujie@8001 144 // new_val /* new_val */,
fujie@8001 145 // r15_thread /* thread */,
fujie@8001 146 // r8 /* tmp */,
fujie@8001 147 // rbx /* tmp2 */);
fujie@8001 148 // }
fujie@8001 149 // }
fujie@8001 150 break;
fujie@8001 151 #endif // INCLUDE_ALL_GCS
fujie@8001 152 case BarrierSet::CardTableModRef:
fujie@8001 153 case BarrierSet::CardTableExtension:
fujie@8001 154 {
fujie@8001 155 if (val == noreg) {
fujie@8001 156 __ store_heap_oop_null(obj);
fujie@8001 157 } else {
fujie@8001 158 __ store_heap_oop(obj, val);
fujie@8001 159 // flatten object address if needed
fujie@8001 160 if (!precise || (obj.index() == noreg && obj.disp() == 0)) {
fujie@8001 161 __ store_check(obj.base());
fujie@8001 162 } else {
fujie@8001 163 //__ leaq(rdx, obj);
fujie@8001 164 //__ store_check(rdx);
fujie@8001 165 }
fujie@8001 166 }
fujie@8001 167 }
fujie@8001 168 break;
fujie@8001 169 case BarrierSet::ModRef:
fujie@8001 170 case BarrierSet::Other:
fujie@8001 171 if (val == noreg) {
fujie@8001 172 __ store_heap_oop_null(obj);
fujie@8001 173 } else {
fujie@8001 174 __ store_heap_oop(obj, val);
fujie@8001 175 }
fujie@8001 176 break;
fujie@8001 177 default :
fujie@8001 178 ShouldNotReachHere();
fujie@8001 179
fujie@8001 180 }
fujie@8001 181 }
fujie@8001 182
aoqi@1 183 // bytecode folding
aoqi@1 184 void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg,
aoqi@6880 185 Register tmp_reg, bool load_bc_into_bc_reg/*=true*/,
aoqi@1 186 int byte_no) {
aoqi@6880 187 if (!RewriteBytecodes) return;
aoqi@1 188 Label L_patch_done;
aoqi@6880 189
aoqi@1 190 switch (bc) {
aoqi@1 191 case Bytecodes::_fast_aputfield:
aoqi@1 192 case Bytecodes::_fast_bputfield:
aoqi@1 193 case Bytecodes::_fast_cputfield:
aoqi@1 194 case Bytecodes::_fast_dputfield:
aoqi@1 195 case Bytecodes::_fast_fputfield:
aoqi@1 196 case Bytecodes::_fast_iputfield:
aoqi@1 197 case Bytecodes::_fast_lputfield:
aoqi@1 198 case Bytecodes::_fast_sputfield:
aoqi@1 199 {
aoqi@6880 200 // We skip bytecode quickening for putfield instructions when
aoqi@6880 201 // the put_code written to the constant pool cache is zero.
aoqi@6880 202 // This is required so that every execution of this instruction
aoqi@6880 203 // calls out to InterpreterRuntime::resolve_get_put to do
aoqi@6880 204 // additional, required work.
aoqi@6880 205 assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
aoqi@6880 206 assert(load_bc_into_bc_reg, "we use bc_reg as temp");
aoqi@6880 207 __ get_cache_and_index_and_bytecode_at_bcp(tmp_reg, bc_reg, tmp_reg, byte_no, 1);
aoqi@6880 208 __ daddi(bc_reg, R0, bc);
aoqi@6880 209 __ beq(tmp_reg, R0, L_patch_done);
aoqi@6880 210 __ delayed()->nop();
aoqi@1 211 }
aoqi@1 212 break;
aoqi@1 213 default:
aoqi@1 214 assert(byte_no == -1, "sanity");
aoqi@6880 215 // the pair bytecodes have already done the load.
aoqi@6880 216 if (load_bc_into_bc_reg) {
aoqi@6880 217 __ move(bc_reg, bc);
aoqi@6880 218 }
aoqi@1 219 }
aoqi@1 220
aoqi@1 221 if (JvmtiExport::can_post_breakpoint()) {
aoqi@1 222 Label L_fast_patch;
aoqi@1 223 // if a breakpoint is present we can't rewrite the stream directly
aoqi@1 224 __ lbu(tmp_reg, at_bcp(0));
aoqi@1 225 __ move(AT, Bytecodes::_breakpoint);
aoqi@1 226 __ bne(tmp_reg, AT, L_fast_patch);
aoqi@1 227 __ delayed()->nop();
aoqi@1 228
aoqi@1 229 __ get_method(tmp_reg);
aoqi@6880 230 // Let breakpoint table handling rewrite to quicker bytecode
aoqi@6880 231 __ call_VM(NOREG, CAST_FROM_FN_PTR(address,
aoqi@6880 232 InterpreterRuntime::set_original_bytecode_at), tmp_reg, BCP, bc_reg);
aoqi@1 233
aoqi@1 234 __ b(L_patch_done);
aoqi@1 235 __ delayed()->nop();
aoqi@1 236 __ bind(L_fast_patch);
aoqi@1 237 }
aoqi@1 238
aoqi@1 239 #ifdef ASSERT
aoqi@1 240 Label L_okay;
aoqi@1 241 __ lbu(tmp_reg, at_bcp(0));
aoqi@1 242 __ move(AT, (int)Bytecodes::java_code(bc));
aoqi@1 243 __ beq(tmp_reg, AT, L_okay);
aoqi@1 244 __ delayed()->nop();
aoqi@1 245 __ beq(tmp_reg, bc_reg, L_patch_done);
aoqi@1 246 __ delayed()->nop();
aoqi@1 247 __ stop("patching the wrong bytecode");
aoqi@1 248 __ bind(L_okay);
aoqi@1 249 #endif
aoqi@1 250
aoqi@1 251 // patch bytecode
aoqi@1 252 __ sb(bc_reg, at_bcp(0));
aoqi@1 253 __ bind(L_patch_done);
aoqi@1 254 }
aoqi@1 255
aoqi@1 256
aoqi@1 257 // Individual instructions
aoqi@1 258
aoqi@1 259 void TemplateTable::nop() {
aoqi@1 260 transition(vtos, vtos);
aoqi@1 261 // nothing to do
aoqi@1 262 }
aoqi@1 263
aoqi@1 264 void TemplateTable::shouldnotreachhere() {
aoqi@1 265 transition(vtos, vtos);
aoqi@1 266 __ stop("shouldnotreachhere bytecode");
aoqi@1 267 }
aoqi@1 268
aoqi@1 269 void TemplateTable::aconst_null() {
aoqi@1 270 transition(vtos, atos);
aoqi@1 271 __ move(FSR, R0);
aoqi@1 272 }
aoqi@1 273
aoqi@1 274 void TemplateTable::iconst(int value) {
aoqi@1 275 transition(vtos, itos);
aoqi@1 276 if (value == 0) {
aoqi@1 277 __ move(FSR, R0);
aoqi@1 278 } else {
aoqi@1 279 __ move(FSR, value);
aoqi@1 280 }
aoqi@1 281 }
aoqi@1 282
aoqi@1 283 void TemplateTable::lconst(int value) {
aoqi@1 284 transition(vtos, ltos);
aoqi@1 285 if (value == 0) {
aoqi@1 286 __ move(FSR, R0);
aoqi@1 287 } else {
aoqi@1 288 __ move(FSR, value);
aoqi@1 289 }
aoqi@1 290 }
aoqi@1 291
aoqi@1 292 void TemplateTable::fconst(int value) {
aoqi@1 293 transition(vtos, ftos);
aoqi@1 294 switch( value ) {
fujie@6888 295 case 0: __ mtc1(R0, FSF); return;
fujie@6888 296 case 1: __ addiu(AT, R0, 1); break;
fujie@6888 297 case 2: __ addiu(AT, R0, 2); break;
aoqi@1 298 default: ShouldNotReachHere();
aoqi@1 299 }
fujie@6888 300 __ mtc1(AT, FSF);
fujie@6888 301 __ cvt_s_w(FSF, FSF);
aoqi@1 302 }
aoqi@1 303
aoqi@1 304 void TemplateTable::dconst(int value) {
aoqi@1 305 transition(vtos, dtos);
aoqi@1 306 switch( value ) {
aoqi@7997 307 case 0: __ dmtc1(R0, FSF);
fujie@6888 308 return;
fujie@6888 309 case 1: __ daddiu(AT, R0, 1);
fujie@6888 310 __ dmtc1(AT, FSF);
fujie@6888 311 __ cvt_d_w(FSF, FSF);
fujie@6888 312 break;
aoqi@1 313 default: ShouldNotReachHere();
aoqi@1 314 }
aoqi@1 315 }
aoqi@1 316
aoqi@1 317 void TemplateTable::bipush() {
aoqi@1 318 transition(vtos, itos);
aoqi@1 319 __ lb(FSR, at_bcp(1));
aoqi@1 320 }
aoqi@1 321
aoqi@1 322 void TemplateTable::sipush() {
aoqi@6880 323 transition(vtos, itos);
fujie@6888 324 __ lb(FSR, BCP, 1);
fujie@6888 325 __ lbu(AT, BCP, 2);
aoqi@7997 326 __ dsll(FSR, FSR, 8);
fujie@6888 327 __ orr(FSR, FSR, AT);
aoqi@1 328 }
aoqi@1 329
aoqi@1 330 // T1 : tags
aoqi@1 331 // T2 : index
aoqi@1 332 // T3 : cpool
aoqi@1 333 // T8 : tag
aoqi@1 334 void TemplateTable::ldc(bool wide) {
aoqi@1 335 transition(vtos, vtos);
aoqi@1 336 Label call_ldc, notFloat, notClass, Done;
aoqi@1 337 // get index in cpool
aoqi@1 338 if (wide) {
fujie@6885 339 __ get_unsigned_2_byte_index_at_bcp(T2, 1);
aoqi@1 340 } else {
aoqi@1 341 __ lbu(T2, at_bcp(1));
aoqi@1 342 }
aoqi@1 343
aoqi@1 344 __ get_cpool_and_tags(T3, T1);
aoqi@1 345
aoqi@1 346 const int base_offset = ConstantPool::header_size() * wordSize;
aoqi@1 347 const int tags_offset = Array<u1>::base_offset_in_bytes();
aoqi@1 348
aoqi@1 349 // get type
fujie@6885 350 if (UseLoongsonISA && Assembler::is_simm(sizeof(tags_offset), 8)) {
fujie@6885 351 __ gslbx(T1, T1, T2, tags_offset);
fujie@6885 352 } else {
fujie@6885 353 __ dadd(AT, T1, T2);
fujie@6885 354 __ lb(T1, AT, tags_offset);
fujie@6885 355 }
aoqi@1 356 //now T1 is the tag
aoqi@1 357
aoqi@1 358 // unresolved class - get the resolved class
aoqi@1 359 __ daddiu(AT, T1, - JVM_CONSTANT_UnresolvedClass);
aoqi@1 360 __ beq(AT, R0, call_ldc);
aoqi@1 361 __ delayed()->nop();
aoqi@1 362
aoqi@1 363 // unresolved class in error (resolution failed) - call into runtime
aoqi@1 364 // so that the same error from first resolution attempt is thrown.
aoqi@6880 365 __ daddiu(AT, T1, -JVM_CONSTANT_UnresolvedClassInError);
aoqi@1 366 __ beq(AT, R0, call_ldc);
aoqi@1 367 __ delayed()->nop();
aoqi@1 368
aoqi@1 369 // resolved class - need to call vm to get java mirror of the class
aoqi@1 370 __ daddiu(AT, T1, - JVM_CONSTANT_Class);
aoqi@1 371 __ bne(AT, R0, notClass);
aoqi@1 372 __ delayed()->dsll(T2, T2, Address::times_8);
aoqi@1 373
aoqi@1 374 __ bind(call_ldc);
aoqi@1 375 __ move(A1, wide);
aoqi@1 376 call_VM(FSR, CAST_FROM_FN_PTR(address, InterpreterRuntime::ldc), A1);
fujie@6885 377 //__ push(atos);
fujie@6885 378 __ sd(FSR, SP, - Interpreter::stackElementSize);
aoqi@1 379 __ b(Done);
fujie@6885 380 __ delayed()->daddiu(SP, SP, - Interpreter::stackElementSize);
fujie@6885 381 __ nop(); // added for performance issue
fujie@6885 382
aoqi@1 383 __ bind(notClass);
aoqi@1 384 __ daddiu(AT, T1, -JVM_CONSTANT_Float);
aoqi@1 385 __ bne(AT, R0, notFloat);
aoqi@1 386 __ delayed()->nop();
aoqi@1 387 // ftos
fujie@6885 388 if (UseLoongsonISA && Assembler::is_simm(sizeof(base_offset), 8)) {
fujie@6885 389 __ gslwxc1(FSF, T3, T2, base_offset);
fujie@6885 390 } else {
fujie@6885 391 __ dadd(AT, T3, T2);
fujie@6885 392 __ lwc1(FSF, AT, base_offset);
fujie@6885 393 }
fujie@6885 394 //__ push_f();
fujie@6885 395 __ swc1(FSF, SP, - Interpreter::stackElementSize);
aoqi@1 396 __ b(Done);
fujie@6885 397 __ delayed()->daddiu(SP, SP, - Interpreter::stackElementSize);
aoqi@1 398
aoqi@1 399 __ bind(notFloat);
aoqi@1 400 #ifdef ASSERT
aoqi@6880 401 {
aoqi@1 402 Label L;
aoqi@1 403 __ daddiu(AT, T1, -JVM_CONSTANT_Integer);
aoqi@1 404 __ beq(AT, R0, L);
aoqi@1 405 __ delayed()->nop();
aoqi@1 406 __ stop("unexpected tag type in ldc");
aoqi@1 407 __ bind(L);
aoqi@1 408 }
aoqi@1 409 #endif
fujie@6885 410 // itos JVM_CONSTANT_Integer only
fujie@6885 411 if (UseLoongsonISA && Assembler::is_simm(sizeof(base_offset), 8)) {
fujie@6885 412 __ gslwx(FSR, T3, T2, base_offset);
fujie@6885 413 } else {
fujie@6885 414 __ dadd(T0, T3, T2);
fujie@6885 415 __ lw(FSR, T0, base_offset);
fujie@6885 416 }
aoqi@1 417 __ push(itos);
aoqi@1 418 __ bind(Done);
aoqi@1 419 }
aoqi@1 420
aoqi@1 421 // Fast path for caching oop constants.
aoqi@1 422 void TemplateTable::fast_aldc(bool wide) {
aoqi@1 423 transition(vtos, atos);
aoqi@1 424
aoqi@1 425 Register result = FSR;
aoqi@1 426 Register tmp = SSR;
aoqi@1 427 int index_size = wide ? sizeof(u2) : sizeof(u1);
aoqi@1 428
aoqi@1 429 Label resolved;
aoqi@6880 430
aoqi@6880 431 // We are resolved if the resolved reference cache entry contains a
aoqi@6880 432 // non-null object (String, MethodType, etc.)
aoqi@1 433 assert_different_registers(result, tmp);
aoqi@1 434 __ get_cache_index_at_bcp(tmp, 1, index_size);
aoqi@1 435 __ load_resolved_reference_at_index(result, tmp);
aoqi@1 436 __ bne(result, R0, resolved);
aoqi@1 437 __ delayed()->nop();
aoqi@1 438
aoqi@1 439 address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);
aoqi@1 440 // first time invocation - must resolve first
aoqi@1 441 int i = (int)bytecode();
aoqi@1 442 __ move(tmp, i);
aoqi@1 443 __ call_VM(result, entry, tmp);
aoqi@1 444
aoqi@1 445 __ bind(resolved);
aoqi@1 446
aoqi@1 447 if (VerifyOops) {
aoqi@1 448 __ verify_oop(result);
aoqi@1 449 }
aoqi@1 450 }
aoqi@1 451
aoqi@1 452
aoqi@1 453 // used register: T2, T3, T1
aoqi@1 454 // T2 : index
aoqi@1 455 // T3 : cpool
aoqi@1 456 // T1 : tag
aoqi@1 457 void TemplateTable::ldc2_w() {
aoqi@1 458 transition(vtos, vtos);
aoqi@1 459 Label Long, Done;
aoqi@1 460
aoqi@1 461 // get index in cpool
fujie@6889 462 __ get_unsigned_2_byte_index_at_bcp(T2, 1);
aoqi@1 463
aoqi@1 464 __ get_cpool_and_tags(T3, T1);
aoqi@1 465
aoqi@1 466 const int base_offset = ConstantPool::header_size() * wordSize;
aoqi@1 467 const int tags_offset = Array<u1>::base_offset_in_bytes();
aoqi@1 468
aoqi@1 469 // get type in T1
fujie@6889 470 if (UseLoongsonISA && Assembler::is_simm(tags_offset, 8)) {
fujie@6889 471 __ gslbx(T1, T1, T2, tags_offset);
fujie@6889 472 } else {
fujie@6889 473 __ dadd(AT, T1, T2);
fujie@6889 474 __ lb(T1, AT, tags_offset);
fujie@6889 475 }
aoqi@1 476
aoqi@1 477 __ daddiu(AT, T1, - JVM_CONSTANT_Double);
aoqi@1 478 __ bne(AT, R0, Long);
aoqi@1 479 __ delayed()->dsll(T2, T2, Address::times_8);
fujie@6889 480
aoqi@6880 481 // dtos
fujie@6889 482 if (UseLoongsonISA && Assembler::is_simm(base_offset, 8)) {
fujie@6889 483 __ gsldxc1(FSF, T3, T2, base_offset);
fujie@6889 484 } else {
fujie@6889 485 __ daddu(AT, T3, T2);
fujie@6889 486 __ ldc1(FSF, AT, base_offset);
fujie@6889 487 }
aoqi@1 488 __ sdc1(FSF, SP, - 2 * wordSize);
aoqi@1 489 __ b(Done);
aoqi@1 490 __ delayed()->daddi(SP, SP, - 2 * wordSize);
aoqi@1 491
aoqi@1 492 // ltos
aoqi@1 493 __ bind(Long);
fujie@6889 494 if (UseLoongsonISA && Assembler::is_simm(base_offset, 8)) {
fujie@6889 495 __ gsldx(FSR, T3, T2, base_offset);
fujie@6889 496 } else {
fujie@6889 497 __ dadd(AT, T3, T2);
fujie@6889 498 __ ld(FSR, AT, base_offset);
fujie@6889 499 }
aoqi@1 500 __ push(ltos);
aoqi@1 501
aoqi@1 502 __ bind(Done);
aoqi@1 503 }
aoqi@1 504
aoqi@1 505 // we compute the actual local variable address here
aoqi@1 506 // the x86 dont do so for it has scaled index memory access model, we dont have, so do here
aoqi@1 507 void TemplateTable::locals_index(Register reg, int offset) {
aoqi@1 508 __ lbu(reg, at_bcp(offset));
aoqi@1 509 __ dsll(reg, reg, Address::times_8);
aoqi@1 510 __ dsub(reg, LVP, reg);
aoqi@1 511 }
aoqi@1 512
aoqi@1 513 // this method will do bytecode folding of the two form:
aoqi@6880 514 // iload iload iload caload
aoqi@1 515 // used register : T2, T3
aoqi@1 516 // T2 : bytecode
aoqi@1 517 // T3 : folded code
aoqi@1 518 void TemplateTable::iload() {
aoqi@1 519 transition(vtos, itos);
aoqi@6880 520 if (RewriteFrequentPairs) {
aoqi@1 521 Label rewrite, done;
aoqi@1 522 // get the next bytecode in T2
aoqi@1 523 __ lbu(T2, at_bcp(Bytecodes::length_for(Bytecodes::_iload)));
aoqi@1 524 // if _iload, wait to rewrite to iload2. We only want to rewrite the
aoqi@1 525 // last two iloads in a pair. Comparing against fast_iload means that
aoqi@1 526 // the next bytecode is neither an iload or a caload, and therefore
aoqi@1 527 // an iload pair.
aoqi@1 528 __ move(AT, Bytecodes::_iload);
aoqi@1 529 __ beq(AT, T2, done);
aoqi@1 530 __ delayed()->nop();
aoqi@1 531
aoqi@1 532 __ move(T3, Bytecodes::_fast_iload2);
aoqi@1 533 __ move(AT, Bytecodes::_fast_iload);
aoqi@1 534 __ beq(AT, T2, rewrite);
aoqi@1 535 __ delayed()->nop();
aoqi@1 536
aoqi@1 537 // if _caload, rewrite to fast_icaload
aoqi@1 538 __ move(T3, Bytecodes::_fast_icaload);
aoqi@1 539 __ move(AT, Bytecodes::_caload);
aoqi@1 540 __ beq(AT, T2, rewrite);
aoqi@1 541 __ delayed()->nop();
aoqi@1 542
aoqi@1 543 // rewrite so iload doesn't check again.
aoqi@1 544 __ move(T3, Bytecodes::_fast_iload);
aoqi@1 545
aoqi@1 546 // rewrite
aoqi@1 547 // T3 : fast bytecode
aoqi@1 548 __ bind(rewrite);
aoqi@1 549 patch_bytecode(Bytecodes::_iload, T3, T2, false);
aoqi@1 550 __ bind(done);
aoqi@1 551 }
aoqi@1 552
aoqi@1 553 // Get the local value into tos
aoqi@1 554 locals_index(T2);
aoqi@1 555 __ lw(FSR, T2, 0);
aoqi@1 556 }
aoqi@1 557
aoqi@1 558 // used register T2
aoqi@1 559 // T2 : index
aoqi@1 560 void TemplateTable::fast_iload2() {
aoqi@6880 561 transition(vtos, itos);
aoqi@6880 562 locals_index(T2);
aoqi@6880 563 __ lw(FSR, T2, 0);
aoqi@6880 564 __ push(itos);
aoqi@6880 565 locals_index(T2, 3);
aoqi@6880 566 __ lw(FSR, T2, 0);
aoqi@1 567 }
aoqi@6880 568
aoqi@1 569 // used register T2
aoqi@1 570 // T2 : index
aoqi@1 571 void TemplateTable::fast_iload() {
aoqi@1 572 transition(vtos, itos);
aoqi@1 573 locals_index(T2);
aoqi@1 574 __ lw(FSR, T2, 0);
aoqi@1 575 }
aoqi@1 576
aoqi@1 577 // used register T2
aoqi@1 578 // T2 : index
aoqi@1 579 void TemplateTable::lload() {
aoqi@1 580 transition(vtos, ltos);
aoqi@1 581 locals_index(T2);
aoqi@1 582 __ ld(FSR, T2, -wordSize);
aoqi@1 583 }
aoqi@1 584
aoqi@1 585 // used register T2
aoqi@1 586 // T2 : index
aoqi@1 587 void TemplateTable::fload() {
aoqi@1 588 transition(vtos, ftos);
aoqi@1 589 locals_index(T2);
aoqi@1 590 __ lwc1(FSF, T2, 0);
aoqi@1 591 }
aoqi@1 592
aoqi@1 593 // used register T2
aoqi@1 594 // T2 : index
aoqi@1 595 void TemplateTable::dload() {
aoqi@1 596 transition(vtos, dtos);
aoqi@1 597 locals_index(T2);
aoqi@6880 598 __ ldc1(FSF, T2, -wordSize);
aoqi@1 599 }
aoqi@1 600
aoqi@1 601 // used register T2
aoqi@1 602 // T2 : index
aoqi@6880 603 void TemplateTable::aload() {
aoqi@1 604 transition(vtos, atos);
aoqi@1 605 locals_index(T2);
aoqi@1 606 __ ld(FSR, T2, 0);
aoqi@1 607 }
aoqi@1 608
aoqi@1 609 void TemplateTable::locals_index_wide(Register reg) {
fujie@6890 610 __ get_unsigned_2_byte_index_at_bcp(reg, 2);
aoqi@1 611 __ dsll(reg, reg, Address::times_8);
aoqi@1 612 __ dsub(reg, LVP, reg);
aoqi@1 613 }
aoqi@1 614
aoqi@1 615 // used register T2
aoqi@1 616 // T2 : index
aoqi@1 617 void TemplateTable::wide_iload() {
aoqi@6880 618 transition(vtos, itos);
aoqi@6880 619 locals_index_wide(T2);
aoqi@6880 620 __ ld(FSR, T2, 0);
aoqi@1 621 }
aoqi@1 622
aoqi@1 623 // used register T2
aoqi@1 624 // T2 : index
aoqi@1 625 void TemplateTable::wide_lload() {
aoqi@6880 626 transition(vtos, ltos);
aoqi@6880 627 locals_index_wide(T2);
wangxue@6881 628 __ ld(FSR, T2, -wordSize);
aoqi@1 629 }
aoqi@1 630
aoqi@1 631 // used register T2
aoqi@1 632 // T2 : index
aoqi@1 633 void TemplateTable::wide_fload() {
aoqi@6880 634 transition(vtos, ftos);
aoqi@6880 635 locals_index_wide(T2);
aoqi@6880 636 __ lwc1(FSF, T2, 0);
aoqi@1 637 }
aoqi@1 638
aoqi@1 639 // used register T2
aoqi@1 640 // T2 : index
aoqi@1 641 void TemplateTable::wide_dload() {
aoqi@6880 642 transition(vtos, dtos);
aoqi@6880 643 locals_index_wide(T2);
wangxue@6881 644 __ ldc1(FSF, T2, -wordSize);
aoqi@1 645 }
aoqi@1 646
aoqi@1 647 // used register T2
aoqi@1 648 // T2 : index
aoqi@1 649 void TemplateTable::wide_aload() {
aoqi@6880 650 transition(vtos, atos);
aoqi@6880 651 locals_index_wide(T2);
aoqi@6880 652 __ ld(FSR, T2, 0);
aoqi@1 653 }
aoqi@1 654
aoqi@1 655 // we use A2 as the regiser for index, BE CAREFUL!
aoqi@1 656 // we dont use our tge 29 now, for later optimization
aoqi@1 657 void TemplateTable::index_check(Register array, Register index) {
aoqi@1 658 // Pop ptr into array
aoqi@1 659 __ pop_ptr(array);
aoqi@1 660 index_check_without_pop(array, index);
aoqi@1 661 }
aoqi@1 662
aoqi@1 663 void TemplateTable::index_check_without_pop(Register array, Register index) {
aoqi@1 664 // destroys ebx
aoqi@1 665 // check array
aoqi@1 666 __ null_check(array, arrayOopDesc::length_offset_in_bytes());
aoqi@1 667
fujie@108 668 #ifdef _LP64
fujie@108 669 // sign extend since tos (index) might contain garbage in upper bits
fujie@108 670 __ sll(index, index, 0);
fujie@108 671 #endif // _LP64
fujie@108 672
aoqi@1 673 // check index
aoqi@1 674 Label ok;
aoqi@1 675 __ lw(AT, array, arrayOopDesc::length_offset_in_bytes());
aoqi@1 676 #ifndef OPT_RANGECHECK
aoqi@1 677 __ sltu(AT, index, AT);
aoqi@1 678 __ bne(AT, R0, ok);
aoqi@6880 679 __ delayed()->nop();
aoqi@1 680
aoqi@1 681 //throw_ArrayIndexOutOfBoundsException assume abberrant index in A2
aoqi@6880 682 if (A2 != index) __ move(A2, index);
aoqi@1 683 __ jmp(Interpreter::_throw_ArrayIndexOutOfBoundsException_entry);
aoqi@1 684 __ delayed()->nop();
aoqi@1 685 __ bind(ok);
aoqi@1 686 #else
aoqi@1 687 __ lw(AT, array, arrayOopDesc::length_offset_in_bytes());
aoqi@1 688 __ move(A2, index);
aoqi@1 689 __ tgeu(A2, AT, 29);
aoqi@1 690 #endif
aoqi@1 691 }
aoqi@1 692
aoqi@1 693 void TemplateTable::iaload() {
aoqi@1 694 transition(itos, itos);
aoqi@6880 695 if(UseBoundCheckInstruction) {
jiangshaofeng@362 696 __ pop(SSR); //SSR:array FSR: index
jiangshaofeng@362 697 __ dsll(FSR, FSR, 2);
jiangshaofeng@362 698 __ dadd(FSR, SSR, FSR);
jiangshaofeng@362 699 __ addi(FSR, FSR, arrayOopDesc::base_offset_in_bytes(T_INT));
aoqi@6880 700
jiangshaofeng@362 701 __ lw(AT, SSR, arrayOopDesc::length_offset_in_bytes()); //bound
jiangshaofeng@362 702 __ dsll(AT, AT, 2);
jiangshaofeng@362 703 __ dadd(AT, SSR, AT);
jiangshaofeng@362 704 __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(T_INT));
aoqi@6880 705
jiangshaofeng@362 706 __ gslwle(FSR, FSR, AT);
jiangshaofeng@362 707 } else {
jiangshaofeng@362 708 index_check(SSR, FSR);
jiangshaofeng@362 709 __ dsll(FSR, FSR, 2);
fujie@6890 710 if (UseLoongsonISA && Assembler::is_simm(arrayOopDesc::base_offset_in_bytes(T_INT), 8)) {
fujie@6890 711 __ gslwx(FSR, FSR, SSR, arrayOopDesc::base_offset_in_bytes(T_INT));
fujie@6890 712 } else {
fujie@6890 713 __ dadd(FSR, SSR, FSR);
fujie@6890 714 __ lw(FSR, FSR, arrayOopDesc::base_offset_in_bytes(T_INT));
fujie@6890 715 }
jiangshaofeng@362 716 }
aoqi@1 717 }
aoqi@1 718
aoqi@1 719 void TemplateTable::laload() {
aoqi@1 720 transition(itos, ltos);
jiangshaofeng@362 721 if(UseBoundCheckInstruction) {
jiangshaofeng@362 722 __ pop(SSR); //SSR:array FSR: index
jiangshaofeng@362 723 __ dsll(FSR, FSR, Address::times_8);
jiangshaofeng@362 724 __ dadd(FSR, SSR, FSR);
jiangshaofeng@362 725 __ addi(FSR, FSR, arrayOopDesc::base_offset_in_bytes(T_LONG) + 0 * wordSize);
aoqi@6880 726
jiangshaofeng@362 727 __ lw(AT, SSR, arrayOopDesc::length_offset_in_bytes()); //bound
jiangshaofeng@362 728 __ dsll(AT, AT, Address::times_8);
jiangshaofeng@362 729 __ dadd(AT, SSR, AT);
jiangshaofeng@362 730 __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(T_LONG) + 0 * wordSize);
aoqi@6880 731
aoqi@6880 732 __ gsldle(FSR, FSR, AT);
jiangshaofeng@362 733 } else {
jiangshaofeng@362 734 index_check(SSR, FSR);
jiangshaofeng@362 735 __ dsll(AT, FSR, Address::times_8);
fujie@6890 736 if (UseLoongsonISA && Assembler::is_simm(arrayOopDesc::base_offset_in_bytes(T_LONG), 8)) {
fujie@6890 737 __ gsldx(FSR, SSR, AT, arrayOopDesc::base_offset_in_bytes(T_LONG));
fujie@6890 738 } else {
fujie@6890 739 __ dadd(AT, SSR, AT);
fujie@6890 740 __ ld(FSR, AT, arrayOopDesc::base_offset_in_bytes(T_LONG));
fujie@6890 741 }
jiangshaofeng@362 742 }
aoqi@1 743 }
aoqi@1 744
aoqi@1 745 void TemplateTable::faload() {
jiangshaofeng@362 746 transition(itos, ftos);
jiangshaofeng@362 747 if(UseBoundCheckInstruction) {
jiangshaofeng@362 748 __ pop(SSR); //SSR:array FSR: index
jiangshaofeng@362 749 __ shl(FSR, 2);
jiangshaofeng@362 750 __ dadd(FSR, SSR, FSR);
jiangshaofeng@362 751 __ addi(FSR, FSR, arrayOopDesc::base_offset_in_bytes(T_FLOAT));
aoqi@6880 752
jiangshaofeng@362 753 __ lw(AT, SSR, arrayOopDesc::length_offset_in_bytes()); //bound
jiangshaofeng@362 754 __ shl(AT, 2);
jiangshaofeng@362 755 __ dadd(AT, SSR, AT);
jiangshaofeng@362 756 __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(T_FLOAT));
aoqi@6880 757
jiangshaofeng@362 758 __ gslwlec1(FSF, FSR, AT);
jiangshaofeng@362 759 } else {
aoqi@6880 760 index_check(SSR, FSR);
jiangshaofeng@362 761 __ shl(FSR, 2);
fujie@6890 762 if (UseLoongsonISA && Assembler::is_simm(arrayOopDesc::base_offset_in_bytes(T_FLOAT), 8)) {
fujie@6890 763 __ gslwxc1(FSF, SSR, FSR, arrayOopDesc::base_offset_in_bytes(T_FLOAT));
fujie@6890 764 } else {
fujie@6890 765 __ dadd(FSR, SSR, FSR);
fujie@6890 766 __ lwc1(FSF, FSR, arrayOopDesc::base_offset_in_bytes(T_FLOAT));
fujie@6890 767 }
jiangshaofeng@362 768 }
aoqi@1 769 }
aoqi@1 770
aoqi@1 771 void TemplateTable::daload() {
jiangshaofeng@362 772 transition(itos, dtos);
jiangshaofeng@362 773 if(UseBoundCheckInstruction) {
jiangshaofeng@362 774 __ pop(SSR); //SSR:array FSR: index
jiangshaofeng@362 775 __ dsll(FSR, FSR, 3);
jiangshaofeng@362 776 __ dadd(FSR, SSR, FSR);
jiangshaofeng@362 777 __ addi(FSR, FSR, arrayOopDesc::base_offset_in_bytes(T_DOUBLE) + 0 * wordSize);
aoqi@6880 778
jiangshaofeng@362 779 __ lw(AT, SSR, arrayOopDesc::length_offset_in_bytes()); //bound
jiangshaofeng@362 780 __ dsll(AT, AT, 3);
jiangshaofeng@362 781 __ dadd(AT, SSR, AT);
jiangshaofeng@362 782 __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(T_DOUBLE) + 0 * wordSize);
aoqi@6880 783
jiangshaofeng@362 784 __ gsldlec1(FSF, FSR, AT);
jiangshaofeng@362 785 } else {
aoqi@6880 786 index_check(SSR, FSR);
jiangshaofeng@362 787 __ dsll(AT, FSR, 3);
fujie@6890 788 if (UseLoongsonISA && Assembler::is_simm(arrayOopDesc::base_offset_in_bytes(T_DOUBLE), 8)) {
fujie@6890 789 __ gsldxc1(FSF, SSR, AT, arrayOopDesc::base_offset_in_bytes(T_DOUBLE));
fujie@6890 790 } else {
fujie@6890 791 __ dadd(AT, SSR, AT);
fujie@6890 792 __ ldc1(FSF, AT, arrayOopDesc::base_offset_in_bytes(T_DOUBLE));
fujie@6890 793 }
jiangshaofeng@362 794 }
aoqi@1 795 }
aoqi@1 796
aoqi@1 797 void TemplateTable::aaload() {
aoqi@1 798 transition(itos, atos);
aoqi@1 799 index_check(SSR, FSR);
aoqi@1 800 __ dsll(FSR, FSR, UseCompressedOops ? Address::times_4 : Address::times_8);
aoqi@1 801 __ dadd(FSR, SSR, FSR);
aoqi@1 802 //add for compressedoops
aoqi@1 803 __ load_heap_oop(FSR, Address(FSR, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
aoqi@1 804 }
aoqi@1 805
aoqi@1 806 void TemplateTable::baload() {
aoqi@1 807 transition(itos, itos);
jiangshaofeng@362 808 if(UseBoundCheckInstruction) {
jiangshaofeng@362 809 __ pop(SSR); //SSR:array FSR:index
jiangshaofeng@362 810 __ dadd(FSR, SSR, FSR);
jiangshaofeng@362 811 __ addi(FSR, FSR, arrayOopDesc::base_offset_in_bytes(T_BYTE)); //base
jiangshaofeng@362 812
aoqi@6880 813 __ lw(AT, SSR, arrayOopDesc::length_offset_in_bytes());
jiangshaofeng@362 814 __ dadd(AT, SSR, AT);
jiangshaofeng@362 815 __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(T_BYTE)); //bound
jiangshaofeng@362 816
jiangshaofeng@362 817 __ gslble(FSR, FSR, AT);
jiangshaofeng@362 818 } else {
aoqi@6880 819 index_check(SSR, FSR);
fujie@6890 820 if (UseLoongsonISA && Assembler::is_simm(arrayOopDesc::base_offset_in_bytes(T_BYTE), 8)) {
fujie@6890 821 __ gslbx(FSR, SSR, FSR, arrayOopDesc::base_offset_in_bytes(T_BYTE));
fujie@6890 822 } else {
fujie@6890 823 __ dadd(FSR, SSR, FSR);
fujie@6890 824 __ lb(FSR, FSR, arrayOopDesc::base_offset_in_bytes(T_BYTE));
fujie@6890 825 }
jiangshaofeng@362 826 }
aoqi@1 827 }
aoqi@1 828
aoqi@1 829 void TemplateTable::caload() {
aoqi@1 830 transition(itos, itos);
aoqi@1 831 index_check(SSR, FSR);
aoqi@1 832 __ dsll(FSR, FSR, Address::times_2);
aoqi@1 833 __ dadd(FSR, SSR, FSR);
aoqi@1 834 __ lhu(FSR, FSR, arrayOopDesc::base_offset_in_bytes(T_CHAR));
aoqi@1 835 }
aoqi@1 836
aoqi@1 837 // iload followed by caload frequent pair
aoqi@1 838 // used register : T2
aoqi@1 839 // T2 : index
aoqi@1 840 void TemplateTable::fast_icaload() {
aoqi@1 841 transition(vtos, itos);
aoqi@1 842 // load index out of locals
aoqi@1 843 locals_index(T2);
aoqi@1 844 __ lw(FSR, T2, 0);
aoqi@1 845 index_check(SSR, FSR);
aoqi@1 846 __ dsll(FSR, FSR, 1);
aoqi@1 847 __ dadd(FSR, SSR, FSR);
aoqi@1 848 __ lhu(FSR, FSR, arrayOopDesc::base_offset_in_bytes(T_CHAR));
aoqi@1 849 }
aoqi@1 850
aoqi@1 851 void TemplateTable::saload() {
aoqi@1 852 transition(itos, itos);
jiangshaofeng@362 853 if(UseBoundCheckInstruction) {
jiangshaofeng@362 854 __ pop(SSR); //SSR:array FSR: index
jiangshaofeng@362 855 __ dsll(FSR, FSR, Address::times_2);
jiangshaofeng@362 856 __ dadd(FSR, SSR, FSR);
jiangshaofeng@362 857 __ addi(FSR, FSR, arrayOopDesc::base_offset_in_bytes(T_SHORT));
aoqi@6880 858
jiangshaofeng@362 859 __ lw(AT, SSR, arrayOopDesc::length_offset_in_bytes()); //bound
jiangshaofeng@362 860 __ dsll(AT, AT, Address::times_2);
jiangshaofeng@362 861 __ dadd(AT, SSR, AT);
jiangshaofeng@362 862 __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(T_SHORT));
aoqi@6880 863
aoqi@6880 864 __ gslhle(FSR, FSR, AT);
jiangshaofeng@362 865 } else {
aoqi@6880 866 index_check(SSR, FSR);
jiangshaofeng@362 867 __ dsll(FSR, FSR, Address::times_2);
fujie@6890 868 if (UseLoongsonISA && Assembler::is_simm(arrayOopDesc::base_offset_in_bytes(T_SHORT), 8)) {
fujie@6890 869 __ gslhx(FSR, SSR, FSR, arrayOopDesc::base_offset_in_bytes(T_SHORT));
fujie@6890 870 } else {
fujie@6890 871 __ dadd(FSR, SSR, FSR);
fujie@6890 872 __ lh(FSR, FSR, arrayOopDesc::base_offset_in_bytes(T_SHORT));
fujie@6890 873 }
jiangshaofeng@362 874 }
aoqi@1 875 }
aoqi@1 876
aoqi@1 877 void TemplateTable::iload(int n) {
aoqi@6880 878 transition(vtos, itos);
aoqi@6880 879 __ lw(FSR, iaddress(n));
aoqi@1 880 }
aoqi@1 881
aoqi@1 882 void TemplateTable::lload(int n) {
aoqi@6880 883 transition(vtos, ltos);
aoqi@6880 884 __ ld(FSR, laddress(n));
aoqi@1 885 }
aoqi@1 886
aoqi@1 887 void TemplateTable::fload(int n) {
aoqi@1 888 transition(vtos, ftos);
aoqi@1 889 __ lwc1(FSF, faddress(n));
aoqi@1 890 }
aoqi@6880 891
aoqi@1 892 void TemplateTable::dload(int n) {
aoqi@6880 893 transition(vtos, dtos);
aoqi@6880 894 __ ldc1(FSF, laddress(n));
aoqi@1 895 }
aoqi@1 896
aoqi@1 897 void TemplateTable::aload(int n) {
aoqi@1 898 transition(vtos, atos);
aoqi@1 899 __ ld(FSR, aaddress(n));
aoqi@1 900 }
aoqi@1 901
aoqi@1 902 // used register : T2, T3
aoqi@1 903 // T2 : bytecode
aoqi@1 904 // T3 : folded code
aoqi@1 905 void TemplateTable::aload_0() {
aoqi@6880 906 transition(vtos, atos);
aoqi@6880 907 // According to bytecode histograms, the pairs:
aoqi@6880 908 //
aoqi@6880 909 // _aload_0, _fast_igetfield
aoqi@6880 910 // _aload_0, _fast_agetfield
aoqi@6880 911 // _aload_0, _fast_fgetfield
aoqi@6880 912 //
aoqi@6880 913 // occur frequently. If RewriteFrequentPairs is set, the (slow)
aoqi@6880 914 // _aload_0 bytecode checks if the next bytecode is either
aoqi@6880 915 // _fast_igetfield, _fast_agetfield or _fast_fgetfield and then
aoqi@6880 916 // rewrites the current bytecode into a pair bytecode; otherwise it
aoqi@6880 917 // rewrites the current bytecode into _fast_aload_0 that doesn't do
aoqi@6880 918 // the pair check anymore.
aoqi@6880 919 //
aoqi@6880 920 // Note: If the next bytecode is _getfield, the rewrite must be
aoqi@6880 921 // delayed, otherwise we may miss an opportunity for a pair.
aoqi@6880 922 //
aoqi@6880 923 // Also rewrite frequent pairs
aoqi@6880 924 // aload_0, aload_1
aoqi@6880 925 // aload_0, iload_1
aoqi@6880 926 // These bytecodes with a small amount of code are most profitable
aoqi@6880 927 // to rewrite
aoqi@6880 928 if (RewriteFrequentPairs) {
aoqi@6880 929 Label rewrite, done;
aoqi@6880 930 // get the next bytecode in T2
aoqi@6880 931 __ lbu(T2, at_bcp(Bytecodes::length_for(Bytecodes::_aload_0)));
aoqi@6880 932
aoqi@6880 933 // do actual aload_0
aoqi@6880 934 aload(0);
aoqi@6880 935
aoqi@6880 936 // if _getfield then wait with rewrite
aoqi@6880 937 __ move(AT, Bytecodes::_getfield);
aoqi@6880 938 __ beq(AT, T2, done);
aoqi@6880 939 __ delayed()->nop();
aoqi@6880 940
aoqi@6880 941 // if _igetfield then reqrite to _fast_iaccess_0
aoqi@6880 942 assert(Bytecodes::java_code(Bytecodes::_fast_iaccess_0) ==
aoqi@6880 943 Bytecodes::_aload_0,
aoqi@6880 944 "fix bytecode definition");
aoqi@6880 945 __ move(T3, Bytecodes::_fast_iaccess_0);
aoqi@6880 946 __ move(AT, Bytecodes::_fast_igetfield);
aoqi@6880 947 __ beq(AT, T2, rewrite);
aoqi@6880 948 __ delayed()->nop();
aoqi@6880 949
aoqi@6880 950 // if _agetfield then reqrite to _fast_aaccess_0
aoqi@6880 951 assert(Bytecodes::java_code(Bytecodes::_fast_aaccess_0) ==
aoqi@6880 952 Bytecodes::_aload_0,
aoqi@6880 953 "fix bytecode definition");
aoqi@6880 954 __ move(T3, Bytecodes::_fast_aaccess_0);
aoqi@6880 955 __ move(AT, Bytecodes::_fast_agetfield);
aoqi@6880 956 __ beq(AT, T2, rewrite);
aoqi@6880 957 __ delayed()->nop();
aoqi@6880 958
aoqi@6880 959 // if _fgetfield then reqrite to _fast_faccess_0
aoqi@6880 960 assert(Bytecodes::java_code(Bytecodes::_fast_faccess_0) ==
aoqi@6880 961 Bytecodes::_aload_0,
aoqi@6880 962 "fix bytecode definition");
aoqi@6880 963 __ move(T3, Bytecodes::_fast_faccess_0);
aoqi@6880 964 __ move(AT, Bytecodes::_fast_fgetfield);
aoqi@6880 965 __ beq(AT, T2, rewrite);
aoqi@6880 966 __ delayed()->nop();
aoqi@6880 967
aoqi@6880 968 // else rewrite to _fast_aload0
aoqi@6880 969 assert(Bytecodes::java_code(Bytecodes::_fast_aload_0) ==
aoqi@6880 970 Bytecodes::_aload_0,
aoqi@6880 971 "fix bytecode definition");
aoqi@6880 972 __ move(T3, Bytecodes::_fast_aload_0);
aoqi@6880 973
aoqi@6880 974 // rewrite
aoqi@6880 975 __ bind(rewrite);
aoqi@6880 976 patch_bytecode(Bytecodes::_aload_0, T3, T2, false);
aoqi@6880 977
aoqi@6880 978 __ bind(done);
aoqi@6880 979 } else {
aoqi@6880 980 aload(0);
aoqi@6880 981 }
aoqi@1 982 }
aoqi@1 983
aoqi@1 984 void TemplateTable::istore() {
aoqi@6880 985 transition(itos, vtos);
aoqi@6880 986 locals_index(T2);
aoqi@6880 987 __ sw(FSR, T2, 0);
aoqi@1 988 }
aoqi@1 989
aoqi@1 990 void TemplateTable::lstore() {
aoqi@1 991 transition(ltos, vtos);
aoqi@1 992 locals_index(T2);
aoqi@1 993 __ sd(FSR, T2, -wordSize);
aoqi@1 994 }
aoqi@1 995
aoqi@1 996 void TemplateTable::fstore() {
aoqi@6880 997 transition(ftos, vtos);
aoqi@6880 998 locals_index(T2);
aoqi@6880 999 __ swc1(FSF, T2, 0);
aoqi@1 1000 }
aoqi@1 1001
aoqi@1 1002 void TemplateTable::dstore() {
aoqi@1 1003 transition(dtos, vtos);
aoqi@1 1004 locals_index(T2);
aoqi@1 1005 __ sdc1(FSF, T2, -wordSize);
aoqi@1 1006 }
aoqi@1 1007
aoqi@1 1008 void TemplateTable::astore() {
aoqi@1 1009 transition(vtos, vtos);
aoqi@1 1010 __ pop_ptr(FSR);
aoqi@1 1011 locals_index(T2);
aoqi@1 1012 __ sd(FSR, T2, 0);
aoqi@1 1013 }
aoqi@1 1014
aoqi@1 1015 void TemplateTable::wide_istore() {
aoqi@6880 1016 transition(vtos, vtos);
aoqi@6880 1017 __ pop_i(FSR);
aoqi@6880 1018 locals_index_wide(T2);
aoqi@6880 1019 __ sd(FSR, T2, 0);
aoqi@1 1020 }
aoqi@1 1021
aoqi@1 1022 void TemplateTable::wide_lstore() {
aoqi@6880 1023 transition(vtos, vtos);
aoqi@6880 1024 __ pop_l(FSR);
aoqi@6880 1025 locals_index_wide(T2);
wangxue@6881 1026 __ sd(FSR, T2, -wordSize);
aoqi@1 1027 }
aoqi@1 1028
aoqi@1 1029 void TemplateTable::wide_fstore() {
aoqi@6880 1030 wide_istore();
aoqi@1 1031 }
aoqi@1 1032
aoqi@1 1033 void TemplateTable::wide_dstore() {
aoqi@6880 1034 wide_lstore();
aoqi@1 1035 }
aoqi@1 1036
aoqi@1 1037 void TemplateTable::wide_astore() {
aoqi@6880 1038 transition(vtos, vtos);
aoqi@6880 1039 __ pop_ptr(FSR);
aoqi@6880 1040 locals_index_wide(T2);
aoqi@6880 1041 __ sd(FSR, T2, 0);
aoqi@1 1042 }
aoqi@1 1043
aoqi@1 1044 // used register : T2
aoqi@1 1045 void TemplateTable::iastore() {
aoqi@1 1046 transition(itos, vtos);
jiangshaofeng@362 1047 __ pop_i(SSR); // T2: array SSR: index
jiangshaofeng@362 1048 if(UseBoundCheckInstruction) {
aoqi@6880 1049 __ pop_ptr(T2);
jiangshaofeng@362 1050 __ dsll(SSR, SSR, Address::times_4);
jiangshaofeng@362 1051 __ dadd(SSR, T2, SSR);
jiangshaofeng@362 1052 __ addi(SSR, SSR, arrayOopDesc::base_offset_in_bytes(T_INT)); // base
aoqi@6880 1053
aoqi@6880 1054 __ lw(AT, T2, arrayOopDesc::length_offset_in_bytes());
jiangshaofeng@362 1055 __ dsll(AT, AT, Address::times_4);
jiangshaofeng@362 1056 __ dadd(AT, T2, AT);
jiangshaofeng@362 1057 __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(T_INT)); //bound
aoqi@6880 1058
jiangshaofeng@362 1059 __ gsswle(FSR, SSR, AT);
jiangshaofeng@362 1060 } else {
jiangshaofeng@362 1061 index_check(T2, SSR); // prefer index in ebx
jiangshaofeng@362 1062 __ dsll(SSR, SSR, Address::times_4);
fujie@6891 1063 if (UseLoongsonISA && Assembler::is_simm(arrayOopDesc::base_offset_in_bytes(T_INT), 8)) {
fujie@6891 1064 __ gsswx(FSR, T2, SSR, arrayOopDesc::base_offset_in_bytes(T_INT));
fujie@6891 1065 } else {
fujie@6891 1066 __ dadd(T2, T2, SSR);
fujie@6891 1067 __ sw(FSR, T2, arrayOopDesc::base_offset_in_bytes(T_INT));
fujie@6891 1068 }
jiangshaofeng@362 1069 }
aoqi@1 1070 }
aoqi@1 1071
aoqi@1 1072
aoqi@1 1073
aoqi@1 1074 // used register T2, T3
aoqi@1 1075 void TemplateTable::lastore() {
aoqi@1 1076 transition(ltos, vtos);
aoqi@1 1077 __ pop_i (T2);
jiangshaofeng@362 1078 if(UseBoundCheckInstruction) {
aoqi@6880 1079 __ pop_ptr(T3);
jiangshaofeng@362 1080 __ dsll(T2, T2, Address::times_8);
jiangshaofeng@362 1081 __ dadd(T2, T3, T2);
jiangshaofeng@362 1082 __ addi(T2, T2, arrayOopDesc::base_offset_in_bytes(T_LONG) + 0 * wordSize); // base
aoqi@6880 1083
aoqi@6880 1084 __ lw(AT, T3, arrayOopDesc::length_offset_in_bytes());
jiangshaofeng@362 1085 __ dsll(AT, AT, Address::times_8);
jiangshaofeng@362 1086 __ dadd(AT, T3, AT);
jiangshaofeng@362 1087 __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(T_LONG) + 0 * wordSize); //bound
aoqi@6880 1088
jiangshaofeng@362 1089 __ gssdle(FSR, T2, AT);
jiangshaofeng@362 1090 } else {
jiangshaofeng@362 1091 index_check(T3, T2);
jiangshaofeng@362 1092 __ dsll(T2, T2, Address::times_8);
fujie@6891 1093 if (UseLoongsonISA && Assembler::is_simm(arrayOopDesc::base_offset_in_bytes(T_LONG), 8)) {
fujie@6891 1094 __ gssdx(FSR, T3, T2, arrayOopDesc::base_offset_in_bytes(T_LONG));
fujie@6891 1095 } else {
fujie@6891 1096 __ dadd(T3, T3, T2);
fujie@6891 1097 __ sd(FSR, T3, arrayOopDesc::base_offset_in_bytes(T_LONG));
fujie@6891 1098 }
jiangshaofeng@362 1099 }
aoqi@1 1100 }
aoqi@1 1101
aoqi@1 1102 // used register T2
aoqi@1 1103 void TemplateTable::fastore() {
aoqi@1 1104 transition(ftos, vtos);
aoqi@6880 1105 __ pop_i(SSR);
jiangshaofeng@362 1106 if(UseBoundCheckInstruction) {
aoqi@6880 1107 __ pop_ptr(T2);
jiangshaofeng@362 1108 __ dsll(SSR, SSR, Address::times_4);
jiangshaofeng@362 1109 __ dadd(SSR, T2, SSR);
jiangshaofeng@362 1110 __ addi(SSR, SSR, arrayOopDesc::base_offset_in_bytes(T_FLOAT)); // base
aoqi@6880 1111
aoqi@6880 1112 __ lw(AT, T2, arrayOopDesc::length_offset_in_bytes());
jiangshaofeng@362 1113 __ dsll(AT, AT, Address::times_4);
jiangshaofeng@362 1114 __ dadd(AT, T2, AT);
jiangshaofeng@362 1115 __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(T_FLOAT)); //bound
aoqi@6880 1116
jiangshaofeng@362 1117 __ gsswlec1(FSF, SSR, AT);
jiangshaofeng@362 1118 } else {
aoqi@6880 1119 index_check(T2, SSR);
jiangshaofeng@362 1120 __ dsll(SSR, SSR, Address::times_4);
fujie@6891 1121 if (UseLoongsonISA && Assembler::is_simm(arrayOopDesc::base_offset_in_bytes(T_FLOAT), 8)) {
fujie@6891 1122 __ gsswxc1(FSF, T2, SSR, arrayOopDesc::base_offset_in_bytes(T_FLOAT));
fujie@6891 1123 } else {
fujie@6891 1124 __ dadd(T2, T2, SSR);
fujie@6891 1125 __ swc1(FSF, T2, arrayOopDesc::base_offset_in_bytes(T_FLOAT));
fujie@6891 1126 }
jiangshaofeng@362 1127 }
aoqi@1 1128 }
aoqi@1 1129
aoqi@1 1130 // used register T2, T3
aoqi@1 1131 void TemplateTable::dastore() {
aoqi@1 1132 transition(dtos, vtos);
aoqi@6880 1133 __ pop_i (T2);
jiangshaofeng@362 1134 if(UseBoundCheckInstruction) {
aoqi@6880 1135 __ pop_ptr(T3);
jiangshaofeng@362 1136 __ dsll(T2, T2, Address::times_8);
jiangshaofeng@362 1137 __ dadd(T2, T3, T2);
jiangshaofeng@362 1138 __ addi(T2, T2, arrayOopDesc::base_offset_in_bytes(T_DOUBLE) + 0 * wordSize); // base
aoqi@6880 1139
aoqi@6880 1140 __ lw(AT, T3, arrayOopDesc::length_offset_in_bytes());
jiangshaofeng@362 1141 __ dsll(AT, AT, Address::times_8);
jiangshaofeng@362 1142 __ dadd(AT, T3, AT);
jiangshaofeng@362 1143 __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(T_DOUBLE) + 0 * wordSize); //bound
aoqi@6880 1144
jiangshaofeng@362 1145 __ gssdlec1(FSF, T2, AT);
jiangshaofeng@362 1146 } else {
aoqi@6880 1147 index_check(T3, T2);
jiangshaofeng@362 1148 __ dsll(T2, T2, Address::times_8);
fujie@6891 1149 if (UseLoongsonISA && Assembler::is_simm(arrayOopDesc::base_offset_in_bytes(T_DOUBLE), 8)) {
fujie@6891 1150 __ gssdxc1(FSF, T3, T2, arrayOopDesc::base_offset_in_bytes(T_DOUBLE));
fujie@6891 1151 } else {
fujie@6891 1152 __ daddu(T3, T3, T2);
fujie@6891 1153 __ sdc1(FSF, T3, arrayOopDesc::base_offset_in_bytes(T_DOUBLE));
fujie@6891 1154 }
jiangshaofeng@362 1155 }
aoqi@1 1156 }
aoqi@1 1157
aoqi@1 1158 // used register : T2, T3, T8
aoqi@1 1159 // T2 : array
aoqi@1 1160 // T3 : subklass
aoqi@1 1161 // T8 : supklass
aoqi@1 1162 void TemplateTable::aastore() {
aoqi@1 1163 Label is_null, ok_is_subtype, done;
aoqi@1 1164 transition(vtos, vtos);
aoqi@1 1165 // stack: ..., array, index, value
aoqi@1 1166 __ ld(FSR, at_tos()); // Value
aoqi@1 1167 __ lw(SSR, at_tos_p1()); // Index
aoqi@1 1168 __ ld(T2, at_tos_p2()); // Array
aoqi@1 1169
aoqi@1 1170 // index_check(T2, SSR);
aoqi@1 1171 index_check_without_pop(T2, SSR);
aoqi@1 1172 // do array store check - check for NULL value first
aoqi@1 1173 __ beq(FSR, R0, is_null);
aoqi@1 1174 __ delayed()->nop();
aoqi@1 1175
aoqi@1 1176 // Move subklass into T3
aoqi@1 1177 //add for compressedoops
aoqi@1 1178 __ load_klass(T3, FSR);
aoqi@1 1179 // Move superklass into T8
aoqi@1 1180 //add for compressedoops
aoqi@1 1181 __ load_klass(T8, T2);
aoqi@1 1182 __ ld(T8, Address(T8, ObjArrayKlass::element_klass_offset()));
aoqi@1 1183 // Compress array+index*4+12 into a single register. T2
aoqi@1 1184 __ dsll(AT, SSR, UseCompressedOops? Address::times_4 : Address::times_8);
aoqi@1 1185 __ dadd(T2, T2, AT);
aoqi@1 1186 __ daddi(T2, T2, arrayOopDesc::base_offset_in_bytes(T_OBJECT));
aoqi@1 1187
aoqi@1 1188 // Generate subtype check.
aoqi@1 1189 // Superklass in T8. Subklass in T3.
aoqi@6880 1190 __ gen_subtype_check(T8, T3, ok_is_subtype); // <-- Jin
aoqi@1 1191 // Come here on failure
aoqi@1 1192 // object is at FSR
aoqi@1 1193 __ jmp(Interpreter::_throw_ArrayStoreException_entry); // <-- Jin
aoqi@1 1194 __ delayed()->nop();
aoqi@1 1195 // Come here on success
aoqi@1 1196 __ bind(ok_is_subtype);
aoqi@1 1197 //replace with do_oop_store->store_heap_oop
aoqi@6880 1198 __ store_heap_oop(Address(T2, 0), FSR); // <-- Jin
aoqi@1 1199 __ store_check(T2);
aoqi@1 1200 __ b(done);
aoqi@1 1201 __ delayed()->nop();
aoqi@1 1202
aoqi@1 1203 // Have a NULL in FSR, EDX=T2, SSR=index. Store NULL at ary[idx]
aoqi@1 1204 __ bind(is_null);
aoqi@1 1205 __ profile_null_seen(T9);
aoqi@1 1206 __ dsll(AT, SSR, UseCompressedOops? Address::times_4 : Address::times_8);
aoqi@1 1207 __ dadd(T2, T2, AT);
aoqi@6880 1208 __ store_heap_oop(Address(T2, arrayOopDesc::base_offset_in_bytes(T_OBJECT)), FSR); /* FSR is null here */
aoqi@1 1209
aoqi@1 1210 __ bind(done);
aoqi@1 1211 __ daddi(SP, SP, 3 * Interpreter::stackElementSize);
aoqi@1 1212 }
aoqi@1 1213
aoqi@1 1214 void TemplateTable::bastore() {
aoqi@1 1215 transition(itos, vtos);
aoqi@6880 1216 __ pop_i(SSR);
jiangshaofeng@362 1217 if(UseBoundCheckInstruction) {
aoqi@6880 1218 __ pop_ptr(T2);
jiangshaofeng@362 1219 __ dadd(SSR, T2, SSR);
jiangshaofeng@362 1220 __ addi(SSR, SSR, arrayOopDesc::base_offset_in_bytes(T_BYTE)); // base
aoqi@6880 1221
aoqi@6880 1222 __ lw(AT, T2, arrayOopDesc::length_offset_in_bytes());
jiangshaofeng@362 1223 __ dadd(AT, T2, AT);
jiangshaofeng@362 1224 __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(T_BYTE)); //bound
aoqi@6880 1225
jiangshaofeng@362 1226 __ gssble(FSR, SSR, AT);
jiangshaofeng@362 1227 } else {
jiangshaofeng@362 1228 index_check(T2, SSR);
fujie@6891 1229 if (UseLoongsonISA && Assembler::is_simm(arrayOopDesc::base_offset_in_bytes(T_BYTE), 8)) {
fujie@6891 1230 __ gssbx(FSR, T2, SSR, arrayOopDesc::base_offset_in_bytes(T_BYTE));
fujie@6891 1231 } else {
fujie@6891 1232 __ dadd(SSR, T2, SSR);
fujie@6891 1233 __ sb(FSR, SSR, arrayOopDesc::base_offset_in_bytes(T_BYTE));
fujie@6891 1234 }
jiangshaofeng@362 1235 }
aoqi@1 1236 }
aoqi@1 1237
aoqi@1 1238 void TemplateTable::castore() {
aoqi@1 1239 transition(itos, vtos);
aoqi@6880 1240 __ pop_i(SSR);
jiangshaofeng@362 1241 if(UseBoundCheckInstruction) {
aoqi@6880 1242 __ pop_ptr(T2);
jiangshaofeng@362 1243 __ dsll(SSR, SSR, Address::times_2);
jiangshaofeng@362 1244 __ dadd(SSR, T2, SSR);
jiangshaofeng@362 1245 __ addi(SSR, SSR, arrayOopDesc::base_offset_in_bytes(T_CHAR)); // base
aoqi@6880 1246
aoqi@6880 1247 __ lw(AT, T2, arrayOopDesc::length_offset_in_bytes());
jiangshaofeng@362 1248 __ dsll(AT, AT, Address::times_2);
jiangshaofeng@362 1249 __ dadd(AT, T2, AT);
jiangshaofeng@362 1250 __ addi(AT, AT, arrayOopDesc::base_offset_in_bytes(T_CHAR)); //bound
aoqi@6880 1251
jiangshaofeng@362 1252 __ gsshle(FSR, SSR, AT);
jiangshaofeng@362 1253 } else {
aoqi@6880 1254 index_check(T2, SSR);
jiangshaofeng@362 1255 __ dsll(SSR, SSR, Address::times_2);
fujie@6891 1256 if (UseLoongsonISA && Assembler::is_simm(arrayOopDesc::base_offset_in_bytes(T_CHAR), 8)) {
fujie@6891 1257 __ gsshx(FSR, T2, SSR, arrayOopDesc::base_offset_in_bytes(T_CHAR));
fujie@6891 1258 } else {
fujie@6891 1259 __ dadd(SSR, T2, SSR);
fujie@6891 1260 __ sh(FSR, SSR, arrayOopDesc::base_offset_in_bytes(T_CHAR));
fujie@6891 1261 }
jiangshaofeng@362 1262 }
aoqi@1 1263 }
aoqi@1 1264
aoqi@1 1265 void TemplateTable::sastore() {
aoqi@1 1266 castore();
aoqi@1 1267 }
aoqi@1 1268
aoqi@1 1269 void TemplateTable::istore(int n) {
aoqi@1 1270 transition(itos, vtos);
aoqi@1 1271 __ sw(FSR, iaddress(n));
aoqi@1 1272 }
aoqi@1 1273
aoqi@1 1274 void TemplateTable::lstore(int n) {
aoqi@1 1275 transition(ltos, vtos);
aoqi@1 1276 __ sd(FSR, laddress(n));
aoqi@1 1277 }
aoqi@1 1278
aoqi@1 1279 void TemplateTable::fstore(int n) {
aoqi@1 1280 transition(ftos, vtos);
aoqi@1 1281 __ swc1(FSF, faddress(n));
aoqi@1 1282 }
aoqi@1 1283
aoqi@1 1284 void TemplateTable::dstore(int n) {
aoqi@1 1285 transition(dtos, vtos);
aoqi@1 1286 __ sdc1(FSF, laddress(n));
aoqi@1 1287 }
aoqi@1 1288
aoqi@1 1289 void TemplateTable::astore(int n) {
aoqi@1 1290 transition(vtos, vtos);
aoqi@1 1291 __ pop_ptr(FSR);
aoqi@1 1292 __ sd(FSR, aaddress(n));
aoqi@1 1293 }
aoqi@1 1294
aoqi@1 1295 void TemplateTable::pop() {
aoqi@1 1296 transition(vtos, vtos);
aoqi@1 1297 __ daddi(SP, SP, Interpreter::stackElementSize);
aoqi@1 1298 }
aoqi@1 1299
aoqi@1 1300 void TemplateTable::pop2() {
aoqi@1 1301 transition(vtos, vtos);
aoqi@1 1302 __ daddi(SP, SP, 2 * Interpreter::stackElementSize);
aoqi@1 1303 }
aoqi@1 1304
aoqi@1 1305 void TemplateTable::dup() {
aoqi@1 1306 transition(vtos, vtos);
aoqi@1 1307 // stack: ..., a
aoqi@1 1308 __ load_ptr(0, FSR);
aoqi@1 1309 __ push_ptr(FSR);
aoqi@1 1310 // stack: ..., a, a
aoqi@1 1311 }
aoqi@1 1312
aoqi@1 1313 // blows FSR
aoqi@1 1314 void TemplateTable::dup_x1() {
aoqi@6880 1315 transition(vtos, vtos);
aoqi@6880 1316 // stack: ..., a, b
aoqi@6880 1317 __ load_ptr(0, FSR); // load b
aoqi@6880 1318 __ load_ptr(1, A5); // load a
aoqi@6880 1319 __ store_ptr(1, FSR); // store b
aoqi@6880 1320 __ store_ptr(0, A5); // store a
aoqi@6880 1321 __ push_ptr(FSR); // push b
aoqi@6880 1322 // stack: ..., b, a, b
aoqi@1 1323 }
aoqi@1 1324
aoqi@1 1325 // blows FSR
aoqi@1 1326 void TemplateTable::dup_x2() {
aoqi@6880 1327 transition(vtos, vtos);
aoqi@6880 1328 // stack: ..., a, b, c
aoqi@6880 1329 __ load_ptr(0, FSR); // load c
aoqi@6880 1330 __ load_ptr(2, A5); // load a
aoqi@6880 1331 __ store_ptr(2, FSR); // store c in a
aoqi@6880 1332 __ push_ptr(FSR); // push c
aoqi@6880 1333 // stack: ..., c, b, c, c
aoqi@6880 1334 __ load_ptr(2, FSR); // load b
aoqi@6880 1335 __ store_ptr(2, A5); // store a in b
aoqi@6880 1336 // stack: ..., c, a, c, c
aoqi@6880 1337 __ store_ptr(1, FSR); // store b in c
aoqi@6880 1338 // stack: ..., c, a, b, c
aoqi@1 1339 }
aoqi@1 1340
aoqi@1 1341 // blows FSR
aoqi@1 1342 void TemplateTable::dup2() {
aoqi@6880 1343 transition(vtos, vtos);
aoqi@6880 1344 // stack: ..., a, b
aoqi@6880 1345 __ load_ptr(1, FSR); // load a
aoqi@6880 1346 __ push_ptr(FSR); // push a
aoqi@6880 1347 __ load_ptr(1, FSR); // load b
aoqi@6880 1348 __ push_ptr(FSR); // push b
aoqi@6880 1349 // stack: ..., a, b, a, b
aoqi@1 1350 }
aoqi@1 1351
aoqi@1 1352 // blows FSR
aoqi@1 1353 void TemplateTable::dup2_x1() {
aoqi@6880 1354 transition(vtos, vtos);
aoqi@6880 1355 // stack: ..., a, b, c
aoqi@6880 1356 __ load_ptr(0, T2); // load c
aoqi@6880 1357 __ load_ptr(1, FSR); // load b
aoqi@6880 1358 __ push_ptr(FSR); // push b
aoqi@6880 1359 __ push_ptr(T2); // push c
aoqi@6880 1360 // stack: ..., a, b, c, b, c
aoqi@6880 1361 __ store_ptr(3, T2); // store c in b
aoqi@6880 1362 // stack: ..., a, c, c, b, c
aoqi@6880 1363 __ load_ptr(4, T2); // load a
aoqi@6880 1364 __ store_ptr(2, T2); // store a in 2nd c
aoqi@6880 1365 // stack: ..., a, c, a, b, c
aoqi@6880 1366 __ store_ptr(4, FSR); // store b in a
aoqi@6880 1367 // stack: ..., b, c, a, b, c
aoqi@6880 1368
aoqi@6880 1369 // stack: ..., b, c, a, b, c
aoqi@1 1370 }
aoqi@1 1371
aoqi@1 1372 // blows FSR, SSR
aoqi@1 1373 void TemplateTable::dup2_x2() {
aoqi@6880 1374 transition(vtos, vtos);
aoqi@6880 1375 // stack: ..., a, b, c, d
aoqi@6880 1376 // stack: ..., a, b, c, d
aoqi@6880 1377 __ load_ptr(0, T2); // load d
aoqi@6880 1378 __ load_ptr(1, FSR); // load c
aoqi@6880 1379 __ push_ptr(FSR); // push c
aoqi@6880 1380 __ push_ptr(T2); // push d
aoqi@6880 1381 // stack: ..., a, b, c, d, c, d
aoqi@6880 1382 __ load_ptr(4, FSR); // load b
aoqi@6880 1383 __ store_ptr(2, FSR); // store b in d
aoqi@6880 1384 __ store_ptr(4, T2); // store d in b
aoqi@6880 1385 // stack: ..., a, d, c, b, c, d
aoqi@6880 1386 __ load_ptr(5, T2); // load a
aoqi@6880 1387 __ load_ptr(3, FSR); // load c
aoqi@6880 1388 __ store_ptr(3, T2); // store a in c
aoqi@6880 1389 __ store_ptr(5, FSR); // store c in a
aoqi@6880 1390 // stack: ..., c, d, a, b, c, d
aoqi@6880 1391
aoqi@6880 1392 // stack: ..., c, d, a, b, c, d
aoqi@1 1393 }
aoqi@1 1394
aoqi@1 1395 // blows FSR
aoqi@1 1396 void TemplateTable::swap() {
aoqi@6880 1397 transition(vtos, vtos);
aoqi@6880 1398 // stack: ..., a, b
aoqi@6880 1399
aoqi@6880 1400 __ load_ptr(1, A5); // load a
aoqi@6880 1401 __ load_ptr(0, FSR); // load b
aoqi@6880 1402 __ store_ptr(0, A5); // store a in b
aoqi@6880 1403 __ store_ptr(1, FSR); // store b in a
aoqi@6880 1404
aoqi@6880 1405 // stack: ..., b, a
aoqi@1 1406 }
aoqi@1 1407
aoqi@1 1408 void TemplateTable::iop2(Operation op) {
aoqi@6880 1409 transition(itos, itos);
fujie@6887 1410
fujie@6887 1411 __ pop_i(SSR);
aoqi@6880 1412 switch (op) {
fujie@6887 1413 case add : __ addu32(FSR, SSR, FSR); break;
fujie@6887 1414 case sub : __ subu32(FSR, SSR, FSR); break;
fujie@6887 1415 case mul : __ mul(FSR, SSR, FSR); break;
fujie@6887 1416 case _and : __ andr(FSR, SSR, FSR); break;
fujie@6887 1417 case _or : __ orr(FSR, SSR, FSR); break;
fujie@6887 1418 case _xor : __ xorr(FSR, SSR, FSR); break;
fujie@6887 1419 case shl : __ sllv(FSR, SSR, FSR); break; // implicit masking of lower 5 bits by Intel shift instr. mips also
fujie@6887 1420 case shr : __ srav(FSR, SSR, FSR); break; // implicit masking of lower 5 bits by Intel shift instr. mips also
fujie@6887 1421 case ushr : __ srlv(FSR, SSR, FSR); break; // implicit masking of lower 5 bits by Intel shift instr. mips also
aoqi@6880 1422 default : ShouldNotReachHere();
aoqi@6880 1423 }
aoqi@1 1424 }
aoqi@1 1425
aoqi@1 1426 // the result stored in FSR, SSR,
aoqi@1 1427 // used registers : T2, T3
aoqi@1 1428 void TemplateTable::lop2(Operation op) {
aoqi@1 1429 transition(ltos, ltos);
fujie@6893 1430 __ pop_l(T2);
fujie@6893 1431
aoqi@1 1432 switch (op) {
fujie@6887 1433 case add : __ daddu(FSR, T2, FSR); break;
fujie@6887 1434 case sub : __ dsubu(FSR, T2, FSR); break;
fujie@6887 1435 case _and: __ andr(FSR, T2, FSR); break;
fujie@6887 1436 case _or : __ orr(FSR, T2, FSR); break;
fujie@6887 1437 case _xor: __ xorr(FSR, T2, FSR); break;
aoqi@1 1438 default : ShouldNotReachHere();
aoqi@1 1439 }
aoqi@1 1440 }
aoqi@1 1441
aoqi@6880 1442 // java require this bytecode could handle 0x80000000/-1, dont cause a overflow exception,
aoqi@1 1443 // the result is 0x80000000
aoqi@1 1444 // the godson2 cpu do the same, so we need not handle this specially like x86
aoqi@1 1445 void TemplateTable::idiv() {
aoqi@6880 1446 transition(itos, itos);
aoqi@6880 1447 Label not_zero;
aoqi@6880 1448
aoqi@6880 1449 __ bne(FSR, R0, not_zero);
aoqi@6880 1450 __ delayed()->nop();
aoqi@6880 1451 __ jmp(Interpreter::_throw_ArithmeticException_entry);
aoqi@6880 1452 __ delayed()->nop();
aoqi@6880 1453 __ bind(not_zero);
aoqi@6880 1454
aoqi@6880 1455 __ pop_i(SSR);
aoqi@6880 1456 if (UseLoongsonISA) {
aoqi@6880 1457 __ gsdiv(FSR, SSR, FSR);
aoqi@6880 1458 } else {
aoqi@6880 1459 __ div(SSR, FSR);
aoqi@6880 1460 __ mflo(FSR);
aoqi@6880 1461 }
aoqi@1 1462 }
aoqi@1 1463
aoqi@1 1464 void TemplateTable::irem() {
aoqi@6880 1465 transition(itos, itos);
aoqi@6880 1466 Label not_zero;
aoqi@6880 1467 __ pop_i(SSR);
aoqi@6880 1468 __ div(SSR, FSR);
aoqi@6880 1469
aoqi@6880 1470 __ bne(FSR, R0, not_zero);
aoqi@6880 1471 __ delayed()->nop();
aoqi@6880 1472 //__ brk(7);
aoqi@6880 1473 __ jmp(Interpreter::_throw_ArithmeticException_entry);
aoqi@6880 1474 __ delayed()->nop();
aoqi@6880 1475
aoqi@6880 1476 __ bind(not_zero);
aoqi@6880 1477 __ mfhi(FSR);
aoqi@1 1478 }
aoqi@1 1479
aoqi@1 1480 void TemplateTable::lmul() {
aoqi@1 1481 transition(ltos, ltos);
jiangshaofeng@89 1482 __ pop_l(T2);
jiangshaofeng@89 1483 if(UseLoongsonISA){
jiangshaofeng@89 1484 __ gsdmult(FSR, T2, FSR);
jiangshaofeng@89 1485 } else {
aoqi@6880 1486 __ dmult(T2, FSR);
aoqi@6880 1487 __ mflo(FSR);
aoqi@6880 1488 }
aoqi@6880 1489 }
aoqi@1 1490
aoqi@1 1491 // NOTE: i DONT use the Interpreter::_throw_ArithmeticException_entry
aoqi@1 1492 void TemplateTable::ldiv() {
aoqi@1 1493 transition(ltos, ltos);
aoqi@1 1494 Label normal;
aoqi@1 1495
aoqi@1 1496 __ bne(FSR, R0, normal);
aoqi@1 1497 __ delayed()->nop();
aoqi@1 1498
aoqi@6880 1499 //__ brk(7); //generate FPE
aoqi@1 1500 __ jmp(Interpreter::_throw_ArithmeticException_entry);
aoqi@1 1501 __ delayed()->nop();
aoqi@1 1502
aoqi@1 1503 __ bind(normal);
fujie@6893 1504 __ pop_l(A2);
chenhaoxuan@87 1505 if (UseLoongsonISA) {
aoqi@6880 1506 __ gsddiv(FSR, A2, FSR);
chenhaoxuan@87 1507 } else {
chenhaoxuan@87 1508 __ ddiv(A2, FSR);
chenhaoxuan@87 1509 __ mflo(FSR);
chenhaoxuan@87 1510 }
aoqi@1 1511 }
aoqi@1 1512
aoqi@1 1513 // NOTE: i DONT use the Interpreter::_throw_ArithmeticException_entry
aoqi@1 1514 void TemplateTable::lrem() {
aoqi@1 1515 transition(ltos, ltos);
aoqi@1 1516 Label normal;
aoqi@1 1517
aoqi@1 1518 __ bne(FSR, R0, normal);
aoqi@1 1519 __ delayed()->nop();
aoqi@1 1520
aoqi@1 1521 __ jmp(Interpreter::_throw_ArithmeticException_entry);
aoqi@1 1522 __ delayed()->nop();
aoqi@1 1523
aoqi@1 1524 __ bind(normal);
fujie@6893 1525 __ pop_l (A2);
lifangyuan@88 1526
lifangyuan@88 1527 if(UseLoongsonISA){
lifangyuan@88 1528 __ gsdmod(FSR, A2, FSR);
aoqi@6880 1529 } else {
lifangyuan@88 1530 __ ddiv(A2, FSR);
lifangyuan@88 1531 __ mfhi(FSR);
lifangyuan@88 1532 }
aoqi@1 1533 }
aoqi@1 1534
aoqi@1 1535 // result in FSR
aoqi@1 1536 // used registers : T0
aoqi@1 1537 void TemplateTable::lshl() {
aoqi@1 1538 transition(itos, ltos);
fujie@6893 1539 __ pop_l(T0);
aoqi@1 1540 __ dsllv(FSR, T0, FSR);
aoqi@1 1541 }
aoqi@1 1542
aoqi@1 1543 // used registers : T0
aoqi@1 1544 void TemplateTable::lshr() {
aoqi@1 1545 transition(itos, ltos);
fujie@6893 1546 __ pop_l(T0);
aoqi@1 1547 __ dsrav(FSR, T0, FSR);
aoqi@1 1548 }
aoqi@1 1549
aoqi@1 1550 // used registers : T0
aoqi@1 1551 void TemplateTable::lushr() {
aoqi@1 1552 transition(itos, ltos);
fujie@6893 1553 __ pop_l(T0);
aoqi@1 1554 __ dsrlv(FSR, T0, FSR);
aoqi@1 1555 }
aoqi@1 1556
aoqi@1 1557 // result in FSF
aoqi@1 1558 void TemplateTable::fop2(Operation op) {
aoqi@6880 1559 transition(ftos, ftos);
aoqi@6880 1560 switch (op) {
aoqi@6880 1561 case add:
aoqi@6880 1562 __ lwc1(FTF, at_sp());
aoqi@6880 1563 __ add_s(FSF, FTF, FSF);
aoqi@6880 1564 break;
aoqi@6880 1565 case sub:
aoqi@6880 1566 __ lwc1(FTF, at_sp());
aoqi@6880 1567 __ sub_s(FSF, FTF, FSF);
aoqi@6880 1568 break;
aoqi@6880 1569 case mul:
aoqi@6880 1570 __ lwc1(FTF, at_sp());
aoqi@6880 1571 __ mul_s(FSF, FTF, FSF);
aoqi@6880 1572 break;
aoqi@6880 1573 case div:
aoqi@6880 1574 __ lwc1(FTF, at_sp());
aoqi@6880 1575 __ div_s(FSF, FTF, FSF);
aoqi@6880 1576 break;
aoqi@6880 1577 case rem:
aoqi@6880 1578 __ mov_s(F13, FSF);
aoqi@6880 1579 __ lwc1(F12, at_sp());
aoqi@6880 1580 __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::frem), 2);
aoqi@6880 1581 break;
aoqi@6880 1582 default : ShouldNotReachHere();
aoqi@6880 1583 }
aoqi@6880 1584
aoqi@6880 1585 __ daddi(SP, SP, 1 * wordSize);
aoqi@1 1586 }
aoqi@1 1587
aoqi@1 1588 // result in SSF||FSF
aoqi@1 1589 // i dont handle the strict flags
aoqi@1 1590 void TemplateTable::dop2(Operation op) {
aoqi@6880 1591 transition(dtos, dtos);
aoqi@6880 1592 switch (op) {
aoqi@6880 1593 case add:
aoqi@6880 1594 __ ldc1(FTF, at_sp());
aoqi@6880 1595 __ add_d(FSF, FTF, FSF);
aoqi@6880 1596 break;
aoqi@6880 1597 case sub:
aoqi@6880 1598 __ ldc1(FTF, at_sp());
aoqi@6880 1599 __ sub_d(FSF, FTF, FSF);
aoqi@6880 1600 break;
aoqi@6880 1601 case mul:
aoqi@6880 1602 __ ldc1(FTF, at_sp());
aoqi@6880 1603 __ mul_d(FSF, FTF, FSF);
aoqi@6880 1604 break;
aoqi@6880 1605 case div:
aoqi@6880 1606 __ ldc1(FTF, at_sp());
aoqi@6880 1607 __ div_d(FSF, FTF, FSF);
aoqi@6880 1608 break;
aoqi@6880 1609 case rem:
aoqi@6880 1610 __ mov_d(F13, FSF);
aoqi@6880 1611 __ ldc1(F12, at_sp());
aoqi@6880 1612 __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::drem), 2);
aoqi@6880 1613 break;
aoqi@6880 1614 default : ShouldNotReachHere();
aoqi@6880 1615 }
aoqi@6880 1616
aoqi@6880 1617 __ daddi(SP, SP, 2 * wordSize);
aoqi@1 1618 }
aoqi@1 1619
aoqi@1 1620 void TemplateTable::ineg() {
aoqi@6880 1621 transition(itos, itos);
wangxue@7998 1622 __ subu32(FSR, R0, FSR);
aoqi@1 1623 }
aoqi@1 1624
aoqi@1 1625 void TemplateTable::lneg() {
aoqi@6880 1626 transition(ltos, ltos);
aoqi@6880 1627 __ dsubu(FSR, R0, FSR);
aoqi@1 1628 }
aoqi@6880 1629
aoqi@6880 1630 void TemplateTable::fneg() {
aoqi@6880 1631 transition(ftos, ftos);
aoqi@6880 1632 __ neg_s(FSF, FSF);
aoqi@1 1633 }
aoqi@1 1634
aoqi@1 1635 void TemplateTable::dneg() {
aoqi@6880 1636 transition(dtos, dtos);
aoqi@6880 1637 __ neg_d(FSF, FSF);
aoqi@1 1638 }
aoqi@1 1639
aoqi@1 1640 // used registers : T2
aoqi@1 1641 void TemplateTable::iinc() {
aoqi@6880 1642 transition(vtos, vtos);
aoqi@6880 1643 locals_index(T2);
aoqi@6880 1644 __ lw(FSR, T2, 0);
aoqi@6880 1645 __ lb(AT, at_bcp(2)); // get constant
aoqi@6880 1646 __ daddu(FSR, FSR, AT);
aoqi@6880 1647 __ sw(FSR, T2, 0);
aoqi@1 1648 }
aoqi@1 1649
aoqi@1 1650 // used register : T2
aoqi@1 1651 void TemplateTable::wide_iinc() {
aoqi@6880 1652 transition(vtos, vtos);
aoqi@6880 1653 locals_index_wide(T2);
aoqi@6880 1654 __ get_2_byte_integer_at_bcp(FSR, AT, 4);
aoqi@6880 1655 __ hswap(FSR);
aoqi@6880 1656 __ lw(AT, T2, 0);
aoqi@6880 1657 __ daddu(FSR, AT, FSR);
aoqi@6880 1658 __ sw(FSR, T2, 0);
aoqi@1 1659 }
aoqi@1 1660
aoqi@1 1661 void TemplateTable::convert() {
aoqi@1 1662 // Checking
aoqi@1 1663 #ifdef ASSERT
aoqi@6880 1664 {
aoqi@6880 1665 TosState tos_in = ilgl;
aoqi@1 1666 TosState tos_out = ilgl;
aoqi@1 1667 switch (bytecode()) {
aoqi@1 1668 case Bytecodes::_i2l: // fall through
aoqi@1 1669 case Bytecodes::_i2f: // fall through
aoqi@1 1670 case Bytecodes::_i2d: // fall through
aoqi@1 1671 case Bytecodes::_i2b: // fall through
aoqi@1 1672 case Bytecodes::_i2c: // fall through
aoqi@1 1673 case Bytecodes::_i2s: tos_in = itos; break;
aoqi@1 1674 case Bytecodes::_l2i: // fall through
aoqi@1 1675 case Bytecodes::_l2f: // fall through
aoqi@1 1676 case Bytecodes::_l2d: tos_in = ltos; break;
aoqi@1 1677 case Bytecodes::_f2i: // fall through
aoqi@1 1678 case Bytecodes::_f2l: // fall through
aoqi@1 1679 case Bytecodes::_f2d: tos_in = ftos; break;
aoqi@1 1680 case Bytecodes::_d2i: // fall through
aoqi@1 1681 case Bytecodes::_d2l: // fall through
aoqi@1 1682 case Bytecodes::_d2f: tos_in = dtos; break;
aoqi@1 1683 default : ShouldNotReachHere();
aoqi@1 1684 }
aoqi@1 1685 switch (bytecode()) {
aoqi@1 1686 case Bytecodes::_l2i: // fall through
aoqi@1 1687 case Bytecodes::_f2i: // fall through
aoqi@1 1688 case Bytecodes::_d2i: // fall through
aoqi@1 1689 case Bytecodes::_i2b: // fall through
aoqi@1 1690 case Bytecodes::_i2c: // fall through
aoqi@1 1691 case Bytecodes::_i2s: tos_out = itos; break;
aoqi@1 1692 case Bytecodes::_i2l: // fall through
aoqi@1 1693 case Bytecodes::_f2l: // fall through
aoqi@1 1694 case Bytecodes::_d2l: tos_out = ltos; break;
aoqi@1 1695 case Bytecodes::_i2f: // fall through
aoqi@1 1696 case Bytecodes::_l2f: // fall through
aoqi@1 1697 case Bytecodes::_d2f: tos_out = ftos; break;
aoqi@1 1698 case Bytecodes::_i2d: // fall through
aoqi@1 1699 case Bytecodes::_l2d: // fall through
aoqi@1 1700 case Bytecodes::_f2d: tos_out = dtos; break;
aoqi@1 1701 default : ShouldNotReachHere();
aoqi@1 1702 }
aoqi@1 1703 transition(tos_in, tos_out);
aoqi@1 1704 }
aoqi@1 1705 #endif // ASSERT
aoqi@1 1706
aoqi@1 1707 // Conversion
aoqi@1 1708 // (Note: use pushl(ecx)/popl(ecx) for 1/2-word stack-ptr manipulation)
aoqi@1 1709 switch (bytecode()) {
aoqi@1 1710 case Bytecodes::_i2l:
aoqi@1 1711 __ sll(FSR, FSR, 0);
aoqi@1 1712 break;
aoqi@1 1713 case Bytecodes::_i2f:
aoqi@1 1714 __ mtc1(FSR, FSF);
aoqi@1 1715 __ cvt_s_w(FSF, FSF);
aoqi@1 1716 break;
aoqi@1 1717 case Bytecodes::_i2d:
aoqi@1 1718 __ mtc1(FSR, FSF);
aoqi@1 1719 __ cvt_d_w(FSF, FSF);
aoqi@1 1720 break;
aoqi@1 1721 case Bytecodes::_i2b:
fujie@256 1722 __ seb(FSR, FSR);
aoqi@1 1723 break;
aoqi@1 1724 case Bytecodes::_i2c:
aoqi@1 1725 __ andi(FSR, FSR, 0xFFFF); // truncate upper 56 bits
aoqi@1 1726 break;
aoqi@1 1727 case Bytecodes::_i2s:
fujie@256 1728 __ seh(FSR, FSR);
aoqi@1 1729 break;
aoqi@1 1730 case Bytecodes::_l2i:
fujie@257 1731 __ sll(FSR, FSR, 0);
aoqi@1 1732 break;
aoqi@1 1733 case Bytecodes::_l2f:
aoqi@1 1734 __ dmtc1(FSR, FSF);
aoqi@1 1735 __ cvt_s_l(FSF, FSF);
aoqi@1 1736 break;
aoqi@1 1737 case Bytecodes::_l2d:
aoqi@1 1738 __ dmtc1(FSR, FSF);
aoqi@1 1739 __ cvt_d_l(FSF, FSF);
aoqi@1 1740 break;
aoqi@1 1741 case Bytecodes::_f2i:
aoqi@6880 1742 {
aoqi@6880 1743 Label L;
aoqi@6880 1744
aoqi@6880 1745 __ trunc_w_s(F12, FSF);
aoqi@6880 1746 __ move(AT, 0x7fffffff);
aoqi@6880 1747 __ mfc1(FSR, F12);
aoqi@6880 1748 __ c_un_s(FSF, FSF); //NaN?
aoqi@6880 1749 __ movt(FSR, R0);
aoqi@6880 1750
aoqi@6880 1751 __ bne(AT, FSR, L);
aoqi@6880 1752 __ delayed()->lui(T9, 0x8000);
aoqi@6880 1753
aoqi@6880 1754 __ mfc1(AT, FSF);
aoqi@6880 1755 __ andr(AT, AT, T9);
aoqi@6880 1756
aoqi@6880 1757 __ movn(FSR, T9, AT);
aoqi@6880 1758
aoqi@6880 1759 __ bind(L);
aoqi@6880 1760 }
aoqi@1 1761 break;
aoqi@1 1762 case Bytecodes::_f2l:
aoqi@6880 1763 {
aoqi@6880 1764 Label L;
aoqi@6880 1765
aoqi@6880 1766 __ trunc_l_s(F12, FSF);
aoqi@6880 1767 __ daddiu(AT, R0, -1);
aoqi@6880 1768 __ dsrl(AT, AT, 1);
aoqi@6880 1769 __ dmfc1(FSR, F12);
aoqi@6880 1770 __ c_un_s(FSF, FSF); //NaN?
aoqi@6880 1771 __ movt(FSR, R0);
aoqi@6880 1772
aoqi@6880 1773 __ bne(AT, FSR, L);
aoqi@6880 1774 __ delayed()->lui(T9, 0x8000);
aoqi@6880 1775
aoqi@6880 1776 __ mfc1(AT, FSF);
aoqi@6880 1777 __ andr(AT, AT, T9);
aoqi@6880 1778
aoqi@6880 1779 __ dsll32(T9, T9, 0);
aoqi@6880 1780 __ movn(FSR, T9, AT);
aoqi@6880 1781
aoqi@6880 1782 __ bind(L);
aoqi@6880 1783 }
aoqi@1 1784 break;
aoqi@1 1785 case Bytecodes::_f2d:
aoqi@1 1786 __ cvt_d_s(FSF, FSF);
aoqi@1 1787 break;
aoqi@1 1788 case Bytecodes::_d2i:
aoqi@6880 1789 {
aoqi@6880 1790 Label L;
aoqi@6880 1791
aoqi@6880 1792 __ trunc_w_d(F12, FSF);
aoqi@6880 1793 __ move(AT, 0x7fffffff);
aoqi@6880 1794 __ mfc1(FSR, F12);
aoqi@6880 1795
aoqi@6880 1796 __ bne(FSR, AT, L);
aoqi@6880 1797 __ delayed()->mtc1(R0, F12);
aoqi@6880 1798
aoqi@6880 1799 __ cvt_d_w(F12, F12);
aoqi@6880 1800 __ c_ult_d(FSF, F12);
aoqi@6880 1801 __ bc1f(L);
aoqi@6880 1802 __ delayed()->addiu(T9, R0, -1);
aoqi@6880 1803
aoqi@6880 1804 __ c_un_d(FSF, FSF); //NaN?
aoqi@6880 1805 __ subu32(FSR, T9, AT);
aoqi@6880 1806 __ movt(FSR, R0);
aoqi@6880 1807
aoqi@6880 1808 __ bind(L);
aoqi@6880 1809 }
aoqi@1 1810 break;
aoqi@1 1811 case Bytecodes::_d2l:
aoqi@6880 1812 {
aoqi@6880 1813 Label L;
aoqi@6880 1814
aoqi@6880 1815 __ trunc_l_d(F12, FSF);
aoqi@6880 1816 __ daddiu(AT, R0, -1);
aoqi@6880 1817 __ dsrl(AT, AT, 1);
aoqi@6880 1818 __ dmfc1(FSR, F12);
aoqi@6880 1819
aoqi@6880 1820 __ bne(FSR, AT, L);
aoqi@6880 1821 __ delayed()->mtc1(R0, F12);
aoqi@6880 1822
aoqi@6880 1823 __ cvt_d_w(F12, F12);
aoqi@6880 1824 __ c_ult_d(FSF, F12);
aoqi@6880 1825 __ bc1f(L);
aoqi@6880 1826 __ delayed()->daddiu(T9, R0, -1);
aoqi@6880 1827
aoqi@6880 1828 __ c_un_d(FSF, FSF); //NaN?
aoqi@6880 1829 __ subu(FSR, T9, AT);
aoqi@6880 1830 __ movt(FSR, R0);
aoqi@6880 1831
aoqi@6880 1832 __ bind(L);
aoqi@6880 1833 }
aoqi@1 1834 break;
aoqi@1 1835 case Bytecodes::_d2f:
aoqi@1 1836 __ cvt_s_d(FSF, FSF);
aoqi@1 1837 break;
aoqi@1 1838 default :
aoqi@1 1839 ShouldNotReachHere();
aoqi@1 1840 }
aoqi@1 1841 }
aoqi@1 1842
aoqi@1 1843 void TemplateTable::lcmp() {
aoqi@1 1844 transition(ltos, itos);
aoqi@1 1845
aoqi@1 1846 Label low, high, done;
aoqi@1 1847 __ pop(T0);
aoqi@1 1848 __ pop(R0);
aoqi@1 1849 __ slt(AT, T0, FSR);
aoqi@1 1850 __ bne(AT, R0, low);
aoqi@1 1851 __ delayed()->nop();
aoqi@1 1852
aoqi@1 1853 __ bne(T0, FSR, high);
aoqi@1 1854 __ delayed()->nop();
aoqi@1 1855
aoqi@1 1856 __ li(FSR, (long)0);
aoqi@1 1857 __ b(done);
aoqi@1 1858 __ delayed()->nop();
aoqi@1 1859
aoqi@1 1860 __ bind(low);
aoqi@1 1861 __ li(FSR, (long)-1);
aoqi@1 1862 __ b(done);
aoqi@1 1863 __ delayed()->nop();
aoqi@1 1864
aoqi@1 1865 __ bind(high);
aoqi@1 1866 __ li(FSR, (long)1);
aoqi@1 1867 __ b(done);
aoqi@1 1868 __ delayed()->nop();
aoqi@1 1869
aoqi@1 1870 __ bind(done);
aoqi@1 1871 }
aoqi@1 1872
aoqi@1 1873 void TemplateTable::float_cmp(bool is_float, int unordered_result) {
aoqi@6880 1874 Label less, done;
aoqi@6880 1875
aoqi@6880 1876 __ move(FSR, R0);
aoqi@6880 1877
aoqi@6880 1878 if (is_float) {
aoqi@6880 1879 __ lwc1(FTF, at_sp());
aoqi@6880 1880 __ c_eq_s(FTF, FSF);
aoqi@6880 1881 __ bc1t(done);
aoqi@6880 1882 __ delayed()->daddi(SP, SP, 1 * wordSize);
aoqi@6880 1883
aoqi@6880 1884 if (unordered_result<0)
aoqi@6880 1885 __ c_ult_s(FTF, FSF);
aoqi@6880 1886 else
aoqi@6880 1887 __ c_olt_s(FTF, FSF);
aoqi@6880 1888 } else {
aoqi@6880 1889 __ ldc1(FTF, at_sp());
aoqi@6880 1890 __ c_eq_d(FTF, FSF);
aoqi@6880 1891 __ bc1t(done);
aoqi@6880 1892 __ delayed()->daddi(SP, SP, 2 * wordSize);
aoqi@6880 1893
aoqi@6880 1894 if (unordered_result<0)
aoqi@6880 1895 __ c_ult_d(FTF, FSF);
aoqi@6880 1896 else
aoqi@6880 1897 __ c_olt_d(FTF, FSF);
aoqi@6880 1898 }
aoqi@6880 1899 __ bc1t(less);
aoqi@6880 1900 __ delayed()->nop();
aoqi@6880 1901 __ move(FSR, 1);
aoqi@6880 1902 __ b(done);
aoqi@6880 1903 __ delayed()->nop();
aoqi@6880 1904 __ bind(less);
aoqi@6880 1905 __ move(FSR, -1);
aoqi@6880 1906 __ bind(done);
aoqi@1 1907 }
aoqi@1 1908
aoqi@1 1909
aoqi@1 1910 // used registers : T3, A7, Rnext
aoqi@1 1911 // FSR : return bci, this is defined by the vm specification
aoqi@1 1912 // T2 : MDO taken count
aoqi@1 1913 // T3 : method
aoqi@1 1914 // A7 : offset
aoqi@1 1915 // Rnext : next bytecode, this is required by dispatch_base
aoqi@1 1916 void TemplateTable::branch(bool is_jsr, bool is_wide) {
aoqi@1 1917 __ get_method(T3);
aoqi@6880 1918 __ profile_taken_branch(A7, T2); // only C2 meaningful
aoqi@1 1919
aoqi@1 1920 #ifndef CORE
aoqi@6880 1921 const ByteSize be_offset = MethodCounters::backedge_counter_offset() +
aoqi@6880 1922 InvocationCounter::counter_offset();
aoqi@6880 1923 const ByteSize inv_offset = MethodCounters::invocation_counter_offset() +
aoqi@6880 1924 InvocationCounter::counter_offset();
aoqi@1 1925 #endif // CORE
aoqi@1 1926
aoqi@1 1927 // Load up T4 with the branch displacement
aoqi@1 1928 if (!is_wide) {
fujie@6895 1929 __ lb(A7, BCP, 1);
fujie@6895 1930 __ lbu(AT, BCP, 2);
aoqi@7997 1931 __ dsll(A7, A7, 8);
fujie@6895 1932 __ orr(A7, A7, AT);
aoqi@1 1933 } else {
aoqi@15 1934 __ get_4_byte_integer_at_bcp(A7, AT, 1);
aoqi@1 1935 __ swap(A7);
aoqi@1 1936 }
aoqi@1 1937
aoqi@1 1938 // Handle all the JSR stuff here, then exit.
aoqi@6880 1939 // It's much shorter and cleaner than intermingling with the non-JSR
aoqi@6880 1940 // normal-branch stuff occuring below.
aoqi@1 1941 if (is_jsr) {
aoqi@1 1942 // Pre-load the next target bytecode into Rnext
aoqi@1 1943 __ dadd(AT, BCP, A7);
aoqi@1 1944 __ lbu(Rnext, AT, 0);
aoqi@1 1945
aoqi@1 1946 // compute return address as bci in FSR
aoqi@1 1947 __ daddi(FSR, BCP, (is_wide?5:3) - in_bytes(ConstMethod::codes_offset()));
aoqi@1 1948 __ ld(AT, T3, in_bytes(Method::const_offset()));
aoqi@1 1949 __ dsub(FSR, FSR, AT);
aoqi@1 1950 // Adjust the bcp in BCP by the displacement in A7
aoqi@1 1951 __ dadd(BCP, BCP, A7);
aoqi@1 1952 // jsr returns atos that is not an oop
aoqi@1 1953 // Push return address
aoqi@1 1954 __ push_i(FSR);
aoqi@1 1955 // jsr returns vtos
aoqi@1 1956 __ dispatch_only_noverify(vtos);
aoqi@1 1957
aoqi@1 1958 return;
aoqi@1 1959 }
aoqi@1 1960
aoqi@1 1961 // Normal (non-jsr) branch handling
aoqi@1 1962
aoqi@1 1963 // Adjust the bcp in S0 by the displacement in T4
aoqi@1 1964 __ dadd(BCP, BCP, A7);
aoqi@1 1965
aoqi@1 1966 #ifdef CORE
aoqi@1 1967 // Pre-load the next target bytecode into EBX
aoqi@1 1968 __ lbu(Rnext, BCP, 0);
aoqi@1 1969 // continue with the bytecode @ target
aoqi@1 1970 __ dispatch_only(vtos);
aoqi@1 1971 #else
aoqi@1 1972 assert(UseLoopCounter || !UseOnStackReplacement, "on-stack-replacement requires loop counters");
aoqi@1 1973 Label backedge_counter_overflow;
aoqi@1 1974 Label profile_method;
aoqi@1 1975 Label dispatch;
aoqi@1 1976 if (UseLoopCounter) {
aoqi@1 1977 // increment backedge counter for backward branches
aoqi@1 1978 // eax: MDO
aoqi@1 1979 // ebx: MDO bumped taken-count
aoqi@1 1980 // T3: method
aoqi@1 1981 // T4: target offset
aoqi@1 1982 // BCP: target bcp
aoqi@1 1983 // LVP: locals pointer
aoqi@6880 1984 __ bgtz(A7, dispatch); // check if forward or backward branch
aoqi@1 1985 __ delayed()->nop();
aoqi@1 1986
aoqi@1 1987 // check if MethodCounters exists
aoqi@1 1988 Label has_counters;
aoqi@6880 1989 __ ld(AT, T3, in_bytes(Method::method_counters_offset())); // use AT as MDO, TEMP
aoqi@1 1990 __ bne(AT, R0, has_counters);
aoqi@1 1991 __ nop();
aoqi@418 1992 __ push(T3);
aoqi@1 1993 //__ push(A7);
aoqi@1 1994 __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::build_method_counters),
aoqi@1 1995 T3);
aoqi@1 1996 //__ pop(A7);
aoqi@418 1997 __ pop(T3);
aoqi@1 1998 __ ld(AT, T3, in_bytes(Method::method_counters_offset())); // use AT as MDO, TEMP
aoqi@1 1999 __ beq(AT, R0, dispatch);
aoqi@1 2000 __ nop();
aoqi@1 2001 __ bind(has_counters);
aoqi@1 2002
aoqi@6880 2003 // increment back edge counter
aoqi@1 2004 __ ld(T1, T3, in_bytes(Method::method_counters_offset()));
aoqi@1 2005 __ lw(T0, T1, in_bytes(be_offset));
aoqi@1 2006 __ increment(T0, InvocationCounter::count_increment);
aoqi@1 2007 __ sw(T0, T1, in_bytes(be_offset));
aoqi@1 2008
aoqi@1 2009 // load invocation counter
aoqi@1 2010 __ lw(T1, T1, in_bytes(inv_offset));
aoqi@1 2011 // buffer bit added, mask no needed
aoqi@1 2012
aoqi@1 2013 // dadd backedge counter & invocation counter
aoqi@1 2014 __ dadd(T1, T1, T0);
aoqi@1 2015
aoqi@1 2016 if (ProfileInterpreter) {
aoqi@1 2017 // Test to see if we should create a method data oop
aoqi@1 2018 // T1 : backedge counter & invocation counter
fujie@6895 2019 if (Assembler::is_simm16(InvocationCounter::InterpreterProfileLimit)) {
fujie@6895 2020 __ slti(AT, T1, InvocationCounter::InterpreterProfileLimit);
fujie@6895 2021 } else {
fujie@6895 2022 __ li(AT, (long)&InvocationCounter::InterpreterProfileLimit);
fujie@6895 2023 __ lw(AT, AT, 0);
fujie@6895 2024 __ slt(AT, T1, AT);
fujie@6895 2025 }
fujie@6895 2026
aoqi@1 2027 __ bne(AT, R0, dispatch);
aoqi@1 2028 __ delayed()->nop();
aoqi@1 2029
aoqi@1 2030 // if no method data exists, go to profile method
aoqi@1 2031 __ test_method_data_pointer(T1, profile_method);
aoqi@1 2032
aoqi@1 2033 if (UseOnStackReplacement) {
fujie@6895 2034 if (Assembler::is_simm16(InvocationCounter::InterpreterBackwardBranchLimit)) {
fujie@6895 2035 __ slti(AT, T2, InvocationCounter::InterpreterBackwardBranchLimit);
fujie@6895 2036 } else {
fujie@6895 2037 __ li(AT, (long)&InvocationCounter::InterpreterBackwardBranchLimit);
fujie@6895 2038 __ lw(AT, AT, 0);
fujie@6895 2039 __ slt(AT, T2, AT);
fujie@6895 2040 }
fujie@6895 2041
aoqi@6880 2042 __ bne(AT, R0, dispatch);
aoqi@6880 2043 __ delayed()->nop();
aoqi@6880 2044
aoqi@6880 2045 // When ProfileInterpreter is on, the backedge_count comes
aoqi@6880 2046 // from the methodDataOop, which value does not get reset on
aoqi@6880 2047 // the call to frequency_counter_overflow().
aoqi@6880 2048 // To avoid excessive calls to the overflow routine while
aoqi@6880 2049 // the method is being compiled, dadd a second test to make
aoqi@6880 2050 // sure the overflow function is called only once every
aoqi@6880 2051 // overflow_frequency.
aoqi@6880 2052 const int overflow_frequency = 1024;
aoqi@6880 2053 __ andi(AT, T2, overflow_frequency-1);
aoqi@6880 2054 __ beq(AT, R0, backedge_counter_overflow);
aoqi@6880 2055 __ delayed()->nop();
aoqi@1 2056 }
aoqi@1 2057 } else {
aoqi@1 2058 if (UseOnStackReplacement) {
aoqi@6880 2059 // check for overflow against eax, which is the sum of the counters
aoqi@6880 2060 __ li(AT, (long)&InvocationCounter::InterpreterBackwardBranchLimit);
aoqi@6880 2061 __ lw(AT, AT, 0);
aoqi@6880 2062 __ slt(AT, T1, AT);
aoqi@6880 2063 __ beq(AT, R0, backedge_counter_overflow);
aoqi@6880 2064 __ delayed()->nop();
aoqi@1 2065 }
aoqi@1 2066 }
aoqi@1 2067 __ bind(dispatch);
aoqi@1 2068 }
aoqi@1 2069
aoqi@1 2070 // Pre-load the next target bytecode into Rnext
aoqi@1 2071 __ lbu(Rnext, BCP, 0);
aoqi@1 2072
aoqi@1 2073 // continue with the bytecode @ target
aoqi@1 2074 // FSR: return bci for jsr's, unused otherwise
aoqi@1 2075 // Rnext: target bytecode
aoqi@1 2076 // BCP: target bcp
aoqi@1 2077 __ dispatch_only(vtos);
aoqi@1 2078
aoqi@1 2079 if (UseLoopCounter) {
aoqi@1 2080 if (ProfileInterpreter) {
aoqi@1 2081 // Out-of-line code to allocate method data oop.
aoqi@1 2082 __ bind(profile_method);
aoqi@1 2083 __ call_VM(NOREG, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method));
aoqi@1 2084 __ lbu(Rnext, BCP, 0);
aoqi@1 2085 __ set_method_data_pointer_for_bcp();
aoqi@1 2086 __ b(dispatch);
aoqi@1 2087 __ delayed()->nop();
aoqi@1 2088 }
aoqi@1 2089
aoqi@1 2090 if (UseOnStackReplacement) {
aoqi@1 2091 // invocation counter overflow
aoqi@1 2092 __ bind(backedge_counter_overflow);
aoqi@6880 2093 __ sub(A7, BCP, A7); // branch bcp
aoqi@6880 2094 call_VM(NOREG, CAST_FROM_FN_PTR(address,
aoqi@6880 2095 InterpreterRuntime::frequency_counter_overflow), A7);
aoqi@1 2096 __ lbu(Rnext, BCP, 0);
aoqi@1 2097
aoqi@1 2098 // V0: osr nmethod (osr ok) or NULL (osr not possible)
aoqi@1 2099 // V1: osr adapter frame return address
aoqi@1 2100 // Rnext: target bytecode
aoqi@1 2101 // LVP: locals pointer
aoqi@1 2102 // BCP: bcp
aoqi@1 2103 __ beq(V0, R0, dispatch);
aoqi@1 2104 __ delayed()->nop();
aoqi@1 2105 // nmethod may have been invalidated (VM may block upon call_VM return)
aoqi@1 2106 __ lw(T3, V0, nmethod::entry_bci_offset());
aoqi@1 2107 __ move(AT, InvalidOSREntryBci);
aoqi@1 2108 __ beq(AT, T3, dispatch);
aoqi@1 2109 __ delayed()->nop();
aoqi@1 2110 // We need to prepare to execute the OSR method. First we must
aoqi@1 2111 // migrate the locals and monitors off of the stack.
aoqi@1 2112 //eax V0: osr nmethod (osr ok) or NULL (osr not possible)
aoqi@1 2113 //ebx V1: osr adapter frame return address
aoqi@1 2114 //edx Rnext: target bytecode
aoqi@1 2115 //edi LVP: locals pointer
aoqi@1 2116 //esi BCP: bcp
aoqi@6880 2117 __ move(BCP, V0);
aoqi@1 2118 // const Register thread = ecx;
aoqi@1 2119 const Register thread = TREG;
aoqi@1 2120 #ifndef OPT_THREAD
aoqi@1 2121 __ get_thread(thread);
aoqi@1 2122 #endif
aoqi@6880 2123 call_VM(noreg, CAST_FROM_FN_PTR(address,
aoqi@6880 2124 SharedRuntime::OSR_migration_begin));
aoqi@1 2125 // eax is OSR buffer, move it to expected parameter location
aoqi@6880 2126 //refer to osrBufferPointer in c1_LIRAssembler_mips.cpp
aoqi@1 2127 __ move(T0, V0);
aoqi@1 2128
aoqi@1 2129 // pop the interpreter frame
aoqi@6880 2130 __ ld(A7, Address(FP, frame::interpreter_frame_sender_sp_offset * wordSize));
aoqi@6880 2131 //FIXME, shall we keep the return address on the stack?
aoqi@1 2132 __ leave(); // remove frame anchor
aoqi@6880 2133 __ move(LVP, RA);
aoqi@1 2134 __ move(SP, A7);
aoqi@1 2135
aoqi@6880 2136 __ move(AT, -(StackAlignmentInBytes));
aoqi@6880 2137 __ andr(SP , SP , AT);
aoqi@6880 2138
aoqi@6880 2139 // push the (possibly adjusted) return address
aoqi@6880 2140 //refer to osr_entry in c1_LIRAssembler_mips.cpp
aoqi@6880 2141 __ ld(AT, BCP, nmethod::osr_entry_point_offset());
aoqi@6880 2142 __ jr(AT);
aoqi@1 2143 __ delayed()->nop();
aoqi@1 2144 }
aoqi@1 2145 }
aoqi@1 2146 #endif // not CORE
aoqi@1 2147 }
aoqi@1 2148
aoqi@6880 2149
aoqi@1 2150 void TemplateTable::if_0cmp(Condition cc) {
aoqi@1 2151 transition(itos, vtos);
aoqi@1 2152 // assume branch is more often taken than not (loops use backward branches)
aoqi@1 2153 Label not_taken;
aoqi@1 2154 switch(cc) {
aoqi@1 2155 case not_equal:
aoqi@1 2156 __ beq(FSR, R0, not_taken);
aoqi@1 2157 break;
aoqi@1 2158 case equal:
aoqi@1 2159 __ bne(FSR, R0, not_taken);
aoqi@1 2160 break;
aoqi@1 2161 case less:
aoqi@1 2162 __ bgez(FSR, not_taken);
aoqi@1 2163 break;
aoqi@1 2164 case less_equal:
aoqi@1 2165 __ bgtz(FSR, not_taken);
aoqi@1 2166 break;
aoqi@1 2167 case greater:
aoqi@1 2168 __ blez(FSR, not_taken);
aoqi@1 2169 break;
aoqi@1 2170 case greater_equal:
aoqi@1 2171 __ bltz(FSR, not_taken);
aoqi@1 2172 break;
aoqi@1 2173 }
aoqi@1 2174 __ delayed()->nop();
aoqi@1 2175
aoqi@1 2176 branch(false, false);
aoqi@1 2177
aoqi@1 2178 __ bind(not_taken);
aoqi@1 2179 __ profile_not_taken_branch(FSR);
aoqi@1 2180 }
aoqi@1 2181
aoqi@1 2182 void TemplateTable::if_icmp(Condition cc) {
aoqi@1 2183 transition(itos, vtos);
aoqi@1 2184 // assume branch is more often taken than not (loops use backward branches)
aoqi@1 2185 Label not_taken;
aoqi@1 2186
aoqi@6880 2187 __ pop_i(SSR);
aoqi@1 2188 switch(cc) {
aoqi@1 2189 case not_equal:
aoqi@1 2190 __ beq(SSR, FSR, not_taken);
aoqi@1 2191 break;
aoqi@1 2192 case equal:
aoqi@1 2193 __ bne(SSR, FSR, not_taken);
aoqi@1 2194 break;
aoqi@1 2195 case less:
aoqi@1 2196 __ slt(AT, SSR, FSR);
aoqi@1 2197 __ beq(AT, R0, not_taken);
aoqi@1 2198 break;
aoqi@1 2199 case less_equal:
aoqi@1 2200 __ slt(AT, FSR, SSR);
aoqi@1 2201 __ bne(AT, R0, not_taken);
aoqi@1 2202 break;
aoqi@1 2203 case greater:
aoqi@1 2204 __ slt(AT, FSR, SSR);
aoqi@1 2205 __ beq(AT, R0, not_taken);
aoqi@1 2206 break;
aoqi@1 2207 case greater_equal:
aoqi@1 2208 __ slt(AT, SSR, FSR);
aoqi@1 2209 __ bne(AT, R0, not_taken);
aoqi@1 2210 break;
aoqi@1 2211 }
aoqi@1 2212 __ delayed()->nop();
aoqi@1 2213
aoqi@1 2214 branch(false, false);
aoqi@1 2215 __ bind(not_taken);
aoqi@1 2216 __ profile_not_taken_branch(FSR);
aoqi@1 2217 }
aoqi@1 2218
aoqi@1 2219 void TemplateTable::if_nullcmp(Condition cc) {
aoqi@1 2220 transition(atos, vtos);
aoqi@1 2221 // assume branch is more often taken than not (loops use backward branches)
aoqi@1 2222 Label not_taken;
aoqi@1 2223 switch(cc) {
aoqi@1 2224 case not_equal:
aoqi@1 2225 __ beq(FSR, R0, not_taken);
aoqi@1 2226 break;
aoqi@1 2227 case equal:
aoqi@1 2228 __ bne(FSR, R0, not_taken);
aoqi@1 2229 break;
aoqi@1 2230 default:
aoqi@1 2231 ShouldNotReachHere();
aoqi@1 2232 }
aoqi@1 2233 __ delayed()->nop();
aoqi@1 2234
aoqi@1 2235 branch(false, false);
aoqi@1 2236 __ bind(not_taken);
aoqi@1 2237 __ profile_not_taken_branch(FSR);
aoqi@1 2238 }
aoqi@1 2239
aoqi@1 2240
aoqi@1 2241 void TemplateTable::if_acmp(Condition cc) {
aoqi@6880 2242 transition(atos, vtos);
aoqi@6880 2243 // assume branch is more often taken than not (loops use backward branches)
aoqi@6880 2244 Label not_taken;
aoqi@6880 2245 // __ lw(SSR, SP, 0);
aoqi@6880 2246 __ pop_ptr(SSR);
aoqi@6880 2247 switch(cc) {
aoqi@6880 2248 case not_equal:
aoqi@6880 2249 __ beq(SSR, FSR, not_taken);
aoqi@6880 2250 break;
aoqi@6880 2251 case equal:
aoqi@6880 2252 __ bne(SSR, FSR, not_taken);
aoqi@6880 2253 break;
aoqi@6880 2254 default:
aoqi@6880 2255 ShouldNotReachHere();
aoqi@6880 2256 }
aoqi@6880 2257 __ delayed()->nop();
aoqi@6880 2258
aoqi@6880 2259 branch(false, false);
aoqi@6880 2260
aoqi@6880 2261 __ bind(not_taken);
aoqi@6880 2262 __ profile_not_taken_branch(FSR);
aoqi@1 2263 }
aoqi@1 2264
aoqi@1 2265 // used registers : T1, T2, T3
aoqi@1 2266 // T1 : method
aoqi@1 2267 // T2 : returb bci
aoqi@1 2268 void TemplateTable::ret() {
aoqi@6880 2269 transition(vtos, vtos);
aoqi@6880 2270
aoqi@6880 2271 locals_index(T2);
aoqi@6880 2272 __ ld(T2, T2, 0);
aoqi@6880 2273 __ profile_ret(T2, T3);
aoqi@6880 2274
aoqi@6880 2275 __ get_method(T1);
aoqi@6880 2276 __ ld(BCP, T1, in_bytes(Method::const_offset()));
aoqi@6880 2277 __ dadd(BCP, BCP, T2);
aoqi@6880 2278 __ daddi(BCP, BCP, in_bytes(ConstMethod::codes_offset()));
aoqi@6880 2279
aoqi@6880 2280 __ dispatch_next(vtos);
aoqi@1 2281 }
aoqi@1 2282
aoqi@1 2283 // used registers : T1, T2, T3
aoqi@1 2284 // T1 : method
aoqi@1 2285 // T2 : returb bci
aoqi@1 2286 void TemplateTable::wide_ret() {
aoqi@6880 2287 transition(vtos, vtos);
aoqi@6880 2288
aoqi@6880 2289 locals_index_wide(T2);
aoqi@6880 2290 __ ld(T2, T2, 0); // get return bci, compute return bcp
aoqi@6880 2291 __ profile_ret(T2, T3);
aoqi@6880 2292
aoqi@6880 2293 __ get_method(T1);
aoqi@6880 2294 __ ld(BCP, T1, in_bytes(Method::const_offset()));
aoqi@6880 2295 __ dadd(BCP, BCP, T2);
aoqi@6880 2296 __ daddi(BCP, BCP, in_bytes(ConstMethod::codes_offset()));
aoqi@6880 2297
aoqi@6880 2298 __ dispatch_next(vtos);
aoqi@1 2299 }
aoqi@1 2300
aoqi@1 2301 // used register T2, T3, A7, Rnext
aoqi@1 2302 // T2 : bytecode pointer
aoqi@1 2303 // T3 : low
aoqi@1 2304 // A7 : high
aoqi@1 2305 // Rnext : dest bytecode, required by dispatch_base
aoqi@1 2306 void TemplateTable::tableswitch() {
aoqi@6880 2307 Label default_case, continue_execution;
aoqi@6880 2308 transition(itos, vtos);
aoqi@6880 2309
aoqi@6880 2310 // align BCP
aoqi@6880 2311 __ daddi(T2, BCP, BytesPerInt);
aoqi@6880 2312 __ li(AT, -BytesPerInt);
aoqi@6880 2313 __ andr(T2, T2, AT);
aoqi@6880 2314
aoqi@6880 2315 // load lo & hi
aoqi@6880 2316 __ lw(T3, T2, 1 * BytesPerInt);
aoqi@6880 2317 __ swap(T3);
aoqi@6880 2318 __ lw(A7, T2, 2 * BytesPerInt);
aoqi@6880 2319 __ swap(A7);
aoqi@6880 2320
aoqi@6880 2321 // check against lo & hi
aoqi@6880 2322 __ slt(AT, FSR, T3);
aoqi@6880 2323 __ bne(AT, R0, default_case);
aoqi@6880 2324 __ delayed()->nop();
aoqi@6880 2325
aoqi@6880 2326 __ slt(AT, A7, FSR);
aoqi@6880 2327 __ bne(AT, R0, default_case);
aoqi@6880 2328 __ delayed()->nop();
aoqi@6880 2329
aoqi@6880 2330 // lookup dispatch offset, in A7 big endian
aoqi@6880 2331 __ dsub(FSR, FSR, T3);
aoqi@6880 2332 __ dsll(AT, FSR, Address::times_4);
aoqi@6880 2333 __ dadd(AT, T2, AT);
aoqi@6880 2334 __ lw(A7, AT, 3 * BytesPerInt);
aoqi@6880 2335 __ profile_switch_case(FSR, T9, T3);
aoqi@6880 2336
aoqi@6880 2337 __ bind(continue_execution);
aoqi@6880 2338 __ swap(A7);
aoqi@6880 2339 __ dadd(BCP, BCP, A7);
aoqi@6880 2340 __ lbu(Rnext, BCP, 0);
aoqi@6880 2341 __ dispatch_only(vtos);
aoqi@6880 2342
aoqi@6880 2343 // handle default
aoqi@6880 2344 __ bind(default_case);
aoqi@6880 2345 __ profile_switch_default(FSR);
aoqi@6880 2346 __ lw(A7, T2, 0);
aoqi@6880 2347 __ b(continue_execution);
aoqi@6880 2348 __ delayed()->nop();
aoqi@1 2349 }
aoqi@1 2350
aoqi@1 2351 void TemplateTable::lookupswitch() {
aoqi@6880 2352 transition(itos, itos);
aoqi@6880 2353 __ stop("lookupswitch bytecode should have been rewritten");
aoqi@1 2354 }
aoqi@1 2355
aoqi@1 2356 // used registers : T2, T3, A7, Rnext
aoqi@1 2357 // T2 : bytecode pointer
aoqi@1 2358 // T3 : pair index
aoqi@1 2359 // A7 : offset
aoqi@1 2360 // Rnext : dest bytecode
aoqi@1 2361 // the data after the opcode is the same as lookupswitch
aoqi@1 2362 // see Rewriter::rewrite_method for more information
aoqi@1 2363 void TemplateTable::fast_linearswitch() {
aoqi@1 2364 transition(itos, vtos);
aoqi@6880 2365 Label loop_entry, loop, found, continue_execution;
aoqi@1 2366
aoqi@1 2367 // swap eax so we can avoid swapping the table entries
aoqi@1 2368 __ swap(FSR);
aoqi@1 2369
aoqi@1 2370 // align BCP
aoqi@1 2371 __ daddi(T2, BCP, BytesPerInt);
aoqi@1 2372 __ li(AT, -BytesPerInt);
aoqi@1 2373 __ andr(T2, T2, AT);
aoqi@1 2374
aoqi@1 2375 // set counter
aoqi@1 2376 __ lw(T3, T2, BytesPerInt);
aoqi@1 2377 __ swap(T3);
aoqi@1 2378 __ b(loop_entry);
aoqi@1 2379 __ delayed()->nop();
aoqi@1 2380
aoqi@1 2381 // table search
aoqi@1 2382 __ bind(loop);
aoqi@1 2383 // get the entry value
aoqi@1 2384 __ dsll(AT, T3, Address::times_8);
aoqi@1 2385 __ dadd(AT, T2, AT);
aoqi@1 2386 __ lw(AT, AT, 2 * BytesPerInt);
aoqi@1 2387
aoqi@1 2388 // found?
aoqi@1 2389 __ beq(FSR, AT, found);
aoqi@1 2390 __ delayed()->nop();
aoqi@1 2391
aoqi@1 2392 __ bind(loop_entry);
aoqi@1 2393 __ bgtz(T3, loop);
aoqi@1 2394 __ delayed()->daddiu(T3, T3, -1);
aoqi@1 2395
aoqi@1 2396 // default case
aoqi@1 2397 __ profile_switch_default(FSR);
aoqi@1 2398 __ lw(A7, T2, 0);
aoqi@1 2399 __ b(continue_execution);
aoqi@1 2400 __ delayed()->nop();
aoqi@1 2401
aoqi@1 2402 // entry found -> get offset
aoqi@1 2403 __ bind(found);
aoqi@1 2404 __ dsll(AT, T3, Address::times_8);
aoqi@1 2405 __ dadd(AT, T2, AT);
aoqi@1 2406 __ lw(A7, AT, 3 * BytesPerInt);
aoqi@1 2407 __ profile_switch_case(T3, FSR, T2);
aoqi@1 2408
aoqi@1 2409 // continue execution
aoqi@6880 2410 __ bind(continue_execution);
aoqi@1 2411 __ swap(A7);
aoqi@1 2412 __ dadd(BCP, BCP, A7);
aoqi@1 2413 __ lbu(Rnext, BCP, 0);
aoqi@1 2414 __ dispatch_only(vtos);
aoqi@1 2415 }
aoqi@1 2416
aoqi@1 2417 // used registers : T0, T1, T2, T3, A7, Rnext
aoqi@1 2418 // T2 : pairs address(array)
aoqi@1 2419 // Rnext : dest bytecode
aoqi@1 2420 // the data after the opcode is the same as lookupswitch
aoqi@1 2421 // see Rewriter::rewrite_method for more information
aoqi@1 2422 void TemplateTable::fast_binaryswitch() {
aoqi@1 2423 transition(itos, vtos);
aoqi@1 2424 // Implementation using the following core algorithm:
aoqi@1 2425 //
aoqi@1 2426 // int binary_search(int key, LookupswitchPair* array, int n) {
aoqi@1 2427 // // Binary search according to "Methodik des Programmierens" by
aoqi@1 2428 // // Edsger W. Dijkstra and W.H.J. Feijen, Addison Wesley Germany 1985.
aoqi@1 2429 // int i = 0;
aoqi@1 2430 // int j = n;
aoqi@1 2431 // while (i+1 < j) {
aoqi@1 2432 // // invariant P: 0 <= i < j <= n and (a[i] <= key < a[j] or Q)
aoqi@1 2433 // // with Q: for all i: 0 <= i < n: key < a[i]
aoqi@1 2434 // // where a stands for the array and assuming that the (inexisting)
aoqi@1 2435 // // element a[n] is infinitely big.
aoqi@1 2436 // int h = (i + j) >> 1;
aoqi@1 2437 // // i < h < j
aoqi@1 2438 // if (key < array[h].fast_match()) {
aoqi@1 2439 // j = h;
aoqi@1 2440 // } else {
aoqi@1 2441 // i = h;
aoqi@1 2442 // }
aoqi@1 2443 // }
aoqi@1 2444 // // R: a[i] <= key < a[i+1] or Q
aoqi@1 2445 // // (i.e., if key is within array, i is the correct index)
aoqi@1 2446 // return i;
aoqi@1 2447 // }
aoqi@1 2448
aoqi@1 2449 // register allocation
aoqi@1 2450 const Register array = T2;
aoqi@1 2451 const Register i = T3, j = A7;
aoqi@1 2452 const Register h = T1;
aoqi@1 2453 const Register temp = T0;
aoqi@1 2454 const Register key = FSR;
aoqi@1 2455
aoqi@1 2456 // setup array
aoqi@1 2457 __ daddi(array, BCP, 3*BytesPerInt);
aoqi@1 2458 __ li(AT, -BytesPerInt);
aoqi@1 2459 __ andr(array, array, AT);
aoqi@1 2460
aoqi@1 2461 // initialize i & j
aoqi@1 2462 __ move(i, R0);
aoqi@1 2463 __ lw(j, array, - 1 * BytesPerInt);
aoqi@6880 2464 // Convert j into native byteordering
aoqi@1 2465 __ swap(j);
aoqi@1 2466
aoqi@1 2467 // and start
aoqi@1 2468 Label entry;
aoqi@1 2469 __ b(entry);
aoqi@1 2470 __ delayed()->nop();
aoqi@1 2471
aoqi@1 2472 // binary search loop
aoqi@6880 2473 {
aoqi@1 2474 Label loop;
aoqi@1 2475 __ bind(loop);
aoqi@1 2476 // int h = (i + j) >> 1;
aoqi@1 2477 __ dadd(h, i, j);
aoqi@1 2478 __ dsrl(h, h, 1);
aoqi@1 2479 // if (key < array[h].fast_match()) {
aoqi@1 2480 // j = h;
aoqi@1 2481 // } else {
aoqi@1 2482 // i = h;
aoqi@1 2483 // }
aoqi@1 2484 // Convert array[h].match to native byte-ordering before compare
aoqi@1 2485 __ dsll(AT, h, Address::times_8);
aoqi@1 2486 __ dadd(AT, array, AT);
aoqi@1 2487 __ lw(temp, AT, 0 * BytesPerInt);
aoqi@1 2488 __ swap(temp);
aoqi@1 2489
aoqi@1 2490 {
aoqi@1 2491 Label set_i, end_of_if;
aoqi@1 2492 __ slt(AT, key, temp);
aoqi@1 2493 __ beq(AT, R0, set_i);
aoqi@6880 2494 __ delayed()->nop();
aoqi@1 2495
aoqi@1 2496 __ b(end_of_if);
aoqi@1 2497 __ delayed(); __ move(j, h);
aoqi@1 2498
aoqi@1 2499 __ bind(set_i);
aoqi@1 2500 __ move(i, h);
aoqi@1 2501
aoqi@1 2502 __ bind(end_of_if);
aoqi@1 2503 }
aoqi@1 2504 // while (i+1 < j)
aoqi@1 2505 __ bind(entry);
aoqi@1 2506 __ daddi(h, i, 1);
aoqi@1 2507 __ slt(AT, h, j);
aoqi@1 2508 __ bne(AT, R0, loop);
aoqi@1 2509 __ delayed()->nop();
aoqi@1 2510 }
aoqi@1 2511
aoqi@1 2512 // end of binary search, result index is i (must check again!)
aoqi@1 2513 Label default_case;
aoqi@1 2514 // Convert array[i].match to native byte-ordering before compare
aoqi@1 2515 __ dsll(AT, i, Address::times_8);
aoqi@1 2516 __ dadd(AT, array, AT);
aoqi@1 2517 __ lw(temp, AT, 0 * BytesPerInt);
aoqi@1 2518 __ swap(temp);
aoqi@1 2519 __ bne(key, temp, default_case);
aoqi@1 2520 __ delayed()->nop();
aoqi@1 2521
aoqi@1 2522 // entry found -> j = offset
aoqi@1 2523 __ dsll(AT, i, Address::times_8);
aoqi@1 2524 __ dadd(AT, array, AT);
aoqi@1 2525 __ lw(j, AT, 1 * BytesPerInt);
aoqi@1 2526 __ profile_switch_case(i, key, array);
aoqi@1 2527 __ swap(j);
aoqi@1 2528
aoqi@1 2529 __ dadd(BCP, BCP, j);
aoqi@1 2530 __ lbu(Rnext, BCP, 0);
aoqi@1 2531 __ dispatch_only(vtos);
aoqi@1 2532
aoqi@1 2533 // default case -> j = default offset
aoqi@1 2534 __ bind(default_case);
aoqi@1 2535 __ profile_switch_default(i);
aoqi@1 2536 __ lw(j, array, - 2 * BytesPerInt);
aoqi@1 2537 __ swap(j);
aoqi@1 2538 __ dadd(BCP, BCP, j);
aoqi@1 2539 __ lbu(Rnext, BCP, 0);
aoqi@1 2540 __ dispatch_only(vtos);
aoqi@1 2541 }
aoqi@1 2542
aoqi@1 2543 void TemplateTable::_return(TosState state) {
aoqi@1 2544 transition(state, state);
aoqi@6880 2545 assert(_desc->calls_vm(),
aoqi@6880 2546 "inconsistent calls_vm information"); // call in remove_activation
aoqi@6880 2547
aoqi@1 2548 if (_desc->bytecode() == Bytecodes::_return_register_finalizer) {
aoqi@1 2549 assert(state == vtos, "only valid state");
aoqi@1 2550 __ ld(T1, aaddress(0));
aoqi@1 2551 __ load_klass(LVP, T1);
aoqi@1 2552 __ lw(LVP, LVP, in_bytes(Klass::access_flags_offset()));
aoqi@6880 2553 __ move(AT, JVM_ACC_HAS_FINALIZER);
aoqi@1 2554 __ andr(AT, AT, LVP);//by_css
aoqi@1 2555 Label skip_register_finalizer;
aoqi@1 2556 __ beq(AT, R0, skip_register_finalizer);
aoqi@6880 2557 __ delayed()->nop();
aoqi@6880 2558 __ call_VM(noreg, CAST_FROM_FN_PTR(address,
aoqi@6880 2559 InterpreterRuntime::register_finalizer), T1);
aoqi@1 2560 __ bind(skip_register_finalizer);
aoqi@1 2561 }
aoqi@1 2562 __ remove_activation(state, T9);
fujie@32 2563 __ sync();
aoqi@1 2564
aoqi@1 2565 __ jr(T9);
aoqi@1 2566 __ delayed()->nop();
aoqi@1 2567 }
aoqi@1 2568
aoqi@1 2569 // ----------------------------------------------------------------------------
aoqi@1 2570 // Volatile variables demand their effects be made known to all CPU's
aoqi@1 2571 // in order. Store buffers on most chips allow reads & writes to
aoqi@1 2572 // reorder; the JMM's ReadAfterWrite.java test fails in -Xint mode
aoqi@1 2573 // without some kind of memory barrier (i.e., it's not sufficient that
aoqi@1 2574 // the interpreter does not reorder volatile references, the hardware
aoqi@1 2575 // also must not reorder them).
aoqi@1 2576 //
aoqi@1 2577 // According to the new Java Memory Model (JMM):
aoqi@1 2578 // (1) All volatiles are serialized wrt to each other. ALSO reads &
aoqi@1 2579 // writes act as aquire & release, so:
aoqi@1 2580 // (2) A read cannot let unrelated NON-volatile memory refs that
aoqi@1 2581 // happen after the read float up to before the read. It's OK for
aoqi@1 2582 // non-volatile memory refs that happen before the volatile read to
aoqi@1 2583 // float down below it.
aoqi@1 2584 // (3) Similar a volatile write cannot let unrelated NON-volatile
aoqi@1 2585 // memory refs that happen BEFORE the write float down to after the
aoqi@1 2586 // write. It's OK for non-volatile memory refs that happen after the
aoqi@1 2587 // volatile write to float up before it.
aoqi@1 2588 //
aoqi@1 2589 // We only put in barriers around volatile refs (they are expensive),
aoqi@1 2590 // not _between_ memory refs (that would require us to track the
aoqi@1 2591 // flavor of the previous memory refs). Requirements (2) and (3)
aoqi@1 2592 // require some barriers before volatile stores and after volatile
aoqi@1 2593 // loads. These nearly cover requirement (1) but miss the
aoqi@1 2594 // volatile-store-volatile-load case. This final case is placed after
aoqi@1 2595 // volatile-stores although it could just as well go before
aoqi@1 2596 // volatile-loads.
aoqi@1 2597 //void TemplateTable::volatile_barrier(Assembler::Membar_mask_bits
aoqi@1 2598 // order_constraint) {
aoqi@1 2599 void TemplateTable::volatile_barrier( ) {
aoqi@1 2600 // Helper function to insert a is-volatile test and memory barrier
aoqi@1 2601 //if (os::is_MP()) { // Not needed on single CPU
aoqi@1 2602 // __ membar(order_constraint);
aoqi@1 2603 //}
aoqi@6880 2604 if( !os::is_MP() ) return; // Not needed on single CPU
aoqi@6880 2605 __ sync();
aoqi@1 2606 }
aoqi@1 2607
aoqi@1 2608 // we dont shift left 2 bits in get_cache_and_index_at_bcp
aoqi@6880 2609 // for we always need shift the index we use it. the ConstantPoolCacheEntry
aoqi@6880 2610 // is 16-byte long, index is the index in
aoqi@6880 2611 // ConstantPoolCache, so cache + base_offset() + index * 16 is
aoqi@1 2612 // the corresponding ConstantPoolCacheEntry
aoqi@1 2613 // used registers : T2
aoqi@1 2614 // NOTE : the returned index need also shift left 4 to get the address!
aoqi@1 2615 void TemplateTable::resolve_cache_and_index(int byte_no,
aoqi@1 2616 Register Rcache,
aoqi@6880 2617 Register index,
aoqi@1 2618 size_t index_size) {
aoqi@1 2619 assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
aoqi@1 2620 const Register temp = A1;
aoqi@1 2621 assert_different_registers(Rcache, index);
aoqi@6880 2622
aoqi@1 2623 Label resolved;
aoqi@1 2624 __ get_cache_and_index_and_bytecode_at_bcp(Rcache, index, temp, byte_no, 1, index_size);
aoqi@1 2625 // is resolved?
aoqi@1 2626 int i = (int)bytecode();
aoqi@1 2627 __ addi(temp, temp, -i);
aoqi@1 2628 __ beq(temp, R0, resolved);
aoqi@1 2629 __ delayed()->nop();
aoqi@1 2630 // resolve first time through
aoqi@1 2631 address entry;
aoqi@1 2632 switch (bytecode()) {
aoqi@1 2633 case Bytecodes::_getstatic : // fall through
aoqi@1 2634 case Bytecodes::_putstatic : // fall through
aoqi@1 2635 case Bytecodes::_getfield : // fall through
aoqi@6880 2636 case Bytecodes::_putfield :
aoqi@6880 2637 entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_get_put);
aoqi@1 2638 break;
aoqi@1 2639 case Bytecodes::_invokevirtual : // fall through
aoqi@1 2640 case Bytecodes::_invokespecial : // fall through
aoqi@1 2641 case Bytecodes::_invokestatic : // fall through
aoqi@6880 2642 case Bytecodes::_invokeinterface:
aoqi@6880 2643 entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke);
aoqi@1 2644 break;
aoqi@1 2645 case Bytecodes::_invokehandle:
aoqi@1 2646 entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokehandle);
aoqi@1 2647 break;
aoqi@1 2648 case Bytecodes::_invokedynamic:
aoqi@1 2649 entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic);
aoqi@1 2650 break;
aoqi@6880 2651 default :
aoqi@1 2652 fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(bytecode())));
aoqi@6880 2653 break;
aoqi@1 2654 }
aoqi@1 2655
aoqi@1 2656 __ move(temp, i);
aoqi@1 2657 __ call_VM(NOREG, entry, temp);
aoqi@1 2658
aoqi@1 2659 // Update registers with resolved info
aoqi@1 2660 __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size);
aoqi@1 2661 __ bind(resolved);
aoqi@1 2662 }
aoqi@1 2663
aoqi@1 2664 // The Rcache and index registers must be set before call
aoqi@1 2665 void TemplateTable::load_field_cp_cache_entry(Register obj,
aoqi@1 2666 Register cache,
aoqi@1 2667 Register index,
aoqi@1 2668 Register off,
aoqi@1 2669 Register flags,
aoqi@1 2670 bool is_static = false) {
aoqi@1 2671 assert_different_registers(cache, index, flags, off);
aoqi@6880 2672
aoqi@1 2673 ByteSize cp_base_offset = ConstantPoolCache::base_offset();
aoqi@1 2674 // Field offset
aoqi@1 2675 __ dsll(AT, index, Address::times_ptr);
aoqi@1 2676 __ dadd(AT, cache, AT);
aoqi@1 2677 __ ld(off, AT, in_bytes(cp_base_offset + ConstantPoolCacheEntry::f2_offset()));
aoqi@6880 2678 // Flags
aoqi@1 2679 __ ld(flags, AT, in_bytes(cp_base_offset + ConstantPoolCacheEntry::flags_offset()));
aoqi@1 2680
aoqi@6880 2681 // klass overwrite register
aoqi@1 2682 if (is_static) {
aoqi@6880 2683 __ ld(obj, AT, in_bytes(cp_base_offset + ConstantPoolCacheEntry::f1_offset()));
aoqi@1 2684 const int mirror_offset = in_bytes(Klass::java_mirror_offset());
aoqi@1 2685 __ ld(obj, Address(obj, mirror_offset));
aoqi@1 2686
aoqi@6880 2687 __ verify_oop(obj);
aoqi@1 2688 }
aoqi@1 2689 }
aoqi@1 2690
aoqi@1 2691 // get the method, itable_index and flags of the current invoke
aoqi@1 2692 void TemplateTable::load_invoke_cp_cache_entry(int byte_no,
aoqi@1 2693 Register method,
aoqi@1 2694 Register itable_index,
aoqi@1 2695 Register flags,
aoqi@1 2696 bool is_invokevirtual,
aoqi@1 2697 bool is_invokevfinal, /*unused*/
aoqi@1 2698 bool is_invokedynamic) {
aoqi@1 2699 // setup registers
aoqi@1 2700 const Register cache = T3;
aoqi@1 2701 const Register index = T1;
aoqi@1 2702 assert_different_registers(method, flags);
aoqi@1 2703 assert_different_registers(method, cache, index);
aoqi@1 2704 assert_different_registers(itable_index, flags);
aoqi@1 2705 assert_different_registers(itable_index, cache, index);
aoqi@1 2706 assert(is_invokevirtual == (byte_no == f2_byte), "is invokevirtual flag redundant");
aoqi@1 2707 // determine constant pool cache field offsets
aoqi@1 2708 const int method_offset = in_bytes(
aoqi@6880 2709 ConstantPoolCache::base_offset() +
aoqi@1 2710 ((byte_no == f2_byte)
aoqi@1 2711 ? ConstantPoolCacheEntry::f2_offset()
aoqi@6880 2712 : ConstantPoolCacheEntry::f1_offset()));
aoqi@1 2713 const int flags_offset = in_bytes(ConstantPoolCache::base_offset() +
aoqi@6880 2714 ConstantPoolCacheEntry::flags_offset());
aoqi@1 2715 // access constant pool cache fields
aoqi@1 2716 const int index_offset = in_bytes(ConstantPoolCache::base_offset() +
aoqi@6880 2717 ConstantPoolCacheEntry::f2_offset());
aoqi@6880 2718
aoqi@1 2719 size_t index_size = (is_invokedynamic ? sizeof(u4): sizeof(u2));
aoqi@1 2720 resolve_cache_and_index(byte_no, cache, index, index_size);
aoqi@1 2721
aoqi@1 2722 //assert(wordSize == 8, "adjust code below");
aoqi@6880 2723 // note we shift 4 not 2, for we get is the true inde
aoqi@1 2724 // of ConstantPoolCacheEntry, not the shifted 2-bit index as x86 version
aoqi@1 2725 __ dsll(AT, index, Address::times_ptr);
aoqi@1 2726 __ dadd(AT, cache, AT);
aoqi@1 2727 __ ld(method, AT, method_offset);
aoqi@1 2728
aoqi@1 2729 if (itable_index != NOREG) {
aoqi@1 2730 __ ld(itable_index, AT, index_offset);
aoqi@1 2731 }
aoqi@1 2732 __ ld(flags, AT, flags_offset);
aoqi@1 2733 }
aoqi@1 2734
aoqi@1 2735 // The registers cache and index expected to be set before call.
aoqi@1 2736 // Correct values of the cache and index registers are preserved.
aoqi@1 2737 void TemplateTable::jvmti_post_field_access(Register cache, Register index,
aoqi@1 2738 bool is_static, bool has_tos) {
aoqi@1 2739 // do the JVMTI work here to avoid disturbing the register state below
aoqi@1 2740 // We use c_rarg registers here because we want to use the register used in
aoqi@1 2741 // the call to the VM
aoqi@6880 2742 if (JvmtiExport::can_post_field_access()) {
aoqi@6880 2743 // Check to see if a field access watch has been set before we
aoqi@6880 2744 // take the time to call into the VM.
aoqi@6880 2745 Label L1;
aoqi@6883 2746 // kill FSR
aoqi@6883 2747 Register tmp1 = T2;
aoqi@6883 2748 Register tmp2 = T1;
aoqi@6883 2749 Register tmp3 = T3;
aoqi@6883 2750 assert_different_registers(cache, index, AT);
aoqi@6880 2751 __ li(AT, (intptr_t)JvmtiExport::get_field_access_count_addr());
aoqi@6883 2752 __ lw(AT, AT, 0);
aoqi@6883 2753 __ beq(AT, R0, L1);
aoqi@6880 2754 __ delayed()->nop();
aoqi@6880 2755
aoqi@6883 2756 __ get_cache_and_index_at_bcp(tmp2, tmp3, 1);
aoqi@6883 2757
aoqi@6880 2758 // cache entry pointer
aoqi@6883 2759 __ daddi(tmp2, tmp2, in_bytes(ConstantPoolCache::base_offset()));
aoqi@6883 2760 __ shl(tmp3, LogBytesPerWord);
aoqi@6883 2761 __ dadd(tmp2, tmp2, tmp3);
aoqi@6880 2762 if (is_static) {
aoqi@6883 2763 __ move(tmp1, R0);
aoqi@6880 2764 } else {
aoqi@6883 2765 __ ld(tmp1, SP, 0);
aoqi@6883 2766 __ verify_oop(tmp1);
aoqi@6880 2767 }
aoqi@6883 2768 // tmp1: object pointer or NULL
aoqi@6883 2769 // tmp2: cache entry pointer
aoqi@6883 2770 // tmp3: jvalue object on the stack
aoqi@6880 2771 __ call_VM(NOREG, CAST_FROM_FN_PTR(address,
aoqi@6883 2772 InterpreterRuntime::post_field_access),
aoqi@6883 2773 tmp1, tmp2, tmp3);
aoqi@6880 2774 __ get_cache_and_index_at_bcp(cache, index, 1);
aoqi@6880 2775 __ bind(L1);
aoqi@6880 2776 }
aoqi@1 2777 }
aoqi@1 2778
aoqi@1 2779 void TemplateTable::pop_and_check_object(Register r) {
aoqi@1 2780 __ pop_ptr(r);
aoqi@1 2781 __ null_check(r); // for field access must check obj.
aoqi@1 2782 __ verify_oop(r);
aoqi@1 2783 }
aoqi@1 2784
aoqi@1 2785 // used registers : T1, T2, T3, T1
aoqi@1 2786 // T1 : flags
aoqi@1 2787 // T2 : off
aoqi@1 2788 // T3 : obj
aoqi@1 2789 // T1 : field address
aoqi@1 2790 // The flags 31, 30, 29, 28 together build a 4 bit number 0 to 8 with the
aoqi@1 2791 // following mapping to the TosState states:
aoqi@1 2792 // btos: 0
aoqi@1 2793 // ctos: 1
aoqi@1 2794 // stos: 2
aoqi@1 2795 // itos: 3
aoqi@1 2796 // ltos: 4
aoqi@1 2797 // ftos: 5
aoqi@1 2798 // dtos: 6
aoqi@1 2799 // atos: 7
aoqi@1 2800 // vtos: 8
aoqi@1 2801 // see ConstantPoolCacheEntry::set_field for more info
aoqi@1 2802 void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
aoqi@1 2803 transition(vtos, vtos);
aoqi@1 2804
aoqi@1 2805 const Register cache = T3;
aoqi@1 2806 const Register index = T0;
aoqi@1 2807
aoqi@1 2808 const Register obj = T3;
aoqi@1 2809 const Register off = T2;
aoqi@1 2810 const Register flags = T1;
aoqi@1 2811 resolve_cache_and_index(byte_no, cache, index, sizeof(u2));
aoqi@6883 2812 jvmti_post_field_access(cache, index, is_static, false);
aoqi@1 2813 load_field_cp_cache_entry(obj, cache, index, off, flags, is_static);
aoqi@1 2814
aoqi@1 2815 if (!is_static) pop_and_check_object(obj);
aoqi@1 2816 __ dadd(index, obj, off);
aoqi@1 2817
aoqi@1 2818
aoqi@6880 2819 Label Done, notByte, notInt, notShort, notChar,
aoqi@6880 2820 notLong, notFloat, notObj, notDouble;
aoqi@1 2821
aoqi@1 2822 assert(btos == 0, "change code, btos != 0");
aoqi@1 2823 __ dsrl(flags, flags, ConstantPoolCacheEntry::tos_state_shift);
aoqi@1 2824 __ andi(flags, flags, 0xf);
aoqi@1 2825 __ bne(flags, R0, notByte);
aoqi@1 2826 __ delayed()->nop();
aoqi@1 2827
aoqi@1 2828 // btos
aoqi@6880 2829 __ lb(FSR, index, 0);
aoqi@1 2830 __ sd(FSR, SP, - wordSize);
aoqi@1 2831
aoqi@1 2832 // Rewrite bytecode to be faster
aoqi@1 2833 if (!is_static) {
aoqi@1 2834 patch_bytecode(Bytecodes::_fast_bgetfield, T3, T2);
aoqi@1 2835 }
aoqi@1 2836 __ b(Done);
aoqi@1 2837 __ delayed()->daddi(SP, SP, - wordSize);
aoqi@1 2838
aoqi@1 2839 __ bind(notByte);
aoqi@1 2840 __ move(AT, itos);
aoqi@1 2841 __ bne(flags, AT, notInt);
aoqi@1 2842 __ delayed()->nop();
aoqi@1 2843
aoqi@1 2844 // itos
aoqi@1 2845 __ lw(FSR, index, 0);
aoqi@1 2846 __ sd(FSR, SP, - wordSize);
aoqi@1 2847
aoqi@1 2848 // Rewrite bytecode to be faster
aoqi@1 2849 if (!is_static) {
aoqi@1 2850 // patch_bytecode(Bytecodes::_fast_igetfield, T3, T2);
aoqi@1 2851 patch_bytecode(Bytecodes::_fast_igetfield, T3, T2);
aoqi@1 2852 }
aoqi@1 2853 __ b(Done);
aoqi@1 2854 __ delayed()->daddi(SP, SP, - wordSize);
aoqi@1 2855
aoqi@1 2856 __ bind(notInt);
aoqi@1 2857 __ move(AT, atos);
aoqi@1 2858 __ bne(flags, AT, notObj);
aoqi@1 2859 __ delayed()->nop();
aoqi@1 2860
aoqi@1 2861 // atos
aoqi@1 2862 //add for compressedoops
aoqi@1 2863 __ load_heap_oop(FSR, Address(index, 0));
aoqi@1 2864 __ sd(FSR, SP, - wordSize);
aoqi@1 2865
aoqi@1 2866 if (!is_static) {
aoqi@1 2867 //patch_bytecode(Bytecodes::_fast_agetfield, T3, T2);
aoqi@1 2868 patch_bytecode(Bytecodes::_fast_agetfield, T3, T2);
aoqi@1 2869 }
aoqi@1 2870 __ b(Done);
aoqi@1 2871 __ delayed()->daddi(SP, SP, - wordSize);
aoqi@1 2872
aoqi@1 2873 __ bind(notObj);
aoqi@1 2874 __ move(AT, ctos);
aoqi@1 2875 __ bne(flags, AT, notChar);
aoqi@1 2876 __ delayed()->nop();
aoqi@1 2877
aoqi@1 2878 // ctos
aoqi@1 2879 __ lhu(FSR, index, 0);
aoqi@1 2880 __ sd(FSR, SP, - wordSize);
aoqi@1 2881
aoqi@1 2882 if (!is_static) {
aoqi@1 2883 patch_bytecode(Bytecodes::_fast_cgetfield, T3, T2);
aoqi@1 2884 }
aoqi@1 2885 __ b(Done);
aoqi@1 2886 __ delayed()->daddi(SP, SP, - wordSize);
aoqi@1 2887
aoqi@1 2888 __ bind(notChar);
aoqi@1 2889 __ move(AT, stos);
aoqi@1 2890 __ bne(flags, AT, notShort);
aoqi@1 2891 __ delayed()->nop();
aoqi@1 2892
aoqi@1 2893 // stos
aoqi@1 2894 __ lh(FSR, index, 0);
aoqi@1 2895 __ sd(FSR, SP, - wordSize);
aoqi@1 2896
aoqi@1 2897 if (!is_static) {
aoqi@1 2898 patch_bytecode(Bytecodes::_fast_sgetfield, T3, T2);
aoqi@1 2899 }
aoqi@1 2900 __ b(Done);
aoqi@1 2901 __ delayed()->daddi(SP, SP, - wordSize);
aoqi@1 2902
aoqi@1 2903 __ bind(notShort);
aoqi@1 2904 __ move(AT, ltos);
aoqi@1 2905 __ bne(flags, AT, notLong);
aoqi@1 2906 __ delayed()->nop();
aoqi@1 2907
aoqi@1 2908 // FIXME : the load/store should be atomic, we have no simple method to do this in mips32
aoqi@1 2909 // ltos
aoqi@1 2910 __ ld(FSR, index, 0 * wordSize);
aoqi@1 2911 __ sd(FSR, SP, -2 * wordSize);
aoqi@1 2912 __ sd(R0, SP, -1 * wordSize);
aoqi@1 2913
aoqi@1 2914 // Don't rewrite to _fast_lgetfield for potential volatile case.
aoqi@1 2915 __ b(Done);
aoqi@1 2916 __ delayed()->daddi(SP, SP, - 2 * wordSize);
aoqi@1 2917
aoqi@1 2918 __ bind(notLong);
aoqi@1 2919 __ move(AT, ftos);
aoqi@1 2920 __ bne(flags, AT, notFloat);
aoqi@1 2921 __ delayed()->nop();
aoqi@1 2922
aoqi@1 2923 // ftos
aoqi@1 2924 __ lwc1(FSF, index, 0);
aoqi@1 2925 __ sdc1(FSF, SP, - wordSize);
aoqi@1 2926
aoqi@1 2927 if (!is_static) {
aoqi@1 2928 patch_bytecode(Bytecodes::_fast_fgetfield, T3, T2);
aoqi@1 2929 }
aoqi@1 2930 __ b(Done);
aoqi@1 2931 __ delayed()->daddi(SP, SP, - wordSize);
aoqi@1 2932
aoqi@1 2933 __ bind(notFloat);
aoqi@1 2934 __ move(AT, dtos);
aoqi@1 2935 __ bne(flags, AT, notDouble);
aoqi@1 2936 __ delayed()->nop();
aoqi@1 2937
aoqi@1 2938 // dtos
aoqi@1 2939 __ ldc1(FSF, index, 0 * wordSize);
aoqi@1 2940 __ sdc1(FSF, SP, - 2 * wordSize);
aoqi@1 2941 __ sd(R0, SP, - 1 * wordSize);
aoqi@1 2942
aoqi@1 2943 if (!is_static) {
aoqi@1 2944 patch_bytecode(Bytecodes::_fast_dgetfield, T3, T2);
aoqi@1 2945 }
aoqi@1 2946 __ b(Done);
aoqi@1 2947 __ delayed()->daddi(SP, SP, - 2 * wordSize);
aoqi@1 2948
aoqi@1 2949 __ bind(notDouble);
aoqi@1 2950
aoqi@1 2951 __ stop("Bad state");
aoqi@1 2952
aoqi@1 2953 __ bind(Done);
aoqi@1 2954 }
aoqi@1 2955
aoqi@6880 2956
aoqi@1 2957 void TemplateTable::getfield(int byte_no) {
aoqi@1 2958 getfield_or_static(byte_no, false);
aoqi@1 2959 }
aoqi@1 2960
aoqi@1 2961 void TemplateTable::getstatic(int byte_no) {
aoqi@1 2962 getfield_or_static(byte_no, true);
aoqi@1 2963 }
aoqi@1 2964
aoqi@1 2965 // The registers cache and index expected to be set before call.
aoqi@1 2966 // The function may destroy various registers, just not the cache and index registers.
aoqi@1 2967 void TemplateTable::jvmti_post_field_mod(Register cache, Register index, bool is_static) {
aoqi@6883 2968 transition(vtos, vtos);
aoqi@6883 2969
aoqi@6880 2970 ByteSize cp_base_offset = ConstantPoolCache::base_offset();
aoqi@6880 2971
aoqi@6880 2972 if (JvmtiExport::can_post_field_modification()) {
aoqi@6883 2973 // Check to see if a field modification watch has been set before
aoqi@6883 2974 // we take the time to call into the VM.
aoqi@6880 2975 Label L1;
aoqi@6883 2976 //kill AT, T1, T2, T3, T9
aoqi@6883 2977 Register tmp1 = T2;
aoqi@6883 2978 Register tmp2 = T1;
aoqi@6883 2979 Register tmp3 = T3;
aoqi@6883 2980 Register tmp4 = T9;
aoqi@6883 2981 assert_different_registers(cache, index, tmp4);
aoqi@6880 2982
aoqi@6880 2983 __ li(AT, JvmtiExport::get_field_modification_count_addr());
aoqi@6883 2984 __ lw(AT, AT, 0);
aoqi@6883 2985 __ beq(AT, R0, L1);
aoqi@6880 2986 __ delayed()->nop();
aoqi@6880 2987
aoqi@6883 2988 __ get_cache_and_index_at_bcp(tmp2, tmp4, 1);
aoqi@6880 2989
aoqi@6880 2990 if (is_static) {
aoqi@6883 2991 __ move(tmp1, R0);
aoqi@6880 2992 } else {
aoqi@6883 2993 // Life is harder. The stack holds the value on top, followed by
aoqi@6883 2994 // the object. We don't know the size of the value, though; it
aoqi@6883 2995 // could be one or two words depending on its type. As a result,
aoqi@6883 2996 // we must find the type to determine where the object is.
aoqi@6880 2997 Label two_word, valsize_known;
aoqi@6883 2998 __ dsll(AT, tmp4, Address::times_8);
aoqi@6883 2999 __ dadd(AT, tmp2, AT);
aoqi@6883 3000 __ ld(tmp3, AT, in_bytes(cp_base_offset +
aoqi@6883 3001 ConstantPoolCacheEntry::flags_offset()));
aoqi@6883 3002 __ shr(tmp3, ConstantPoolCacheEntry::tos_state_shift);
aoqi@6880 3003
aoqi@6880 3004 // Make sure we don't need to mask ecx for tos_state_shift
aoqi@6880 3005 // after the above shift
aoqi@6880 3006 ConstantPoolCacheEntry::verify_tos_state_shift();
aoqi@6883 3007 __ move(tmp1, SP);
aoqi@6880 3008 __ move(AT, ltos);
aoqi@6883 3009 __ beq(tmp3, AT, two_word);
aoqi@6880 3010 __ delayed()->nop();
aoqi@6880 3011 __ move(AT, dtos);
aoqi@6883 3012 __ beq(tmp3, AT, two_word);
aoqi@6880 3013 __ delayed()->nop();
aoqi@6880 3014 __ b(valsize_known);
aoqi@6883 3015 __ delayed()->daddi(tmp1, tmp1, Interpreter::expr_offset_in_bytes(1) );
aoqi@6880 3016
aoqi@6880 3017 __ bind(two_word);
aoqi@6883 3018 __ daddi(tmp1, tmp1, Interpreter::expr_offset_in_bytes(2));
aoqi@6880 3019
aoqi@6880 3020 __ bind(valsize_known);
aoqi@6880 3021 // setup object pointer
aoqi@6883 3022 __ ld(tmp1, tmp1, 0*wordSize);
aoqi@6880 3023 }
aoqi@6880 3024 // cache entry pointer
aoqi@6883 3025 __ daddi(tmp2, tmp2, in_bytes(cp_base_offset));
aoqi@6883 3026 __ shl(tmp4, LogBytesPerWord);
aoqi@6883 3027 __ daddu(tmp2, tmp2, tmp4);
aoqi@6880 3028 // object (tos)
aoqi@6883 3029 __ move(tmp3, SP);
aoqi@6883 3030 // tmp1: object pointer set up above (NULL if static)
aoqi@6883 3031 // tmp2: cache entry pointer
aoqi@6883 3032 // tmp3: jvalue object on the stack
aoqi@6883 3033 __ call_VM(NOREG,
aoqi@6883 3034 CAST_FROM_FN_PTR(address,
aoqi@6883 3035 InterpreterRuntime::post_field_modification),
aoqi@6883 3036 tmp1, tmp2, tmp3);
aoqi@6880 3037 __ get_cache_and_index_at_bcp(cache, index, 1);
aoqi@6880 3038 __ bind(L1);
aoqi@6880 3039 }
aoqi@1 3040 }
aoqi@1 3041
aoqi@1 3042 // used registers : T0, T1, T2, T3, T8
aoqi@1 3043 // T1 : flags
aoqi@1 3044 // T2 : off
aoqi@1 3045 // T3 : obj
aoqi@1 3046 // T8 : volatile bit
aoqi@1 3047 // see ConstantPoolCacheEntry::set_field for more info
aoqi@1 3048 void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
aoqi@1 3049 transition(vtos, vtos);
aoqi@1 3050
aoqi@1 3051 const Register cache = T3;
aoqi@1 3052 const Register index = T0;
aoqi@1 3053 const Register obj = T3;
aoqi@1 3054 const Register off = T2;
aoqi@1 3055 const Register flags = T1;
aoqi@1 3056 const Register bc = T3;
aoqi@1 3057
aoqi@1 3058 resolve_cache_and_index(byte_no, cache, index, sizeof(u2));
aoqi@6883 3059 jvmti_post_field_mod(cache, index, is_static);
aoqi@1 3060 load_field_cp_cache_entry(obj, cache, index, off, flags, is_static);
aoqi@1 3061
aoqi@1 3062 Label notVolatile, Done;
aoqi@1 3063 __ move(AT, 1<<ConstantPoolCacheEntry::is_volatile_shift);
aoqi@1 3064 __ andr(T8, flags, AT);
aoqi@1 3065
aoqi@1 3066 Label notByte, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble;
aoqi@6880 3067
aoqi@1 3068 assert(btos == 0, "change code, btos != 0");
aoqi@1 3069 // btos
aoqi@1 3070 __ dsrl(flags, flags, ConstantPoolCacheEntry::tos_state_shift);
aoqi@1 3071 __ andi(flags, flags, ConstantPoolCacheEntry::tos_state_mask);
aoqi@1 3072 __ bne(flags, R0, notByte);
aoqi@1 3073 __ delayed()->nop();
aoqi@1 3074
aoqi@1 3075 __ pop(btos);
aoqi@1 3076 if (!is_static) {
aoqi@6880 3077 pop_and_check_object(obj);
aoqi@1 3078 }
aoqi@1 3079 __ dadd(AT, obj, off);
aoqi@1 3080 __ sb(FSR, AT, 0);
aoqi@1 3081
aoqi@1 3082 if (!is_static) {
aoqi@1 3083 patch_bytecode(Bytecodes::_fast_bputfield, bc, off, true, byte_no);
aoqi@1 3084 }
aoqi@1 3085 __ b(Done);
aoqi@1 3086 __ delayed()->nop();
aoqi@1 3087
aoqi@1 3088 __ bind(notByte);
aoqi@1 3089 // itos
aoqi@1 3090 __ move(AT, itos);
aoqi@1 3091 __ bne(flags, AT, notInt);
aoqi@1 3092 __ delayed()->nop();
aoqi@1 3093
aoqi@1 3094 __ pop(itos);
aoqi@1 3095 if (!is_static) {
aoqi@6880 3096 pop_and_check_object(obj);
aoqi@1 3097 }
aoqi@1 3098 __ dadd(AT, obj, off);
aoqi@1 3099 __ sw(FSR, AT, 0);
aoqi@1 3100
aoqi@1 3101 if (!is_static) {
aoqi@1 3102 patch_bytecode(Bytecodes::_fast_iputfield, bc, off, true, byte_no);
aoqi@1 3103 }
aoqi@1 3104 __ b(Done);
aoqi@6880 3105 __ delayed()->nop();
aoqi@1 3106 __ bind(notInt);
aoqi@1 3107 // atos
aoqi@1 3108 __ move(AT, atos);
aoqi@1 3109 __ bne(flags, AT, notObj);
aoqi@1 3110 __ delayed()->nop();
aoqi@1 3111
aoqi@1 3112 __ pop(atos);
aoqi@1 3113 if (!is_static) {
aoqi@6880 3114 pop_and_check_object(obj);
aoqi@1 3115 }
aoqi@1 3116
aoqi@1 3117 __ dadd(AT, obj, off);
aoqi@1 3118 __ store_heap_oop(Address(AT, 0), FSR);
aoqi@1 3119 __ store_check(obj);
aoqi@1 3120
aoqi@1 3121 if (!is_static) {
aoqi@1 3122 patch_bytecode(Bytecodes::_fast_aputfield, bc, off, true, byte_no);
aoqi@1 3123 }
aoqi@1 3124 __ b(Done);
aoqi@1 3125 __ delayed()->nop();
aoqi@1 3126 __ bind(notObj);
aoqi@1 3127 // ctos
aoqi@1 3128 __ move(AT, ctos);
aoqi@1 3129 __ bne(flags, AT, notChar);
aoqi@1 3130 __ delayed()->nop();
aoqi@1 3131
aoqi@1 3132 __ pop(ctos);
aoqi@1 3133 if (!is_static) {
aoqi@6880 3134 pop_and_check_object(obj);
aoqi@1 3135 }
aoqi@1 3136 __ dadd(AT, obj, off);
aoqi@1 3137 __ sh(FSR, AT, 0);
aoqi@1 3138 if (!is_static) {
aoqi@1 3139 patch_bytecode(Bytecodes::_fast_cputfield, bc, off, true, byte_no);
aoqi@1 3140 }
aoqi@1 3141 __ b(Done);
aoqi@1 3142 __ delayed()->nop();
aoqi@1 3143 __ bind(notChar);
aoqi@1 3144 // stos
aoqi@1 3145 __ move(AT, stos);
aoqi@1 3146 __ bne(flags, AT, notShort);
aoqi@1 3147 __ delayed()->nop();
aoqi@1 3148
aoqi@1 3149 __ pop(stos);
aoqi@1 3150 if (!is_static) {
aoqi@6880 3151 pop_and_check_object(obj);
aoqi@1 3152 }
aoqi@1 3153 __ dadd(AT, obj, off);
aoqi@1 3154 __ sh(FSR, AT, 0);
aoqi@1 3155 if (!is_static) {
aoqi@1 3156 patch_bytecode(Bytecodes::_fast_sputfield, bc, off, true, byte_no);
aoqi@1 3157 }
aoqi@1 3158 __ b(Done);
aoqi@1 3159 __ delayed()->nop();
aoqi@1 3160 __ bind(notShort);
aoqi@1 3161 // ltos
aoqi@1 3162 __ move(AT, ltos);
aoqi@1 3163 __ bne(flags, AT, notLong);
aoqi@1 3164 __ delayed()->nop();
aoqi@1 3165
aoqi@1 3166 // FIXME: there is no simple method to load/store 64-bit data in a atomic operation
aoqi@1 3167 // we just ignore the volatile flag.
aoqi@1 3168 //Label notVolatileLong;
aoqi@1 3169 //__ beq(T1, R0, notVolatileLong);
aoqi@1 3170 //__ delayed()->nop();
aoqi@1 3171
aoqi@1 3172 //addent = 2 * wordSize;
aoqi@1 3173 // no need
aoqi@1 3174 //__ lw(FSR, SP, 0);
aoqi@1 3175 //__ lw(SSR, SP, 1 * wordSize);
aoqi@1 3176 //if (!is_static) {
aoqi@6880 3177 // __ lw(T3, SP, addent);
aoqi@6880 3178 // addent += 1 * wordSize;
aoqi@6880 3179 // __ verify_oop(T3);
aoqi@1 3180 //}
aoqi@1 3181
aoqi@1 3182 //__ daddu(AT, T3, T2);
aoqi@1 3183
aoqi@1 3184 // Replace with real volatile test
aoqi@1 3185 // NOTE : we assume that sdc1&ldc1 operate in 32-bit, this is true for Godson2 even in 64-bit kernel
aoqi@1 3186 // last modified by yjl 7/12/2005
aoqi@6880 3187 //__ ldc1(FSF, SP, 0);
aoqi@1 3188 //__ sdc1(FSF, AT, 0);
aoqi@1 3189 //volatile_barrier();
aoqi@1 3190
aoqi@1 3191 // Don't rewrite volatile version
aoqi@1 3192 //__ b(notVolatile);
aoqi@1 3193 //__ delayed()->addiu(SP, SP, addent);
aoqi@1 3194
aoqi@1 3195 //__ bind(notVolatileLong);
aoqi@1 3196
aoqi@1 3197 //__ pop(ltos); // overwrites edx
aoqi@6880 3198 // __ lw(FSR, SP, 0 * wordSize);
aoqi@6880 3199 // __ lw(SSR, SP, 1 * wordSize);
aoqi@6880 3200 // __ daddi(SP, SP, 2*wordSize);
aoqi@1 3201 __ pop(ltos);
aoqi@1 3202 if (!is_static) {
aoqi@6880 3203 pop_and_check_object(obj);
aoqi@1 3204 }
aoqi@1 3205 __ dadd(AT, obj, off);
aoqi@1 3206 __ sd(FSR, AT, 0);
aoqi@1 3207 if (!is_static) {
aoqi@1 3208 patch_bytecode(Bytecodes::_fast_lputfield, bc, off, true, byte_no);
aoqi@1 3209 }
aoqi@1 3210 __ b(notVolatile);
aoqi@1 3211 __ delayed()->nop();
aoqi@1 3212
aoqi@1 3213 __ bind(notLong);
aoqi@1 3214 // ftos
aoqi@1 3215 __ move(AT, ftos);
aoqi@1 3216 __ bne(flags, AT, notFloat);
aoqi@1 3217 __ delayed()->nop();
aoqi@1 3218
aoqi@1 3219 __ pop(ftos);
aoqi@1 3220 if (!is_static) {
aoqi@6880 3221 pop_and_check_object(obj);
aoqi@1 3222 }
aoqi@1 3223 __ dadd(AT, obj, off);
aoqi@1 3224 __ swc1(FSF, AT, 0);
aoqi@1 3225 if (!is_static) {
aoqi@1 3226 patch_bytecode(Bytecodes::_fast_fputfield, bc, off, true, byte_no);
aoqi@1 3227 }
aoqi@1 3228 __ b(Done);
aoqi@1 3229 __ delayed()->nop();
aoqi@1 3230 __ bind(notFloat);
aoqi@1 3231 // dtos
aoqi@1 3232 __ move(AT, dtos);
aoqi@1 3233 __ bne(flags, AT, notDouble);
aoqi@1 3234 __ delayed()->nop();
aoqi@1 3235
aoqi@1 3236 __ pop(dtos);
aoqi@1 3237 if (!is_static) {
aoqi@6880 3238 pop_and_check_object(obj);
aoqi@1 3239 }
aoqi@1 3240 __ dadd(AT, obj, off);
aoqi@1 3241 __ sdc1(FSF, AT, 0);
aoqi@1 3242 if (!is_static) {
aoqi@1 3243 patch_bytecode(Bytecodes::_fast_dputfield, bc, off, true, byte_no);
aoqi@1 3244 }
aoqi@6880 3245
aoqi@6880 3246 #ifdef ASSERT
aoqi@1 3247 __ b(Done);
aoqi@1 3248 __ delayed()->nop();
aoqi@6880 3249
aoqi@1 3250 __ bind(notDouble);
aoqi@1 3251 __ stop("Bad state");
aoqi@6880 3252 #endif
aoqi@1 3253
aoqi@1 3254 __ bind(Done);
aoqi@1 3255
aoqi@1 3256 // Check for volatile store
aoqi@1 3257 __ beq(T8, R0, notVolatile);
aoqi@1 3258 __ delayed()->nop();
aoqi@1 3259 volatile_barrier( );
aoqi@1 3260 __ bind(notVolatile);
aoqi@1 3261 }
aoqi@1 3262
aoqi@1 3263 void TemplateTable::putfield(int byte_no) {
aoqi@1 3264 putfield_or_static(byte_no, false);
aoqi@1 3265 }
aoqi@1 3266
aoqi@1 3267 void TemplateTable::putstatic(int byte_no) {
aoqi@1 3268 putfield_or_static(byte_no, true);
aoqi@1 3269 }
aoqi@1 3270
aoqi@1 3271 // used registers : T1, T2, T3
aoqi@1 3272 // T1 : cp_entry
aoqi@1 3273 // T2 : obj
aoqi@1 3274 // T3 : value pointer
aoqi@1 3275 void TemplateTable::jvmti_post_fast_field_mod() {
aoqi@6880 3276 if (JvmtiExport::can_post_field_modification()) {
aoqi@6880 3277 // Check to see if a field modification watch has been set before
aoqi@6880 3278 // we take the time to call into the VM.
aoqi@6880 3279 Label L2;
aoqi@6883 3280 //kill AT, T1, T2, T3, T9
aoqi@6883 3281 Register tmp1 = T2;
aoqi@6883 3282 Register tmp2 = T1;
aoqi@6883 3283 Register tmp3 = T3;
aoqi@6883 3284 Register tmp4 = T9;
aoqi@6880 3285 __ li(AT, JvmtiExport::get_field_modification_count_addr());
aoqi@6883 3286 __ lw(tmp3, AT, 0);
aoqi@6883 3287 __ beq(tmp3, R0, L2);
aoqi@6880 3288 __ delayed()->nop();
aoqi@6883 3289 __ pop_ptr(tmp1);
aoqi@6883 3290 __ verify_oop(tmp1);
aoqi@6883 3291 __ push_ptr(tmp1);
aoqi@6880 3292 switch (bytecode()) { // load values into the jvalue object
aoqi@6883 3293 case Bytecodes::_fast_aputfield: __ push_ptr(FSR); break;
aoqi@6883 3294 case Bytecodes::_fast_bputfield: // fall through
aoqi@6883 3295 case Bytecodes::_fast_sputfield: // fall through
aoqi@6883 3296 case Bytecodes::_fast_cputfield: // fall through
aoqi@6883 3297 case Bytecodes::_fast_iputfield: __ push_i(FSR); break;
aoqi@6883 3298 case Bytecodes::_fast_dputfield: __ push_d(FSF); break;
aoqi@6883 3299 case Bytecodes::_fast_fputfield: __ push_f(); break;
aoqi@6883 3300 case Bytecodes::_fast_lputfield: __ push_l(FSR); break;
aoqi@6880 3301 default: ShouldNotReachHere();
aoqi@6880 3302 }
aoqi@6883 3303 __ move(tmp3, SP);
aoqi@6880 3304 // access constant pool cache entry
aoqi@6883 3305 __ get_cache_entry_pointer_at_bcp(tmp2, FSR, 1);
aoqi@6883 3306 __ verify_oop(tmp1);
aoqi@6883 3307 // tmp1: object pointer copied above
aoqi@6883 3308 // tmp2: cache entry pointer
aoqi@6883 3309 // tmp3: jvalue object on the stack
aoqi@6883 3310 __ call_VM(NOREG,
aoqi@6883 3311 CAST_FROM_FN_PTR(address,
aoqi@6883 3312 InterpreterRuntime::post_field_modification),
aoqi@6883 3313 tmp1, tmp2, tmp3);
aoqi@6883 3314
aoqi@6883 3315 switch (bytecode()) { // restore tos values
aoqi@6883 3316 case Bytecodes::_fast_aputfield: __ pop_ptr(FSR); break;
aoqi@6883 3317 case Bytecodes::_fast_bputfield: // fall through
aoqi@6883 3318 case Bytecodes::_fast_sputfield: // fall through
aoqi@6883 3319 case Bytecodes::_fast_cputfield: // fall through
aoqi@6883 3320 case Bytecodes::_fast_iputfield: __ pop_i(FSR); break;
aoqi@6883 3321 case Bytecodes::_fast_dputfield: __ pop_d(); break;
aoqi@6883 3322 case Bytecodes::_fast_fputfield: __ pop_f(); break;
aoqi@6883 3323 case Bytecodes::_fast_lputfield: __ pop_l(FSR); break;
aoqi@6883 3324 }
aoqi@6880 3325 __ bind(L2);
aoqi@6880 3326 }
aoqi@1 3327 }
aoqi@1 3328
aoqi@1 3329 // used registers : T2, T3, T1
aoqi@1 3330 // T2 : index & off & field address
aoqi@1 3331 // T3 : cache & obj
aoqi@1 3332 // T1 : flags
aoqi@1 3333 void TemplateTable::fast_storefield(TosState state) {
aoqi@1 3334 transition(state, vtos);
aoqi@1 3335
aoqi@1 3336 ByteSize base = ConstantPoolCache::base_offset();
aoqi@1 3337
aoqi@1 3338 jvmti_post_fast_field_mod();
aoqi@1 3339
aoqi@1 3340 // access constant pool cache
aoqi@1 3341 __ get_cache_and_index_at_bcp(T3, T2, 1);
aoqi@1 3342
aoqi@1 3343 // test for volatile with edx but edx is tos register for lputfield.
aoqi@6880 3344 __ dsll(AT, T2, Address::times_8);
aoqi@1 3345 __ dadd(AT, T3, AT);
aoqi@1 3346 __ ld(T1, AT, in_bytes(base + ConstantPoolCacheEntry::flags_offset()));
aoqi@1 3347
aoqi@1 3348 // replace index with field offset from cache entry
aoqi@1 3349 __ ld(T2, AT, in_bytes(base + ConstantPoolCacheEntry::f2_offset()));
aoqi@1 3350
aoqi@1 3351 // Doug Lea believes this is not needed with current Sparcs (TSO) and Intel (PSO).
aoqi@1 3352 // volatile_barrier( );
aoqi@1 3353
aoqi@1 3354 Label notVolatile, Done;
aoqi@1 3355 // Check for volatile store
aoqi@1 3356 __ move(AT, 1<<ConstantPoolCacheEntry::is_volatile_shift);
aoqi@1 3357 __ andr(AT, T1, AT);
aoqi@1 3358 __ beq(AT, R0, notVolatile);
aoqi@1 3359 __ delayed()->nop();
aoqi@1 3360
aoqi@1 3361
aoqi@1 3362 // Get object from stack
aoqi@1 3363 pop_and_check_object(T3);
aoqi@6880 3364
aoqi@6880 3365 // field address
aoqi@1 3366 __ dadd(T2, T3, T2);
aoqi@1 3367
aoqi@1 3368 // access field
aoqi@1 3369 switch (bytecode()) {
aoqi@6880 3370 case Bytecodes::_fast_bputfield:
aoqi@1 3371 __ sb(FSR, T2, 0);
aoqi@1 3372 break;
aoqi@1 3373 case Bytecodes::_fast_sputfield: // fall through
aoqi@6880 3374 case Bytecodes::_fast_cputfield:
aoqi@1 3375 __ sh(FSR, T2, 0);
aoqi@1 3376 break;
aoqi@6880 3377 case Bytecodes::_fast_iputfield:
aoqi@1 3378 __ sw(FSR, T2, 0);
aoqi@1 3379 break;
aoqi@6880 3380 case Bytecodes::_fast_lputfield:
aoqi@1 3381 __ sd(FSR, T2, 0 * wordSize);
aoqi@1 3382 break;
aoqi@6880 3383 case Bytecodes::_fast_fputfield:
aoqi@1 3384 __ swc1(FSF, T2, 0);
aoqi@1 3385 break;
aoqi@6880 3386 case Bytecodes::_fast_dputfield:
aoqi@1 3387 __ sdc1(FSF, T2, 0 * wordSize);
aoqi@1 3388 break;
aoqi@6880 3389 case Bytecodes::_fast_aputfield:
aoqi@1 3390 __ store_heap_oop(Address(T2, 0), FSR);
aoqi@1 3391 __ store_check(T3);
aoqi@1 3392 break;
aoqi@1 3393 default:
aoqi@1 3394 ShouldNotReachHere();
aoqi@1 3395 }
aoqi@1 3396
aoqi@1 3397 Label done;
aoqi@1 3398 volatile_barrier( );
aoqi@1 3399 __ b(done);
aoqi@1 3400 __ delayed()->nop();
aoqi@1 3401
aoqi@1 3402 // Same code as above, but don't need edx to test for volatile.
aoqi@1 3403 __ bind(notVolatile);
aoqi@1 3404 pop_and_check_object(T3);
aoqi@1 3405 //get the field address
aoqi@1 3406 __ dadd(T2, T3, T2);
aoqi@1 3407
aoqi@1 3408 // access field
aoqi@1 3409 switch (bytecode()) {
aoqi@6880 3410 case Bytecodes::_fast_bputfield:
aoqi@6880 3411 __ sb(FSR, T2, 0);
aoqi@1 3412 break;
aoqi@1 3413 case Bytecodes::_fast_sputfield: // fall through
aoqi@6880 3414 case Bytecodes::_fast_cputfield:
aoqi@1 3415 __ sh(FSR, T2, 0);
aoqi@1 3416 break;
aoqi@6880 3417 case Bytecodes::_fast_iputfield:
aoqi@1 3418 __ sw(FSR, T2, 0);
aoqi@1 3419 break;
aoqi@6880 3420 case Bytecodes::_fast_lputfield:
aoqi@1 3421 __ sd(FSR, T2, 0 * wordSize);
aoqi@1 3422 break;
aoqi@6880 3423 case Bytecodes::_fast_fputfield:
aoqi@1 3424 __ swc1(FSF, T2, 0);
aoqi@1 3425 break;
aoqi@6880 3426 case Bytecodes::_fast_dputfield:
aoqi@1 3427 __ sdc1(FSF, T2, 0 * wordSize);
aoqi@1 3428 break;
aoqi@6880 3429 case Bytecodes::_fast_aputfield:
aoqi@1 3430 //add for compressedoops
aoqi@1 3431 __ store_heap_oop(Address(T2, 0), FSR);
aoqi@1 3432 __ store_check(T3);
aoqi@1 3433 break;
aoqi@1 3434 default:
aoqi@1 3435 ShouldNotReachHere();
aoqi@1 3436 }
aoqi@1 3437 __ bind(done);
aoqi@1 3438 }
aoqi@1 3439
aoqi@1 3440 // used registers : T2, T3, T1
aoqi@1 3441 // T3 : cp_entry & cache
aoqi@1 3442 // T2 : index & offset
aoqi@1 3443 void TemplateTable::fast_accessfield(TosState state) {
aoqi@1 3444 transition(atos, state);
aoqi@1 3445
aoqi@1 3446 // do the JVMTI work here to avoid disturbing the register state below
aoqi@1 3447 if (JvmtiExport::can_post_field_access()) {
aoqi@1 3448 // Check to see if a field access watch has been set before we take
aoqi@1 3449 // the time to call into the VM.
aoqi@1 3450 Label L1;
aoqi@1 3451 __ li(AT, (intptr_t)JvmtiExport::get_field_access_count_addr());
aoqi@1 3452 __ lw(T3, AT, 0);
aoqi@1 3453 __ beq(T3, R0, L1);
aoqi@1 3454 __ delayed()->nop();
aoqi@1 3455 // access constant pool cache entry
aoqi@1 3456 __ get_cache_entry_pointer_at_bcp(T3, T1, 1);
aoqi@1 3457 __ move(TSR, FSR);
aoqi@1 3458 __ verify_oop(FSR);
aoqi@1 3459 // FSR: object pointer copied above
aoqi@1 3460 // T3: cache entry pointer
aoqi@6880 3461 __ call_VM(NOREG,
aoqi@6880 3462 CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_access),
aoqi@6880 3463 FSR, T3);
aoqi@1 3464 __ move(FSR, TSR);
aoqi@1 3465 __ bind(L1);
aoqi@1 3466 }
aoqi@1 3467
aoqi@1 3468 // access constant pool cache
aoqi@1 3469 __ get_cache_and_index_at_bcp(T3, T2, 1);
aoqi@1 3470 // replace index with field offset from cache entry
aoqi@1 3471 __ dsll(AT, T2, Address::times_8);
aoqi@1 3472 __ dadd(AT, T3, AT);
aoqi@6880 3473 __ ld(T2, AT, in_bytes(ConstantPoolCache::base_offset()
aoqi@6880 3474 + ConstantPoolCacheEntry::f2_offset()));
aoqi@1 3475
aoqi@1 3476 // eax: object
aoqi@1 3477 __ verify_oop(FSR);
aoqi@1 3478 __ null_check(FSR);
aoqi@1 3479 // field addresses
aoqi@1 3480 __ dadd(FSR, FSR, T2);
aoqi@1 3481
aoqi@1 3482 // access field
aoqi@1 3483 switch (bytecode()) {
aoqi@6880 3484 case Bytecodes::_fast_bgetfield:
aoqi@1 3485 __ lb(FSR, FSR, 0);
aoqi@1 3486 break;
aoqi@6880 3487 case Bytecodes::_fast_sgetfield:
aoqi@1 3488 __ lh(FSR, FSR, 0);
aoqi@1 3489 break;
aoqi@6880 3490 case Bytecodes::_fast_cgetfield:
aoqi@1 3491 __ lhu(FSR, FSR, 0);
aoqi@1 3492 break;
aoqi@1 3493 case Bytecodes::_fast_igetfield:
aoqi@1 3494 __ lw(FSR, FSR, 0);
aoqi@1 3495 break;
aoqi@6880 3496 case Bytecodes::_fast_lgetfield:
aoqi@6880 3497 __ stop("should not be rewritten");
aoqi@1 3498 break;
aoqi@6880 3499 case Bytecodes::_fast_fgetfield:
aoqi@1 3500 __ lwc1(FSF, FSR, 0);
aoqi@1 3501 break;
aoqi@6880 3502 case Bytecodes::_fast_dgetfield:
aoqi@1 3503 __ ldc1(FSF, FSR, 0);
aoqi@1 3504 break;
aoqi@1 3505 case Bytecodes::_fast_agetfield:
aoqi@1 3506 //add for compressedoops
aoqi@1 3507 __ load_heap_oop(FSR, Address(FSR, 0));
aoqi@1 3508 __ verify_oop(FSR);
aoqi@1 3509 break;
aoqi@1 3510 default:
aoqi@1 3511 ShouldNotReachHere();
aoqi@1 3512 }
aoqi@1 3513
aoqi@1 3514 // Doug Lea believes this is not needed with current Sparcs(TSO) and Intel(PSO)
aoqi@1 3515 // volatile_barrier( );
aoqi@1 3516 }
aoqi@1 3517
aoqi@1 3518 // generator for _fast_iaccess_0, _fast_aaccess_0, _fast_faccess_0
aoqi@1 3519 // used registers : T1, T2, T3, T1
aoqi@1 3520 // T1 : obj & field address
aoqi@1 3521 // T2 : off
aoqi@1 3522 // T3 : cache
aoqi@1 3523 // T1 : index
aoqi@1 3524 void TemplateTable::fast_xaccess(TosState state) {
aoqi@1 3525 transition(vtos, state);
aoqi@6880 3526
aoqi@1 3527 // get receiver
aoqi@1 3528 __ ld(T1, aaddress(0));
aoqi@1 3529 // access constant pool cache
aoqi@1 3530 __ get_cache_and_index_at_bcp(T3, T2, 2);
aoqi@1 3531 __ dsll(AT, T2, Address::times_8);
aoqi@1 3532 __ dadd(AT, T3, AT);
aoqi@6880 3533 __ ld(T2, AT, in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::f2_offset()));
aoqi@6880 3534
aoqi@6880 3535 // make sure exception is reported in correct bcp range (getfield is
aoqi@6880 3536 // next instruction)
aoqi@1 3537 __ daddi(BCP, BCP, 1);
aoqi@1 3538 __ null_check(T1);
aoqi@1 3539 __ dadd(T1, T1, T2);
aoqi@1 3540
aoqi@1 3541 if (state == itos) {
aoqi@1 3542 __ lw(FSR, T1, 0);
aoqi@1 3543 } else if (state == atos) {
aoqi@1 3544 __ load_heap_oop(FSR, Address(T1, 0));
aoqi@1 3545 __ verify_oop(FSR);
aoqi@1 3546 } else if (state == ftos) {
aoqi@1 3547 __ lwc1(FSF, T1, 0);
aoqi@1 3548 } else {
aoqi@1 3549 ShouldNotReachHere();
aoqi@1 3550 }
aoqi@1 3551 __ daddi(BCP, BCP, -1);
aoqi@1 3552 }
aoqi@1 3553
aoqi@6880 3554
aoqi@6880 3555
aoqi@6880 3556 //-----------------------------------------------------------------------------
aoqi@1 3557 // Calls
aoqi@1 3558
aoqi@6880 3559 void TemplateTable::count_calls(Register method, Register temp) {
aoqi@6880 3560 // implemented elsewhere
aoqi@6880 3561 ShouldNotReachHere();
aoqi@1 3562 }
aoqi@1 3563
aoqi@1 3564 // method, index, recv, flags: T1, T2, T3, T1
aoqi@1 3565 // byte_no = 2 for _invokevirtual, 1 else
aoqi@1 3566 // T0 : return address
aoqi@6880 3567 // get the method & index of the invoke, and push the return address of
aoqi@1 3568 // the invoke(first word in the frame)
aoqi@1 3569 // this address is where the return code jmp to.
aoqi@1 3570 // NOTE : this method will set T3&T1 as recv&flags
aoqi@1 3571 void TemplateTable::prepare_invoke(int byte_no,
aoqi@6880 3572 Register method, // linked method (or i-klass)
aoqi@6880 3573 Register index, // itable index, MethodType, etc.
aoqi@6880 3574 Register recv, // if caller wants to see it
aoqi@6880 3575 Register flags // if caller wants to test it
aoqi@6880 3576 ) {
aoqi@1 3577 // determine flags
aoqi@1 3578 const Bytecodes::Code code = bytecode();
aoqi@1 3579 const bool is_invokeinterface = code == Bytecodes::_invokeinterface;
aoqi@1 3580 const bool is_invokedynamic = code == Bytecodes::_invokedynamic;
aoqi@1 3581 const bool is_invokehandle = code == Bytecodes::_invokehandle;
aoqi@1 3582 const bool is_invokevirtual = code == Bytecodes::_invokevirtual;
aoqi@1 3583 const bool is_invokespecial = code == Bytecodes::_invokespecial;
aoqi@1 3584 const bool load_receiver = (recv != noreg);
aoqi@1 3585 const bool save_flags = (flags != noreg);
aoqi@1 3586 assert(load_receiver == (code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic),"");
aoqi@1 3587 assert(save_flags == (is_invokeinterface || is_invokevirtual), "need flags for vfinal");
aoqi@1 3588 assert(flags == noreg || flags == T1, "error flags reg.");
aoqi@1 3589 assert(recv == noreg || recv == T3, "error recv reg.");
aoqi@6880 3590
aoqi@1 3591 // setup registers & access constant pool cache
aoqi@1 3592 if(recv == noreg) recv = T3;
aoqi@1 3593 if(flags == noreg) flags = T1;
aoqi@1 3594 assert_different_registers(method, index, recv, flags);
aoqi@1 3595
aoqi@1 3596 // save 'interpreter return address'
aoqi@1 3597 __ save_bcp();
aoqi@1 3598
aoqi@1 3599 load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual, false, is_invokedynamic);
aoqi@6880 3600
aoqi@1 3601 if (is_invokedynamic || is_invokehandle) {
aoqi@1 3602 Label L_no_push;
aoqi@1 3603 __ move(AT, (1 << ConstantPoolCacheEntry::has_appendix_shift));
aoqi@1 3604 __ andr(AT, AT, flags);
aoqi@1 3605 __ beq(AT, R0, L_no_push);
aoqi@1 3606 __ delayed()->nop();
aoqi@1 3607 // Push the appendix as a trailing parameter.
aoqi@1 3608 // This must be done before we get the receiver,
aoqi@1 3609 // since the parameter_size includes it.
aoqi@1 3610 Register tmp = SSR;
aoqi@1 3611 __ push(tmp);
aoqi@1 3612 __ move(tmp, index);
aoqi@1 3613 assert(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset == 0, "appendix expected at index+0");
aoqi@1 3614 __ load_resolved_reference_at_index(index, tmp);
aoqi@1 3615 __ pop(tmp);
aoqi@1 3616 __ push(index); // push appendix (MethodType, CallSite, etc.)
aoqi@1 3617 __ bind(L_no_push);
aoqi@1 3618 }
aoqi@1 3619
aoqi@6880 3620 // load receiver if needed (after appendix is pushed so parameter size is correct)
aoqi@6880 3621 // Note: no return address pushed yet
aoqi@1 3622 if (load_receiver) {
aoqi@6880 3623 __ move(AT, ConstantPoolCacheEntry::parameter_size_mask);
aoqi@6880 3624 __ andr(recv, flags, AT);
aoqi@6880 3625 // 2014/07/31 Fu: Since we won't push RA on stack, no_return_pc_pushed_yet should be 0.
aoqi@6880 3626 const int no_return_pc_pushed_yet = 0; // argument slot correction before we push return address
aoqi@6880 3627 const int receiver_is_at_end = -1; // back off one slot to get receiver
aoqi@6880 3628 Address recv_addr = __ argument_address(recv, no_return_pc_pushed_yet + receiver_is_at_end);
aoqi@6880 3629 __ ld(recv, recv_addr);
aoqi@6880 3630 __ verify_oop(recv);
aoqi@1 3631 }
aoqi@1 3632 if(save_flags) {
aoqi@1 3633 __ move(BCP, flags);
aoqi@1 3634 }
aoqi@6880 3635
aoqi@1 3636 // compute return type
aoqi@1 3637 __ dsrl(flags, flags, ConstantPoolCacheEntry::tos_state_shift);
aoqi@1 3638 __ andi(flags, flags, 0xf);
aoqi@1 3639
aoqi@1 3640 // Make sure we don't need to mask flags for tos_state_shift after the above shift
aoqi@1 3641 ConstantPoolCacheEntry::verify_tos_state_shift();
aoqi@1 3642 // load return address
aoqi@6880 3643 {
aoqi@1 3644 const address table = (address) Interpreter::invoke_return_entry_table_for(code);
aoqi@1 3645 __ li(AT, (long)table);
aoqi@1 3646 __ dsll(flags, flags, LogBytesPerWord);
aoqi@1 3647 __ dadd(AT, AT, flags);
aoqi@1 3648 __ ld(RA, AT, 0);
aoqi@1 3649 }
aoqi@6880 3650
aoqi@1 3651 if (save_flags) {
aoqi@1 3652 __ move(flags, BCP);
aoqi@1 3653 __ restore_bcp();
aoqi@1 3654 }
aoqi@1 3655 }
aoqi@1 3656
aoqi@1 3657 // used registers : T0, T3, T1, T2
aoqi@1 3658 // T3 : recv, this two register using convention is by prepare_invoke
aoqi@1 3659 // T1 : flags, klass
aoqi@1 3660 // Rmethod : method, index must be Rmethod
aoqi@6880 3661 void TemplateTable::invokevirtual_helper(Register index,
aoqi@6880 3662 Register recv,
aoqi@6880 3663 Register flags) {
aoqi@1 3664
aoqi@1 3665 assert_different_registers(index, recv, flags, T2);
aoqi@1 3666
aoqi@1 3667 // Test for an invoke of a final method
aoqi@1 3668 Label notFinal;
aoqi@1 3669 __ move(AT, (1 << ConstantPoolCacheEntry::is_vfinal_shift));
aoqi@1 3670 __ andr(AT, flags, AT);
aoqi@1 3671 __ beq(AT, R0, notFinal);
aoqi@1 3672 __ delayed()->nop();
aoqi@1 3673
aoqi@1 3674 Register method = index; // method must be Rmethod
aoqi@1 3675 assert(method == Rmethod, "methodOop must be Rmethod for interpreter calling convention");
aoqi@1 3676
aoqi@1 3677 // do the call - the index is actually the method to call
aoqi@6880 3678 // the index is indeed methodOop, for this is vfinal,
aoqi@1 3679 // see ConstantPoolCacheEntry::set_method for more info
aoqi@1 3680
aoqi@1 3681 __ verify_oop(method);
aoqi@1 3682
aoqi@1 3683 // It's final, need a null check here!
aoqi@1 3684 __ null_check(recv);
aoqi@1 3685
aoqi@1 3686 // profile this call
aoqi@1 3687 __ profile_final_call(T2);
aoqi@1 3688
aoqi@6880 3689 // 2014/11/24 Fu
aoqi@1 3690 // T2: tmp, used for mdp
aoqi@1 3691 // method: callee
aoqi@1 3692 // T9: tmp
aoqi@6880 3693 // is_virtual: true
aoqi@1 3694 __ profile_arguments_type(T2, method, T9, true);
aoqi@1 3695
aoqi@1 3696 __ jump_from_interpreted(method, T2);
aoqi@1 3697
aoqi@1 3698 __ bind(notFinal);
aoqi@1 3699
aoqi@1 3700 // get receiver klass
aoqi@1 3701 __ null_check(recv, oopDesc::klass_offset_in_bytes());
aoqi@1 3702 __ load_klass(T2, recv);
aoqi@1 3703 __ verify_oop(T2);
aoqi@6880 3704
aoqi@1 3705 // profile this call
aoqi@1 3706 __ profile_virtual_call(T2, T0, T1);
aoqi@1 3707
aoqi@1 3708 // get target methodOop & entry point
aoqi@6880 3709 const int base = InstanceKlass::vtable_start_offset() * wordSize;
fujie@211 3710 assert(vtableEntry::size() * wordSize == wordSize, "adjust the scaling in the code below");
fujie@211 3711 __ dsll(AT, index, Address::times_ptr);
fujie@211 3712 // T2: receiver
aoqi@1 3713 __ dadd(AT, T2, AT);
aoqi@6880 3714 //this is a ualign read
aoqi@1 3715 __ ld(method, AT, base + vtableEntry::method_offset_in_bytes());
fujie@211 3716 __ profile_arguments_type(T2, method, T9, true);
aoqi@1 3717 __ jump_from_interpreted(method, T2);
aoqi@1 3718
aoqi@1 3719 }
aoqi@1 3720
aoqi@1 3721 void TemplateTable::invokevirtual(int byte_no) {
aoqi@1 3722 transition(vtos, vtos);
aoqi@1 3723 assert(byte_no == f2_byte, "use this argument");
aoqi@1 3724 prepare_invoke(byte_no, Rmethod, NOREG, T3, T1);
aoqi@1 3725 // now recv & flags in T3, T1
aoqi@1 3726 invokevirtual_helper(Rmethod, T3, T1);
aoqi@1 3727 }
aoqi@1 3728
aoqi@1 3729 // T9 : entry
aoqi@1 3730 // Rmethod : method
aoqi@1 3731 void TemplateTable::invokespecial(int byte_no) {
aoqi@1 3732 transition(vtos, vtos);
aoqi@1 3733 assert(byte_no == f1_byte, "use this argument");
aoqi@1 3734 prepare_invoke(byte_no, Rmethod, NOREG, T3);
aoqi@1 3735 // now recv & flags in T3, T1
aoqi@1 3736 __ verify_oop(T3);
aoqi@1 3737 __ null_check(T3);
aoqi@1 3738 __ profile_call(T9);
aoqi@1 3739
aoqi@6880 3740 // 2014/11/24 Fu
aoqi@1 3741 // T8: tmp, used for mdp
aoqi@1 3742 // Rmethod: callee
aoqi@1 3743 // T9: tmp
aoqi@6880 3744 // is_virtual: false
aoqi@1 3745 __ profile_arguments_type(T8, Rmethod, T9, false);
aoqi@1 3746
aoqi@1 3747 __ jump_from_interpreted(Rmethod, T9);
aoqi@1 3748 __ move(T0, T3);//aoqi ?
aoqi@1 3749 }
aoqi@1 3750
aoqi@1 3751 void TemplateTable::invokestatic(int byte_no) {
aoqi@1 3752 transition(vtos, vtos);
aoqi@1 3753 assert(byte_no == f1_byte, "use this argument");
aoqi@1 3754 prepare_invoke(byte_no, Rmethod, NOREG);
aoqi@1 3755 __ verify_oop(Rmethod);
aoqi@1 3756
aoqi@1 3757 __ profile_call(T9);
aoqi@1 3758
aoqi@6880 3759 // 2014/11/24 Fu
aoqi@1 3760 // T8: tmp, used for mdp
aoqi@1 3761 // Rmethod: callee
aoqi@1 3762 // T9: tmp
aoqi@6880 3763 // is_virtual: false
aoqi@1 3764 __ profile_arguments_type(T8, Rmethod, T9, false);
aoqi@1 3765
aoqi@1 3766 __ jump_from_interpreted(Rmethod, T9);
aoqi@1 3767 }
aoqi@1 3768
aoqi@6880 3769 // i have no idea what to do here, now. for future change. FIXME.
aoqi@1 3770 void TemplateTable::fast_invokevfinal(int byte_no) {
aoqi@6880 3771 transition(vtos, vtos);
aoqi@6880 3772 assert(byte_no == f2_byte, "use this argument");
aoqi@6880 3773 __ stop("fast_invokevfinal not used on mips64");
aoqi@1 3774 }
aoqi@1 3775
aoqi@1 3776 // used registers : T0, T1, T2, T3, T1, A7
aoqi@1 3777 // T0 : itable, vtable, entry
aoqi@1 3778 // T1 : interface
aoqi@1 3779 // T3 : receiver
aoqi@1 3780 // T1 : flags, klass
aoqi@1 3781 // Rmethod : index, method, this is required by interpreter_entry
aoqi@1 3782 void TemplateTable::invokeinterface(int byte_no) {
aoqi@1 3783 transition(vtos, vtos);
aoqi@1 3784 //this method will use T1-T4 and T0
aoqi@1 3785 assert(byte_no == f1_byte, "use this argument");
aoqi@1 3786 prepare_invoke(byte_no, T2, Rmethod, T3, T1);
aoqi@1 3787 // T2: Interface
aoqi@1 3788 // Rmethod: index
aoqi@6880 3789 // T3: receiver
aoqi@1 3790 // T1: flags
aoqi@6880 3791
aoqi@6880 3792 // Special case of invokeinterface called for virtual method of
aoqi@6880 3793 // java.lang.Object. See cpCacheOop.cpp for details.
aoqi@6880 3794 // This code isn't produced by javac, but could be produced by
aoqi@6880 3795 // another compliant java compiler.
aoqi@1 3796 Label notMethod;
aoqi@1 3797 __ move(AT, (1 << ConstantPoolCacheEntry::is_forced_virtual_shift));
aoqi@1 3798 __ andr(AT, T1, AT);
aoqi@1 3799 __ beq(AT, R0, notMethod);
aoqi@1 3800 __ delayed()->nop();
aoqi@1 3801
aoqi@1 3802 invokevirtual_helper(Rmethod, T3, T1);
aoqi@1 3803 __ bind(notMethod);
aoqi@1 3804 // Get receiver klass into T1 - also a null check
aoqi@1 3805 //add for compressedoops
aoqi@1 3806 __ load_klass(T1, T3);
aoqi@1 3807 __ verify_oop(T1);
aoqi@1 3808
aoqi@1 3809 // profile this call
aoqi@1 3810 __ profile_virtual_call(T1, T0, FSR);
aoqi@1 3811
aoqi@1 3812 // Compute start of first itableOffsetEntry (which is at the end of the vtable)
aoqi@1 3813 // TODO: x86 add a new method lookup_interface_method // LEE
aoqi@6880 3814 const int base = InstanceKlass::vtable_start_offset() * wordSize;
aoqi@1 3815 assert(vtableEntry::size() * wordSize == 8, "adjust the scaling in the code below");
aoqi@1 3816 __ lw(AT, T1, InstanceKlass::vtable_length_offset() * wordSize);
aoqi@1 3817 __ dsll(AT, AT, Address::times_8);
aoqi@1 3818 __ dadd(T0, T1, AT);
aoqi@1 3819 __ daddi(T0, T0, base);
aoqi@1 3820 if (HeapWordsPerLong > 1) {
aoqi@1 3821 // Round up to align_object_offset boundary
aoqi@1 3822 __ round_to(T0, BytesPerLong);
aoqi@1 3823 }
aoqi@1 3824 // now T0 is the begin of the itable
aoqi@1 3825
aoqi@1 3826 Label entry, search, interface_ok;
aoqi@1 3827
aoqi@6880 3828 ///__ jmp(entry);
aoqi@1 3829 __ b(entry);
aoqi@1 3830 __ delayed()->nop();
aoqi@1 3831
aoqi@1 3832 __ bind(search);
aoqi@1 3833 __ increment(T0, itableOffsetEntry::size() * wordSize);
aoqi@1 3834
aoqi@1 3835 __ bind(entry);
aoqi@1 3836
aoqi@1 3837 // Check that the entry is non-null. A null entry means that the receiver
aoqi@1 3838 // class doesn't implement the interface, and wasn't the same as the
aoqi@1 3839 // receiver class checked when the interface was resolved.
aoqi@1 3840 __ ld(AT, T0, itableOffsetEntry::interface_offset_in_bytes());
aoqi@1 3841 __ bne(AT, R0, interface_ok);
aoqi@1 3842 __ delayed()->nop();
aoqi@1 3843 // throw exception
aoqi@1 3844 // the call_VM checks for exception, so we should never return here.
aoqi@1 3845
aoqi@6880 3846 //__ pop();//FIXME here,
aoqi@6880 3847 // pop return address (pushed by prepare_invoke).
aoqi@1 3848 // no need now, we just save the value in RA now
aoqi@1 3849
aoqi@1 3850 __ call_VM(NOREG, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_IncompatibleClassChangeError));
aoqi@1 3851 __ should_not_reach_here();
aoqi@1 3852
aoqi@1 3853 __ bind(interface_ok);
aoqi@6880 3854 //NOTICE here, no pop as x86 do
aoqi@1 3855 __ bne(AT, T2, search);
aoqi@1 3856 __ delayed()->nop();
aoqi@1 3857
aoqi@1 3858 // now we get vtable of the interface
aoqi@1 3859 __ ld(T0, T0, itableOffsetEntry::offset_offset_in_bytes());
aoqi@1 3860 __ daddu(T0, T1, T0);
aoqi@1 3861 assert(itableMethodEntry::size() * wordSize == 8, "adjust the scaling in the code below");
aoqi@1 3862 __ dsll(AT, Rmethod, Address::times_8);
aoqi@1 3863 __ daddu(AT, T0, AT);
aoqi@1 3864 // now we get the method
aoqi@1 3865 __ ld(Rmethod, AT, 0);
aoqi@1 3866 // Rnext: methodOop to call
aoqi@1 3867 // T3: receiver
aoqi@1 3868 // Check for abstract method error
aoqi@1 3869 // Note: This should be done more efficiently via a throw_abstract_method_error
aoqi@1 3870 // interpreter entry point and a conditional jump to it in case of a null
aoqi@1 3871 // method.
aoqi@6880 3872 {
aoqi@1 3873 Label L;
aoqi@1 3874 __ bne(Rmethod, R0, L);
aoqi@1 3875 __ delayed()->nop();
aoqi@1 3876
aoqi@1 3877 // throw exception
aoqi@1 3878 // note: must restore interpreter registers to canonical
aoqi@1 3879 // state for exception handling to work correctly!
aoqi@1 3880 ///__ popl(ebx); // pop return address (pushed by prepare_invoke)
aoqi@6880 3881 //__ restore_bcp(); // esi must be correct for exception handler
aoqi@1 3882 //(was destroyed)
aoqi@6880 3883 //__ restore_locals(); // make sure locals pointer
aoqi@1 3884 //is correct as well (was destroyed)
aoqi@6880 3885 ///__ call_VM(noreg, CAST_FROM_FN_PTR(address,
aoqi@1 3886 //InterpreterRuntime::throw_AbstractMethodError));
aoqi@1 3887 __ call_VM(NOREG, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
aoqi@1 3888 // the call_VM checks for exception, so we should never return here.
aoqi@1 3889 __ should_not_reach_here();
aoqi@1 3890 __ bind(L);
aoqi@1 3891 }
aoqi@6880 3892
aoqi@6880 3893 // 2014/11/24 Fu
aoqi@1 3894 // T8: tmp, used for mdp
aoqi@1 3895 // Rmethod: callee
aoqi@1 3896 // T9: tmp
aoqi@1 3897 // is_virtual: true
aoqi@1 3898 __ profile_arguments_type(T8, Rmethod, T9, true);
aoqi@1 3899
aoqi@1 3900 __ jump_from_interpreted(Rmethod, T9);
aoqi@1 3901 }
aoqi@1 3902
aoqi@6880 3903
aoqi@1 3904 void TemplateTable::invokehandle(int byte_no) {
aoqi@1 3905 transition(vtos, vtos);
aoqi@1 3906 assert(byte_no == f1_byte, "use this argument");
aoqi@1 3907 const Register T2_method = Rmethod;
aoqi@1 3908 const Register FSR_mtype = FSR;
aoqi@1 3909 const Register T3_recv = T3;
aoqi@1 3910
aoqi@1 3911 if (!EnableInvokeDynamic) {
aoqi@1 3912 // rewriter does not generate this bytecode
aoqi@1 3913 __ should_not_reach_here();
aoqi@1 3914 return;
aoqi@1 3915 }
aoqi@6880 3916
aoqi@1 3917 prepare_invoke(byte_no, T2_method, FSR_mtype, T3_recv);
aoqi@1 3918 //??__ verify_method_ptr(T2_method);
aoqi@1 3919 __ verify_oop(T3_recv);
aoqi@1 3920 __ null_check(T3_recv);
aoqi@6880 3921
aoqi@1 3922 // rax: MethodType object (from cpool->resolved_references[f1], if necessary)
aoqi@1 3923 // rbx: MH.invokeExact_MT method (from f2)
aoqi@6880 3924
aoqi@1 3925 // Note: rax_mtype is already pushed (if necessary) by prepare_invoke
aoqi@6880 3926
aoqi@1 3927 // FIXME: profile the LambdaForm also
aoqi@1 3928 __ profile_final_call(T9);
aoqi@1 3929
aoqi@6880 3930 // 2014/11/24 Fu
aoqi@1 3931 // T8: tmp, used for mdp
aoqi@1 3932 // T2_method: callee
aoqi@1 3933 // T9: tmp
aoqi@1 3934 // is_virtual: true
aoqi@1 3935 __ profile_arguments_type(T8, T2_method, T9, true);
aoqi@6880 3936
aoqi@1 3937 __ jump_from_interpreted(T2_method, T9);
aoqi@1 3938 }
aoqi@1 3939
aoqi@1 3940 void TemplateTable::invokedynamic(int byte_no) {
aoqi@1 3941 transition(vtos, vtos);
aoqi@1 3942 assert(byte_no == f1_byte, "use this argument");
aoqi@6880 3943
aoqi@1 3944 if (!EnableInvokeDynamic) {
aoqi@1 3945 // We should not encounter this bytecode if !EnableInvokeDynamic.
aoqi@1 3946 // The verifier will stop it. However, if we get past the verifier,
aoqi@1 3947 // this will stop the thread in a reasonable way, without crashing the JVM.
aoqi@1 3948 __ call_VM(noreg, CAST_FROM_FN_PTR(address,
aoqi@1 3949 InterpreterRuntime::throw_IncompatibleClassChangeError));
aoqi@1 3950 // the call_VM checks for exception, so we should never return here.
aoqi@1 3951 __ should_not_reach_here();
aoqi@1 3952 return;
aoqi@1 3953 }
aoqi@6880 3954
aoqi@1 3955 //const Register Rmethod = T2;
aoqi@1 3956 const Register T2_callsite = T2;
aoqi@6880 3957
aoqi@1 3958 prepare_invoke(byte_no, Rmethod, T2_callsite);
aoqi@6880 3959
aoqi@1 3960 // rax: CallSite object (from cpool->resolved_references[f1])
aoqi@1 3961 // rbx: MH.linkToCallSite method (from f2)
aoqi@6880 3962
aoqi@1 3963 // Note: rax_callsite is already pushed by prepare_invoke
aoqi@1 3964 // %%% should make a type profile for any invokedynamic that takes a ref argument
aoqi@1 3965 // profile this call
aoqi@1 3966 __ profile_call(T9);
aoqi@1 3967
aoqi@6880 3968 // 2014/11/24 Fu
aoqi@1 3969 // T8: tmp, used for mdp
aoqi@1 3970 // Rmethod: callee
aoqi@1 3971 // T9: tmp
aoqi@6880 3972 // is_virtual: false
aoqi@1 3973 __ profile_arguments_type(T8, Rmethod, T9, false);
aoqi@1 3974
aoqi@1 3975 __ verify_oop(T2_callsite);
aoqi@6880 3976
aoqi@1 3977 __ jump_from_interpreted(Rmethod, T9);
aoqi@1 3978 }
aoqi@1 3979
aoqi@6880 3980 //-----------------------------------------------------------------------------
aoqi@1 3981 // Allocation
aoqi@1 3982 // T1 : tags & buffer end & thread
aoqi@1 3983 // T2 : object end
aoqi@1 3984 // T3 : klass
aoqi@1 3985 // T1 : object size
aoqi@1 3986 // A1 : cpool
aoqi@1 3987 // A2 : cp index
aoqi@1 3988 // return object in FSR
aoqi@1 3989 void TemplateTable::_new() {
aoqi@1 3990 transition(vtos, atos);
fujie@6884 3991 __ get_unsigned_2_byte_index_at_bcp(A2, 1);
aoqi@1 3992
aoqi@1 3993 Label slow_case;
aoqi@1 3994 Label done;
aoqi@1 3995 Label initialize_header;
aoqi@6880 3996 Label initialize_object; // including clearing the fields
aoqi@1 3997 Label allocate_shared;
aoqi@1 3998
aoqi@1 3999 // get InstanceKlass in T3
aoqi@1 4000 __ get_cpool_and_tags(A1, T1);
fujie@6884 4001
aoqi@1 4002 __ dsll(AT, A2, Address::times_8);
fujie@6884 4003 if (UseLoongsonISA && Assembler::is_simm(sizeof(ConstantPool), 8)) {
fujie@6884 4004 __ gsldx(T3, A1, AT, sizeof(ConstantPool));
fujie@6884 4005 } else {
fujie@6884 4006 __ dadd(AT, A1, AT);
fujie@6884 4007 __ ld(T3, AT, sizeof(ConstantPool));
fujie@6884 4008 }
aoqi@1 4009
aoqi@6880 4010 // make sure the class we're about to instantiate has been resolved.
aoqi@1 4011 // Note: slow_case does a pop of stack, which is why we loaded class/pushed above
aoqi@1 4012 const int tags_offset = Array<u1>::base_offset_in_bytes();
fujie@6884 4013 if (UseLoongsonISA && Assembler::is_simm(tags_offset, 8)) {
fujie@6884 4014 __ gslbx(AT, T1, A2, tags_offset);
fujie@6884 4015 } else {
fujie@6884 4016 __ dadd(T1, T1, A2);
fujie@6884 4017 __ lb(AT, T1, tags_offset);
fujie@6884 4018 }
aoqi@1 4019 __ daddiu(AT, AT, - (int)JVM_CONSTANT_Class);
aoqi@1 4020 __ bne(AT, R0, slow_case);
fujie@6884 4021 //__ delayed()->nop();
aoqi@1 4022
aoqi@6880 4023
aoqi@6880 4024 // make sure klass is initialized & doesn't have finalizer
aoqi@1 4025 // make sure klass is fully initialized
Jin@2 4026 __ lhu(T1, T3, in_bytes(InstanceKlass::init_state_offset()));
aoqi@1 4027 __ daddiu(AT, T1, - (int)InstanceKlass::fully_initialized);
aoqi@1 4028 __ bne(AT, R0, slow_case);
fujie@6884 4029 //__ delayed()->nop();
aoqi@1 4030
aoqi@1 4031 // has_finalizer
fujie@6884 4032 __ lw(T0, T3, in_bytes(Klass::layout_helper_offset()) );
fujie@6884 4033 __ andi(AT, T0, Klass::_lh_instance_slow_path_bit);
aoqi@1 4034 __ bne(AT, R0, slow_case);
fujie@6884 4035 //__ delayed()->nop();
aoqi@1 4036
aoqi@1 4037 // Allocate the instance
aoqi@1 4038 // 1) Try to allocate in the TLAB
aoqi@1 4039 // 2) if fail and the object is large allocate in the shared Eden
aoqi@1 4040 // 3) if the above fails (or is not applicable), go to a slow case
aoqi@1 4041 // (creates a new TLAB, etc.)
aoqi@1 4042
aoqi@1 4043 const bool allow_shared_alloc =
aoqi@1 4044 Universe::heap()->supports_inline_contig_alloc() && !CMSIncrementalMode;
aoqi@1 4045
aoqi@1 4046 if (UseTLAB) {
aoqi@1 4047 #ifndef OPT_THREAD
aoqi@1 4048 const Register thread = T8;
aoqi@1 4049 __ get_thread(thread);
aoqi@1 4050 #else
aoqi@1 4051 const Register thread = TREG;
aoqi@1 4052 #endif
aoqi@1 4053 // get tlab_top
aoqi@1 4054 __ ld(FSR, thread, in_bytes(JavaThread::tlab_top_offset()));
aoqi@1 4055 // get tlab_end
aoqi@1 4056 __ ld(AT, thread, in_bytes(JavaThread::tlab_end_offset()));
fujie@6884 4057 __ dadd(T2, FSR, T0);
aoqi@1 4058 __ slt(AT, AT, T2);
aoqi@1 4059 __ bne(AT, R0, allow_shared_alloc ? allocate_shared : slow_case);
aoqi@1 4060 __ delayed()->nop();
aoqi@1 4061 __ sd(T2, thread, in_bytes(JavaThread::tlab_top_offset()));
aoqi@1 4062
aoqi@1 4063 if (ZeroTLAB) {
aoqi@1 4064 // the fields have been already cleared
fujie@6884 4065 __ beq(R0, R0, initialize_header);
aoqi@1 4066 } else {
aoqi@1 4067 // initialize both the header and fields
fujie@6884 4068 __ beq(R0, R0, initialize_object);
aoqi@1 4069 }
aoqi@1 4070 __ delayed()->nop();
aoqi@1 4071 }
aoqi@1 4072
aoqi@1 4073 // Allocation in the shared Eden , if allowed
aoqi@1 4074 // T0 : instance size in words
aoqi@6880 4075 if(allow_shared_alloc){
aoqi@1 4076 __ bind(allocate_shared);
aoqi@6880 4077
aoqi@1 4078 Label retry;
aoqi@1 4079 Address heap_top(T1);
fujie@6884 4080 __ set64(T1, (long)Universe::heap()->top_addr());
aoqi@1 4081 __ ld(FSR, heap_top);
fujie@6884 4082
aoqi@1 4083 __ bind(retry);
fujie@6884 4084 __ set64(AT, (long)Universe::heap()->end_addr());
fujie@6884 4085 __ ld(AT, AT, 0);
aoqi@1 4086 __ dadd(T2, FSR, T0);
aoqi@1 4087 __ slt(AT, AT, T2);
aoqi@1 4088 __ bne(AT, R0, slow_case);
aoqi@1 4089 __ delayed()->nop();
aoqi@1 4090
aoqi@1 4091 // Compare FSR with the top addr, and if still equal, store the new
aoqi@1 4092 // top addr in ebx at the address of the top addr pointer. Sets ZF if was
aoqi@1 4093 // equal, and clears it otherwise. Use lock prefix for atomicity on MPs.
aoqi@1 4094 //
aoqi@1 4095 // FSR: object begin
aoqi@1 4096 // T2: object end
aoqi@1 4097 // T0: instance size in words
aoqi@1 4098
aoqi@6880 4099 // if someone beat us on the allocation, try again, otherwise continue
aoqi@1 4100 __ cmpxchg(T2, heap_top, FSR);
aoqi@1 4101 __ beq(AT, R0, retry);
aoqi@1 4102 __ delayed()->nop();
aoqi@1 4103 }
aoqi@1 4104
aoqi@1 4105 if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) {
aoqi@1 4106 // The object is initialized before the header. If the object size is
aoqi@1 4107 // zero, go directly to the header initialization.
aoqi@1 4108 __ bind(initialize_object);
fujie@6884 4109 __ set64(AT, - sizeof(oopDesc));
aoqi@1 4110 __ daddu(T0, T0, AT);
fujie@6884 4111 __ beq(T0, R0, initialize_header);
aoqi@1 4112 __ delayed()->nop();
aoqi@1 4113
aoqi@1 4114 // initialize remaining object fields: T0 is a multiple of 2
aoqi@6880 4115 {
aoqi@1 4116 Label loop;
aoqi@1 4117 __ dadd(T1, FSR, T0);
aoqi@1 4118 __ daddi(T1, T1, -oopSize);
aoqi@1 4119
aoqi@1 4120 __ bind(loop);
aoqi@1 4121 __ sd(R0, T1, sizeof(oopDesc) + 0 * oopSize);
aoqi@1 4122 __ bne(T1, FSR, loop); //dont clear header
aoqi@1 4123 __ delayed()->daddi(T1, T1, -oopSize);
aoqi@1 4124 }
fujie@6884 4125
aoqi@6880 4126 //klass in T3,
aoqi@1 4127 // initialize object header only.
aoqi@1 4128 __ bind(initialize_header);
aoqi@1 4129 if (UseBiasedLocking) {
aoqi@6880 4130 __ ld(AT, T3, in_bytes(Klass::prototype_header_offset()));
aoqi@6880 4131 __ sd(AT, FSR, oopDesc::mark_offset_in_bytes ());
aoqi@1 4132 } else {
fujie@6884 4133 __ set64(AT, (long)markOopDesc::prototype());
aoqi@1 4134 __ sd(AT, FSR, oopDesc::mark_offset_in_bytes());
aoqi@1 4135 }
aoqi@1 4136
aoqi@1 4137 __ store_klass_gap(FSR, R0);
aoqi@1 4138 __ store_klass(FSR, T3);
aoqi@1 4139
aoqi@1 4140 {
aoqi@1 4141 SkipIfEqual skip_if(_masm, &DTraceAllocProbes, 0);
aoqi@1 4142 // Trigger dtrace event for fastpath
aoqi@1 4143 __ push(atos);
aoqi@1 4144 __ call_VM_leaf(
aoqi@6880 4145 CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc), FSR);
aoqi@1 4146 __ pop(atos);
aoqi@6880 4147
aoqi@1 4148 }
aoqi@1 4149 __ b(done);
aoqi@1 4150 __ delayed()->nop();
aoqi@6880 4151 }
aoqi@6880 4152
aoqi@1 4153 // slow case
aoqi@1 4154 __ bind(slow_case);
aoqi@1 4155 call_VM(FSR, CAST_FROM_FN_PTR(address, InterpreterRuntime::_new), A1, A2);
aoqi@1 4156
aoqi@1 4157 // continue
aoqi@1 4158 __ bind(done);
fujie@32 4159 __ sync();
aoqi@1 4160 }
aoqi@1 4161
aoqi@1 4162 void TemplateTable::newarray() {
aoqi@6880 4163 transition(itos, atos);
aoqi@6880 4164 __ lbu(A1, at_bcp(1));
aoqi@6880 4165 //type, count
aoqi@6880 4166 call_VM(FSR, CAST_FROM_FN_PTR(address, InterpreterRuntime::newarray), A1, FSR);
aoqi@6880 4167 __ sync();
aoqi@1 4168 }
aoqi@1 4169
aoqi@1 4170 void TemplateTable::anewarray() {
aoqi@1 4171 transition(itos, atos);
aoqi@16 4172 __ get_2_byte_integer_at_bcp(A2, AT, 1);
aoqi@1 4173 __ huswap(A2);
aoqi@1 4174 __ get_constant_pool(A1);
aoqi@1 4175 // cp, index, count
aoqi@1 4176 call_VM(FSR, CAST_FROM_FN_PTR(address, InterpreterRuntime::anewarray), A1, A2, FSR);
fujie@32 4177 __ sync();
aoqi@1 4178 }
aoqi@1 4179
aoqi@1 4180 void TemplateTable::arraylength() {
aoqi@1 4181 transition(atos, itos);
aoqi@1 4182 __ null_check(FSR, arrayOopDesc::length_offset_in_bytes());
aoqi@1 4183 __ lw(FSR, FSR, arrayOopDesc::length_offset_in_bytes());
aoqi@1 4184 }
aoqi@1 4185
aoqi@1 4186 // i use T2 as ebx, T3 as ecx, T1 as edx
aoqi@1 4187 // when invoke gen_subtype_check, super in T3, sub in T2, object in FSR(it's always)
aoqi@1 4188 // T2 : sub klass
aoqi@1 4189 // T3 : cpool
aoqi@1 4190 // T3 : super klass
aoqi@1 4191 void TemplateTable::checkcast() {
aoqi@1 4192 transition(atos, atos);
aoqi@1 4193 Label done, is_null, ok_is_subtype, quicked, resolved;
aoqi@1 4194 __ beq(FSR, R0, is_null);
aoqi@1 4195 __ delayed()->nop();
aoqi@1 4196
aoqi@1 4197 // Get cpool & tags index
aoqi@1 4198 __ get_cpool_and_tags(T3, T1);
aoqi@16 4199 __ get_2_byte_integer_at_bcp(T2, AT, 1);
aoqi@1 4200 __ huswap(T2);
aoqi@1 4201
aoqi@1 4202 // See if bytecode has already been quicked
aoqi@1 4203 __ dadd(AT, T1, T2);
aoqi@1 4204 __ lb(AT, AT, Array<u1>::base_offset_in_bytes());
aoqi@1 4205 __ daddiu(AT, AT, - (int)JVM_CONSTANT_Class);
aoqi@1 4206 __ beq(AT, R0, quicked);
aoqi@1 4207 __ delayed()->nop();
aoqi@1 4208
aoqi@1 4209 /* 2012/6/2 Jin: In InterpreterRuntime::quicken_io_cc, lots of new classes may be loaded.
aoqi@1 4210 * Then, GC will move the object in V0 to another places in heap.
aoqi@1 4211 * Therefore, We should never save such an object in register.
aoqi@1 4212 * Instead, we should save it in the stack. It can be modified automatically by the GC thread.
aoqi@1 4213 * After GC, the object address in FSR is changed to a new place.
aoqi@1 4214 */
aoqi@1 4215 __ push(atos);
aoqi@1 4216 const Register thread = TREG;
aoqi@1 4217 #ifndef OPT_THREAD
aoqi@1 4218 __ get_thread(thread);
aoqi@1 4219 #endif
aoqi@1 4220 call_VM(NOREG, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc));
aoqi@1 4221 __ get_vm_result_2(T3, thread);
aoqi@1 4222 __ pop_ptr(FSR);
aoqi@1 4223 __ b(resolved);
aoqi@1 4224 __ delayed()->nop();
aoqi@1 4225
aoqi@1 4226 // klass already in cp, get superklass in T3
aoqi@1 4227 __ bind(quicked);
aoqi@1 4228 __ dsll(AT, T2, Address::times_8);
aoqi@1 4229 __ dadd(AT, T3, AT);
aoqi@1 4230 __ ld(T3, AT, sizeof(ConstantPool));
aoqi@1 4231
aoqi@1 4232 __ bind(resolved);
aoqi@1 4233
aoqi@1 4234 // get subklass in T2
aoqi@1 4235 //add for compressedoops
aoqi@1 4236 __ load_klass(T2, FSR);
aoqi@1 4237 // Superklass in T3. Subklass in T2.
aoqi@1 4238 __ gen_subtype_check(T3, T2, ok_is_subtype);
aoqi@1 4239
aoqi@1 4240 // Come here on failure
aoqi@1 4241 // object is at FSR
aoqi@1 4242 __ jmp(Interpreter::_throw_ClassCastException_entry);
aoqi@1 4243 __ delayed()->nop();
aoqi@1 4244
aoqi@1 4245 // Come here on success
aoqi@1 4246 __ bind(ok_is_subtype);
aoqi@1 4247
aoqi@1 4248 // Collect counts on whether this check-cast sees NULLs a lot or not.
aoqi@1 4249 if (ProfileInterpreter) {
aoqi@6880 4250 __ b(done);
aoqi@6880 4251 __ delayed()->nop();
aoqi@6880 4252 __ bind(is_null);
aoqi@6880 4253 __ profile_null_seen(T3);
aoqi@1 4254 } else {
aoqi@6880 4255 __ bind(is_null);
aoqi@1 4256 }
aoqi@1 4257 __ bind(done);
aoqi@1 4258 }
aoqi@1 4259
aoqi@1 4260 // i use T3 as cpool, T1 as tags, T2 as index
aoqi@1 4261 // object always in FSR, superklass in T3, subklass in T2
aoqi@1 4262 void TemplateTable::instanceof() {
aoqi@1 4263 transition(atos, itos);
aoqi@1 4264 Label done, is_null, ok_is_subtype, quicked, resolved;
aoqi@1 4265
aoqi@1 4266 __ beq(FSR, R0, is_null);
aoqi@1 4267 __ delayed()->nop();
aoqi@1 4268
aoqi@1 4269 // Get cpool & tags index
aoqi@1 4270 __ get_cpool_and_tags(T3, T1);
aoqi@1 4271 // get index
aoqi@16 4272 __ get_2_byte_integer_at_bcp(T2, AT, 1);
aoqi@1 4273 __ hswap(T2);
aoqi@1 4274
aoqi@1 4275 // See if bytecode has already been quicked
aoqi@1 4276 // quicked
aoqi@1 4277 __ daddu(AT, T1, T2);
aoqi@1 4278 __ lb(AT, AT, Array<u1>::base_offset_in_bytes());
aoqi@1 4279 __ daddiu(AT, AT, - (int)JVM_CONSTANT_Class);
aoqi@1 4280 __ beq(AT, R0, quicked);
aoqi@1 4281 __ delayed()->nop();
aoqi@1 4282
aoqi@1 4283 __ push(atos);
aoqi@1 4284 const Register thread = TREG;
aoqi@1 4285 #ifndef OPT_THREAD
aoqi@1 4286 __ get_thread(thread);
aoqi@1 4287 #endif
aoqi@1 4288 call_VM(NOREG, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc));
aoqi@1 4289 __ get_vm_result_2(T3, thread);
aoqi@6880 4290 __ pop_ptr(FSR);
aoqi@1 4291 __ b(resolved);
aoqi@1 4292 __ delayed()->nop();
aoqi@1 4293
aoqi@1 4294 // get superklass in T3, subklass in T2
aoqi@1 4295 __ bind(quicked);
aoqi@1 4296 __ dsll(AT, T2, Address::times_8);
aoqi@1 4297 __ daddu(AT, T3, AT);
aoqi@6880 4298 __ ld(T3, AT, sizeof(ConstantPool));
aoqi@1 4299
aoqi@1 4300 __ bind(resolved);
aoqi@1 4301 // get subklass in T2
aoqi@1 4302 //add for compressedoops
aoqi@1 4303 __ load_klass(T2, FSR);
aoqi@6880 4304
aoqi@1 4305 // Superklass in T3. Subklass in T2.
aoqi@1 4306 __ gen_subtype_check(T3, T2, ok_is_subtype);
aoqi@1 4307 // Come here on failure
aoqi@1 4308 __ b(done);
aoqi@1 4309 __ delayed(); __ move(FSR, R0);
aoqi@1 4310
aoqi@1 4311 // Come here on success
aoqi@1 4312 __ bind(ok_is_subtype);
aoqi@1 4313 __ move(FSR, 1);
aoqi@1 4314
aoqi@1 4315 // Collect counts on whether this test sees NULLs a lot or not.
aoqi@1 4316 if (ProfileInterpreter) {
aoqi@6880 4317 __ beq(R0, R0, done);
aoqi@6880 4318 __ nop();
aoqi@6880 4319 __ bind(is_null);
aoqi@6880 4320 __ profile_null_seen(T3);
aoqi@1 4321 } else {
aoqi@6880 4322 __ bind(is_null); // same as 'done'
aoqi@1 4323 }
aoqi@1 4324 __ bind(done);
aoqi@1 4325 // FSR = 0: obj == NULL or obj is not an instanceof the specified klass
aoqi@1 4326 // FSR = 1: obj != NULL and obj is an instanceof the specified klass
aoqi@1 4327 }
aoqi@1 4328
aoqi@1 4329 //--------------------------------------------------------
aoqi@1 4330 //--------------------------------------------
aoqi@1 4331 // Breakpoints
aoqi@1 4332 void TemplateTable::_breakpoint() {
aoqi@6880 4333 // Note: We get here even if we are single stepping..
aoqi@6880 4334 // jbug inists on setting breakpoints at every bytecode
aoqi@6880 4335 // even if we are in single step mode.
aoqi@6880 4336
aoqi@6880 4337 transition(vtos, vtos);
aoqi@6880 4338
aoqi@6880 4339 // get the unpatched byte code
aoqi@6880 4340 __ get_method(A1);
aoqi@6880 4341 __ call_VM(NOREG,
aoqi@6880 4342 CAST_FROM_FN_PTR(address,
aoqi@6880 4343 InterpreterRuntime::get_original_bytecode_at),
aoqi@6880 4344 A1, BCP);
aoqi@6880 4345 __ move(Rnext, V0); // Jin: Rnext will be used in dispatch_only_normal
aoqi@6880 4346
aoqi@6880 4347 // post the breakpoint event
aoqi@6880 4348 __ get_method(A1);
aoqi@6880 4349 __ call_VM(NOREG, CAST_FROM_FN_PTR(address, InterpreterRuntime::_breakpoint), A1, BCP);
aoqi@6880 4350
aoqi@6880 4351 // complete the execution of original bytecode
aoqi@6880 4352 __ dispatch_only_normal(vtos);
aoqi@6880 4353 }
aoqi@6880 4354
aoqi@6880 4355 //-----------------------------------------------------------------------------
aoqi@1 4356 // Exceptions
aoqi@1 4357
aoqi@1 4358 void TemplateTable::athrow() {
aoqi@6880 4359 transition(atos, vtos);
aoqi@6880 4360 __ null_check(FSR);
aoqi@6880 4361 __ jmp(Interpreter::throw_exception_entry());
aoqi@6880 4362 __ delayed()->nop();
aoqi@1 4363 }
aoqi@1 4364
aoqi@6880 4365 //-----------------------------------------------------------------------------
aoqi@1 4366 // Synchronization
aoqi@1 4367 //
aoqi@1 4368 // Note: monitorenter & exit are symmetric routines; which is reflected
aoqi@1 4369 // in the assembly code structure as well
aoqi@1 4370 //
aoqi@1 4371 // Stack layout:
aoqi@1 4372 //
aoqi@1 4373 // [expressions ] <--- SP = expression stack top
aoqi@1 4374 // ..
aoqi@1 4375 // [expressions ]
aoqi@1 4376 // [monitor entry] <--- monitor block top = expression stack bot
aoqi@1 4377 // ..
aoqi@1 4378 // [monitor entry]
aoqi@1 4379 // [frame data ] <--- monitor block bot
aoqi@1 4380 // ...
aoqi@1 4381 // [return addr ] <--- FP
aoqi@1 4382
aoqi@1 4383 // we use T2 as monitor entry pointer, T3 as monitor top pointer, c_rarg0 as free slot pointer
aoqi@1 4384 // object always in FSR
aoqi@1 4385 void TemplateTable::monitorenter() {
aoqi@1 4386 transition(atos, vtos);
aoqi@6880 4387
aoqi@1 4388 // check for NULL object
aoqi@1 4389 __ null_check(FSR);
aoqi@1 4390
aoqi@6880 4391 const Address monitor_block_top(FP, frame::interpreter_frame_monitor_block_top_offset
aoqi@1 4392 * wordSize);
aoqi@1 4393 const int entry_size = (frame::interpreter_frame_monitor_size()* wordSize);
aoqi@1 4394 Label allocated;
aoqi@1 4395
aoqi@1 4396 // initialize entry pointer
aoqi@1 4397 __ move(c_rarg0, R0);
aoqi@1 4398
aoqi@1 4399 // find a free slot in the monitor block (result in edx)
aoqi@6880 4400 {
aoqi@1 4401 Label entry, loop, exit, next;
aoqi@1 4402 __ ld(T2, monitor_block_top);
aoqi@1 4403 __ b(entry);
aoqi@1 4404 __ delayed()->daddi(T3, FP, frame::interpreter_frame_initial_sp_offset * wordSize);
aoqi@1 4405
aoqi@1 4406 // free slot?
aoqi@1 4407 __ bind(loop);
aoqi@1 4408 __ ld(AT, T2, BasicObjectLock::obj_offset_in_bytes());
aoqi@1 4409 __ bne(AT, R0, next);
aoqi@1 4410 __ delayed()->nop();
aoqi@1 4411 __ move(c_rarg0, T2);
aoqi@1 4412
aoqi@1 4413 __ bind(next);
aoqi@1 4414 __ beq(FSR, AT, exit);
aoqi@1 4415 __ delayed()->nop();
aoqi@1 4416 __ daddi(T2, T2, entry_size);
aoqi@1 4417
aoqi@1 4418 __ bind(entry);
aoqi@1 4419 __ bne(T3, T2, loop);
aoqi@1 4420 __ delayed()->nop();
aoqi@1 4421 __ bind(exit);
aoqi@1 4422 }
aoqi@1 4423
aoqi@1 4424 __ bne(c_rarg0, R0, allocated);
aoqi@1 4425 __ delayed()->nop();
aoqi@1 4426
aoqi@1 4427 // allocate one if there's no free slot
aoqi@6880 4428 {
aoqi@1 4429 Label entry, loop;
aoqi@1 4430 // 1. compute new pointers // SP: old expression stack top
aoqi@1 4431 __ ld(c_rarg0, monitor_block_top);
aoqi@1 4432 __ daddi(SP, SP, - entry_size);
aoqi@1 4433 __ daddi(c_rarg0, c_rarg0, - entry_size);
aoqi@1 4434 __ sd(c_rarg0, monitor_block_top);
aoqi@1 4435 __ b(entry);
aoqi@1 4436 __ delayed(); __ move(T3, SP);
aoqi@1 4437
aoqi@1 4438 // 2. move expression stack contents
aoqi@1 4439 __ bind(loop);
aoqi@1 4440 __ ld(AT, T3, entry_size);
aoqi@1 4441 __ sd(AT, T3, 0);
aoqi@6880 4442 __ daddi(T3, T3, wordSize);
aoqi@1 4443 __ bind(entry);
aoqi@1 4444 __ bne(T3, c_rarg0, loop);
aoqi@1 4445 __ delayed()->nop();
aoqi@1 4446 }
aoqi@1 4447
aoqi@1 4448 __ bind(allocated);
aoqi@6880 4449 // Increment bcp to point to the next bytecode,
aoqi@6880 4450 // so exception handling for async. exceptions work correctly.
aoqi@6880 4451 // The object has already been poped from the stack, so the
aoqi@1 4452 // expression stack looks correct.
aoqi@6880 4453 __ daddi(BCP, BCP, 1);
aoqi@1 4454 __ sd(FSR, c_rarg0, BasicObjectLock::obj_offset_in_bytes());
aoqi@1 4455 __ lock_object(c_rarg0);
aoqi@1 4456 // check to make sure this monitor doesn't cause stack overflow after locking
aoqi@1 4457 __ save_bcp(); // in case of exception
aoqi@1 4458 __ generate_stack_overflow_check(0);
aoqi@1 4459 // The bcp has already been incremented. Just need to dispatch to next instruction.
aoqi@1 4460
aoqi@1 4461 __ dispatch_next(vtos);
aoqi@1 4462 }
aoqi@1 4463
aoqi@1 4464 // T2 : top
aoqi@1 4465 // c_rarg0 : entry
aoqi@1 4466 void TemplateTable::monitorexit() {
aoqi@1 4467 transition(atos, vtos);
aoqi@1 4468
aoqi@1 4469 __ null_check(FSR);
aoqi@1 4470
aoqi@1 4471 const int entry_size =(frame::interpreter_frame_monitor_size()* wordSize);
aoqi@1 4472 Label found;
aoqi@1 4473
aoqi@1 4474 // find matching slot
aoqi@6880 4475 {
aoqi@1 4476 Label entry, loop;
aoqi@1 4477 __ ld(c_rarg0, FP, frame::interpreter_frame_monitor_block_top_offset * wordSize);
aoqi@1 4478 __ b(entry);
aoqi@1 4479 __ delayed()->daddiu(T2, FP, frame::interpreter_frame_initial_sp_offset * wordSize);
aoqi@1 4480
aoqi@1 4481 __ bind(loop);
aoqi@1 4482 __ ld(AT, c_rarg0, BasicObjectLock::obj_offset_in_bytes());
aoqi@1 4483 __ beq(FSR, AT, found);
aoqi@1 4484 __ delayed()->nop();
aoqi@1 4485 __ daddiu(c_rarg0, c_rarg0, entry_size);
aoqi@1 4486 __ bind(entry);
aoqi@1 4487 __ bne(T2, c_rarg0, loop);
aoqi@1 4488 __ delayed()->nop();
aoqi@1 4489 }
aoqi@1 4490
aoqi@1 4491 // error handling. Unlocking was not block-structured
aoqi@1 4492 Label end;
aoqi@6880 4493 __ call_VM(NOREG, CAST_FROM_FN_PTR(address,
aoqi@6880 4494 InterpreterRuntime::throw_illegal_monitor_state_exception));
aoqi@1 4495 __ should_not_reach_here();
aoqi@1 4496
aoqi@1 4497 // call run-time routine
aoqi@1 4498 // c_rarg0: points to monitor entry
aoqi@1 4499 __ bind(found);
aoqi@1 4500 __ move(TSR, FSR);
aoqi@1 4501 __ unlock_object(c_rarg0);
aoqi@1 4502 __ move(FSR, TSR);
aoqi@1 4503 __ bind(end);
aoqi@1 4504 }
aoqi@1 4505
aoqi@6880 4506
aoqi@6880 4507 // Wide instructions
aoqi@1 4508 void TemplateTable::wide() {
aoqi@1 4509 transition(vtos, vtos);
aoqi@1 4510 // Note: the esi increment step is part of the individual wide bytecode implementations
aoqi@1 4511 __ lbu(Rnext, at_bcp(1));
aoqi@1 4512 __ dsll(T9, Rnext, Address::times_8);
aoqi@1 4513 __ li(AT, (long)Interpreter::_wentry_point);
aoqi@1 4514 __ dadd(AT, T9, AT);
aoqi@1 4515 __ ld(T9, AT, 0);
aoqi@1 4516 __ jr(T9);
aoqi@1 4517 __ delayed()->nop();
aoqi@1 4518 }
aoqi@1 4519
aoqi@1 4520
aoqi@1 4521 void TemplateTable::multianewarray() {
aoqi@1 4522 transition(vtos, atos);
aoqi@1 4523 // last dim is on top of stack; we want address of first one:
aoqi@1 4524 // first_addr = last_addr + (ndims - 1) * wordSize
aoqi@6880 4525 __ lbu(A1, at_bcp(3)); // dimension
aoqi@6880 4526 __ daddi(A1, A1, -1);
aoqi@1 4527 __ dsll(A1, A1, Address::times_8);
aoqi@6880 4528 __ dadd(A1, SP, A1); // now A1 pointer to the count array on the stack
aoqi@1 4529 call_VM(FSR, CAST_FROM_FN_PTR(address, InterpreterRuntime::multianewarray), A1);
aoqi@1 4530 __ lbu(AT, at_bcp(3));
aoqi@1 4531 __ dsll(AT, AT, Address::times_8);
aoqi@1 4532 __ dadd(SP, SP, AT);
fujie@32 4533 __ sync();
aoqi@1 4534 }
aoqi@1 4535 #endif // !CC_INTERP

mercurial