New Debugger command to dump Bus memory allocations
This commit is contained in:
parent
b71fd5002b
commit
fa88aa6a2d
9 changed files with 316 additions and 72 deletions
|
|
@ -44,3 +44,189 @@ to change our assertion from "cpu.addrIDTLimit == 0x03FF" to "cpu.addrIDTLimit >
|
||||||
Checkpoint
|
Checkpoint
|
||||||
---
|
---
|
||||||
The BIOS now progresses as far as F000:F747 (PUSH GS).
|
The BIOS now progresses as far as F000:F747 (PUSH GS).
|
||||||
|
|
||||||
|
Checkpoint
|
||||||
|
---
|
||||||
|
The BIOS now progresses as far as 0030:8618 (MOV AX,GS).
|
||||||
|
|
||||||
|
Checkpoint
|
||||||
|
---
|
||||||
|
The BIOS now progresses to a Compaq memory-mapped write operation:
|
||||||
|
|
||||||
|
stopped (27129586 ops, 2209813 cycles, 361 ms, 6121366 hz)
|
||||||
|
EAX=000098FC EBX=0000E000 ECX=00000000 EDX=00000000
|
||||||
|
ESP=000000E4 EBP=00000000 ESI=0000FFFF EDI=00007FBE
|
||||||
|
SS=0028[00000300,FFFF] DS=0050[80C00000,FFFF] ES=0048[00FF0000,FFFF]
|
||||||
|
CS=0030[000F0000,FFFF] FS=0000[00000000,FFFF] GS=0304[00003040,FFFF]
|
||||||
|
LD=0000[00000000,0000] GD=[0001C000,005F] ID=[000FF821,0007] TR=0000 A20=ON
|
||||||
|
CR0=0000FFF1 CR2=00000000 CR3=00000000 PS=00000083 V0 D0 I0 T0 S1 Z0 A0 P0 C1
|
||||||
|
0030:8637 C6060000FC MOV [0000],FC ;history=1
|
||||||
|
|
||||||
|
and then gets stuck loading CS:IP of 0x28:0xF4AC:
|
||||||
|
|
||||||
|
assertion failure in deskpro386.cpu386
|
||||||
|
Fault 0x0D blocked by Debugger
|
||||||
|
stopped (27572151 ops, 443210 cycles, 340635 ms, 1301 hz)
|
||||||
|
EAX=0000FFF1 EBX=00000080 ECX=0000270F EDX=0000004A
|
||||||
|
ESP=000000FE EBP=00000000 ESI=00007FB6 EDI=00008000
|
||||||
|
SS=0030[00000300,FFFF] DS=0040[00000400,FFFF] ES=0000[00000000,FFFF]
|
||||||
|
CS=F000[000F0000,FFFF] FS=0000[00000000,FFFF] GS=0304[00003040,FFFF]
|
||||||
|
LD=0000[00000000,0000] GD=[00FF0730,0047] ID=[00000000,FFFF] TR=0000 A20=OFF
|
||||||
|
CR0=0000FFF1 CR2=00000000 CR3=00000000 PS=00000082 V0 D0 I0 T0 S1 Z0 A0 P0 C0
|
||||||
|
F000:F4A7 EAACF42800 JMP 0028:F4AC
|
||||||
|
|
||||||
|
Here's the code leading up to it:
|
||||||
|
|
||||||
|
F000:F494 B000 MOV AL,00 ;history=8
|
||||||
|
F000:F496 E680 OUT 80,AL ;history=7
|
||||||
|
F000:F498 2E CS: ;history=6
|
||||||
|
F000:F499 0F01167E07 LGDT [077E] ;history=5
|
||||||
|
F000:F49E 0F2000 MOV EAX,CR0 ;history=4
|
||||||
|
F000:F4A1 0D0100 OR AX,0001 ;history=3
|
||||||
|
F000:F4A4 0F2200 MOV CR0,EAX ;history=2
|
||||||
|
F000:F4A7 EAACF42800 JMP 0028:F4AC ;history=1
|
||||||
|
|
||||||
|
Set the following breakpoints:
|
||||||
|
|
||||||
|
breakpoint enabled: F000:F498 (exec)
|
||||||
|
breakpoint enabled: %00FF0758 (write)
|
||||||
|
|
||||||
|
The write breakpoint first catches the code at 0030:F692 copying ROM data near F000:F378
|
||||||
|
to memory at %0x00FF0000 near 0x738.
|
||||||
|
|
||||||
|
It later catches code at 0030:C924 writing to that region.
|
||||||
|
|
||||||
|
Then code at 0030:8590:
|
||||||
|
|
||||||
|
EAX=00000048 EBX=000010F0 ECX=00003E29 EDX=00000000
|
||||||
|
ESP=000000E4 EBP=00000000 ESI=0000075C EDI=0000075C
|
||||||
|
SS=0028[00000300,FFFF] DS=0050[000F0000,FFFF] ES=0048[00FF0000,FFFF]
|
||||||
|
CS=0030[000F0000,FFFF] FS=0000[00000000,FFFF] GS=0304[00003040,FFFF]
|
||||||
|
LD=0000[00000000,0000] GD=[0001C000,005F] ID=[000FF821,0007] TR=0000 A20=ON
|
||||||
|
CR0=0000FFF1 CR2=00000000 CR3=00000000 PS=00000046 V0 D0 I0 T0 S0 Z1 A0 P1 C0
|
||||||
|
0030:8590 66F3 REPZ
|
||||||
|
|
||||||
|
dw ds:73c l10
|
||||||
|
0050:073C 92C0 8000 FFFF 0000 - 9200 0000 FFFF 0000 ................
|
||||||
|
0050:074C 9A0F 0000 FFFF 0000 - 9200 C000 FFFF 0000 ................
|
||||||
|
|
||||||
|
dw es:73c l10
|
||||||
|
0048:073C 92C0 8000 FFFF 0000 - 9200 0000 FFFF 0000 ................
|
||||||
|
0048:074C 9A0F 0000 FFFF 0000 - 9200 C000 FFFF 0000 ................
|
||||||
|
|
||||||
|
dw %ff073c l10
|
||||||
|
%00FF073C 92C0 8000 FFFF 0000 - 9200 0000 FFFF 0000 ................
|
||||||
|
%00FF074C 9A0F 0000 FFFF 0000 - 9200 C000 FFFF 0000 ................
|
||||||
|
|
||||||
|
Next we stopped here, and the memory at %ff07ec was still good:
|
||||||
|
|
||||||
|
stopped (27129603 ops, 555386 cycles, 117 ms, 4746889 hz)
|
||||||
|
EAX=000098FC EBX=0000E000 ECX=00000000 EDX=00000000
|
||||||
|
ESP=000000E4 EBP=00000000 ESI=0000FFFF EDI=00007FBE
|
||||||
|
SS=0028[00000300,FFFF] DS=0050[80C00000,FFFF] ES=0048[00FF0000,FFFF]
|
||||||
|
CS=0030[000F0000,FFFF] FS=0000[00000000,FFFF] GS=0304[00003040,FFFF]
|
||||||
|
LD=0000[00000000,0000] GD=[0001C000,005F] ID=[000FF821,0007] TR=0000 A20=ON
|
||||||
|
CR0=0000FFF1 CR2=00000000 CR3=00000000 PS=00000083 V0 D0 I0 T0 S1 Z0 A0 P0 C1
|
||||||
|
0030:863C 1F POP DS
|
||||||
|
|
||||||
|
%00FF073C 92C0 8000 FFFF 0000 - 9200 0000 FFFF 0000 ................
|
||||||
|
%00FF074C 9A0F 0000 FFFF 0000 - 9200 C000 FFFF 0000 ................
|
||||||
|
|
||||||
|
BEFORE AFTER
|
||||||
|
====== =====
|
||||||
|
|
||||||
|
id physaddr blkaddr used size type id physaddr blkaddr used size type
|
||||||
|
-------- --------- -------- ------ ------ ---- -------- --------- -------- ------ ------ ----
|
||||||
|
00020003 %00000000: 00000000 0x8000 0x8000 RAM 00020003 %00000000: 00000000 0x8000 0x8000 RAM
|
||||||
|
00020004 %00008000: 00008000 0x8000 0x8000 RAM 00020004 %00008000: 00008000 0x8000 0x8000 RAM
|
||||||
|
00020005 %00010000: 00010000 0x8000 0x8000 RAM 00020005 %00010000: 00010000 0x8000 0x8000 RAM
|
||||||
|
00020006 %00018000: 00018000 0x8000 0x8000 RAM 00020006 %00018000: 00018000 0x8000 0x8000 RAM
|
||||||
|
00020007 %00020000: 00020000 0x8000 0x8000 RAM 00020007 %00020000: 00020000 0x8000 0x8000 RAM
|
||||||
|
00020008 %00028000: 00028000 0x8000 0x8000 RAM 00020008 %00028000: 00028000 0x8000 0x8000 RAM
|
||||||
|
00020009 %00030000: 00030000 0x8000 0x8000 RAM 00020009 %00030000: 00030000 0x8000 0x8000 RAM
|
||||||
|
0002000A %00038000: 00038000 0x8000 0x8000 RAM 0002000A %00038000: 00038000 0x8000 0x8000 RAM
|
||||||
|
0002000B %00040000: 00040000 0x8000 0x8000 RAM 0002000B %00040000: 00040000 0x8000 0x8000 RAM
|
||||||
|
0002000C %00048000: 00048000 0x8000 0x8000 RAM 0002000C %00048000: 00048000 0x8000 0x8000 RAM
|
||||||
|
0002000D %00050000: 00050000 0x8000 0x8000 RAM 0002000D %00050000: 00050000 0x8000 0x8000 RAM
|
||||||
|
0002000E %00058000: 00058000 0x8000 0x8000 RAM 0002000E %00058000: 00058000 0x8000 0x8000 RAM
|
||||||
|
0002000F %00060000: 00060000 0x8000 0x8000 RAM 0002000F %00060000: 00060000 0x8000 0x8000 RAM
|
||||||
|
00020010 %00068000: 00068000 0x8000 0x8000 RAM 00020010 %00068000: 00068000 0x8000 0x8000 RAM
|
||||||
|
00020011 %00070000: 00070000 0x8000 0x8000 RAM 00020011 %00070000: 00070000 0x8000 0x8000 RAM
|
||||||
|
00020012 %00078000: 00078000 0x8000 0x8000 RAM 00020012 %00078000: 00078000 0x8000 0x8000 RAM
|
||||||
|
00020013 %00080000: 00080000 0x8000 0x8000 RAM 00020013 %00080000: 00080000 0x8000 0x8000 RAM
|
||||||
|
00020014 %00088000: 00088000 0x8000 0x8000 RAM 00020014 %00088000: 00088000 0x8000 0x8000 RAM
|
||||||
|
00020015 %00090000: 00090000 0x8000 0x8000 RAM 00020015 %00090000: 00090000 0x8000 0x8000 RAM
|
||||||
|
00020016 %00098000: 00098000 0x8000 0x8000 RAM 00020016 %00098000: 00098000 0x8000 0x8000 RAM
|
||||||
|
00020044 %000B8000: 000B8000 0x8000 0x8000 VIDEO 00020050 %000B8000: 000B8000 0x8000 0x8000 VIDEO
|
||||||
|
00020001 %000C0000: 000C0000 0x4000 0x8000 ROM 00020001 %000C0000: 000C0000 0x4000 0x8000 ROM
|
||||||
|
|
||||||
|
00020051 %000E0000: 000E0000 0x???? 0x8000 ROM
|
||||||
|
00020052 %000E8000: 000E0000 0x???? 0x8000 ROM
|
||||||
|
00020002 %000F0000: 000F8000 0x8000 0x8000 ROM 00020053 %000F0000: 000E0000 0x???? 0x8000 ROM
|
||||||
|
00020002 %000F8000: 000F8000 0x8000 0x8000 ROM 00020054 %000F8000: 000E0000 0x???? 0x8000 ROM
|
||||||
|
|
||||||
|
00020024 %00100000: 00100000 0x8000 0x8000 RAM 00020024 %00100000: 00100000 0x8000 0x8000 RAM
|
||||||
|
00020025 %00108000: 00108000 0x8000 0x8000 RAM 00020025 %00108000: 00108000 0x8000 0x8000 RAM
|
||||||
|
00020026 %00110000: 00110000 0x8000 0x8000 RAM 00020026 %00110000: 00110000 0x8000 0x8000 RAM
|
||||||
|
00020027 %00118000: 00118000 0x8000 0x8000 RAM 00020027 %00118000: 00118000 0x8000 0x8000 RAM
|
||||||
|
00020028 %00120000: 00120000 0x8000 0x8000 RAM 00020028 %00120000: 00120000 0x8000 0x8000 RAM
|
||||||
|
00020029 %00128000: 00128000 0x8000 0x8000 RAM 00020029 %00128000: 00128000 0x8000 0x8000 RAM
|
||||||
|
0002002A %00130000: 00130000 0x8000 0x8000 RAM 0002002A %00130000: 00130000 0x8000 0x8000 RAM
|
||||||
|
0002002B %00138000: 00138000 0x8000 0x8000 RAM 0002002B %00138000: 00138000 0x8000 0x8000 RAM
|
||||||
|
0002002C %00140000: 00140000 0x8000 0x8000 RAM 0002002C %00140000: 00140000 0x8000 0x8000 RAM
|
||||||
|
0002002D %00148000: 00148000 0x8000 0x8000 RAM 0002002D %00148000: 00148000 0x8000 0x8000 RAM
|
||||||
|
0002002E %00150000: 00150000 0x8000 0x8000 RAM 0002002E %00150000: 00150000 0x8000 0x8000 RAM
|
||||||
|
0002002F %00158000: 00158000 0x8000 0x8000 RAM 0002002F %00158000: 00158000 0x8000 0x8000 RAM
|
||||||
|
00020030 %00160000: 00160000 0x8000 0x8000 RAM 00020030 %00160000: 00160000 0x8000 0x8000 RAM
|
||||||
|
00020031 %00168000: 00168000 0x8000 0x8000 RAM 00020031 %00168000: 00168000 0x8000 0x8000 RAM
|
||||||
|
00020032 %00170000: 00170000 0x8000 0x8000 RAM 00020032 %00170000: 00170000 0x8000 0x8000 RAM
|
||||||
|
00020033 %00178000: 00178000 0x8000 0x8000 RAM 00020033 %00178000: 00178000 0x8000 0x8000 RAM
|
||||||
|
00020034 %00180000: 00180000 0x8000 0x8000 RAM 00020034 %00180000: 00180000 0x8000 0x8000 RAM
|
||||||
|
00020035 %00188000: 00188000 0x8000 0x8000 RAM 00020035 %00188000: 00188000 0x8000 0x8000 RAM
|
||||||
|
00020036 %00190000: 00190000 0x8000 0x8000 RAM 00020036 %00190000: 00190000 0x8000 0x8000 RAM
|
||||||
|
00020037 %00198000: 00198000 0x8000 0x8000 RAM 00020037 %00198000: 00198000 0x8000 0x8000 RAM
|
||||||
|
00020038 %001A0000: 001A0000 0x8000 0x8000 RAM 00020038 %001A0000: 001A0000 0x8000 0x8000 RAM
|
||||||
|
00020039 %001A8000: 001A8000 0x8000 0x8000 RAM 00020039 %001A8000: 001A8000 0x8000 0x8000 RAM
|
||||||
|
0002003A %001B0000: 001B0000 0x8000 0x8000 RAM 0002003A %001B0000: 001B0000 0x8000 0x8000 RAM
|
||||||
|
0002003B %001B8000: 001B8000 0x8000 0x8000 RAM 0002003B %001B8000: 001B8000 0x8000 0x8000 RAM
|
||||||
|
0002003C %001C0000: 001C0000 0x8000 0x8000 RAM 0002003C %001C0000: 001C0000 0x8000 0x8000 RAM
|
||||||
|
0002003D %001C8000: 001C8000 0x8000 0x8000 RAM 0002003D %001C8000: 001C8000 0x8000 0x8000 RAM
|
||||||
|
0002003E %001D0000: 001D0000 0x8000 0x8000 RAM 0002003E %001D0000: 001D0000 0x8000 0x8000 RAM
|
||||||
|
0002003F %001D8000: 001D8000 0x8000 0x8000 RAM 0002003F %001D8000: 001D8000 0x8000 0x8000 RAM
|
||||||
|
00020040 %001E0000: 001E0000 0x8000 0x8000 RAM 00020040 %001E0000: 001E0000 0x8000 0x8000 RAM
|
||||||
|
00020041 %001E8000: 001E8000 0x8000 0x8000 RAM 00020041 %001E8000: 001E8000 0x8000 0x8000 RAM
|
||||||
|
00020042 %001F0000: 001F0000 0x8000 0x8000 RAM 00020042 %001F0000: 001F0000 0x8000 0x8000 RAM
|
||||||
|
00020043 %001F8000: 001F8000 0x8000 0x8000 RAM 00020043 %001F8000: 001F8000 0x8000 0x8000 RAM
|
||||||
|
|
||||||
|
00020017 %00FA0000: 00FA0000 0x8000 0x8000 RAM 00020017 %00FA0000: 00FA0000 0x8000 0x8000 RAM
|
||||||
|
00020018 %00FA8000: 00FA8000 0x8000 0x8000 RAM 00020018 %00FA8000: 00FA8000 0x8000 0x8000 RAM
|
||||||
|
00020019 %00FB0000: 00FB0000 0x8000 0x8000 RAM 00020019 %00FB0000: 00FB0000 0x8000 0x8000 RAM
|
||||||
|
0002001A %00FB8000: 00FB8000 0x8000 0x8000 RAM 0002001A %00FB8000: 00FB8000 0x8000 0x8000 RAM
|
||||||
|
0002001B %00FC0000: 00FC0000 0x8000 0x8000 RAM 0002001B %00FC0000: 00FC0000 0x8000 0x8000 RAM
|
||||||
|
0002001C %00FC8000: 00FC8000 0x8000 0x8000 RAM 0002001C %00FC8000: 00FC8000 0x8000 0x8000 RAM
|
||||||
|
0002001D %00FD0000: 00FD0000 0x8000 0x8000 RAM 0002001D %00FD0000: 00FD0000 0x8000 0x8000 RAM
|
||||||
|
0002001E %00FD8000: 00FD8000 0x8000 0x8000 RAM 0002001E %00FD8000: 00FD8000 0x8000 0x8000 RAM
|
||||||
|
0002001F %00FE0000: 00FE0000 0x8000 0x8000 RAM 0002001F %00FE0000: 00FE0000 0x8000 0x8000 RAM
|
||||||
|
00020020 %00FE8000: 00FE8000 0x8000 0x8000 RAM 00020020 %00FE8000: 00FE8000 0x8000 0x8000 RAM
|
||||||
|
00020021 %00FF0000: 00FF0000 0x8000 0x8000 RAM 00020021 %00FF0000: 00FF0000 0x8000 0x8000 RAM
|
||||||
|
00020022 %00FF8000: 00FF8000 0x8000 0x8000 RAM 00020022 %00FF8000: 00FF8000 0x8000 0x8000 RAM
|
||||||
|
|
||||||
|
00020023 %80C00000: 80C00000 0x0001 0x8000 H/W 00020023 %80C00000: 80C00000 0x0001 0x8000 H/W
|
||||||
|
00020002 %FFFF0000: 000F8000 0x8000 0x8000 ROM 00020002 %FFFF0000: 000F8000 0x8000 0x8000 ROM
|
||||||
|
00020002 %FFFF8000: 000F8000 0x8000 0x8000 ROM 00020002 %FFFF8000: 000F8000 0x8000 0x8000 ROM
|
||||||
|
|
||||||
|
But when we stopped here next, it was no longer good:
|
||||||
|
|
||||||
|
breakpoint hit: F000:F498 (exec)
|
||||||
|
stopped (27572162 ops, 443166 cycles, 143 ms, 3099063 hz)
|
||||||
|
EAX=0000FF00 EBX=00000080 ECX=0000270F EDX=0000004A
|
||||||
|
ESP=000000FE EBP=00000000 ESI=00007FB6 EDI=00008000
|
||||||
|
SS=0030 DS=0040 ES=0000 FS=0000 GS=0304 PS=00000046 V0 D0 I0 T0 S0 Z1 A0 P1 C0
|
||||||
|
F000:F498 2E CS:
|
||||||
|
F000:F499 0F01167E07 LGDT [077E]
|
||||||
|
|
||||||
|
F000:077E 0047 0730 00FF FFFF - 0000 0000 87AA 0018 G.0.............
|
||||||
|
F000:078E 87F8 0018 8828 0018 - 0F2E 1601 0778 200F ....(.......x..
|
||||||
|
|
||||||
|
%00FF0730 0000 0000 0000 0000 - 0000 0000 0000 0000 ................
|
||||||
|
%00FF0740 0000 0000 0000 0000 - 0000 0000 0000 0000 ................
|
||||||
|
|
|
||||||
|
|
@ -273,6 +273,7 @@ Bus.prototype.initMemory = function()
|
||||||
for (var iBlock = 0; iBlock < this.blockTotal; iBlock++) {
|
for (var iBlock = 0; iBlock < this.blockTotal; iBlock++) {
|
||||||
var addr = iBlock * this.blockSize;
|
var addr = iBlock * this.blockSize;
|
||||||
var block = this.aMemBlocks[iBlock] = new Memory(addr);
|
var block = this.aMemBlocks[iBlock] = new Memory(addr);
|
||||||
|
|
||||||
if (DEBUGGER) block.setDebugInfo(this.cpu, this.dbg, this.blockSize);
|
if (DEBUGGER) block.setDebugInfo(this.cpu, this.dbg, this.blockSize);
|
||||||
}
|
}
|
||||||
this.cpu.initMemory(this.aMemBlocks, this.blockShift, this.blockLimit, this.blockMask);
|
this.cpu.initMemory(this.aMemBlocks, this.blockShift, this.blockLimit, this.blockMask);
|
||||||
|
|
@ -597,6 +598,7 @@ Bus.prototype.setMemoryBlocks = function(addr, size, aBlocks, type)
|
||||||
block = aBlocks[i++];
|
block = aBlocks[i++];
|
||||||
} else {
|
} else {
|
||||||
block = new Memory(addr);
|
block = new Memory(addr);
|
||||||
|
if (DEBUGGER) block.setDebugInfo(this.cpu, this.dbg, this.blockSize);
|
||||||
block.clone(aBlocks[i++], type);
|
block.clone(aBlocks[i++], type);
|
||||||
}
|
}
|
||||||
this.aMemBlocks[iBlock++] = block;
|
this.aMemBlocks[iBlock++] = block;
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ if (DEBUGGER) {
|
||||||
var Interrupts = require("./interrupts");
|
var Interrupts = require("./interrupts");
|
||||||
var Messages = require("./messages");
|
var Messages = require("./messages");
|
||||||
var Bus = require("./bus");
|
var Bus = require("./bus");
|
||||||
|
var Memory = require("./memory");
|
||||||
var Keyboard = require("./keyboard");
|
var Keyboard = require("./keyboard");
|
||||||
var State = require("./state");
|
var State = require("./state");
|
||||||
var CPU = require("./cpu");
|
var CPU = require("./cpu");
|
||||||
|
|
@ -487,6 +488,7 @@ if (DEBUGGER) {
|
||||||
"tss": Messages.TSS,
|
"tss": Messages.TSS,
|
||||||
"int": Messages.INT,
|
"int": Messages.INT,
|
||||||
"fault": Messages.FAULT,
|
"fault": Messages.FAULT,
|
||||||
|
"bus": Messages.BUS,
|
||||||
"mem": Messages.MEM,
|
"mem": Messages.MEM,
|
||||||
"port": Messages.PORT,
|
"port": Messages.PORT,
|
||||||
"dma": Messages.DMA,
|
"dma": Messages.DMA,
|
||||||
|
|
@ -560,11 +562,12 @@ if (DEBUGGER) {
|
||||||
* On the 80286, it introduced a new (and growing) series of two-byte opcodes
|
* On the 80286, it introduced a new (and growing) series of two-byte opcodes
|
||||||
*
|
*
|
||||||
* Based on the active CPU model, we make every effort to execute and disassemble this (and every other)
|
* Based on the active CPU model, we make every effort to execute and disassemble this (and every other)
|
||||||
* opcode appropriately, by setting the opcode's entry in aaOpDescs accordingly. 0x0F defaults to the 8086
|
* opcode appropriately, by setting the opcode's entry in aaOpDescs accordingly. 0x0F in aaOpDescs points
|
||||||
* entry: aOpDescPopCS.
|
* to the 8086 table: aOpDescPopCS.
|
||||||
*
|
*
|
||||||
* Note that we do NOT modify aaOpDescs directly; this.aaOpDescs is a reference to it if the processor
|
* Note that we must NOT modify aaOpDescs directly. this.aaOpDescs will point to Debugger.aaOpDescs
|
||||||
* is an 8086, otherwise we make a copy of the array and THEN modify it.
|
* if the processor is an 8086, because that's the processor that the hard-coded contents of the table
|
||||||
|
* represent; for all other processors, this.aaOpDescs will contain a copy of the table that we can modify.
|
||||||
*/
|
*/
|
||||||
Debugger.aOpDescPopCS = [Debugger.INS.POP, Debugger.TYPE_CS | Debugger.TYPE_OUT];
|
Debugger.aOpDescPopCS = [Debugger.INS.POP, Debugger.TYPE_CS | Debugger.TYPE_OUT];
|
||||||
Debugger.aOpDescUndefined = [Debugger.INS.NONE, Debugger.TYPE_NONE];
|
Debugger.aOpDescUndefined = [Debugger.INS.NONE, Debugger.TYPE_NONE];
|
||||||
|
|
@ -575,13 +578,13 @@ if (DEBUGGER) {
|
||||||
* the corresponding opcode. The sub-elements are as follows:
|
* the corresponding opcode. The sub-elements are as follows:
|
||||||
*
|
*
|
||||||
* [0]: {number} of the opcode name (see INS.*)
|
* [0]: {number} of the opcode name (see INS.*)
|
||||||
* [1]: {number} containing the destination operand descriptor bit(s)
|
* [1]: {number} containing the destination operand descriptor bit(s), if any
|
||||||
* [2]: {number} containing the source operand descriptor bit(s)
|
* [2]: {number} containing the source operand descriptor bit(s), if any
|
||||||
* [3]: {number} containing optional third operand descriptor bit(s)
|
* [3]: {number} containing the occasional third operand descriptor bit(s), if any
|
||||||
*
|
*
|
||||||
* These sub-elements are all optional. If [0] is not present, the opcode is undefined; if [1] is not
|
* These sub-elements are all optional. If [0] is not present, the opcode is undefined; if [1] is not
|
||||||
* present (or contains zero), the opcode has no (or only implied) operands; and if [2] is not present,
|
* present (or contains zero), the opcode has no (or only implied) operands; if [2] is not present, the
|
||||||
* the opcode has only a single operand.
|
* opcode has only a single operand. And so on.
|
||||||
*/
|
*/
|
||||||
Debugger.aaOpDescs = [
|
Debugger.aaOpDescs = [
|
||||||
/* 0x00 */ [Debugger.INS.ADD, Debugger.TYPE_MODRM | Debugger.TYPE_BYTE | Debugger.TYPE_BOTH, Debugger.TYPE_REG | Debugger.TYPE_BYTE | Debugger.TYPE_IN],
|
/* 0x00 */ [Debugger.INS.ADD, Debugger.TYPE_MODRM | Debugger.TYPE_BYTE | Debugger.TYPE_BOTH, Debugger.TYPE_REG | Debugger.TYPE_BYTE | Debugger.TYPE_IN],
|
||||||
|
|
@ -1216,6 +1219,7 @@ if (DEBUGGER) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.messageDump(Messages.BUS, function onDumpBus(s) { dbg.dumpBus(s); });
|
||||||
this.messageDump(Messages.DESC, function onDumpDesc(s) { dbg.dumpDesc(s); });
|
this.messageDump(Messages.DESC, function onDumpDesc(s) { dbg.dumpDesc(s); });
|
||||||
this.messageDump(Messages.TSS, function onDumpTSS(s) { dbg.dumpTSS(s); });
|
this.messageDump(Messages.TSS, function onDumpTSS(s) { dbg.dumpTSS(s); });
|
||||||
this.messageDump(Messages.DOS, function onDumpDOS(s) { dbg.dumpDOS(s); });
|
this.messageDump(Messages.DOS, function onDumpDOS(s) { dbg.dumpDOS(s); });
|
||||||
|
|
@ -1464,6 +1468,25 @@ if (DEBUGGER) {
|
||||||
"TASK_LDT": 0x2a
|
"TASK_LDT": 0x2a
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* dumpBus(s)
|
||||||
|
*
|
||||||
|
* This dumps Bus allocations.
|
||||||
|
*
|
||||||
|
* @this {Debugger}
|
||||||
|
* @param {string} [s]
|
||||||
|
*/
|
||||||
|
Debugger.prototype.dumpBus = function(s)
|
||||||
|
{
|
||||||
|
this.println("id physaddr blkaddr used size type");
|
||||||
|
this.println("-------- --------- -------- ------ ------ ----");
|
||||||
|
for (var i = 0; i < this.bus.aMemBlocks.length; i++) {
|
||||||
|
var block = this.bus.aMemBlocks[i];
|
||||||
|
if (block.type === Memory.TYPE.NONE) continue;
|
||||||
|
this.println(str.toHex(block.id) + " %" + str.toHex(i << this.bus.blockShift) + ": " + str.toHex(block.addr) + " " + str.toHexWord(block.used) + " " + str.toHexWord(block.size) + " " + Memory.TYPE.NAMES[block.type]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dumpDesc(s)
|
* dumpDesc(s)
|
||||||
*
|
*
|
||||||
|
|
@ -2703,21 +2726,6 @@ if (DEBUGGER) {
|
||||||
Debugger.prototype.addBreakpoint = function(aBreak, aAddr, fTemp)
|
Debugger.prototype.addBreakpoint = function(aBreak, aAddr, fTemp)
|
||||||
{
|
{
|
||||||
if (!this.findBreakpoint(aBreak, aAddr)) {
|
if (!this.findBreakpoint(aBreak, aAddr)) {
|
||||||
/*
|
|
||||||
* We used to calculate the physical address of the breakpoint address now, at the
|
|
||||||
* time the breakpoint is added, and save it in aAddr[2], so that a breakpoint set in
|
|
||||||
* one mode (eg, in real-mode) would still work as intended if the mode changed later
|
|
||||||
* (eg, to protected-mode).
|
|
||||||
*
|
|
||||||
* However, that creates difficulties setting protected-mode breakpoints in segments
|
|
||||||
* that might not be defined yet, or that may move in physical memory; so we're not
|
|
||||||
* doing this anymore:
|
|
||||||
*
|
|
||||||
* aAddr[2] = this.getAddr(aAddr);
|
|
||||||
*
|
|
||||||
* The way to create a real-mode breakpoint that will break regardless of mode is to
|
|
||||||
* use the physical address of the real-mode memory location instead.
|
|
||||||
*/
|
|
||||||
aAddr[3] = fTemp;
|
aAddr[3] = fTemp;
|
||||||
aBreak.push(aAddr);
|
aBreak.push(aAddr);
|
||||||
if (aBreak != this.aBreakExec) {
|
if (aBreak != this.aBreakExec) {
|
||||||
|
|
@ -2884,7 +2892,28 @@ if (DEBUGGER) {
|
||||||
var fBreak = false;
|
var fBreak = false;
|
||||||
addr = this.mapBreakpoint(addr);
|
addr = this.mapBreakpoint(addr);
|
||||||
for (var i = 1; i < aBreak.length; i++) {
|
for (var i = 1; i < aBreak.length; i++) {
|
||||||
|
|
||||||
var aAddrBreak = aBreak[i];
|
var aAddrBreak = aBreak[i];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to zap the physical address field of the breakpoint address before
|
||||||
|
* calling getAddr(), to force it to recalculate the physical address every time,
|
||||||
|
* unless this is a breakpoint on a physical address (as indicated by a -1 offset).
|
||||||
|
*/
|
||||||
|
if (aAddrBreak[0] != -1) aAddrBreak[2] = null;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We used to calculate the physical address of the breakpoint at the time the
|
||||||
|
* breakpoint was added, so that a breakpoint set in one mode (eg, in real-mode)
|
||||||
|
* would still work as intended if the mode changed later (eg, to protected-mode).
|
||||||
|
*
|
||||||
|
* However, that created difficulties setting protected-mode breakpoints in segments
|
||||||
|
* that might not be defined yet, or that could move in physical memory.
|
||||||
|
*
|
||||||
|
* If you want to create a real-mode breakpoint that will break regardless of mode,
|
||||||
|
* use the physical address of the real-mode memory location instead.
|
||||||
|
*/
|
||||||
|
|
||||||
if (addr == this.mapBreakpoint(this.getAddr(aAddrBreak))) {
|
if (addr == this.mapBreakpoint(this.getAddr(aAddrBreak))) {
|
||||||
if (aAddrBreak[3]) {
|
if (aAddrBreak[3]) {
|
||||||
this.findBreakpoint(aBreak, aAddrBreak, true);
|
this.findBreakpoint(aBreak, aAddrBreak, true);
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,7 @@ var littleEndian = (TYPEDARRAYS? (function() {
|
||||||
function Memory(addr, used, size, type, controller)
|
function Memory(addr, used, size, type, controller)
|
||||||
{
|
{
|
||||||
var i;
|
var i;
|
||||||
|
this.id = (Memory.idBlock += 2);
|
||||||
this.adw = null;
|
this.adw = null;
|
||||||
this.offset = 0;
|
this.offset = 0;
|
||||||
this.addr = addr;
|
this.addr = addr;
|
||||||
|
|
@ -223,6 +224,11 @@ Memory.TYPE = {
|
||||||
COLORS: ["black", "blue", "green", "cyan"]
|
COLORS: ["black", "blue", "green", "cyan"]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Last used block ID
|
||||||
|
*/
|
||||||
|
Memory.idBlock = 0;
|
||||||
|
|
||||||
Memory.prototype = {
|
Memory.prototype = {
|
||||||
constructor: Memory,
|
constructor: Memory,
|
||||||
parent: null,
|
parent: null,
|
||||||
|
|
@ -237,6 +243,12 @@ Memory.prototype = {
|
||||||
* @param {number} [type]
|
* @param {number} [type]
|
||||||
*/
|
*/
|
||||||
clone: function(mem, type) {
|
clone: function(mem, type) {
|
||||||
|
/*
|
||||||
|
* Original memory block IDs are even; cloned memory block IDs are odd;
|
||||||
|
* the original ID of the current block is lost, but that's OK, since it was
|
||||||
|
* presumably produced merely to become a clone.
|
||||||
|
*/
|
||||||
|
this.id = mem.id | 0x1;
|
||||||
this.size = mem.size;
|
this.size = mem.size;
|
||||||
if (type) {
|
if (type) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
|
|
||||||
|
|
@ -55,31 +55,32 @@ var Messages = {
|
||||||
TSS: 0x00000008,
|
TSS: 0x00000008,
|
||||||
INT: 0x00000010,
|
INT: 0x00000010,
|
||||||
FAULT: 0x00000020,
|
FAULT: 0x00000020,
|
||||||
MEM: 0x00000040,
|
BUS: 0x00000040,
|
||||||
PORT: 0x00000080,
|
MEM: 0x00000080,
|
||||||
DMA: 0x00000100,
|
PORT: 0x00000100,
|
||||||
PIC: 0x00000200,
|
DMA: 0x00000200,
|
||||||
TIMER: 0x00000400,
|
PIC: 0x00000400,
|
||||||
CMOS: 0x00000800,
|
TIMER: 0x00000800,
|
||||||
RTC: 0x00001000,
|
CMOS: 0x00001000,
|
||||||
C8042: 0x00002000,
|
RTC: 0x00002000,
|
||||||
CHIPSET: 0x00004000,
|
C8042: 0x00004000,
|
||||||
KEYBOARD: 0x00008000,
|
CHIPSET: 0x00008000,
|
||||||
KEYS: 0x00010000,
|
KEYBOARD: 0x00010000,
|
||||||
VIDEO: 0x00020000,
|
KEYS: 0x00020000,
|
||||||
FDC: 0x00040000,
|
VIDEO: 0x00040000,
|
||||||
HDC: 0x00080000,
|
FDC: 0x00080000,
|
||||||
DISK: 0x00100000,
|
HDC: 0x00100000,
|
||||||
SERIAL: 0x00200000,
|
DISK: 0x00200000,
|
||||||
SPEAKER: 0x00400000,
|
SERIAL: 0x00400000,
|
||||||
STATE: 0x00800000,
|
SPEAKER: 0x00800000,
|
||||||
MOUSE: 0x01000000,
|
STATE: 0x01000000,
|
||||||
COMPUTER: 0x02000000,
|
MOUSE: 0x02000000,
|
||||||
DOS: 0x04000000,
|
COMPUTER: 0x04000000,
|
||||||
DATA: 0x08000000,
|
DOS: 0x08000000,
|
||||||
LOG: 0x10000000,
|
DATA: 0x10000000,
|
||||||
WARN: 0x20000000,
|
LOG: 0x20000000,
|
||||||
HALT: 0x40000000
|
WARN: 0x40000000,
|
||||||
|
HALT: 0x80000000|0
|
||||||
};
|
};
|
||||||
|
|
||||||
if (typeof module !== 'undefined') module.exports = Messages;
|
if (typeof module !== 'undefined') module.exports = Messages;
|
||||||
|
|
|
||||||
|
|
@ -330,7 +330,7 @@ CompaqController.writeByte = function writeCompaqControllerByte(off, b)
|
||||||
{
|
{
|
||||||
var aBlocks;
|
var aBlocks;
|
||||||
var controller = this.controller;
|
var controller = this.controller;
|
||||||
var bus = controller.bus;
|
var bus = controller.ram.bus;
|
||||||
if (b != controller.bMappings) {
|
if (b != controller.bMappings) {
|
||||||
if (!(b & CompaqController.MAPPINGS.UNMAPPED)) {
|
if (!(b & CompaqController.MAPPINGS.UNMAPPED)) {
|
||||||
if (!controller.aBlocksDst) {
|
if (!controller.aBlocksDst) {
|
||||||
|
|
|
||||||
|
|
@ -2025,8 +2025,6 @@ X86CPU.prototype.getPF = function()
|
||||||
/**
|
/**
|
||||||
* getAF()
|
* getAF()
|
||||||
*
|
*
|
||||||
* Notes regarding auxiliary carry following an I386 addition:
|
|
||||||
*
|
|
||||||
* To determine if there's been a carry out of the low 4 bits of an arithmetic operation,
|
* To determine if there's been a carry out of the low 4 bits of an arithmetic operation,
|
||||||
* we look at all the possible inputs for bit 4, and calculate AF = PS^(D^S):
|
* we look at all the possible inputs for bit 4, and calculate AF = PS^(D^S):
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1130,9 +1130,9 @@ X86.fnLFS = function LFS(dst, src)
|
||||||
*
|
*
|
||||||
* op=0x0F,0x01,reg=0x2 (GRP7:LGDT)
|
* op=0x0F,0x01,reg=0x2 (GRP7:LGDT)
|
||||||
*
|
*
|
||||||
* The 80286 LGDT instruction expects a 40-bit operand: a 16-bit limit, followed by a 24-bit address;
|
* The 80286 LGDT instruction expects a 40-bit operand: a 16-bit limit, followed by a 24-bit address
|
||||||
* the ModRM decoder has already supplied the first word of the operand (in dst), which corresponds to the
|
* (or a 32-bit address in 32-bit mode); the ModRM decoder has already supplied the first word of the
|
||||||
* limit, so we must fetch the remaining 24 bits ourselves.
|
* operand (in dst), which corresponds to the limit, so we must fetch the remaining bits ourselves.
|
||||||
*
|
*
|
||||||
* @this {X86CPU}
|
* @this {X86CPU}
|
||||||
* @param {number} dst
|
* @param {number} dst
|
||||||
|
|
@ -1144,7 +1144,11 @@ X86.fnLGDT = function LGDT(dst, src)
|
||||||
if (this.regEA === X86.ADDR_INVALID) {
|
if (this.regEA === X86.ADDR_INVALID) {
|
||||||
X86.opInvalid.call(this);
|
X86.opInvalid.call(this);
|
||||||
} else {
|
} else {
|
||||||
this.addrGDT = this.getShort(this.regEA + 2) | (this.getByte(this.regEA + 4) << 16);
|
/*
|
||||||
|
* It shouldn't hurt to always fetch 32 bits of physical memory, which we'll then
|
||||||
|
* mask with either a 24-bit or a 32-bit mask.
|
||||||
|
*/
|
||||||
|
this.addrGDT = this.getLong(this.regEA + 2) & (this.dataMask | (this.dataMask << 8));
|
||||||
this.addrGDTLimit = this.addrGDT + dst;
|
this.addrGDTLimit = this.addrGDT + dst;
|
||||||
this.opFlags |= X86.OPFLAG.NOWRITE;
|
this.opFlags |= X86.OPFLAG.NOWRITE;
|
||||||
this.nStepCycles -= 11;
|
this.nStepCycles -= 11;
|
||||||
|
|
@ -1176,9 +1180,9 @@ X86.fnLGS = function LGS(dst, src)
|
||||||
*
|
*
|
||||||
* op=0x0F,0x01,reg=0x3 (GRP7:LIDT)
|
* op=0x0F,0x01,reg=0x3 (GRP7:LIDT)
|
||||||
*
|
*
|
||||||
* The 80286 LIDT instruction expects a 40-bit operand: a 16-bit limit, followed by a 24-bit address;
|
* The 80286 LIDT instruction expects a 40-bit operand: a 16-bit limit, followed by a 24-bit address
|
||||||
* the ModRM decoder has already supplied the first word of the operand (in dst), which corresponds to the
|
* (or a 32-bit address in 32-bit mode); the ModRM decoder has already supplied the first word of the
|
||||||
* limit, so we must fetch the remaining 24 bits ourselves.
|
* operand (in dst), which corresponds to the limit, so we must fetch the remaining bits ourselves.
|
||||||
*
|
*
|
||||||
* @this {X86CPU}
|
* @this {X86CPU}
|
||||||
* @param {number} dst
|
* @param {number} dst
|
||||||
|
|
@ -1190,7 +1194,11 @@ X86.fnLIDT = function LIDT(dst, src)
|
||||||
if (this.regEA === X86.ADDR_INVALID) {
|
if (this.regEA === X86.ADDR_INVALID) {
|
||||||
X86.opInvalid.call(this);
|
X86.opInvalid.call(this);
|
||||||
} else {
|
} else {
|
||||||
this.addrIDT = this.getShort(this.regEA + 2) | (this.getByte(this.regEA + 4) << 16);
|
/*
|
||||||
|
* It shouldn't hurt to always fetch 32 bits of physical memory, which we'll then
|
||||||
|
* mask with either a 24-bit or a 32-bit mask.
|
||||||
|
*/
|
||||||
|
this.addrIDT = this.getLong(this.regEA + 2) & (this.dataMask | (this.dataMask << 8));
|
||||||
this.addrIDTLimit = this.addrIDT + dst;
|
this.addrIDTLimit = this.addrIDT + dst;
|
||||||
this.opFlags |= X86.OPFLAG.NOWRITE;
|
this.opFlags |= X86.OPFLAG.NOWRITE;
|
||||||
this.nStepCycles -= 12;
|
this.nStepCycles -= 12;
|
||||||
|
|
@ -2182,7 +2190,6 @@ X86.fnSGDT = function SGDT(dst, src)
|
||||||
* calls us does that automatically with the value we return (dst).
|
* calls us does that automatically with the value we return (dst).
|
||||||
*/
|
*/
|
||||||
dst = this.addrGDTLimit - this.addrGDT;
|
dst = this.addrGDTLimit - this.addrGDT;
|
||||||
this.setShort(this.regEA + 2, this.addrGDT);
|
|
||||||
/*
|
/*
|
||||||
* We previously left the 6th byte of the target operand "undefined". But it turns out we have to set
|
* We previously left the 6th byte of the target operand "undefined". But it turns out we have to set
|
||||||
* it to *something*, because there's processor detection in PC-DOS 7.0 (at least in the SETUP portion)
|
* it to *something*, because there's processor detection in PC-DOS 7.0 (at least in the SETUP portion)
|
||||||
|
|
@ -2211,12 +2218,10 @@ X86.fnSGDT = function SGDT(dst, src)
|
||||||
* 145E:4BC2 9D POPF
|
* 145E:4BC2 9D POPF
|
||||||
* 145E:4BC3 CB RETF
|
* 145E:4BC3 CB RETF
|
||||||
*
|
*
|
||||||
* This code is expecting SGDT on an 80286 to set the 6th "undefined" byte to 0xFF. So we use setShort()
|
* This code is expecting SGDT on an 80286 to set the 6th "undefined" byte to 0xFF.
|
||||||
* instead of setByte() and force the upper byte to 0xFF.
|
|
||||||
*
|
|
||||||
* TODO: Remove the 0xFF00 below on post-80286 processors; also, determine whether this behavior is unique to real-mode.
|
|
||||||
*/
|
*/
|
||||||
this.setShort(this.regEA + 4, 0xFF00 | (this.addrGDT >> 16));
|
var addr = this.addrGDT | (this.model == X86.MODEL_80286? 0xff000000 : 0);
|
||||||
|
this.setLong(this.regEA + 2, addr);
|
||||||
this.nStepCycles -= 11;
|
this.nStepCycles -= 11;
|
||||||
}
|
}
|
||||||
return dst;
|
return dst;
|
||||||
|
|
@ -2522,14 +2527,12 @@ X86.fnSIDT = function SIDT(dst, src)
|
||||||
* us does that automatically with the value we return (dst).
|
* us does that automatically with the value we return (dst).
|
||||||
*/
|
*/
|
||||||
dst = this.addrIDTLimit - this.addrIDT;
|
dst = this.addrIDTLimit - this.addrIDT;
|
||||||
this.setShort(this.regEA + 2, this.addrIDT);
|
|
||||||
/*
|
/*
|
||||||
* As with SGDT, the 6th byte is technically "undefined" on an 80286, but we now set it to 0xFF, for the
|
* As with SGDT, the 6th byte is technically "undefined" on an 80286, but we now set it to 0xFF, for the
|
||||||
* same reasons discussed in SGDT (above).
|
* same reasons discussed in SGDT (above).
|
||||||
*
|
|
||||||
* TODO: Remove the 0xFF00 below on post-80286 processors; also, determine whether this behavior is unique to real-mode.
|
|
||||||
*/
|
*/
|
||||||
this.setShort(this.regEA + 4, 0xFF00 | (this.addrIDT >> 16));
|
var addr = this.addrIDT | (this.model == X86.MODEL_80286? 0xff000000 : 0);
|
||||||
|
this.setLong(this.regEA + 2, addr);
|
||||||
this.nStepCycles -= 12;
|
this.nStepCycles -= 12;
|
||||||
}
|
}
|
||||||
return dst;
|
return dst;
|
||||||
|
|
|
||||||
|
|
@ -2079,9 +2079,22 @@ X86.opMOVwsr = function MOVwsr()
|
||||||
case 0x3:
|
case 0x3:
|
||||||
this.regMD16 = this.segDS.sel;
|
this.regMD16 = this.segDS.sel;
|
||||||
break;
|
break;
|
||||||
|
case 0x4:
|
||||||
|
if (I386 && this.model >= X86.MODEL_80386) {
|
||||||
|
this.regMD16 = this.segFS.sel;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
X86.opInvalid.call(this);
|
||||||
|
break;
|
||||||
|
case 0x5:
|
||||||
|
if (I386 && this.model >= X86.MODEL_80386) {
|
||||||
|
this.regMD16 = this.segGS.sel;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* falls through */
|
||||||
default:
|
default:
|
||||||
X86.opUndefined.call(this);
|
X86.opInvalid.call(this);
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Like other MOV operations, the destination does not need to be read, just written.
|
* Like other MOV operations, the destination does not need to be read, just written.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue