Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

I implemented these by adding a parameter “extended_inst” to the cpu20 device. When set the code now emulates these instructions. The following instructions will be emulated with this flag set:

  • MUL

  • DIV

  • ASH

  • ASHC

  • XOR

  • SOB

Testing the EIS instructions: FKAC..

...

But there is an instruction there with the same opcode, at 000620: MTPS. Which is according to the docs a LSI11 only instruction which moves a word to the PSW. It has an accompanying read called MFPS. This is odd because the 11/34 is not a LSI11 CPU, but the test’s documentation says:

...

...

So, apparently the 11/34 implemented that MTPS instruction. Sigh. This was confirmed here:

“The Micro/J-11 supported all of the possible PDP-11 instructions, except for those unique to the PDP-11/60, and the PDP-11/34 (MTPS and MFPS).“

I implemented the mtps (1064xx) and mfps (1067xx) instructions by adding yet another cpu20 parameter:

Code Block
    parameter_bool_c allow_mxps = parameter_bool_c(this, "allow_mxps", "mxps",/*readonly*/
                             false, "Allow mtps and mfps instructions (1=11/34, LSI11, 0=standard 11/20 behavior)");

Next run

The next run came a lot further but still died with a trap 010, illegal instruction. The log showed:

Code Block
[11:42:20.938773 Dbg    cpu 03410@ka11.c:0412] EXEC [000726] MOV
[11:42:20.938777 Dbg    cpu 03410@ka11.c:0161] DATI [000730] => 000001
[11:42:20.938780 Dbg    cpu 03410@ka11.c:0161] DATI [000732] => 000440
[11:42:20.938784 Dbg    cpu 03410@ka11.c:0161] DATI [000440] => 000000
[11:42:20.938787 Dbg    cpu 03410@ka11.c:0174] DATO [000440] <= 000001
[11:42:20.938793 Dbg    cpu 03410@ka11.c:0161] DATI [000734] => 005037
[11:42:20.938797 Dbg    cpu 03410@ka11.c:0639] EXEC [000734] CLR
[11:42:20.938800 Dbg    cpu 03410@ka11.c:0161] DATI [000736] => 000442
[11:42:20.938803 Dbg    cpu 03410@ka11.c:0161] DATI [000442] => 000014
[11:42:20.938807 Dbg    cpu 03410@ka11.c:0174] DATO [000442] <= 000000
[11:42:20.938814 Dbg    cpu 03410@ka11.c:0161] DATI [000740] => 010701
[11:42:20.938817 Dbg    cpu 03410@ka11.c:0412] EXEC [000740] MOV
[11:42:20.938824 Dbg    cpu 03410@ka11.c:0161] DATI [000742] => 013700
[11:42:20.938827 Dbg    cpu 03410@ka11.c:0412] EXEC [000742] MOV
[11:42:20.938831 Dbg    cpu 03410@ka11.c:0161] DATI [000744] => 000434
[11:42:20.938834 Dbg    cpu 03410@ka11.c:0161] DATI [000434] => 000001
[11:42:20.938840 Dbg    cpu 03410@ka11.c:0161] DATI [000746] => 032737
[11:42:20.938843 Dbg    cpu 03410@ka11.c:0423] EXEC [000746] BIT
[11:42:20.938847 Dbg    cpu 03410@ka11.c:0161] DATI [000750] => 000001
[11:42:20.938850 Dbg    cpu 03410@ka11.c:0161] DATI [000752] => 000406
[11:42:20.938854 Dbg    cpu 03410@ka11.c:0161] DATI [000406] => 000000
[11:42:20.938860 Dbg    cpu 03410@ka11.c:0161] DATI [000754] => 001004
[11:42:20.938864 Dbg    cpu 03410@ka11.c:0738] EXEC [000754] BNE
[11:42:20.938870 Dbg    cpu 03410@ka11.c:0161] DATI [000756] => 013701
[11:42:20.938873 Dbg    cpu 03410@ka11.c:0412] EXEC [000756] MOV
[11:42:20.938877 Dbg    cpu 03410@ka11.c:0161] DATI [000760] => 000436
[11:42:20.938880 Dbg    cpu 03410@ka11.c:0161] DATI [000436] => 000000
[11:42:20.938886 Dbg    cpu 03410@ka11.c:0161] DATI [000762] => 072001
[11:42:20.938890 Dbg    cpu 03410@ka11.c:0498] EXEC [000762] ASH
[11:42:20.938897 Dbg    cpu 03410@ka11.c:0161] DATI [000764] => 000402
[11:42:20.938900 Dbg    cpu 03410@ka11.c:0737] EXEC [000764] BR
[11:42:20.938907 Dbg    cpu 03410@ka11.c:0161] DATI [000772] => 106737
[11:42:20.938911 Dbg    cpu 03410@ka11.c:0715] EXEC [000772] MFPS
[11:42:20.938914 Dbg    cpu 03410@ka11.c:0174] DATOB [000772] <= 000000
[11:42:20.938920 Dbg    cpu 03410@ka11.c:0161] DATI [000774] => 000432
[11:42:20.938924 Dbg    cpu 03410@ka11.c:0737] EXEC [000774] BR
[11:42:20.938930 Dbg    cpu 03410@ka11.c:0161] DATI [001062] => 177354
[11:42:20.938933 Dbg    cpu 03410@ka11.c:0815] TRAP 10

The FKAC test

Reading the fiche to understand the ASH part of it..

The test tests the ASH instruction for the registers R0..R5, where those registers are the ones to be shifted. On even passes, when we test Rn, the shift count (coming from temp2) is moved to R(n+1) and that register is used as the count. On odd passes it uses test2 directly.

The test loops 30x (36oct) though the same sets of code. Every EVEN run it

Variables:

  • temp1: current value to be shifted.

  • temp2: shift count. On even passes this gets moved to a register, and the register is used as the count source. On odd passes the ash instruction addresses temp2 directly (mode 67).

  • temp3 : the expected result of the shift operation expected in the shifted register

  • temp4: the expected PSW result

Debugging using Unibone and FKAC

Speed up emulation

By default the emulation will fully control the Unibus. This means that when it runs all data is sent to it. This is necessary when testing real hardware, of course, but for my use case, testing the emulation, I do not need the Unibus to be controlled. And disabling that greatly speeds up the emulation!

Set the parameter “pmi” to 1 to disable Unibus control.

Use Unibone breakpoints

Invaluable is the “bp” parameter in the Unibone which can be used to set a single breakpoint. As the fiche I had of FKAC was a lot different from the actual code I converted the BIC file to a binary and then used pdp11dasm to disassemble that binary. With that I could at least match pieces of actual code with the fiche.

...

Info

It later appeared that this fiche (MD-11-DFKAC-A__PDP11-34__EIS_INSTRUCTION_TEST__EP-DFKAC-A-DL-A__OCT_1977_bw.pdf), which dates from 8-sep-76 and which is called DFACA is not the right one for FKACA0. There is a better PDF (MAINDEC-11-DFKAC-A-D_1134-EIS-Instruction-Tests_Dec75.pdf) in the Diagnostics database which stems from 4-AUG-77 and which matches the module.

Implementing MTPS and MFPS

So, apparently the 11/34 implemented that MTPS instruction. Sigh. This was confirmed here:

“The Micro/J-11 supported all of the possible PDP-11 instructions, except for those unique to the PDP-11/60, and the PDP-11/34 (MTPS and MFPS).“

I implemented the mtps (1064xx) and mfps (1067xx) instructions by adding yet another cpu20 parameter:

Code Block
    parameter_bool_c allow_mxps = parameter_bool_c(this, "allow_mxps", "mxps",/*readonly*/
                             false, "Allow mtps and mfps instructions (1=11/34, LSI11, 0=standard 11/20 behavior)");

While mfps moves only the lower byte of the PSW it was not clear to me whether it would store it as a word. I did opt for that; we’ll have to see if that is true or not (it does seem to be; if I implement it as storing a byte the tests fail).

Next FKAC runs

The next runs now ran without traps, but I had to fix a number of test failures. This was a bit messy. I found out the following things from those failures…

  • The ASH and ASHC opcodes have a bit of a messy description of when the V flag is set. This flag can only be set when rotating left, and in that case it seems to get set if any of the 1 bit shifts causes the sign to change. I.e. it is not enough to shift the value immediately n bits and then check the sign of the result with the original. In the code this means that shift left and shift right are implemented differently: the right shift can be done quickly, but the left one is done bit by bit.

  • I had major trouble with the “div” instruction. Test 255 does “-9 / 3” and expects the result to be -3. This consequently failed: the quotient was always a very large number (containing a lot of hex 5’s). The code in C was simple: just “a / b”, and the values, when printed before were really -9 and 3. The result was assigned to a variable on the stack, and printing this variable immediately after gave the large number. I moved the variable to static and then the code ran without problems. In the end I decided to use ldiv() instead. I cannot explain what happened and it seems a bit worrysome.

The FKACA0 test now runs to completion without errors:

Code Block
Serial port ttyS2 opened by UniBone


MEMORY MANAGEMENT UNIT NOT FOUND



BOOTING UP XXDP-SM SMALL MONITOR


XXDP-SM SMALL MONITOR - XXDP V2.4
REVISION: D0
BOOTED FROM DL0
28KW OF MEMORY
UNIBUS SYSTEM

RESTART ADDRESS: 152010
TYPE "H" FOR HELP 

.R FKAC??
FKACA0.BIC

END PASS��
END PASS��
END PASS��
END PASS��
END PASS��
END PASS��
END PASS��
END PASS��
END PASS��
END PASS��
END PASS��
END PASS��
END PASS��
END PASS��
END PASS��
END PASS��
END PASS��
END PASS��
END PASS��
END PASS��
END PASS��

The FKAC test

Reading the fiche to understand the ASH part of it..

The test tests the ASH instruction for the registers R0..R5, where those registers are the ones to be shifted. On even passes, when we test Rn, the shift count (coming from temp2) is moved to R(n+1) and that register is used as the count. On odd passes it uses test2 directly.

The test loops 30x (36oct) though the same sets of code. After that every test number will be checked and used to change things like the shift value and the initial value. Once all ASH tests are done it switches to ASHC tests which are very similar. These are then followed by mul and div. Xor and Sob are not tested.

Variables:

  • temp1: current value to be shifted.

  • temp2: shift count. On even passes this gets moved to a register, and the register is used as the count source. On odd passes the ash instruction addresses temp2 directly (mode 67).

  • temp3 : the expected result of the shift operation expected in the shifted register

  • temp4: the expected PSW result

Debugging tests using Unibone

Speed up emulation

By default the emulation will fully control the Unibus. This means that when it runs all data is sent to it. This is necessary when testing real hardware, of course, but for my use case, testing the emulation, I do not need the Unibus to be controlled. And disabling that greatly speeds up the emulation!

Set the parameter “pmi” to 1 to disable Unibus control.

Use Unibone breakpoints

Invaluable is the “bp” parameter in the Unibone which can be used to set a single breakpoint. As the fiche I had of FKAC was a lot different from the actual code I converted the BIC file to a binary and then used pdp11dasm to disassemble that binary. With that I could at least match pieces of actual code with the fiche.

In my version of FKAC the $HLT routing which gets called at error is at location 16440oct, and this routine’s return statement is at 16622oct, so I added a breakpoint at the last address causing the test to stop as soon as an error has been found- and has been printed.

Use printf while developing

These appear on the UB console and can help a lot.

Use Unibone statement logging

Set the CPU debug level to 5, and use “dbg s” to dump a log of statements executed. The log is verbose in volume but terse in information, but it often allows you to at least follow flow just before a breakpoint.