hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp
changeset 360 21d113ecbf6a
parent 189 4248c8e21063
child 670 ddf3e9583f2f
child 1374 4c24294029a9
equal deleted inserted replaced
357:f4edb0d9f109 360:21d113ecbf6a
   125     const Argument parameter_size = Argument(6, false);
   125     const Argument parameter_size = Argument(6, false);
   126     const Argument thread         = Argument(7, false);
   126     const Argument thread         = Argument(7, false);
   127 
   127 
   128     // setup thread register
   128     // setup thread register
   129     __ ld_ptr(thread.as_address(), G2_thread);
   129     __ ld_ptr(thread.as_address(), G2_thread);
       
   130     __ reinit_heapbase();
   130 
   131 
   131 #ifdef ASSERT
   132 #ifdef ASSERT
   132     // make sure we have no pending exceptions
   133     // make sure we have no pending exceptions
   133     { const Register t = G3_scratch;
   134     { const Register t = G3_scratch;
   134       Label L;
   135       Label L;
   894   //      icc/xcc: set as O0 (depending on wordSize)
   895   //      icc/xcc: set as O0 (depending on wordSize)
   895   //      sub  : O1, argument, not changed
   896   //      sub  : O1, argument, not changed
   896   //      super: O2, argument, not changed
   897   //      super: O2, argument, not changed
   897   //      raddr: O7, blown by call
   898   //      raddr: O7, blown by call
   898   address generate_partial_subtype_check() {
   899   address generate_partial_subtype_check() {
       
   900     __ align(CodeEntryAlignment);
   899     StubCodeMark mark(this, "StubRoutines", "partial_subtype_check");
   901     StubCodeMark mark(this, "StubRoutines", "partial_subtype_check");
   900     address start = __ pc();
   902     address start = __ pc();
   901     Label loop, miss;
   903     Label loop, miss;
   902 
   904 
   903     // Compare super with sub directly, since super is not in its own SSA.
   905     // Compare super with sub directly, since super is not in its own SSA.
   912       __ bind(L);
   914       __ bind(L);
   913     }
   915     }
   914 
   916 
   915 #if defined(COMPILER2) && !defined(_LP64)
   917 #if defined(COMPILER2) && !defined(_LP64)
   916     // Do not use a 'save' because it blows the 64-bit O registers.
   918     // Do not use a 'save' because it blows the 64-bit O registers.
   917     __ add(SP,-4*wordSize,SP);  // Make space for 4 temps
   919     __ add(SP,-4*wordSize,SP);  // Make space for 4 temps (stack must be 2 words aligned)
   918     __ st_ptr(L0,SP,(frame::register_save_words+0)*wordSize);
   920     __ st_ptr(L0,SP,(frame::register_save_words+0)*wordSize);
   919     __ st_ptr(L1,SP,(frame::register_save_words+1)*wordSize);
   921     __ st_ptr(L1,SP,(frame::register_save_words+1)*wordSize);
   920     __ st_ptr(L2,SP,(frame::register_save_words+2)*wordSize);
   922     __ st_ptr(L2,SP,(frame::register_save_words+2)*wordSize);
   921     __ st_ptr(L3,SP,(frame::register_save_words+3)*wordSize);
   923     __ st_ptr(L3,SP,(frame::register_save_words+3)*wordSize);
   922     Register Rret   = O0;
   924     Register Rret   = O0;
   932     Register L0_ary_len = L0;
   934     Register L0_ary_len = L0;
   933     Register L1_ary_ptr = L1;
   935     Register L1_ary_ptr = L1;
   934     Register L2_super   = L2;
   936     Register L2_super   = L2;
   935     Register L3_index   = L3;
   937     Register L3_index   = L3;
   936 
   938 
       
   939 #ifdef _LP64
       
   940     Register L4_ooptmp  = L4;
       
   941 
       
   942     if (UseCompressedOops) {
       
   943       // this must be under UseCompressedOops check, as we rely upon fact
       
   944       // that L4 not clobbered in C2 on 32-bit platforms, where we do explicit save
       
   945       // on stack, see several lines above
       
   946       __ encode_heap_oop(Rsuper, L4_ooptmp);
       
   947     }
       
   948 #endif
       
   949 
   937     inc_counter_np(SharedRuntime::_partial_subtype_ctr, L0, L1);
   950     inc_counter_np(SharedRuntime::_partial_subtype_ctr, L0, L1);
   938 
   951 
   939     __ ld_ptr( Rsub, sizeof(oopDesc) + Klass::secondary_supers_offset_in_bytes(), L3 );
   952     __ ld_ptr( Rsub, sizeof(oopDesc) + Klass::secondary_supers_offset_in_bytes(), L3 );
   940     __ lduw(L3,arrayOopDesc::length_offset_in_bytes(),L0_ary_len);
   953     __ lduw(L3,arrayOopDesc::length_offset_in_bytes(),L0_ary_len);
   941     __ add(L3,arrayOopDesc::base_offset_in_bytes(T_OBJECT),L1_ary_ptr);
   954     __ add(L3,arrayOopDesc::base_offset_in_bytes(T_OBJECT),L1_ary_ptr);
   942     __ clr(L3_index);           // zero index
   955     __ clr(L3_index);           // zero index
   943     // Load a little early; will load 1 off the end of the array.
   956     // Load a little early; will load 1 off the end of the array.
   944     // Ok for now; revisit if we have other uses of this routine.
   957     // Ok for now; revisit if we have other uses of this routine.
   945     __ ld_ptr(L1_ary_ptr,0,L2_super);// Will load a little early
   958     if (UseCompressedOops) {
   946     __ align(CodeEntryAlignment);
   959       __ ld(L1_ary_ptr,0,L2_super);// Will load a little early
   947 
   960     } else {
       
   961       __ ld_ptr(L1_ary_ptr,0,L2_super);// Will load a little early
       
   962     }
       
   963 
       
   964     assert(heapOopSize != 0, "heapOopSize should be initialized");
   948     // The scan loop
   965     // The scan loop
   949     __ BIND(loop);
   966     __ BIND(loop);
   950     __ add(L1_ary_ptr,wordSize,L1_ary_ptr); // Bump by OOP size
   967     __ add(L1_ary_ptr, heapOopSize, L1_ary_ptr); // Bump by OOP size
   951     __ cmp(L3_index,L0_ary_len);
   968     __ cmp(L3_index,L0_ary_len);
   952     __ br(Assembler::equal,false,Assembler::pn,miss);
   969     __ br(Assembler::equal,false,Assembler::pn,miss);
   953     __ delayed()->inc(L3_index); // Bump index
   970     __ delayed()->inc(L3_index); // Bump index
   954     __ subcc(L2_super,Rsuper,Rret);   // Check for match; zero in Rret for a hit
   971 
   955     __ brx( Assembler::notEqual, false, Assembler::pt, loop );
   972     if (UseCompressedOops) {
   956     __ delayed()->ld_ptr(L1_ary_ptr,0,L2_super); // Will load a little early
   973 #ifdef  _LP64
       
   974       __ subcc(L2_super,L4_ooptmp,Rret);   // Check for match; zero in Rret for a hit
       
   975       __ br( Assembler::notEqual, false, Assembler::pt, loop );
       
   976       __ delayed()->ld(L1_ary_ptr,0,L2_super);// Will load a little early
       
   977 #else
       
   978       ShouldNotReachHere();
       
   979 #endif
       
   980     } else {
       
   981       __ subcc(L2_super,Rsuper,Rret);   // Check for match; zero in Rret for a hit
       
   982       __ brx( Assembler::notEqual, false, Assembler::pt, loop );
       
   983       __ delayed()->ld_ptr(L1_ary_ptr,0,L2_super);// Will load a little early
       
   984     }
   957 
   985 
   958     // Got a hit; report success; set cache.  Cache load doesn't
   986     // Got a hit; report success; set cache.  Cache load doesn't
   959     // happen here; for speed it is directly emitted by the compiler.
   987     // happen here; for speed it is directly emitted by the compiler.
   960     __ st_ptr( Rsuper, Rsub, sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() );
   988     __ st_ptr( Rsuper, Rsub, sizeof(oopDesc) + Klass::secondary_super_cache_offset_in_bytes() );
   961 
   989 
  1105       __ mov(L1, count);
  1133       __ mov(L1, count);
  1106       __ restore();
  1134       __ restore();
  1107     }
  1135     }
  1108 #endif // 0
  1136 #endif // 0
  1109   }
  1137   }
  1110 
       
  1111   //
  1138   //
  1112   //  Generate post-write barrier for array.
  1139   //  Generate post-write barrier for array.
  1113   //
  1140   //
  1114   //  Input:
  1141   //  Input:
  1115   //     addr     - register containing starting address
  1142   //     addr     - register containing starting address
  1146           assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
  1173           assert(sizeof(*ct->byte_map_base) == sizeof(jbyte), "adjust this code");
  1147           assert_different_registers(addr, count, tmp);
  1174           assert_different_registers(addr, count, tmp);
  1148 
  1175 
  1149           Label L_loop;
  1176           Label L_loop;
  1150 
  1177 
  1151           __ sll_ptr(count, LogBytesPerOop, count);
  1178           __ sll_ptr(count, LogBytesPerHeapOop, count);
  1152           __ sub(count, BytesPerOop, count);
  1179           __ sub(count, BytesPerHeapOop, count);
  1153           __ add(count, addr, count);
  1180           __ add(count, addr, count);
  1154           // Use two shifts to clear out those low order two bits! (Cannot opt. into 1.)
  1181           // Use two shifts to clear out those low order two bits! (Cannot opt. into 1.)
  1155           __ srl_ptr(addr, CardTableModRefBS::card_shift, addr);
  1182           __ srl_ptr(addr, CardTableModRefBS::card_shift, addr);
  1156           __ srl_ptr(count, CardTableModRefBS::card_shift, count);
  1183           __ srl_ptr(count, CardTableModRefBS::card_shift, count);
  1157           __ sub(count, addr, count);
  1184           __ sub(count, addr, count);
  1169         break;
  1196         break;
  1170       default      :
  1197       default      :
  1171         ShouldNotReachHere();
  1198         ShouldNotReachHere();
  1172 
  1199 
  1173     }
  1200     }
  1174 
       
  1175   }
  1201   }
  1176 
  1202 
  1177 
  1203 
  1178   // Copy big chunks forward with shift
  1204   // Copy big chunks forward with shift
  1179   //
  1205   //
  2224     // save arguments for barrier generation
  2250     // save arguments for barrier generation
  2225     __ mov(to, G1);
  2251     __ mov(to, G1);
  2226     __ mov(count, G5);
  2252     __ mov(count, G5);
  2227     gen_write_ref_array_pre_barrier(G1, G5);
  2253     gen_write_ref_array_pre_barrier(G1, G5);
  2228   #ifdef _LP64
  2254   #ifdef _LP64
  2229     generate_disjoint_long_copy_core(aligned);
  2255     assert_clean_int(count, O3);     // Make sure 'count' is clean int.
       
  2256     if (UseCompressedOops) {
       
  2257       generate_disjoint_int_copy_core(aligned);
       
  2258     } else {
       
  2259       generate_disjoint_long_copy_core(aligned);
       
  2260     }
  2230   #else
  2261   #else
  2231     generate_disjoint_int_copy_core(aligned);
  2262     generate_disjoint_int_copy_core(aligned);
  2232   #endif
  2263   #endif
  2233     // O0 is used as temp register
  2264     // O0 is used as temp register
  2234     gen_write_ref_array_post_barrier(G1, G5, O0);
  2265     gen_write_ref_array_post_barrier(G1, G5, O0);
  2272 
  2303 
  2273     address nooverlap_target = aligned ?
  2304     address nooverlap_target = aligned ?
  2274         StubRoutines::arrayof_oop_disjoint_arraycopy() :
  2305         StubRoutines::arrayof_oop_disjoint_arraycopy() :
  2275         disjoint_oop_copy_entry;
  2306         disjoint_oop_copy_entry;
  2276 
  2307 
  2277     array_overlap_test(nooverlap_target, LogBytesPerWord);
  2308     array_overlap_test(nooverlap_target, LogBytesPerHeapOop);
  2278 
  2309 
  2279   #ifdef _LP64
  2310   #ifdef _LP64
  2280     generate_conjoint_long_copy_core(aligned);
  2311     if (UseCompressedOops) {
       
  2312       generate_conjoint_int_copy_core(aligned);
       
  2313     } else {
       
  2314       generate_conjoint_long_copy_core(aligned);
       
  2315     }
  2281   #else
  2316   #else
  2282     generate_conjoint_int_copy_core(aligned);
  2317     generate_conjoint_int_copy_core(aligned);
  2283   #endif
  2318   #endif
  2284 
  2319 
  2285     // O0 is used as temp register
  2320     // O0 is used as temp register
  2375 
  2410 
  2376     __ align(CodeEntryAlignment);
  2411     __ align(CodeEntryAlignment);
  2377     StubCodeMark mark(this, "StubRoutines", name);
  2412     StubCodeMark mark(this, "StubRoutines", name);
  2378     address start = __ pc();
  2413     address start = __ pc();
  2379 
  2414 
  2380     int klass_off = oopDesc::klass_offset_in_bytes();
       
  2381 
       
  2382     gen_write_ref_array_pre_barrier(G1, G5);
  2415     gen_write_ref_array_pre_barrier(G1, G5);
  2383 
  2416 
  2384 
  2417 
  2385 #ifdef ASSERT
  2418 #ifdef ASSERT
  2386     // We sometimes save a frame (see partial_subtype_check below).
  2419     // We sometimes save a frame (see partial_subtype_check below).
  2393     // caller guarantees that the arrays really are different
  2426     // caller guarantees that the arrays really are different
  2394     // otherwise, we would have to make conjoint checks
  2427     // otherwise, we would have to make conjoint checks
  2395     { Label L;
  2428     { Label L;
  2396       __ mov(O3, G1);           // spill: overlap test smashes O3
  2429       __ mov(O3, G1);           // spill: overlap test smashes O3
  2397       __ mov(O4, G4);           // spill: overlap test smashes O4
  2430       __ mov(O4, G4);           // spill: overlap test smashes O4
  2398       array_overlap_test(L, LogBytesPerWord);
  2431       array_overlap_test(L, LogBytesPerHeapOop);
  2399       __ stop("checkcast_copy within a single array");
  2432       __ stop("checkcast_copy within a single array");
  2400       __ bind(L);
  2433       __ bind(L);
  2401       __ mov(G1, O3);
  2434       __ mov(G1, O3);
  2402       __ mov(G4, O4);
  2435       __ mov(G4, O4);
  2403     }
  2436     }
  2427     //   G3, G4, G5 --- current oop, oop.klass, oop.klass.super
  2460     //   G3, G4, G5 --- current oop, oop.klass, oop.klass.super
  2428     __ align(16);
  2461     __ align(16);
  2429 
  2462 
  2430     __ bind(store_element);
  2463     __ bind(store_element);
  2431     // deccc(G1_remain);                // decrement the count (hoisted)
  2464     // deccc(G1_remain);                // decrement the count (hoisted)
  2432     __ st_ptr(G3_oop, O1_to, O5_offset); // store the oop
  2465     __ store_heap_oop(G3_oop, O1_to, O5_offset); // store the oop
  2433     __ inc(O5_offset, wordSize);        // step to next offset
  2466     __ inc(O5_offset, heapOopSize);     // step to next offset
  2434     __ brx(Assembler::zero, true, Assembler::pt, do_card_marks);
  2467     __ brx(Assembler::zero, true, Assembler::pt, do_card_marks);
  2435     __ delayed()->set(0, O0);           // return -1 on success
  2468     __ delayed()->set(0, O0);           // return -1 on success
  2436 
  2469 
  2437     // ======== loop entry is here ========
  2470     // ======== loop entry is here ========
  2438     __ bind(load_element);
  2471     __ bind(load_element);
  2439     __ ld_ptr(O0_from, O5_offset, G3_oop);  // load the oop
  2472     __ load_heap_oop(O0_from, O5_offset, G3_oop);  // load the oop
  2440     __ br_null(G3_oop, true, Assembler::pt, store_element);
  2473     __ br_null(G3_oop, true, Assembler::pt, store_element);
  2441     __ delayed()->deccc(G1_remain);     // decrement the count
  2474     __ delayed()->deccc(G1_remain);     // decrement the count
  2442 
  2475 
  2443     __ ld_ptr(G3_oop, klass_off, G4_klass); // query the object klass
  2476     __ load_klass(G3_oop, G4_klass); // query the object klass
  2444 
  2477 
  2445     generate_type_check(G4_klass, O3_ckoff, O4_ckval, G5_super,
  2478     generate_type_check(G4_klass, O3_ckoff, O4_ckval, G5_super,
  2446                         // branch to this on success:
  2479                         // branch to this on success:
  2447                         store_element,
  2480                         store_element,
  2448                         // decrement this on success:
  2481                         // decrement this on success:
  2640     __ delayed()->tst(length);
  2673     __ delayed()->tst(length);
  2641     __ br(Assembler::negative, false, Assembler::pn, L_failed);
  2674     __ br(Assembler::negative, false, Assembler::pn, L_failed);
  2642 
  2675 
  2643     BLOCK_COMMENT("arraycopy argument klass checks");
  2676     BLOCK_COMMENT("arraycopy argument klass checks");
  2644     //  get src->klass()
  2677     //  get src->klass()
  2645     __ delayed()->ld_ptr(src, oopDesc::klass_offset_in_bytes(), G3_src_klass);
  2678     if (UseCompressedOops) {
       
  2679       __ delayed()->nop(); // ??? not good
       
  2680       __ load_klass(src, G3_src_klass);
       
  2681     } else {
       
  2682       __ delayed()->ld_ptr(src, oopDesc::klass_offset_in_bytes(), G3_src_klass);
       
  2683     }
  2646 
  2684 
  2647 #ifdef ASSERT
  2685 #ifdef ASSERT
  2648     //  assert(src->klass() != NULL);
  2686     //  assert(src->klass() != NULL);
  2649     BLOCK_COMMENT("assert klasses not null");
  2687     BLOCK_COMMENT("assert klasses not null");
  2650     { Label L_a, L_b;
  2688     { Label L_a, L_b;
  2651       __ br_notnull(G3_src_klass, false, Assembler::pt, L_b); // it is broken if klass is NULL
  2689       __ br_notnull(G3_src_klass, false, Assembler::pt, L_b); // it is broken if klass is NULL
  2652       __ delayed()->ld_ptr(dst, oopDesc::klass_offset_in_bytes(), G4_dst_klass);
  2690       __ delayed()->nop();
  2653       __ bind(L_a);
  2691       __ bind(L_a);
  2654       __ stop("broken null klass");
  2692       __ stop("broken null klass");
  2655       __ bind(L_b);
  2693       __ bind(L_b);
       
  2694       __ load_klass(dst, G4_dst_klass);
  2656       __ br_null(G4_dst_klass, false, Assembler::pn, L_a); // this would be broken also
  2695       __ br_null(G4_dst_klass, false, Assembler::pn, L_a); // this would be broken also
  2657       __ delayed()->mov(G0, G4_dst_klass);      // scribble the temp
  2696       __ delayed()->mov(G0, G4_dst_klass);      // scribble the temp
  2658       BLOCK_COMMENT("assert done");
  2697       BLOCK_COMMENT("assert done");
  2659     }
  2698     }
  2660 #endif
  2699 #endif
  2671                     Klass::layout_helper_offset_in_bytes();
  2710                     Klass::layout_helper_offset_in_bytes();
  2672 
  2711 
  2673     // Load 32-bits signed value. Use br() instruction with it to check icc.
  2712     // Load 32-bits signed value. Use br() instruction with it to check icc.
  2674     __ lduw(G3_src_klass, lh_offset, G5_lh);
  2713     __ lduw(G3_src_klass, lh_offset, G5_lh);
  2675 
  2714 
       
  2715     if (UseCompressedOops) {
       
  2716       __ load_klass(dst, G4_dst_klass);
       
  2717     }
  2676     // Handle objArrays completely differently...
  2718     // Handle objArrays completely differently...
  2677     juint objArray_lh = Klass::array_layout_helper(T_OBJECT);
  2719     juint objArray_lh = Klass::array_layout_helper(T_OBJECT);
  2678     __ set(objArray_lh, O5_temp);
  2720     __ set(objArray_lh, O5_temp);
  2679     __ cmp(G5_lh,       O5_temp);
  2721     __ cmp(G5_lh,       O5_temp);
  2680     __ br(Assembler::equal, false, Assembler::pt, L_objArray);
  2722     __ br(Assembler::equal, false, Assembler::pt, L_objArray);
  2681     __ delayed()->ld_ptr(dst, oopDesc::klass_offset_in_bytes(), G4_dst_klass);
  2723     if (UseCompressedOops) {
       
  2724       __ delayed()->nop();
       
  2725     } else {
       
  2726       __ delayed()->ld_ptr(dst, oopDesc::klass_offset_in_bytes(), G4_dst_klass);
       
  2727     }
  2682 
  2728 
  2683     //  if (src->klass() != dst->klass()) return -1;
  2729     //  if (src->klass() != dst->klass()) return -1;
  2684     __ cmp(G3_src_klass, G4_dst_klass);
  2730     __ cmp(G3_src_klass, G4_dst_klass);
  2685     __ brx(Assembler::notEqual, false, Assembler::pn, L_failed);
  2731     __ brx(Assembler::notEqual, false, Assembler::pn, L_failed);
  2686     __ delayed()->nop();
  2732     __ delayed()->nop();
  2775     arraycopy_range_checks(src, src_pos, dst, dst_pos, length,
  2821     arraycopy_range_checks(src, src_pos, dst, dst_pos, length,
  2776                            O5_temp, G5_lh, L_failed);
  2822                            O5_temp, G5_lh, L_failed);
  2777 
  2823 
  2778     __ add(src, arrayOopDesc::base_offset_in_bytes(T_OBJECT), src); //src offset
  2824     __ add(src, arrayOopDesc::base_offset_in_bytes(T_OBJECT), src); //src offset
  2779     __ add(dst, arrayOopDesc::base_offset_in_bytes(T_OBJECT), dst); //dst offset
  2825     __ add(dst, arrayOopDesc::base_offset_in_bytes(T_OBJECT), dst); //dst offset
  2780     __ sll_ptr(src_pos, LogBytesPerOop, src_pos);
  2826     __ sll_ptr(src_pos, LogBytesPerHeapOop, src_pos);
  2781     __ sll_ptr(dst_pos, LogBytesPerOop, dst_pos);
  2827     __ sll_ptr(dst_pos, LogBytesPerHeapOop, dst_pos);
  2782     __ add(src, src_pos, from);       // src_addr
  2828     __ add(src, src_pos, from);       // src_addr
  2783     __ add(dst, dst_pos, to);         // dst_addr
  2829     __ add(dst, dst_pos, to);         // dst_addr
  2784   __ BIND(L_plain_copy);
  2830   __ BIND(L_plain_copy);
  2785     __ br(Assembler::always, false, Assembler::pt,StubRoutines::_oop_arraycopy);
  2831     __ br(Assembler::always, false, Assembler::pt,StubRoutines::_oop_arraycopy);
  2786     __ delayed()->signx(length, count); // length
  2832     __ delayed()->signx(length, count); // length
  2799                              O5_temp, G5_lh, L_failed);
  2845                              O5_temp, G5_lh, L_failed);
  2800 
  2846 
  2801       // Marshal the base address arguments now, freeing registers.
  2847       // Marshal the base address arguments now, freeing registers.
  2802       __ add(src, arrayOopDesc::base_offset_in_bytes(T_OBJECT), src); //src offset
  2848       __ add(src, arrayOopDesc::base_offset_in_bytes(T_OBJECT), src); //src offset
  2803       __ add(dst, arrayOopDesc::base_offset_in_bytes(T_OBJECT), dst); //dst offset
  2849       __ add(dst, arrayOopDesc::base_offset_in_bytes(T_OBJECT), dst); //dst offset
  2804       __ sll_ptr(src_pos, LogBytesPerOop, src_pos);
  2850       __ sll_ptr(src_pos, LogBytesPerHeapOop, src_pos);
  2805       __ sll_ptr(dst_pos, LogBytesPerOop, dst_pos);
  2851       __ sll_ptr(dst_pos, LogBytesPerHeapOop, dst_pos);
  2806       __ add(src, src_pos, from);               // src_addr
  2852       __ add(src, src_pos, from);               // src_addr
  2807       __ add(dst, dst_pos, to);                 // dst_addr
  2853       __ add(dst, dst_pos, to);                 // dst_addr
  2808       __ signx(length, count);                  // length (reloaded)
  2854       __ signx(length, count);                  // length (reloaded)
  2809 
  2855 
  2810       Register sco_temp = O3;                   // this register is free now
  2856       Register sco_temp = O3;                   // this register is free now