// File: kernel.cpp
#include "loop_106.h"
#include <stdint.h>
#include <arm_sve.h>
#define restrict __restrict
#define SC_SVE_ATTR
#define FOR_COND(P, S, I, N) svptest_first(svptrue_b##S(), P = svwhilelt_b##S(I, N))
#define FOR_LOOP(T, I, M, N, P, S, W) for (T I = M; FOR_COND(P, S, I, N); I += svcnt##W())
#define FOR_LOOP_8(T, I, M, N, P)  FOR_LOOP(T, I, M, N, P, 8, b)
#define FOR_LOOP_16(T, I, M, N, P) FOR_LOOP(T, I, M, N, P, 16, h)
#define FOR_LOOP_32(T, I, M, N, P) FOR_LOOP(T, I, M, N, P, 32, w)
#define FOR_LOOP_64(T, I, M, N, P) FOR_LOOP(T, I, M, N, P, 64, d)
static inline uint32_t get_sve_vl(void) {
  uint64_t vl = 0; asm volatile("incb %[vl], all, mul #8" : [vl] "+r"(vl) : :);
  return (uint32_t)vl;
}
static inline uint32_t get_vl(void) { return get_sve_vl(); }

extern "C" void inner_loop_106(struct loop_106_data * input) {
  uint32_t * a = input->a;
  uint32_t * b = input->b;
  uint32_t * perm = input->perm;
  int64_t n = input->n;

  svuint32_t pmt0 = svdup_u32_z(svptrue_b8(), ~perm[0]);
  svuint32_t pmt1 = svdup_u32_z(svptrue_b8(), ~perm[1]);
  svuint32_t pmt2 = svdup_u32_z(svptrue_b8(), ~perm[2]);
  svuint32_t pmt3 = svdup_u32_z(svptrue_b8(), ~perm[3]);
  svuint32_t pmt4 = svdup_u32_z(svptrue_b8(), ~perm[4]);

  svbool_t p;
  FOR_LOOP_32(int64_t, i, 0, n, p) {
    svuint32_t data = svld1(p, a + i);
    data = svbgrp(data, pmt0);
    data = svbgrp(data, pmt1);
    data = svbgrp(data, pmt2);
    data = svbgrp(data, pmt3);
    data = svbgrp(data, pmt4);
    svst1(p, b + i, data);
  }
}