Mercurial > hg > graal-jvmci-8
comparison src/cpu/sparc/vm/stubGenerator_sparc.cpp @ 3839:3d42f82cd811
7063628: Use cbcond on T4
Summary: Add new short branch instruction to Hotspot sparc assembler.
Reviewed-by: never, twisti, jrose
author | kvn |
---|---|
date | Thu, 21 Jul 2011 11:25:07 -0700 |
parents | d83ac25d0304 |
children | baf763f388e6 |
comparison
equal
deleted
inserted
replaced
3838:6a991dcb52bb | 3839:3d42f82cd811 |
---|---|
148 #ifdef ASSERT | 148 #ifdef ASSERT |
149 // make sure we have no pending exceptions | 149 // make sure we have no pending exceptions |
150 { const Register t = G3_scratch; | 150 { const Register t = G3_scratch; |
151 Label L; | 151 Label L; |
152 __ ld_ptr(G2_thread, in_bytes(Thread::pending_exception_offset()), t); | 152 __ ld_ptr(G2_thread, in_bytes(Thread::pending_exception_offset()), t); |
153 __ br_null(t, false, Assembler::pt, L); | 153 __ br_null_short(t, Assembler::pt, L); |
154 __ delayed()->nop(); | |
155 __ stop("StubRoutines::call_stub: entered with pending exception"); | 154 __ stop("StubRoutines::call_stub: entered with pending exception"); |
156 __ bind(L); | 155 __ bind(L); |
157 } | 156 } |
158 #endif | 157 #endif |
159 | 158 |
205 | 204 |
206 // test if any parameters & setup of Lentry_args | 205 // test if any parameters & setup of Lentry_args |
207 Label exit; | 206 Label exit; |
208 __ ld_ptr(parameter_size.as_in().as_address(), cnt); // parameter counter | 207 __ ld_ptr(parameter_size.as_in().as_address(), cnt); // parameter counter |
209 __ add( FP, STACK_BIAS, dst ); | 208 __ add( FP, STACK_BIAS, dst ); |
210 __ tst(cnt); | 209 __ cmp_zero_and_br(Assembler::zero, cnt, exit); |
211 __ br(Assembler::zero, false, Assembler::pn, exit); | |
212 __ delayed()->sub(dst, BytesPerWord, dst); // setup Lentry_args | 210 __ delayed()->sub(dst, BytesPerWord, dst); // setup Lentry_args |
213 | 211 |
214 // copy parameters if any | 212 // copy parameters if any |
215 Label loop; | 213 Label loop; |
216 __ BIND(loop); | 214 __ BIND(loop); |
280 __ BIND(exit); | 278 __ BIND(exit); |
281 __ ret(); | 279 __ ret(); |
282 __ delayed()->restore(); | 280 __ delayed()->restore(); |
283 | 281 |
284 __ BIND(is_object); | 282 __ BIND(is_object); |
285 __ ba(false, exit); | 283 __ ba(exit); |
286 __ delayed()->st_ptr(O0, addr, G0); | 284 __ delayed()->st_ptr(O0, addr, G0); |
287 | 285 |
288 __ BIND(is_float); | 286 __ BIND(is_float); |
289 __ ba(false, exit); | 287 __ ba(exit); |
290 __ delayed()->stf(FloatRegisterImpl::S, F0, addr, G0); | 288 __ delayed()->stf(FloatRegisterImpl::S, F0, addr, G0); |
291 | 289 |
292 __ BIND(is_double); | 290 __ BIND(is_double); |
293 __ ba(false, exit); | 291 __ ba(exit); |
294 __ delayed()->stf(FloatRegisterImpl::D, F0, addr, G0); | 292 __ delayed()->stf(FloatRegisterImpl::D, F0, addr, G0); |
295 | 293 |
296 __ BIND(is_long); | 294 __ BIND(is_long); |
297 #ifdef _LP64 | 295 #ifdef _LP64 |
298 __ ba(false, exit); | 296 __ ba(exit); |
299 __ delayed()->st_long(O0, addr, G0); // store entire long | 297 __ delayed()->st_long(O0, addr, G0); // store entire long |
300 #else | 298 #else |
301 #if defined(COMPILER2) | 299 #if defined(COMPILER2) |
302 // All return values are where we want them, except for Longs. C2 returns | 300 // All return values are where we want them, except for Longs. C2 returns |
303 // longs in G1 in the 32-bit build whereas the interpreter wants them in O0/O1. | 301 // longs in G1 in the 32-bit build whereas the interpreter wants them in O0/O1. |
305 // build we simply always use G1. | 303 // build we simply always use G1. |
306 // Note: I tried to make c2 return longs in O0/O1 and G1 so we wouldn't have to | 304 // Note: I tried to make c2 return longs in O0/O1 and G1 so we wouldn't have to |
307 // do this here. Unfortunately if we did a rethrow we'd see an machepilog node | 305 // do this here. Unfortunately if we did a rethrow we'd see an machepilog node |
308 // first which would move g1 -> O0/O1 and destroy the exception we were throwing. | 306 // first which would move g1 -> O0/O1 and destroy the exception we were throwing. |
309 | 307 |
310 __ ba(false, exit); | 308 __ ba(exit); |
311 __ delayed()->stx(G1, addr, G0); // store entire long | 309 __ delayed()->stx(G1, addr, G0); // store entire long |
312 #else | 310 #else |
313 __ st(O1, addr, BytesPerInt); | 311 __ st(O1, addr, BytesPerInt); |
314 __ ba(false, exit); | 312 __ ba(exit); |
315 __ delayed()->st(O0, addr, G0); | 313 __ delayed()->st(O0, addr, G0); |
316 #endif /* COMPILER2 */ | 314 #endif /* COMPILER2 */ |
317 #endif /* _LP64 */ | 315 #endif /* _LP64 */ |
318 } | 316 } |
319 return start; | 317 return start; |
380 | 378 |
381 #ifdef ASSERT | 379 #ifdef ASSERT |
382 // make sure that this code is only executed if there is a pending exception | 380 // make sure that this code is only executed if there is a pending exception |
383 { Label L; | 381 { Label L; |
384 __ ld_ptr(exception_addr, Gtemp); | 382 __ ld_ptr(exception_addr, Gtemp); |
385 __ br_notnull(Gtemp, false, Assembler::pt, L); | 383 __ br_notnull_short(Gtemp, Assembler::pt, L); |
386 __ delayed()->nop(); | |
387 __ stop("StubRoutines::forward exception: no pending exception (1)"); | 384 __ stop("StubRoutines::forward exception: no pending exception (1)"); |
388 __ bind(L); | 385 __ bind(L); |
389 } | 386 } |
390 #endif | 387 #endif |
391 | 388 |
404 __ add(O7, frame::pc_return_offset, Oissuing_pc); // save the issuing PC | 401 __ add(O7, frame::pc_return_offset, Oissuing_pc); // save the issuing PC |
405 | 402 |
406 #ifdef ASSERT | 403 #ifdef ASSERT |
407 // make sure exception is set | 404 // make sure exception is set |
408 { Label L; | 405 { Label L; |
409 __ br_notnull(Oexception, false, Assembler::pt, L); | 406 __ br_notnull_short(Oexception, Assembler::pt, L); |
410 __ delayed()->nop(); | |
411 __ stop("StubRoutines::forward exception: no pending exception (2)"); | 407 __ stop("StubRoutines::forward exception: no pending exception (2)"); |
412 __ bind(L); | 408 __ bind(L); |
413 } | 409 } |
414 #endif | 410 #endif |
415 // jump to exception handler | 411 // jump to exception handler |
499 Label L; | 495 Label L; |
500 | 496 |
501 Address exception_addr(G2_thread, Thread::pending_exception_offset()); | 497 Address exception_addr(G2_thread, Thread::pending_exception_offset()); |
502 Register scratch_reg = Gtemp; | 498 Register scratch_reg = Gtemp; |
503 __ ld_ptr(exception_addr, scratch_reg); | 499 __ ld_ptr(exception_addr, scratch_reg); |
504 __ br_notnull(scratch_reg, false, Assembler::pt, L); | 500 __ br_notnull_short(scratch_reg, Assembler::pt, L); |
505 __ delayed()->nop(); | |
506 __ should_not_reach_here(); | 501 __ should_not_reach_here(); |
507 __ bind(L); | 502 __ bind(L); |
508 #endif // ASSERT | 503 #endif // ASSERT |
509 BLOCK_COMMENT("call forward_exception_entry"); | 504 BLOCK_COMMENT("call forward_exception_entry"); |
510 __ call(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type); | 505 __ call(StubRoutines::forward_exception_entry(), relocInfo::runtime_call_type); |
612 __ set(StubRoutines::Sparc::locked, lock_reg); | 607 __ set(StubRoutines::Sparc::locked, lock_reg); |
613 // Initialize yield counter | 608 // Initialize yield counter |
614 __ mov(G0,yield_reg); | 609 __ mov(G0,yield_reg); |
615 | 610 |
616 __ BIND(retry); | 611 __ BIND(retry); |
617 __ cmp(yield_reg, V8AtomicOperationUnderLockSpinCount); | 612 __ cmp_and_br_short(yield_reg, V8AtomicOperationUnderLockSpinCount, Assembler::less, Assembler::pt, dontyield); |
618 __ br(Assembler::less, false, Assembler::pt, dontyield); | |
619 __ delayed()->nop(); | |
620 | 613 |
621 // This code can only be called from inside the VM, this | 614 // This code can only be called from inside the VM, this |
622 // stub is only invoked from Atomic::add(). We do not | 615 // stub is only invoked from Atomic::add(). We do not |
623 // want to use call_VM, because _last_java_sp and such | 616 // want to use call_VM, because _last_java_sp and such |
624 // must already be set. | 617 // must already be set. |
674 __ mov(O0, O3); // scratch copy of exchange value | 667 __ mov(O0, O3); // scratch copy of exchange value |
675 __ ld(O1, 0, O2); // observe the previous value | 668 __ ld(O1, 0, O2); // observe the previous value |
676 // try to replace O2 with O3 | 669 // try to replace O2 with O3 |
677 __ cas_under_lock(O1, O2, O3, | 670 __ cas_under_lock(O1, O2, O3, |
678 (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr(),false); | 671 (address)StubRoutines::Sparc::atomic_memory_operation_lock_addr(),false); |
679 __ cmp(O2, O3); | 672 __ cmp_and_br_short(O2, O3, Assembler::notEqual, Assembler::pn, retry); |
680 __ br(Assembler::notEqual, false, Assembler::pn, retry); | |
681 __ delayed()->nop(); | |
682 | 673 |
683 __ retl(false); | 674 __ retl(false); |
684 __ delayed()->mov(O2, O0); // report previous value to caller | 675 __ delayed()->mov(O2, O0); // report previous value to caller |
685 | 676 |
686 } else { | 677 } else { |
796 if (VM_Version::v9_instructions_work()) { | 787 if (VM_Version::v9_instructions_work()) { |
797 Label(retry); | 788 Label(retry); |
798 __ BIND(retry); | 789 __ BIND(retry); |
799 | 790 |
800 __ lduw(O1, 0, O2); | 791 __ lduw(O1, 0, O2); |
801 __ add(O0, O2, O3); | 792 __ add(O0, O2, O3); |
802 __ cas(O1, O2, O3); | 793 __ cas(O1, O2, O3); |
803 __ cmp( O2, O3); | 794 __ cmp_and_br_short(O2, O3, Assembler::notEqual, Assembler::pn, retry); |
804 __ br(Assembler::notEqual, false, Assembler::pn, retry); | |
805 __ delayed()->nop(); | |
806 __ retl(false); | 795 __ retl(false); |
807 __ delayed()->add(O0, O2, O0); // note that cas made O2==O3 | 796 __ delayed()->add(O0, O2, O0); // note that cas made O2==O3 |
808 } else { | 797 } else { |
809 const Register& lock_reg = O2; | 798 const Register& lock_reg = O2; |
810 const Register& lock_ptr_reg = O3; | 799 const Register& lock_ptr_reg = O3; |
1368 generate_disjoint_long_copy_core(aligned); | 1357 generate_disjoint_long_copy_core(aligned); |
1369 __ mov(G4, count); // Restore count | 1358 __ mov(G4, count); // Restore count |
1370 | 1359 |
1371 // copy tailing bytes | 1360 // copy tailing bytes |
1372 __ BIND(L_copy_byte); | 1361 __ BIND(L_copy_byte); |
1373 __ br_zero(Assembler::zero, false, Assembler::pt, count, L_exit); | 1362 __ cmp_and_br_short(count, 0, Assembler::equal, Assembler::pt, L_exit); |
1374 __ delayed()->nop(); | |
1375 __ align(OptoLoopAlignment); | 1363 __ align(OptoLoopAlignment); |
1376 __ BIND(L_copy_byte_loop); | 1364 __ BIND(L_copy_byte_loop); |
1377 __ ldub(from, offset, O3); | 1365 __ ldub(from, offset, O3); |
1378 __ deccc(count); | 1366 __ deccc(count); |
1379 __ stb(O3, to, offset); | 1367 __ stb(O3, to, offset); |
1480 __ delayed()->stx(O4, end_to, 0); | 1468 __ delayed()->stx(O4, end_to, 0); |
1481 __ inc(count, 16); | 1469 __ inc(count, 16); |
1482 | 1470 |
1483 // copy 1 element (2 bytes) at a time | 1471 // copy 1 element (2 bytes) at a time |
1484 __ BIND(L_copy_byte); | 1472 __ BIND(L_copy_byte); |
1485 __ br_zero(Assembler::zero, false, Assembler::pt, count, L_exit); | 1473 __ cmp_and_br_short(count, 0, Assembler::equal, Assembler::pt, L_exit); |
1486 __ delayed()->nop(); | |
1487 __ align(OptoLoopAlignment); | 1474 __ align(OptoLoopAlignment); |
1488 __ BIND(L_copy_byte_loop); | 1475 __ BIND(L_copy_byte_loop); |
1489 __ dec(end_from); | 1476 __ dec(end_from); |
1490 __ dec(end_to); | 1477 __ dec(end_to); |
1491 __ ldub(end_from, 0, O4); | 1478 __ ldub(end_from, 0, O4); |
1598 generate_disjoint_long_copy_core(aligned); | 1585 generate_disjoint_long_copy_core(aligned); |
1599 __ mov(G4, count); // restore | 1586 __ mov(G4, count); // restore |
1600 | 1587 |
1601 // copy 1 element at a time | 1588 // copy 1 element at a time |
1602 __ BIND(L_copy_2_bytes); | 1589 __ BIND(L_copy_2_bytes); |
1603 __ br_zero(Assembler::zero, false, Assembler::pt, count, L_exit); | 1590 __ cmp_and_br_short(count, 0, Assembler::equal, Assembler::pt, L_exit); |
1604 __ delayed()->nop(); | |
1605 __ align(OptoLoopAlignment); | 1591 __ align(OptoLoopAlignment); |
1606 __ BIND(L_copy_2_bytes_loop); | 1592 __ BIND(L_copy_2_bytes_loop); |
1607 __ lduh(from, offset, O3); | 1593 __ lduh(from, offset, O3); |
1608 __ deccc(count); | 1594 __ deccc(count); |
1609 __ sth(O3, to, offset); | 1595 __ sth(O3, to, offset); |
1944 __ delayed()->stx(O4, end_to, 0); | 1930 __ delayed()->stx(O4, end_to, 0); |
1945 __ inc(count, 8); | 1931 __ inc(count, 8); |
1946 | 1932 |
1947 // copy 1 element (2 bytes) at a time | 1933 // copy 1 element (2 bytes) at a time |
1948 __ BIND(L_copy_2_bytes); | 1934 __ BIND(L_copy_2_bytes); |
1949 __ br_zero(Assembler::zero, false, Assembler::pt, count, L_exit); | 1935 __ cmp_and_br_short(count, 0, Assembler::equal, Assembler::pt, L_exit); |
1950 __ delayed()->nop(); | |
1951 __ BIND(L_copy_2_bytes_loop); | 1936 __ BIND(L_copy_2_bytes_loop); |
1952 __ dec(end_from, 2); | 1937 __ dec(end_from, 2); |
1953 __ dec(end_to, 2); | 1938 __ dec(end_to, 2); |
1954 __ lduh(end_from, 0, O4); | 1939 __ lduh(end_from, 0, O4); |
1955 __ deccc(count); | 1940 __ deccc(count); |
2058 generate_disjoint_long_copy_core(aligned); | 2043 generate_disjoint_long_copy_core(aligned); |
2059 __ mov(G4, count); // Restore | 2044 __ mov(G4, count); // Restore |
2060 | 2045 |
2061 // copy 1 element at a time | 2046 // copy 1 element at a time |
2062 __ BIND(L_copy_4_bytes); | 2047 __ BIND(L_copy_4_bytes); |
2063 __ br_zero(Assembler::zero, false, Assembler::pt, count, L_exit); | 2048 __ cmp_and_br_short(count, 0, Assembler::equal, Assembler::pt, L_exit); |
2064 __ delayed()->nop(); | |
2065 __ BIND(L_copy_4_bytes_loop); | 2049 __ BIND(L_copy_4_bytes_loop); |
2066 __ ld(from, offset, O3); | 2050 __ ld(from, offset, O3); |
2067 __ deccc(count); | 2051 __ deccc(count); |
2068 __ st(O3, to, offset); | 2052 __ st(O3, to, offset); |
2069 __ brx(Assembler::notZero, false, Assembler::pt, L_copy_4_bytes_loop); | 2053 __ brx(Assembler::notZero, false, Assembler::pt, L_copy_4_bytes_loop); |
2191 __ delayed()->stx(O4, end_to, 0); | 2175 __ delayed()->stx(O4, end_to, 0); |
2192 __ inc(count, 4); | 2176 __ inc(count, 4); |
2193 | 2177 |
2194 // copy 1 element (4 bytes) at a time | 2178 // copy 1 element (4 bytes) at a time |
2195 __ BIND(L_copy_4_bytes); | 2179 __ BIND(L_copy_4_bytes); |
2196 __ br_zero(Assembler::zero, false, Assembler::pt, count, L_exit); | 2180 __ cmp_and_br_short(count, 0, Assembler::equal, Assembler::pt, L_exit); |
2197 __ delayed()->nop(); | |
2198 __ BIND(L_copy_4_bytes_loop); | 2181 __ BIND(L_copy_4_bytes_loop); |
2199 __ dec(end_from, 4); | 2182 __ dec(end_from, 4); |
2200 __ dec(end_to, 4); | 2183 __ dec(end_to, 4); |
2201 __ ld(end_from, 0, O4); | 2184 __ ld(end_from, 0, O4); |
2202 __ deccc(count); | 2185 __ deccc(count); |
2574 __ save_frame(0); | 2557 __ save_frame(0); |
2575 __ check_klass_subtype_slow_path(sub_klass->after_save(), | 2558 __ check_klass_subtype_slow_path(sub_klass->after_save(), |
2576 super_klass->after_save(), | 2559 super_klass->after_save(), |
2577 L0, L1, L2, L4, | 2560 L0, L1, L2, L4, |
2578 NULL, &L_pop_to_miss); | 2561 NULL, &L_pop_to_miss); |
2579 __ ba(false, L_success); | 2562 __ ba(L_success); |
2580 __ delayed()->restore(); | 2563 __ delayed()->restore(); |
2581 | 2564 |
2582 __ bind(L_pop_to_miss); | 2565 __ bind(L_pop_to_miss); |
2583 __ restore(); | 2566 __ restore(); |
2584 | 2567 |
2671 __ delayed()->set(0, O0); // return -1 on success | 2654 __ delayed()->set(0, O0); // return -1 on success |
2672 | 2655 |
2673 // ======== loop entry is here ======== | 2656 // ======== loop entry is here ======== |
2674 __ BIND(load_element); | 2657 __ BIND(load_element); |
2675 __ load_heap_oop(O0_from, O5_offset, G3_oop); // load the oop | 2658 __ load_heap_oop(O0_from, O5_offset, G3_oop); // load the oop |
2676 __ br_null(G3_oop, true, Assembler::pt, store_element); | 2659 __ br_null_short(G3_oop, Assembler::pt, store_element); |
2677 __ delayed()->nop(); | |
2678 | 2660 |
2679 __ load_klass(G3_oop, G4_klass); // query the object klass | 2661 __ load_klass(G3_oop, G4_klass); // query the object klass |
2680 | 2662 |
2681 generate_type_check(G4_klass, O3_ckoff, O4_ckval, G5_super, | 2663 generate_type_check(G4_klass, O3_ckoff, O4_ckval, G5_super, |
2682 // branch to this on success: | 2664 // branch to this on success: |
2894 | 2876 |
2895 #ifdef ASSERT | 2877 #ifdef ASSERT |
2896 // assert(src->klass() != NULL); | 2878 // assert(src->klass() != NULL); |
2897 BLOCK_COMMENT("assert klasses not null"); | 2879 BLOCK_COMMENT("assert klasses not null"); |
2898 { Label L_a, L_b; | 2880 { Label L_a, L_b; |
2899 __ br_notnull(G3_src_klass, false, Assembler::pt, L_b); // it is broken if klass is NULL | 2881 __ br_notnull_short(G3_src_klass, Assembler::pt, L_b); // it is broken if klass is NULL |
2900 __ delayed()->nop(); | |
2901 __ bind(L_a); | 2882 __ bind(L_a); |
2902 __ stop("broken null klass"); | 2883 __ stop("broken null klass"); |
2903 __ bind(L_b); | 2884 __ bind(L_b); |
2904 __ load_klass(dst, G4_dst_klass); | 2885 __ load_klass(dst, G4_dst_klass); |
2905 __ br_null(G4_dst_klass, false, Assembler::pn, L_a); // this would be broken also | 2886 __ br_null(G4_dst_klass, false, Assembler::pn, L_a); // this would be broken also |
2935 } else { | 2916 } else { |
2936 __ delayed()->ld_ptr(dst, oopDesc::klass_offset_in_bytes(), G4_dst_klass); | 2917 __ delayed()->ld_ptr(dst, oopDesc::klass_offset_in_bytes(), G4_dst_klass); |
2937 } | 2918 } |
2938 | 2919 |
2939 // if (src->klass() != dst->klass()) return -1; | 2920 // if (src->klass() != dst->klass()) return -1; |
2940 __ cmp(G3_src_klass, G4_dst_klass); | 2921 __ cmp_and_brx_short(G3_src_klass, G4_dst_klass, Assembler::notEqual, Assembler::pn, L_failed); |
2941 __ brx(Assembler::notEqual, false, Assembler::pn, L_failed); | |
2942 __ delayed()->nop(); | |
2943 | 2922 |
2944 // if (!src->is_Array()) return -1; | 2923 // if (!src->is_Array()) return -1; |
2945 __ cmp(G5_lh, Klass::_lh_neutral_value); // < 0 | 2924 __ cmp(G5_lh, Klass::_lh_neutral_value); // < 0 |
2946 __ br(Assembler::greaterEqual, false, Assembler::pn, L_failed); | 2925 __ br(Assembler::greaterEqual, false, Assembler::pn, L_failed); |
2947 | 2926 |
3005 __ cmp(G3_elsize, LogBytesPerInt); | 2984 __ cmp(G3_elsize, LogBytesPerInt); |
3006 __ br(Assembler::equal, true, Assembler::pt, entry_jint_arraycopy); | 2985 __ br(Assembler::equal, true, Assembler::pt, entry_jint_arraycopy); |
3007 __ delayed()->signx(length, count); // length | 2986 __ delayed()->signx(length, count); // length |
3008 #ifdef ASSERT | 2987 #ifdef ASSERT |
3009 { Label L; | 2988 { Label L; |
3010 __ cmp(G3_elsize, LogBytesPerLong); | 2989 __ cmp_and_br_short(G3_elsize, LogBytesPerLong, Assembler::equal, Assembler::pt, L); |
3011 __ br(Assembler::equal, false, Assembler::pt, L); | |
3012 __ delayed()->nop(); | |
3013 __ stop("must be long copy, but elsize is wrong"); | 2990 __ stop("must be long copy, but elsize is wrong"); |
3014 __ bind(L); | 2991 __ bind(L); |
3015 } | 2992 } |
3016 #endif | 2993 #endif |
3017 __ br(Assembler::always, false, Assembler::pt, entry_jlong_arraycopy); | 2994 __ br(Assembler::always, false, Assembler::pt, entry_jlong_arraycopy); |