src/cpu/mips/vm/templateTable_mips_64.cpp

Mon, 06 Nov 2017 16:51:47 +0800

author
aoqi
date
Mon, 06 Nov 2017 16:51:47 +0800
changeset 7997
6cbff0651f1a
parent 6895
34448c1bea2d
child 7998
367db633bbea
permissions
-rw-r--r--

[Code Reorganization] remove trailing whitespace to pass jcheck test

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

mercurial