tests: add armv7 debug test and a register dumper
[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(const 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(const 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");
65         return 0;
66 }
67
68 static int read_ldrd_pld(const 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");
79         return 0;
80 }
81
82 static int g_skip;
83 static int read_c_32_skip(const 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(const 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(const 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 unsigned int run(const char *name,
118         void (*inv)(const void *mem, size_t size),
119         int  (*test)(const void *mem, size_t size),
120         const void *mem, unsigned int baseline)
121 {
122         unsigned int i, cycles, smallest = ~0;
123
124         for (i = 0; i < TRIES; i++) {
125                 cycles = pcnt_get();
126                 if (inv)
127                         inv(mem, TEST_SIZE);
128                 test(mem, TEST_SIZE);
129                 cycles = pcnt_get() - cycles;
130
131                 if (cycles < smallest)
132                         smallest = cycles;
133         }
134
135         printf("%-10s %6uk", name, smallest / 1000);
136         if (baseline != 0)
137                 printf(" %5lld%%", smallest * 100ull / baseline);
138         printf("\n");
139
140         return smallest;
141 }
142
143 static void run_all(const char *name,
144         void (*inv)(const void *mem, size_t size),
145         const void *mem)
146 {
147         static unsigned int b[16];
148         unsigned int r[16];
149         int t = 0;
150
151         printf("%s\n", name);
152         r[t] = run("  8",       inv, read_c_8,  mem, b[t]); t++;
153         r[t] = run(" 16",       inv, read_c_16, mem, b[t]); t++;
154         r[t] = run(" 32",       inv, read_c_32, mem, b[t]); t++;
155         r[t] = run(" 64",       inv, read_c_64, mem, b[t]); t++;
156         g_skip = 32;
157         r[t] = run(" 32_s32",   inv, read_c_32_skip, mem, b[t]); t++;
158         g_skip = 64;
159         r[t] = run(" 32_s64",   inv, read_c_32_skip, mem, b[t]); t++;
160         r[t] = run(" ldrd",     inv, read_ldrd,      mem, b[t]); t++;
161         r[t] = run(" ldrd pld", inv, read_ldrd_pld,  mem, b[t]); t++;
162         r[t] = run(" fbt neon", inv, read_fbt_neon,  mem, b[t]); t++;
163         r[t] = run(" fbt vfp",  inv, read_fbt_vfp,   mem, b[t]); t++;
164
165         if (b[0] == 0)
166                 memcpy(b, r, sizeof(b));
167 }
168
169 static void shm_inv(const void *mem, size_t size)
170 {
171         dsp_cache_inv_virt((void *)mem, size);
172 }
173
174 static void run_shm(const char *name, dsp_cache_t ct, int use_inv)
175 {
176         dsp_mem_region_t region;
177         void *mem;
178
179         region = dsp_shm_alloc(ct, TEST_SIZE);
180         if (region.size < TEST_SIZE || region.virt_addr == 0) {
181                 fprintf(stderr, "dsp_shm_alloc failed\n");
182                 return;
183         }
184         mem = (void *)region.virt_addr;
185         // printf("mapped %d %p\n", ct, mem);
186
187         run_all(name, use_inv ? shm_inv : NULL, mem);
188
189         dsp_shm_free(region);
190 }
191
192 int main()
193 {
194         int ret;
195
196         // prefault
197         memset(dummy, 1, sizeof(dummy));
198         memset(dummy2, 1, sizeof(dummy2));
199         printf("pid: %d dummy: %p\n", (int)getpid(), dummy);
200
201         pcnt_init();
202
203         run_all(".bss", NULL, dummy);
204
205         ret = dsp_open();
206         if (ret != 0) {
207                 fprintf(stderr, "dsp_open %d\n", ret);
208                 return 1;
209         }
210
211         run_shm("shm wb", DSP_CACHE_RW, 0);
212         //run_shm("shm wt", DSP_CACHE_R, 0);
213         run_shm("shm nc", DSP_CACHE_W, 0);
214         //run_shm("shm wb inv", DSP_CACHE_RW, 1);
215         run_shm("shm wt inv", DSP_CACHE_R, 1);
216
217         dsp_close();
218
219         return 0;
220 }