17ec681f3Smrg/* 27ec681f3Smrg * Copyright © 2021 Google, Inc. 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice (including the next 127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg * Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 207ec681f3Smrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 217ec681f3Smrg * SOFTWARE. 227ec681f3Smrg */ 237ec681f3Smrg 247ec681f3Smrg#include <assert.h> 257ec681f3Smrg#include <ctype.h> 267ec681f3Smrg#include <inttypes.h> 277ec681f3Smrg#include <stdio.h> 287ec681f3Smrg#include <stdlib.h> 297ec681f3Smrg#include <termios.h> 307ec681f3Smrg#include <unistd.h> 317ec681f3Smrg 327ec681f3Smrg#include "freedreno_pm4.h" 337ec681f3Smrg 347ec681f3Smrg#include "emu.h" 357ec681f3Smrg#include "util.h" 367ec681f3Smrg 377ec681f3Smrg/* 387ec681f3Smrg * Emulator User Interface: 397ec681f3Smrg * 407ec681f3Smrg * Handles the user prompts and input parsing. 417ec681f3Smrg */ 427ec681f3Smrg 437ec681f3Smrgstatic void 447ec681f3Smrgclear_line(void) 457ec681f3Smrg{ 467ec681f3Smrg if (!isatty(STDOUT_FILENO)) 477ec681f3Smrg return; 487ec681f3Smrg printf("\r \r"); 497ec681f3Smrg} 507ec681f3Smrg 517ec681f3Smrgstatic int 527ec681f3Smrgreadchar(void) 537ec681f3Smrg{ 547ec681f3Smrg static struct termios saved_termios, unbuffered_termios; 557ec681f3Smrg int c; 567ec681f3Smrg 577ec681f3Smrg fflush(stdout); 587ec681f3Smrg 597ec681f3Smrg tcgetattr(STDIN_FILENO, &saved_termios); 607ec681f3Smrg unbuffered_termios = saved_termios; 617ec681f3Smrg cfmakeraw(&unbuffered_termios); 627ec681f3Smrg 637ec681f3Smrg tcsetattr(STDIN_FILENO, TCSANOW, &unbuffered_termios); 647ec681f3Smrg do { 657ec681f3Smrg c = getchar(); 667ec681f3Smrg } while (isspace(c)); 677ec681f3Smrg tcsetattr(STDIN_FILENO, TCSANOW, &saved_termios); 687ec681f3Smrg 697ec681f3Smrg /* TODO, read from script until EOF and then read from stdin: */ 707ec681f3Smrg if (c == -1) 717ec681f3Smrg exit(0); 727ec681f3Smrg 737ec681f3Smrg return c; 747ec681f3Smrg} 757ec681f3Smrg 767ec681f3Smrgstatic const char * 777ec681f3Smrgextract_string(char **buf) 787ec681f3Smrg{ 797ec681f3Smrg char *p = *buf; 807ec681f3Smrg 817ec681f3Smrg /* eat any leading whitespace: */ 827ec681f3Smrg while (*p && isspace(*p)) 837ec681f3Smrg p++; 847ec681f3Smrg 857ec681f3Smrg if (!*p) 867ec681f3Smrg return NULL; 877ec681f3Smrg 887ec681f3Smrg char *ret = p; 897ec681f3Smrg 907ec681f3Smrg /* skip to next whitespace: */ 917ec681f3Smrg while (*p && !isspace(*p)) 927ec681f3Smrg p++; 937ec681f3Smrg 947ec681f3Smrg if (*p) 957ec681f3Smrg *p = '\0'; 967ec681f3Smrg 977ec681f3Smrg *buf = ++p; 987ec681f3Smrg 997ec681f3Smrg return ret; 1007ec681f3Smrg} 1017ec681f3Smrg 1027ec681f3Smrgstatic size_t 1037ec681f3Smrgreadline(char **p) 1047ec681f3Smrg{ 1057ec681f3Smrg static char *buf; 1067ec681f3Smrg static size_t n; 1077ec681f3Smrg 1087ec681f3Smrg ssize_t ret = getline(&buf, &n, stdin); 1097ec681f3Smrg if (ret < 0) 1107ec681f3Smrg return ret; 1117ec681f3Smrg 1127ec681f3Smrg *p = buf; 1137ec681f3Smrg return 0; 1147ec681f3Smrg} 1157ec681f3Smrg 1167ec681f3Smrgstatic ssize_t 1177ec681f3Smrgread_two_values(const char **val1, const char **val2) 1187ec681f3Smrg{ 1197ec681f3Smrg char *p; 1207ec681f3Smrg 1217ec681f3Smrg ssize_t ret = readline(&p); 1227ec681f3Smrg if (ret < 0) 1237ec681f3Smrg return ret; 1247ec681f3Smrg 1257ec681f3Smrg *val1 = extract_string(&p); 1267ec681f3Smrg *val2 = extract_string(&p); 1277ec681f3Smrg 1287ec681f3Smrg return 0; 1297ec681f3Smrg} 1307ec681f3Smrg 1317ec681f3Smrgstatic ssize_t 1327ec681f3Smrgread_one_value(const char **val) 1337ec681f3Smrg{ 1347ec681f3Smrg char *p; 1357ec681f3Smrg 1367ec681f3Smrg ssize_t ret = readline(&p); 1377ec681f3Smrg if (ret < 0) 1387ec681f3Smrg return ret; 1397ec681f3Smrg 1407ec681f3Smrg *val = extract_string(&p); 1417ec681f3Smrg 1427ec681f3Smrg return 0; 1437ec681f3Smrg} 1447ec681f3Smrg 1457ec681f3Smrgstatic void 1467ec681f3Smrgdump_gpr_register(struct emu *emu, unsigned n) 1477ec681f3Smrg{ 1487ec681f3Smrg printf(" GPR: "); 1497ec681f3Smrg print_dst(n); 1507ec681f3Smrg printf(": "); 1517ec681f3Smrg if (BITSET_TEST(emu->gpr_regs.written, n)) { 1527ec681f3Smrg printdelta("%08x\n", emu->gpr_regs.val[n]); 1537ec681f3Smrg } else { 1547ec681f3Smrg printf("%08x\n", emu->gpr_regs.val[n]); 1557ec681f3Smrg } 1567ec681f3Smrg} 1577ec681f3Smrg 1587ec681f3Smrgstatic void 1597ec681f3Smrgdump_gpr_registers(struct emu *emu) 1607ec681f3Smrg{ 1617ec681f3Smrg for (unsigned i = 0; i < ARRAY_SIZE(emu->gpr_regs.val); i++) { 1627ec681f3Smrg dump_gpr_register(emu, i); 1637ec681f3Smrg } 1647ec681f3Smrg} 1657ec681f3Smrg 1667ec681f3Smrgstatic void 1677ec681f3Smrgdump_gpu_register(struct emu *emu, unsigned n) 1687ec681f3Smrg{ 1697ec681f3Smrg printf(" GPU: "); 1707ec681f3Smrg char *name = afuc_gpu_reg_name(n); 1717ec681f3Smrg if (name) { 1727ec681f3Smrg printf("%s", name); 1737ec681f3Smrg free(name); 1747ec681f3Smrg } else { 1757ec681f3Smrg printf("0x%04x", n); 1767ec681f3Smrg } 1777ec681f3Smrg printf(": "); 1787ec681f3Smrg if (BITSET_TEST(emu->gpu_regs.written, n)) { 1797ec681f3Smrg printdelta("%08x\n", emu->gpu_regs.val[n]); 1807ec681f3Smrg } else { 1817ec681f3Smrg printf("%08x\n", emu->gpu_regs.val[n]); 1827ec681f3Smrg } 1837ec681f3Smrg} 1847ec681f3Smrg 1857ec681f3Smrgstatic void 1867ec681f3Smrgdump_pipe_register(struct emu *emu, unsigned n) 1877ec681f3Smrg{ 1887ec681f3Smrg printf(" PIPE: "); 1897ec681f3Smrg print_pipe_reg(n); 1907ec681f3Smrg printf(": "); 1917ec681f3Smrg if (BITSET_TEST(emu->pipe_regs.written, n)) { 1927ec681f3Smrg printdelta("%08x\n", emu->pipe_regs.val[n]); 1937ec681f3Smrg } else { 1947ec681f3Smrg printf("%08x\n", emu->pipe_regs.val[n]); 1957ec681f3Smrg } 1967ec681f3Smrg} 1977ec681f3Smrg 1987ec681f3Smrgstatic void 1997ec681f3Smrgdump_control_register(struct emu *emu, unsigned n) 2007ec681f3Smrg{ 2017ec681f3Smrg printf(" CTRL: "); 2027ec681f3Smrg print_control_reg(n); 2037ec681f3Smrg printf(": "); 2047ec681f3Smrg if (BITSET_TEST(emu->control_regs.written, n)) { 2057ec681f3Smrg printdelta("%08x\n", emu->control_regs.val[n]); 2067ec681f3Smrg } else { 2077ec681f3Smrg printf("%08x\n", emu->control_regs.val[n]); 2087ec681f3Smrg } 2097ec681f3Smrg} 2107ec681f3Smrg 2117ec681f3Smrgstatic void 2127ec681f3Smrgdump_gpumem(struct emu *emu, uintptr_t addr) 2137ec681f3Smrg{ 2147ec681f3Smrg uint32_t val = emu_mem_read_dword(emu, addr); 2157ec681f3Smrg 2167ec681f3Smrg printf(" MEM: 0x%016"PRIxPTR": ", addr); 2177ec681f3Smrg if (addr == emu->gpumem_written) { 2187ec681f3Smrg printdelta("0x%08x\n", val); 2197ec681f3Smrg } else { 2207ec681f3Smrg printf("0x%08x\n", val); 2217ec681f3Smrg } 2227ec681f3Smrg} 2237ec681f3Smrg 2247ec681f3Smrgstatic void 2257ec681f3Smrgemu_write_gpr_prompt(struct emu *emu) 2267ec681f3Smrg{ 2277ec681f3Smrg clear_line(); 2287ec681f3Smrg printf(" GPR register (name or offset) and value: "); 2297ec681f3Smrg 2307ec681f3Smrg const char *name; 2317ec681f3Smrg const char *value; 2327ec681f3Smrg 2337ec681f3Smrg if (read_two_values(&name, &value)) 2347ec681f3Smrg return; 2357ec681f3Smrg 2367ec681f3Smrg unsigned offset = afuc_gpr_reg(name); 2377ec681f3Smrg uint32_t val = strtoul(value, NULL, 0); 2387ec681f3Smrg 2397ec681f3Smrg emu_set_gpr_reg(emu, offset, val); 2407ec681f3Smrg} 2417ec681f3Smrg 2427ec681f3Smrgstatic void 2437ec681f3Smrgemu_write_control_prompt(struct emu *emu) 2447ec681f3Smrg{ 2457ec681f3Smrg clear_line(); 2467ec681f3Smrg printf(" Control register (name or offset) and value: "); 2477ec681f3Smrg 2487ec681f3Smrg const char *name; 2497ec681f3Smrg const char *value; 2507ec681f3Smrg 2517ec681f3Smrg if (read_two_values(&name, &value)) 2527ec681f3Smrg return; 2537ec681f3Smrg 2547ec681f3Smrg unsigned offset = afuc_control_reg(name); 2557ec681f3Smrg uint32_t val = strtoul(value, NULL, 0); 2567ec681f3Smrg 2577ec681f3Smrg emu_set_control_reg(emu, offset, val); 2587ec681f3Smrg} 2597ec681f3Smrg 2607ec681f3Smrgstatic void 2617ec681f3Smrgemu_dump_control_prompt(struct emu *emu) 2627ec681f3Smrg{ 2637ec681f3Smrg clear_line(); 2647ec681f3Smrg printf(" Control register (name or offset): "); 2657ec681f3Smrg 2667ec681f3Smrg const char *name; 2677ec681f3Smrg 2687ec681f3Smrg if (read_one_value(&name)) 2697ec681f3Smrg return; 2707ec681f3Smrg 2717ec681f3Smrg printf("\n"); 2727ec681f3Smrg 2737ec681f3Smrg unsigned offset = afuc_control_reg(name); 2747ec681f3Smrg dump_control_register(emu, offset); 2757ec681f3Smrg} 2767ec681f3Smrg 2777ec681f3Smrgstatic void 2787ec681f3Smrgemu_write_gpu_prompt(struct emu *emu) 2797ec681f3Smrg{ 2807ec681f3Smrg clear_line(); 2817ec681f3Smrg printf(" GPU register (name or offset) and value: "); 2827ec681f3Smrg 2837ec681f3Smrg const char *name; 2847ec681f3Smrg const char *value; 2857ec681f3Smrg 2867ec681f3Smrg if (read_two_values(&name, &value)) 2877ec681f3Smrg return; 2887ec681f3Smrg 2897ec681f3Smrg unsigned offset = afuc_gpu_reg(name); 2907ec681f3Smrg uint32_t val = strtoul(value, NULL, 0); 2917ec681f3Smrg 2927ec681f3Smrg emu_set_gpu_reg(emu, offset, val); 2937ec681f3Smrg} 2947ec681f3Smrg 2957ec681f3Smrgstatic void 2967ec681f3Smrgemu_dump_gpu_prompt(struct emu *emu) 2977ec681f3Smrg{ 2987ec681f3Smrg clear_line(); 2997ec681f3Smrg printf(" GPU register (name or offset): "); 3007ec681f3Smrg 3017ec681f3Smrg const char *name; 3027ec681f3Smrg 3037ec681f3Smrg if (read_one_value(&name)) 3047ec681f3Smrg return; 3057ec681f3Smrg 3067ec681f3Smrg printf("\n"); 3077ec681f3Smrg 3087ec681f3Smrg unsigned offset = afuc_gpu_reg(name); 3097ec681f3Smrg dump_gpu_register(emu, offset); 3107ec681f3Smrg} 3117ec681f3Smrg 3127ec681f3Smrgstatic void 3137ec681f3Smrgemu_write_mem_prompt(struct emu *emu) 3147ec681f3Smrg{ 3157ec681f3Smrg clear_line(); 3167ec681f3Smrg printf(" GPU memory offset and value: "); 3177ec681f3Smrg 3187ec681f3Smrg const char *offset; 3197ec681f3Smrg const char *value; 3207ec681f3Smrg 3217ec681f3Smrg if (read_two_values(&offset, &value)) 3227ec681f3Smrg return; 3237ec681f3Smrg 3247ec681f3Smrg uintptr_t addr = strtoull(offset, NULL, 0); 3257ec681f3Smrg uint32_t val = strtoul(value, NULL, 0); 3267ec681f3Smrg 3277ec681f3Smrg emu_mem_write_dword(emu, addr, val); 3287ec681f3Smrg} 3297ec681f3Smrg 3307ec681f3Smrgstatic void 3317ec681f3Smrgemu_dump_mem_prompt(struct emu *emu) 3327ec681f3Smrg{ 3337ec681f3Smrg clear_line(); 3347ec681f3Smrg printf(" GPU memory offset: "); 3357ec681f3Smrg 3367ec681f3Smrg const char *offset; 3377ec681f3Smrg 3387ec681f3Smrg if (read_one_value(&offset)) 3397ec681f3Smrg return; 3407ec681f3Smrg 3417ec681f3Smrg printf("\n"); 3427ec681f3Smrg 3437ec681f3Smrg uintptr_t addr = strtoull(offset, NULL, 0); 3447ec681f3Smrg dump_gpumem(emu, addr); 3457ec681f3Smrg} 3467ec681f3Smrg 3477ec681f3Smrgstatic void 3487ec681f3Smrgemu_dump_prompt(struct emu *emu) 3497ec681f3Smrg{ 3507ec681f3Smrg do { 3517ec681f3Smrg clear_line(); 3527ec681f3Smrg printf(" dump: GPR (r)egisters, (c)ontrol register, (g)pu register, (m)emory: "); 3537ec681f3Smrg 3547ec681f3Smrg int c = readchar(); 3557ec681f3Smrg printf("%c\n", c); 3567ec681f3Smrg 3577ec681f3Smrg if (c == 'r') { 3587ec681f3Smrg /* Since there aren't too many GPR registers, just dump 3597ec681f3Smrg * them all: 3607ec681f3Smrg */ 3617ec681f3Smrg dump_gpr_registers(emu); 3627ec681f3Smrg break; 3637ec681f3Smrg } else if (c == 'c') { 3647ec681f3Smrg emu_dump_control_prompt(emu); 3657ec681f3Smrg break; 3667ec681f3Smrg } else if (c == 'g') { 3677ec681f3Smrg emu_dump_gpu_prompt(emu); 3687ec681f3Smrg break; 3697ec681f3Smrg } else if (c == 'm') { 3707ec681f3Smrg emu_dump_mem_prompt(emu); 3717ec681f3Smrg break; 3727ec681f3Smrg } else { 3737ec681f3Smrg printf("invalid option: '%c'\n", c); 3747ec681f3Smrg break; 3757ec681f3Smrg } 3767ec681f3Smrg } while (true); 3777ec681f3Smrg} 3787ec681f3Smrg 3797ec681f3Smrgstatic void 3807ec681f3Smrgemu_write_prompt(struct emu *emu) 3817ec681f3Smrg{ 3827ec681f3Smrg do { 3837ec681f3Smrg clear_line(); 3847ec681f3Smrg printf(" write: GPR (r)egister, (c)ontrol register, (g)pu register, (m)emory: "); 3857ec681f3Smrg 3867ec681f3Smrg int c = readchar(); 3877ec681f3Smrg printf("%c\n", c); 3887ec681f3Smrg 3897ec681f3Smrg if (c == 'r') { 3907ec681f3Smrg emu_write_gpr_prompt(emu); 3917ec681f3Smrg break; 3927ec681f3Smrg } else if (c == 'c') { 3937ec681f3Smrg emu_write_control_prompt(emu); 3947ec681f3Smrg break; 3957ec681f3Smrg } else if (c == 'g') { 3967ec681f3Smrg emu_write_gpu_prompt(emu); 3977ec681f3Smrg break; 3987ec681f3Smrg } else if (c == 'm') { 3997ec681f3Smrg emu_write_mem_prompt(emu); 4007ec681f3Smrg break; 4017ec681f3Smrg } else { 4027ec681f3Smrg printf("invalid option: '%c'\n", c); 4037ec681f3Smrg break; 4047ec681f3Smrg } 4057ec681f3Smrg } while (true); 4067ec681f3Smrg} 4077ec681f3Smrg 4087ec681f3Smrgstatic void 4097ec681f3Smrgemu_packet_prompt(struct emu *emu) 4107ec681f3Smrg{ 4117ec681f3Smrg clear_line(); 4127ec681f3Smrg printf(" Enter packet (opc or register name), followed by payload: "); 4137ec681f3Smrg fflush(stdout); 4147ec681f3Smrg 4157ec681f3Smrg char *p; 4167ec681f3Smrg if (readline(&p) < 0) 4177ec681f3Smrg return; 4187ec681f3Smrg 4197ec681f3Smrg printf("\n"); 4207ec681f3Smrg 4217ec681f3Smrg const char *name = extract_string(&p); 4227ec681f3Smrg 4237ec681f3Smrg /* Read the payload, so we can know the size to generate correct header: */ 4247ec681f3Smrg uint32_t payload[0x7f]; 4257ec681f3Smrg unsigned cnt = 0; 4267ec681f3Smrg 4277ec681f3Smrg do { 4287ec681f3Smrg const char *val = extract_string(&p); 4297ec681f3Smrg if (!val) 4307ec681f3Smrg break; 4317ec681f3Smrg 4327ec681f3Smrg assert(cnt < ARRAY_SIZE(payload)); 4337ec681f3Smrg payload[cnt++] = strtoul(val, NULL, 0); 4347ec681f3Smrg } while (true); 4357ec681f3Smrg 4367ec681f3Smrg uint32_t hdr; 4377ec681f3Smrg if (afuc_pm4_id(name) >= 0) { 4387ec681f3Smrg unsigned opcode = afuc_pm4_id(name); 4397ec681f3Smrg hdr = pm4_pkt7_hdr(opcode, cnt); 4407ec681f3Smrg } else { 4417ec681f3Smrg unsigned regindx = afuc_gpu_reg(name); 4427ec681f3Smrg hdr = pm4_pkt4_hdr(regindx, cnt); 4437ec681f3Smrg } 4447ec681f3Smrg 4457ec681f3Smrg ASSERTED bool ret = emu_queue_push(&emu->roq, hdr); 4467ec681f3Smrg assert(ret); 4477ec681f3Smrg 4487ec681f3Smrg for (unsigned i = 0; i < cnt; i++) { 4497ec681f3Smrg ASSERTED bool ret = emu_queue_push(&emu->roq, payload[i]); 4507ec681f3Smrg assert(ret); 4517ec681f3Smrg } 4527ec681f3Smrg} 4537ec681f3Smrg 4547ec681f3Smrgvoid 4557ec681f3Smrgemu_main_prompt(struct emu *emu) 4567ec681f3Smrg{ 4577ec681f3Smrg if (emu->run_mode) 4587ec681f3Smrg return; 4597ec681f3Smrg 4607ec681f3Smrg do { 4617ec681f3Smrg clear_line(); 4627ec681f3Smrg printf("(s)tep, (r)un, (d)ump, (w)rite, (p)acket, (h)elp, (q)uit: "); 4637ec681f3Smrg 4647ec681f3Smrg int c = readchar(); 4657ec681f3Smrg 4667ec681f3Smrg printf("%c\n", c); 4677ec681f3Smrg 4687ec681f3Smrg if (c == 's') { 4697ec681f3Smrg break; 4707ec681f3Smrg } else if (c == 'r') { 4717ec681f3Smrg emu->run_mode = true; 4727ec681f3Smrg break; 4737ec681f3Smrg } else if (c == 'd') { 4747ec681f3Smrg emu_dump_prompt(emu); 4757ec681f3Smrg } else if (c == 'w') { 4767ec681f3Smrg emu_write_prompt(emu); 4777ec681f3Smrg } else if (c == 'p') { 4787ec681f3Smrg emu_packet_prompt(emu); 4797ec681f3Smrg } else if (c == 'h') { 4807ec681f3Smrg printf(" (s)tep - single step to next instruction\n"); 4817ec681f3Smrg printf(" (r)un - run until next waitin\n"); 4827ec681f3Smrg printf(" (d)ump - dump memory/register menu\n"); 4837ec681f3Smrg printf(" (w)rite - write memory/register menu\n"); 4847ec681f3Smrg printf(" (p)acket - inject a pm4 packet\n"); 4857ec681f3Smrg printf(" (h)elp - show this usage message\n"); 4867ec681f3Smrg printf(" (q)uit - exit emulator\n"); 4877ec681f3Smrg } else if (c == 'q') { 4887ec681f3Smrg printf("\n"); 4897ec681f3Smrg exit(0); 4907ec681f3Smrg } else { 4917ec681f3Smrg printf("invalid option: '%c'\n", c); 4927ec681f3Smrg } 4937ec681f3Smrg } while (true); 4947ec681f3Smrg} 4957ec681f3Smrg 4967ec681f3Smrgvoid 4977ec681f3Smrgemu_clear_state_change(struct emu *emu) 4987ec681f3Smrg{ 4997ec681f3Smrg memset(emu->control_regs.written, 0, sizeof(emu->control_regs.written)); 5007ec681f3Smrg memset(emu->pipe_regs.written, 0, sizeof(emu->pipe_regs.written)); 5017ec681f3Smrg memset(emu->gpu_regs.written, 0, sizeof(emu->gpu_regs.written)); 5027ec681f3Smrg memset(emu->gpr_regs.written, 0, sizeof(emu->gpr_regs.written)); 5037ec681f3Smrg emu->gpumem_written = ~0; 5047ec681f3Smrg} 5057ec681f3Smrg 5067ec681f3Smrgvoid 5077ec681f3Smrgemu_dump_state_change(struct emu *emu) 5087ec681f3Smrg{ 5097ec681f3Smrg unsigned i; 5107ec681f3Smrg 5117ec681f3Smrg if (emu->quiet) 5127ec681f3Smrg return; 5137ec681f3Smrg 5147ec681f3Smrg /* Print the GPRs that changed: */ 5157ec681f3Smrg BITSET_FOREACH_SET (i, emu->gpr_regs.written, EMU_NUM_GPR_REGS) { 5167ec681f3Smrg dump_gpr_register(emu, i); 5177ec681f3Smrg } 5187ec681f3Smrg 5197ec681f3Smrg BITSET_FOREACH_SET (i, emu->gpu_regs.written, EMU_NUM_GPU_REGS) { 5207ec681f3Smrg dump_gpu_register(emu, i); 5217ec681f3Smrg } 5227ec681f3Smrg 5237ec681f3Smrg BITSET_FOREACH_SET (i, emu->pipe_regs.written, EMU_NUM_PIPE_REGS) { 5247ec681f3Smrg dump_pipe_register(emu, i); 5257ec681f3Smrg } 5267ec681f3Smrg 5277ec681f3Smrg BITSET_FOREACH_SET (i, emu->control_regs.written, EMU_NUM_CONTROL_REGS) { 5287ec681f3Smrg dump_control_register(emu, i); 5297ec681f3Smrg } 5307ec681f3Smrg 5317ec681f3Smrg if (emu->gpumem_written != ~0) { 5327ec681f3Smrg dump_gpumem(emu, emu->gpumem_written); 5337ec681f3Smrg } 5347ec681f3Smrg} 535