// File: /workspace/github_c_makefile_star2_O2/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 $0x1418, %rsp           # imm = 0x1418
movq %rdi, (%rsp)
cmpl $0x4, %r8d
jae 0x61592
movl %r9d, %r13d
leal -0x1(%r13), %eax
cmpl $0x4, %eax
jae 0x615b1
movq %rcx, %rbx
movq %rdx, %r12
movq %rsi, %r14
movl %r8d, %ebp
cmpb $0x0, 0x1450(%rsp)
je 0x6128b
movq (%rsp), %rdx
movl %edx, %eax
andl $-0x2, %eax
andl $-0x2, %edx
shlq $0x2, %rdx
xorl %ecx, %ecx
movq %r14, %rsi
testq %rdx, %rdx
je 0x61281
movl %ecx, (%rsi)
leal 0x1(%rcx), %edi
movl %edi, 0x4(%rsi)
addq $0x8, %rsi
addl $0x2, %ecx
addq $-0x8, %rdx
jmp 0x61267
testb $0x1, (%rsp)
je 0x6128b
movl %ecx, (%r14,%rax,4)
movl %r13d, %edx
shll $0xa, %edx
leaq 0x410(%rsp), %rdi
xorl %esi, %esi
callq 0x62f0
cmpl $0x2, %r13d
je 0x61371
cmpl $0x3, %r13d
je 0x6131f
cmpl $0x4, %r13d
jne 0x6141c
movl (%rsp), %eax
leaq (%rbx,%rbp), %rcx
shlq $0x2, %rax
xorl %edx, %edx
movl $0x3fc, %esi            # imm = 0x3FC
cmpq %rdx, %rax
je 0x6147c
movl (%r14,%rdx), %edi
movl (%rcx,%rdi,2), %edi
movzbl %dil, %r8d
incl 0x410(%rsp,%r8,4)
movl %edi, %r8d
shrl $0x6, %r8d
andl %esi, %r8d
incl 0x810(%rsp,%r8)
movl %edi, %r8d
shrl $0xe, %r8d
andl %esi, %r8d
incl 0xc10(%rsp,%r8)
shrl $0x16, %edi
andl $-0x4, %edi
incl 0x1010(%rsp,%rdi)
addq $0x4, %rdx
jmp 0x612cc
movl (%rsp), %eax
leaq (%rbx,%rbp), %rcx
shlq $0x2, %rax
xorl %edx, %edx
movl $0x3fc, %esi            # imm = 0x3FC
cmpq %rdx, %rax
je 0x6147c
movl (%r14,%rdx), %edi
movl (%rcx,%rdi,2), %edi
movzbl %dil, %r8d
incl 0x410(%rsp,%r8,4)
movl %edi, %r8d
shrl $0x6, %r8d
andl %esi, %r8d
incl 0x810(%rsp,%r8)
shrl $0xe, %edi
andl %esi, %edi
incl 0xc10(%rsp,%rdi)
addq $0x4, %rdx
jmp 0x61331
movq (%rsp), %rdx
movl %edx, %eax
andl $-0x2, %eax
leaq (%rbx,%rbp), %rcx
andl $-0x2, %edx
shlq $0x2, %rdx
movl $0xff, %esi
movl $0x3fc, %edi            # imm = 0x3FC
movq %r14, %r8
testq %rdx, %rdx
je 0x613ea
movl (%r8), %r9d
movl 0x4(%r8), %r10d
movl (%rcx,%r9,2), %r9d
movl (%rcx,%r10,2), %r10d
movl %r9d, %r11d
andl %esi, %r11d
incl 0x410(%rsp,%r11,4)
shrl $0x6, %r9d
andl %edi, %r9d
incl 0x810(%rsp,%r9)
movl %r10d, %r9d
andl %esi, %r9d
incl 0x410(%rsp,%r9,4)
shrl $0x6, %r10d
andl %edi, %r10d
incl 0x810(%rsp,%r10)
addq $0x8, %r8
addq $-0x8, %rdx
jmp 0x61392
testb $0x1, (%rsp)
je 0x6147c
movl (%r14,%rax,4), %eax
leaq (%rbx,%rax,2), %rax
movl (%rbp,%rax), %eax
movl $0xff, %ecx
movl %eax, %edx
andl %ecx, %edx
incl 0x410(%rsp,%rdx,4)
shrl $0x8, %eax
andl %ecx, %eax
orl $0x100, %eax            # imm = 0x100
jmp 0x61473
movq (%rsp), %rdx
movl %edx, %eax
andl $-0x2, %eax
leaq (%rbx,%rbp), %rcx
andl $-0x2, %edx
shlq $0x2, %rdx
movq %r14, %rsi
testq %rdx, %rdx
je 0x61460
movl (%rsi), %edi
movl 0x4(%rsi), %r8d
movzbl (%rcx,%rdi,2), %edi
movzbl (%rcx,%r8,2), %r8d
incl 0x410(%rsp,%rdi,4)
incl 0x410(%rsp,%r8,4)
addq $0x8, %rsi
addq $-0x8, %rdx
jmp 0x61433
testb $0x1, (%rsp)
je 0x6147c
movl (%r14,%rax,4), %eax
leaq (%rbx,%rax,2), %rax
movzbl (%rbp,%rax), %eax
movl %eax, %eax
incl 0x410(%rsp,%rax,4)
addq %rbp, %rbx
movl %r13d, %eax
movq %rax, 0x8(%rsp)
leaq 0x414(%rsp), %rdx
movq (%rsp), %rsi
andl $-0x2, %esi
shlq $0x2, %rsi
xorl %edi, %edi
movl $0xff, %r8d
cmpq 0x8(%rsp), %rdi
je 0x6157d
movq %r12, %r9
xorl %ecx, %ecx
xorl %r10d, %r10d
cmpq $0x100, %rcx            # imm = 0x100
jae 0x614d7
movl %r10d, 0x10(%rsp,%rcx,4)
addl -0x4(%rdx,%rcx,4), %r10d
movl %r10d, 0x14(%rsp,%rcx,4)
addl (%rdx,%rcx,4), %r10d
addq $0x2, %rcx
jmp 0x614b5
leaq (,%rdi,8), %rcx
xorl %r10d, %r10d
cmpq %r10, %rsi
je 0x6154b
movl (%r14,%r10), %r12d
movl 0x4(%r14,%r10), %r11d
movl (%rbx,%r12,2), %ebp
shrl %cl, %ebp
movl (%rbx,%r11,2), %r15d
shrl %cl, %r15d
andl %r8d, %ebp
andl %r8d, %r15d
movl 0x10(%rsp,%rbp,4), %r13d
cmpl %r15d, %ebp
jne 0x6151f
leal 0x2(%r13), %r15d
movl %r15d, 0x10(%rsp,%rbp,4)
movl %r12d, (%r9,%r13,4)
incl %r13d
jmp 0x6153e
leal 0x1(%r13), %eax
movl %eax, 0x10(%rsp,%rbp,4)
movl %r15d, %eax
movl 0x10(%rsp,%rax,4), %r15d
leal 0x1(%r15), %ebp
movl %ebp, 0x10(%rsp,%rax,4)
movl %r12d, (%r9,%r13,4)
movl %r15d, %r13d
movl %r13d, %eax
movl %r11d, (%r9,%rax,4)
addq $0x8, %r10
jmp 0x614e2
testb $0x1, (%rsp)
je 0x61568
movl (%r14,%r10), %eax
movl (%rbx,%rax,2), %r10d
shrl %cl, %r10d
movzbl %r10b, %ecx
movl 0x10(%rsp,%rcx,4), %ecx
movl %eax, (%r9,%rcx,4)
incq %rdi
addq $0x400, %rdx            # imm = 0x400
movq %r14, %r12
movq %r9, %r14
jmp 0x614a2
movq %r14, %rax
addq $0x1418, %rsp           # imm = 0x1418
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x10564(%rip), %rdi     # 0x71afd
leaq 0xfe8f(%rip), %rsi      # 0x7142f
leaq 0x1057e(%rip), %rcx     # 0x71b25
movl $0x2f6, %edx            # imm = 0x2F6
callq 0x61b0
leaq 0x105e1(%rip), %rdi     # 0x71b99
leaq 0xfe70(%rip), %rsi      # 0x7142f
leaq 0x1055f(%rip), %rcx     # 0x71b25
movl $0x2f7, %edx            # imm = 0x2F7
callq 0x61b0