4912 // cnt is signed int. Do not rely on high word! |
4912 // cnt is signed int. Do not rely on high word! |
4913 // counts # characters, not bytes. |
4913 // counts # characters, not bytes. |
4914 // The result is the number of characters copied before the first incompatible character was found. |
4914 // The result is the number of characters copied before the first incompatible character was found. |
4915 // If precise is true, the processing stops exactly at this point. Otherwise, the result may be off |
4915 // If precise is true, the processing stops exactly at this point. Otherwise, the result may be off |
4916 // by a few bytes. The result always indicates the number of copied characters. |
4916 // by a few bytes. The result always indicates the number of copied characters. |
|
4917 // When used as a character index, the returned value points to the first incompatible character. |
4917 // |
4918 // |
4918 // Note: Does not behave exactly like package private StringUTF16 compress java implementation in case of failure: |
4919 // Note: Does not behave exactly like package private StringUTF16 compress java implementation in case of failure: |
4919 // - Different number of characters may have been written to dead array (if precise is false). |
4920 // - Different number of characters may have been written to dead array (if precise is false). |
4920 // - Returns a number <cnt instead of 0. (Result gets compared with cnt.) |
4921 // - Returns a number <cnt instead of 0. (Result gets compared with cnt.) |
4921 unsigned int MacroAssembler::string_compress(Register result, Register src, Register dst, Register cnt, |
4922 unsigned int MacroAssembler::string_compress(Register result, Register src, Register dst, Register cnt, |
4922 Register tmp, bool precise) { |
4923 Register tmp, bool precise) { |
4923 assert_different_registers(Z_R0, Z_R1, src, dst, cnt, tmp); |
4924 assert_different_registers(Z_R0, Z_R1, result, src, dst, cnt, tmp); |
4924 |
4925 |
4925 if (precise) { |
4926 if (precise) { |
4926 BLOCK_COMMENT("encode_iso_array {"); |
4927 BLOCK_COMMENT("encode_iso_array {"); |
4927 } else { |
4928 } else { |
4928 BLOCK_COMMENT("string_compress {"); |
4929 BLOCK_COMMENT("string_compress {"); |
5025 z_vo(Vtmp1, Z_V20, Z_V21); |
5026 z_vo(Vtmp1, Z_V20, Z_V21); |
5026 z_vo(Vtmp2, Z_V22, Z_V23); |
5027 z_vo(Vtmp2, Z_V22, Z_V23); |
5027 z_vo(Vtmp1, Vtmp1, Vtmp2); |
5028 z_vo(Vtmp1, Vtmp1, Vtmp2); |
5028 z_vn(Vtmp1, Vtmp1, Vmask); |
5029 z_vn(Vtmp1, Vtmp1, Vmask); |
5029 z_vceqhs(Vtmp1, Vtmp1, Vzero); // high half of all chars must be zero for successful compress. |
5030 z_vceqhs(Vtmp1, Vtmp1, Vzero); // high half of all chars must be zero for successful compress. |
5030 z_brne(VectorBreak); // break vector loop, incompatible character found. |
5031 z_bvnt(VectorBreak); // break vector loop if not all vector elements compare eq -> incompatible character found. |
5031 // re-process data from current iteration in break handler. |
5032 // re-process data from current iteration in break handler. |
5032 |
5033 |
5033 //---< pack & store characters >--- |
5034 //---< pack & store characters >--- |
5034 z_vpkh(Vtmp1, Z_V20, Z_V21); // pack (src1, src2) -> tmp1 |
5035 z_vpkh(Vtmp1, Z_V20, Z_V21); // pack (src1, src2) -> tmp1 |
5035 z_vpkh(Vtmp2, Z_V22, Z_V23); // pack (src3, src4) -> tmp2 |
5036 z_vpkh(Vtmp2, Z_V22, Z_V23); // pack (src3, src4) -> tmp2 |
5092 z_lgfr(Z_R0, Rcnt); // # chars processed in total after unrolled loop. |
5093 z_lgfr(Z_R0, Rcnt); // # chars processed in total after unrolled loop. |
5093 z_nilf(Z_R0, ~(min_cnt-1)); |
5094 z_nilf(Z_R0, ~(min_cnt-1)); |
5094 z_tmll(Rcnt, min_cnt-1); |
5095 z_tmll(Rcnt, min_cnt-1); |
5095 z_brnaz(ScalarShortcut); // if all bits zero, there is nothing left to do for scalar loop. |
5096 z_brnaz(ScalarShortcut); // if all bits zero, there is nothing left to do for scalar loop. |
5096 // Rix == 0 in all cases. |
5097 // Rix == 0 in all cases. |
|
5098 z_sllg(Z_R1, Rcnt, 1); // # src bytes already processed. Only lower 32 bits are valid! |
|
5099 // Z_R1 contents must be treated as unsigned operand! For huge strings, |
|
5100 // (Rcnt >= 2**30), the value may spill into the sign bit by sllg. |
5097 z_lgfr(result, Rcnt); // all characters processed. |
5101 z_lgfr(result, Rcnt); // all characters processed. |
5098 z_sgfr(Rdst, Rcnt); // restore ptr |
5102 z_slgfr(Rdst, Rcnt); // restore ptr |
5099 z_sgfr(Rsrc, Rcnt); // restore ptr, double the element count for Rsrc restore |
5103 z_slgfr(Rsrc, Z_R1); // restore ptr, double the element count for Rsrc restore |
5100 z_sgfr(Rsrc, Rcnt); |
|
5101 z_bru(AllDone); |
5104 z_bru(AllDone); |
5102 |
5105 |
5103 bind(UnrolledBreak); |
5106 bind(UnrolledBreak); |
5104 z_lgfr(Z_R0, Rcnt); // # chars processed in total after unrolled loop |
5107 z_lgfr(Z_R0, Rcnt); // # chars processed in total after unrolled loop |
5105 z_nilf(Z_R0, ~(min_cnt-1)); |
5108 z_nilf(Z_R0, ~(min_cnt-1)); |
5106 z_sll(Rix, log_min_cnt); // # chars processed so far in UnrolledLoop, excl. current iteration. |
5109 z_sll(Rix, log_min_cnt); // # chars not yet processed in UnrolledLoop (due to break), broken iteration not included. |
5107 z_sr(Z_R0, Rix); // correct # chars processed in total. |
5110 z_sr(Z_R0, Rix); // fix # chars processed OK so far. |
5108 if (!precise) { |
5111 if (!precise) { |
5109 z_lgfr(result, Z_R0); |
5112 z_lgfr(result, Z_R0); |
|
5113 z_sllg(Z_R1, Z_R0, 1); // # src bytes already processed. Only lower 32 bits are valid! |
|
5114 // Z_R1 contents must be treated as unsigned operand! For huge strings, |
|
5115 // (Rcnt >= 2**30), the value may spill into the sign bit by sllg. |
5110 z_aghi(result, min_cnt/2); // min_cnt/2 characters have already been written |
5116 z_aghi(result, min_cnt/2); // min_cnt/2 characters have already been written |
5111 // but ptrs were not updated yet. |
5117 // but ptrs were not updated yet. |
5112 z_sgfr(Rdst, Z_R0); // restore ptr |
5118 z_slgfr(Rdst, Z_R0); // restore ptr |
5113 z_sgfr(Rsrc, Z_R0); // restore ptr, double the element count for Rsrc restore |
5119 z_slgfr(Rsrc, Z_R1); // restore ptr, double the element count for Rsrc restore |
5114 z_sgfr(Rsrc, Z_R0); |
|
5115 z_bru(AllDone); |
5120 z_bru(AllDone); |
5116 } |
5121 } |
5117 bind(UnrolledDone); |
5122 bind(UnrolledDone); |
5118 } |
5123 } |
5119 |
5124 |