diff --git a/build.sh b/build.sh index 4739ef97b3..a15a032920 100755 --- a/build.sh +++ b/build.sh @@ -165,7 +165,7 @@ done target="qemu-system-i386" if test ! -z "$debug"; then build_cflags='-O0 -g -DXEMU_DEBUG_BUILD=1' - opts="--enable-debug" + opts="--enable-debug --enable-trace-backends=log" else opts="--enable-lto" fi diff --git a/hw/xbox/nv2a/debug.h b/hw/xbox/nv2a/debug.h index 73c8bd3f4f..7eb574c017 100644 --- a/hw/xbox/nv2a/debug.h +++ b/hw/xbox/nv2a/debug.h @@ -36,7 +36,6 @@ # define NV2A_DPRINTF(format, ...) do { } while (0) #endif -// #define DEBUG_NV2A_REG // #define DEBUG_NV2A_GL #ifdef DEBUG_NV2A_GL diff --git a/hw/xbox/nv2a/nv2a.c b/hw/xbox/nv2a/nv2a.c index 445b792501..7bd3960753 100644 --- a/hw/xbox/nv2a/nv2a.c +++ b/hw/xbox/nv2a/nv2a.c @@ -21,9 +21,6 @@ #include "hw/xbox/nv2a/nv2a_int.h" -#define DBG_IRQ 0 -#define DBG_DMA 0 - void nv2a_update_irq(NV2AState *d) { /* PFIFO */ @@ -48,7 +45,7 @@ void nv2a_update_irq(NV2AState *d) } if (d->pmc.pending_interrupts && d->pmc.enabled_interrupts) { - NV2A_XPRINTF(DBG_IRQ, "raise irq\n"); + trace_nv2a_irq(d->pmc.pending_interrupts); pci_irq_assert(PCI_DEVICE(d)); } else { pci_irq_deassert(PCI_DEVICE(d)); @@ -77,10 +74,8 @@ void *nv_dma_map(NV2AState *d, hwaddr dma_obj_address, hwaddr *len) DMAObject dma = nv_dma_load(d, dma_obj_address); /* TODO: Handle targets and classes properly */ - NV2A_XPRINTF(DBG_DMA, - "dma_map %" HWADDR_PRIx " - %x, %x, %" HWADDR_PRIx " %" HWADDR_PRIx "\n", - dma_obj_address, - dma.dma_class, dma.dma_target, dma.address, dma.limit); + trace_nv2a_dma_map(dma_obj_address, dma.dma_class, dma.dma_target, + dma.address, dma.limit); dma.address &= 0x07FFFFFF; assert(dma.address < memory_region_size(d->vram)); @@ -89,75 +84,36 @@ void *nv_dma_map(NV2AState *d, hwaddr dma_obj_address, hwaddr *len) return d->vram_ptr + dma.address; } -const struct NV2ABlockInfo blocktable[] = { - #define ENTRY(NAME, OFFSET, SIZE, RDFUNC, WRFUNC) \ - [NV_##NAME] = { \ - .name = #NAME, \ - .offset = OFFSET, \ - .size = SIZE, \ - .ops = { .read = RDFUNC, .write = WRFUNC }, \ +const NV2ABlockInfo blocktable[NV_NUM_BLOCKS] = { + #define ENTRY(NAME, LNAME, OFFSET, SIZE) [NV_##NAME] = { \ + .name = #NAME, \ + .offset = OFFSET, \ + .size = SIZE, \ + .ops = { .read = LNAME ## _read, .write = LNAME ## _write }, \ } - ENTRY(PMC, 0x000000, 0x001000, pmc_read, pmc_write), - ENTRY(PBUS, 0x001000, 0x001000, pbus_read, pbus_write), - ENTRY(PFIFO, 0x002000, 0x002000, pfifo_read, pfifo_write), - ENTRY(PRMA, 0x007000, 0x001000, prma_read, prma_write), - ENTRY(PVIDEO, 0x008000, 0x001000, pvideo_read, pvideo_write), - ENTRY(PTIMER, 0x009000, 0x001000, ptimer_read, ptimer_write), - ENTRY(PCOUNTER, 0x00a000, 0x001000, pcounter_read, pcounter_write), - ENTRY(PVPE, 0x00b000, 0x001000, pvpe_read, pvpe_write), - ENTRY(PTV, 0x00d000, 0x001000, ptv_read, ptv_write), - ENTRY(PRMFB, 0x0a0000, 0x020000, prmfb_read, prmfb_write), - ENTRY(PRMVIO, 0x0c0000, 0x001000, prmvio_read, prmvio_write), - ENTRY(PFB, 0x100000, 0x001000, pfb_read, pfb_write), - ENTRY(PSTRAPS, 0x101000, 0x001000, pstraps_read, pstraps_write), - ENTRY(PGRAPH, 0x400000, 0x002000, pgraph_read, pgraph_write), - ENTRY(PCRTC, 0x600000, 0x001000, pcrtc_read, pcrtc_write), - ENTRY(PRMCIO, 0x601000, 0x001000, prmcio_read, prmcio_write), - ENTRY(PRAMDAC, 0x680000, 0x001000, pramdac_read, pramdac_write), - ENTRY(PRMDIO, 0x681000, 0x001000, prmdio_read, prmdio_write), - // ENTRY(PRAMIN, 0x700000, 0x100000, pramin_read, pramin_write), - ENTRY(USER, 0x800000, 0x800000, user_read, user_write), + ENTRY(PMC, pmc, 0x000000, 0x001000), + ENTRY(PBUS, pbus, 0x001000, 0x001000), + ENTRY(PFIFO, pfifo, 0x002000, 0x002000), + ENTRY(PRMA, prma, 0x007000, 0x001000), + ENTRY(PVIDEO, pvideo, 0x008000, 0x001000), + ENTRY(PTIMER, ptimer, 0x009000, 0x001000), + ENTRY(PCOUNTER, pcounter, 0x00a000, 0x001000), + ENTRY(PVPE, pvpe, 0x00b000, 0x001000), + ENTRY(PTV, ptv, 0x00d000, 0x001000), + ENTRY(PRMFB, prmfb, 0x0a0000, 0x020000), + ENTRY(PRMVIO, prmvio, 0x0c0000, 0x001000), + ENTRY(PFB, pfb, 0x100000, 0x001000), + ENTRY(PSTRAPS, pstraps, 0x101000, 0x001000), + ENTRY(PGRAPH, pgraph, 0x400000, 0x002000), + ENTRY(PCRTC, pcrtc, 0x600000, 0x001000), + ENTRY(PRMCIO, prmcio, 0x601000, 0x001000), + ENTRY(PRAMDAC, pramdac, 0x680000, 0x001000), + ENTRY(PRMDIO, prmdio, 0x681000, 0x001000), + // ENTRY(PRAMIN, pramin, 0x700000, 0x100000), + ENTRY(USER, user, 0x800000, 0x800000), }; #undef ENTRY -#ifdef DEBUG_NV2A_REG -static const char *nv2a_reg_names[] = {}; - -void nv2a_reg_log_read(int block, hwaddr addr, uint64_t val) -{ - if (blocktable[block].name) { - hwaddr naddr = blocktable[block].offset + addr; - if (naddr < ARRAY_SIZE(nv2a_reg_names) && nv2a_reg_names[naddr]) { - NV2A_DPRINTF("%s: read [%s] -> 0x%" PRIx64 "\n", - blocktable[block].name, nv2a_reg_names[naddr], val); - } else { - NV2A_DPRINTF("%s: read [%" HWADDR_PRIx "] -> 0x%" PRIx64 "\n", - blocktable[block].name, addr, val); - } - } else { - NV2A_DPRINTF("(%d?): read [%" HWADDR_PRIx "] -> 0x%" PRIx64 "\n", - block, addr, val); - } -} - -void nv2a_reg_log_write(int block, hwaddr addr, uint64_t val) -{ - if (blocktable[block].name) { - hwaddr naddr = blocktable[block].offset + addr; - if (naddr < ARRAY_SIZE(nv2a_reg_names) && nv2a_reg_names[naddr]) { - NV2A_DPRINTF("%s: [%s] = 0x%" PRIx64 "\n", - blocktable[block].name, nv2a_reg_names[naddr], val); - } else { - NV2A_DPRINTF("%s: [%" HWADDR_PRIx "] = 0x%" PRIx64 "\n", - blocktable[block].name, addr, val); - } - } else { - NV2A_DPRINTF("(%d?): [%" HWADDR_PRIx "] = 0x%" PRIx64 "\n", - block, addr, val); - } -} -#endif - static int nv2a_get_bpp(VGACommonState *s) { NV2AState *d = container_of(s, NV2AState, vga); diff --git a/hw/xbox/nv2a/nv2a_int.h b/hw/xbox/nv2a/nv2a_int.h index 935011ea30..69dd2ca720 100644 --- a/hw/xbox/nv2a/nv2a_int.h +++ b/hw/xbox/nv2a/nv2a_int.h @@ -41,6 +41,7 @@ #include "hw/pci/pci.h" #include "cpu.h" +#include "trace.h" #include "swizzle.h" #include "lru.h" #include "gl/gloffscreen.h" @@ -488,19 +489,32 @@ typedef struct NV2ABlockInfo { uint64_t size; MemoryRegionOps ops; } NV2ABlockInfo; +extern const NV2ABlockInfo blocktable[NV_NUM_BLOCKS]; extern GloContext *g_nv2a_context_render; extern GloContext *g_nv2a_context_display; void nv2a_update_irq(NV2AState *d); -#ifdef DEBUG_NV2A_REG -void nv2a_reg_log_read(int block, hwaddr addr, uint64_t val); -void nv2a_reg_log_write(int block, hwaddr addr, uint64_t val); -#else -#define nv2a_reg_log_read(block, addr, val) do {} while (0) -#define nv2a_reg_log_write(block, addr, val) do {} while (0) -#endif +static inline +void nv2a_reg_log_read(int block, hwaddr addr, unsigned int size, uint64_t val) +{ + const char *block_name = "UNK"; + if (block < ARRAY_SIZE(blocktable) && blocktable[block].name) { + block_name = blocktable[block].name; + } + trace_nv2a_reg_read(block_name, addr, size, val); +} + +static inline +void nv2a_reg_log_write(int block, hwaddr addr, unsigned int size, uint64_t val) +{ + const char *block_name = "UNK"; + if (block < ARRAY_SIZE(blocktable) && blocktable[block].name) { + block_name = blocktable[block].name; + } + trace_nv2a_reg_write(block_name, addr, size, val); +} #define DEFINE_PROTO(n) \ uint64_t n##_read(void *opaque, hwaddr addr, unsigned int size); \ diff --git a/hw/xbox/nv2a/pbus.c b/hw/xbox/nv2a/pbus.c index 737d1bfb2d..3296c329fd 100644 --- a/hw/xbox/nv2a/pbus.c +++ b/hw/xbox/nv2a/pbus.c @@ -42,7 +42,7 @@ uint64_t pbus_read(void *opaque, hwaddr addr, unsigned int size) break; } - nv2a_reg_log_read(NV_PBUS, addr, r); + nv2a_reg_log_read(NV_PBUS, addr, size, r); return r; } @@ -51,7 +51,7 @@ void pbus_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) NV2AState *s = opaque; PCIDevice *d = PCI_DEVICE(s); - nv2a_reg_log_write(NV_PBUS, addr, val); + nv2a_reg_log_write(NV_PBUS, addr, size, val); switch (addr) { case NV_PBUS_PCI_NV_1: diff --git a/hw/xbox/nv2a/pcrtc.c b/hw/xbox/nv2a/pcrtc.c index 340b370077..cc9f77c231 100644 --- a/hw/xbox/nv2a/pcrtc.c +++ b/hw/xbox/nv2a/pcrtc.c @@ -43,7 +43,7 @@ uint64_t pcrtc_read(void *opaque, hwaddr addr, unsigned int size) break; } - nv2a_reg_log_read(NV_PCRTC, addr, r); + nv2a_reg_log_read(NV_PCRTC, addr, size, r); return r; } @@ -51,7 +51,7 @@ void pcrtc_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) { NV2AState *d = (NV2AState *)opaque; - nv2a_reg_log_write(NV_PCRTC, addr, val); + nv2a_reg_log_write(NV_PCRTC, addr, size, val); switch (addr) { case NV_PCRTC_INTR_0: diff --git a/hw/xbox/nv2a/pfb.c b/hw/xbox/nv2a/pfb.c index 892195d06a..ef2d7528af 100644 --- a/hw/xbox/nv2a/pfb.c +++ b/hw/xbox/nv2a/pfb.c @@ -42,7 +42,7 @@ uint64_t pfb_read(void *opaque, hwaddr addr, unsigned int size) break; } - nv2a_reg_log_read(NV_PFB, addr, r); + nv2a_reg_log_read(NV_PFB, addr, size, r); return r; } @@ -50,7 +50,7 @@ void pfb_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) { NV2AState *d = (NV2AState *)opaque; - nv2a_reg_log_write(NV_PFB, addr, val); + nv2a_reg_log_write(NV_PFB, addr, size, val); switch (addr) { default: diff --git a/hw/xbox/nv2a/pfifo.c b/hw/xbox/nv2a/pfifo.c index 0b54bf694b..0f73a9092c 100644 --- a/hw/xbox/nv2a/pfifo.c +++ b/hw/xbox/nv2a/pfifo.c @@ -58,7 +58,7 @@ uint64_t pfifo_read(void *opaque, hwaddr addr, unsigned int size) qemu_mutex_unlock(&d->pfifo.lock); - nv2a_reg_log_read(NV_PFIFO, addr, r); + nv2a_reg_log_read(NV_PFIFO, addr, size, r); return r; } @@ -66,7 +66,7 @@ void pfifo_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) { NV2AState *d = (NV2AState *)opaque; - nv2a_reg_log_write(NV_PFIFO, addr, val); + nv2a_reg_log_write(NV_PFIFO, addr, size, val); qemu_mutex_lock(&d->pfifo.lock); diff --git a/hw/xbox/nv2a/pgraph.c b/hw/xbox/nv2a/pgraph.c index 14c878bda5..b08f3afaa8 100644 --- a/hw/xbox/nv2a/pgraph.c +++ b/hw/xbox/nv2a/pgraph.c @@ -20,6 +20,7 @@ */ #include "nv2a_int.h" + #include "s3tc.h" #include "ui/xemu-settings.h" #include "qemu/fast-hash.h" @@ -511,7 +512,7 @@ uint64_t pgraph_read(void *opaque, hwaddr addr, unsigned int size) qemu_mutex_unlock(&pg->lock); - nv2a_reg_log_read(NV_PGRAPH, addr, r); + nv2a_reg_log_read(NV_PGRAPH, addr, size, r); return r; } @@ -520,7 +521,7 @@ void pgraph_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) NV2AState *d = (NV2AState *)opaque; PGRAPHState *pg = &d->pgraph; - nv2a_reg_log_write(NV_PGRAPH, addr, val); + nv2a_reg_log_write(NV_PGRAPH, addr, size, val); qemu_mutex_lock(&d->pfifo.lock); // FIXME: Factor out fifo lock here qemu_mutex_lock(&pg->lock); @@ -1006,7 +1007,6 @@ int pgraph_method(NV2AState *d, unsigned int subchannel, uint32_t graphics_class = GET_MASK(pg->regs[NV_PGRAPH_CTX_SWITCH1], NV_PGRAPH_CTX_SWITCH1_GRCLASS); - // NV2A_DPRINTF("graphics_class %d 0x%x\n", subchannel, graphics_class); pgraph_method_log(subchannel, graphics_class, method, parameter); if (subchannel != 0) { @@ -1016,128 +1016,140 @@ int pgraph_method(NV2AState *d, unsigned int subchannel, /* ugly switch for now */ switch (graphics_class) { - - case NV_BETA: { switch (method) { - case NV012_SET_OBJECT: - beta->object_instance = parameter; - break; - - case NV012_SET_BETA: - if (parameter & 0x80000000) { - beta->beta = 0; - } else { - // The parameter is a signed fixed-point number with a sign bit and - // 31 fractional bits. Note that negative values are clamped to 0, - // and only 8 fractional bits are actually implemented in hardware. - beta->beta = parameter & 0x7f800000; + case NV_BETA: { + switch (method) { + case NV012_SET_OBJECT: + beta->object_instance = parameter; + break; + case NV012_SET_BETA: + if (parameter & 0x80000000) { + beta->beta = 0; + } else { + // The parameter is a signed fixed-point number with a sign bit + // and 31 fractional bits. Note that negative values are clamped + // to 0, and only 8 fractional bits are actually implemented in + // hardware. + beta->beta = parameter & 0x7f800000; + } + break; + default: + goto unhandled; } break; - } break; } - - case NV_CONTEXT_PATTERN: { switch (method) { - case NV044_SET_MONOCHROME_COLOR0: - pg->regs[NV_PGRAPH_PATT_COLOR0] = parameter; - break; - } break; } - - case NV_CONTEXT_SURFACES_2D: { switch (method) { - case NV062_SET_OBJECT: - context_surfaces_2d->object_instance = parameter; - break; - - case NV062_SET_CONTEXT_DMA_IMAGE_SOURCE: - context_surfaces_2d->dma_image_source = parameter; - break; - case NV062_SET_CONTEXT_DMA_IMAGE_DESTIN: - context_surfaces_2d->dma_image_dest = parameter; - break; - case NV062_SET_COLOR_FORMAT: - context_surfaces_2d->color_format = parameter; - break; - case NV062_SET_PITCH: - context_surfaces_2d->source_pitch = parameter & 0xFFFF; - context_surfaces_2d->dest_pitch = parameter >> 16; - break; - case NV062_SET_OFFSET_SOURCE: - context_surfaces_2d->source_offset = parameter & 0x07FFFFFF; - break; - case NV062_SET_OFFSET_DESTIN: - context_surfaces_2d->dest_offset = parameter & 0x07FFFFFF; - break; - } break; } - - case NV_IMAGE_BLIT: { switch (method) { - case NV09F_SET_OBJECT: - image_blit->object_instance = parameter; - break; - - case NV09F_SET_CONTEXT_SURFACES: - image_blit->context_surfaces = parameter; - break; - case NV09F_SET_OPERATION: - image_blit->operation = parameter; - break; - case NV09F_CONTROL_POINT_IN: - image_blit->in_x = parameter & 0xFFFF; - image_blit->in_y = parameter >> 16; - break; - case NV09F_CONTROL_POINT_OUT: - image_blit->out_x = parameter & 0xFFFF; - image_blit->out_y = parameter >> 16; - break; - case NV09F_SIZE: - image_blit->width = parameter & 0xFFFF; - image_blit->height = parameter >> 16; - - if (image_blit->width && image_blit->height) { - pgraph_image_blit(d); + } + case NV_CONTEXT_PATTERN: { + switch (method) { + case NV044_SET_MONOCHROME_COLOR0: + pg->regs[NV_PGRAPH_PATT_COLOR0] = parameter; + break; + default: + goto unhandled; } break; - } break; } + } + case NV_CONTEXT_SURFACES_2D: { + switch (method) { + case NV062_SET_OBJECT: + context_surfaces_2d->object_instance = parameter; + break; + case NV062_SET_CONTEXT_DMA_IMAGE_SOURCE: + context_surfaces_2d->dma_image_source = parameter; + break; + case NV062_SET_CONTEXT_DMA_IMAGE_DESTIN: + context_surfaces_2d->dma_image_dest = parameter; + break; + case NV062_SET_COLOR_FORMAT: + context_surfaces_2d->color_format = parameter; + break; + case NV062_SET_PITCH: + context_surfaces_2d->source_pitch = parameter & 0xFFFF; + context_surfaces_2d->dest_pitch = parameter >> 16; + break; + case NV062_SET_OFFSET_SOURCE: + context_surfaces_2d->source_offset = parameter & 0x07FFFFFF; + break; + case NV062_SET_OFFSET_DESTIN: + context_surfaces_2d->dest_offset = parameter & 0x07FFFFFF; + break; + default: + goto unhandled; + } + break; + } + case NV_IMAGE_BLIT: { + switch (method) { + case NV09F_SET_OBJECT: + image_blit->object_instance = parameter; + break; + case NV09F_SET_CONTEXT_SURFACES: + image_blit->context_surfaces = parameter; + break; + case NV09F_SET_OPERATION: + image_blit->operation = parameter; + break; + case NV09F_CONTROL_POINT_IN: + image_blit->in_x = parameter & 0xFFFF; + image_blit->in_y = parameter >> 16; + break; + case NV09F_CONTROL_POINT_OUT: + image_blit->out_x = parameter & 0xFFFF; + image_blit->out_y = parameter >> 16; + break; + case NV09F_SIZE: + image_blit->width = parameter & 0xFFFF; + image_blit->height = parameter >> 16; + if (image_blit->width && image_blit->height) { + pgraph_image_blit(d); + } + break; + default: + goto unhandled; + } + break; + } case NV_KELVIN_PRIMITIVE: { MethodFunc handler = pgraph_kelvin_methods[METHOD_ADDR_TO_INDEX(method)].handler; if (handler == NULL) { - NV2A_GL_DPRINTF(true, " unhandled (0x%02x 0x%08x)", - graphics_class, method); - } else { - size_t num_words_consumed = 1; - handler(d, pg, subchannel, method, parameter, parameters, - num_words_available, &num_words_consumed, inc); - - /* Squash repeated BEGIN,DRAW_ARRAYS,END */ - #define LAM(i, mthd) ((parameters[i*2+1] & 0x31fff) == (mthd)) - #define LAP(i, prm) (parameters[i*2+2] == (prm)) - #define LAMP(i, mthd, prm) (LAM(i, mthd) && LAP(i, prm)) - - if (method == NV097_DRAW_ARRAYS && (max_lookahead_words >= 7) && - pg->draw_arrays_length < - (ARRAY_SIZE(pg->gl_draw_arrays_start) - 1) && - LAMP(0, NV097_SET_BEGIN_END, NV097_SET_BEGIN_END_OP_END) && - LAMP(1, NV097_SET_BEGIN_END, pg->primitive_mode) && - LAM(2, NV097_DRAW_ARRAYS)) { - num_words_consumed += 4; - pg->draw_arrays_prevent_connect = true; - } - - #undef LAM - #undef LAP - #undef LAMP - - num_processed = num_words_consumed; + goto unhandled; } + size_t num_words_consumed = 1; + handler(d, pg, subchannel, method, parameter, parameters, + num_words_available, &num_words_consumed, inc); + + /* Squash repeated BEGIN,DRAW_ARRAYS,END */ + #define LAM(i, mthd) ((parameters[i*2+1] & 0x31fff) == (mthd)) + #define LAP(i, prm) (parameters[i*2+2] == (prm)) + #define LAMP(i, mthd, prm) (LAM(i, mthd) && LAP(i, prm)) + + if (method == NV097_DRAW_ARRAYS && (max_lookahead_words >= 7) && + pg->draw_arrays_length < + (ARRAY_SIZE(pg->gl_draw_arrays_start) - 1) && + LAMP(0, NV097_SET_BEGIN_END, NV097_SET_BEGIN_END_OP_END) && + LAMP(1, NV097_SET_BEGIN_END, pg->primitive_mode) && + LAM(2, NV097_DRAW_ARRAYS)) { + num_words_consumed += 4; + pg->draw_arrays_prevent_connect = true; + } + + #undef LAM + #undef LAP + #undef LAMP + + num_processed = num_words_consumed; break; } - default: - NV2A_GL_DPRINTF(true, " unhandled (0x%02x 0x%08x)", - graphics_class, method); - break; - + goto unhandled; } return num_processed; + +unhandled: + trace_nv2a_pgraph_method_unhandled(subchannel, graphics_class, + method, parameter); + return num_processed; } DEF_METHOD(NV097, SET_OBJECT) @@ -1206,25 +1218,27 @@ DEF_METHOD(NV097, SET_FLIP_MODULO) DEF_METHOD(NV097, FLIP_INCREMENT_WRITE) { - NV2A_DPRINTF("flip increment write %d -> ", - GET_MASK(pg->regs[NV_PGRAPH_SURFACE], - NV_PGRAPH_SURFACE_WRITE_3D)); + uint32_t old = + GET_MASK(pg->regs[NV_PGRAPH_SURFACE], NV_PGRAPH_SURFACE_WRITE_3D); + SET_MASK(pg->regs[NV_PGRAPH_SURFACE], NV_PGRAPH_SURFACE_WRITE_3D, (GET_MASK(pg->regs[NV_PGRAPH_SURFACE], NV_PGRAPH_SURFACE_WRITE_3D)+1) % GET_MASK(pg->regs[NV_PGRAPH_SURFACE], NV_PGRAPH_SURFACE_MODULO_3D) ); - NV2A_DPRINTF("%d\n", - GET_MASK(pg->regs[NV_PGRAPH_SURFACE], - NV_PGRAPH_SURFACE_WRITE_3D)); + uint32_t new = + GET_MASK(pg->regs[NV_PGRAPH_SURFACE], NV_PGRAPH_SURFACE_WRITE_3D); + + trace_nv2a_pgraph_flip_increment_write(old, new); NV2A_GL_DFRAME_TERMINATOR(); pg->frame_time++; } DEF_METHOD(NV097, FLIP_STALL) { + trace_nv2a_pgraph_flip_stall(); pgraph_update_surface(d, false, true, true); nv2a_profile_flip_stall(); pg->waiting_for_flip = true; @@ -3392,7 +3406,6 @@ DEF_METHOD(NV097, SET_TRANSFORM_CONSTANT_LOAD) assert(parameter < NV2A_VERTEXSHADER_CONSTANTS); SET_MASK(pg->regs[NV_PGRAPH_CHEOPS_OFFSET], NV_PGRAPH_CHEOPS_OFFSET_CONST_LD_PTR, parameter); - NV2A_DPRINTF("load to %d\n", parameter); } @@ -3425,60 +3438,52 @@ void pgraph_context_switch(NV2AState *d, unsigned int channel_id) static void pgraph_method_log(unsigned int subchannel, unsigned int graphics_class, - unsigned int method, uint32_t parameter) { -#ifdef DEBUG_NV2A + unsigned int method, uint32_t parameter) +{ + const char *method_name = "?"; static unsigned int last = 0; static unsigned int count = 0; - if (last == 0x1800 && method != last) { - NV2A_GL_DPRINTF(true, "pgraph method (%d) 0x%x * %d", - subchannel, last, count); + + if (last == NV097_ARRAY_ELEMENT16 && method != last) { + method_name = "NV097_ARRAY_ELEMENT16"; + trace_nv2a_pgraph_method_abbrev(subchannel, graphics_class, last, + method_name, count); + NV2A_GL_DPRINTF(false, "pgraph method (%d) 0x%x %s * %d", subchannel, + last, method_name, count); } - if (method != 0x1800) { - const char* method_name = NULL; + + if (method != NV097_ARRAY_ELEMENT16) { uint32_t base = method; - // unsigned int nmethod = 0; switch (graphics_class) { - case NV_KELVIN_PRIMITIVE: { - // nmethod = method | (0x5c << 16); - int idx = METHOD_ADDR_TO_INDEX(method); - if (idx < ARRAY_SIZE(pgraph_kelvin_methods)) { - method_name = pgraph_kelvin_methods[idx].name; - base = pgraph_kelvin_methods[idx].base; - } - break; + case NV_KELVIN_PRIMITIVE: { + int idx = METHOD_ADDR_TO_INDEX(method); + if (idx < ARRAY_SIZE(pgraph_kelvin_methods) && + pgraph_kelvin_methods[idx].handler) { + method_name = pgraph_kelvin_methods[idx].name; + base = pgraph_kelvin_methods[idx].base; } - case NV_CONTEXT_SURFACES_2D: - // nmethod = method | (0x6d << 16); - break; - case NV_CONTEXT_PATTERN: - // nmethod = method | (0x68 << 16); - break; - default: - break; + break; + } + default: + break; } - char buf[256]; - char *ptr = buf; - char *end = ptr + sizeof(buf); - - ptr += snprintf(ptr, end - ptr, "pgraph method (%d): 0x%x -> 0x%04x", - subchannel, graphics_class, method); - - if (method_name) { - ptr += snprintf(ptr, end - ptr, " %s", method_name); - uint32_t o = method - base; - if (o) { - ptr += snprintf(ptr, end - ptr, "+0x%02x", o); - } - } - - ptr += snprintf(ptr, end - ptr, " (0x%x)", parameter); - NV2A_GL_DPRINTF(true, "%s", buf); + uint32_t offset = method - base; + trace_nv2a_pgraph_method(subchannel, graphics_class, method, + method_name, offset, parameter); + NV2A_GL_DPRINTF(false, + "pgraph method (%d): 0x%" PRIx32 " -> 0x%04" PRIx32 + " %s[%" PRId32 "] 0x%" PRIx32, + subchannel, graphics_class, method, method_name, offset, + parameter); + } + + if (method == last) { + count++; + } else { + count = 0; } - if (method == last) { count++; } - else {count = 0; } last = method; -#endif } static void pgraph_allocate_inline_buffer_vertices(PGRAPHState *pg, @@ -4954,16 +4959,12 @@ static void pgraph_surface_access_callback( assert(offset < e->size); if (qatomic_read(&e->draw_dirty)) { - NV2A_XPRINTF(DBG_SURFACE_SYNC, - "Surface accessed at %" HWADDR_PRIx "+%" HWADDR_PRIx "\n", - e->vram_addr, offset); + trace_nv2a_pgraph_surface_cpu_access(e->vram_addr, offset); pgraph_wait_for_surface_download(e); } if (write && !qatomic_read(&e->upload_pending)) { - NV2A_XPRINTF(DBG_SURFACE_SYNC, - "Surface write at %" HWADDR_PRIx "+%" HWADDR_PRIx "\n", - e->vram_addr, offset); + trace_nv2a_pgraph_surface_cpu_access(e->vram_addr, offset); qatomic_set(&e->upload_pending, true); } } @@ -4973,9 +4974,8 @@ static SurfaceBinding *pgraph_surface_put(NV2AState *d, SurfaceBinding *surface_in) { assert(pgraph_surface_get(d, addr) == NULL); - NV2A_XPRINTF(DBG_SURFACES, - "Adding surface region at [%" HWADDR_PRIx ": %" HWADDR_PRIx ")\n", - surface_in->vram_addr, surface_in->vram_addr + surface_in->size); + trace_nv2a_pgraph_surface_created(surface_in->vram_addr, + surface_in->vram_addr + surface_in->size); SurfaceBinding *surface, *next; uintptr_t e_end = surface_in->vram_addr + surface_in->size - 1; @@ -5039,8 +5039,7 @@ static SurfaceBinding *pgraph_surface_get_within(NV2AState *d, hwaddr addr) static void pgraph_surface_invalidate(NV2AState *d, SurfaceBinding *surface) { - NV2A_XPRINTF(DBG_SURFACES, "Removing surface at %" HWADDR_PRIx "\n", - surface->vram_addr); + trace_nv2a_pgraph_surface_invalidated(surface->vram_addr); assert(surface != d->pgraph.color_binding); assert(surface != d->pgraph.zeta_binding); diff --git a/hw/xbox/nv2a/pmc.c b/hw/xbox/nv2a/pmc.c index 1a0191cbbf..62e96ec6ff 100644 --- a/hw/xbox/nv2a/pmc.c +++ b/hw/xbox/nv2a/pmc.c @@ -46,7 +46,7 @@ uint64_t pmc_read(void *opaque, hwaddr addr, unsigned int size) break; } - nv2a_reg_log_read(NV_PMC, addr, r); + nv2a_reg_log_read(NV_PMC, addr, size, r); return r; } @@ -54,7 +54,7 @@ void pmc_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) { NV2AState *d = (NV2AState *)opaque; - nv2a_reg_log_write(NV_PMC, addr, val); + nv2a_reg_log_write(NV_PMC, addr, size, val); switch (addr) { case NV_PMC_INTR_0: diff --git a/hw/xbox/nv2a/pramdac.c b/hw/xbox/nv2a/pramdac.c index 14ed307125..1a93549f57 100644 --- a/hw/xbox/nv2a/pramdac.c +++ b/hw/xbox/nv2a/pramdac.c @@ -74,8 +74,7 @@ uint64_t pramdac_read(void *opaque, hwaddr addr, unsigned int size) /* Surprisingly, QEMU doesn't handle unaligned access for you properly */ r >>= 32 - 8 * size - 8 * (addr & 3); - NV2A_DPRINTF("PRAMDAC: read %d [0x%" HWADDR_PRIx "] -> %" PRIx64 "\n", size, - addr, r); + nv2a_reg_log_read(NV_PRAMDAC, addr, size, r); return r; } @@ -84,7 +83,7 @@ void pramdac_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) NV2AState *d = (NV2AState *)opaque; uint32_t m, n, p; - nv2a_reg_log_write(NV_PRAMDAC, addr, val); + nv2a_reg_log_write(NV_PRAMDAC, addr, size, val); switch (addr) { case NV_PRAMDAC_NVPLL_COEFF: diff --git a/hw/xbox/nv2a/prmcio.c b/hw/xbox/nv2a/prmcio.c index fe396a00b3..d75e14a518 100644 --- a/hw/xbox/nv2a/prmcio.c +++ b/hw/xbox/nv2a/prmcio.c @@ -27,7 +27,7 @@ uint64_t prmcio_read(void *opaque, hwaddr addr, unsigned int size) NV2AState *d = opaque; uint64_t r = vga_ioport_read(&d->vga, addr); - nv2a_reg_log_read(NV_PRMCIO, addr, r); + nv2a_reg_log_read(NV_PRMCIO, addr, size, r); return r; } @@ -35,7 +35,7 @@ void prmcio_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) { NV2AState *d = opaque; - nv2a_reg_log_write(NV_PRMCIO, addr, val); + nv2a_reg_log_write(NV_PRMCIO, addr, size, val); switch (addr) { case VGA_ATT_W: diff --git a/hw/xbox/nv2a/prmdio.c b/hw/xbox/nv2a/prmdio.c index ff04adf661..a80c23ef94 100644 --- a/hw/xbox/nv2a/prmdio.c +++ b/hw/xbox/nv2a/prmdio.c @@ -32,7 +32,7 @@ uint64_t prmdio_read(void *opaque, hwaddr addr, unsigned int size) break; } - nv2a_reg_log_read(NV_PRMDIO, addr, r); + nv2a_reg_log_read(NV_PRMDIO, addr, size, r); return r; } @@ -40,7 +40,7 @@ void prmdio_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) { NV2AState *d = (NV2AState *)opaque; - nv2a_reg_log_write(NV_PRMDIO, addr, val); + nv2a_reg_log_write(NV_PRMDIO, addr, size, val); switch (addr) { case NV_USER_DAC_WRITE_MODE_ADDRESS: diff --git a/hw/xbox/nv2a/prmvio.c b/hw/xbox/nv2a/prmvio.c index bdf075e069..3908d894ff 100644 --- a/hw/xbox/nv2a/prmvio.c +++ b/hw/xbox/nv2a/prmvio.c @@ -27,7 +27,7 @@ uint64_t prmvio_read(void *opaque, hwaddr addr, unsigned int size) NV2AState *d = opaque; uint64_t r = vga_ioport_read(&d->vga, addr); - nv2a_reg_log_read(NV_PRMVIO, addr, r); + nv2a_reg_log_read(NV_PRMVIO, addr, size, r); return r; } @@ -35,6 +35,6 @@ void prmvio_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) { NV2AState *d = opaque; - nv2a_reg_log_write(NV_PRMVIO, addr, val); + nv2a_reg_log_write(NV_PRMVIO, addr, size, val); vga_ioport_write(&d->vga, addr, val); } diff --git a/hw/xbox/nv2a/ptimer.c b/hw/xbox/nv2a/ptimer.c index c056a9edb4..e18f708695 100644 --- a/hw/xbox/nv2a/ptimer.c +++ b/hw/xbox/nv2a/ptimer.c @@ -59,7 +59,7 @@ uint64_t ptimer_read(void *opaque, hwaddr addr, unsigned int size) break; } - nv2a_reg_log_read(NV_PTIMER, addr, r); + nv2a_reg_log_read(NV_PTIMER, addr, size, r); return r; } @@ -67,7 +67,7 @@ void ptimer_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) { NV2AState *d = opaque; - nv2a_reg_log_write(NV_PTIMER, addr, val); + nv2a_reg_log_write(NV_PTIMER, addr, size, val); switch (addr) { case NV_PTIMER_INTR_0: diff --git a/hw/xbox/nv2a/pvideo.c b/hw/xbox/nv2a/pvideo.c index 4c2aaae742..8ca1ac24ab 100644 --- a/hw/xbox/nv2a/pvideo.c +++ b/hw/xbox/nv2a/pvideo.c @@ -45,7 +45,7 @@ uint64_t pvideo_read(void *opaque, hwaddr addr, unsigned int size) break; } - nv2a_reg_log_read(NV_PVIDEO, addr, r); + nv2a_reg_log_read(NV_PVIDEO, addr, size, r); return r; } @@ -53,7 +53,7 @@ void pvideo_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) { NV2AState *d = opaque; - nv2a_reg_log_write(NV_PVIDEO, addr, val); + nv2a_reg_log_write(NV_PVIDEO, addr, size, val); switch (addr) { case NV_PVIDEO_BUFFER: diff --git a/hw/xbox/nv2a/stubs.c b/hw/xbox/nv2a/stubs.c index 3638a06108..2f52c6ecdc 100644 --- a/hw/xbox/nv2a/stubs.c +++ b/hw/xbox/nv2a/stubs.c @@ -26,7 +26,7 @@ hwaddr addr, \ unsigned int size) \ { \ - nv2a_reg_log_read(region_id, addr, 0); \ + nv2a_reg_log_read(region_id, addr, size, 0); \ return 0; \ } \ void name ## _write(void *opaque, \ @@ -34,7 +34,7 @@ uint64_t val, \ unsigned int size) \ { \ - nv2a_reg_log_write(region_id, addr, val); \ + nv2a_reg_log_write(region_id, addr, size, val); \ } \ DEFINE_STUB(prma, NV_PRMA) diff --git a/hw/xbox/nv2a/trace-events b/hw/xbox/nv2a/trace-events new file mode 100644 index 0000000000..3ef0859636 --- /dev/null +++ b/hw/xbox/nv2a/trace-events @@ -0,0 +1,17 @@ +# See docs/devel/tracing.rst for syntax documentation. + +# nv2a.c +nv2a_reg_read(const char *block, uint32_t addr, unsigned int size, uint64_t val) "%s addr 0x%"PRIx32" size %d val 0x%"PRIx64 +nv2a_reg_write(const char *block, uint32_t addr, unsigned int size, uint64_t val) "%s addr 0x%"PRIx32" size %d val 0x%"PRIx64 +nv2a_irq(uint32_t pending) "%08"PRIx32 +nv2a_dma_map(uint32_t obj_address, uint32_t dma_class, uint32_t dma_target, uint32_t dma_addr, uint32_t dma_limit) "obj 0x%08"PRIx32" class 0x%08"PRIx32" target 0x%08"PRIx32" addr 0x%08"PRIx32" limit 0x%08"PRIx32 + +# pgraph.c +nv2a_pgraph_method(uint32_t subchannel, uint32_t graphics_class, uint32_t method, const char *name, uint32_t offset, uint32_t parameter) "%d: 0x%"PRIx32" -> 0x%04"PRIx32" %s[%"PRId32"] 0x%"PRIx32 +nv2a_pgraph_method_abbrev(uint32_t subchannel, uint32_t graphics_class, uint32_t method, const char *name, unsigned int count) "%d: 0x%"PRIx32" -> 0x%04"PRIx32" %s * %d" +nv2a_pgraph_method_unhandled(uint32_t subchannel, uint32_t graphics_class, uint32_t method, uint32_t parameter) "%d: 0x%"PRIx32" -> 0x%04"PRIx32" 0x%"PRIx32 +nv2a_pgraph_surface_cpu_access(uint32_t addr, uint32_t offset) "0x%08"PRIx32"+0x%"PRIx32 +nv2a_pgraph_surface_created(uint32_t addr, uint32_t end_addr) "[0x%08"PRIx32", 0x%08"PRIx32")" +nv2a_pgraph_surface_invalidated(uint32_t addr) "0x%08"PRIx32 +nv2a_pgraph_flip_stall(void) "" +nv2a_pgraph_flip_increment_write(uint32_t write3d_old, uint32_t write3d_new) "0x%"PRIx32" -> 0x%"PRIx32 diff --git a/hw/xbox/nv2a/trace.h b/hw/xbox/nv2a/trace.h new file mode 100644 index 0000000000..fd655cbfaf --- /dev/null +++ b/hw/xbox/nv2a/trace.h @@ -0,0 +1 @@ +#include "trace/trace-hw_xbox_nv2a.h" diff --git a/hw/xbox/nv2a/user.c b/hw/xbox/nv2a/user.c index b0429de495..28e917d4d6 100644 --- a/hw/xbox/nv2a/user.c +++ b/hw/xbox/nv2a/user.c @@ -66,7 +66,7 @@ uint64_t user_read(void *opaque, hwaddr addr, unsigned int size) qemu_mutex_unlock(&d->pfifo.lock); - nv2a_reg_log_read(NV_USER, addr, r); + nv2a_reg_log_read(NV_USER, addr, size, r); return r; } @@ -74,7 +74,7 @@ void user_write(void *opaque, hwaddr addr, uint64_t val, unsigned int size) { NV2AState *d = (NV2AState *)opaque; - nv2a_reg_log_write(NV_USER, addr, val); + nv2a_reg_log_write(NV_USER, addr, size, val); unsigned int channel_id = addr >> 16; assert(channel_id < NV2A_NUM_CHANNELS); diff --git a/meson.build b/meson.build index 88e1e34401..2376d49cfc 100644 --- a/meson.build +++ b/meson.build @@ -2186,6 +2186,7 @@ if have_system 'softmmu', 'ui', 'hw/remote', + 'hw/xbox/nv2a', ] endif if have_system or have_user