136 lines
3.3 KiB
C
136 lines
3.3 KiB
C
|
#include <stdio.h>
|
||
|
|
||
|
typedef unsigned int u32;
|
||
|
|
||
|
u32 arm_imm_find_nonzero(u32 imm, u32 start_bit)
|
||
|
{
|
||
|
u32 i;
|
||
|
|
||
|
for(i = start_bit; i < 32; i += 2)
|
||
|
{
|
||
|
if((imm >> i) & 0x03)
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return i;
|
||
|
}
|
||
|
|
||
|
u32 arm_disect_imm_32bit(u32 imm, u32 *stores, u32 *rotations)
|
||
|
{
|
||
|
u32 store_count = 0;
|
||
|
u32 left_shift = 0;
|
||
|
|
||
|
// Otherwise it'll return 0 things to store because it'll never
|
||
|
// find anything.
|
||
|
if(imm == 0)
|
||
|
{
|
||
|
rotations[0] = 0;
|
||
|
stores[0] = 0;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
// Find chunks of non-zero data at 2 bit alignments.
|
||
|
while(1)
|
||
|
{
|
||
|
left_shift = arm_imm_find_nonzero(imm, left_shift);
|
||
|
|
||
|
if(left_shift == 32)
|
||
|
{
|
||
|
// We've hit the end of the useful data.
|
||
|
return store_count;
|
||
|
}
|
||
|
|
||
|
// Hit the end, it might wrap back around to the beginning.
|
||
|
if(left_shift >= 24)
|
||
|
{
|
||
|
// Make a mask for the residual bits. IE, if we have
|
||
|
// 5 bits of data at the end we can wrap around to 3
|
||
|
// bits of data in the beginning. Thus the first
|
||
|
// thing, after being shifted left, has to be less
|
||
|
// than 111b, 0x7, or (1 << 3) - 1.
|
||
|
u32 top_bits = 32 - left_shift;
|
||
|
u32 residual_bits = 8 - top_bits;
|
||
|
u32 residual_mask = (1 << residual_bits) - 1;
|
||
|
|
||
|
if((store_count > 1) && (left_shift > 24) &&
|
||
|
((stores[0] << (32 - rotations[0])) < residual_mask))
|
||
|
{
|
||
|
// Then we can throw out the last bit and tack it on
|
||
|
// to the first bit.
|
||
|
u32 initial_bits = rotations[0];
|
||
|
stores[0] = (stores[0] << (top_bits + (32 - rotations[0]))) |
|
||
|
((imm >> left_shift) & 0xFF);
|
||
|
rotations[0] = top_bits;
|
||
|
|
||
|
return store_count;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// There's nothing to wrap over to in the beginning
|
||
|
stores[store_count] = (imm >> left_shift) & 0xFF;
|
||
|
rotations[store_count] = (32 - left_shift) & 0x1F;
|
||
|
return store_count + 1;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
stores[store_count] = (imm >> left_shift) & 0xFF;
|
||
|
rotations[store_count] = (32 - left_shift) & 0x1F;
|
||
|
|
||
|
store_count++;
|
||
|
left_shift += 8;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#define ror(value, shift) \
|
||
|
((value) >> shift) | ((value) << (32 - shift)) \
|
||
|
|
||
|
u32 arm_assemble_imm_32bit(u32 *stores, u32 *rotations, u32 store_count)
|
||
|
{
|
||
|
u32 n = ror(stores[0], rotations[0]);
|
||
|
u32 i;
|
||
|
printf("%x : %x\n", stores[0], rotations[0]);
|
||
|
|
||
|
for(i = 1; i < store_count; i++)
|
||
|
{
|
||
|
printf("%x : %x\n", stores[i], rotations[i]);
|
||
|
n |= ror(stores[i], rotations[i]);
|
||
|
}
|
||
|
|
||
|
return n;
|
||
|
}
|
||
|
|
||
|
|
||
|
int main(int argc, char *argv[])
|
||
|
{
|
||
|
u32 n = 0;
|
||
|
u32 stores[4];
|
||
|
u32 rotations[4];
|
||
|
u32 store_count;
|
||
|
u32 n2;
|
||
|
|
||
|
if(argc != 1)
|
||
|
{
|
||
|
n = strtoul(argv[1], NULL, 16);
|
||
|
store_count = arm_disect_imm_32bit(n, stores, rotations);
|
||
|
n2 = arm_assemble_imm_32bit(stores, rotations, store_count);
|
||
|
printf("%08x -> %08x (%d stores)\n", n, n2, store_count);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
do
|
||
|
{
|
||
|
store_count = arm_disect_imm_32bit(n, stores, rotations);
|
||
|
n2 = arm_assemble_imm_32bit(stores, rotations, store_count);
|
||
|
if(n != n2)
|
||
|
{
|
||
|
printf("Failure: %08x -/-> %08x\n", n, n2);
|
||
|
return -1;
|
||
|
}
|
||
|
n++;
|
||
|
} while(n != 0);
|
||
|
|
||
|
printf("Done!\n");
|
||
|
return 0;
|
||
|
}
|