// File: /workspace/github_c_makefile_star2_O1/jonof[P]jftekwar/jfbuild/src/rg_etc1.cpp
// Function: unsigned int* rg_etc1::indirect_radix_sort<unsigned int, unsigned short>(unsigned int, unsigned int*, unsigned int*, unsigned short const*, unsigned int, unsigned int, bool)
T* indirect_radix_sort(uint num_indices, T* pIndices0, T* pIndices1, const Q* pKeys, uint key_ofs, uint key_size, bool init_indices)
   {  
      RG_ETC1_ASSERT((key_ofs >= 0) && (key_ofs < sizeof(T)));
      RG_ETC1_ASSERT((key_size >= 1) && (key_size <= 4));

      if (init_indices)
      {
         T* p = pIndices0;
         T* q = pIndices0 + (num_indices >> 1) * 2;
         uint i;
         for (i = 0; p != q; p += 2, i += 2)
         {
            p[0] = static_cast<T>(i);
            p[1] = static_cast<T>(i + 1); 
         }

         if (num_indices & 1)
            *p = static_cast<T>(i);
      }

      uint hist[256 * 4];

      memset(hist, 0, sizeof(hist[0]) * 256 * key_size);

#define RG_ETC1_GET_KEY(p) (*(const uint*)((const uint8*)(pKeys + *(p)) + key_ofs))
#define RG_ETC1_GET_KEY_FROM_INDEX(i) (*(const uint*)((const uint8*)(pKeys + (i)) + key_ofs))

      if (key_size == 4)
      {
         T* p = pIndices0;
         T* q = pIndices0 + num_indices;
         for ( ; p != q; p++)
         {
            const uint key = RG_ETC1_GET_KEY(p);

            hist[        key        & 0xFF]++;
            hist[256 + ((key >>  8) & 0xFF)]++;
            hist[512 + ((key >> 16) & 0xFF)]++;
            hist[768 + ((key >> 24) & 0xFF)]++;
         }
      }
      else if (key_size == 3)
      {
         T* p = pIndices0;
         T* q = pIndices0 + num_indices;
         for ( ; p != q; p++)
         {
            const uint key = RG_ETC1_GET_KEY(p);

            hist[        key        & 0xFF]++;
            hist[256 + ((key >>  8) & 0xFF)]++;
            hist[512 + ((key >> 16) & 0xFF)]++;
         }
      }   
      else if (key_size == 2)
      {
         T* p = pIndices0;
         T* q = pIndices0 + (num_indices >> 1) * 2;

         for ( ; p != q; p += 2)
         {
            const uint key0 = RG_ETC1_GET_KEY(p);
            const uint key1 = RG_ETC1_GET_KEY(p+1);

            hist[        key0         & 0xFF]++;
            hist[256 + ((key0 >>  8) & 0xFF)]++;

            hist[        key1        & 0xFF]++;
            hist[256 + ((key1 >>  8) & 0xFF)]++;
         }

         if (num_indices & 1)
         {
            const uint key = RG_ETC1_GET_KEY(p);

            hist[        key        & 0xFF]++;
            hist[256 + ((key >>  8) & 0xFF)]++;
         }
      }      
      else
      {
         RG_ETC1_ASSERT(key_size == 1);
         if (key_size != 1)
            return NULL;

         T* p = pIndices0;
         T* q = pIndices0 + (num_indices >> 1) * 2;

         for ( ; p != q; p += 2)
         {
            const uint key0 = RG_ETC1_GET_KEY(p);
            const uint key1 = RG_ETC1_GET_KEY(p+1);

            hist[key0 & 0xFF]++;
            hist[key1 & 0xFF]++;
         }

         if (num_indices & 1)
         {
            const uint key = RG_ETC1_GET_KEY(p);

            hist[key & 0xFF]++;
         }
      }      

      T* pCur = pIndices0;
      T* pNew = pIndices1;

      for (uint pass = 0; pass < key_size; pass++)
      {
         const uint* pHist = &hist[pass << 8];

         uint offsets[256];

         uint cur_ofs = 0;
         for (uint i = 0; i < 256; i += 2)
         {
            offsets[i] = cur_ofs;
            cur_ofs += pHist[i];

            offsets[i+1] = cur_ofs;
            cur_ofs += pHist[i+1];
         }

         const uint pass_shift = pass << 3;

         T* p = pCur;
         T* q = pCur + (num_indices >> 1) * 2;

         for ( ; p != q; p += 2)
         {
            uint index0 = p[0];
            uint index1 = p[1];

            uint c0 = (RG_ETC1_GET_KEY_FROM_INDEX(index0) >> pass_shift) & 0xFF;
            uint c1 = (RG_ETC1_GET_KEY_FROM_INDEX(index1) >> pass_shift) & 0xFF;

            if (c0 == c1)
            {
               uint dst_offset0 = offsets[c0];

               offsets[c0] = dst_offset0 + 2;

               pNew[dst_offset0] = static_cast<T>(index0);
               pNew[dst_offset0 + 1] = static_cast<T>(index1);
            }
            else
            {
               uint dst_offset0 = offsets[c0]++;
               uint dst_offset1 = offsets[c1]++;

               pNew[dst_offset0] = static_cast<T>(index0);
               pNew[dst_offset1] = static_cast<T>(index1);
            }
         }

         if (num_indices & 1)
         {
            uint index = *p;
            uint c = (RG_ETC1_GET_KEY_FROM_INDEX(index) >> pass_shift) & 0xFF;

            uint dst_offset = offsets[c];
            offsets[c] = dst_offset + 1;

            pNew[dst_offset] = static_cast<T>(index);
         }

         T* t = pCur;
         pCur = pNew;
         pNew = t;
      }            

      return pCur;
   }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1428, %rsp           # imm = 0x1428
movl %edi, 0xc(%rsp)
cmpl $0x4, %r8d
jae 0x6ad98
movl %r9d, %r12d
leal -0x1(%r12), %eax
cmpl $0x4, %eax
jae 0x6adb7
movq %rcx, %rbx
movq %rdx, %r14
movq %rsi, %r15
movl %r8d, %r13d
cmpb $0x0, 0x1460(%rsp)
je 0x6aa65
movl 0xc(%rsp), %eax
andl $-0x2, %eax
je 0x6aa57
leaq (%r15,%rax,4), %rdx
xorl %eax, %eax
movq %r15, %rcx
movl %eax, (%rcx)
leal 0x1(%rax), %esi
movl %esi, 0x4(%rcx)
addq $0x8, %rcx
addl $0x2, %eax
cmpq %rdx, %rcx
jne 0x6aa41
jmp 0x6aa5c
xorl %eax, %eax
movq %r15, %rcx
testb $0x1, 0xc(%rsp)
je 0x6aa65
movl %eax, (%rcx)
movl %r12d, %edx
shll $0xa, %edx
leaq 0x420(%rsp), %rdi
xorl %esi, %esi
callq 0x62f0
cmpl $0x2, %r12d
je 0x6ab61
cmpl $0x3, %r12d
je 0x6ab04
cmpl $0x4, %r12d
jne 0x6ac08
cmpl $0x0, 0xc(%rsp)
je 0x6ac61
movl 0xc(%rsp), %eax
leaq (%rbx,%r13), %rcx
shlq $0x2, %rax
xorl %edx, %edx
movl $0x3fc, %esi            # imm = 0x3FC
movl (%r15,%rdx), %edi
movl (%rcx,%rdi,2), %edi
movzbl %dil, %r8d
incl 0x420(%rsp,%r8,4)
movl %edi, %r8d
shrl $0x6, %r8d
andl %esi, %r8d
incl 0x820(%rsp,%r8)
movl %edi, %r8d
shrl $0xe, %r8d
andl %esi, %r8d
incl 0xc20(%rsp,%r8)
shrl $0x16, %edi
andl $-0x4, %edi
incl 0x1020(%rsp,%rdi)
addq $0x4, %rdx
cmpq %rdx, %rax
jne 0x6aab2
jmp 0x6ac61
cmpl $0x0, 0xc(%rsp)
je 0x6ac61
movl 0xc(%rsp), %eax
leaq (%rbx,%r13), %rcx
shlq $0x2, %rax
xorl %edx, %edx
movl $0x3fc, %esi            # imm = 0x3FC
movl (%r15,%rdx), %edi
movl (%rcx,%rdi,2), %edi
movzbl %dil, %r8d
incl 0x420(%rsp,%r8,4)
movl %edi, %r8d
shrl $0x6, %r8d
andl %esi, %r8d
incl 0x820(%rsp,%r8)
shrl $0xe, %edi
andl %esi, %edi
incl 0xc20(%rsp,%rdi)
addq $0x4, %rdx
cmpq %rdx, %rax
jne 0x6ab22
jmp 0x6ac61
movl 0xc(%rsp), %eax
movl %eax, %ecx
movq %r15, %rax
andl $-0x2, %ecx
je 0x6abd6
leaq (%r15,%rcx,4), %rcx
leaq (%rbx,%r13), %rdx
movl $0xff, %esi
movl $0x3fc, %edi            # imm = 0x3FC
movq %r15, %rax
movl (%rax), %r8d
movl 0x4(%rax), %r9d
movl (%rdx,%r8,2), %r8d
movl (%rdx,%r9,2), %r9d
movl %r8d, %r10d
andl %esi, %r10d
incl 0x420(%rsp,%r10,4)
shrl $0x6, %r8d
andl %edi, %r8d
incl 0x820(%rsp,%r8)
movl %r9d, %r8d
andl %esi, %r8d
incl 0x420(%rsp,%r8,4)
shrl $0x6, %r9d
andl %edi, %r9d
incl 0x820(%rsp,%r9)
addq $0x8, %rax
cmpq %rcx, %rax
jne 0x6ab84
testb $0x1, 0xc(%rsp)
je 0x6ac61
movl (%rax), %eax
leaq (%rbx,%rax,2), %rax
movl (%r13,%rax), %eax
movl $0xff, %ecx
movl %eax, %edx
andl %ecx, %edx
incl 0x420(%rsp,%rdx,4)
shrl $0x8, %eax
andl %ecx, %eax
orl $0x100, %eax            # imm = 0x100
jmp 0x6ac58
movl 0xc(%rsp), %eax
movl %eax, %ecx
movq %r15, %rax
andl $-0x2, %ecx
je 0x6ac45
leaq (%r15,%rcx,4), %rcx
leaq (%rbx,%r13), %rdx
movq %r15, %rax
movl (%rax), %esi
movl 0x4(%rax), %edi
movzbl (%rdx,%rsi,2), %esi
movzbl (%rdx,%rdi,2), %edi
incl 0x420(%rsp,%rsi,4)
incl 0x420(%rsp,%rdi,4)
addq $0x8, %rax
cmpq %rcx, %rax
jne 0x6ac21
testb $0x1, 0xc(%rsp)
je 0x6ac61
movl (%rax), %eax
leaq (%rbx,%rax,2), %rax
movzbl (%r13,%rax), %eax
movl %eax, %eax
incl 0x420(%rsp,%rax,4)
testl %r12d, %r12d
je 0x6ad83
addq %r13, %rbx
movl 0xc(%rsp), %eax
andl $-0x2, %eax
movq %rax, 0x10(%rsp)
movl %r12d, %eax
movq %rax, 0x18(%rsp)
leaq 0x424(%rsp), %rdi
xorl %r8d, %r8d
movl $0xff, %r9d
movq %r14, %rax
movq $-0x2, %rcx
xorl %esi, %esi
movl %esi, 0x28(%rsp,%rcx,4)
addl 0x4(%rdi,%rcx,4), %esi
movl %esi, 0x2c(%rsp,%rcx,4)
addl 0x8(%rdi,%rcx,4), %esi
addq $0x2, %rcx
cmpq $0xfe, %rcx
jb 0x6ac9e
leaq (,%r8,8), %rcx
movq %r15, %rdx
movq %r15, %r10
cmpq $0x0, 0x10(%rsp)
je 0x6ad3f
movq %rdx, %r10
movq 0x10(%rsp), %rsi
leaq (%rdx,%rsi,4), %r11
movl (%r10), %r12d
movl 0x4(%r10), %r15d
movl (%rbx,%r12,2), %ebp
shrl %cl, %ebp
movl (%rbx,%r15,2), %esi
shrl %cl, %esi
andl %r9d, %ebp
andl %r9d, %esi
movl 0x20(%rsp,%rbp,4), %r13d
cmpl %esi, %ebp
jne 0x6ad10
leal 0x2(%r13), %esi
movl %esi, 0x20(%rsp,%rbp,4)
movl %r12d, (%rax,%r13,4)
incl %r13d
jmp 0x6ad2f
leal 0x1(%r13), %r14d
movl %r14d, 0x20(%rsp,%rbp,4)
movl %esi, %esi
movl 0x20(%rsp,%rsi,4), %r14d
leal 0x1(%r14), %ebp
movl %ebp, 0x20(%rsp,%rsi,4)
movl %r12d, (%rax,%r13,4)
movl %r14d, %r13d
movl %r13d, %esi
movl %r15d, (%rax,%rsi,4)
addq $0x8, %r10
cmpq %r11, %r10
jne 0x6acdd
testb $0x1, 0xc(%rsp)
je 0x6ad66
movl (%r10), %esi
movl (%rbx,%rsi,2), %r10d
shrl %cl, %r10d
movzbl %r10b, %ecx
movl 0x20(%rsp,%rcx,4), %r10d
leal 0x1(%r10), %r11d
movl %r11d, 0x20(%rsp,%rcx,4)
movl %esi, (%rax,%r10,4)
incq %r8
addq $0x400, %rdi            # imm = 0x400
movq %rax, %r15
cmpq 0x18(%rsp), %r8
movq %rdx, %r14
jne 0x6ac92
jmp 0x6ad86
movq %r15, %rax
addq $0x1428, %rsp           # imm = 0x1428
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x10a52(%rip), %rdi     # 0x7b7f1
leaq 0x10409(%rip), %rsi     # 0x7b1af
leaq 0x10a6c(%rip), %rcx     # 0x7b819
movl $0x2f6, %edx            # imm = 0x2F6
callq 0x61b0
leaq 0x10acf(%rip), %rdi     # 0x7b88d
leaq 0x103ea(%rip), %rsi     # 0x7b1af
leaq 0x10a4d(%rip), %rcx     # 0x7b819
movl $0x2f7, %edx            # imm = 0x2F7
callq 0x61b0
nop