diff --git a/doc/w11a_diff_70_jsr_sp.md b/doc/w11a_diff_70_jsr_sp.md new file mode 100644 index 00000000..30e4b2e4 --- /dev/null +++ b/doc/w11a_diff_70_jsr_sp.md @@ -0,0 +1,29 @@ +## Known differences between w11a and KB11-C (11/70) + +### `jsr sp` pushes original `sp` value + +In the logic of the `jsr` instruction is the given register the +_linkage register_, meant to be used for parameter passing. +`jsr` pushes the _linkage register_ to the stack, and the matching `rts` +will restore it. That works fine for `r0` to `r5` and for `pc`. +But in a `jsr sp` that interferes with the implicit use of `sp` +as the stack pointer, `sp` is saved on the stack which is defined by `sp`. +The question is whether the original `sp` value is saved, or the `sp` +value after it has been decremented to hold the address for the write +to stack. The specification simply says +``` + down(sp) := sp +``` +and the question is whether the side effect of the left side happens before +the right side is evaluated. + +The 11/70 implementation of `jsr` first decrements the `sp` in +microstate `jsr.20` and then starts a write of `sp` in `jsr.30`. +So the modified `sp` is stored. + +The w11 implement ion first reads `sp` into a register, then decrements +`sp` and writes. So the original `sp` is stored. + +`jsr sp` is never used due to its bizarre semantics. The matching `rts sp` +results in a useless `sp` too. Given that, this is considered an +acceptable deviation from 11/70 behavior. diff --git a/doc/w11a_known_differences.md b/doc/w11a_known_differences.md index ebaa1e5f..c32afeeb 100644 --- a/doc/w11a_known_differences.md +++ b/doc/w11a_known_differences.md @@ -8,6 +8,7 @@ The issues of the w11 CPU and systems are listed in a separate document - [Instruction fetch after `SPL`](w11a_diff_70_spl_bug.md) - ['red stack violation' loses PSW](w11a_diff_70_red_stack_abort.md) - ['instruction completed flag' in `MMR0` is not implemented](w11a_diff_70_instruction_complete.md) +- [`jsr sp` pushes original `sp` value](w11a_diff_70_jsr_sp.md) - [18-bit UNIBUS address space not mapped](w11a_diff_70_unibus_mapping.md) All points relate to very 11/70 specific behavior, no operating system diff --git a/tools/tcode/cpu_basics.mac b/tools/tcode/cpu_basics.mac index a3ca04a3..fa1dae30 100644 --- a/tools/tcode/cpu_basics.mac +++ b/tools/tcode/cpu_basics.mac @@ -1,4 +1,4 @@ -; $Id: cpu_basics.mac 1263 2022-07-28 09:00:42Z mueller $ +; $Id: cpu_basics.mac 1285 2022-08-25 06:15:42Z mueller $ ; SPDX-License-Identifier: GPL-3.0-or-later ; Copyright 2015-2022 by Walter F.J. Mueller ; @@ -944,6 +944,50 @@ ta0403: clr 900$ ; reset call counter ; 9999$: iot ; end of test A4.3 ; +; Test A4.4 -- jsr sp and rts sp ++++++++++++++++++++++++++++++++++++++ +; In case of jsr sp and rts sp, the sp register is used both as linkage +; register and implicitly as stack pointer. That interferes and gives +; quite bizarre semantics, certainly never used, but should work +; - jsr sp, will +; - push current SP onto stack +; - set SP to the location of following instruction +; - jump to +; - rts sp will +; - set PC to current SP +; - pop SP of the current stack +; that will set SP to the opcode of instruction being returned to ! +; +ta0404: hcmpeq sp,#stack ; check stack is default + clr 100$ ; clear 'args' after jsr + clr 100$+2 +; + jsr sp,300$ ; will push SP to current stack +100$: .word 0 ; 'args', will be overwritten + .word 0 ; +; +200$: clr r1 ; return instruction, also loaded SP + hcmpeq sp,200$ ; check loaded SP + mov #stack-2,sp ; restore stack to where jsr pushed it +; +; w11 saves original sp, 11/70,SimH,e11 save sp after it was decremented +; This is considered a minor deviation (jsr sp never used!) +; + mov #stack,r1 + tstb systyp ; check environment + bge 210$ ; >=0 is on w11 + sub #2,r1 ; if not, subtract 2 (now sp-2) +210$: hcmpeq (sp)+,r1 ; check jsr stored stack pointer + hcmpeq 100$,#123 ; check writes via SP in routine + hcmpeq 100$+2,#345 ; check writes via SP in routine + jmp 9999$ +; +; this routine must never 'push' that will overwrite the calling jsr !! +300$: mov #123,(sp)+ + mov #345,(sp)+ + rts sp +; +9999$: iot ; end of test A4.4 +; ; Test A5 -- mark ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ; This sub-section verifies ; x xxx xxx xxx xxx xxx NZVC Instruction / Remark @@ -3094,7 +3138,7 @@ tf0301: mov #v..iot+2,v..iot ; block iot handler ; END OF ALL TESTS - loop closure ============================================ ; mov tstno,r0 ; hack, for easy monitoring ... - hcmpeq tstno,#52. ; all tests done ? + hcmpeq tstno,#53. ; all tests done ? ; jmp loop ;