diff options
Diffstat (limited to 'src/freedreno/afuc/disasm.c')
-rw-r--r-- | src/freedreno/afuc/disasm.c | 44 |
1 files changed, 38 insertions, 6 deletions
diff --git a/src/freedreno/afuc/disasm.c b/src/freedreno/afuc/disasm.c index 145fdbda9a7..44e7eaf1017 100644 --- a/src/freedreno/afuc/disasm.c +++ b/src/freedreno/afuc/disasm.c @@ -39,6 +39,7 @@ #include "afuc.h" #include "util.h" +#include "emu.h" static int gpuver; @@ -48,6 +49,9 @@ static int gpuver; */ static bool verbose = false; +/* emulator mode: */ +static bool emulator = false; + static void print_gpu_reg(uint32_t regbase) { @@ -64,7 +68,7 @@ print_gpu_reg(uint32_t regbase) #define printerr(fmt, ...) afuc_printc(AFUC_ERR, fmt, ##__VA_ARGS__) #define printlbl(fmt, ...) afuc_printc(AFUC_LBL, fmt, ##__VA_ARGS__) -static void +void print_src(unsigned reg) { if (reg == REG_REM) @@ -79,7 +83,7 @@ print_src(unsigned reg) printf("$%02x", reg); } -static void +void print_dst(unsigned reg) { if (reg == REG_REM) @@ -257,7 +261,7 @@ fxn_name(uint32_t offset) return name; } -static void +void print_control_reg(uint32_t id) { char *name = afuc_control_reg_name(id); @@ -269,7 +273,7 @@ print_control_reg(uint32_t id) } } -static void +void print_pipe_reg(uint32_t id) { char *name = afuc_pipe_reg_name(id); @@ -752,6 +756,20 @@ disasm(uint32_t *buf, int sizedwords) } } + if (emulator) { + struct emu state = { + .instrs = instrs, + .sizedwords = sizedwords, + }; + + emu_init(&state); + + while (true) { + disasm_instr(instrs, state.gpr_regs.pc); + emu_step(&state); + } + } + /* print instructions: */ for (i = 0; i < jmptbl_start; i++) { disasm_instr(instrs, i); @@ -784,7 +802,8 @@ usage(void) "\tdisasm [-g GPUVER] [-v] [-c] filename.asm\n" "\t\t-g - specify GPU version (5, etc)\n" "\t\t-c - use colors\n" - "\t\t-v - verbose output\n"); + "\t\t-v - verbose output\n" + "\t\t-e - emulator mode\n"); exit(2); } @@ -798,7 +817,7 @@ main(int argc, char **argv) int c, ret; /* Argument parsing: */ - while ((c = getopt(argc, argv, "g:vc")) != -1) { + while ((c = getopt(argc, argv, "g:vce")) != -1) { switch (c) { case 'g': gpuver = atoi(optarg); @@ -809,6 +828,10 @@ main(int argc, char **argv) case 'c': colors = true; break; + case 'e': + emulator = true; + verbose = true; + break; default: usage(); } @@ -830,6 +853,15 @@ main(int argc, char **argv) } } + /* a6xx is *mostly* a superset of a5xx, but some opcodes shuffle + * around, and behavior of special regs is a bit different. Right + * now we only bother to support the a6xx variant. + */ + if (emulator && (gpuver != 6)) { + fprintf(stderr, "Emulator only supported on a6xx!\n"); + return 1; + } + ret = afuc_util_init(gpuver, colors); if (ret < 0) { usage(); |