summaryrefslogtreecommitdiff
path: root/cesar/mac/pbproc/src/sacki_enc.c
diff options
context:
space:
mode:
Diffstat (limited to 'cesar/mac/pbproc/src/sacki_enc.c')
-rw-r--r--cesar/mac/pbproc/src/sacki_enc.c191
1 files changed, 191 insertions, 0 deletions
diff --git a/cesar/mac/pbproc/src/sacki_enc.c b/cesar/mac/pbproc/src/sacki_enc.c
new file mode 100644
index 0000000000..fceffd9f74
--- /dev/null
+++ b/cesar/mac/pbproc/src/sacki_enc.c
@@ -0,0 +1,191 @@
+/* Cesar project {{{
+ *
+ * Copyright (C) 2007 Spidcom
+ *
+ * <<<Licence>>>
+ *
+ * }}} */
+/**
+ * \file mac/pbproc/src/sacki_enc.c
+ * \brief SACKI compression.
+ * \ingroup mac_pbproc
+ */
+#include "common/std.h"
+
+#include "inc/sacki_enc.h"
+
+#include "pbproc_sacki_enc_tables.h"
+
+#ifdef PBPROC_SACKI_ENC_DEBUG
+# undef PBPROC_SACKI_ENC_DEBUG
+void
+pbproc_sacki_enc_debug (u32 code, uint codel, uint eat);
+# define PBPROC_SACKI_ENC_DEBUG(code, codel, eat) \
+ pbproc_sacki_enc_debug ((code), (codel), (eat))
+#else
+# define PBPROC_SACKI_ENC_DEBUG(code, codel, eat)
+#endif
+
+static const struct sack_enc_finish_t * const sack_enc_f[] = {
+ sack_enc_f1,
+ sack_enc_f2,
+ sack_enc_f3,
+};
+
+void
+pbproc_sacki_enc_init (pbproc_sacki_enc_t *ctx, uint sil)
+{
+ ctx->si[0] = 0;
+ ctx->si[1] = 0;
+ ctx->si[2] = 0;
+ ctx->sis = 0;
+ ctx->sil = sil;
+ ctx->bmps = 0;
+}
+
+void
+pbproc_sacki_enc_process (pbproc_sacki_enc_t *ctx, const volatile u32 *bmp,
+ uint bmpl, bool final)
+{
+ u32 bmp0, bmp1; /* Extended bmp cache. */
+ uint bmp01l; /* Number of bits remaining in {bmp1, bmp0}. */
+ uint bmps; /* Start offset in bmp. */
+ u32 si0; /* SACKI write cache. */
+ uint sisw; /* SACKI start offset in words. */
+ uint sisb; /* SACKI start offset in bits. */
+ uint sil; /* SACKI bits left. */
+ /* Load bmp cache. */
+ bmps = ctx->bmps;
+ bmp += bmps / 32;
+ bmpl -= bmps;
+ bmp01l = MIN (bmpl, 32 - bmps % 32);
+ bmpl -= bmp01l;
+ bmp0 = *bmp++;
+ bmp0 >>= bmps % 32;
+ bmp1 = 0;
+ /* Load si cache. */
+ sisw = ctx->sis / 32;
+ sisb = ctx->sis % 32;
+ si0 = ctx->si[sisw];
+ sil = ctx->sil;
+ /* Fast compression. */
+ while (1)
+ {
+ /* Load words? */
+ if (bmp01l < 8 && bmpl)
+ {
+ bmp1 = *bmp++;
+ bmp0 |= bmp1 << bmp01l;
+ bmp1 = bmp01l == 0 ? 0 : bmp1 >> (32 - bmp01l);
+ if (bmpl >= 32)
+ {
+ bmp01l += 32;
+ bmpl -= 32;
+ }
+ else
+ {
+ bmp01l += bmpl;
+ bmpl = 0;
+ }
+ }
+ /* Can continue? */
+ if (bmp01l < 8 || sil == 0)
+ break;
+ /* Look up table. */
+ u32 code = sack_enc_8[bmp0 & 0xff].code;
+ uint codel = sack_enc_8[bmp0 & 0xff].codel;
+ uint bmp_eat = sack_enc_8[bmp0 & 0xff].eat;
+ PBPROC_SACKI_ENC_DEBUG (code, codel, bmp_eat);
+ /* Output bits. */
+ codel = MIN (codel, sil);
+ si0 |= code << sisb;
+ if (sisb + codel >= 32)
+ {
+ /* si0 overflow, store it. */
+ ctx->si[sisw] = si0;
+ si0 = code >> (32 - sisb);
+ sisw++;
+ sisb = sisb + codel - 32;
+ }
+ else
+ {
+ sisb += codel;
+ }
+ sil -= codel;
+ /* Consume input. */
+ dbg_assert (bmp_eat <= bmp01l);
+ bmp0 >>= bmp_eat;
+ bmp0 |= bmp1 << (32 - bmp_eat);
+ bmp1 >>= bmp_eat;
+ bmp01l -= bmp_eat;
+ bmps += bmp_eat;
+ }
+ dbg_assert ((bmp01l < 8 && bmpl == 0) || sil == 0);
+ if (final)
+ {
+ while (bmp01l >= 4 && sil)
+ {
+ u32 code = sack_enc_4[bmp0 & 0xf].code;
+ uint codel = sack_enc_4[bmp0 & 0xf].codel;
+ uint bmp_eat = sack_enc_4[bmp0 & 0xf].eat_m1 + 1;
+ PBPROC_SACKI_ENC_DEBUG (code, codel, bmp_eat);
+ /* Output bits. */
+ codel = MIN (codel, sil);
+ si0 |= code << sisb;
+ if (sisb + codel >= 32)
+ {
+ /* si0 overflow, store it. */
+ ctx->si[sisw] = si0;
+ si0 = code >> (32 - sisb);
+ sisw++;
+ sisb = sisb + codel - 32;
+ }
+ else
+ {
+ sisb += codel;
+ }
+ sil -= codel;
+ /* Consume input. */
+ dbg_assert (bmp_eat <= bmp01l);
+ bmp0 >>= bmp_eat;
+ bmp01l -= bmp_eat;
+ bmps += bmp_eat;
+ }
+ if (bmp01l && sil)
+ {
+ const struct sack_enc_finish_t *t = sack_enc_f[bmp01l - 1];
+ u32 bmp0m = bmp0 & ((1 << bmp01l) - 1);
+ u32 code = t[bmp0m].code;
+ u32 codel = t[bmp0m].codel;
+ PBPROC_SACKI_ENC_DEBUG (code, codel, bmp01l);
+ /* Output bits. */
+ codel = MIN (codel, sil);
+ si0 |= code << sisb;
+ if (sisb + codel >= 32)
+ {
+ /* si0 overflow, store it. */
+ ctx->si[sisw] = si0;
+ si0 = code >> (32 - sisb);
+ sisw++;
+ sisb = sisb + codel - 32;
+ }
+ else
+ {
+ sisb += codel;
+ }
+ sil -= codel;
+ }
+ bmps += bmp01l;
+ bmp01l = 0;
+ }
+ dbg_assert (bmp01l <= 8 || sil == 0);
+ ctx->bmps = bmps;
+ ctx->sil = sil;
+ ctx->sis = sisw * 32 + sisb;
+ if (sisb)
+ {
+ si0 &= (1u << sisb) - 1;
+ ctx->si[sisw] = si0;
+ }
+}
+