add op_lidstate
[pandora-misc.git] / tests / test_uncached.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdint.h>
4 #include <sys/types.h>
5 #include <unistd.h>
6
7 #include <inc_libc64_mini.h>
8
9 void aligned_fetch_fbmem_to_scratch_neon(int numbytes, void *scratch, const void *fbmem);
10 void aligned_fetch_fbmem_to_scratch_vfp (int numbytes, void *scratch, const void *fbmem);
11
12 #define TEST_SIZE (1024 * 1024)
13 #define TRIES 16
14
15 static char dummy [TEST_SIZE] __attribute__((aligned(64)));
16 static char dummy2[TEST_SIZE] __attribute__((aligned(64)));
17
18 static inline void pcnt_init(void)
19 {
20         int v;
21         asm volatile("mrc p15, 0, %0, c9, c12, 0" : "=r"(v));
22         v |= 5; // master enable, ccnt reset
23         v &= ~8; // ccnt divider 0
24         asm volatile("mcr p15, 0, %0, c9, c12, 0" :: "r"(v));
25         // enable cycle counter
26         asm volatile("mcr p15, 0, %0, c9, c12, 1" :: "r"(1<<31));
27 }
28
29 static inline unsigned int pcnt_get(void)
30 {
31         unsigned int val;
32         __asm__ volatile("mrc p15, 0, %0, c9, c13, 0"
33                          : "=r"(val));
34         return val;
35 }
36
37 #define make_rd_test(name, type) \
38 static int name(void *mem_, size_t size) \
39 { \
40         const type *mem = mem_; \
41         int sum = 0; \
42  \
43         size /= sizeof(*mem); \
44         while (size-- > 0) \
45                 sum += *mem++; \
46  \
47         return sum; \
48 }
49
50 make_rd_test(read_c_8,  int8_t)
51 make_rd_test(read_c_16, int16_t)
52 make_rd_test(read_c_32, int32_t)
53 make_rd_test(read_c_64, int64_t)
54
55 static int read_ldrd(void *mem, size_t size)
56 {
57         size /= 8;
58         asm volatile(
59                 "0: ldrd r2, r3, [%0], #8\n"
60                 "   subs %1, #1\n"
61                 "   bgt  0b\n"
62                  : "=&r"(mem), "=&r"(size)
63                  : "0"(mem), "1"(size)
64                  : "r2", "r3", "cc", "memory");
65         return 0;
66 }
67
68 static int read_ldrd_pld(void *mem, size_t size)
69 {
70         size /= 8;
71         asm volatile(
72                 "0: ldrd r2, r3, [%0], #8\n"
73                 "   subs %1, #1\n"
74                 "   pld  [%0, #64*4]\n"
75                 "   bgt  0b\n"
76                  : "=&r"(mem), "=&r"(size)
77                  : "0"(mem), "1"(size)
78                  : "r2", "r3", "cc", "memory");
79         return 0;
80 }
81
82 static int g_skip;
83 static int read_c_32_skip(void *mem_, size_t size)
84 {
85         const int *mem = mem_;
86         int skip = g_skip / 4;
87         int sum = 0;
88         size_t i;
89
90         size /= 4;
91         for (i = 0; i < size; i += skip)
92                 sum += mem[i];
93
94         return sum;
95 }
96
97 static int read_fbt_neon(void *mem, size_t size)
98 {
99         size_t i;
100
101         for (i = 0; i < size; i += 256)
102                 aligned_fetch_fbmem_to_scratch_neon(256, dummy2, mem + i);
103
104         return 0;
105 }
106
107 static int read_fbt_vfp(void *mem, size_t size)
108 {
109         size_t i;
110
111         for (i = 0; i < size; i += 256)
112                 aligned_fetch_fbmem_to_scratch_vfp(256, dummy2, mem  + i);
113
114         return 0;
115 }
116
117 static int write8(void *mem, size_t size)
118 {
119         asm volatile(
120                 "0: strb %1, [%0], #1\n"
121                 "   subs %1, #1\n"
122                 "   bgt  0b\n"
123                  : "=&r"(mem), "=&r"(size)
124                  : "0"(mem), "1"(size)
125                  : "cc", "memory");
126         return 0;
127 }
128
129 static int write16(void *mem, size_t size)
130 {
131         asm volatile(
132                 "0: strh %1, [%0], #2\n"
133                 "   subs %1, #2\n"
134                 "   bgt  0b\n"
135                  : "=&r"(mem), "=&r"(size)
136                  : "0"(mem), "1"(size)
137                  : "cc", "memory");
138         return 0;
139 }
140
141 static int write32(void *mem, size_t size)
142 {
143         asm volatile(
144                 "0: str %1, [%0], #4\n"
145                 "   subs %1, #4\n"
146                 "   bgt  0b\n"
147                  : "=&r"(mem), "=&r"(size)
148                  : "0"(mem), "1"(size)
149                  : "cc", "memory");
150         return 0;
151 }
152
153 static int write64(void *mem, size_t size)
154 {
155         asm volatile(
156                 "0: strd r12, r13, [%0], #8\n"
157                 "   subs %1, #8\n"
158                 "   bgt  0b\n"
159                  : "=&r"(mem), "=&r"(size)
160                  : "0"(mem), "1"(size)
161                  : "cc", "memory");
162         return 0;
163 }
164
165 static unsigned int run(const char *name,
166         void (*inv)(void *mem, size_t size),
167         int  (*test)(void *mem, size_t size),
168         void *mem, unsigned int baseline)
169 {
170         unsigned int i, cycles, smallest = ~0;
171
172         for (i = 0; i < TRIES; i++) {
173                 cycles = pcnt_get();
174                 if (inv)
175                         inv(mem, TEST_SIZE);
176                 test(mem, TEST_SIZE);
177                 cycles = pcnt_get() - cycles;
178
179                 if (cycles < smallest)
180                         smallest = cycles;
181         }
182
183         printf("%-10s %6uk", name, smallest / 1000);
184         if (baseline != 0)
185                 printf(" %5lld%%", smallest * 100ull / baseline);
186         printf("\n");
187
188         return smallest;
189 }
190
191 static void run_all(const char *name,
192         void (*inv)(void *mem, size_t size),
193         void *mem)
194 {
195         static unsigned int b[16];
196         unsigned int r[16];
197         int t = 0;
198
199         printf("%s\n", name);
200         r[t] = run("  8",       inv, read_c_8,  mem, b[t]); t++;
201         r[t] = run(" 16",       inv, read_c_16, mem, b[t]); t++;
202         r[t] = run(" 32",       inv, read_c_32, mem, b[t]); t++;
203         r[t] = run(" 64",       inv, read_c_64, mem, b[t]); t++;
204         g_skip = 32;
205         r[t] = run(" 32_s32",   inv, read_c_32_skip, mem, b[t]); t++;
206         g_skip = 64;
207         r[t] = run(" 32_s64",   inv, read_c_32_skip, mem, b[t]); t++;
208         r[t] = run(" ldrd",     inv, read_ldrd,      mem, b[t]); t++;
209         r[t] = run(" ldrd pld", inv, read_ldrd_pld,  mem, b[t]); t++;
210         r[t] = run(" fbt neon", inv, read_fbt_neon,  mem, b[t]); t++;
211         r[t] = run(" fbt vfp",  inv, read_fbt_vfp,   mem, b[t]); t++;
212         r[t] = run(" w08",     NULL, write8,         mem, b[t]); t++;
213         r[t] = run(" w16",     NULL, write16,        mem, b[t]); t++;
214         r[t] = run(" w32",     NULL, write32,        mem, b[t]); t++;
215         r[t] = run(" w64",     NULL, write64,        mem, b[t]); t++;
216
217         if (b[0] == 0)
218                 memcpy(b, r, sizeof(b));
219 }
220
221 static void shm_inv(void *mem, size_t size)
222 {
223         dsp_cache_inv_virt(mem, size);
224 }
225
226 static void run_shm(const char *name, dsp_cache_t ct, int use_inv)
227 {
228         dsp_mem_region_t region;
229         void *mem;
230
231         region = dsp_shm_alloc(ct, TEST_SIZE);
232         if (region.size < TEST_SIZE || region.virt_addr == 0) {
233                 fprintf(stderr, "dsp_shm_alloc failed\n");
234                 return;
235         }
236         mem = (void *)region.virt_addr;
237         // printf("mapped %d %p\n", ct, mem);
238
239         run_all(name, use_inv ? shm_inv : NULL, mem);
240
241         dsp_shm_free(region);
242 }
243
244 int main()
245 {
246         int ret;
247
248         // prefault
249         memset(dummy, 1, sizeof(dummy));
250         memset(dummy2, 1, sizeof(dummy2));
251         printf("pid: %d dummy: %p\n", (int)getpid(), dummy);
252
253         pcnt_init();
254
255         run_all(".bss", NULL, dummy);
256
257         ret = dsp_open();
258         if (ret != 0) {
259                 fprintf(stderr, "dsp_open %d\n", ret);
260                 return 1;
261         }
262
263         run_shm("shm wb", DSP_CACHE_RW, 0);
264         //run_shm("shm wt", DSP_CACHE_R, 0);
265         run_shm("shm nc", DSP_CACHE_W, 0);
266         //run_shm("shm wb inv", DSP_CACHE_RW, 1);
267         run_shm("shm wt inv", DSP_CACHE_R, 1);
268
269         dsp_close();
270
271         return 0;
272 }