Merge branch 'next-release'

This commit is contained in:
Jeff Parsons 2016-11-20 14:08:59 -08:00
commit 6b204b1747
18 changed files with 964 additions and 652 deletions

View file

@ -10,4 +10,8 @@ PDP-11 Software
We have archived the following selected PDP-11 software:
- [Boot Software](boot/)
- [DEC PDP-11 Tapes](tapes/), including [Paper Tape Diagnostics](tapes/diags/)
- [DEC PDP-11 Paper Tapes](tapes/), including [Paper Tape Diagnostics](tapes/diags/)
Additional DEC diagnostics are also available on disk, such as:
- [XXDP+ Diagnostics](/disks/dec/rl02k/xxdp/)

View file

@ -1,13 +1,13 @@
---
layout: page
title: DEC PDP-11 Tape Images
title: DEC PDP-11 Paper Tape Images
permalink: /apps/pdp11/tapes/
---
DEC PDP-11 Tape Images
----------------------
DEC PDP-11 Paper Tape Images
----------------------------
To load any of the DEC PDP-11 tapes listed below, you will need to use a [PDPjs Machine](/devices/pdp11/machine/)
To load any of the DEC PDP-11 paper tapes listed below, you will need to use a [PDPjs Machine](/devices/pdp11/machine/)
with a [PC11 High-Speed Paper Tape Reader/Punch](/devices/pdp11/pc11/), such as this
[PDP-11/20](/devices/pdp11/machine/1120/basic/debugger), and then follow this three-step process:

View file

@ -17,6 +17,8 @@ into RAM using the machine's "Load" button instead of "Attach", allowing you to
loading the [Bootstrap Loader](/apps/pdp11/boot/bootstrap/) in order to load the [Absolute Loader](/apps/pdp11/tapes/absloader/)
in order to load the desired tape.
Additional (non-paper tape) diagnostics are available on the [XXDP+ Diagnostics](/disks/dec/rl02k/xxdp/) disk.
[![MAINDEC-11-D0AA-PB (MAR/70): TEST 1 - BRANCH](MAINDEC-11-D0AA-PB.jpg)](#tests-1-12)
[![MAINDEC-11-D0BA-PB (MAR/70): TEST 2 - CON BRANCH](MAINDEC-11-D0BA-PB.jpg)](#tests-1-12)
[![MAINDEC-11-D0CA-PB (MAR/70): TEST 3 - UNARY](MAINDEC-11-D0CA-PB.jpg)](#tests-1-12)
@ -35,13 +37,13 @@ in order to load the desired tape.
[![MAINDEC-11-D0NC-PB (FEB/72): TEST 14C - TRAP TEST](MAINDEC-11-D0NC-PB.jpg)](#test-14)
[![MAINDEC-11-D0OA-PB (MAR/70): TEST 15 - CPU EXERCISER](MAINDEC-11-D0OA-PB.jpg)](#test-15)
Instructions for Running Diagnostics
------------------------------------
Running Paper Tape Diagnostics
------------------------------
### Tests 1-12
Instructions for running "TEST 1 - BRANCH" through "TEST 12 - JUMP" come from the
[MAINDEC USER REFERENCE MANUAL, OCTOBER 1973](http://archive.pcjs.org/pubs/dec/pdp11/diags/MAINDEC_User_Reference_Manual_Oct73.pdf),
[MAINDEC USER REFERENCE MANUAL, OCTOBER 1973](http://archive.pcjs.org/pubs/dec/pdp11/diags/MAINDEC-11-DZQAB-B-D_User_Reference_Manual_Oct73.pdf),
p. 19:
MAINDEC-11-D0AA to D0LA (NEW NUMBER - DZKAA to DZKAL)
@ -138,6 +140,22 @@ instruction, and the test will halt.
Note that, as the instructions indicate, this test will fail on a PDP-11/45 or newer machine, because
it expects the MUL instruction to trap.
This test is also noteworthy because it uncovered a bug involving instructions like this:
MOV R0,(R0)+
Imagine that R0 contains 1000. PDPjs (as well as several other emulators I tested) would write the value 1000
to address 1000 after auto-incrementing R0 to 1002.
Unfortunately, that’s wrong. Apparently, the PDP-11 performs both source and destination address calculations
before reading and writing the source and destination values. So, in the above example, the value 1002 must be
written to address 1000.
I should add that not all emulators get this wrong: [SimH](https://github.com/simh/simh), the gold standard of
PDP-11 emulators, handles it correctly. However, it's unclear how much confidence one should place in SimH,
because as I discovered later when running the [11/70 CPU EXERCISER](#md-11-1170-cpu-exerciser) diagnostic,
SimH is not infallible.
MAINDEC-11-D0NA (NEW NUMBER - DAKAA)
T14 TRAPS
@ -179,6 +197,9 @@ it expects the MUL instruction to trap.
Before loading and running this test on the [PDP-11/20 with Front Panel and Debugger](/devices/pdp11/machine/1120/panel/debugger/),
it's recommended that you also toggle SW-15, as described below, so that the test will HALT on any failure.
Also, this test, like [Test 14](#test-14), fails on a PDP-11/45 or newer machine. In this case, it's because DEC
changed the behavior of the RTI instruction on newer models.
MAINDEC-11-D0OA (NEW NUMBER - DZQKA)
T15 Instruction Exerciser
@ -234,4 +255,175 @@ so for now, I'm just going to pick out selected tapes and archive them here.
From [bitsavers.org](http://bitsavers.trailing-edge.com/bits/DEC/pdp11/papertapeimages/20040101/), Tray 02:
* Tape 04: [MAINDEC-11-DEQKC-B1-PB 06/12/78; 11/70 cpu instruction; exerciser; (c)1975,76](MAINDEC-11-DEQKC-B1-PB.json)
* Tape 04: [MAINDEC-11-DEQKC-B1-PB 06/12/78; 11/70 cpu instruction exerciser; (c)1975,76](#md-11-1170-cpu-exerciser)
MD-11 11/70 CPU EXERCISER
-------------------------
When started in a [PDP-11/70](/devices/pdp11/machine/1170/panel/debugger/cpuexer/) with no disk drives attached,
this diagnostic displays the following startup information:
MAINDEC-11-DEQKC-B...PDP 11/70 CPU EXERCISOR
OPT.CP=145406
OPERATIONAL SWITCH SETTINGS
SWITCH USE
15 HALT ON ERROR
14 LOOP ON TEST
13 INHIBIT ERROR TYPEOUTS
12 INHIBIT UBE
11 INHIBIT ITTERATIONS
10 BELL ON ERROR
9 LOOP ON ERROR
8 INHIBIT RELOCATION VIA I/O DEVICE
7 INHIBIT TYPEOUT OF THIS TEXT AND SYS SIZE
6 INHIBIT RELOCATION
5 INHIBIT ROUND ROBIN RELOCATION
4 INHIBIT RANDOM DISK ADDRESS
3 INHIBIT MBT
2 THESE THREE SWITCHES
1 ARE ENCODED TO SELECT RELOCATION
0 ON THE FOLLOWING DEVICES:
0...RP11/RP03
1...RK11/RK05
2...NOT USED
3...NOT USED
4...RH70/RP04
5...RH70/RS04 OR RS03
6...NOT USED
7...NOT USED
THE FOLLOWING DEVICES AND DRIVES WILL BE USED FOR RELOCATION:
DEVICE DRIVES
TYPE A CHARACTER TO CONTINUE
The first time I tried this test, there were a number of failures. Here's one example:
000:00:00
ERRORPC PHYSC PC PSW MAINT TEST NO SUB-PASS CNT
022024 00022024 000340 000000 000041 000000 000000
I disassembled the code responsible for that failure:
021632: 052737 000340 177776 BIS #340,@#177776
021640: 010746 MOV PC,-(SP)
021642: 062716 000152 ADD #152,@SP
021646: 011637 000004 MOV @SP,@#4
021652: 012737 000340 000006 MOV #340,@#6
021660: 013727 000014 001472 MOV @#14,#1472
021666: 062716 000100 ADD #100,@SP
021672: 012637 000014 MOV (SP)+,@#14
021676: 012737 000340 000016 MOV #340,@#16
021704: 012703 000376 MOV #376,R3
021710: 010313 MOV R3,@R3
021712: 010306 MOV R3,SP
021714: 032767 140000 000234 BIT #140000,022156
021722: 001015 BNE 021756
021724: 005716 TST @SP
021726: 021666 177776 CMP @SP,177776(SP)
021732: 012656 MOV (SP)+,@-(SP)
021734: 057636 000000 BIS @000000(SP),@(SP)+
021740: 054676 000000 BIS -(SP),@000000(SP)
021744: 005006 CLR SP
021746: 013766 020000 020000 MOV @#20000,20000(SP)
021754: 000425 BR 022030
021756: 156737 000175 177777 BISB 022157,@#177777
021764: 012706 000376 MOV #376,SP
021770: 016646 177776 MOV 177776(SP),-(SP)
021774: 051616 BIS @SP,@SP
021776: 061666 177776 ADD @SP,177776(SP)
022002: 105037 177777 CLRB @#177777
022006: 012706 000700 MOV #700,SP
022012: 000451 BR 022136
022014: 012600 MOV (SP)+,R0
022016: 012602 MOV (SP)+,R2
022020: 012706 000700 MOV #700,SP
022024: 104000 EMT 000
I wasn't able to locate a source code listing for this particular (1978) version of the 11/70 CPU Instruction Exerciser,
but I did find another useful document,
[11/40 and 11/45 INSTRUCTION EXERCISER (Sep, 1974)](http://archive.pcjs.org/pubs/dec/pdp11/diags/MAINDEC-11-DCQKC-D-D_1140_1145_INSTRUCTION_EXERCISER_Sep74.pdf),
where I discovered a matching test sequence on p. 86.
Here's an excerpt:
; THE BELOW INSTRUCTIONS SHOULD NOT CAUSE AN OVERFLOW TRAP
TST (SP) ; BECAUSE TST IS A NON MODIFYING INST
CMP (SP),-2(SP) ; SO IS COMPARE
MOV (SP)+,@-(SP) ; BECAUSE OF ADDRESS MODE 5
BIS @(SP),@(SP)+ ; BECAUSE OF ADDRESS MODE 3
BIS -(SP),@(SP) ; BECAUSE OF ADDRESS MODE 7
CLR SP
MOV @#20000,20000(SP)
BR 3$ ; BRANCH OVER NON KERNEL MODE TESTS
This test uncovered a number of stack overflow-related issues that PDPjs needed to resolve,
including the fact that none of the "deferred" addressing modes (3, 5, or 7) apparently trigger a
stack overflow; eg:
R0=000000 R1=154112 R2=155754 R3=000376 R4=160316 R5=153412
SP=000376 PC=021734 PS=000340 IR=000000 SL=000377 T0 N0 Z0 V0 C0
021734: 057636 000000 BIS @000000(SP),@(SP)+
whereas addressing mode 6 *does*; eg:
R0=001437 R1=154112 R2=000040 R3=000376 R4=160316 R5=153412
SP=000376 PC=022074 PS=000340 IR=000000 SL=000377 T0 N0 Z0 V0 C0
022074: 050666 177776 BIS SP,177776(SP)
I have to assume that the idiosyncrasies of stack overflow checking changed over time, because [Test 14](#test-14),
which predates the 11/45 and 11/70, expects this instruction:
TST -(SP)
to trap when SP is 150. That contradicts this newer test (ie, that TST should not cause an overflow
trap "BECAUSE TST IS A NON MODIFYING INST"). For this and other reasons, PDPjs now installs different
checkStackLimit() handlers based on the CPU model.
---
Here's the next test that PDPjs failed. Again, I found the same sequence of instructions in the 11/40 and 11/45
version of the diagnostic, at PC 023360 rather than 023450, so I have annotated the code below with DEC's comments:
023450: 012704 000001 MOV #1,R4 ;SET R4
023454: 006767 000060 SXT 023540 ;PRESET DATA=0
023460: 074467 000054 XOR R4,023540
023464: 100423 BMI 023534
023466: 006304 ASL R4 ;SHIFT R4
023470: 102373 BVC 023460 ;UNTIL V SETS (R4=100000)
023472: 100020 BPL 023534 ;BRANCH IF 'N' IS CLEAR
023474: 074467 000040 XOR R4,023540 ;XOR6A=177777
023500: 100015 BPL 023534
023502: 074767 000032 XOR PC,023540 ;XOR PC WITH XOR6A (177777)
023506: 010767 000030 MOV PC,023542 ;FORM PC AS USED IN XOR ABOVE
023512: 162767 000004 000022 SUB #4,023542
023520: 005167 000016 COM 023542
023524: 026767 000012 000006 CMP 023542,023540 ;XOR6A SHOULD = COMPLEMENT OF PC
023532: 001401 BEQ 023536
023534: 104000 EMT 000 ;ERROR: XOR TESTS ABOVE FAILED [They use HLT instead of EMT here]
In my case, the failure was caused by the XOR instruction: it hadn't been updated along with the rest of the
PDPjs instructions to defer evaluating register operands until BOTH *src* and *dst* operands have been decoded.
So at this point:
R0=154343 R1=154112 R2=023422 R3=154501 R4=100000 R5=155066
SP=000700 PC=023502 PS=000010 IR=000000 SL=000377 T0 N1 Z0 V0 C0
023502: 074767 000032 XOR PC,023540 ;XOR PC WITH XOR6A (177777)
the XOR instruction was using 23504 for the *src* operand instead of 23506.
Interestingly, this test PASSES in SimH, even though it *also* incorrectly uses 23504 for XOR's *src* operand.
Why? Because when SimH gets to this instruction:
023506: 010767 000030 MOV PC,023542 ;FORM PC AS USED IN XOR ABOVE
it incorrectly stores 023510 instead of 023512 into memory, and both mistakes end up canceling each other out.
In fact, I'm less impressed with the accuracy of [SimH's](https://github.com/simh/simh) PDP-11 emulation
than I used to be, because in the process of getting to this particular test within the "11/70 CPU EXERCISER"
(MAINDEC-11-DEQKC-B1-PB) diagnostic, there were numerous other failures as well (eg, TEST 41 and TEST 45).
However, SimH is not my baby, so delving into those failures is an exercise for another day.
DISCLAIMER: Until I can run this test on real PDP-11 hardware, I have to acknowledge another possible
explanation for the above failure: that SimH is *correct*, and that unlike all other registers, the value
of the PC register is always used immediately, rather than after both *src* and *dst* have been decoded.
But that strikes me as a strange architectural inconsistency, and given SimH's other "11/70 CPU EXERCISER"
test failures, I'm going to stick with my original assumption -- for now.

View file

@ -0,0 +1,14 @@
---
layout: page
title: PDP-11/70 with Front Panel and Debugger
permalink: /devices/pdp11/machine/1170/panel/debugger/cpuexer/
machines:
- id: test1170
type: pdp11
debugger: true
autoStart: true
---
This machine runs the [11/70 CPU Instruction Exerciser](/apps/pdp11/tapes/diags/#md-11-1170-cpu-exerciser): MAINDEC-11-DEQKC-B1-PB.
{% include machine.html id="test1170" %}

View file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/versions/pdpjs/1.30.3/machine.xsl"?>
<machine id="test1170" class="pdp11" border="1" pos="center" background="#FAEBD7">
<name pos="center">PDP-11/70 with 256Kb, Front Panel and Debugger</name>
<computer id="computer" busWidth="22"/>
<cpu id="cpu" model="1170" cycles="6666667"/>
<ram id="ram" addr="0x00000" size="0x40000" file="/apps/pdp11/tapes/diags/MAINDEC-11-DEQKC-B1-PB.json"/>
<device id="default" type="default"/>
<serial id="dl11" adapter="0" binding="print" upperCase="true"/>
<panel ref="/devices/pdp11/panel/1170/debugger/front.xml"/>
<debugger id="debugger" base="8" messages="" commands=""/>
<device ref="/devices/pdp11/pc11/default.xml"/>
</machine>

View file

@ -12,6 +12,9 @@ machines:
path: http://archive.pcjs.org/disks/dec/rl02k/RL02K-XXDP.json
---
This machine is ready to boot the [XXDP+ Diagnostics](/disks/dec/rl02k/xxdp/) ("BOOT RL0") and run the
[EKBEE1](/disks/dec/rl02k/xxdp/ekbee1/) diagnostic ("R EKBEE1").
{% include machine.html id="test1170" %}
Other interesting things to know about this machine:

View file

@ -9,7 +9,7 @@
<device id="default" type="default"/>
<serial id="dl11" adapter="0" binding="print" upperCase="true"/>
<panel ref="/devices/pdp11/panel/1170/debugger/front.xml"/>
<debugger id="debugger" base="8" messages="" commands=""/>
<debugger id="debugger" base="8" messages="" commands="bp 076060"/>
<device ref="/devices/pdp11/pc11/default.xml"/>
<device ref="/devices/pdp11/rl11/default.xml"/>
</machine>

View file

@ -1,14 +1,23 @@
---
layout: page
title: "DEC RL02K Disk Images: XXDP+"
title: "XXDP+ Diagnostics Disk"
permalink: /disks/dec/rl02k/xxdp/
---
DEC RL02K Disk Images: XXDP+
----------------------------
XXDP+ Diagnostics Disk
----------------------
To boot the "XXDP+ Diagnostics" disk, start a [PDP-11/70](devices/pdp11/machine/1170/panel/debugger/) and select
the "XXDP+ Diagnostics" disk from the "Disk Drive Controls", click "Load", and wait for the message:
The XXDP+ Diagnostics disk described below contains a wealth of PDP-11 tests. Tests that PDPjs has exercised
include:
- [EKBEE1: 11/70 MEMORY MANAGEMENT DIAGNOSTIC](ekbee1/) ([Demo](/devices/pdp11/machine/1170/panel/debugger/xxdp/))
Running XXDP+ Diagnostics
-------------------------
To boot the "XXDP+ Diagnostics" disk, start a [PDP-11/70](devices/pdp11/machine/1170/panel/debugger/) with an
[RL11 Disk Controller](/devices/pdp11/rl11/), select the "XXDP+ Diagnostics" disk from the "Disk Drive Controls",
click "Load", and wait for the message:
Mounted disk "XXDP+ Diagnostics" in drive RL0
@ -1180,4 +1189,3 @@ The "D" (DIRECTORY) command displays the following information:
948 DXDPU .CMD 25-MAR-82 1 037331
949 SXDP26.BAK 25-MAR-82 1 037332
950 SXDP27.BAK 25-MAR-82 1 037333

View file

@ -0,0 +1,73 @@
---
layout: page
title: "EKBEE1: 11/70 MEMORY MANAGEMENT DIAGNOSTIC"
permalink: /disks/dec/rl02k/xxdp/ekbee1/
---
EKBEE1: 11/70 MEMORY MANAGEMENT DIAGNOSTIC
------------------------------------------
From the
[PDP-11 Diagnostic Handbook (1988)](http://archive.pcjs.org/pubs/dec/pdp11/diags/PDP11_DiagnosticHandbook_1988.pdf),
p. 1-10:
11/70 MEMORY MANAGEMENT TEST
ABSTRACT:
This program was designed using a "BOTTOM UP" approach starting with the smallest segment of MEMORY
MANAGEMENT logic and building up to cover all the logic. The program begins by testing some of the
internal CPU data and address path and address detection logic, then works outward through the MEM.
MANAGEMENT registers. It is assumed that both the CPU and the CACHE have been tested, or are known
to be good.
OPERATING PROCEDURES:
Set the switch register by <CONTROL P>
CON = xxxxxxWZ
(W = deposit xxxxxx into console switch register)
(R = read and type console switch settings / CON = R)
(Z = switch console terminal back to program)
.R EKBEEI
SWITCH SETTINGS
SW15 = 1 halt on error
SW14 = 1 loop on current test
SW13 = 1 inhibit all error typeouts
SW12 = 1 inhibit trace trapping
SW11 = 1 inhibit iterations
SW10 = 1 ring bell on error
SW09 = 1 loop on error
SW08 = 1 loop on test in SWR < 06:00>
SW07 = 1 inhibit multiple error typeouts
SW06 = 1 selects subtest
...
The closest we have to a source code listing of the EKBEE1 diagnostic comes from some
[scanned microfiche](http://archive.pcjs.org/pubs/dec/pdp11/diags/AC-7975E-MC_CEKBEE0_1170_MEM_MGMT_May80.pdf)
on [bitsavers.org](http://bitsavers.trailing-edge.com/pdf/dec/pdp11/microfiche/ftp.j-hoppe.de/bw/gh/) for:
PRODUCT CODE: AC-7975E-MC
PRODUCT NAME: CEKBEE0 11/70 MEM MGMT
DATE CREATED: MAY, 1980
MAINTAINER: DIAGNOSTIC ENGINEERING
One of the last tests within the diagnostic to pass in PDPjs was "TEST 122: KT BEND", which appears on p. 208 of
the PDF (p. 199 of the source code listing):
;;***************************************************************
;*TEST 122 KT BEND
;*
;* THIS TEST ENSURES THAT TMCE KT BEND GOES LOW ON AN ODD
;* ADDRESS ERROR, SL RED, AND NEXM. THIS IS DONE BY EXECUTING
;* AN INSTRUCTION FOR EACH Of THESE THESE CASES THAT ALSO
;* CAUSES A KT ABORT. THE ABORT SHOULD NOT BE HONORED.
;*
;* NOTE: ON A KB11-E OR KB11-EM THE KT ABORT SHOULD BE HONORED OVER A
;* NEXM TRAP. IF THIS IS A KB11-E/EM THEN THIS FEATURE IS TESTED.
;****************************************************************
As noted in the *mapVirtualToPhysical()* function in [cpustate.js](/modules/pdp11/lib/cpustate.js), this test
begins at PC 076060.
This diagnostic should run in any [PDP-11/70](/devices/pdp11/machine/1170/) ([Demo](/devices/pdp11/machine/1170/panel/debugger/xxdp/)).

View file

@ -211,7 +211,7 @@ BusPDP11.IOHANDLER = {
*
* Those fallbacks may not always be appropriate; for example, byte writes to some device registers
* must be zero-extended to update the entire word. For those cases, the fallback's "preliminary" read
* is issued with a zero address so that the handler can distinguish a normal read from one of these
* is issued with a fPreWrite flag so that the handler can distinguish a normal read from one of these
* preliminary reads (aka read-before-write), and return an appropriate value for the update (eg, zero).
*
* If none of these fallback behaviors are appropriate, the device has a simple recourse: register

View file

@ -1243,15 +1243,15 @@ PDP11.JSR_CYCLES = [
PDP11.opJSR = function(opCode)
{
/*
* Since JMP and JSR opcodes have their own unique timings for the various dst modes, we must snapshot
* nStepCycles before decoding the mode, and then use that to update nStepCycles.
* Since JMP and JSR opcodes have their own unique timings for the various dst modes, we must
* snapshot nStepCycles before decoding the mode, and then use that to update nStepCycles.
*/
this.nSnapCycles = this.nStepCycles;
/*
* TODO: Determine whether or not the SRCMODE operand (regsGen[reg]) should be snapped BEFORE or AFTER we
* decode the DSTMODE operand. Doing it AFTER seems a bit risky.
*/
var addr = this.readDstAddr(opCode);
/*
* As per the WARNING in readSrcWord(), reading the SRC register AFTER decoding the DST operand
* is entirely appropriate.
*/
var reg = (opCode >> PDP11.SRCMODE.SHIFT) & PDP11.OPREG.MASK;
this.pushWord(this.regsGen[reg]);
this.regsGen[reg] = this.getPC();
@ -1883,7 +1883,11 @@ PDP11.opWAIT = function(opCode)
PDP11.opXOR = function(opCode)
{
var reg = (opCode >> PDP11.SRCMODE.SHIFT) & PDP11.OPREG.MASK;
this.updateDstWord(opCode, this.regsGen[reg], PDP11.fnXOR);
/*
* As per the WARNING in readSrcWord(), we must supply a register number rather than a register value,
* which will then be evaluated by updateDstWord() after both the SRC and DST operands have been decoded.
*/
this.updateDstWord(opCode, -reg-1 /* this.regsGen[reg] */, PDP11.fnXOR);
this.nStepCycles -= (this.dstMode? (8 + 1) : (2 + 1) + (this.dstReg == 7? 2 : 0));
};

View file

@ -125,8 +125,10 @@ CPUStatePDP11.prototype.initProcessor = function()
{
if (this.model == PDP11.MODEL_1120) {
this.decode = PDP11.op1120.bind(this);
this.checkStackLimit = this.checkStackLimit1120;
} else {
this.decode = PDP11.op1145.bind(this);
this.checkStackLimit = this.checkStackLimit1145;
}
this.initRegs();
@ -247,7 +249,7 @@ CPUStatePDP11.prototype.resetMMU = function()
this.regMMR1 = 0; // 177574
this.regMMR2 = 0; // 177576
this.regMMR3 = 0; // 172516
this.regErr = 0; // 177766
this.regErr = 0; // 177766 TODO: Do we ever need to clear this, because it appears to accumulate errors...
this.regPIR = 0; // 177772
this.regSL = 0xff; // 177774
this.mmuEnable = 0; // MMU enabled for PDP11.ACCESS.READ or PDP11.ACCESS.WRITE
@ -1304,9 +1306,11 @@ CPUStatePDP11.prototype.trap = function(vector, flag, reason)
if (this.trapPSW < 0) {
this.trapPSW = this.getPSW();
} else if (!this.mmuMode) {
/*
* Double-fault (nested trap) condition detected.
*/
reason = PDP11.REASON.RED; // double-fault (nested trap) forces a RED condition
}
var fRed = false;
if (reason == PDP11.REASON.RED) {
vector = 4;
/*
* The next two lines used to be deferred until after the setPSW() below, but
@ -1314,7 +1318,7 @@ CPUStatePDP11.prototype.trap = function(vector, flag, reason)
*/
this.regErr |= PDP11.CPUERR.RED;
this.regsGen[6] = 4;
reason = PDP11.REASON.RED;
fRed = true;
}
/*
@ -1343,14 +1347,15 @@ CPUStatePDP11.prototype.trap = function(vector, flag, reason)
*/
this.setPSW((newPSW & ~PDP11.PSW.PMODE) | ((this.trapPSW >> 2) & PDP11.PSW.PMODE));
this.pushWord(this.trapPSW);
this.pushWord(this.regsGen[7]);
this.pushWord(this.trapPSW, fRed);
this.pushWord(this.regsGen[7], fRed);
this.setPC(newPC);
/*
* DEC's "TRAP TEST" triggers a RESERVED trap with an invalid opcode and the stack deliberately
* set too low, and expects the stack overflow trap to be "sprung" immediately afterward, so we
* only want to "lose interest" in the TRAP flag(s) that were set on entry, not ALL of them.
* DEC's "TRAP TEST" (MAINDEC-11-D0NA-PB) triggers a RESERVED trap with an invalid opcode and the
* stack deliberately set too low, and expects the stack overflow trap to be "sprung" immediately
* afterward, so we only want to "lose interest" in the TRAP flag(s) that were set on entry, not ALL
* of them.
*
* this.opFlags &= ~PDP11.OPFLAG.TRAP_MASK; // lose interest in traps after an abort
*
@ -1488,12 +1493,12 @@ CPUStatePDP11.prototype.mapUnibus = function(addr)
};
/**
* mapVirtualToPhysical(virtualAddress, accessFlags)
* mapVirtualToPhysical(virtualAddress, access)
*
* mapVirtualToPhysical() does memory management. It converts a 17-bit I/D virtual address to a
* 22-bit physical address. A real PDP 11/70 memory management unit can be enabled separately
* for read and write for diagnostic purposes. This is handled here by having an enable mask
* (mmuEnable) which is tested against the operation access mask (accessFlags). If there is no
* (mmuEnable) which is tested against the operation access mask (access). If there is no
* match, then the virtual address is simply mapped as a 16 bit physical address with the upper
* page going to the IO address space. Significant access mask values used are PDP11.ACCESS.READ
* and PDP11.ACCESS.WRITE.
@ -1539,19 +1544,19 @@ CPUStatePDP11.prototype.mapUnibus = function(addr)
*
* @this {CPUStatePDP11}
* @param {number} virtualAddress
* @param {number} accessFlags
* @param {number} access
* @return {number}
*/
CPUStatePDP11.prototype.mapVirtualToPhysical = function(virtualAddress, accessFlags)
CPUStatePDP11.prototype.mapVirtualToPhysical = function(virtualAddress, access)
{
var page, pdr, physicalAddress;
this.assert(!(virtualAddress & ~0x1ffff) && accessFlags);
this.assert(!(virtualAddress & ~0x1ffff) && access);
/*
* This can happen when the DSTMODE (MAINT) bit of MMR0 is set but *not* the ENABLED bit.
*/
if (!(accessFlags & this.mmuEnable)) {
if (!(access & this.mmuEnable)) {
physicalAddress = virtualAddress & 0xffff;
if (physicalAddress >= BusPDP11.IOPAGE_16BIT) {
physicalAddress |= this.addrIOPage;
@ -1572,13 +1577,24 @@ CPUStatePDP11.prototype.mapVirtualToPhysical = function(virtualAddress, accessFl
* As an aside it turns out that it is the memory management unit that does odd address and
* non-existent memory trapping: who knew? :-) I thought these would have been handled at access time.
*
* I haven't imported the non-existent memory checks he performed (yet); I would like to see the problems
* in action first.
* TEST #122 ("KT BEND") in the "EKBEE1" diagnostic (PC 076060) triggers an ODDADDR error using this
* instruction:
*
* As for the ODDADDR error that's supposed to generate a BUS error rather than an MMU error, this happens
* in TEST #122 ("KT BEND") in the "EKBEE1" diagnostic (PC 076456).
* 076356: 005037 140001 CLR @#140001
*
* and it expects that instruction to generate a BUS error rather than an MMU error, so we deal with that
* next. However, the test also claims to check for an NEXM (non-existent memory) error, using this
* instruction:
*
* 076170: 005037 140100 CLR @#140100
*
* but that error never materializes, so I've NOT included any NEXM checks yet. I assume that any such
* checks would be limited to whatever's recorded in the Memory Size registers (177760), because actually
* checking every physical address at this stage -- even in a real MMU -- seems prohibitively expensive.
*
* TODO: Investigate why the test's NEXM error doesn't occur.
*/
if ((physicalAddress & 0x1) && !(accessFlags & PDP11.ACCESS.BYTE)) {
if ((physicalAddress & 0x1) && !(access & PDP11.ACCESS.BYTE)) {
this.regErr |= PDP11.CPUERR.ODDADDR;
this.trap(PDP11.TRAP.BUS, 0, physicalAddress);
}
@ -1592,7 +1608,7 @@ CPUStatePDP11.prototype.mapVirtualToPhysical = function(virtualAddress, accessFl
case PDP11.PDR.ACF.RO: // 0x2: read-only, abort on write attempt
pdr |= PDP11.PDR.ACCESSED;
if (accessFlags & PDP11.ACCESS.WRITE) {
if (access & PDP11.ACCESS.WRITE) {
newMMR0 = PDP11.MMR0.ABORT_RO;
}
break;
@ -1602,13 +1618,13 @@ CPUStatePDP11.prototype.mapVirtualToPhysical = function(virtualAddress, accessFl
/* falls through */
case PDP11.PDR.ACF.RW2: // 0x5: read/write, memory management trap upon completion of a write (11/70 only)
if (accessFlags & PDP11.ACCESS.WRITE) {
if (access & PDP11.ACCESS.WRITE) {
newMMR0 = PDP11.MMR0.TRAP_MMU;
}
/* falls through */
case PDP11.PDR.ACF.RW: // 0x6: read/write, no system trap/abort action
pdr |= ((accessFlags & PDP11.ACCESS.WRITE) ? (PDP11.PDR.ACCESSED | PDP11.PDR.MODIFIED) : PDP11.PDR.ACCESSED);
pdr |= ((access & PDP11.ACCESS.WRITE) ? (PDP11.PDR.ACCESSED | PDP11.PDR.MODIFIED) : PDP11.PDR.ACCESSED);
break;
default: // 0x0 (non-resident, abort all accesses) or 0x3 or 0x7 (unused, abort all accesses)
@ -1717,61 +1733,23 @@ CPUStatePDP11.prototype.popWord = function()
};
/**
* pushWord(data)
* pushWord(data, fRed)
*
* @this {CPUStatePDP11}
* @param {number} data
* @param {boolean} [fRed]
*/
CPUStatePDP11.prototype.pushWord = function(data)
CPUStatePDP11.prototype.pushWord = function(data, fRed)
{
var virtualAddress = (this.regsGen[6] - 2) & 0xffff;
this.regsGen[6] = virtualAddress; // BSD needs SP updated before any fault :-(
this.lastOp = (this.lastOp & 0xffff) | ((this.lastOp & ~0xffff) << 8) | (0x00f6 << 16);
this.checkStackLimit(0, virtualAddress);
if (!fRed) this.checkStackLimit(PDP11.ACCESS.WRITE_WORD, -2, virtualAddress);
this.writeWord(virtualAddress, data);
};
/**
* checkStackLimit(mode, addr)
*
* The special "mode 0" case used by pushWord() ignores addr <= 4, because pushWord() is used by trap(),
* and if the trap() was generated by a RED error (below) or generated a RED error itself, then we need to
* avoid triggering another (nested) RED error.
*
* TODO: pushWord() is not used exclusively by trap(); it's also used by a few instructions, like opJSR(),
* so we might need to do some additional factoring of this function's logic.
*
* @this {CPUStatePDP11}
* @param {number} mode (ie, the addressing mode, or 0 if pushWord() is checking)
* @param {number} addr
*/
CPUStatePDP11.prototype.checkStackLimit = function(mode, addr)
{
if (!this.mmuMode) {
/*
* NOTE: I've removed the tests below for addr >= 0xFFFE, which were ported from the original code,
* because while it's definitely a bad physical stack address, I'm not sure it rises to the level of
* a trap, and this code is already expensive enough as it is.
*/
if (addr <= this.regSL && (mode || addr > 4) /* || mode && addr >= 0xFFFE */) {
if (this.model >= PDP11.MODEL_1145 && (addr <= this.regSL - 32 /* || mode == 1 && addr >= 0xFFFE */)) {
this.regErr |= PDP11.CPUERR.RED;
this.regsGen[6] = 4;
this.trap(PDP11.TRAP.BUS, 0, PDP11.REASON.RED);
} else {
/*
* On older machines (eg, the PDP-11/20), the instruction is always allowed to complete,
* so the trap must always be issued in this fashion.
*/
this.regErr |= PDP11.CPUERR.YELLOW;
this.opFlags |= PDP11.OPFLAG.TRAP_SP;
}
}
}
};
/**
* getAddrByMode(mode, reg, accessFlags)
* getAddrByMode(mode, reg, access)
*
* getAddrByMode() maps a six bit operand to a 17 bit I/D virtual address space.
*
@ -1798,7 +1776,14 @@ CPUStatePDP11.prototype.checkStackLimit = function(mode, addr)
* --------------------
* On the PDP-11/20, stack overflow traps occur when an address below 400 is referenced
* by SP in either mode 4 (auto-decrement) or 5 (auto-decrement deferred). The instruction
* is allowed to complete before the trap is issued.
* is allowed to complete before the trap is issued. NOTE: This information comes
* directly from the PDP-11/20 Handbook (1971), but the 11/20 diagnostics apparently only
* test mode 4, not mode 5, because when I later removed stack limit checks for mode 5 on
* the 11/70, none of the 11/20 tests complained.
*
* TODO: Find some independent confirmation as to whether ANY PDP-11 models check for
* stack overflow on mode 5 (auto-decrement deferred); if they do, then further tweaks to
* checkStackLimit functions may be required.
*
* On the PDP-11/70, the stack limit register (177774) allows a variable boundary for the
* kernel stack.
@ -1806,13 +1791,13 @@ CPUStatePDP11.prototype.checkStackLimit = function(mode, addr)
* @this {CPUStatePDP11}
* @param {number} mode
* @param {number} reg
* @param {number} accessFlags
* @param {number} access
* @return {number}
*/
CPUStatePDP11.prototype.getAddrByMode = function(mode, reg, accessFlags)
CPUStatePDP11.prototype.getAddrByMode = function(mode, reg, access)
{
var virtualAddress, step;
var addrDSpace = (accessFlags & PDP11.ACCESS.VIRT)? 0 : this.addrDSpace;
var addrDSpace = (access & PDP11.ACCESS.VIRT)? 0 : this.addrDSpace;
/*
* Modes that need to auto-increment or auto-decrement will break, in order to perform
@ -1835,9 +1820,7 @@ CPUStatePDP11.prototype.getAddrByMode = function(mode, reg, accessFlags)
* Mode 1: (R)
*/
case 1:
if (reg == 6 && (accessFlags & PDP11.ACCESS.WRITE)) {
this.checkStackLimit(mode, this.regsGen[6]);
}
if (reg == 6) this.checkStackLimit(access, 0, this.regsGen[6]);
this.nStepCycles -= (2 + 1);
return (reg == 7? this.regsGen[reg] : (this.regsGen[reg] | addrDSpace));
@ -1847,11 +1830,10 @@ CPUStatePDP11.prototype.getAddrByMode = function(mode, reg, accessFlags)
case 2:
step = 2;
virtualAddress = this.regsGen[reg];
if (reg == 6) this.checkStackLimit(access, step, virtualAddress);
if (reg != 7) {
virtualAddress |= addrDSpace;
if (reg < 6 && (accessFlags & PDP11.ACCESS.BYTE)) {
step = 1;
}
if (reg < 6 && (access & PDP11.ACCESS.BYTE)) step = 1;
}
this.nStepCycles -= (2 + 1);
break;
@ -1873,8 +1855,9 @@ CPUStatePDP11.prototype.getAddrByMode = function(mode, reg, accessFlags)
*/
case 4:
step = -2;
if (reg < 6 && (accessFlags & PDP11.ACCESS.BYTE)) step = -1;
if (reg < 6 && (access & PDP11.ACCESS.BYTE)) step = -1;
virtualAddress = (this.regsGen[reg] + step) & 0xffff;
if (reg == 6) this.checkStackLimit(access, step, virtualAddress);
if (reg != 7) virtualAddress |= addrDSpace;
this.nStepCycles -= (3 + 1);
break;
@ -1895,9 +1878,10 @@ CPUStatePDP11.prototype.getAddrByMode = function(mode, reg, accessFlags)
*/
case 6:
virtualAddress = this.readWord(this.advancePC(2));
virtualAddress = ((virtualAddress + this.regsGen[reg]) & 0xffff) | addrDSpace;
virtualAddress = (virtualAddress + this.regsGen[reg]) & 0xffff;
if (reg == 6) this.checkStackLimit(access, 0, virtualAddress);
this.nStepCycles -= (4 + 2);
return virtualAddress;
return virtualAddress | addrDSpace;
/*
* Mode 7: @d(R)
@ -1905,24 +1889,73 @@ CPUStatePDP11.prototype.getAddrByMode = function(mode, reg, accessFlags)
case 7:
virtualAddress = this.readWord(this.advancePC(2));
virtualAddress = (virtualAddress + this.regsGen[reg]) & 0xffff;
virtualAddress = this.readWord(virtualAddress | this.addrDSpace) | addrDSpace;
virtualAddress = this.readWord(virtualAddress | this.addrDSpace);
this.nStepCycles -= (7 + 3);
return virtualAddress;
return virtualAddress | addrDSpace;
}
this.regsGen[reg] = (this.regsGen[reg] + step) & 0xffff;
this.lastOp = (this.lastOp & 0xffff) | ((this.lastOp & ~0xffff) << 8) | ((((step << 3) & 0xf8) | reg) << 16);
/*
* NOTE: We had to eliminate the test for "(accessFlags & PDP11.ACCESS.WRITE)", because DEC's
* "TRAP TEST" expects "TST -(SP)" to trap when SP is 150.
*/
if (reg == 6 && step < 0) {
this.checkStackLimit(mode, this.regsGen[6]);
}
return virtualAddress;
};
/**
* checkStackLimit1120(access, step, addr)
*
* @this {CPUStatePDP11}
* @param {number} access
* @param {number} step
* @param {number} addr
*/
CPUStatePDP11.prototype.checkStackLimit1120 = function(access, step, addr)
{
/*
* NOTE: DEC's "TRAP TEST" (MAINDEC-11-D0NA-PB) expects "TST -(SP)" to trap when SP is 150,
* so we ignore the access parameter. Also, strangely, it does NOT expect this instruction
* to trap:
*
* R0=006302 R1=000000 R2=000000 R3=000000 R4=000000 R5=000776
* SP=000000 PC=006346 PS=000344 IR=000000 SL=000377 T0 N0 Z1 V0 C0
* 006346: 112667 171426 MOVB (SP)+,000000
*
* so if the step parameter is positive, we let it go.
*/
if (!this.mmuMode && step <= 0 && addr <= this.regSL) {
/*
* On older machines (eg, the PDP-11/20), there is no "YELLOW" and "RED" distinction, and the
* instruction is always allowed to complete, so the trap must always be issued in this fashion.
*/
this.opFlags |= PDP11.OPFLAG.TRAP_SP;
}
};
/**
* checkStackLimit1145(access, step, addr)
*
* @this {CPUStatePDP11}
* @param {number} access
* @param {number} step
* @param {number} addr
*/
CPUStatePDP11.prototype.checkStackLimit1145 = function(access, step, addr)
{
if (!this.mmuMode) {
/*
* NOTE: The 11/70 CPU Instruction Exerciser does NOT expect reads to trigger a stack overflow,
* so we check the access parameter.
*/
if ((access & PDP11.ACCESS.WRITE) && addr <= this.regSL) {
if (addr <= this.regSL - 32) {
this.trap(PDP11.TRAP.BUS, 0, PDP11.REASON.RED);
} else {
this.regErr |= PDP11.CPUERR.YELLOW;
this.opFlags |= PDP11.OPFLAG.TRAP_SP;
}
}
}
};
/**
* getByteDirect(addr)
*
@ -2008,35 +2041,35 @@ CPUStatePDP11.prototype.setWordDirect = function(addr, data)
};
/**
* getPhysicalAddrByMode(mode, reg, accessFlags)
* getPhysicalAddrByMode(mode, reg, access)
*
* This is a handler set up by setMemoryAccess(). All calls should go through getAddr().
*
* @this {CPUStatePDP11}
* @param {number} mode
* @param {number} reg
* @param {number} accessFlags
* @param {number} access
* @return {number}
*/
CPUStatePDP11.prototype.getPhysicalAddrByMode = function(mode, reg, accessFlags)
CPUStatePDP11.prototype.getPhysicalAddrByMode = function(mode, reg, access)
{
return this.getAddrByMode(mode, reg, accessFlags);
return this.getAddrByMode(mode, reg, access);
};
/**
* getVirtualAddrByMode(mode, reg, accessFlags)
* getVirtualAddrByMode(mode, reg, access)
*
* This is a handler set up by setMemoryAccess(). All calls should go through getAddr().
*
* @this {CPUStatePDP11}
* @param {number} mode
* @param {number} reg
* @param {number} accessFlags
* @param {number} access
* @return {number}
*/
CPUStatePDP11.prototype.getVirtualAddrByMode = function(mode, reg, accessFlags)
CPUStatePDP11.prototype.getVirtualAddrByMode = function(mode, reg, access)
{
return this.mapVirtualToPhysical(this.getAddrByMode(mode, reg, accessFlags), accessFlags);
return this.mapVirtualToPhysical(this.getAddrByMode(mode, reg, access), access);
};
/**
@ -2096,14 +2129,14 @@ CPUStatePDP11.prototype.writeWordToVirtual = function(virtualAddress, data)
};
/**
* readWordFromPrevSpace(opCode, accessFlags)
* readWordFromPrevSpace(opCode, access)
*
* @this {CPUStatePDP11}
* @param {number} opCode
* @param {number} accessFlags (really just PDP11.ACCESS.DSPACE or PDP11.ACCESS.ISPACE)
* @param {number} access (really just PDP11.ACCESS.DSPACE or PDP11.ACCESS.ISPACE)
* @return {number}
*/
CPUStatePDP11.prototype.readWordFromPrevSpace = function(opCode, accessFlags)
CPUStatePDP11.prototype.readWordFromPrevSpace = function(opCode, access)
{
var data;
var reg = this.dstReg = opCode & PDP11.OPREG.MASK;
@ -2116,25 +2149,25 @@ CPUStatePDP11.prototype.readWordFromPrevSpace = function(opCode, accessFlags)
}
} else {
var addr = this.getAddrByMode(mode, reg, PDP11.ACCESS.READ_WORD);
if (!(accessFlags & PDP11.ACCESS.DSPACE)) {
if (!(access & PDP11.ACCESS.DSPACE)) {
if ((this.regPSW & 0xf000) !== 0xf000) addr &= 0xffff;
}
this.mmuMode = (this.regPSW >> 12) & 3;
data = this.readWord(addr | (accessFlags & this.addrDSpace));
data = this.readWord(addr | (access & this.addrDSpace));
this.mmuMode = (this.regPSW >> 14) & 3;
}
return data;
};
/**
* writeWordToPrevSpace(opCode, accessFlags, data)
* writeWordToPrevSpace(opCode, access, data)
*
* @this {CPUStatePDP11}
* @param {number} opCode
* @param {number} accessFlags (really just PDP11.ACCESS.DSPACE or PDP11.ACCESS.ISPACE)
* @param {number} access (really just PDP11.ACCESS.DSPACE or PDP11.ACCESS.ISPACE)
* @param {number} data
*/
CPUStatePDP11.prototype.writeWordToPrevSpace = function(opCode, accessFlags, data)
CPUStatePDP11.prototype.writeWordToPrevSpace = function(opCode, access, data)
{
this.lastOp = (this.lastOp & 0xffff) | (0x0016 << 16);
var reg = this.dstReg = opCode & PDP11.OPREG.MASK;
@ -2147,7 +2180,7 @@ CPUStatePDP11.prototype.writeWordToPrevSpace = function(opCode, accessFlags, dat
}
} else {
var addr = this.getAddrByMode(mode, reg, PDP11.ACCESS.WRITE_WORD);
if (!(accessFlags & PDP11.ACCESS.DSPACE)) addr &= 0xffff;
if (!(access & PDP11.ACCESS.DSPACE)) addr &= 0xffff;
/*
* TODO: Consider replacing the following code with writeWord(), by adding optional mmuMode
* parameters for each of the discrete mapVirtualToPhysical() and bus.setWord() operations, because
@ -2155,7 +2188,7 @@ CPUStatePDP11.prototype.writeWordToPrevSpace = function(opCode, accessFlags, dat
* setMemoryAccess() handlers.
*/
this.mmuMode = (this.regPSW >> 12) & 3;
addr = this.mapVirtualToPhysical(addr | (accessFlags & PDP11.ACCESS.DSPACE), PDP11.ACCESS.WRITE);
addr = this.mapVirtualToPhysical(addr | (access & PDP11.ACCESS.DSPACE), PDP11.ACCESS.WRITE);
this.mmuMode = (this.regPSW >> 14) & 3;
this.bus.setWord(addr, data);
}
@ -2195,7 +2228,7 @@ CPUStatePDP11.prototype.readSrcByte = function(opCode)
* been decoded and any pre-decrement or post-increment operations affecting the SRC register have
* been completed.
*
* Here's an example from DEC's "TRAP TEST":
* Here's an example from DEC's "TRAP TEST" (MAINDEC-11-D0NA-PB):
*
* 007200: 012700 006340 MOV #6340,R0
* 007204: 010020 MOV R0,(R0)+

View file

@ -69,41 +69,6 @@ function DevicePDP11(parmsDevice)
Component.subclass(DevicePDP11);
DevicePDP11.M9312 = [
0x101F, /*0010037*/ 0x01C0, /*0000700*/ 0x105F, /*0010137*/ 0x01C2, /*0000702*/ 0x111F, /*0010437*/ 0x01C4, /*0000704*/ 0x0A1F, /*0005037*/ 0x01C6, /*0000706*/
0x55DF, /*0052737*/ 0x8000, /*0100000*/ 0xFFFE, /*0177776*/ 0x35DF, /*0032737*/ 0x4000, /*0040000*/ 0xFFFE, /*0177776*/ 0x0302, /*0001402*/ 0x0A9F, /*0005237*/
0x01C6, /*0000706*/ 0x0A1F, /*0005037*/ 0xFFFE, /*0177776*/ 0x0101, /*0000401*/ 0x0000, /*0000000*/ 0x0A06, /*0005006*/ 0x8104, /*0100404*/ 0x8503, /*0102403*/
0x8202, /*0101002*/ 0x0501, /*0002401*/ 0x8301, /*0101401*/ 0x0000, /*0000000*/ 0x0AC6, /*0005306*/ 0x8003, /*0100003*/ 0x0302, /*0001402*/ 0x0401, /*0002001*/
0x0701, /*0003401*/ 0x0000, /*0000000*/ 0x0C06, /*0006006*/ 0x8402, /*0102002*/ 0x8601, /*0103001*/ 0x0201, /*0001001*/ 0x0000, /*0000000*/ 0x15C6, /*0012706*/
0xAAAA, /*0125252*/ 0x1180, /*0010600*/ 0x1001, /*0010001*/ 0x1042, /*0010102*/ 0x1083, /*0010203*/ 0x10C4, /*0010304*/ 0x1105, /*0010405*/ 0xE141, /*0160501*/
0x0501, /*0002401*/ 0x0301, /*0001401*/ 0x0000, /*0000000*/ 0x0C42, /*0006102*/ 0x8601, /*0103001*/ 0x0501, /*0002401*/ 0x0000, /*0000000*/ 0x6083, /*0060203*/
0x0A83, /*0005203*/ 0x0A43, /*0005103*/ 0x60C1, /*0060301*/ 0x8701, /*0103401*/ 0x0701, /*0003401*/ 0x0000, /*0000000*/ 0x0C04, /*0006004*/ 0x5103, /*0050403*/
0x6143, /*0060503*/ 0x0A83, /*0005203*/ 0x8702, /*0103402*/ 0x0AC1, /*0005301*/ 0x0501, /*0002401*/ 0x0000, /*0000000*/ 0x0A40, /*0005100*/ 0x8301, /*0101401*/
0x0000, /*0000000*/ 0x4001, /*0040001*/ 0x6041, /*0060101*/ 0x0601, /*0003001*/ 0x0701, /*0003401*/ 0x0000, /*0000000*/ 0x00C1, /*0000301*/ 0x2057, /*0020127*/
0x5455, /*0052125*/ 0x0204, /*0001004*/ 0x3105, /*0030405*/ 0x0602, /*0003002*/ 0x0A45, /*0005105*/ 0x0201, /*0001001*/ 0x0000, /*0000000*/ 0x95C0, /*0112700*/
0xFF01, /*0177401*/ 0x8001, /*0100001*/ 0x0000, /*0000000*/ 0x7E02, /*0077002*/ 0x0A01, /*0005001*/ 0x0A81, /*0005201*/ 0x7E02, /*0077002*/ 0x0BC0, /*0005700*/
0x0202, /*0001002*/ 0x0BC1, /*0005701*/ 0x0301, /*0001401*/ 0x0000, /*0000000*/ 0x15C6, /*0012706*/ 0x01FE, /*0000776*/ 0x09F7, /*0004767*/ 0x0002, /*0000002*/
0x0000, /*0000000*/ 0x25CE, /*0022716*/ 0x00D0, /*0000320*/ 0x0301, /*0001401*/ 0x0000, /*0000000*/ 0x15CE, /*0012716*/ 0x00E2, /*0000342*/ 0x0087, /*0000207*/
0x0000, /*0000000*/ 0x0A26, /*0005046*/ 0x15E6, /*0012746*/ 0x00EC, /*0000354*/ 0x0002, /*0000002*/ 0x0000, /*0000000*/ 0x005F, /*0000137*/ 0x00F2, /*0000362*/
0x0080, /*0000200*/ 0x15C5, /*0012705*/ 0xE000, /*0160000*/ 0x0A1F, /*0005037*/ 0x0006, /*0000006*/ 0x15DF, /*0012737*/ 0x0100, /*0000400*/ 0x0004, /*0000004*/
0x15C6, /*0012706*/ 0x01FE, /*0000776*/ 0x0BE5, /*0005745*/ 0x15DF, /*0012737*/ 0x01CC, /*0000714*/ 0x004C, /*0000114*/ 0x0A1F, /*0005037*/ 0x004E, /*0000116*/
0x15C3, /*0012703*/ 0xFFE6, /*0177746*/ 0x15CB, /*0012713*/ 0x000C, /*0000014*/ 0x15C2, /*0012702*/ 0x0200, /*0001000*/ 0x1080, /*0010200*/ 0x1008, /*0010010*/
0x0BD0, /*0005720*/ 0x2005, /*0020005*/ 0x83FC, /*0101774*/ 0x1080, /*0010200*/ 0x1201, /*0011001*/ 0x2001, /*0020001*/ 0x0301, /*0001401*/ 0x0000, /*0000000*/
0x0A50, /*0005120*/ 0x2005, /*0020005*/ 0x83F9, /*0101771*/ 0x1801, /*0014001*/ 0x0A41, /*0005101*/ 0x2001, /*0020001*/ 0x0301, /*0001401*/ 0x0000, /*0000000*/
0x2002, /*0020002*/ 0x02F9, /*0001371*/ 0x0A0E, /*0005016*/ 0x15C4, /*0012704*/ 0xAAAA, /*0125252*/ 0x15CB, /*0012713*/ 0x0018, /*0000030*/ 0x15C0, /*0012700*/
0x0800, /*0004000*/ 0x15C2, /*0012702*/ 0x0200, /*0001000*/ 0x0A44, /*0005104*/ 0x1108, /*0010410*/ 0x0A48, /*0005110*/ 0x0A48, /*0005110*/ 0x2204, /*0021004*/
0x0301, /*0001401*/ 0x0000, /*0000000*/ 0x0C1F, /*0006037*/ 0xFFEA, /*0177752*/ 0x8702, /*0103402*/ 0x0000, /*0000000*/ 0x0131, /*0000461*/ 0x8A4E, /*0105116*/
0x02F2, /*0001362*/ 0x0102, /*0000402*/ 0x0077, /*0000167*/ 0xFE88, /*0177210*/ 0x0BD0, /*0005720*/ 0x7E93, /*0077223*/ 0x15CB, /*0012713*/ 0x0024, /*0000044*/
0x15C0, /*0012700*/ 0x0C00, /*0006000*/ 0x8A76, /*0105166*/ 0x0001, /*0000001*/ 0x02E4, /*0001344*/ 0x15C2, /*0012702*/ 0x0200, /*0001000*/ 0x1080, /*0010200*/
0x1008, /*0010010*/ 0x0BD0, /*0005720*/ 0x2005, /*0020005*/ 0x83FC, /*0101774*/ 0x15C1, /*0012701*/ 0x0003, /*0000003*/ 0x0A0E, /*0005016*/ 0x0BDF, /*0005737*/
0x01C6, /*0000706*/ 0x0210, /*0001020*/ 0x15CE, /*0012716*/ 0x0018, /*0000030*/ 0x1080, /*0010200*/ 0x0A48, /*0005110*/ 0x0A48, /*0005110*/ 0x2008, /*0020010*/
0x0301, /*0001401*/ 0x0000, /*0000000*/ 0x0BD0, /*0005720*/ 0x0C1F, /*0006037*/ 0xFFEA, /*0177752*/ 0x8702, /*0103402*/ 0x0000, /*0000000*/ 0x0108, /*0000410*/
0x2005, /*0020005*/ 0x83F3, /*0101763*/ 0x138B, /*0011613*/ 0x0A0E, /*0005016*/ 0x7E51, /*0077121*/ 0x0104, /*0000404*/ 0x0000, /*0000000*/ 0x0102, /*0000402*/
0x15CB, /*0012713*/ 0x000C, /*0000014*/ 0x17C0, /*0013700*/ 0x01C0, /*0000700*/ 0x17C1, /*0013701*/ 0x01C2, /*0000702*/ 0x17C4, /*0013704*/ 0x01C4, /*0000704*/
0x0074, /*0000164*/ 0x0002, /*0000002*/ 0x17C4, /*0013704*/ 0xFF78, /*0177570*/ 0x45C4, /*0042704*/ 0xFE00, /*0177000*/ 0x55C4, /*0052704*/ 0xF600, /*0173000*/
0x97C0, /*0113700*/ 0xFF79, /*0177571*/ 0x0C80, /*0006200*/ 0x00A1, /*0000241*/ 0x004C, /*0000114*/ 0x0000, /*0000000*/ 0x4230, /*0041060*/ 0x2A2D /*0025055*/
];
/**
* initBus(cmp, bus, cpu, dbg)
*

View file

@ -46,7 +46,8 @@ var MessagesPDP11 = {
KEYS: 0x00020000,
PAPER: 0x00100000,
DISK: 0x00400000,
SERIAL: 0x00800000,
RL11: 0x00800000,
SERIAL: 0x01000000,
SPEAKER: 0x02000000,
COMPUTER: 0x04000000,
LOG: 0x10000000,
@ -83,6 +84,7 @@ MessagesPDP11.CATEGORIES = {
"key": MessagesPDP11.KEYS, // using "key" instead of "keys", since the latter is a method on JavasScript objects
"paper": MessagesPDP11.PAPER,
"disk": MessagesPDP11.DISK,
"rl11": MessagesPDP11.RL11,
"serial": MessagesPDP11.SERIAL,
"speaker": MessagesPDP11.SPEAKER,
"computer": MessagesPDP11.COMPUTER,

View file

@ -308,11 +308,11 @@ RAMPDP11.prototype.loadImage = function(aBytes, addrLoad, addrExec, addrInit, fR
}
var offBlock = off;
if (w != 0x0001) {
if (MAXDEBUG) this.println("invalid signature (" + str.toHexWord(w) + ") at offset " + str.toHexWord(offBlock));
this.printMessage("invalid signature (" + str.toHexWord(w) + ") at offset " + str.toHexWord(offBlock), MessagesPDP11.PAPER);
break;
}
if (off + 6 >= aBytes.length) {
if (MAXDEBUG) this.println("invalid block at offset " + str.toHexWord(offBlock));
this.printMessage("invalid block at offset " + str.toHexWord(offBlock), MessagesPDP11.PAPER);
break;
}
off += 2;
@ -326,12 +326,12 @@ RAMPDP11.prototype.loadImage = function(aBytes, addrLoad, addrExec, addrInit, fR
len--;
}
if (len != 0 || off >= aBytes.length) {
if (MAXDEBUG) this.println("insufficient data for block at offset " + str.toHexWord(offBlock));
this.printMessage("insufficient data for block at offset " + str.toHexWord(offBlock), MessagesPDP11.PAPER);
break;
}
checksum += aBytes[off++] & 0xff;
if (checksum & 0xff) {
if (MAXDEBUG) this.println("invalid checksum (" + str.toHexByte(checksum) + ") for block at offset " + str.toHexWord(offBlock));
this.printMessage("invalid checksum (" + str.toHexByte(checksum) + ") for block at offset " + str.toHexWord(offBlock), MessagesPDP11.PAPER);
break;
}
if (!cbData) {

View file

@ -52,7 +52,7 @@ if (NODE) {
*/
function RL11(parms)
{
Component.call(this, "RL11", parms, RL11, MessagesPDP11.DISK);
Component.call(this, "RL11", parms, RL11, MessagesPDP11.RL11);
/*
* We record any 'autoMount' object now, but we no longer parse it until initBus(),
@ -963,6 +963,8 @@ RL11.prototype.processCommand = function()
}
};
/**
* endReadWrite(err, iCylinder, iHead, iSector, nWords, addr)
*
@ -1027,7 +1029,7 @@ RL11.prototype.readData = function(drive, iCylinder, iHead, iSector, nWords, add
err = PDP11.RL11.ERRC.HNF;
break;
}
var data = this.bus.setWord(addr, b0 | (b1 << 8));
var data = this.bus.setWordDirect(addr, b0 | (b1 << 8));
if (this.bus.checkFault()) {
err = PDP11.RL11.ERRC.NXM;
break;
@ -1075,7 +1077,7 @@ RL11.prototype.writeData = function(drive, iCylinder, iHead, iSector, nWords, ad
}
while (nWords--) {
var data = this.bus.getWord(addr);
var data = this.bus.getWordDirect(addr);
if (this.bus.checkFault()) {
err = PDP11.RL11.ERRC.NXM;
break;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long