diff --git a/docs/pcjs/demos/components.xsl b/docs/pcjs/demos/components.xsl index bd142a09c..36234ab1d 100644 --- a/docs/pcjs/demos/components.xsl +++ b/docs/pcjs/demos/components.xsl @@ -972,7 +972,7 @@ - + 20 @@ -994,7 +994,7 @@ computer - ,buswidth:,resume:,state:'' + ,busWidth:,resume:,state:'' diff --git a/modules/pcjs/lib/debugger.js b/modules/pcjs/lib/debugger.js index ea6ddf420..7f46fe07a 100644 --- a/modules/pcjs/lib/debugger.js +++ b/modules/pcjs/lib/debugger.js @@ -3134,33 +3134,34 @@ if (DEBUGGER) { var sOperand = " "; var typeSize = type & Debugger.TYPE_SIZE; switch (typeSize) { - case Debugger.TYPE_BYTE: - /* - * There's the occasional immediate byte we don't need to display (eg, the 0x0A - * following an AAM or AAD instruction), so we suppress the byte if it lacks a TYPE_IN - * or TYPE_OUT designation (and TYPE_BOTH, as the name implies, includes both). - */ - if (type & Debugger.TYPE_BOTH) { - sOperand = str.toHex(this.getByte(aAddr, 1), 2); - } + case Debugger.TYPE_BYTE: + /* + * There's the occasional immediate byte we don't need to display (eg, the 0x0A + * following an AAM or AAD instruction), so we suppress the byte if it lacks a TYPE_IN + * or TYPE_OUT designation (and TYPE_BOTH, as the name implies, includes both). + */ + if (type & Debugger.TYPE_BOTH) { + sOperand = str.toHex(this.getByte(aAddr, 1), 2); + } + break; + case Debugger.TYPE_SBYTE: + sOperand = str.toHex((this.getByte(aAddr, 1) << 24) >> 24, 4); + break; + case Debugger.TYPE_WORDV: + if (aAddr[4]) { + sOperand = str.toHex(this.getLong(aAddr, 4)); break; - case Debugger.TYPE_SBYTE: - sOperand = str.toHex((this.getByte(aAddr, 1) << 24) >> 24, 4); - break; - case Debugger.TYPE_WORDV: - if (aAddr[4]) { - sOperand = str.toHex(this.getLong(aAddr, 4)); - break; - } - /* falls through */ - case Debugger.TYPE_WORD: - sOperand = str.toHex(this.getShort(aAddr, 2), 4); - break; - case Debugger.TYPE_FARP: - sOperand = this.hexAddr(this.newAddr(this.getWord(aAddr, 2), this.getShort(aAddr, 2), null, aAddr[4], aAddr[5])); - break; - default: - sOperand = "imm(" + str.toHexWord(type) + ")"; + } + /* falls through */ + case Debugger.TYPE_WORD: + sOperand = str.toHex(this.getShort(aAddr, 2), 4); + break; + case Debugger.TYPE_FARP: + sOperand = this.hexAddr(this.newAddr(this.getWord(aAddr, 2), this.getShort(aAddr, 2), null, aAddr[4], aAddr[5])); + break; + default: + sOperand = "imm(" + str.toHexWord(type) + ")"; + break; } return sOperand; }; @@ -3345,36 +3346,36 @@ if (DEBUGGER) { { var b; switch (sFlag) { - case "V": - b = this.cpu.getOF(); - break; - case "D": - b = this.cpu.getDF(); - break; - case "I": - b = this.cpu.getIF(); - break; - case "T": - b = this.cpu.getTF(); - break; - case "S": - b = this.cpu.getSF(); - break; - case "Z": - b = this.cpu.getZF(); - break; - case "A": - b = this.cpu.getAF(); - break; - case "P": - b = this.cpu.getPF(); - break; - case "C": - b = this.cpu.getCF(); - break; - default: - b = 0; - break; + case "V": + b = this.cpu.getOF(); + break; + case "D": + b = this.cpu.getDF(); + break; + case "I": + b = this.cpu.getIF(); + break; + case "T": + b = this.cpu.getTF(); + break; + case "S": + b = this.cpu.getSF(); + break; + case "Z": + b = this.cpu.getZF(); + break; + case "A": + b = this.cpu.getAF(); + break; + case "P": + b = this.cpu.getPF(); + break; + case "C": + b = this.cpu.getCF(); + break; + default: + b = 0; + break; } return sFlag + (b? '1' : '0') + ' '; }; diff --git a/modules/pcjs/lib/x86cpu.js b/modules/pcjs/lib/x86cpu.js index 8a7d737dd..f6b227c2f 100644 --- a/modules/pcjs/lib/x86cpu.js +++ b/modules/pcjs/lib/x86cpu.js @@ -1592,6 +1592,7 @@ X86CPU.prototype.setProtMode = function(fProt) if (I386 && this.model >= X86.MODEL_80386) { this.segFS.updateMode(fProt); this.segGS.updateMode(fProt); + this.resetSizes(); } }; diff --git a/modules/pcjs/lib/x86seg.js b/modules/pcjs/lib/x86seg.js index bb80f8c7f..52e771e9d 100644 --- a/modules/pcjs/lib/x86seg.js +++ b/modules/pcjs/lib/x86seg.js @@ -925,7 +925,18 @@ X86Seg.prototype.updateMode = function(fProt) this.loadIDT = this.loadIDTReal; this.checkRead = this.checkReadReal; this.checkWrite = this.checkWriteReal; - this.limit = 0xffff; + /* + * Like the base, we don't want to mess with the limit, so that features like "Unreal" mode + * (or "Big Real" mode as it's called in the HIMEM source code) will work, at least until the + * next explicit segment load. + * + * See http://www.os2museum.com/wp/himem-sys-unreal-mode-and-loadall/ for more details. + * + * this.limit = 0xffff; + * + * TODO: The checkReadReal() and checkWriteReal() functions need to generate GP faults for offsets + * beyond the current real-mode limit. + */ this.acc = this.ext = 0; this.cpl = this.dpl = 0; this.addrDesc = X86.ADDR_INVALID; diff --git a/tests/pc/80386/tests.nasm b/tests/pc/80386/tests.nasm index 4b39c08ac..92736a376 100644 --- a/tests/pc/80386/tests.nasm +++ b/tests/pc/80386/tests.nasm @@ -21,6 +21,7 @@ ACC_TYPE_WRITABLE equ 0x0200 ACC_TYPE_CODE_READABLE equ (0x1a00 | ACC_PRESENT) ACC_TYPE_DATA_WRITABLE equ (0x1200 | ACC_PRESENT) +EXT_NONE equ 0x0000 EXT_BIG equ 0x0040 ; @@ -33,7 +34,7 @@ EXT_BIG equ 0x0040 ; 0x0d08-0x0d0f GDTR ; 0x0d10-0x0fff reserved ; -; And in the second page (0x1000-0x1fff), let's build a page directory, followed by a single page table that +; And in the second page (0x1000-0x1fff), we build a page directory, followed by a single page table that ; will allow us to map up to 4Mb (although we'll only create entries for the first 1Mb). ; RAM_GDT equ 0x0c00 @@ -50,8 +51,12 @@ CR0_MSW_PE equ 0x0001 ; set initializes a register to the specified value (eg, "set eax,0") ; %macro set 2 - %if %2 = 0 - sub %1,%1 + %ifnum %2 + %if %2 = 0 + xor %1,%1 + %else + mov %1,%2 + %endif %else mov %1,%2 %endif @@ -60,7 +65,7 @@ CR0_MSW_PE equ 0x0001 ; ; defDesc defines a descriptor, given a base (%1), limit (%2), type (%3), dpl (%4), and ext (%5) ; -%macro defDesc 1-4 0,0,0,0 +%macro defDesc 1-5 0,0,0,0,0 dw (%2 & 0x0000ffff) dw (%1 & 0x0000ffff) dw ((%1 & 0x00ff0000) >> 16) | %3 | (%4 << 13) @@ -68,15 +73,16 @@ CR0_MSW_PE equ 0x0001 %endmacro ; -; setDesc creates a descriptor, given a base (%1), limit (%2), type (%3), dpl (%4), and ext (%5) +; setDesc creates a descriptor, given a base (%1), limit (%2), type (%3), ext (%4), and selector (%5) ; %assign selDesc 0 -%macro setDesc 1-4 0,0,0,none +%macro setDesc 1-5 0,0,0,0,none set ebx,%1 set ecx,%2 - set edx,%3 + set dx,%3 + set ax,%4 call storeDesc - %assign %4 selDesc + %assign %5 selDesc %assign selDesc selDesc+8 %endmacro @@ -99,11 +105,13 @@ start: cli ; disable all interrupts cmp eax,ebx je near initRAM ; apparently we have to tell NASM "near" because this is a forward reference times 32768 nop ; lots of NOPs to force a 16-bit conditional jump + ; -; storeDesc(EBX=base, ECX=limit, EDX=type, EDI=target) +; storeDesc(EBX=base, ECX=limit, DX=type, AX=ext, DI=address of descriptor) ; storeDesc: cld + push ax mov ax,cx stosw ; store the low 16 bits of limit from ECX mov ax,bx @@ -112,13 +120,17 @@ storeDesc: shr ebx,16 mov al,bl stosw + pop ax shr ecx,16 - mov al,cl - and al,0xf + and cl,0xf + or al,cl mov ah,bh stosw ret +; +; The following ROM-based data structures are obsolete, because we build these data structures in RAM now. +; addrGDT:dw romGDTEnd - romGDT - 1 ; 16-bit limit of romGDT dw romGDT, 0xffff ; 32-bit base address of romGDT (works as long as we're aliased at 0xffff0000) @@ -126,13 +138,18 @@ romGDT: defDesc 0 ; the first descriptor in any descriptor table is always a d defDesc 0x000f0000,0x0000ffff,ACC_TYPE_CODE_READABLE defDesc 0x00000000,0x000fffff,ACC_TYPE_DATA_WRITABLE romGDTEnd: +; +; End of ROM-based data structures +; initRAM: set edi,RAM_GDT mov [RAM_GDTR+2],edi - setDesc 0,0,0,NULL - setDesc 0x000f0000,0x0000ffff,ACC_TYPE_CODE_READABLE,CSEG_PROT - setDesc 0x00000000,0x000fffff,ACC_TYPE_DATA_WRITABLE,DSEG_PROT + setDesc 0,0,0,0,NULL + mov eax,cs + shl eax,4 + setDesc eax,0x0000ffff,ACC_TYPE_CODE_READABLE,EXT_BIG,CSEG_PROT + setDesc 0x0,0x000fffff,ACC_TYPE_DATA_WRITABLE,EXT_BIG,DSEG_PROT sub edi,RAM_GDT dec edi mov [RAM_GDTR],di @@ -141,20 +158,25 @@ goProt: o32 lgdt [RAM_GDTR] mov eax,cr0 or eax,CR0_MSW_PE mov cr0,eax - jmp dword CSEG_PROT:inProt - -inProt: mov ax,DSEG_PROT + jmp CSEG_PROT:inProt +inProt: + bits 32 + mov ax,DSEG_PROT mov ds,ax + mov es,ax + mov ss,ax + ; -; Do some protected-mode tests... +; Do some protected-mode tests now... ; goReal: mov eax,cr0 and eax,~CR0_MSW_PE mov cr0,eax - jmp dword CSEG_REAL:inReal - -inReal: or eax,1 + bits 16 + jmp CSEG_REAL:inReal +inReal: + or ax,1 jnz start ; apparently we do NOT have to say "near" here since this is a backward reference ; @@ -163,7 +185,6 @@ inReal: or eax,1 ; times 0xfff0-0x100-($-$$) nop - bits 16 jmp CSEG_REAL:start db 0x20