1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker * Copyright © 2021 Google, Inc.
3*61046927SAndroid Build Coastguard Worker * SPDX-License-Identifier: MIT
4*61046927SAndroid Build Coastguard Worker */
5*61046927SAndroid Build Coastguard Worker
6*61046927SAndroid Build Coastguard Worker #include <assert.h>
7*61046927SAndroid Build Coastguard Worker #include <ctype.h>
8*61046927SAndroid Build Coastguard Worker #include <inttypes.h>
9*61046927SAndroid Build Coastguard Worker #include <stdio.h>
10*61046927SAndroid Build Coastguard Worker #include <stdlib.h>
11*61046927SAndroid Build Coastguard Worker #include <termios.h>
12*61046927SAndroid Build Coastguard Worker #include <unistd.h>
13*61046927SAndroid Build Coastguard Worker
14*61046927SAndroid Build Coastguard Worker #include "freedreno_pm4.h"
15*61046927SAndroid Build Coastguard Worker
16*61046927SAndroid Build Coastguard Worker #include "emu.h"
17*61046927SAndroid Build Coastguard Worker #include "util.h"
18*61046927SAndroid Build Coastguard Worker
19*61046927SAndroid Build Coastguard Worker /*
20*61046927SAndroid Build Coastguard Worker * Emulator User Interface:
21*61046927SAndroid Build Coastguard Worker *
22*61046927SAndroid Build Coastguard Worker * Handles the user prompts and input parsing.
23*61046927SAndroid Build Coastguard Worker */
24*61046927SAndroid Build Coastguard Worker
25*61046927SAndroid Build Coastguard Worker static void
clear_line(void)26*61046927SAndroid Build Coastguard Worker clear_line(void)
27*61046927SAndroid Build Coastguard Worker {
28*61046927SAndroid Build Coastguard Worker if (!isatty(STDOUT_FILENO))
29*61046927SAndroid Build Coastguard Worker return;
30*61046927SAndroid Build Coastguard Worker printf("\r \r");
31*61046927SAndroid Build Coastguard Worker }
32*61046927SAndroid Build Coastguard Worker
33*61046927SAndroid Build Coastguard Worker static int
readchar(void)34*61046927SAndroid Build Coastguard Worker readchar(void)
35*61046927SAndroid Build Coastguard Worker {
36*61046927SAndroid Build Coastguard Worker static struct termios saved_termios, unbuffered_termios;
37*61046927SAndroid Build Coastguard Worker int c;
38*61046927SAndroid Build Coastguard Worker
39*61046927SAndroid Build Coastguard Worker fflush(stdout);
40*61046927SAndroid Build Coastguard Worker
41*61046927SAndroid Build Coastguard Worker tcgetattr(STDIN_FILENO, &saved_termios);
42*61046927SAndroid Build Coastguard Worker unbuffered_termios = saved_termios;
43*61046927SAndroid Build Coastguard Worker cfmakeraw(&unbuffered_termios);
44*61046927SAndroid Build Coastguard Worker
45*61046927SAndroid Build Coastguard Worker tcsetattr(STDIN_FILENO, TCSANOW, &unbuffered_termios);
46*61046927SAndroid Build Coastguard Worker do {
47*61046927SAndroid Build Coastguard Worker c = getchar();
48*61046927SAndroid Build Coastguard Worker } while (isspace(c));
49*61046927SAndroid Build Coastguard Worker tcsetattr(STDIN_FILENO, TCSANOW, &saved_termios);
50*61046927SAndroid Build Coastguard Worker
51*61046927SAndroid Build Coastguard Worker /* TODO, read from script until EOF and then read from stdin: */
52*61046927SAndroid Build Coastguard Worker if (c == -1)
53*61046927SAndroid Build Coastguard Worker exit(0);
54*61046927SAndroid Build Coastguard Worker
55*61046927SAndroid Build Coastguard Worker return c;
56*61046927SAndroid Build Coastguard Worker }
57*61046927SAndroid Build Coastguard Worker
58*61046927SAndroid Build Coastguard Worker static const char *
extract_string(char ** buf)59*61046927SAndroid Build Coastguard Worker extract_string(char **buf)
60*61046927SAndroid Build Coastguard Worker {
61*61046927SAndroid Build Coastguard Worker char *p = *buf;
62*61046927SAndroid Build Coastguard Worker
63*61046927SAndroid Build Coastguard Worker /* eat any leading whitespace: */
64*61046927SAndroid Build Coastguard Worker while (*p && isspace(*p))
65*61046927SAndroid Build Coastguard Worker p++;
66*61046927SAndroid Build Coastguard Worker
67*61046927SAndroid Build Coastguard Worker if (!*p)
68*61046927SAndroid Build Coastguard Worker return NULL;
69*61046927SAndroid Build Coastguard Worker
70*61046927SAndroid Build Coastguard Worker char *ret = p;
71*61046927SAndroid Build Coastguard Worker
72*61046927SAndroid Build Coastguard Worker /* skip to next whitespace: */
73*61046927SAndroid Build Coastguard Worker while (*p && !isspace(*p))
74*61046927SAndroid Build Coastguard Worker p++;
75*61046927SAndroid Build Coastguard Worker
76*61046927SAndroid Build Coastguard Worker if (*p)
77*61046927SAndroid Build Coastguard Worker *p = '\0';
78*61046927SAndroid Build Coastguard Worker
79*61046927SAndroid Build Coastguard Worker *buf = ++p;
80*61046927SAndroid Build Coastguard Worker
81*61046927SAndroid Build Coastguard Worker return ret;
82*61046927SAndroid Build Coastguard Worker }
83*61046927SAndroid Build Coastguard Worker
84*61046927SAndroid Build Coastguard Worker static size_t
readline(char ** p)85*61046927SAndroid Build Coastguard Worker readline(char **p)
86*61046927SAndroid Build Coastguard Worker {
87*61046927SAndroid Build Coastguard Worker static char *buf;
88*61046927SAndroid Build Coastguard Worker static size_t n;
89*61046927SAndroid Build Coastguard Worker
90*61046927SAndroid Build Coastguard Worker ssize_t ret = getline(&buf, &n, stdin);
91*61046927SAndroid Build Coastguard Worker if (ret < 0)
92*61046927SAndroid Build Coastguard Worker return ret;
93*61046927SAndroid Build Coastguard Worker
94*61046927SAndroid Build Coastguard Worker *p = buf;
95*61046927SAndroid Build Coastguard Worker return 0;
96*61046927SAndroid Build Coastguard Worker }
97*61046927SAndroid Build Coastguard Worker
98*61046927SAndroid Build Coastguard Worker static ssize_t
read_two_values(const char ** val1,const char ** val2)99*61046927SAndroid Build Coastguard Worker read_two_values(const char **val1, const char **val2)
100*61046927SAndroid Build Coastguard Worker {
101*61046927SAndroid Build Coastguard Worker char *p;
102*61046927SAndroid Build Coastguard Worker
103*61046927SAndroid Build Coastguard Worker ssize_t ret = readline(&p);
104*61046927SAndroid Build Coastguard Worker if (ret < 0)
105*61046927SAndroid Build Coastguard Worker return ret;
106*61046927SAndroid Build Coastguard Worker
107*61046927SAndroid Build Coastguard Worker *val1 = extract_string(&p);
108*61046927SAndroid Build Coastguard Worker *val2 = extract_string(&p);
109*61046927SAndroid Build Coastguard Worker
110*61046927SAndroid Build Coastguard Worker return 0;
111*61046927SAndroid Build Coastguard Worker }
112*61046927SAndroid Build Coastguard Worker
113*61046927SAndroid Build Coastguard Worker static ssize_t
read_one_value(const char ** val)114*61046927SAndroid Build Coastguard Worker read_one_value(const char **val)
115*61046927SAndroid Build Coastguard Worker {
116*61046927SAndroid Build Coastguard Worker char *p;
117*61046927SAndroid Build Coastguard Worker
118*61046927SAndroid Build Coastguard Worker ssize_t ret = readline(&p);
119*61046927SAndroid Build Coastguard Worker if (ret < 0)
120*61046927SAndroid Build Coastguard Worker return ret;
121*61046927SAndroid Build Coastguard Worker
122*61046927SAndroid Build Coastguard Worker *val = extract_string(&p);
123*61046927SAndroid Build Coastguard Worker
124*61046927SAndroid Build Coastguard Worker return 0;
125*61046927SAndroid Build Coastguard Worker }
126*61046927SAndroid Build Coastguard Worker
127*61046927SAndroid Build Coastguard Worker static void
print_dst(unsigned reg)128*61046927SAndroid Build Coastguard Worker print_dst(unsigned reg)
129*61046927SAndroid Build Coastguard Worker {
130*61046927SAndroid Build Coastguard Worker if (reg == REG_REM)
131*61046927SAndroid Build Coastguard Worker printf("$rem"); /* remainding dwords in packet */
132*61046927SAndroid Build Coastguard Worker else if (reg == REG_ADDR)
133*61046927SAndroid Build Coastguard Worker printf("$addr");
134*61046927SAndroid Build Coastguard Worker else if (reg == REG_USRADDR)
135*61046927SAndroid Build Coastguard Worker printf("$usraddr");
136*61046927SAndroid Build Coastguard Worker else if (reg == REG_DATA)
137*61046927SAndroid Build Coastguard Worker printf("$data");
138*61046927SAndroid Build Coastguard Worker else
139*61046927SAndroid Build Coastguard Worker printf("$%02x", reg);
140*61046927SAndroid Build Coastguard Worker }
141*61046927SAndroid Build Coastguard Worker
142*61046927SAndroid Build Coastguard Worker static void
dump_gpr_register(struct emu * emu,unsigned n)143*61046927SAndroid Build Coastguard Worker dump_gpr_register(struct emu *emu, unsigned n)
144*61046927SAndroid Build Coastguard Worker {
145*61046927SAndroid Build Coastguard Worker printf(" GPR: ");
146*61046927SAndroid Build Coastguard Worker print_dst(n);
147*61046927SAndroid Build Coastguard Worker printf(": ");
148*61046927SAndroid Build Coastguard Worker if (BITSET_TEST(emu->gpr_regs.written, n)) {
149*61046927SAndroid Build Coastguard Worker printdelta("%08x\n", emu->gpr_regs.val[n]);
150*61046927SAndroid Build Coastguard Worker } else {
151*61046927SAndroid Build Coastguard Worker printf("%08x\n", emu->gpr_regs.val[n]);
152*61046927SAndroid Build Coastguard Worker }
153*61046927SAndroid Build Coastguard Worker }
154*61046927SAndroid Build Coastguard Worker
155*61046927SAndroid Build Coastguard Worker static void
dump_gpr_registers(struct emu * emu)156*61046927SAndroid Build Coastguard Worker dump_gpr_registers(struct emu *emu)
157*61046927SAndroid Build Coastguard Worker {
158*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < ARRAY_SIZE(emu->gpr_regs.val); i++) {
159*61046927SAndroid Build Coastguard Worker dump_gpr_register(emu, i);
160*61046927SAndroid Build Coastguard Worker }
161*61046927SAndroid Build Coastguard Worker }
162*61046927SAndroid Build Coastguard Worker
163*61046927SAndroid Build Coastguard Worker static void
dump_gpu_register(struct emu * emu,unsigned n)164*61046927SAndroid Build Coastguard Worker dump_gpu_register(struct emu *emu, unsigned n)
165*61046927SAndroid Build Coastguard Worker {
166*61046927SAndroid Build Coastguard Worker printf(" GPU: ");
167*61046927SAndroid Build Coastguard Worker char *name = afuc_gpu_reg_name(n);
168*61046927SAndroid Build Coastguard Worker if (name) {
169*61046927SAndroid Build Coastguard Worker printf("%s", name);
170*61046927SAndroid Build Coastguard Worker free(name);
171*61046927SAndroid Build Coastguard Worker } else {
172*61046927SAndroid Build Coastguard Worker printf("0x%04x", n);
173*61046927SAndroid Build Coastguard Worker }
174*61046927SAndroid Build Coastguard Worker printf(": ");
175*61046927SAndroid Build Coastguard Worker if (BITSET_TEST(emu->gpu_regs.written, n)) {
176*61046927SAndroid Build Coastguard Worker printdelta("%08x\n", emu->gpu_regs.val[n]);
177*61046927SAndroid Build Coastguard Worker } else {
178*61046927SAndroid Build Coastguard Worker printf("%08x\n", emu->gpu_regs.val[n]);
179*61046927SAndroid Build Coastguard Worker }
180*61046927SAndroid Build Coastguard Worker }
181*61046927SAndroid Build Coastguard Worker
182*61046927SAndroid Build Coastguard Worker static void
dump_pipe_register(struct emu * emu,unsigned n)183*61046927SAndroid Build Coastguard Worker dump_pipe_register(struct emu *emu, unsigned n)
184*61046927SAndroid Build Coastguard Worker {
185*61046927SAndroid Build Coastguard Worker printf(" PIPE: ");
186*61046927SAndroid Build Coastguard Worker print_pipe_reg(n);
187*61046927SAndroid Build Coastguard Worker printf(": ");
188*61046927SAndroid Build Coastguard Worker if (BITSET_TEST(emu->pipe_regs.written, n)) {
189*61046927SAndroid Build Coastguard Worker printdelta("%08x\n", emu->pipe_regs.val[n]);
190*61046927SAndroid Build Coastguard Worker } else {
191*61046927SAndroid Build Coastguard Worker printf("%08x\n", emu->pipe_regs.val[n]);
192*61046927SAndroid Build Coastguard Worker }
193*61046927SAndroid Build Coastguard Worker }
194*61046927SAndroid Build Coastguard Worker
195*61046927SAndroid Build Coastguard Worker static void
dump_control_register(struct emu * emu,unsigned n)196*61046927SAndroid Build Coastguard Worker dump_control_register(struct emu *emu, unsigned n)
197*61046927SAndroid Build Coastguard Worker {
198*61046927SAndroid Build Coastguard Worker printf(" CTRL: ");
199*61046927SAndroid Build Coastguard Worker print_control_reg(n);
200*61046927SAndroid Build Coastguard Worker printf(": ");
201*61046927SAndroid Build Coastguard Worker if (BITSET_TEST(emu->control_regs.written, n)) {
202*61046927SAndroid Build Coastguard Worker printdelta("%08x\n", emu->control_regs.val[n]);
203*61046927SAndroid Build Coastguard Worker } else {
204*61046927SAndroid Build Coastguard Worker printf("%08x\n", emu->control_regs.val[n]);
205*61046927SAndroid Build Coastguard Worker }
206*61046927SAndroid Build Coastguard Worker }
207*61046927SAndroid Build Coastguard Worker
208*61046927SAndroid Build Coastguard Worker static void
dump_sqe_register(struct emu * emu,unsigned n)209*61046927SAndroid Build Coastguard Worker dump_sqe_register(struct emu *emu, unsigned n)
210*61046927SAndroid Build Coastguard Worker {
211*61046927SAndroid Build Coastguard Worker printf(" SQE: ");
212*61046927SAndroid Build Coastguard Worker print_sqe_reg(n);
213*61046927SAndroid Build Coastguard Worker printf(": ");
214*61046927SAndroid Build Coastguard Worker if (BITSET_TEST(emu->sqe_regs.written, n)) {
215*61046927SAndroid Build Coastguard Worker printdelta("%08x\n", emu->sqe_regs.val[n]);
216*61046927SAndroid Build Coastguard Worker } else {
217*61046927SAndroid Build Coastguard Worker printf("%08x\n", emu->sqe_regs.val[n]);
218*61046927SAndroid Build Coastguard Worker }
219*61046927SAndroid Build Coastguard Worker }
220*61046927SAndroid Build Coastguard Worker
221*61046927SAndroid Build Coastguard Worker static void
dump_sqe_registers(struct emu * emu)222*61046927SAndroid Build Coastguard Worker dump_sqe_registers(struct emu *emu)
223*61046927SAndroid Build Coastguard Worker {
224*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < ARRAY_SIZE(emu->sqe_regs.val); i++) {
225*61046927SAndroid Build Coastguard Worker dump_sqe_register(emu, i);
226*61046927SAndroid Build Coastguard Worker }
227*61046927SAndroid Build Coastguard Worker }
228*61046927SAndroid Build Coastguard Worker
229*61046927SAndroid Build Coastguard Worker
230*61046927SAndroid Build Coastguard Worker static void
dump_gpumem(struct emu * emu,uintptr_t addr)231*61046927SAndroid Build Coastguard Worker dump_gpumem(struct emu *emu, uintptr_t addr)
232*61046927SAndroid Build Coastguard Worker {
233*61046927SAndroid Build Coastguard Worker uint32_t val = emu_mem_read_dword(emu, addr);
234*61046927SAndroid Build Coastguard Worker
235*61046927SAndroid Build Coastguard Worker printf(" MEM: 0x%016"PRIxPTR": ", addr);
236*61046927SAndroid Build Coastguard Worker if (addr == emu->gpumem_written) {
237*61046927SAndroid Build Coastguard Worker printdelta("0x%08x\n", val);
238*61046927SAndroid Build Coastguard Worker } else {
239*61046927SAndroid Build Coastguard Worker printf("0x%08x\n", val);
240*61046927SAndroid Build Coastguard Worker }
241*61046927SAndroid Build Coastguard Worker }
242*61046927SAndroid Build Coastguard Worker
243*61046927SAndroid Build Coastguard Worker static void
emu_write_gpr_prompt(struct emu * emu)244*61046927SAndroid Build Coastguard Worker emu_write_gpr_prompt(struct emu *emu)
245*61046927SAndroid Build Coastguard Worker {
246*61046927SAndroid Build Coastguard Worker clear_line();
247*61046927SAndroid Build Coastguard Worker printf(" GPR register (name or offset) and value: ");
248*61046927SAndroid Build Coastguard Worker
249*61046927SAndroid Build Coastguard Worker const char *name;
250*61046927SAndroid Build Coastguard Worker const char *value;
251*61046927SAndroid Build Coastguard Worker
252*61046927SAndroid Build Coastguard Worker if (read_two_values(&name, &value))
253*61046927SAndroid Build Coastguard Worker return;
254*61046927SAndroid Build Coastguard Worker
255*61046927SAndroid Build Coastguard Worker unsigned offset = afuc_gpr_reg(name);
256*61046927SAndroid Build Coastguard Worker uint32_t val = strtoul(value, NULL, 0);
257*61046927SAndroid Build Coastguard Worker
258*61046927SAndroid Build Coastguard Worker emu_set_gpr_reg(emu, offset, val);
259*61046927SAndroid Build Coastguard Worker }
260*61046927SAndroid Build Coastguard Worker
261*61046927SAndroid Build Coastguard Worker static void
emu_write_control_prompt(struct emu * emu)262*61046927SAndroid Build Coastguard Worker emu_write_control_prompt(struct emu *emu)
263*61046927SAndroid Build Coastguard Worker {
264*61046927SAndroid Build Coastguard Worker clear_line();
265*61046927SAndroid Build Coastguard Worker printf(" Control register (name or offset) and value: ");
266*61046927SAndroid Build Coastguard Worker
267*61046927SAndroid Build Coastguard Worker const char *name;
268*61046927SAndroid Build Coastguard Worker const char *value;
269*61046927SAndroid Build Coastguard Worker
270*61046927SAndroid Build Coastguard Worker if (read_two_values(&name, &value))
271*61046927SAndroid Build Coastguard Worker return;
272*61046927SAndroid Build Coastguard Worker
273*61046927SAndroid Build Coastguard Worker unsigned offset = afuc_control_reg(name);
274*61046927SAndroid Build Coastguard Worker uint32_t val = strtoul(value, NULL, 0);
275*61046927SAndroid Build Coastguard Worker
276*61046927SAndroid Build Coastguard Worker emu_set_control_reg(emu, offset, val);
277*61046927SAndroid Build Coastguard Worker }
278*61046927SAndroid Build Coastguard Worker
279*61046927SAndroid Build Coastguard Worker static void
emu_dump_control_prompt(struct emu * emu)280*61046927SAndroid Build Coastguard Worker emu_dump_control_prompt(struct emu *emu)
281*61046927SAndroid Build Coastguard Worker {
282*61046927SAndroid Build Coastguard Worker clear_line();
283*61046927SAndroid Build Coastguard Worker printf(" Control register (name or offset): ");
284*61046927SAndroid Build Coastguard Worker
285*61046927SAndroid Build Coastguard Worker const char *name;
286*61046927SAndroid Build Coastguard Worker
287*61046927SAndroid Build Coastguard Worker if (read_one_value(&name))
288*61046927SAndroid Build Coastguard Worker return;
289*61046927SAndroid Build Coastguard Worker
290*61046927SAndroid Build Coastguard Worker printf("\n");
291*61046927SAndroid Build Coastguard Worker
292*61046927SAndroid Build Coastguard Worker unsigned offset = afuc_control_reg(name);
293*61046927SAndroid Build Coastguard Worker dump_control_register(emu, offset);
294*61046927SAndroid Build Coastguard Worker }
295*61046927SAndroid Build Coastguard Worker
296*61046927SAndroid Build Coastguard Worker static void
emu_write_sqe_prompt(struct emu * emu)297*61046927SAndroid Build Coastguard Worker emu_write_sqe_prompt(struct emu *emu)
298*61046927SAndroid Build Coastguard Worker {
299*61046927SAndroid Build Coastguard Worker clear_line();
300*61046927SAndroid Build Coastguard Worker printf(" SQE register (name or offset) and value: ");
301*61046927SAndroid Build Coastguard Worker
302*61046927SAndroid Build Coastguard Worker const char *name;
303*61046927SAndroid Build Coastguard Worker const char *value;
304*61046927SAndroid Build Coastguard Worker
305*61046927SAndroid Build Coastguard Worker if (read_two_values(&name, &value))
306*61046927SAndroid Build Coastguard Worker return;
307*61046927SAndroid Build Coastguard Worker
308*61046927SAndroid Build Coastguard Worker unsigned offset = afuc_sqe_reg(name);
309*61046927SAndroid Build Coastguard Worker uint32_t val = strtoul(value, NULL, 0);
310*61046927SAndroid Build Coastguard Worker
311*61046927SAndroid Build Coastguard Worker emu_set_sqe_reg(emu, offset, val);
312*61046927SAndroid Build Coastguard Worker }
313*61046927SAndroid Build Coastguard Worker
314*61046927SAndroid Build Coastguard Worker static void
emu_write_gpu_prompt(struct emu * emu)315*61046927SAndroid Build Coastguard Worker emu_write_gpu_prompt(struct emu *emu)
316*61046927SAndroid Build Coastguard Worker {
317*61046927SAndroid Build Coastguard Worker clear_line();
318*61046927SAndroid Build Coastguard Worker printf(" GPU register (name or offset) and value: ");
319*61046927SAndroid Build Coastguard Worker
320*61046927SAndroid Build Coastguard Worker const char *name;
321*61046927SAndroid Build Coastguard Worker const char *value;
322*61046927SAndroid Build Coastguard Worker
323*61046927SAndroid Build Coastguard Worker if (read_two_values(&name, &value))
324*61046927SAndroid Build Coastguard Worker return;
325*61046927SAndroid Build Coastguard Worker
326*61046927SAndroid Build Coastguard Worker unsigned offset = afuc_gpu_reg(name);
327*61046927SAndroid Build Coastguard Worker uint32_t val = strtoul(value, NULL, 0);
328*61046927SAndroid Build Coastguard Worker
329*61046927SAndroid Build Coastguard Worker emu_set_gpu_reg(emu, offset, val);
330*61046927SAndroid Build Coastguard Worker }
331*61046927SAndroid Build Coastguard Worker
332*61046927SAndroid Build Coastguard Worker static void
emu_dump_gpu_prompt(struct emu * emu)333*61046927SAndroid Build Coastguard Worker emu_dump_gpu_prompt(struct emu *emu)
334*61046927SAndroid Build Coastguard Worker {
335*61046927SAndroid Build Coastguard Worker clear_line();
336*61046927SAndroid Build Coastguard Worker printf(" GPU register (name or offset): ");
337*61046927SAndroid Build Coastguard Worker
338*61046927SAndroid Build Coastguard Worker const char *name;
339*61046927SAndroid Build Coastguard Worker
340*61046927SAndroid Build Coastguard Worker if (read_one_value(&name))
341*61046927SAndroid Build Coastguard Worker return;
342*61046927SAndroid Build Coastguard Worker
343*61046927SAndroid Build Coastguard Worker printf("\n");
344*61046927SAndroid Build Coastguard Worker
345*61046927SAndroid Build Coastguard Worker unsigned offset = afuc_gpu_reg(name);
346*61046927SAndroid Build Coastguard Worker dump_gpu_register(emu, offset);
347*61046927SAndroid Build Coastguard Worker }
348*61046927SAndroid Build Coastguard Worker
349*61046927SAndroid Build Coastguard Worker static void
emu_write_mem_prompt(struct emu * emu)350*61046927SAndroid Build Coastguard Worker emu_write_mem_prompt(struct emu *emu)
351*61046927SAndroid Build Coastguard Worker {
352*61046927SAndroid Build Coastguard Worker clear_line();
353*61046927SAndroid Build Coastguard Worker printf(" GPU memory offset and value: ");
354*61046927SAndroid Build Coastguard Worker
355*61046927SAndroid Build Coastguard Worker const char *offset;
356*61046927SAndroid Build Coastguard Worker const char *value;
357*61046927SAndroid Build Coastguard Worker
358*61046927SAndroid Build Coastguard Worker if (read_two_values(&offset, &value))
359*61046927SAndroid Build Coastguard Worker return;
360*61046927SAndroid Build Coastguard Worker
361*61046927SAndroid Build Coastguard Worker uintptr_t addr = strtoull(offset, NULL, 0);
362*61046927SAndroid Build Coastguard Worker uint32_t val = strtoul(value, NULL, 0);
363*61046927SAndroid Build Coastguard Worker
364*61046927SAndroid Build Coastguard Worker emu_mem_write_dword(emu, addr, val);
365*61046927SAndroid Build Coastguard Worker }
366*61046927SAndroid Build Coastguard Worker
367*61046927SAndroid Build Coastguard Worker static void
emu_dump_mem_prompt(struct emu * emu)368*61046927SAndroid Build Coastguard Worker emu_dump_mem_prompt(struct emu *emu)
369*61046927SAndroid Build Coastguard Worker {
370*61046927SAndroid Build Coastguard Worker clear_line();
371*61046927SAndroid Build Coastguard Worker printf(" GPU memory offset: ");
372*61046927SAndroid Build Coastguard Worker
373*61046927SAndroid Build Coastguard Worker const char *offset;
374*61046927SAndroid Build Coastguard Worker
375*61046927SAndroid Build Coastguard Worker if (read_one_value(&offset))
376*61046927SAndroid Build Coastguard Worker return;
377*61046927SAndroid Build Coastguard Worker
378*61046927SAndroid Build Coastguard Worker printf("\n");
379*61046927SAndroid Build Coastguard Worker
380*61046927SAndroid Build Coastguard Worker uintptr_t addr = strtoull(offset, NULL, 0);
381*61046927SAndroid Build Coastguard Worker dump_gpumem(emu, addr);
382*61046927SAndroid Build Coastguard Worker }
383*61046927SAndroid Build Coastguard Worker
384*61046927SAndroid Build Coastguard Worker static void
emu_dump_prompt(struct emu * emu)385*61046927SAndroid Build Coastguard Worker emu_dump_prompt(struct emu *emu)
386*61046927SAndroid Build Coastguard Worker {
387*61046927SAndroid Build Coastguard Worker do {
388*61046927SAndroid Build Coastguard Worker clear_line();
389*61046927SAndroid Build Coastguard Worker printf(" dump: GPR (r)egisters, (c)ontrol register, (s)qe registers, (g)pu register, (m)emory: ");
390*61046927SAndroid Build Coastguard Worker
391*61046927SAndroid Build Coastguard Worker int c = readchar();
392*61046927SAndroid Build Coastguard Worker printf("%c\n", c);
393*61046927SAndroid Build Coastguard Worker
394*61046927SAndroid Build Coastguard Worker if (c == 'r') {
395*61046927SAndroid Build Coastguard Worker /* Since there aren't too many GPR registers, just dump
396*61046927SAndroid Build Coastguard Worker * them all:
397*61046927SAndroid Build Coastguard Worker */
398*61046927SAndroid Build Coastguard Worker dump_gpr_registers(emu);
399*61046927SAndroid Build Coastguard Worker break;
400*61046927SAndroid Build Coastguard Worker } else if (c == 's') {
401*61046927SAndroid Build Coastguard Worker /* Similarly, just dump all the SQE registers */
402*61046927SAndroid Build Coastguard Worker dump_sqe_registers(emu);
403*61046927SAndroid Build Coastguard Worker break;
404*61046927SAndroid Build Coastguard Worker } else if (c == 'c') {
405*61046927SAndroid Build Coastguard Worker emu_dump_control_prompt(emu);
406*61046927SAndroid Build Coastguard Worker break;
407*61046927SAndroid Build Coastguard Worker } else if (c == 'g') {
408*61046927SAndroid Build Coastguard Worker emu_dump_gpu_prompt(emu);
409*61046927SAndroid Build Coastguard Worker break;
410*61046927SAndroid Build Coastguard Worker } else if (c == 'm') {
411*61046927SAndroid Build Coastguard Worker emu_dump_mem_prompt(emu);
412*61046927SAndroid Build Coastguard Worker break;
413*61046927SAndroid Build Coastguard Worker } else {
414*61046927SAndroid Build Coastguard Worker printf("invalid option: '%c'\n", c);
415*61046927SAndroid Build Coastguard Worker break;
416*61046927SAndroid Build Coastguard Worker }
417*61046927SAndroid Build Coastguard Worker } while (true);
418*61046927SAndroid Build Coastguard Worker }
419*61046927SAndroid Build Coastguard Worker
420*61046927SAndroid Build Coastguard Worker static void
emu_write_prompt(struct emu * emu)421*61046927SAndroid Build Coastguard Worker emu_write_prompt(struct emu *emu)
422*61046927SAndroid Build Coastguard Worker {
423*61046927SAndroid Build Coastguard Worker do {
424*61046927SAndroid Build Coastguard Worker clear_line();
425*61046927SAndroid Build Coastguard Worker printf(" write: GPR (r)egister, (c)ontrol register, (s)sqe register, (g)pu register, (m)emory: ");
426*61046927SAndroid Build Coastguard Worker
427*61046927SAndroid Build Coastguard Worker int c = readchar();
428*61046927SAndroid Build Coastguard Worker printf("%c\n", c);
429*61046927SAndroid Build Coastguard Worker
430*61046927SAndroid Build Coastguard Worker if (c == 'r') {
431*61046927SAndroid Build Coastguard Worker emu_write_gpr_prompt(emu);
432*61046927SAndroid Build Coastguard Worker break;
433*61046927SAndroid Build Coastguard Worker } else if (c == 's') {
434*61046927SAndroid Build Coastguard Worker emu_write_sqe_prompt(emu);
435*61046927SAndroid Build Coastguard Worker break;
436*61046927SAndroid Build Coastguard Worker } else if (c == 'c') {
437*61046927SAndroid Build Coastguard Worker emu_write_control_prompt(emu);
438*61046927SAndroid Build Coastguard Worker break;
439*61046927SAndroid Build Coastguard Worker } else if (c == 'g') {
440*61046927SAndroid Build Coastguard Worker emu_write_gpu_prompt(emu);
441*61046927SAndroid Build Coastguard Worker break;
442*61046927SAndroid Build Coastguard Worker } else if (c == 'm') {
443*61046927SAndroid Build Coastguard Worker emu_write_mem_prompt(emu);
444*61046927SAndroid Build Coastguard Worker break;
445*61046927SAndroid Build Coastguard Worker } else {
446*61046927SAndroid Build Coastguard Worker printf("invalid option: '%c'\n", c);
447*61046927SAndroid Build Coastguard Worker break;
448*61046927SAndroid Build Coastguard Worker }
449*61046927SAndroid Build Coastguard Worker } while (true);
450*61046927SAndroid Build Coastguard Worker }
451*61046927SAndroid Build Coastguard Worker
452*61046927SAndroid Build Coastguard Worker static void
emu_packet_prompt(struct emu * emu)453*61046927SAndroid Build Coastguard Worker emu_packet_prompt(struct emu *emu)
454*61046927SAndroid Build Coastguard Worker {
455*61046927SAndroid Build Coastguard Worker clear_line();
456*61046927SAndroid Build Coastguard Worker printf(" Enter packet (opc or register name), followed by payload: ");
457*61046927SAndroid Build Coastguard Worker fflush(stdout);
458*61046927SAndroid Build Coastguard Worker
459*61046927SAndroid Build Coastguard Worker char *p;
460*61046927SAndroid Build Coastguard Worker if (readline(&p) < 0)
461*61046927SAndroid Build Coastguard Worker return;
462*61046927SAndroid Build Coastguard Worker
463*61046927SAndroid Build Coastguard Worker printf("\n");
464*61046927SAndroid Build Coastguard Worker
465*61046927SAndroid Build Coastguard Worker const char *name = extract_string(&p);
466*61046927SAndroid Build Coastguard Worker
467*61046927SAndroid Build Coastguard Worker /* Read the payload, so we can know the size to generate correct header: */
468*61046927SAndroid Build Coastguard Worker uint32_t payload[0x7f];
469*61046927SAndroid Build Coastguard Worker unsigned cnt = 0;
470*61046927SAndroid Build Coastguard Worker
471*61046927SAndroid Build Coastguard Worker do {
472*61046927SAndroid Build Coastguard Worker const char *val = extract_string(&p);
473*61046927SAndroid Build Coastguard Worker if (!val)
474*61046927SAndroid Build Coastguard Worker break;
475*61046927SAndroid Build Coastguard Worker
476*61046927SAndroid Build Coastguard Worker assert(cnt < ARRAY_SIZE(payload));
477*61046927SAndroid Build Coastguard Worker payload[cnt++] = strtoul(val, NULL, 0);
478*61046927SAndroid Build Coastguard Worker } while (true);
479*61046927SAndroid Build Coastguard Worker
480*61046927SAndroid Build Coastguard Worker uint32_t hdr;
481*61046927SAndroid Build Coastguard Worker if (afuc_pm4_id(name) >= 0) {
482*61046927SAndroid Build Coastguard Worker unsigned opcode = afuc_pm4_id(name);
483*61046927SAndroid Build Coastguard Worker hdr = pm4_pkt7_hdr(opcode, cnt);
484*61046927SAndroid Build Coastguard Worker } else {
485*61046927SAndroid Build Coastguard Worker unsigned regindx = afuc_gpu_reg(name);
486*61046927SAndroid Build Coastguard Worker hdr = pm4_pkt4_hdr(regindx, cnt);
487*61046927SAndroid Build Coastguard Worker }
488*61046927SAndroid Build Coastguard Worker
489*61046927SAndroid Build Coastguard Worker ASSERTED bool ret = emu_queue_push(&emu->roq, hdr);
490*61046927SAndroid Build Coastguard Worker assert(ret);
491*61046927SAndroid Build Coastguard Worker
492*61046927SAndroid Build Coastguard Worker for (unsigned i = 0; i < cnt; i++) {
493*61046927SAndroid Build Coastguard Worker ASSERTED bool ret = emu_queue_push(&emu->roq, payload[i]);
494*61046927SAndroid Build Coastguard Worker assert(ret);
495*61046927SAndroid Build Coastguard Worker }
496*61046927SAndroid Build Coastguard Worker }
497*61046927SAndroid Build Coastguard Worker
498*61046927SAndroid Build Coastguard Worker void
emu_main_prompt(struct emu * emu)499*61046927SAndroid Build Coastguard Worker emu_main_prompt(struct emu *emu)
500*61046927SAndroid Build Coastguard Worker {
501*61046927SAndroid Build Coastguard Worker if (emu->run_mode)
502*61046927SAndroid Build Coastguard Worker return;
503*61046927SAndroid Build Coastguard Worker
504*61046927SAndroid Build Coastguard Worker do {
505*61046927SAndroid Build Coastguard Worker clear_line();
506*61046927SAndroid Build Coastguard Worker printf("(s)tep, (r)un, (d)ump, (w)rite, (p)acket, (h)elp, (q)uit: ");
507*61046927SAndroid Build Coastguard Worker
508*61046927SAndroid Build Coastguard Worker int c = readchar();
509*61046927SAndroid Build Coastguard Worker
510*61046927SAndroid Build Coastguard Worker printf("%c\n", c);
511*61046927SAndroid Build Coastguard Worker
512*61046927SAndroid Build Coastguard Worker if (c == 's') {
513*61046927SAndroid Build Coastguard Worker break;
514*61046927SAndroid Build Coastguard Worker } else if (c == 'r') {
515*61046927SAndroid Build Coastguard Worker emu->run_mode = true;
516*61046927SAndroid Build Coastguard Worker break;
517*61046927SAndroid Build Coastguard Worker } else if (c == 'd') {
518*61046927SAndroid Build Coastguard Worker emu_dump_prompt(emu);
519*61046927SAndroid Build Coastguard Worker } else if (c == 'w') {
520*61046927SAndroid Build Coastguard Worker emu_write_prompt(emu);
521*61046927SAndroid Build Coastguard Worker } else if (c == 'p') {
522*61046927SAndroid Build Coastguard Worker emu_packet_prompt(emu);
523*61046927SAndroid Build Coastguard Worker } else if (c == 'h') {
524*61046927SAndroid Build Coastguard Worker printf(" (s)tep - single step to next instruction\n");
525*61046927SAndroid Build Coastguard Worker printf(" (r)un - run until next waitin\n");
526*61046927SAndroid Build Coastguard Worker printf(" (d)ump - dump memory/register menu\n");
527*61046927SAndroid Build Coastguard Worker printf(" (w)rite - write memory/register menu\n");
528*61046927SAndroid Build Coastguard Worker printf(" (p)acket - inject a pm4 packet\n");
529*61046927SAndroid Build Coastguard Worker printf(" (h)elp - show this usage message\n");
530*61046927SAndroid Build Coastguard Worker printf(" (q)uit - exit emulator\n");
531*61046927SAndroid Build Coastguard Worker } else if (c == 'q') {
532*61046927SAndroid Build Coastguard Worker printf("\n");
533*61046927SAndroid Build Coastguard Worker exit(0);
534*61046927SAndroid Build Coastguard Worker } else {
535*61046927SAndroid Build Coastguard Worker printf("invalid option: '%c'\n", c);
536*61046927SAndroid Build Coastguard Worker }
537*61046927SAndroid Build Coastguard Worker } while (true);
538*61046927SAndroid Build Coastguard Worker }
539*61046927SAndroid Build Coastguard Worker
540*61046927SAndroid Build Coastguard Worker void
emu_clear_state_change(struct emu * emu)541*61046927SAndroid Build Coastguard Worker emu_clear_state_change(struct emu *emu)
542*61046927SAndroid Build Coastguard Worker {
543*61046927SAndroid Build Coastguard Worker memset(emu->control_regs.written, 0, sizeof(emu->control_regs.written));
544*61046927SAndroid Build Coastguard Worker memset(emu->sqe_regs.written, 0, sizeof(emu->sqe_regs.written));
545*61046927SAndroid Build Coastguard Worker memset(emu->pipe_regs.written, 0, sizeof(emu->pipe_regs.written));
546*61046927SAndroid Build Coastguard Worker memset(emu->gpu_regs.written, 0, sizeof(emu->gpu_regs.written));
547*61046927SAndroid Build Coastguard Worker memset(emu->gpr_regs.written, 0, sizeof(emu->gpr_regs.written));
548*61046927SAndroid Build Coastguard Worker emu->gpumem_written = ~0;
549*61046927SAndroid Build Coastguard Worker }
550*61046927SAndroid Build Coastguard Worker
551*61046927SAndroid Build Coastguard Worker void
emu_dump_state_change(struct emu * emu)552*61046927SAndroid Build Coastguard Worker emu_dump_state_change(struct emu *emu)
553*61046927SAndroid Build Coastguard Worker {
554*61046927SAndroid Build Coastguard Worker unsigned i;
555*61046927SAndroid Build Coastguard Worker
556*61046927SAndroid Build Coastguard Worker if (emu->quiet)
557*61046927SAndroid Build Coastguard Worker return;
558*61046927SAndroid Build Coastguard Worker
559*61046927SAndroid Build Coastguard Worker /* Print the GPRs that changed: */
560*61046927SAndroid Build Coastguard Worker BITSET_FOREACH_SET (i, emu->gpr_regs.written, EMU_NUM_GPR_REGS) {
561*61046927SAndroid Build Coastguard Worker dump_gpr_register(emu, i);
562*61046927SAndroid Build Coastguard Worker }
563*61046927SAndroid Build Coastguard Worker
564*61046927SAndroid Build Coastguard Worker BITSET_FOREACH_SET (i, emu->gpu_regs.written, EMU_NUM_GPU_REGS) {
565*61046927SAndroid Build Coastguard Worker dump_gpu_register(emu, i);
566*61046927SAndroid Build Coastguard Worker }
567*61046927SAndroid Build Coastguard Worker
568*61046927SAndroid Build Coastguard Worker BITSET_FOREACH_SET (i, emu->pipe_regs.written, EMU_NUM_PIPE_REGS) {
569*61046927SAndroid Build Coastguard Worker dump_pipe_register(emu, i);
570*61046927SAndroid Build Coastguard Worker }
571*61046927SAndroid Build Coastguard Worker
572*61046927SAndroid Build Coastguard Worker BITSET_FOREACH_SET (i, emu->control_regs.written, EMU_NUM_CONTROL_REGS) {
573*61046927SAndroid Build Coastguard Worker dump_control_register(emu, i);
574*61046927SAndroid Build Coastguard Worker }
575*61046927SAndroid Build Coastguard Worker
576*61046927SAndroid Build Coastguard Worker BITSET_FOREACH_SET (i, emu->sqe_regs.written, EMU_NUM_SQE_REGS) {
577*61046927SAndroid Build Coastguard Worker dump_sqe_register(emu, i);
578*61046927SAndroid Build Coastguard Worker }
579*61046927SAndroid Build Coastguard Worker
580*61046927SAndroid Build Coastguard Worker if (emu->gpumem_written != ~0) {
581*61046927SAndroid Build Coastguard Worker dump_gpumem(emu, emu->gpumem_written);
582*61046927SAndroid Build Coastguard Worker }
583*61046927SAndroid Build Coastguard Worker }
584