aboutsummaryrefslogtreecommitdiff
path: root/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu/aarch64/vm/macroAssembler_aarch64.cpp')
-rw-r--r--src/cpu/aarch64/vm/macroAssembler_aarch64.cpp61
1 files changed, 61 insertions, 0 deletions
diff --git a/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp b/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
index a00726d37..6c2b02d99 100644
--- a/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
+++ b/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp
@@ -3613,3 +3613,64 @@ void MacroAssembler::char_arrays_equals(Register ary1, Register ary2,
BLOCK_COMMENT("} char_arrays_equals");
}
+
+// encode char[] to byte[] in ISO_8859_1
+void MacroAssembler::encode_iso_array(Register src, Register dst,
+ Register len, Register result,
+ FloatRegister Vtmp1, FloatRegister Vtmp2,
+ FloatRegister Vtmp3, FloatRegister Vtmp4)
+{
+ Label DONE, NEXT_32, LOOP_8, NEXT_8, LOOP_1, NEXT_1;
+ Register tmp1 = rscratch1;
+
+ mov(result, len); // Save initial len
+
+ subs(len, len, 32);
+ br(LT, LOOP_8);
+
+// The following code uses the SIMD 'uqxtn' and 'uqxtn2' instructions
+// to convert chars to bytes. These set the 'QC' bit in the FPSR if
+// any char could not fit in a byte, so clear the FPSR so we can test it.
+ clear_fpsr();
+
+ BIND(NEXT_32);
+ ld1(Vtmp1, Vtmp2, Vtmp3, Vtmp4, T8H, src);
+ uqxtn(Vtmp1, T8B, Vtmp1, T8H); // uqxtn - write bottom half
+ uqxtn(Vtmp1, T16B, Vtmp2, T8H); // uqxtn2 - write top half
+ uqxtn(Vtmp2, T8B, Vtmp3, T8H);
+ uqxtn(Vtmp2, T16B, Vtmp4, T8H); // uqxtn2
+ get_fpsr(tmp1);
+ cbnzw(tmp1, LOOP_8);
+ st1(Vtmp1, Vtmp2, T16B, post(dst, 32));
+ subs(len, len, 32);
+ add(src, src, 64);
+ br(GE, NEXT_32);
+
+ BIND(LOOP_8);
+ adds(len, len, 32-8);
+ br(LT, LOOP_1);
+ clear_fpsr(); // QC may be set from loop above, clear again
+ BIND(NEXT_8);
+ ld1(Vtmp1, T8H, src);
+ uqxtn(Vtmp1, T8B, Vtmp1, T8H);
+ get_fpsr(tmp1);
+ cbnzw(tmp1, LOOP_1);
+ st1(Vtmp1, T8B, post(dst, 8));
+ subs(len, len, 8);
+ add(src, src, 16);
+ br(GE, NEXT_8);
+
+ BIND(LOOP_1);
+ adds(len, len, 8);
+ br(LE, DONE);
+ BIND(NEXT_1);
+ ldrh(tmp1, Address(post(src, 2)));
+ tst(tmp1, 0xff00);
+ br(NE, DONE);
+ strb(tmp1, Address(post(dst, 1)));
+ subs(len, len, 1);
+ br(GT, NEXT_1);
+
+ BIND(DONE);
+ sub(result, result, len); // Return index where we stopped
+}