[APEXC] 1. Added pseudo PC register for the debugger, it will now highlight the next instruction to be executed.

2. Added "normal" addresses to disassembler output, so anyone can see the program flow. [Robbbert]
This commit is contained in:
Miodrag Milanovic 2010-01-31 13:19:16 +00:00
parent 439b7362ac
commit a461dfee73
3 changed files with 31 additions and 19 deletions

View File

@ -356,6 +356,7 @@ struct _apexc_state
int running; /* 1 flag: */
/* running: flag implied by the existence of the stop instruction */
UINT32 pc; /* address of next instruction for the disassembler */
running_device *device;
const address_space *program;
@ -540,6 +541,7 @@ static void execute(apexc_state *cpustate)
function = (cpustate->cr >> 7) & 0x1F;
c6 = (cpustate->cr >> 1) & 0x3F;
vector = cpustate->cr & 1;
cpustate->pc = y<<2;
function &= 0x1E; /* this is a mere guess - the LSBit is reserved for future additions */
@ -595,6 +597,7 @@ static void execute(apexc_state *cpustate)
{
/* load ml with X */
delay1 = load_ml(cpustate, x, vector);
cpustate->pc = x<<2;
/* burn pre-fetch delay if needed */
if (delay1)
{
@ -827,7 +830,7 @@ static CPU_EXECUTE( apexc )
do
{
debugger_instruction_hook(device, effective_address(cpustate, cpustate->ml));
debugger_instruction_hook(device, cpustate->pc);
if (cpustate->running)
execute(cpustate);
@ -870,6 +873,7 @@ static CPU_SET_INFO( apexc )
case CPUINFO_INT_REGISTER + APEXC_A: cpustate->a = info->i; break;
case CPUINFO_INT_REGISTER + APEXC_R: cpustate->r = info->i; break;
case CPUINFO_INT_REGISTER + APEXC_ML: cpustate->ml = info->i & 0x3ff; break;
case CPUINFO_INT_REGISTER + APEXC_PC: cpustate->pc = info->i; break;
case CPUINFO_INT_REGISTER + APEXC_WS: cpustate->working_store = info->i & 0xf; break;
case CPUINFO_INT_REGISTER + APEXC_STATE: cpustate->running = info->i ? TRUE : FALSE; break;
}
@ -904,11 +908,7 @@ CPU_GET_INFO( apexc )
case CPUINFO_INT_SP: info->i = 0; /* no SP */ break;
case CPUINFO_INT_PC:
/* no PC - return memory location register instead, this should be
equivalent unless executed in the midst of an instruction */
info->i = effective_address(cpustate, cpustate->ml);
break;
case CPUINFO_INT_PREVIOUSPC: info->i = 0; /* no PC */ break;
case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->pc; /* psuedo-PC */ break;
/*case CPUINFO_INT_INPUT_STATE + ...:*/ /* no interrupts */
@ -916,6 +916,7 @@ CPU_GET_INFO( apexc )
case CPUINFO_INT_REGISTER + APEXC_A: info->i = cpustate->a; break;
case CPUINFO_INT_REGISTER + APEXC_R: info->i = cpustate->r; break;
case CPUINFO_INT_REGISTER + APEXC_ML: info->i = cpustate->ml; break;
case CPUINFO_INT_REGISTER + APEXC_PC: info->i = cpustate->pc; break;
case CPUINFO_INT_REGISTER + APEXC_WS: info->i = cpustate->working_store; break;
case CPUINFO_INT_REGISTER + APEXC_STATE: info->i = cpustate->running; break;
case CPUINFO_INT_REGISTER + APEXC_ML_FULL: info->i = effective_address(cpustate, cpustate->ml); break;
@ -940,6 +941,7 @@ CPU_GET_INFO( apexc )
case CPUINFO_STR_REGISTER + APEXC_A: sprintf(info->s, "A :%08X", cpustate->a); break;
case CPUINFO_STR_REGISTER + APEXC_R: sprintf(info->s, "R :%08X", cpustate->r); break;
case CPUINFO_STR_REGISTER + APEXC_ML: sprintf(info->s, "ML:%03X", cpustate->ml); break;
case CPUINFO_STR_REGISTER + APEXC_PC: sprintf(info->s, "PC:%03X", cpustate->pc); break;
case CPUINFO_STR_REGISTER + APEXC_WS: sprintf(info->s, "WS:%01X", cpustate->working_store); break;
case CPUINFO_STR_REGISTER + APEXC_STATE: sprintf(info->s, "CPU state:%01X", cpustate->running ? TRUE : FALSE); break;

View File

@ -13,9 +13,10 @@ enum
APEXC_WS, /* working store */
APEXC_STATE, /* whether CPU is running */
APEXC_ML_FULL /* read-only pseudo-register for exclusive use by the control panel code
APEXC_ML_FULL, /* read-only pseudo-register for exclusive use by the control panel code
in the apexc driver : enables it to get the complete address computed
from the contents of ML and WS */
APEXC_PC /* doesn't actually exist; is there for the disassembler */
};
CPU_GET_INFO( apexc );

View File

@ -51,6 +51,15 @@
For vector instructions, replace the first space on the right of the mnemonic
with a 'v'.
01-Feb-2010 (Robbbert):
I've added the actual address, (as shown in the extreme left of the debugger
output), so that you can see much easier how the program will flow. Example:
+C XXX(##/##) XXX(##/##)
The X value shows where the data word is located, and the Y value is the
address of the next instruction.
*/
enum _format_type {branch, shiftl, shiftr, multiply, store, swap, one_address, two_address};
typedef enum _format_type format_type;
@ -104,7 +113,7 @@ CPU_DISASSEMBLE( apexc )
case two_address:
case branch:
case swap:
buffer += sprintf(buffer, "%-10s", mnemonic); /* 10 chars*/
buffer += sprintf(buffer, " %-10s", mnemonic); /* 10 chars*/
break;
case shiftl:
@ -113,32 +122,32 @@ CPU_DISASSEMBLE( apexc )
n = c6;
else
n = 64-c6;
buffer += sprintf(buffer, "%-2s(%2d) ", mnemonic, n); /* 10 chars */
buffer += sprintf(buffer, " %-2s(%2d) ", mnemonic, n); /* 10 chars */
break;
case multiply:
n = 33-c6;
if (n == 32)
/* case "32" : do not show bit specifier */
buffer += sprintf(buffer, "%-10s", mnemonic); /* 10 chars */
buffer += sprintf(buffer, " %-10s", mnemonic); /* 10 chars */
else
buffer += sprintf(buffer, "%-2s(%2d) ", mnemonic, n); /* 10 chars */
buffer += sprintf(buffer, " %-2s(%2d) ", mnemonic, n); /* 10 chars */
break;
case store:
if (c6 == 0)
{ /* case "1-32" : do not show bit specifier */
buffer += sprintf(buffer, "%-10s", mnemonic); /* 10 chars*/
buffer += sprintf(buffer, " %-10s", mnemonic); /* 10 chars*/
}
else if (c6 & 0x20)
{ /* case "1-n" */
n = c6-32;
buffer += sprintf(buffer, "%-2s (1-%02d) ", mnemonic, n); /* 10 chars */
buffer += sprintf(buffer, " %-2s (1-%02d) ", mnemonic, n); /* 10 chars */
}
else
{ /* case "n-32" */
n = c6+1;
buffer += sprintf(buffer, "%-2s(%02d-32) ", mnemonic, n); /* 8 chars */
buffer += sprintf(buffer, " %-2s(%02d-32) ", mnemonic, n); /* 8 chars */
}
}
@ -147,28 +156,28 @@ CPU_DISASSEMBLE( apexc )
{
case branch:
buffer--; /* eat last char */
buffer += sprintf(buffer, "<(%02d/%02d) >=", (x >> 5) & 0x1f, x & 0x1f); /* 10+1 chars */
buffer += sprintf(buffer, "<%03X(%02d/%02d) >=", x<<2, (x >> 5) & 0x1f, x & 0x1f); /* 10+1 chars */
break;
case multiply:
case swap:
buffer += sprintf(buffer, "(%02d) ", (x >> 5) & 0x1f); /* 10 chars */
buffer += sprintf(buffer, " (%02d) ", (x >> 5) & 0x1f); /* 10 chars */
break;
case one_address:
case shiftl:
case shiftr:
buffer += sprintf(buffer, " "); /* 10 chars */
buffer += sprintf(buffer, " "); /* 10 chars */
break;
case two_address:
case store:
buffer += sprintf(buffer, "(%02d/%02d) ", (x >> 5) & 0x1f, x & 0x1f); /* 10 chars */
buffer += sprintf(buffer, "%03X(%02d/%02d) ", x<<2, (x >> 5) & 0x1f, x & 0x1f); /* 10 chars */
break;
}
/* print Y address */
buffer += sprintf(buffer, "(%02d/%02d)", (y >> 5) & 0x1f, y & 0x1f); /* 7 chars */
buffer += sprintf(buffer, "%03X(%02d/%02d)", y<<2, (y >> 5) & 0x1f, y & 0x1f); /* 7 chars */
return 4;
}