std/xz: implement apply_filter_0b_riscv
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index daa3e28..6e9e897 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -66847,6 +66847,12 @@
wuffs_base__slice_u8 a_dst_slice);
WUFFS_BASE__GENERATED_C_CODE
+static uint8_t
+wuffs_xz__decoder__apply_filter_0b_riscv(
+ wuffs_xz__decoder* self,
+ wuffs_base__slice_u8 a_dst_slice);
+
+WUFFS_BASE__GENERATED_C_CODE
static wuffs_base__status
wuffs_xz__decoder__do_transform_io(
wuffs_xz__decoder* self,
@@ -67385,6 +67391,98 @@
return ((uint8_t)(((uint64_t)(v_s.len))));
}
+// -------- func xz.decoder.apply_filter_0b_riscv
+
+WUFFS_BASE__GENERATED_C_CODE
+static uint8_t
+wuffs_xz__decoder__apply_filter_0b_riscv(
+ wuffs_xz__decoder* self,
+ wuffs_base__slice_u8 a_dst_slice) {
+ wuffs_base__slice_u8 v_s = {0};
+ uint32_t v_p = 0;
+ uint32_t v_x = 0;
+ uint32_t v_x27 = 0;
+ uint32_t v_y = 0;
+ uint32_t v_addr = 0;
+
+ v_s = a_dst_slice;
+ v_p = self->private_impl.f_bcj_pos;
+ while (((uint64_t)(v_s.len)) >= 8u) {
+ if (v_s.ptr[0u] == 239u) {
+ if (((uint8_t)(v_s.ptr[1u] & 13u)) != 0u) {
+ v_p += 2u;
+ v_s = wuffs_base__slice_u8__subslice_i(v_s, 2u);
+ continue;
+ }
+ v_addr = ((((uint32_t)(((uint8_t)(v_s.ptr[1u] & 240u)))) << 13u) | (((uint32_t)(v_s.ptr[2u])) << 9u) | (((uint32_t)(v_s.ptr[3u])) << 1u));
+ v_addr -= v_p;
+ v_s.ptr[1u] = ((uint8_t)(((uint8_t)(v_s.ptr[1u] & 15u)) | ((uint8_t)(((v_addr >> 8u) & 240u)))));
+ v_s.ptr[2u] = ((uint8_t)((((v_addr >> 16u) & 15u) | ((v_addr >> 7u) & 16u) | (((uint32_t)(v_addr << 4u)) & 224u))));
+ v_s.ptr[3u] = ((uint8_t)((((v_addr >> 4u) & 127u) | ((v_addr >> 13u) & 128u))));
+ v_p += 4u;
+ v_s = wuffs_base__slice_u8__subslice_i(v_s, 4u);
+ continue;
+ } else if (((uint8_t)(v_s.ptr[0u] & 127u)) == 23u) {
+ v_x = ((((uint32_t)(v_s.ptr[0u])) << 0u) |
+ (((uint32_t)(v_s.ptr[1u])) << 8u) |
+ (((uint32_t)(v_s.ptr[2u])) << 16u) |
+ (((uint32_t)(v_s.ptr[3u])) << 24u));
+ if ((v_x & 3712u) != 0u) {
+ v_y = ((((uint32_t)(v_s.ptr[4u])) << 0u) |
+ (((uint32_t)(v_s.ptr[5u])) << 8u) |
+ (((uint32_t)(v_s.ptr[6u])) << 16u) |
+ (((uint32_t)(v_s.ptr[7u])) << 24u));
+ if (((((uint32_t)(v_x << 8u)) ^ ((uint32_t)(v_y - 3u))) & 1015811u) != 0u) {
+ v_p += 6u;
+ v_s = wuffs_base__slice_u8__subslice_i(v_s, 6u);
+ continue;
+ }
+ v_addr = ((v_x & 4294963200u) | (v_y >> 20u));
+ v_x = (279u | ((uint32_t)(v_y << 12u)));
+ v_s.ptr[0u] = ((uint8_t)((v_x >> 0u)));
+ v_s.ptr[1u] = ((uint8_t)((v_x >> 8u)));
+ v_s.ptr[2u] = ((uint8_t)((v_x >> 16u)));
+ v_s.ptr[3u] = ((uint8_t)((v_x >> 24u)));
+ v_s.ptr[4u] = ((uint8_t)((v_addr >> 0u)));
+ v_s.ptr[5u] = ((uint8_t)((v_addr >> 8u)));
+ v_s.ptr[6u] = ((uint8_t)((v_addr >> 16u)));
+ v_s.ptr[7u] = ((uint8_t)((v_addr >> 24u)));
+ v_p += 8u;
+ v_s = wuffs_base__slice_u8__subslice_i(v_s, 8u);
+ continue;
+ }
+ v_x27 = (v_x >> 27u);
+ if (((uint32_t)(((uint32_t)(v_x - 12567u)) << 18u)) >= (v_x27 & 29u)) {
+ v_p += 4u;
+ v_s = wuffs_base__slice_u8__subslice_i(v_s, 4u);
+ continue;
+ }
+ v_addr = ((((uint32_t)(v_s.ptr[4u])) << 24u) |
+ (((uint32_t)(v_s.ptr[5u])) << 16u) |
+ (((uint32_t)(v_s.ptr[6u])) << 8u) |
+ (((uint32_t)(v_s.ptr[7u])) << 0u));
+ v_addr -= v_p;
+ v_y = ((v_x >> 12u) | ((uint32_t)(v_addr << 20u)));
+ v_x = (23u | (v_x27 << 7u) | (((uint32_t)(v_addr + 2048u)) & 4294963200u));
+ v_s.ptr[0u] = ((uint8_t)((v_x >> 0u)));
+ v_s.ptr[1u] = ((uint8_t)((v_x >> 8u)));
+ v_s.ptr[2u] = ((uint8_t)((v_x >> 16u)));
+ v_s.ptr[3u] = ((uint8_t)((v_x >> 24u)));
+ v_s.ptr[4u] = ((uint8_t)((v_y >> 0u)));
+ v_s.ptr[5u] = ((uint8_t)((v_y >> 8u)));
+ v_s.ptr[6u] = ((uint8_t)((v_y >> 16u)));
+ v_s.ptr[7u] = ((uint8_t)((v_y >> 24u)));
+ v_p += 8u;
+ v_s = wuffs_base__slice_u8__subslice_i(v_s, 8u);
+ continue;
+ }
+ v_p += 2u;
+ v_s = wuffs_base__slice_u8__subslice_i(v_s, 2u);
+ }
+ self->private_impl.f_bcj_pos = v_p;
+ return ((uint8_t)(((uint64_t)(v_s.len))));
+}
+
// -------- func xz.decoder.get_quirk
WUFFS_BASE__GENERATED_C_CODE
@@ -68382,7 +68480,7 @@
self->private_data.f_filter_data[v_f][v_k] = 0u;
v_k += 1u;
}
- } else if ((v_filter_id < 3u) || (10u < v_filter_id)) {
+ } else if ((v_filter_id < 3u) || (11u < v_filter_id)) {
status = wuffs_base__make_status(wuffs_xz__error__unsupported_filter);
goto exit;
} else if (v_f != 0u) {
@@ -68408,9 +68506,12 @@
} else if (v_filter_id == 9u) {
self->private_impl.choosy_apply_non_final_filters = (
&wuffs_xz__decoder__apply_filter_09_sparc);
- } else {
+ } else if (v_filter_id == 10u) {
self->private_impl.choosy_apply_non_final_filters = (
&wuffs_xz__decoder__apply_filter_0a_arm64);
+ } else {
+ self->private_impl.choosy_apply_non_final_filters = (
+ &wuffs_xz__decoder__apply_filter_0b_riscv);
}
{
WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
diff --git a/std/xz/decode_filter.wuffs b/std/xz/decode_filter.wuffs
index fbc4dbe..7c560e8 100644
--- a/std/xz/decode_filter.wuffs
+++ b/std/xz/decode_filter.wuffs
@@ -440,3 +440,105 @@
this.bcj_pos = p
return s.length() as base.u8
}
+
+pri func decoder.apply_filter_0b_riscv!(dst_slice: slice base.u8) base.u8 {
+ var s : slice base.u8
+ var p : base.u32
+ var x : base.u32
+ var x27 : base.u32[..= 31]
+ var y : base.u32
+ var addr : base.u32
+
+ s = args.dst_slice
+ p = this.bcj_pos
+
+ while s.length() >= 8,
+ post s.length() < 8,
+ {
+ if s[0] == 0xEF {
+ // RISC-V JAL instruction.
+ if (s[1] & 0x0D) <> 0x00 {
+ p ~mod+= 2
+ s = s[2 ..]
+ continue
+ }
+ addr = (((s[1] & 0xF0) as base.u32) << 13) |
+ ((s[2] as base.u32) << 9) |
+ ((s[3] as base.u32) << 1)
+ addr ~mod-= p
+ s[1] = (s[1] & 0x0F) |
+ (((addr >> 8) & 0xF0) as base.u8)
+ s[2] = (((addr >> 16) & 0x0F) |
+ ((addr >> 7) & 0x10) |
+ ((addr ~mod<< 4) & 0xE0)) as base.u8
+ s[3] = (((addr >> 4) & 0x7F) |
+ ((addr >> 13) & 0x80)) as base.u8
+ p ~mod+= 4
+ s = s[4 ..]
+ continue
+
+ } else if (s[0] & 0x7F) == 0x17 {
+ // RISC-V AUIPC instruction.
+ x = ((s[0] as base.u32) << 0x00) |
+ ((s[1] as base.u32) << 0x08) |
+ ((s[2] as base.u32) << 0x10) |
+ ((s[3] as base.u32) << 0x18)
+
+ if (x & 0xE80) <> 0 {
+ y = ((s[4] as base.u32) << 0x00) |
+ ((s[5] as base.u32) << 0x08) |
+ ((s[6] as base.u32) << 0x10) |
+ ((s[7] as base.u32) << 0x18)
+ if (((x ~mod<< 8) ^ (y ~mod- 3)) & 0x000F_8003) <> 0 {
+ p ~mod+= 6
+ s = s[6 ..]
+ continue
+ }
+ addr = (x & 0xFFFF_F000) | (y >> 20)
+ x = 0x117 | (y ~mod<< 12)
+ s[0] = ((x >> 0x00) & 0xFF) as base.u8
+ s[1] = ((x >> 0x08) & 0xFF) as base.u8
+ s[2] = ((x >> 0x10) & 0xFF) as base.u8
+ s[3] = ((x >> 0x18) & 0xFF) as base.u8
+ s[4] = ((addr >> 0x00) & 0xFF) as base.u8
+ s[5] = ((addr >> 0x08) & 0xFF) as base.u8
+ s[6] = ((addr >> 0x10) & 0xFF) as base.u8
+ s[7] = ((addr >> 0x18) & 0xFF) as base.u8
+ p ~mod+= 8
+ s = s[8 ..]
+ continue
+ }
+
+ x27 = x >> 27
+ if ((x ~mod- 0x3117) ~mod<< 18) >= (x27 & 0x1D) {
+ p ~mod+= 4
+ s = s[4 ..]
+ continue
+ }
+ addr = ((s[4] as base.u32) << 0x18) |
+ ((s[5] as base.u32) << 0x10) |
+ ((s[6] as base.u32) << 0x08) |
+ ((s[7] as base.u32) << 0x00)
+ addr ~mod-= p
+ y = (x >> 12) | (addr ~mod<< 20)
+ x = 0x17 | (x27 << 7) | ((addr ~mod+ 0x800) & 0xFFFF_F000)
+ s[0] = ((x >> 0x00) & 0xFF) as base.u8
+ s[1] = ((x >> 0x08) & 0xFF) as base.u8
+ s[2] = ((x >> 0x10) & 0xFF) as base.u8
+ s[3] = ((x >> 0x18) & 0xFF) as base.u8
+ s[4] = ((y >> 0x00) & 0xFF) as base.u8
+ s[5] = ((y >> 0x08) & 0xFF) as base.u8
+ s[6] = ((y >> 0x10) & 0xFF) as base.u8
+ s[7] = ((y >> 0x18) & 0xFF) as base.u8
+ p ~mod+= 8
+ s = s[8 ..]
+ continue
+ }
+
+ p ~mod+= 2
+ s = s[2 ..]
+ } endwhile
+
+ this.bcj_pos = p
+ return s.length() as base.u8
+}
diff --git a/std/xz/decode_xz.wuffs b/std/xz/decode_xz.wuffs
index 50bb338..04240e1 100644
--- a/std/xz/decode_xz.wuffs
+++ b/std/xz/decode_xz.wuffs
@@ -413,7 +413,7 @@
k += 1
} endwhile
- } else if (filter_id < 0x03) or (0x0A < filter_id) {
+ } else if (filter_id < 0x03) or (0x0B < filter_id) {
return "#unsupported filter"
} else if f <> 0 {
// We only support BCJ (Branch, Call, Jump) filters if they're the
@@ -434,8 +434,10 @@
choose apply_non_final_filters = [apply_filter_08_armthumb]
} else if filter_id == 0x09 {
choose apply_non_final_filters = [apply_filter_09_sparc]
- } else {
+ } else if filter_id == 0x0A {
choose apply_non_final_filters = [apply_filter_0a_arm64]
+ } else {
+ choose apply_non_final_filters = [apply_filter_0b_riscv]
}
c8 = args.src.read_u8?()
diff --git a/test/3pdata/mzcat-checksums-of-xzsuite.txt b/test/3pdata/mzcat-checksums-of-xzsuite.txt
index 67b30ff..3e39cb5 100644
--- a/test/3pdata/mzcat-checksums-of-xzsuite.txt
+++ b/test/3pdata/mzcat-checksums-of-xzsuite.txt
@@ -62,6 +62,8 @@
OK. db4847fb test/3pdata/xzsuite/good-1-lzma2-3.xz
OK. db4847fb test/3pdata/xzsuite/good-1-lzma2-4.xz
OK. 00000000 test/3pdata/xzsuite/good-1-lzma2-5.xz
+OK. 9d269cdc test/3pdata/xzsuite/good-1-riscv-lzma2-1.xz
+OK. 8d115715 test/3pdata/xzsuite/good-1-riscv-lzma2-2.xz
OK. cc270da1 test/3pdata/xzsuite/good-1-sparc-lzma2.xz
OK. a3679091 test/3pdata/xzsuite/good-1-x86-lzma2.xz
OK. 15a2a343 test/3pdata/xzsuite/good-2-lzma2.xz
diff --git a/test/data/artificial-xz-filter/make.go b/test/data/artificial-xz-filter/make.go
index d81c02a..7355a09 100644
--- a/test/data/artificial-xz-filter/make.go
+++ b/test/data/artificial-xz-filter/make.go
@@ -39,6 +39,9 @@
// No test case generated for 04/x86, as the x86 CPU bytecode format is
// complicated (variable length instructions). Test coverage is instead
// provided by xz-tests-files's good-1-x86-lzma2.xz file.
+ //
+ // Similarly, no test case here for 0b/riscv. It's covered by the
+ // good-1-riscv-lzma2-*.xz files.
{"05", "powerpc", genPowerpc},
{"06", "ia64", genIa64},
{"07", "arm", genArm},