cleanup: remove cpu ctrl files, move tests
[gpsp.git] / gp2x / test / load_imm_test.c
1 #include <stdio.h>\r
2 \r
3 typedef unsigned int u32;\r
4 \r
5 u32 arm_imm_find_nonzero(u32 imm, u32 start_bit)\r
6 {\r
7   u32 i;\r
8 \r
9   for(i = start_bit; i < 32; i += 2)\r
10   {\r
11     if((imm >> i) & 0x03)\r
12       break;\r
13   }\r
14 \r
15   return i;\r
16 }\r
17 \r
18 u32 arm_disect_imm_32bit(u32 imm, u32 *stores, u32 *rotations)\r
19 {\r
20   u32 store_count = 0;\r
21   u32 left_shift = 0;\r
22 \r
23   // Otherwise it'll return 0 things to store because it'll never\r
24   // find anything.\r
25   if(imm == 0)\r
26   {\r
27     rotations[0] = 0;\r
28     stores[0] = 0;\r
29     return 1;\r
30   }\r
31 \r
32   // Find chunks of non-zero data at 2 bit alignments.\r
33   while(1)\r
34   {\r
35     left_shift = arm_imm_find_nonzero(imm, left_shift);\r
36 \r
37     if(left_shift == 32)\r
38     {\r
39       // We've hit the end of the useful data.\r
40       return store_count;\r
41     }\r
42 \r
43     // Hit the end, it might wrap back around to the beginning.\r
44     if(left_shift >= 24)\r
45     {\r
46       // Make a mask for the residual bits. IE, if we have\r
47       // 5 bits of data at the end we can wrap around to 3\r
48       // bits of data in the beginning. Thus the first\r
49       // thing, after being shifted left, has to be less\r
50       // than 111b, 0x7, or (1 << 3) - 1.\r
51       u32 top_bits = 32 - left_shift;\r
52       u32 residual_bits = 8 - top_bits;\r
53       u32 residual_mask = (1 << residual_bits) - 1;\r
54 \r
55       if((store_count > 1) && (left_shift > 24) &&\r
56        ((stores[0] << (32 - rotations[0])) < residual_mask))\r
57       {\r
58         // Then we can throw out the last bit and tack it on\r
59         // to the first bit.\r
60         u32 initial_bits = rotations[0];\r
61         stores[0] = (stores[0] << (top_bits + (32 - rotations[0]))) |\r
62          ((imm >> left_shift) & 0xFF);\r
63         rotations[0] = top_bits;\r
64 \r
65         return store_count;\r
66       }\r
67       else\r
68       {\r
69         // There's nothing to wrap over to in the beginning\r
70         stores[store_count] = (imm >> left_shift) & 0xFF;\r
71         rotations[store_count] = (32 - left_shift) & 0x1F;\r
72         return store_count + 1;\r
73       }\r
74       break;\r
75     }\r
76 \r
77     stores[store_count] = (imm >> left_shift) & 0xFF;\r
78     rotations[store_count] = (32 - left_shift) & 0x1F;\r
79 \r
80     store_count++;\r
81     left_shift += 8;\r
82   }\r
83 }\r
84 \r
85 #define ror(value, shift)                                                     \\r
86   ((value) >> shift) | ((value) << (32 - shift))                              \\r
87 \r
88 u32 arm_assemble_imm_32bit(u32 *stores, u32 *rotations, u32 store_count)\r
89 {\r
90   u32 n = ror(stores[0], rotations[0]);\r
91   u32 i;\r
92   printf("%x : %x\n", stores[0], rotations[0]);\r
93 \r
94   for(i = 1; i < store_count; i++)\r
95   {\r
96     printf("%x : %x\n", stores[i], rotations[i]);\r
97     n |= ror(stores[i], rotations[i]);\r
98   }\r
99 \r
100   return n;\r
101 }\r
102 \r
103 \r
104 int main(int argc, char *argv[])\r
105 {\r
106   u32 n = 0;\r
107   u32 stores[4];\r
108   u32 rotations[4];\r
109   u32 store_count;\r
110   u32 n2;\r
111 \r
112   if(argc != 1)\r
113   {\r
114     n = strtoul(argv[1], NULL, 16);\r
115     store_count = arm_disect_imm_32bit(n, stores, rotations);\r
116     n2 = arm_assemble_imm_32bit(stores, rotations, store_count);\r
117     printf("%08x -> %08x (%d stores)\n", n, n2, store_count);\r
118     return 0;\r
119   }\r
120 \r
121   do\r
122   {\r
123     store_count = arm_disect_imm_32bit(n, stores, rotations);\r
124     n2 = arm_assemble_imm_32bit(stores, rotations, store_count);\r
125     if(n != n2)\r
126     {\r
127       printf("Failure: %08x -/-> %08x\n", n, n2);\r
128       return -1;\r
129     }\r
130     n++;\r
131   } while(n != 0);\r
132 \r
133   printf("Done!\n");\r
134   return 0;\r
135 }\r