📄 agdi.cpp
字号:
if (pBX == NULL) { // setup a temporary Bp
if (nAdr != 0xFFFFFFFF) { // example: g,main
pBX = &abp;
abp.type = AG_ABREAK;
abp.enabled = 1;
abp.rcount = 1;
abp.ocount = 1;
abp.Adr = nAdr;
if (!SetClrBp (1, pBX)) { // setup temporary break
return;
}
}
}
GoCmd();
if (abp.enabled) { // clear temporary break
SetClrBp (0, &abp);
pBX = NULL;
}
GoMode = 0;
if (PlayDead) return;
curPC = ReadPC();
if (BrkWalk (curPC)) break;
}
SaCBreaks (0, nAdr); // set breakpoints (1:=set, 0:=clear)
}
/*
* Go/Step/Stop commands
*/
_EXPO_ U32 AG_GoStep (U16 nCode, U32 nSteps, GADR *pA) {
U32 nE;
if (PlayDead) return (0); // driver is disconnected.
nE = 0; // clear error code
switch (nCode) {
case AG_STOPRUN: // Stop Go/Step.
StopRun = 1;
nE = StopExec(); // nE: 1=Stopped, 0=executing
if (nE == 1) iRun = 0; // stopped.
if (!iRun) {
Invalidate(); // registers, caches, etc.
}
NumRecs = 0; // clear 'number of trace records'
break;
case AG_NSTEP: // execute 'nSteps' instruction steps
iRun = 1; // 'executing'
for ( ; nSteps != 0 ; --nSteps ) {
if (StopRun) break; // Stop-Button was pressed
if (Step() != 0x01) break; // 0x01 means 'Ok.'
}
StopRun = 0; // clear Stop-Button flag.
Invalidate(); // registers, caches, etc.
iRun = 0; // clear 'executing' flag
NumRecs = 0; // clear 'number of trace records'
break;
case AG_GOTILADR: // run til 'pA->Adr' or some Bp,
iRun = 1; // whichever comes first
GoUntil (pA->Adr);
StopRun = 0;
Invalidate(); // registers, caches, etc.
iRun = 0; // clear 'executing' flag
NumRecs = 0; // clear 'number of trace records'
break;
case AG_GOFORBRK: // run forever or till some Bp reached.
iRun = 1;
GoUntil (0xFFFFFFFF); // means 'go forever'
StopRun = 0;
Invalidate(); // registers, caches, etc.
iRun = 0; // clear 'executing' flag
NumRecs = 0; // clear 'number of trace records'
break;
}
if (PlayDead) { // target not connected
StopTarget(); // shut it down
PostMessage (hMfrm, Uv2Msg, MSG_UV2_TERMINATE, 0); // terminate ourselves
}
else {
GetRegs(); // get target registers
*pCURPC = REG51.nPC; // let uVision2 know about PC...
}
return (nE);
}
/*
* Serial Window read/write
*/
_EXPO_ U32 AG_Serial (U16 nCode, U32 nSerNo, U32 nMany, void *vp) {
struct SerAS va;
if (PlayDead) return (0); // driver is disconnected.
va.n1 = nSerNo; // 0:=Serial #1, 1:=Serial #2
va.n2 = nMany; // number of items to write
switch (nCode) {
case AG_SERBOUT: // write nMany bytes to Serial #1 Window of uVision2
va.v.pS = (SC8 *) vp; // content
SendMessage (hMfrm, Uv2Msg, MSG_UV2_SERBOUT, (LPARAM) &va);
break;
case AG_SERWOUT: // write nMany words to Serial #1 Window
// va.v.pW = (U16 *) vp; // content
// SendMessage (hMfrm, Uv2Msg, MSG_UV2_SERWOUT, (LPARAM) &va);
break;
case AG_SERXIN: // Key was pressed in Serial Window #1 or #2
// WriteToSerPort (nSerNo, (char *) vp, nMany); // Output to serial interface
// nSerno := Window number (#0 or #1)
// vp := &character(s) to send
// nMany := number of characters to send
break;
}
return (0);
}
#if 0 // Example on how to output a string to uVision's serial window #1:
char szSerTxt[] = "this should appear in serial window #1";
AG_Serial (AG_SERBOUT, 0, sizeof (szSerTxt) - 1, (void *) szSerTxt);
#endif
/*
* Calculate Trace History
*/
#define MAXTRC 256 // assume 1024 (use a power of two value)
static DWORD TracePC [MAXTRC]; // trace code-address buffer
static int CalcNumRecords (void) {
if (NumRecs == 0) { // seems to be invalidated
//---just a test vector:
TracePC [0] = 0x0000000; // Slot[0] not used.
TracePC [1] = 0x0000047;
TracePC [2] = 0x0000049;
TracePC [3] = 0x000004B;
TracePC [4] = 0x000004C;
TracePC [5] = 0x0000050;
TracePC [6] = 0x0000050;
TracePC [7] = 0x0000050;
TracePC [8] = 0x0000050;
TracePC [9] = 0x0000050;
TracePC[10] = 0x0000050;
NumRecs = 10; // assume 10 entries
// Calc:
// TracePC [0] := unused
// TracePC [1] := newest code address
// ..
// TracePC [n] := oldest code address ( n >= 0, n < MAXTRC )
}
return (NumRecs);
}
/*
* Trace-History access function:
* - the first call is always nCode 3 for 'query number of records'
* - then nCode 0 / 1 are activated.
* Note: Emulator hardware must support tracing
*/
_EXPO_ U32 AG_HistFunc (U32 nCode, I32 indx, I32 dir, void *vp) {
U32 nR = 0;
if (PlayDead) return (0);
switch (nCode) {
case 0: // Function #0: get Hist index
if (NumRecs == 0) break;
if (dir) { // dir, 1:=towards older entries
if (indx < NumRecs) {
nR = indx + 1;
}
}
else { // dir, 0:=towards newer entries
if (indx > 0) nR = indx - 1;
else nR = 0;
}
break;
case 1: // Function #1: GetTracePC
if (indx >= 0 && indx < MAXTRC) {
nR = TracePC [indx]; // get PC of trace record 'indx'
nR |= amCODE << 24;
}
break;
case 2: // Function #2: GetHistRegs
// this function should be ignored since regs are not recorded anyway.
break; // get recorded regs of record 'indx'
case 3: // Function #3: get Nr. of entries
if (iRun) return (0); // block view-trace while running
// - Find out the number of instructions based on the TRACE-Sfrs up to,
// but not including the current PC
//***NOTE: make sure that CalcNumRecords() is as fast as possible since
// it is called many times due to Billy's OnUpdate() handling.
NumRecs = CalcNumRecords();
nR = NumRecs; // return-value.
break;
}
if (PlayDead == 1) {
StopTarget();
PostMessage (hMfrm, Uv2Msg, MSG_UV2_TERMINATE, 0);
}
return (nR);
}
/*
* Register View Management
*/
struct rGroup rGroups[] = {
{ 0x00, 0x01, "Regs", }, // Group 0, show expanded
{ 0x00, 0x01, "Sys", }, // Group 1, show expanded
};
struct rItem rItems[] = {
//--desc-nGi-nItem-szReg[]--isPC-cc-iHig--
{ 0x01, 0, 0x00, "r0", 0, 1, 0, },
{ 0x01, 0, 0x01, "r1", 0, 1, 0, },
{ 0x01, 0, 0x02, "r2", 0, 1, 0, },
{ 0x01, 0, 0x03, "r3", 0, 1, 0, },
{ 0x01, 0, 0x04, "r4", 0, 1, 0, },
{ 0x01, 0, 0x05, "r5", 0, 1, 0, },
{ 0x01, 0, 0x06, "r6", 0, 1, 0, },
{ 0x01, 0, 0x07, "r7", 0, 1, 0, },
{ 0x01, 1, 0x10, "a", 0, 1, 0, },
{ 0x01, 1, 0x11, "b", 0, 1, 0, },
{ 0x01, 1, 0x12, "sp", 0, 1, 0, },
{ 0x01, 1, 0x13, "dptr", 0, 1, 0, },
{ 0x01, 1, 0x14, "PC $", 1, 1, 0, },
//{ 0x01, 1, 0x15, "states", 0, 0, 0, },
//{ 0x01, 1, 0x16, "sec", 0, 0, 0, },
{ 0x01, 1, 0x100,"psw", 0, 1, 0, },
{ 0x01, 1, 0x101,"p", 0, 1, 0, }, // child-0
{ 0x01, 1, 0x102,"f1", 0, 1, 0, }, // child-1
{ 0x01, 1, 0x103,"ov", 0, 1, 0, },
{ 0x01, 1, 0x104,"rs", 0, 1, 0, },
{ 0x01, 1, 0x105,"f0", 0, 1, 0, },
{ 0x01, 1, 0x106,"ac", 0, 1, 0, },
{ 0x01, 1, 0x107,"cy", 0, 1, 0, },
{ 0x01, 1, 0x108,"", 0, 0, 0, }, // End of 'psw' children.
};
struct bmsk {
U16 mask;
I32 shft;
};
static const struct bmsk mx51[] = {
{ 0x0001, 0, }, // P
{ 0x0002, 1, }, // F1
{ 0x0004, 2, }, // OV
{ 0x0018, 3, }, // RS0, RS1
{ 0x0020, 5, }, // F0
{ 0x0040, 6, }, // AC
{ 0x0080, 7, }, // CY
};
static BYTE nRmode;
static BYTE nRstat;
static RG51 uRg; // shadow registers
static char szV [128]; // temporary buffer
/*
* uVision2 want's to display some registers value...
*/
static void RegGet (RITEM *vp, int nR) {
GVAL v;
U32 n, z;
if (PlayDead) return; // target is disconnected...
switch (nR & 0xF0000000) {
case UPR_NORMAL: // Setup Normal Regs
GetRegs(); // update our local regs
uRg = REG51; // capture current regs
nRmode = 0; // normal mode
*pCURPC = uRg.nPC; // C:0xnnnn
if (PlayDead) { // target died...
StopTarget();
PostMessage (hMfrm, Uv2Msg, MSG_UV2_TERMINATE, 0); // Bye
}
return;
case UPR_HIST: // Setup History Regs
//--- currently not supported !
// v.i32 = nR & 0xFFFF; // History index (max. 64K entries)
// if (ioc.numtra != MAXTRC) v.i32 = (ioc.numtra - v.i32) & (MAXTRC - 1);
// else v.i32 = (ioc.curtra - v.i32) & (MAXTRC - 1);
// uRg = *(((REG51 *) ioc.trap) + v.i32); // HistRegs
// nRstat = 1; // mark 'PSW' as current.
// nRmode = 1; // history mode
return;
}
v.u64 = 0;
vp->iDraw = 0;
switch (vp->nItem) {
case 0x00: case 0x01: case 0x02: case 0x03:
case 0x04: case 0x05: case 0x06: case 0x07:
v.uc = uRg.Rn [vp->nItem & 0x07]; // current Rn
x8: if (v.uc != vp->v.uc || vp->szVal[0] == 0) {
sprintf (vp->szVal, "0x%02x", v.u32);
}
break;
case 0x10: v.uc = uRg.acc; goto x8; // A
case 0x11: v.uc = uRg.b; goto x8; // B
case 0x12: v.uc = uRg.sp; goto x8; // SP
case 0x13: // DPTR
v.u16 = ((U16) uRg.dph) << 8 | (U16) uRg.dpl;
if (v.u16 != vp->v.u16 || vp->szVal[0] == 0) {
sprintf (vp->szVal, "0x%04x", v.u32);
}
break;
case 0x14: // 'PC $'
if (uRg.nPC != vp->v.u32 || vp->szVal[0] == 0) {
sprintf (vp->szVal, "0x%04x", uRg.nPC & 0xFFFF);
vp->iDraw = 1;
}
vp->v.u32 = uRg.nPC;
vp->iHigh = 0; // never highlighted
return;
case 0x15: // States
case 0x16: // Seconds
// not relevant in target mode
return;
case 0x100: // PSW
case 0x101: // P
case 0x102: // F1
case 0x103: // OV
case 0x104: // RS
case 0x105: // F0
case 0x106: // AC
case 0x107: // Cy
if (vp->nItem == 0x100) { // PSW
v.uc = uRg.psw; // want PSW only
goto x8;
}
//--- want some bit from PSW:
n = vp->nItem - 0x101; // use item-number as index
z = uRg.psw & mx51[n].mask; // masked value, not normalized
v.u32 = z >> mx51[n].shft; // normalize
if (v.u32 != vp->v.u32 || vp->szVal[0] == 0) { // value changed
sprintf (vp->szVal, "%d ", v.u32); // spaces to ease mouse hit.
}
break;
}
if (v.u32 == vp->v.u32) { // value unchanged
if (vp->iHigh) { // item is currently highlighted
vp->iHigh = 0; // clear highlight color
vp->iDraw = 1; // need repaint.
}
}
else { // value changed
vp->iHigh = 1; // highlight
vp->iDraw = 1; // need repaint
}
vp->v.u64 = v.u64; // update 'On Screen' value
}
/*
* uVision2 want's to change some registers value...
*/
static I32 RegSet (RITEM *vp, GVAL *pV) {
I32 n;
U16 val;
if (nRmode == 1) return (0); // Error: can't change HistRegs !
if (PlayDead) return (0); // cancel: driver is disconnected...
if (iRun) return (0); // cancel: currently running...
switch (vp->nItem) {
default: return (0);
case 0x00: case 0x01: case 0x02: case 0x03: // R0...R7
case 0x04: case 0x05: case 0x06: case 0x07:
uRg.Rn [vp->nItem & 0x07] = pV->uc;
x: SetRegs (&uRg);
break;
case 0x10: uRg.acc = pV->uc; goto x; // A
case 0x11: uRg.b = pV->uc; goto x; // B
case 0x12: uRg.sp = pV->uc; goto x; // SP
case 0x13:
uRg.dpl = (BYTE) pV->u16;
uRg.dph = (BYTE) (pV->u16 >> 8);
goto x;
case 0x14:
if (iRun) return (0); // $ PC: can't change while running...
uRg.nPC = (pV->ul & 0xFFFF) | (amCODE << 24);
goto x;
// case 0x15: // states, can't change
// case 0x16: // sec, can't change
// break;
case 0x100: // PSW
uRg.psw = pV->uc;
goto x;
case 0x101: // P
case 0x102: // F1
case 0x103: // OV
case 0x104: // RS
case 0x105: // F0
case 0x106: // AC
case 0x107: // Cy
val = pV->uc;
n = vp->nItem - 0x101; // use Item-number for index
uRg.psw &= ~mx51[n].mask; // clear value
val = (val << mx51[n].shft) & mx51[n].mask;
uRg.psw |= (BYTE) val;
nRstat = 1; // mark 'PSW' as curr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -