1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2021 Google, Inc. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21bf215546Sopenharmony_ci * SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include <assert.h> 25bf215546Sopenharmony_ci#include <ctype.h> 26bf215546Sopenharmony_ci#include <inttypes.h> 27bf215546Sopenharmony_ci#include <stdio.h> 28bf215546Sopenharmony_ci#include <stdlib.h> 29bf215546Sopenharmony_ci#include <termios.h> 30bf215546Sopenharmony_ci#include <unistd.h> 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci#include "freedreno_pm4.h" 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci#include "emu.h" 35bf215546Sopenharmony_ci#include "util.h" 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci/* 38bf215546Sopenharmony_ci * Emulator User Interface: 39bf215546Sopenharmony_ci * 40bf215546Sopenharmony_ci * Handles the user prompts and input parsing. 41bf215546Sopenharmony_ci */ 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_cistatic void 44bf215546Sopenharmony_ciclear_line(void) 45bf215546Sopenharmony_ci{ 46bf215546Sopenharmony_ci if (!isatty(STDOUT_FILENO)) 47bf215546Sopenharmony_ci return; 48bf215546Sopenharmony_ci printf("\r \r"); 49bf215546Sopenharmony_ci} 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_cistatic int 52bf215546Sopenharmony_cireadchar(void) 53bf215546Sopenharmony_ci{ 54bf215546Sopenharmony_ci static struct termios saved_termios, unbuffered_termios; 55bf215546Sopenharmony_ci int c; 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_ci fflush(stdout); 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ci tcgetattr(STDIN_FILENO, &saved_termios); 60bf215546Sopenharmony_ci unbuffered_termios = saved_termios; 61bf215546Sopenharmony_ci cfmakeraw(&unbuffered_termios); 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci tcsetattr(STDIN_FILENO, TCSANOW, &unbuffered_termios); 64bf215546Sopenharmony_ci do { 65bf215546Sopenharmony_ci c = getchar(); 66bf215546Sopenharmony_ci } while (isspace(c)); 67bf215546Sopenharmony_ci tcsetattr(STDIN_FILENO, TCSANOW, &saved_termios); 68bf215546Sopenharmony_ci 69bf215546Sopenharmony_ci /* TODO, read from script until EOF and then read from stdin: */ 70bf215546Sopenharmony_ci if (c == -1) 71bf215546Sopenharmony_ci exit(0); 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci return c; 74bf215546Sopenharmony_ci} 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_cistatic const char * 77bf215546Sopenharmony_ciextract_string(char **buf) 78bf215546Sopenharmony_ci{ 79bf215546Sopenharmony_ci char *p = *buf; 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci /* eat any leading whitespace: */ 82bf215546Sopenharmony_ci while (*p && isspace(*p)) 83bf215546Sopenharmony_ci p++; 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_ci if (!*p) 86bf215546Sopenharmony_ci return NULL; 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_ci char *ret = p; 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci /* skip to next whitespace: */ 91bf215546Sopenharmony_ci while (*p && !isspace(*p)) 92bf215546Sopenharmony_ci p++; 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci if (*p) 95bf215546Sopenharmony_ci *p = '\0'; 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci *buf = ++p; 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci return ret; 100bf215546Sopenharmony_ci} 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_cistatic size_t 103bf215546Sopenharmony_cireadline(char **p) 104bf215546Sopenharmony_ci{ 105bf215546Sopenharmony_ci static char *buf; 106bf215546Sopenharmony_ci static size_t n; 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci ssize_t ret = getline(&buf, &n, stdin); 109bf215546Sopenharmony_ci if (ret < 0) 110bf215546Sopenharmony_ci return ret; 111bf215546Sopenharmony_ci 112bf215546Sopenharmony_ci *p = buf; 113bf215546Sopenharmony_ci return 0; 114bf215546Sopenharmony_ci} 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_cistatic ssize_t 117bf215546Sopenharmony_ciread_two_values(const char **val1, const char **val2) 118bf215546Sopenharmony_ci{ 119bf215546Sopenharmony_ci char *p; 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci ssize_t ret = readline(&p); 122bf215546Sopenharmony_ci if (ret < 0) 123bf215546Sopenharmony_ci return ret; 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci *val1 = extract_string(&p); 126bf215546Sopenharmony_ci *val2 = extract_string(&p); 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci return 0; 129bf215546Sopenharmony_ci} 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_cistatic ssize_t 132bf215546Sopenharmony_ciread_one_value(const char **val) 133bf215546Sopenharmony_ci{ 134bf215546Sopenharmony_ci char *p; 135bf215546Sopenharmony_ci 136bf215546Sopenharmony_ci ssize_t ret = readline(&p); 137bf215546Sopenharmony_ci if (ret < 0) 138bf215546Sopenharmony_ci return ret; 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ci *val = extract_string(&p); 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci return 0; 143bf215546Sopenharmony_ci} 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_cistatic void 146bf215546Sopenharmony_cidump_gpr_register(struct emu *emu, unsigned n) 147bf215546Sopenharmony_ci{ 148bf215546Sopenharmony_ci printf(" GPR: "); 149bf215546Sopenharmony_ci print_dst(n); 150bf215546Sopenharmony_ci printf(": "); 151bf215546Sopenharmony_ci if (BITSET_TEST(emu->gpr_regs.written, n)) { 152bf215546Sopenharmony_ci printdelta("%08x\n", emu->gpr_regs.val[n]); 153bf215546Sopenharmony_ci } else { 154bf215546Sopenharmony_ci printf("%08x\n", emu->gpr_regs.val[n]); 155bf215546Sopenharmony_ci } 156bf215546Sopenharmony_ci} 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_cistatic void 159bf215546Sopenharmony_cidump_gpr_registers(struct emu *emu) 160bf215546Sopenharmony_ci{ 161bf215546Sopenharmony_ci for (unsigned i = 0; i < ARRAY_SIZE(emu->gpr_regs.val); i++) { 162bf215546Sopenharmony_ci dump_gpr_register(emu, i); 163bf215546Sopenharmony_ci } 164bf215546Sopenharmony_ci} 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_cistatic void 167bf215546Sopenharmony_cidump_gpu_register(struct emu *emu, unsigned n) 168bf215546Sopenharmony_ci{ 169bf215546Sopenharmony_ci printf(" GPU: "); 170bf215546Sopenharmony_ci char *name = afuc_gpu_reg_name(n); 171bf215546Sopenharmony_ci if (name) { 172bf215546Sopenharmony_ci printf("%s", name); 173bf215546Sopenharmony_ci free(name); 174bf215546Sopenharmony_ci } else { 175bf215546Sopenharmony_ci printf("0x%04x", n); 176bf215546Sopenharmony_ci } 177bf215546Sopenharmony_ci printf(": "); 178bf215546Sopenharmony_ci if (BITSET_TEST(emu->gpu_regs.written, n)) { 179bf215546Sopenharmony_ci printdelta("%08x\n", emu->gpu_regs.val[n]); 180bf215546Sopenharmony_ci } else { 181bf215546Sopenharmony_ci printf("%08x\n", emu->gpu_regs.val[n]); 182bf215546Sopenharmony_ci } 183bf215546Sopenharmony_ci} 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_cistatic void 186bf215546Sopenharmony_cidump_pipe_register(struct emu *emu, unsigned n) 187bf215546Sopenharmony_ci{ 188bf215546Sopenharmony_ci printf(" PIPE: "); 189bf215546Sopenharmony_ci print_pipe_reg(n); 190bf215546Sopenharmony_ci printf(": "); 191bf215546Sopenharmony_ci if (BITSET_TEST(emu->pipe_regs.written, n)) { 192bf215546Sopenharmony_ci printdelta("%08x\n", emu->pipe_regs.val[n]); 193bf215546Sopenharmony_ci } else { 194bf215546Sopenharmony_ci printf("%08x\n", emu->pipe_regs.val[n]); 195bf215546Sopenharmony_ci } 196bf215546Sopenharmony_ci} 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_cistatic void 199bf215546Sopenharmony_cidump_control_register(struct emu *emu, unsigned n) 200bf215546Sopenharmony_ci{ 201bf215546Sopenharmony_ci printf(" CTRL: "); 202bf215546Sopenharmony_ci print_control_reg(n); 203bf215546Sopenharmony_ci printf(": "); 204bf215546Sopenharmony_ci if (BITSET_TEST(emu->control_regs.written, n)) { 205bf215546Sopenharmony_ci printdelta("%08x\n", emu->control_regs.val[n]); 206bf215546Sopenharmony_ci } else { 207bf215546Sopenharmony_ci printf("%08x\n", emu->control_regs.val[n]); 208bf215546Sopenharmony_ci } 209bf215546Sopenharmony_ci} 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_cistatic void 212bf215546Sopenharmony_cidump_gpumem(struct emu *emu, uintptr_t addr) 213bf215546Sopenharmony_ci{ 214bf215546Sopenharmony_ci uint32_t val = emu_mem_read_dword(emu, addr); 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci printf(" MEM: 0x%016"PRIxPTR": ", addr); 217bf215546Sopenharmony_ci if (addr == emu->gpumem_written) { 218bf215546Sopenharmony_ci printdelta("0x%08x\n", val); 219bf215546Sopenharmony_ci } else { 220bf215546Sopenharmony_ci printf("0x%08x\n", val); 221bf215546Sopenharmony_ci } 222bf215546Sopenharmony_ci} 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_cistatic void 225bf215546Sopenharmony_ciemu_write_gpr_prompt(struct emu *emu) 226bf215546Sopenharmony_ci{ 227bf215546Sopenharmony_ci clear_line(); 228bf215546Sopenharmony_ci printf(" GPR register (name or offset) and value: "); 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_ci const char *name; 231bf215546Sopenharmony_ci const char *value; 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci if (read_two_values(&name, &value)) 234bf215546Sopenharmony_ci return; 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci unsigned offset = afuc_gpr_reg(name); 237bf215546Sopenharmony_ci uint32_t val = strtoul(value, NULL, 0); 238bf215546Sopenharmony_ci 239bf215546Sopenharmony_ci emu_set_gpr_reg(emu, offset, val); 240bf215546Sopenharmony_ci} 241bf215546Sopenharmony_ci 242bf215546Sopenharmony_cistatic void 243bf215546Sopenharmony_ciemu_write_control_prompt(struct emu *emu) 244bf215546Sopenharmony_ci{ 245bf215546Sopenharmony_ci clear_line(); 246bf215546Sopenharmony_ci printf(" Control register (name or offset) and value: "); 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_ci const char *name; 249bf215546Sopenharmony_ci const char *value; 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci if (read_two_values(&name, &value)) 252bf215546Sopenharmony_ci return; 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_ci unsigned offset = afuc_control_reg(name); 255bf215546Sopenharmony_ci uint32_t val = strtoul(value, NULL, 0); 256bf215546Sopenharmony_ci 257bf215546Sopenharmony_ci emu_set_control_reg(emu, offset, val); 258bf215546Sopenharmony_ci} 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_cistatic void 261bf215546Sopenharmony_ciemu_dump_control_prompt(struct emu *emu) 262bf215546Sopenharmony_ci{ 263bf215546Sopenharmony_ci clear_line(); 264bf215546Sopenharmony_ci printf(" Control register (name or offset): "); 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci const char *name; 267bf215546Sopenharmony_ci 268bf215546Sopenharmony_ci if (read_one_value(&name)) 269bf215546Sopenharmony_ci return; 270bf215546Sopenharmony_ci 271bf215546Sopenharmony_ci printf("\n"); 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_ci unsigned offset = afuc_control_reg(name); 274bf215546Sopenharmony_ci dump_control_register(emu, offset); 275bf215546Sopenharmony_ci} 276bf215546Sopenharmony_ci 277bf215546Sopenharmony_cistatic void 278bf215546Sopenharmony_ciemu_write_gpu_prompt(struct emu *emu) 279bf215546Sopenharmony_ci{ 280bf215546Sopenharmony_ci clear_line(); 281bf215546Sopenharmony_ci printf(" GPU register (name or offset) and value: "); 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci const char *name; 284bf215546Sopenharmony_ci const char *value; 285bf215546Sopenharmony_ci 286bf215546Sopenharmony_ci if (read_two_values(&name, &value)) 287bf215546Sopenharmony_ci return; 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_ci unsigned offset = afuc_gpu_reg(name); 290bf215546Sopenharmony_ci uint32_t val = strtoul(value, NULL, 0); 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci emu_set_gpu_reg(emu, offset, val); 293bf215546Sopenharmony_ci} 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_cistatic void 296bf215546Sopenharmony_ciemu_dump_gpu_prompt(struct emu *emu) 297bf215546Sopenharmony_ci{ 298bf215546Sopenharmony_ci clear_line(); 299bf215546Sopenharmony_ci printf(" GPU register (name or offset): "); 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_ci const char *name; 302bf215546Sopenharmony_ci 303bf215546Sopenharmony_ci if (read_one_value(&name)) 304bf215546Sopenharmony_ci return; 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ci printf("\n"); 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci unsigned offset = afuc_gpu_reg(name); 309bf215546Sopenharmony_ci dump_gpu_register(emu, offset); 310bf215546Sopenharmony_ci} 311bf215546Sopenharmony_ci 312bf215546Sopenharmony_cistatic void 313bf215546Sopenharmony_ciemu_write_mem_prompt(struct emu *emu) 314bf215546Sopenharmony_ci{ 315bf215546Sopenharmony_ci clear_line(); 316bf215546Sopenharmony_ci printf(" GPU memory offset and value: "); 317bf215546Sopenharmony_ci 318bf215546Sopenharmony_ci const char *offset; 319bf215546Sopenharmony_ci const char *value; 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci if (read_two_values(&offset, &value)) 322bf215546Sopenharmony_ci return; 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_ci uintptr_t addr = strtoull(offset, NULL, 0); 325bf215546Sopenharmony_ci uint32_t val = strtoul(value, NULL, 0); 326bf215546Sopenharmony_ci 327bf215546Sopenharmony_ci emu_mem_write_dword(emu, addr, val); 328bf215546Sopenharmony_ci} 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_cistatic void 331bf215546Sopenharmony_ciemu_dump_mem_prompt(struct emu *emu) 332bf215546Sopenharmony_ci{ 333bf215546Sopenharmony_ci clear_line(); 334bf215546Sopenharmony_ci printf(" GPU memory offset: "); 335bf215546Sopenharmony_ci 336bf215546Sopenharmony_ci const char *offset; 337bf215546Sopenharmony_ci 338bf215546Sopenharmony_ci if (read_one_value(&offset)) 339bf215546Sopenharmony_ci return; 340bf215546Sopenharmony_ci 341bf215546Sopenharmony_ci printf("\n"); 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_ci uintptr_t addr = strtoull(offset, NULL, 0); 344bf215546Sopenharmony_ci dump_gpumem(emu, addr); 345bf215546Sopenharmony_ci} 346bf215546Sopenharmony_ci 347bf215546Sopenharmony_cistatic void 348bf215546Sopenharmony_ciemu_dump_prompt(struct emu *emu) 349bf215546Sopenharmony_ci{ 350bf215546Sopenharmony_ci do { 351bf215546Sopenharmony_ci clear_line(); 352bf215546Sopenharmony_ci printf(" dump: GPR (r)egisters, (c)ontrol register, (g)pu register, (m)emory: "); 353bf215546Sopenharmony_ci 354bf215546Sopenharmony_ci int c = readchar(); 355bf215546Sopenharmony_ci printf("%c\n", c); 356bf215546Sopenharmony_ci 357bf215546Sopenharmony_ci if (c == 'r') { 358bf215546Sopenharmony_ci /* Since there aren't too many GPR registers, just dump 359bf215546Sopenharmony_ci * them all: 360bf215546Sopenharmony_ci */ 361bf215546Sopenharmony_ci dump_gpr_registers(emu); 362bf215546Sopenharmony_ci break; 363bf215546Sopenharmony_ci } else if (c == 'c') { 364bf215546Sopenharmony_ci emu_dump_control_prompt(emu); 365bf215546Sopenharmony_ci break; 366bf215546Sopenharmony_ci } else if (c == 'g') { 367bf215546Sopenharmony_ci emu_dump_gpu_prompt(emu); 368bf215546Sopenharmony_ci break; 369bf215546Sopenharmony_ci } else if (c == 'm') { 370bf215546Sopenharmony_ci emu_dump_mem_prompt(emu); 371bf215546Sopenharmony_ci break; 372bf215546Sopenharmony_ci } else { 373bf215546Sopenharmony_ci printf("invalid option: '%c'\n", c); 374bf215546Sopenharmony_ci break; 375bf215546Sopenharmony_ci } 376bf215546Sopenharmony_ci } while (true); 377bf215546Sopenharmony_ci} 378bf215546Sopenharmony_ci 379bf215546Sopenharmony_cistatic void 380bf215546Sopenharmony_ciemu_write_prompt(struct emu *emu) 381bf215546Sopenharmony_ci{ 382bf215546Sopenharmony_ci do { 383bf215546Sopenharmony_ci clear_line(); 384bf215546Sopenharmony_ci printf(" write: GPR (r)egister, (c)ontrol register, (g)pu register, (m)emory: "); 385bf215546Sopenharmony_ci 386bf215546Sopenharmony_ci int c = readchar(); 387bf215546Sopenharmony_ci printf("%c\n", c); 388bf215546Sopenharmony_ci 389bf215546Sopenharmony_ci if (c == 'r') { 390bf215546Sopenharmony_ci emu_write_gpr_prompt(emu); 391bf215546Sopenharmony_ci break; 392bf215546Sopenharmony_ci } else if (c == 'c') { 393bf215546Sopenharmony_ci emu_write_control_prompt(emu); 394bf215546Sopenharmony_ci break; 395bf215546Sopenharmony_ci } else if (c == 'g') { 396bf215546Sopenharmony_ci emu_write_gpu_prompt(emu); 397bf215546Sopenharmony_ci break; 398bf215546Sopenharmony_ci } else if (c == 'm') { 399bf215546Sopenharmony_ci emu_write_mem_prompt(emu); 400bf215546Sopenharmony_ci break; 401bf215546Sopenharmony_ci } else { 402bf215546Sopenharmony_ci printf("invalid option: '%c'\n", c); 403bf215546Sopenharmony_ci break; 404bf215546Sopenharmony_ci } 405bf215546Sopenharmony_ci } while (true); 406bf215546Sopenharmony_ci} 407bf215546Sopenharmony_ci 408bf215546Sopenharmony_cistatic void 409bf215546Sopenharmony_ciemu_packet_prompt(struct emu *emu) 410bf215546Sopenharmony_ci{ 411bf215546Sopenharmony_ci clear_line(); 412bf215546Sopenharmony_ci printf(" Enter packet (opc or register name), followed by payload: "); 413bf215546Sopenharmony_ci fflush(stdout); 414bf215546Sopenharmony_ci 415bf215546Sopenharmony_ci char *p; 416bf215546Sopenharmony_ci if (readline(&p) < 0) 417bf215546Sopenharmony_ci return; 418bf215546Sopenharmony_ci 419bf215546Sopenharmony_ci printf("\n"); 420bf215546Sopenharmony_ci 421bf215546Sopenharmony_ci const char *name = extract_string(&p); 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci /* Read the payload, so we can know the size to generate correct header: */ 424bf215546Sopenharmony_ci uint32_t payload[0x7f]; 425bf215546Sopenharmony_ci unsigned cnt = 0; 426bf215546Sopenharmony_ci 427bf215546Sopenharmony_ci do { 428bf215546Sopenharmony_ci const char *val = extract_string(&p); 429bf215546Sopenharmony_ci if (!val) 430bf215546Sopenharmony_ci break; 431bf215546Sopenharmony_ci 432bf215546Sopenharmony_ci assert(cnt < ARRAY_SIZE(payload)); 433bf215546Sopenharmony_ci payload[cnt++] = strtoul(val, NULL, 0); 434bf215546Sopenharmony_ci } while (true); 435bf215546Sopenharmony_ci 436bf215546Sopenharmony_ci uint32_t hdr; 437bf215546Sopenharmony_ci if (afuc_pm4_id(name) >= 0) { 438bf215546Sopenharmony_ci unsigned opcode = afuc_pm4_id(name); 439bf215546Sopenharmony_ci hdr = pm4_pkt7_hdr(opcode, cnt); 440bf215546Sopenharmony_ci } else { 441bf215546Sopenharmony_ci unsigned regindx = afuc_gpu_reg(name); 442bf215546Sopenharmony_ci hdr = pm4_pkt4_hdr(regindx, cnt); 443bf215546Sopenharmony_ci } 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_ci ASSERTED bool ret = emu_queue_push(&emu->roq, hdr); 446bf215546Sopenharmony_ci assert(ret); 447bf215546Sopenharmony_ci 448bf215546Sopenharmony_ci for (unsigned i = 0; i < cnt; i++) { 449bf215546Sopenharmony_ci ASSERTED bool ret = emu_queue_push(&emu->roq, payload[i]); 450bf215546Sopenharmony_ci assert(ret); 451bf215546Sopenharmony_ci } 452bf215546Sopenharmony_ci} 453bf215546Sopenharmony_ci 454bf215546Sopenharmony_civoid 455bf215546Sopenharmony_ciemu_main_prompt(struct emu *emu) 456bf215546Sopenharmony_ci{ 457bf215546Sopenharmony_ci if (emu->run_mode) 458bf215546Sopenharmony_ci return; 459bf215546Sopenharmony_ci 460bf215546Sopenharmony_ci do { 461bf215546Sopenharmony_ci clear_line(); 462bf215546Sopenharmony_ci printf("(s)tep, (r)un, (d)ump, (w)rite, (p)acket, (h)elp, (q)uit: "); 463bf215546Sopenharmony_ci 464bf215546Sopenharmony_ci int c = readchar(); 465bf215546Sopenharmony_ci 466bf215546Sopenharmony_ci printf("%c\n", c); 467bf215546Sopenharmony_ci 468bf215546Sopenharmony_ci if (c == 's') { 469bf215546Sopenharmony_ci break; 470bf215546Sopenharmony_ci } else if (c == 'r') { 471bf215546Sopenharmony_ci emu->run_mode = true; 472bf215546Sopenharmony_ci break; 473bf215546Sopenharmony_ci } else if (c == 'd') { 474bf215546Sopenharmony_ci emu_dump_prompt(emu); 475bf215546Sopenharmony_ci } else if (c == 'w') { 476bf215546Sopenharmony_ci emu_write_prompt(emu); 477bf215546Sopenharmony_ci } else if (c == 'p') { 478bf215546Sopenharmony_ci emu_packet_prompt(emu); 479bf215546Sopenharmony_ci } else if (c == 'h') { 480bf215546Sopenharmony_ci printf(" (s)tep - single step to next instruction\n"); 481bf215546Sopenharmony_ci printf(" (r)un - run until next waitin\n"); 482bf215546Sopenharmony_ci printf(" (d)ump - dump memory/register menu\n"); 483bf215546Sopenharmony_ci printf(" (w)rite - write memory/register menu\n"); 484bf215546Sopenharmony_ci printf(" (p)acket - inject a pm4 packet\n"); 485bf215546Sopenharmony_ci printf(" (h)elp - show this usage message\n"); 486bf215546Sopenharmony_ci printf(" (q)uit - exit emulator\n"); 487bf215546Sopenharmony_ci } else if (c == 'q') { 488bf215546Sopenharmony_ci printf("\n"); 489bf215546Sopenharmony_ci exit(0); 490bf215546Sopenharmony_ci } else { 491bf215546Sopenharmony_ci printf("invalid option: '%c'\n", c); 492bf215546Sopenharmony_ci } 493bf215546Sopenharmony_ci } while (true); 494bf215546Sopenharmony_ci} 495bf215546Sopenharmony_ci 496bf215546Sopenharmony_civoid 497bf215546Sopenharmony_ciemu_clear_state_change(struct emu *emu) 498bf215546Sopenharmony_ci{ 499bf215546Sopenharmony_ci memset(emu->control_regs.written, 0, sizeof(emu->control_regs.written)); 500bf215546Sopenharmony_ci memset(emu->pipe_regs.written, 0, sizeof(emu->pipe_regs.written)); 501bf215546Sopenharmony_ci memset(emu->gpu_regs.written, 0, sizeof(emu->gpu_regs.written)); 502bf215546Sopenharmony_ci memset(emu->gpr_regs.written, 0, sizeof(emu->gpr_regs.written)); 503bf215546Sopenharmony_ci emu->gpumem_written = ~0; 504bf215546Sopenharmony_ci} 505bf215546Sopenharmony_ci 506bf215546Sopenharmony_civoid 507bf215546Sopenharmony_ciemu_dump_state_change(struct emu *emu) 508bf215546Sopenharmony_ci{ 509bf215546Sopenharmony_ci unsigned i; 510bf215546Sopenharmony_ci 511bf215546Sopenharmony_ci if (emu->quiet) 512bf215546Sopenharmony_ci return; 513bf215546Sopenharmony_ci 514bf215546Sopenharmony_ci /* Print the GPRs that changed: */ 515bf215546Sopenharmony_ci BITSET_FOREACH_SET (i, emu->gpr_regs.written, EMU_NUM_GPR_REGS) { 516bf215546Sopenharmony_ci dump_gpr_register(emu, i); 517bf215546Sopenharmony_ci } 518bf215546Sopenharmony_ci 519bf215546Sopenharmony_ci BITSET_FOREACH_SET (i, emu->gpu_regs.written, EMU_NUM_GPU_REGS) { 520bf215546Sopenharmony_ci dump_gpu_register(emu, i); 521bf215546Sopenharmony_ci } 522bf215546Sopenharmony_ci 523bf215546Sopenharmony_ci BITSET_FOREACH_SET (i, emu->pipe_regs.written, EMU_NUM_PIPE_REGS) { 524bf215546Sopenharmony_ci dump_pipe_register(emu, i); 525bf215546Sopenharmony_ci } 526bf215546Sopenharmony_ci 527bf215546Sopenharmony_ci BITSET_FOREACH_SET (i, emu->control_regs.written, EMU_NUM_CONTROL_REGS) { 528bf215546Sopenharmony_ci dump_control_register(emu, i); 529bf215546Sopenharmony_ci } 530bf215546Sopenharmony_ci 531bf215546Sopenharmony_ci if (emu->gpumem_written != ~0) { 532bf215546Sopenharmony_ci dump_gpumem(emu, emu->gpumem_written); 533bf215546Sopenharmony_ci } 534bf215546Sopenharmony_ci} 535