Debugger: Plumb access source information through to access logger

This commit is contained in:
Vicki Pfau 2025-01-14 03:20:01 -08:00
parent deb4f547fa
commit b8c890e1bc
11 changed files with 107 additions and 0 deletions

View File

@ -20,6 +20,15 @@ enum mCPUComponentType {
CPU_COMPONENT_MAX
};
enum mMemoryAccessSource {
mACCESS_UNKNOWN = 0,
mACCESS_PROGRAM,
mACCESS_DMA,
mACCESS_SYSTEM,
mACCESS_DECOMPRESS,
mACCESS_COPY,
};
struct mCPUComponent {
uint32_t id;
void (*init)(void* cpu, struct mCPUComponent* component);

View File

@ -111,6 +111,7 @@ struct mDebuggerEntryInfo {
uint32_t newValue;
enum mWatchpointType watchType;
enum mWatchpointType accessType;
enum mMemoryAccessSource accessSource;
} wp;
struct {

View File

@ -132,6 +132,8 @@ struct ARMMemory {
uint32_t activeNonseqCycles16;
int32_t (*stall)(struct ARMCore*, int32_t wait);
void (*setActiveRegion)(struct ARMCore*, uint32_t address);
enum mMemoryAccessSource accessSource;
};
struct ARMCoprocessor {

View File

@ -61,6 +61,8 @@ struct SM83Memory {
uint16_t activeMask;
uint16_t activeRegionEnd;
void (*setActiveRegion)(struct SM83Core*, uint16_t address);
enum mMemoryAccessSource accessSource;
};
struct SM83InterruptHandler {

View File

@ -121,6 +121,7 @@ static void _checkWatchpoints(struct ARMDebugger* debugger, uint32_t address, en
info.type.wp.newValue = newValue;
info.type.wp.watchType = watchpoint->type;
info.type.wp.accessType = type;
info.type.wp.accessSource = debugger->cpu->memory.accessSource;
info.address = address;
info.segment = 0;
info.width = width;

View File

@ -69,9 +69,29 @@ static void _mDebuggerAccessLoggerEntered(struct mDebuggerModule* debugger, enum
}
offset &= -info->width;
mDebuggerAccessLogFlagsEx flagsEx = 0;
int i;
switch (reason) {
case DEBUGGER_ENTER_WATCHPOINT:
switch (info->type.wp.accessSource) {
case mACCESS_PROGRAM:
flagsEx = mDebuggerAccessLogFlagsExFillAccessProgram(flagsEx);
break;
case mACCESS_DMA:
flagsEx = mDebuggerAccessLogFlagsExFillAccessDMA(flagsEx);
break;
case mACCESS_SYSTEM:
flagsEx = mDebuggerAccessLogFlagsExFillAccessSystem(flagsEx);
break;
case mACCESS_DECOMPRESS:
flagsEx = mDebuggerAccessLogFlagsExFillAccessDecompress(flagsEx);
break;
case mACCESS_COPY:
flagsEx = mDebuggerAccessLogFlagsExFillAccessCopy(flagsEx);
break;
case mACCESS_UNKNOWN:
break;
}
for (i = 0; i < info->width; ++i) {
if (info->type.wp.accessType & WATCHPOINT_WRITE) {
region->block[offset + i] = mDebuggerAccessLogFlagsFillWrite(region->block[offset + i]);
@ -83,16 +103,29 @@ static void _mDebuggerAccessLoggerEntered(struct mDebuggerModule* debugger, enum
switch (info->width) {
case 1:
region->block[offset] = mDebuggerAccessLogFlagsFillAccess8(region->block[offset]);
if (region->blockEx) {
region->blockEx[offset] |= flagsEx;
}
break;
case 2:
region->block[offset] = mDebuggerAccessLogFlagsFillAccess16(region->block[offset]);
region->block[offset + 1] = mDebuggerAccessLogFlagsFillAccess16(region->block[offset + 1]);
if (region->blockEx) {
region->blockEx[offset] |= flagsEx;
region->blockEx[offset + 1] |= flagsEx;
}
break;
case 4:
region->block[offset] = mDebuggerAccessLogFlagsFillAccess32(region->block[offset]);
region->block[offset + 1] = mDebuggerAccessLogFlagsFillAccess32(region->block[offset + 1]);
region->block[offset + 2] = mDebuggerAccessLogFlagsFillAccess32(region->block[offset + 2]);
region->block[offset + 3] = mDebuggerAccessLogFlagsFillAccess32(region->block[offset + 3]);
if (region->blockEx) {
region->blockEx[offset] |= flagsEx;
region->blockEx[offset + 1] |= flagsEx;
region->blockEx[offset + 2] |= flagsEx;
region->blockEx[offset + 3] |= flagsEx;
}
break;
case 8:
region->block[offset] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset]);
@ -103,6 +136,16 @@ static void _mDebuggerAccessLoggerEntered(struct mDebuggerModule* debugger, enum
region->block[offset + 5] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 5]);
region->block[offset + 6] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 6]);
region->block[offset + 7] = mDebuggerAccessLogFlagsFillAccess64(region->block[offset + 7]);
if (region->blockEx) {
region->blockEx[offset] |= flagsEx;
region->blockEx[offset + 1] |= flagsEx;
region->blockEx[offset + 2] |= flagsEx;
region->blockEx[offset + 3] |= flagsEx;
region->blockEx[offset + 4] |= flagsEx;
region->blockEx[offset + 5] |= flagsEx;
region->blockEx[offset + 6] |= flagsEx;
region->blockEx[offset + 7] |= flagsEx;
}
break;
}
break;

View File

@ -148,6 +148,7 @@ void GBMemoryInit(struct GB* gb) {
cpu->memory.store8 = GBStore8;
cpu->memory.currentSegment = GBCurrentSegment;
cpu->memory.setActiveRegion = GBSetActiveRegion;
cpu->memory.accessSource = mACCESS_UNKNOWN;
gb->memory.wram = 0;
gb->memory.wramBank = 0;
@ -205,6 +206,7 @@ void GBMemoryReset(struct GB* gb) {
gb->memory.hdmaDest = 0;
gb->memory.isHdma = false;
gb->cpu->memory.accessSource = mACCESS_UNKNOWN;
gb->memory.dmaEvent.context = gb;
gb->memory.dmaEvent.name = "GB DMA";
@ -576,10 +578,13 @@ void _GBMemoryDMAService(struct mTiming* timing, void* context, uint32_t cyclesL
struct GB* gb = context;
int dmaRemaining = gb->memory.dmaRemaining;
gb->memory.dmaRemaining = 0;
enum mMemoryAccessSource oldAccess = gb->cpu->memory.accessSource;
gb->cpu->memory.accessSource = mACCESS_DMA;
uint8_t b = GBLoad8(gb->cpu, gb->memory.dmaSource);
// TODO: Can DMA write OAM during modes 2-3?
gb->video.oam.raw[gb->memory.dmaDest] = b;
gb->video.renderer->writeOAM(gb->video.renderer, gb->memory.dmaDest);
gb->cpu->memory.accessSource = oldAccess;
++gb->memory.dmaSource;
++gb->memory.dmaDest;
gb->memory.dmaRemaining = dmaRemaining - 1;
@ -591,8 +596,11 @@ void _GBMemoryDMAService(struct mTiming* timing, void* context, uint32_t cyclesL
void _GBMemoryHDMAService(struct mTiming* timing, void* context, uint32_t cyclesLate) {
struct GB* gb = context;
gb->cpuBlocked = true;
enum mMemoryAccessSource oldAccess = gb->cpu->memory.accessSource;
gb->cpu->memory.accessSource = mACCESS_DMA;
uint8_t b = gb->cpu->memory.load8(gb->cpu, gb->memory.hdmaSource);
gb->cpu->memory.store8(gb->cpu, gb->memory.hdmaDest, b);
gb->cpu->memory.accessSource = oldAccess;
++gb->memory.hdmaSource;
++gb->memory.hdmaDest;
--gb->memory.hdmaRemaining;

View File

@ -174,6 +174,8 @@ static void _BgAffineSet(struct GBA* gba) {
int destination = cpu->gprs[1];
float a, b, c, d;
float rx, ry;
enum mMemoryAccessSource oldAccess = cpu->memory.accessSource;
cpu->memory.accessSource = mACCESS_SYSTEM;
while (i--) {
// [ sx 0 0 ] [ cos(theta) -sin(theta) 0 ] [ 1 0 cx - ox ] [ A B rx ]
// [ 0 sy 0 ] * [ sin(theta) cos(theta) 0 ] * [ 0 1 cy - oy ] = [ C D ry ]
@ -205,6 +207,7 @@ static void _BgAffineSet(struct GBA* gba) {
cpu->memory.store32(cpu, destination + 12, ry * 256, 0);
destination += 16;
}
cpu->memory.accessSource = oldAccess;
}
static void _ObjAffineSet(struct GBA* gba) {
@ -216,6 +219,8 @@ static void _ObjAffineSet(struct GBA* gba) {
int destination = cpu->gprs[1];
int diff = cpu->gprs[3];
float a, b, c, d;
enum mMemoryAccessSource oldAccess = cpu->memory.accessSource;
cpu->memory.accessSource = mACCESS_SYSTEM;
while (i--) {
// [ sx 0 ] [ cos(theta) -sin(theta) ] [ A B ]
// [ 0 sy ] * [ sin(theta) cos(theta) ] = [ C D ]
@ -237,6 +242,7 @@ static void _ObjAffineSet(struct GBA* gba) {
cpu->memory.store16(cpu, destination + diff * 3, d * 256, 0);
destination += diff * 4;
}
cpu->memory.accessSource = oldAccess;
}
static void _MidiKey2Freq(struct GBA* gba) {
@ -244,7 +250,10 @@ static void _MidiKey2Freq(struct GBA* gba) {
int oldRegion = gba->memory.activeRegion;
gba->memory.activeRegion = GBA_REGION_BIOS;
enum mMemoryAccessSource oldAccess = cpu->memory.accessSource;
cpu->memory.accessSource = mACCESS_SYSTEM;
uint32_t key = cpu->memory.load32(cpu, cpu->gprs[0] + 4, 0);
cpu->memory.accessSource = oldAccess;
gba->memory.activeRegion = oldRegion;
cpu->gprs[0] = key / exp2f((180.f - cpu->gprs[1] - cpu->gprs[2] / 256.f) / 12.f);
@ -624,6 +633,8 @@ static void _unLz77(struct GBA* gba, int width) {
uint32_t source = cpu->gprs[0];
uint32_t dest = cpu->gprs[1];
int cycles = 20;
enum mMemoryAccessSource oldAccess = cpu->memory.accessSource;
cpu->memory.accessSource = mACCESS_DECOMPRESS;
int remaining = (cpu->memory.load32(cpu, source, &cycles) & 0xFFFFFF00) >> 8;
// We assume the signature byte (0x10) is correct
int blockheader = 0; // Some compilers warn if this isn't set, even though it's trivially provably always set
@ -698,6 +709,7 @@ static void _unLz77(struct GBA* gba, int width) {
blocksRemaining = 8;
}
}
cpu->memory.accessSource = oldAccess;
cpu->gprs[0] = source;
cpu->gprs[1] = dest;
cpu->gprs[3] = 0;
@ -713,6 +725,8 @@ static void _unHuffman(struct GBA* gba) {
struct ARMCore* cpu = gba->cpu;
uint32_t source = cpu->gprs[0] & 0xFFFFFFFC;
uint32_t dest = cpu->gprs[1];
enum mMemoryAccessSource oldAccess = cpu->memory.accessSource;
cpu->memory.accessSource = mACCESS_DECOMPRESS;
uint32_t header = cpu->memory.load32(cpu, source, 0);
int remaining = header >> 8;
unsigned bits = header & 0xF;
@ -722,6 +736,7 @@ static void _unHuffman(struct GBA* gba) {
}
if (32 % bits || bits == 1) {
mLOG(GBA_BIOS, STUB, "Unimplemented unaligned Huffman");
cpu->memory.accessSource = oldAccess;
return;
}
// We assume the signature byte (0x20) is correct
@ -773,6 +788,7 @@ static void _unHuffman(struct GBA* gba) {
}
}
}
cpu->memory.accessSource = oldAccess;
cpu->gprs[0] = source;
cpu->gprs[1] = dest;
}
@ -780,6 +796,8 @@ static void _unHuffman(struct GBA* gba) {
static void _unRl(struct GBA* gba, int width) {
struct ARMCore* cpu = gba->cpu;
uint32_t source = cpu->gprs[0];
enum mMemoryAccessSource oldAccess = cpu->memory.accessSource;
cpu->memory.accessSource = mACCESS_DECOMPRESS;
int remaining = (cpu->memory.load32(cpu, source & 0xFFFFFFFC, 0) & 0xFFFFFF00) >> 8;
int padding = (4 - remaining) & 0x3;
// We assume the signature byte (0x30) is correct
@ -846,6 +864,7 @@ static void _unRl(struct GBA* gba, int width) {
++dest;
}
}
cpu->memory.accessSource = oldAccess;
cpu->gprs[0] = source;
cpu->gprs[1] = dest;
}
@ -854,6 +873,8 @@ static void _unFilter(struct GBA* gba, int inwidth, int outwidth) {
struct ARMCore* cpu = gba->cpu;
uint32_t source = cpu->gprs[0] & 0xFFFFFFFC;
uint32_t dest = cpu->gprs[1];
enum mMemoryAccessSource oldAccess = cpu->memory.accessSource;
cpu->memory.accessSource = mACCESS_DECOMPRESS;
uint32_t header = cpu->memory.load32(cpu, source, 0);
int remaining = header >> 8;
// We assume the signature nybble (0x8) is correct
@ -888,6 +909,7 @@ static void _unFilter(struct GBA* gba, int inwidth, int outwidth) {
old = new;
source += inwidth;
}
cpu->memory.accessSource = oldAccess;
cpu->gprs[0] = source;
cpu->gprs[1] = dest;
}
@ -897,6 +919,8 @@ static void _unBitPack(struct GBA* gba) {
uint32_t source = cpu->gprs[0];
uint32_t dest = cpu->gprs[1];
uint32_t info = cpu->gprs[2];
enum mMemoryAccessSource oldAccess = cpu->memory.accessSource;
cpu->memory.accessSource = mACCESS_DECOMPRESS;
unsigned sourceLen = cpu->memory.load16(cpu, info, 0);
unsigned sourceWidth = cpu->memory.load8(cpu, info + 2, 0);
unsigned destWidth = cpu->memory.load8(cpu, info + 3, 0);
@ -908,6 +932,7 @@ static void _unBitPack(struct GBA* gba) {
break;
default:
mLOG(GBA_BIOS, GAME_ERROR, "Bad BitUnPack source width: %u", sourceWidth);
cpu->memory.accessSource = oldAccess;
return;
}
switch (destWidth) {
@ -920,6 +945,7 @@ static void _unBitPack(struct GBA* gba) {
break;
default:
mLOG(GBA_BIOS, GAME_ERROR, "Bad BitUnPack destination width: %u", destWidth);
cpu->memory.accessSource = oldAccess;
return;
}
uint32_t bias = cpu->memory.load32(cpu, info + 4, 0);
@ -949,6 +975,7 @@ static void _unBitPack(struct GBA* gba) {
dest += 4;
}
}
cpu->memory.accessSource = oldAccess;
cpu->gprs[0] = source;
cpu->gprs[1] = dest;
}

View File

@ -248,10 +248,12 @@ void GBADMAService(struct GBA* gba, int number, struct GBADMA* info) {
uint32_t dest = info->nextDest;
uint32_t sourceRegion = source >> BASE_OFFSET;
uint32_t destRegion = dest >> BASE_OFFSET;
enum mMemoryAccessSource oldAccess = cpu->memory.accessSource;
int32_t cycles = 2;
gba->cpuBlocked = true;
gba->performingDMA = 1 | (number << 1);
cpu->memory.accessSource = mACCESS_DMA;
if (info->count == info->nextCount) {
if (width == 4) {
@ -315,6 +317,7 @@ void GBADMAService(struct GBA* gba, int number, struct GBADMA* info) {
--info->nextCount;
gba->performingDMA = 0;
cpu->memory.accessSource = oldAccess;
int i;
for (i = 0; i < 4; ++i) {

View File

@ -82,6 +82,7 @@ void GBAMemoryInit(struct GBA* gba) {
cpu->memory.activeSeqCycles16 = 0;
cpu->memory.activeNonseqCycles32 = 0;
cpu->memory.activeNonseqCycles16 = 0;
cpu->memory.accessSource = mACCESS_UNKNOWN;
gba->memory.biosPrefetch = 0;
gba->memory.agbPrintProtect = 0;
@ -132,6 +133,7 @@ void GBAMemoryReset(struct GBA* gba) {
gba->memory.prefetch = false;
gba->memory.lastPrefetchedPc = 0;
gba->cpu->memory.accessSource = mACCESS_UNKNOWN;
if (!gba->memory.wram || !gba->memory.iwram) {
GBAMemoryDeinit(gba);
@ -299,22 +301,27 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
memory->activeRegion = newRegion;
switch (newRegion) {
case GBA_REGION_BIOS:
cpu->memory.accessSource = mACCESS_SYSTEM;
cpu->memory.activeRegion = memory->bios;
cpu->memory.activeMask = GBA_SIZE_BIOS - 1;
break;
case GBA_REGION_EWRAM:
cpu->memory.accessSource = mACCESS_PROGRAM;
cpu->memory.activeRegion = memory->wram;
cpu->memory.activeMask = GBA_SIZE_EWRAM - 1;
break;
case GBA_REGION_IWRAM:
cpu->memory.accessSource = mACCESS_PROGRAM;
cpu->memory.activeRegion = memory->iwram;
cpu->memory.activeMask = GBA_SIZE_IWRAM - 1;
break;
case GBA_REGION_PALETTE_RAM:
cpu->memory.accessSource = mACCESS_PROGRAM;
cpu->memory.activeRegion = (uint32_t*) gba->video.palette;
cpu->memory.activeMask = GBA_SIZE_PALETTE_RAM - 1;
break;
case GBA_REGION_VRAM:
cpu->memory.accessSource = mACCESS_PROGRAM;
if (address & 0x10000) {
cpu->memory.activeRegion = (uint32_t*) &gba->video.vram[0x8000];
cpu->memory.activeMask = 0x00007FFF;
@ -324,6 +331,7 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
}
break;
case GBA_REGION_OAM:
cpu->memory.accessSource = mACCESS_PROGRAM;
cpu->memory.activeRegion = (uint32_t*) gba->video.oam.raw;
cpu->memory.activeMask = GBA_SIZE_OAM - 1;
break;
@ -333,6 +341,7 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
case GBA_REGION_ROM1_EX:
case GBA_REGION_ROM2:
case GBA_REGION_ROM2_EX:
cpu->memory.accessSource = mACCESS_PROGRAM;
cpu->memory.activeRegion = memory->rom;
cpu->memory.activeMask = memory->romMask;
if ((address & (GBA_SIZE_ROM0 - 1)) < memory->romSize) {
@ -345,6 +354,7 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
}
// Fall through
default:
cpu->memory.accessSource = mACCESS_UNKNOWN;
memory->activeRegion = -1;
cpu->memory.activeRegion = (uint32_t*) _deadbeef;
cpu->memory.activeMask = 0;

View File

@ -61,6 +61,7 @@ static void _checkWatchpoints(struct SM83Debugger* debugger, uint16_t address, e
info.type.wp.newValue = newValue;
info.type.wp.watchType = watchpoint->type;
info.type.wp.accessType = type;
info.type.wp.accessSource = debugger->cpu->memory.accessSource;
info.address = address;
info.segment = debugger->originalMemory.currentSegment(debugger->cpu, address);
info.width = 1;