Cleaned up management of unused PSW bits

This commit is contained in:
Jeff Parsons 2016-12-04 16:23:37 -08:00 • committed by Jeff Parsons
commit 1e1db7b78e
24 changed files with 574 additions and 530 deletions

14
blog/README.md Normal file
View file

@ -0,0 +1,14 @@
---
layout: blog
title: Blog
menu_title: Blog
menu_order: 1
permalink: /blog/
---
Keep tabs on the [PCjs Project](https://github.com/jeffpar/pcjs) on GitHub:
[Releases](https://github.com/jeffpar/pcjs/releases), [Issues](https://github.com/jeffpar/pcjs/issues),
and [Commits](https://github.com/jeffpar/pcjs/commits/master).
For random musings about PCjs, web technologies, old hardware and software, and more, read on.

BIN
blog/images/avd-tablet.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

BIN
blog/images/googlewhack.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 316 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 518 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 KiB

View file

@ -1736,7 +1736,7 @@ PDP11.opSPL = function(opCode)
return;
}
if (!(this.regPSW & PDP11.PSW.CMODE)) {
this.regPSW = (this.regPSW & ~(PDP11.PSW.UNUSED | PDP11.PSW.PRI)) | ((opCode & 0x7) << PDP11.PSW.SHIFT.PRI);
this.regPSW = (this.regPSW & ~PDP11.PSW.PRI) | ((opCode & 0x7) << PDP11.PSW.SHIFT.PRI);
this.opFlags |= PDP11.OPFLAG.IRQ_DELAY;
this.opFlags &= ~PDP11.OPFLAG.IRQ;
}

View file

@ -134,14 +134,18 @@ CPUStatePDP11.prototype.initProcessor = function()
this.offRegSrc = 0;
this.maskRegSrcByte = 0xff;
if (this.model == PDP11.MODEL_1120) {
if (this.model <= PDP11.MODEL_1120) {
this.decode = PDP11.op1120.bind(this);
this.checkStackLimit = this.checkStackLimit1120;
this.offRegSrc = 8;
this.maskRegSrcByte = -1;
this.pswUsed = ~(PDP11.PSW.UNUSED | PDP11.PSW.REGSET | PDP11.PSW.PMODE | PDP11.PSW.CMODE) & 0xffff;
this.pswRegSet = 0;
} else {
this.decode = PDP11.op1145.bind(this);
this.checkStackLimit = this.checkStackLimit1145;
this.pswUsed = ~(PDP11.PSW.UNUSED | (this.model < PDP11.MODEL_1145? PDP11.PSW.REGSET : 0)) & 0xffff;
this.pswRegSet = (this.model >= PDP11.MODEL_1145? PDP11.PSW.REGSET : 0);
}
this.initRegs();
@ -728,16 +732,15 @@ CPUStatePDP11.prototype.setNF = function()
*/
CPUStatePDP11.prototype.getOpcode = function()
{
var pc = this.regsGen[PDP11.REG.PC];
this.opLast = pc;
var pc = this.opLast = this.regsGen[PDP11.REG.PC];
/*
* If PC is unaligned, a BUS trap will be generated, and because it will generate an
* exception, the next line (the equivalent of advancePC(2)) will not be executed, ensuring that
* original unaligned PC will be pushed onto the stack by trap().
*/
var op = this.readWord(pc);
var opCode = this.readWord(pc);
this.regsGen[PDP11.REG.PC] = (pc + 2) & 0xffff;
return op;
return opCode;
};
/**
@ -1137,11 +1140,12 @@ CPUStatePDP11.prototype.getPSW = function()
*/
CPUStatePDP11.prototype.setPSW = function(newPSW)
{
newPSW &= this.pswUsed;
this.flagN = newPSW << 12;
this.flagZ = (~newPSW) & 4;
this.flagV = newPSW << 14;
this.flagC = newPSW << 16;
if ((newPSW ^ this.regPSW) & PDP11.PSW.REGSET) {
if ((newPSW ^ this.regPSW) & this.pswRegSet) {
/*
* Swap register sets
*/
@ -1500,7 +1504,7 @@ CPUStatePDP11.prototype.trapReturn = function()
* safer, but if we're going to do pushes in trap(), then I see no reason to avoid doing pops in trapReturn().
*/
var addr = this.popWord();
var newPSW = this.popWord() & ~PDP11.PSW.UNUSED;
var newPSW = this.popWord();
if (this.regPSW & PDP11.PSW.CMODE) {
/*
* Keep SPL and allow lower only for modes and register set.
@ -2594,11 +2598,11 @@ CPUStatePDP11.prototype.branch = function(opCode, condition)
CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
{
/*
* The Debugger uses fComplete to determine if the instruction completed (true) or was interrupted
* The Debugger uses complete to determine if the instruction completed (true) or was interrupted
* by a breakpoint or some other exceptional condition (false). NOTE: this does NOT include JavaScript
* exceptions, which stepCPU() expects the caller to catch using its own exception handler.
*
* The CPU relies on the use of stopCPU() rather than fComplete, because the CPU never single-steps
* The CPU relies on the use of stopCPU() rather than complete, because the CPU never single-steps
* (ie, nMinCycles is always some large number), whereas the Debugger does. And conversely, when the
* Debugger is single-stepping (even when performing multiple single-steps), fRunning is never set,
* so stopCPU() would have no effect as far as the Debugger is concerned.
@ -2618,11 +2622,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
* if nDebugState is <= zero).
*/
var nDebugState = (!nMinCycles)? -1 : (this.flags.starting? 0 : 1);
/*
* We've moved beyond "starting" now and have officially "started".
*/
this.flags.starting = false;
this.flags.starting = false; // we've moved beyond "starting" and have officially "started" now
/*
* We move the minimum cycle count to nStepCycles (the number of cycles left to step), so that other
@ -2631,16 +2631,25 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
*/
this.nBurstCycles = this.nStepCycles = nMinCycles;
/*
* And finally, move the nDebugCheck state to an OPFLAG bit, so that the loop need check only one variable.
*/
this.opFlags = (this.opFlags & ~PDP11.OPFLAG.DEBUGGER) | (nDebugCheck? PDP11.OPFLAG.DEBUGGER : 0);
do {
if (DEBUGGER && nDebugCheck) {
if (this.opFlags) {
/*
* NOTE: We still check DEBUGGER to ensure that this code will be compiled out of existence in
* non-DEBUGGER builds.
*/
if (DEBUGGER && (this.opFlags & PDP11.OPFLAG.DEBUGGER)) {
if (this.dbg.checkInstruction(this.getPC(), nDebugState)) {
this.stopCPU();
break;
}
if (!++nDebugCheck) this.opFlags &= ~PDP11.OPFLAG.DEBUGGER;
if (!nDebugState) nDebugState++;
nDebugCheck++;
}
if (this.opFlags) {
/*
* If we're in the IRQ or WAIT state, check for any pending interrupts.
*
@ -2651,7 +2660,7 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
*/
if ((this.opFlags & (PDP11.OPFLAG.IRQ_MASK | PDP11.OPFLAG.WAIT)) /* && nDebugState >= 0 */) {
if (this.checkInterrupts()) {
if (DEBUGGER && nDebugCheck && this.dbg.checkInstruction(this.getPC(), nDebugState)) {
if ((this.opFlags & PDP11.OPFLAG.DEBUGGER) && this.dbg.checkInstruction(this.getPC(), nDebugState)) {
this.stopCPU();
break;
}
@ -2674,15 +2683,13 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
*/
if (this.opFlags & PDP11.OPFLAG.TRAP_MASK) {
if (this.checkTraps()) {
if (DEBUGGER && nDebugCheck && this.dbg.checkInstruction(this.getPC(), nDebugState)) {
if ((this.opFlags & PDP11.OPFLAG.DEBUGGER) && this.dbg.checkInstruction(this.getPC(), nDebugState)) {
this.stopCPU();
break;
}
if (nDebugState < 0) break;
}
}
} else {
this.assert(!this.irqNext && !this.regPIR);
}
/*
@ -2691,7 +2698,8 @@ CPUStatePDP11.prototype.stepCPU = function(nMinCycles)
*/
this.opFlags = (this.opFlags & PDP11.OPFLAG.PRESERVE) | (this.regPSW & PDP11.PSW.TF);
this.decode(this.getOpcode());
var opCode = this.getOpcode();
this.decode(opCode);
} while (this.nStepCycles > 0);

View file

@ -124,8 +124,20 @@ var PDP11 = {
/*
* CPU model numbers (supported)
*
* The 11/20 includes the 11/10, which is not identified separately because there was
* nothing functionally different about it.
*
* The 11/40 added the MODE bits to the PSW (but only KERNEL=00 and USER=11) and 18-bit
* addressing via an MMU; there was still only one register set.
*
* The 11/45 added REGSET bit to the PSW (along with the second register set), and added
* SUPERVISOR=01 to the set of modes.
*
* The 11/70 added 22-bit addressing and corresponding extensions to the MMU.
*/
MODEL_1120: 1120,
MODEL_1140: 1140,
MODEL_1145: 1145,
MODEL_1170: 1170,
@ -169,9 +181,13 @@ var PDP11 = {
PRI: 0x00E0, // bits 5-7 (000340) Priority
UNUSED: 0x0700, // bits 8-10 (003400) UNUSED
/*
* PSW bits above this point are unused on 11/20-class machines
* The REGSET bit (and the alternate register set stored in regsAlt) came into existence
* with the 11/45; (ie, they were not present on the 11/10, 11/20, or 11/40).
*/
REGSET: 0x0800, // bit 11 (004000) Register Set
/*
* The MODE bits came into existence with the 11/40 (eg, not present on the 11/10 or 11/20).
*/
PMODE: 0x3000, // bits 12-13 (030000) Prev Mode (see PDP11.MODE)
CMODE: 0xC000, // bits 14-15 (140000) Curr Mode (see PDP11.MODE)
SHIFT: {
@ -266,6 +282,7 @@ var PDP11 = {
IRQ_DELAY: 0x0001, // incremented until it becomes IRQ (set by SPL and traps)
IRQ: 0x0002, // time to call checkInterrupts()
IRQ_MASK: 0x0003,
DEBUGGER: 0x0004, // set if the Debugger wants to perform checks
WAIT: 0x0008, // WAIT operation in progress
PRESERVE: 0x000F, // OPFLAG bits to preserve prior to the next instruction
TRAP_TF: 0x0010, // aka PDP11.PSW.TF (WARNING: do not change this bit, or you will likely break opRTI())
@ -873,8 +890,7 @@ PDP11.ACCESS.UPDATE_WORD = PDP11.ACCESS.WORD | PDP11.ACCESS.UPDATE; // forme
PDP11.ACCESS.UPDATE_BYTE = PDP11.ACCESS.BYTE | PDP11.ACCESS.UPDATE; // formerly MODIFY_BYTE (1 | 2 | 4)
/*
* PSW arithmetic flags are NOT stored directly into the PSW register; they are maintained across separate
* flag registers.
* PSW arithmetic flags are NOT stored directly into the PSW register; they are maintained across separate flag registers.
*/
PDP11.PSW.FLAGS = (PDP11.PSW.NF | PDP11.PSW.ZF | PDP11.PSW.VF | PDP11.PSW.CF);

View file

@ -1078,11 +1078,13 @@ DevicePDP11.prototype.writePSW = function(data, addr)
*
* 004174: 052767 000020 173574 BIS #20,177776
*
* Since that test was written for the PDP-11/20, it's possible that newer machines
* have a different behavior, but for now, we assume that all machines allow setting PSW.TF.
* Since that test was written for the PDP-11/20, it's possible that newer machines have a different
* behavior, but for now, we assume that all machines allow setting PSW.TF.
*
* Moreover, we have changed setPSW() to disallow the setting of any bits not supported by the current
* CPU model, so it seems rather pointless to do any masking of bits here.
*/
var maskDisallowed = PDP11.PSW.UNUSED;
this.cpu.setPSW((data & ~maskDisallowed) | (this.cpu.getPSW() & maskDisallowed));
this.cpu.setPSW(data);
};
/**

View file

@ -1,10 +0,0 @@
---
layout: page
title: DEC PDP-11/10 Publications
permalink: /pubs/dec/pdp11/1110/
---
DEC PDP-11/10 Publications
---
* PDP-11/10 Handbook (1969) [[PDF](http://research.microsoft.com/en-us/um/people/gbell/Digital/PDP%2011%20Handbook%201969.pdf)]

View file

@ -7,4 +7,15 @@ permalink: /pubs/dec/pdp11/1120/
DEC PDP-11/20 Publications
---
* PDP-11/20 Handbook (1971) [[PDF](http://bitsavers.trailing-edge.com/pdf/dec/pdp11/handbooks/PDP1120_Handbook_1972.pdf)]
- PDP-11/20 Handbook (1969) [[PDF](http://research.microsoft.com/en-us/um/people/gbell/Digital/PDP%2011%20Handbook%201969.pdf)]
- PDP-11/20 Handbook (1971) [[PDF](http://bitsavers.trailing-edge.com/pdf/dec/pdp11/handbooks/PDP1120_Handbook_1972.pdf)]
The above publications actually apply to several PDP-11 models:
- PDP-11/10, which provided a minimum of 128 words of read/write memory (and 1024 words of read-only memory)
- PDP-11/20, which provided a minimum of 4,096 words of read-write memory
The 1971 Handbook also covers some additional models, which DEC says were "functionally identical":
- PDP-11/15 OEM Computer
- PDP-11R20 Rugged Computer

View file

@ -7,7 +7,9 @@ permalink: /pubs/dec/pdp11/
DEC PDP-11 Publications
---
* [PDP-11/10](1110/)
* [PDP-11/20](1120/)
- PDP-11/20 Handbook (1969) [[PDF](http://research.microsoft.com/en-us/um/people/gbell/Digital/PDP%2011%20Handbook%201969.pdf)]
- PDP-11/20 Handbook (1971) [[PDF](http://bitsavers.trailing-edge.com/pdf/dec/pdp11/handbooks/PDP1120_Handbook_1972.pdf)]
* [PDP-11/20](1120/)
* [PDP-11/40](1140/)
* [PDP-11/45](1145/)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long