#include "decode.h"
#include "decode_internal.h"
#include "utilities.h"
#define R_QWORDS_HALF_LOG2 UPTOPOW2(R_QWORDS / 2)
_INLINE_ void
rotr_big(OUT syndrome_t *out, IN const syndrome_t *in, IN size_t qw_num)
{
bike_static_assert(sizeof(*out) > 8 * (R_QWORDS + (2 * R_QWORDS_HALF_LOG2)),
rotr_big_err);
*out = *in;
for(uint32_t idx = R_QWORDS_HALF_LOG2; idx >= 1; idx >>= 1) {
const uint64_t mask = ((uint32_t)secure_l32_mask(qw_num, idx) + 1U) - 1ULL;
qw_num = qw_num - (idx & u64_barrier(mask));
for(size_t i = 0; i < (R_QWORDS + idx); i++) {
out->qw[i] = (out->qw[i] & u64_barrier(~mask)) |
(out->qw[i + idx] & u64_barrier(mask));
}
}
}
_INLINE_ void
rotr_small(OUT syndrome_t *out, IN const syndrome_t *in, IN const size_t bits)
{
bike_static_assert(sizeof(*out) > (8 * R_QWORDS), rotr_small_qw_err);
const uint64_t mask = (0 - (!!bits));
const uint64_t high_shift = (64 - bits) & u64_barrier(mask);
for(size_t i = 0; i < R_QWORDS; i++) {
const uint64_t low_part = in->qw[i] >> bits;
const uint64_t high_part = (in->qw[i + 1] << high_shift) & u64_barrier(mask);
out->qw[i] = low_part | high_part;
}
}
void rotate_right_port(OUT syndrome_t *out,
IN const syndrome_t *in,
IN const uint32_t bitscount)
{
rotr_big(out, in, (bitscount / 64));
rotr_small(out, out, (bitscount % 64));
}
void dup_port(IN OUT syndrome_t *s)
{
s->qw[R_QWORDS - 1] =
(s->qw[0] << LAST_R_QWORD_LEAD) | (s->qw[R_QWORDS - 1] & LAST_R_QWORD_MASK);
for(size_t i = 0; i < (2 * R_QWORDS) - 1; i++) {
s->qw[R_QWORDS + i] =
(s->qw[i] >> LAST_R_QWORD_TRAIL) | (s->qw[i + 1] << LAST_R_QWORD_LEAD);
}
}
void bit_sliced_adder_port(OUT upc_t *upc,
IN OUT syndrome_t *rotated_syndrome,
IN const size_t num_of_slices)
{
for(size_t j = 0; j < num_of_slices; j++) {
for(size_t i = 0; i < R_QWORDS; i++) {
const uint64_t carry = (upc->slice[j].u.qw[i] & rotated_syndrome->qw[i]);
upc->slice[j].u.qw[i] ^= rotated_syndrome->qw[i];
rotated_syndrome->qw[i] = carry;
}
}
}
void bit_slice_full_subtract_port(OUT upc_t *upc, IN uint8_t val)
{
uint64_t br[R_QWORDS] = {0};
for(size_t j = 0; j < SLICES; j++) {
const uint64_t lsb_mask = 0 - (val & 0x1);
val >>= 1;
for(size_t i = 0; i < R_QWORDS; i++) {
const uint64_t a = upc->slice[j].u.qw[i];
const uint64_t b = lsb_mask;
const uint64_t tmp = ((~a) & b & (~br[i])) | ((((~a) | b) & br[i]));
upc->slice[j].u.qw[i] = a ^ b ^ br[i];
br[i] = tmp;
}
}
}