Fixed the evaluation of register operands for the XOR opcode (this slipped through the cracks, since it doesn't use readSrcWord())

This commit is contained in:
Jeff Parsons 2016-11-20 13:45:08 -08:00 committed by Jeff Parsons
commit 48047c4a60
5 changed files with 61 additions and 12 deletions

View file

@ -361,3 +361,47 @@ which predates the 11/45 and 11/70, expects this instruction:
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.

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

@ -1352,9 +1352,10 @@ CPUStatePDP11.prototype.trap = function(vector, flag, reason)
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
*
@ -2227,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

@ -153,7 +153,7 @@ function Mf(){this.N&49152?(this.va|=128,this.qa(4,0,-7)):(this.w&&1120==this.fb
var Tf=[3,9,9,13,10,14,12,16,4,9,9,13,10,14,13,17];function Uf(a){var b=Ae(this,a);this.I=this.b;S(this,Fe(this,a,b));this.b=this.I-Tf[(this.D?8:0)+this.g]+(7!=this.f||this.g?0:2)}function Vf(a){var b=ze(this,a);S(this,Ee(this,a,b,65535)<<8);this.b-=this.g?9+(this.H&&6<=this.f?1:0):(this.D?5:3)+(7==this.f?2:0)}var Wf=[7,13,13,17,14,18,17,21];
function Xf(a){var b=De(this,a);a=a>>6&7;b&32768&&(b|=-65536);var c=this.u[a];c&32768&&(c|=-65536);b=~~(b*c);this.u[a]=b>>16&65535;this.u[a|1]=b&65535;this.J&128||(this.Z=b>>16,this.$=this.Z|b,this.V=0,this.U=-32768>b||32767<b?65536:0);this.b-=23}function Yf(){this.b-=5}function Zf(){this.N&49152||(this.v.reset(),Rb(this),this.w&&this.w.setData(this.u[0],!0));this.b-=667}function $f(a){if(a&8)W.call(this,a);else{var b=te(this);a&=7;7==a?R(this,b):(R(this,this.u[a]),this.u[a]=b);this.b-=9}}
function ag(){se(this);this.b-=13}function bg(a){a&1&&(this.U=65536);a&2&&(this.V=32768);a&4&&(this.$=0);a&8&&(this.Z=32768);this.b-=5}function cg(a){var b=(a&448)>>6;if(this.u[b]=this.u[b]-1&65535)R(this,this.u[7]-((a&63)<<1)),this.b+=1;this.b-=6}function dg(a){U(this,a,Ae(this,a),df);this.b-=this.g?9+(this.H&&6<=this.f?1:0):(this.D?5:3)+(7==this.f?2:0)}function eg(a){U(this,a,0,ff);this.b-=this.g?9:3+(7==this.f?2:0)}function fg(){this.qa(28,0,-8);this.b-=5}
function gg(){this.w&&(this.w.oc(this.u[7],!0),this.w.setData(this.u[0],!0));this.J|=4;Qd(this,-2);this.b-=3}function hg(a){U(this,a,this.u[a>>6&7],gf);this.b-=this.g?9:3+(7==this.f?2:0)}function W(a){var b;if(b=this.j)b=this.j,H(b,1)?(F(b,"undefined opcode "+K(b,a),!0,!0),b=Nf(b)):b=!1;b||this.qa(8,0,-8)}function Hd(a){ig[a>>12].call(this,a)}function jg(a){kg[a>>6&3].call(this,a)}function lg(a){mg[a>>6&3].call(this,a)}function ng(a){og[a>>6&3].call(this,a)}function pg(a){qg[a&15].call(this,a)}
function gg(){this.w&&(this.w.oc(this.u[7],!0),this.w.setData(this.u[0],!0));this.J|=4;Qd(this,-2);this.b-=3}function hg(a){U(this,a,-(a>>6&7)-1,gf);this.b-=this.g?9:3+(7==this.f?2:0)}function W(a){var b;if(b=this.j)b=this.j,H(b,1)?(F(b,"undefined opcode "+K(b,a),!0,!0),b=Nf(b)):b=!1;b||this.qa(8,0,-8)}function Hd(a){ig[a>>12].call(this,a)}function jg(a){kg[a>>6&3].call(this,a)}function lg(a){mg[a>>6&3].call(this,a)}function ng(a){og[a>>6&3].call(this,a)}function pg(a){qg[a&15].call(this,a)}
function rg(a){sg[a&15].call(this,a)}function tg(a){ug[a>>6&3].call(this,a)}function vg(a){wg[a>>6&3].call(this,a)}function xg(a){yg[a>>6&3].call(this,a)}
var ig=[function(a){zg[a>>8&15].call(this,a)},Uf,If,rf,nf,pf,hf,W,function(a){Ag[a>>8&15].call(this,a)},Vf,Jf,sf,of,qf,dg,W],zg=[function(a){Bg[a>>4&15].call(this,a)},Ef,Bf,tf,uf,zf,vf,xf,Sf,Sf,jg,lg,ng,W,W,W],kg=[function(a){ne(this,Fe(this,a,0));this.b-=this.g?9:3+(7==this.f?2:0)},function(a){U(this,a,0,Se);this.b-=this.g?9:3+(7==this.f?2:0)},function(a){U(this,a,1,We);this.b-=this.g?9:3+(7==this.f?2:0)},function(a){U(this,a,1,Ue);this.b-=this.g?9:3+(7==this.f?2:0)}],mg=[function(a){U(this,a,0,
Ye);this.b-=this.g?11:6},function(a){U(this,a,Ld(this)?1:0,Ie);this.b-=this.g?9:3+(7==this.f?2:0)},function(a){U(this,a,Ld(this)?1:0,df);this.b-=this.g?9:3+(7==this.f?2:0)},function(a){a=De(this,a);ne(this,a);this.b-=this.g?4:3+(7==this.f?2:0)}],og=[function(a){U(this,a,0,bf);this.b-=this.g?9:3+(7==this.f?2:0)},function(a){U(this,a,0,$e);this.b-=this.g?9:3+(7==this.f?2:0)},function(a){U(this,a,0,Me);this.b-=this.g?9:3+(7==this.f?2:0)},function(a){U(this,a,0,Ke);this.b-=this.g?9:3+(7==this.f?2:0)}],

View file

@ -140,7 +140,7 @@ function de(){this.C&49152?(this.fa|=128,K(this,4,0,-7)):(this.w&&1120==this.La&
function ke(a){var b=Wc(this,a);this.I=this.a;R(this,ad(this,a,b));this.a=this.I-je[(this.B?8:0)+this.c]+(7!=this.b||this.c?0:2)}function le(a){var b=Vc(this,a);R(this,$c(this,a,b,65535)<<8);this.a-=this.c?9+(this.D&&6<=this.b?1:0):(this.B?5:3)+(7==this.b?2:0)}var me=[7,13,13,17,14,18,17,21];
function ne(a){var b=Zc(this,a);a=a>>6&7;b&32768&&(b|=-65536);var c=this.g[a];c&32768&&(c|=-65536);b=~~(b*c);this.g[a]=b>>16&65535;this.g[a|1]=b&65535;this.u&128||(this.s=b>>16,this.i=this.s|b,this.f=0,this.m=-32768>b||32767<b?65536:0);this.a-=23}function oe(){this.a-=5}function pe(){this.C&49152||(this.h.reset(),lb(this),this.w&&this.w.setData(this.g[0],!0));this.a-=667}function qe(a){if(a&8)K(this,8,0,-8);else{var b=Qc(this);a&=7;7==a?Q(this,b):(Q(this,this.g[a]),this.g[a]=b);this.a-=9}}
function re(){Pc(this);this.a-=13}function X(a){a&1&&(this.m=65536);a&2&&(this.f=32768);a&4&&(this.i=0);a&8&&(this.s=32768);this.a-=5}function se(a){var b=(a&448)>>6;if(this.g[b]=this.g[b]-1&65535)Q(this,this.g[7]-((a&63)<<1)),this.a+=1;this.a-=6}function te(a){U(this,a,Wc(this,a),xd);this.a-=this.c?9+(this.D&&6<=this.b?1:0):(this.B?5:3)+(7==this.b?2:0)}function ue(a){U(this,a,0,zd);this.a-=this.c?9:3+(7==this.b?2:0)}function ve(){K(this,28,0,-8);this.a-=5}
function we(){this.w&&(this.w.ea=this.g[7],this.w.setData(this.g[0],!0));this.u|=4;Hc(this,-2);this.a-=3}function xe(a){U(this,a,this.g[a>>6&7],Ad);this.a-=this.c?9:3+(7==this.b?2:0)}function Y(){K(this,8,0,-8)}function Cc(a){ye[a>>12].call(this,a)}function ze(a){Ae[a>>6&3].call(this,a)}function Be(a){Ce[a>>6&3].call(this,a)}function De(a){Ee[a>>6&3].call(this,a)}function Fe(a){Ge[a&15].call(this,a)}function He(a){Ie[a&15].call(this,a)}function Je(a){Ke[a>>6&3].call(this,a)}
function we(){this.w&&(this.w.ea=this.g[7],this.w.setData(this.g[0],!0));this.u|=4;Hc(this,-2);this.a-=3}function xe(a){U(this,a,-(a>>6&7)-1,Ad);this.a-=this.c?9:3+(7==this.b?2:0)}function Y(){K(this,8,0,-8)}function Cc(a){ye[a>>12].call(this,a)}function ze(a){Ae[a>>6&3].call(this,a)}function Be(a){Ce[a>>6&3].call(this,a)}function De(a){Ee[a>>6&3].call(this,a)}function Fe(a){Ge[a&15].call(this,a)}function He(a){Ie[a&15].call(this,a)}function Je(a){Ke[a>>6&3].call(this,a)}
function Le(a){Me[a>>6&3].call(this,a)}function Ne(a){Oe[a>>6&3].call(this,a)}
var ye=[function(a){Pe[a>>8&15].call(this,a)},ke,$d,Kd,Gd,Id,Bd,Y,function(a){Qe[a>>8&15].call(this,a)},le,ae,Ld,Hd,Jd,te,Y],Pe=[function(a){Re[a>>4&15].call(this,a)},Xd,Ud,Md,Nd,Sd,Od,Qd,ie,ie,ze,Be,De,Y,Y,Y],Ae=[function(a){Kc(this,ad(this,a,0));this.a-=this.c?9:3+(7==this.b?2:0)},function(a){U(this,a,0,ld);this.a-=this.c?9:3+(7==this.b?2:0)},function(a){U(this,a,1,pd);this.a-=this.c?9:3+(7==this.b?2:0)},function(a){U(this,a,1,nd);this.a-=this.c?9:3+(7==this.b?2:0)}],Ce=[function(a){U(this,a,0,
rd);this.a-=this.c?11:6},function(a){U(this,a,P(this)?1:0,bd);this.a-=this.c?9:3+(7==this.b?2:0)},function(a){U(this,a,P(this)?1:0,xd);this.a-=this.c?9:3+(7==this.b?2:0)},function(a){a=Zc(this,a);Kc(this,a);this.a-=this.c?4:3+(7==this.b?2:0)}],Ee=[function(a){U(this,a,0,vd);this.a-=this.c?9:3+(7==this.b?2:0)},function(a){U(this,a,0,td);this.a-=this.c?9:3+(7==this.b?2:0)},function(a){U(this,a,0,fd);this.a-=this.c?9:3+(7==this.b?2:0)},function(a){U(this,a,0,dd);this.a-=this.c?9:3+(7==this.b?2:0)}],