14e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi/* Reed-Solomon encoder
24e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi * Copyright 2004, Phil Karn, KA9Q
34e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi * May be used under the terms of the GNU Lesser General Public License (LGPL)
44e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi */
54e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#include <string.h>
64e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#include "fixed.h"
74e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#ifdef __VEC__
84e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#include <sys/sysctl.h>
94e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#endif
104e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
114e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
124e213d510f437769f8a28578dd4f786fb7d16c4Bill Yistatic enum {UNKNOWN=0,MMX,SSE,SSE2,ALTIVEC,PORT} cpu_mode;
134e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
144e213d510f437769f8a28578dd4f786fb7d16c4Bill Yistatic void encode_rs_8_c(data_t *data, data_t *parity,int pad);
154e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#if __vec__
164e213d510f437769f8a28578dd4f786fb7d16c4Bill Yistatic void encode_rs_8_av(data_t *data, data_t *parity,int pad);
174e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#endif
184e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#if __i386__
194e213d510f437769f8a28578dd4f786fb7d16c4Bill Yiint cpu_features(void);
204e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#endif
214e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
224e213d510f437769f8a28578dd4f786fb7d16c4Bill Yivoid encode_rs_8(data_t *data, data_t *parity,int pad){
234e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  if(cpu_mode == UNKNOWN){
244e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#ifdef __i386__
254e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    int f;
264e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    /* Figure out what kind of CPU we have */
274e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    f = cpu_features();
284e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    if(f & (1<<26)){ /* SSE2 is present */
294e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      cpu_mode = SSE2;
304e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    } else if(f & (1<<25)){ /* SSE is present */
314e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      cpu_mode = SSE;
324e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    } else if(f & (1<<23)){ /* MMX is present */
334e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      cpu_mode = MMX;
344e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    } else { /* No SIMD at all */
354e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      cpu_mode = PORT;
364e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    }
374e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#elif __VEC__
384e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    /* Ask the OS if we have Altivec support */
394e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    int selectors[2] = { CTL_HW, HW_VECTORUNIT };
404e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    int hasVectorUnit = 0;
414e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    size_t length = sizeof(hasVectorUnit);
424e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    int error = sysctl(selectors, 2, &hasVectorUnit, &length, NULL, 0);
434e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    if(0 == error && hasVectorUnit)
444e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      cpu_mode = ALTIVEC;
454e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    else
464e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi      cpu_mode = PORT;
474e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#else
484e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    cpu_mode = PORT;
494e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#endif
504e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  }
514e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  switch(cpu_mode){
524e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#if __vec__
534e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  case ALTIVEC:
544e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    encode_rs_8_av(data,parity,pad);
554e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    return;
564e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#endif
574e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#if __i386__
584e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  case MMX:
594e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  case SSE:
604e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  case SSE2:
614e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#endif
624e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  default:
634e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    encode_rs_8_c(data,parity,pad);
644e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    return;
654e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  }
664e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi}
674e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
684e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#if __vec__ /* PowerPC G4/G5 Altivec instructions are available */
694e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
704e213d510f437769f8a28578dd4f786fb7d16c4Bill Yistatic vector unsigned char reverse = (vector unsigned char)(0,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1);
714e213d510f437769f8a28578dd4f786fb7d16c4Bill Yistatic vector unsigned char shift_right = (vector unsigned char)(15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30);
724e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
734e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi/* Lookup table for feedback multiplications
744e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi * These are the low half of the coefficients. Since the generator polynomial is
754e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi * palindromic, we form the other half by reversing this one
764e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi */
774e213d510f437769f8a28578dd4f786fb7d16c4Bill Yiextern static union { vector unsigned char v; unsigned char c[16]; } table[256];
784e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
794e213d510f437769f8a28578dd4f786fb7d16c4Bill Yistatic void encode_rs_8_av(data_t *data, data_t *parity,int pad){
804e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  union { vector unsigned char v[2]; unsigned char c[32]; } shift_register;
814e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  int i;
824e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
834e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  shift_register.v[0] = (vector unsigned char)(0);
844e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  shift_register.v[1] = (vector unsigned char)(0);
854e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
864e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  for(i=0;i<NN-NROOTS-pad;i++){
874e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    vector unsigned char feedback0,feedback1;
884e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    unsigned char f;
894e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
904e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    f = data[i] ^ shift_register.c[31];
914e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    feedback1 = table[f].v;
924e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    feedback0 = vec_perm(feedback1,feedback1,reverse);
934e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
944e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    /* Shift right one byte */
954e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    shift_register.v[1] = vec_perm(shift_register.v[0],shift_register.v[1],shift_right) ^ feedback1;
964e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    shift_register.v[0] = vec_sro(shift_register.v[0],(vector unsigned char)(8)) ^ feedback0;
974e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    shift_register.c[0] = f;
984e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  }
994e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi  for(i=0;i<NROOTS;i++)
1004e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi    parity[NROOTS-i-1] = shift_register.c[i];
1014e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi}
1024e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#endif
1034e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
1044e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi/* Portable C version */
1054e213d510f437769f8a28578dd4f786fb7d16c4Bill Yistatic void encode_rs_8_c(data_t *data, data_t *parity,int pad){
1064e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
1074e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi#include "encode_rs.h"
1084e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi
1094e213d510f437769f8a28578dd4f786fb7d16c4Bill Yi}
110