- [FIX] Al fer break on interrupt de vegades se passava de instruccions

- [NEW] el analitzador pot mostrar les instruccions repetides des de l'ultim estat
- [NEW] gestió de opcodes usats
This commit is contained in:
2024-12-12 22:44:44 +01:00
parent c70c3652bf
commit 8c197d5519
6 changed files with 136 additions and 4 deletions

View File

@@ -201,6 +201,7 @@ int main(int argc, char *argv[])
zx_ula::sound_update(dt);
zxscreen::refresh(dt);
if (z80debug::debugging()) break;
}
}

32
z80.cpp
View File

@@ -193,6 +193,7 @@ namespace z80
{
WRITE_MEM_8(addr, value & 0xff);
WRITE_MEM_8(addr+1, (value>>8) & 0xff);
//if (value==0x7229) z80debug::stop();
}
void PUSH(uint16_t b)
@@ -675,6 +676,7 @@ namespace z80
if (options[Z80_OPTION_BREAK_ON_INTERRUPT]) {
printf("Break on interrupt! 0x%2x, PC: 0x%2x\n", address, rPC);
z80debug::setcursor(rPC);
z80debug::history::store();
z80debug::stop();
}
}
@@ -1081,8 +1083,10 @@ namespace z80
t = 0;
const uint8_t opcode = READ_M1();
memtag[current_opcode_address] = MEMTAG_INST;
memtouched[current_opcode_address] = MEMTAG_INST;
memtouched[current_opcode_address] = memtouched[current_opcode_address] != MEMTAG_NONE ? MEMTAG_REPEAT : MEMTAG_INST;
uint16_t tmp;
if (opcode!=0xED && opcode!=0xCB && opcode!=0xDD && opcode!=0xFD ) z80debug::useOpcode(opcode, 0);
switch (opcode)
{
@@ -1370,6 +1374,9 @@ namespace z80
void BIT_INSTRUCTIONS()
{
const uint8_t opcode = READ_M1();
z80debug::useOpcode(opcode, 2);
switch (opcode)
{
case 0x00: rB = RLC(rB); break;
@@ -1651,6 +1658,8 @@ namespace z80
const uint8_t opcode = READ_M1();
int8_t d;
if (opcode!=0xCB) z80debug::useOpcode(opcode, 3);
switch (opcode)
{
case 0x00: INVALID(opcode); break;
@@ -1872,6 +1881,9 @@ namespace z80
const int8_t d = READ_MEM_8();
const uint8_t opcode = READ_MEM_8();
t+=3;
z80debug::useOpcode(opcode, 4);
switch (opcode)
{
case 0x00: rB = WRITE_MEM_8(rIX+d, RLC(READ_MEM_8(rIX+d))); break;
@@ -2151,6 +2163,9 @@ namespace z80
void MISC_INSTRUCTIONS()
{
const uint8_t opcode = READ_M1();
z80debug::useOpcode(opcode, 1);
rR = (rR&0x80) + ((rR+1) & 0x7f);
uint16_t tmp;
@@ -2232,6 +2247,8 @@ namespace z80
const uint8_t opcode = READ_M1();
int8_t d;
if (opcode!=0xCB) z80debug::useOpcode(opcode, 5);
switch (opcode)
{
case 0x00: INVALID(opcode); break;
@@ -2453,6 +2470,9 @@ namespace z80
const int8_t d = READ_MEM_8();
const uint8_t opcode = READ_MEM_8();
t+=3;
z80debug::useOpcode(opcode, 6);
switch (opcode)
{
case 0x00: rB = WRITE_MEM_8(rIY+d, RLC(READ_MEM_8(rIY+d))); break;
@@ -2762,6 +2782,16 @@ namespace z80
for (int i=0; i<65536; ++i) memtouched[i] = MEMTAG_NONE;
}
void fixMemTouched()
{
for (int i=0; i<65536; ++i)
if ( (memtouched[i]==MEMTAG_INST) || (memtouched[i]==MEMTAG_REPEAT) )
memtouched[i] = MEMTAG_DATA;
//else if (memtouched[i]==MEMTAG_DATA)
// memtouched[i] = MEMTAG_REPEAT;
}
const bool getOption(const int option)
{
return options[option];

2
z80.h
View File

@@ -8,6 +8,7 @@ namespace z80
#define MEMTAG_INST 1
#define MEMTAG_CODE 2
#define MEMTAG_DATA 3
#define MEMTAG_REPEAT 4
#define Z80_OPTION_STOP_ON_INVALID 0
#define Z80_OPTION_BREAK_ON_INTERRUPT 1
@@ -42,6 +43,7 @@ namespace z80
uint8_t getMemTouched(const uint16_t addr);
void clearMemTouched();
void fixMemTouched();
const bool getOption(const int option);
void setOption(const int option, const bool value);

View File

@@ -17,12 +17,16 @@ namespace z80analyze
{
if (e->type == SDL_MOUSEBUTTONUP)
{
z80::clearMemTouched();
if (e->button.button == 1)
z80::clearMemTouched();
else
z80::fixMemTouched();
refresh();
}
if (e->type == SDL_MOUSEMOTION)
{
refreshTitle();
refresh();
}
return true;
}
@@ -31,6 +35,7 @@ namespace z80analyze
{
if (!win)
{
SDL_ShowCursor(SDL_DISABLE);
win = SDL_CreateWindow("Z80 Analyzer", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 512, 512, SDL_WINDOW_SHOWN);
ren = SDL_CreateRenderer(win, -1, 0);
tex = SDL_CreateTexture(ren, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, 256, 256);
@@ -60,9 +65,22 @@ namespace z80analyze
for (int i=0; i<65536; ++i)
{
uint8_t tag = z80::getMemTouched(i);
pixels[i] = tag==MEMTAG_NONE ? 0x808080 : tag==MEMTAG_DATA ? 0x0000FF : 0x00FF00;
pixels[i] = tag==MEMTAG_NONE ? 0x808080 : tag==MEMTAG_DATA ? 0x0000FF : tag==MEMTAG_REPEAT ? 0xFF0000 : 0x00FF00;
}
pixels[z80::getPC()] = 0xFF0000;
pixels[z80::getPC()] = 0xFFFFFF;
int mx, my;
SDL_GetMouseState(&mx, &my);
mx/=2; my/=2;
pixels[(mx-2)+(my)*256] = 0x000000;
pixels[(mx-1)+(my)*256] = 0x000000;
pixels[(mx+1)+(my)*256] = 0x000000;
pixels[(mx+2)+(my)*256] = 0x000000;
pixels[(mx)+(my-1)*256] = 0x000000;
pixels[(mx)+(my-2)*256] = 0x000000;
pixels[(mx)+(my+1)*256] = 0x000000;
pixels[(mx)+(my+2)*256] = 0x000000;
SDL_UnlockTexture(tex);
SDL_RenderCopy(ren, tex, NULL, NULL);
SDL_RenderPresent(ren);

View File

@@ -62,6 +62,8 @@ namespace z80debug
uint16_t cursor = 0;
uint8_t use[7][256];
char temp[256];
const char *tohex(int value, int numdigits)
{
@@ -106,12 +108,15 @@ namespace z80debug
} else if (e->key.keysym.scancode==SDL_SCANCODE_F1) {
z80debug::history::gototop();
z80debug::refresh();
z80analyze::refresh();
} else if (e->key.keysym.scancode==SDL_SCANCODE_F2) {
z80debug::history::goback();
z80debug::refresh();
z80analyze::refresh();
} else if (e->key.keysym.scancode==SDL_SCANCODE_F3) {
z80debug::history::goforward();
z80debug::refresh();
z80analyze::refresh();
/*} else if (e->key.keysym.scancode==SDL_SCANCODE_F6) {
z80debug::history::gototop();
const uint8_t dt = z80::step();
@@ -217,6 +222,7 @@ namespace z80debug
tex = ui::createtexture(ren);
}
focus();
z80analyze::refresh();
}
void focus()
@@ -611,9 +617,11 @@ namespace z80debug
if (strcmp(cmd, "s")==0 || strcmp(cmd, "step")==0) {
z80::step();
z80analyze::refresh();
} else if (strcmp(cmd, "c")==0 || strcmp(cmd, "cont")==0) {
z80::step();
z80debug::cont();
z80analyze::refresh();
} else if (strcmp(cmd, "r")==0 || strcmp(cmd, "reset")==0) {
uint8_t *mem = z80::getMem();
for (int i=0x4000; i<=0xffff; ++i) mem[i]=0;
@@ -621,6 +629,7 @@ namespace z80debug
z80::connect_port(0xfe, zx_ula::port_in, zx_ula::port_out);
//for (int i=0; i<65536; ++i) breakpoints[i]=0;
z80debug::refresh();
z80analyze::refresh();
} else if (strcmp(cmd, "b")==0 || strcmp(cmd, "break")==0) {
getcmd();
if (cmd[0] == 0) { breakpoints[z80::getPC()]=1; return; }
@@ -682,6 +691,7 @@ namespace z80debug
//strcpy(address, cmd);
//loadngo(filename, address);
loadstate(filename);
z80analyze::refresh();
} else if (strcmp(cmd, "t")==0 || strcmp(cmd, "tape")==0) {
getcmd();
if (strcmp(cmd, "load")==0) {
@@ -759,6 +769,17 @@ namespace z80debug
sendToConsoleLog("Keyup sent for key: ");
sendMoreToConsoleLog(cmd);
}
} else if (strcmp(cmd, "opcodes")==0) {
getcmd();
if (strcmp(cmd, "clear")==0 || strcmp(cmd, "reset")==0) {
clearUsedOpcodes();
} else if (strcmp(cmd, "mark")==0) {
markUsedOpcodes();
} else if (strcmp(cmd, "count")==0) {
printf("Num opcodes used: %i\n", getNumOpcodesUsed());
} else if (strcmp(cmd, "print")==0) {
printOpcodesUsed();
}
}
}
@@ -831,6 +852,60 @@ namespace z80debug
cursor = find_previous_opcode(cursor);
}
void useOpcode(const uint8_t opcode, const uint8_t base)
{
if (use[base][opcode]<255) use[base][opcode]++;
}
void clearUsedOpcodes()
{
for (int i=0; i<7; ++i) {
for (int j=0; j<256; ++j) {
use[i][j]=0;
}
}
}
void markUsedOpcodes()
{
for (int i=0; i<7; ++i) {
for (int j=0; j<256; ++j) {
if (use[i][j]==1) use[i][j]++;
}
}
}
const int getNumOpcodesUsed()
{
int count = 0;
for (int i=0; i<7; ++i) {
for (int j=0; j<256; ++j) {
if (use[i][j]==1) count++;
}
}
return count;
}
void printOpcodesUsed()
{
for (int i=0; i<7; ++i) {
for (int j=0; j<256; ++j) {
if (use[i][j]==1) {
switch (i) {
case 1: printf("ED "); break;
case 2: printf("CB "); break;
case 3: printf("DD "); break;
case 4: printf("DD CB "); break;
case 5: printf("FD "); break;
case 6: printf("FD CB "); break;
}
printf("%2X\n",j);
}
}
}
}
namespace history
{

View File

@@ -34,6 +34,12 @@ namespace z80debug
void cursorfwd();
void cursorback();
void useOpcode(const uint8_t opcode, const uint8_t base);
void clearUsedOpcodes();
void markUsedOpcodes();
const int getNumOpcodesUsed();
void printOpcodesUsed();
namespace history
{
void store();