7

I'm trying to understand the MTPI (and its MFPI counterpart) instruction on the PDP/11.

As far as I understood, it:

  • it retrieves a value from the "current" memory space with the current mapping (e.g. kernel mapping). Like: (R0): retrieve from the current memory space-address which is in the R0 register.

  • it then determines the physical memory location of the "previous"-stackpointer in the "previous" memory space (e.g. the user mapping) and then stores it then on that stack

I wrote the following to verify this. If all goes well, it should end with the 'Z' (zero) flag set. In simh/pdp11 this is not what happens, the Z-flag is not set. So clearly my understanding of it is wrong. Any hints?

; initialize kernel- and user stackpointers
; kernel
    MOV #1000,R6
; user
    MOV #0177717,R0
    MOV #1000,(R0)

; make sure current run-mode is kernel and previous is user
    MOV #0177776,R0
    MOV #030000,(R0)
    NOP

; user: 020000-040000 will be mapped to physical address 060000
    MOV #0177642,R0
; 060000 / 0100 (0100 => 64 decimal)
    MOV #0600,(R0)
    NOP

; user: make sure write- and read-access is possible
    MOV #0177602,R0
    MOV #077406,(R0)

; kernel: flat mapping
    MOV #0172340,R0
    MOV #0000,(R0)
    NOP

; kernel: make sure write- and read-access is possible
    MOV #0172300,R0
    MOV #077406,(R0)

; enable MMU
    MOV #0177572,R0
    BIS #1,(R0)

; write word on stack that will be checked for to be at the
; remapped address
    MOV #01234,-(SP)
; this address in kernel space should be 060000 in userspace
    MOV #020000,R0
    MTPI    (R0)
    NOP

; check for 01234 at 060000 in kernel space
    MOV #060000,R0
    CMP #01234,(R0)
    NOP

    HALT
2
  • I'm not so sure about loading the user SP. See this question. Maybe it works in simh. But your code does not need a user SP. Apr 9 at 22:12
  • @another-dave: indeed, that was an(-other) misunderstanding of MTPI and friends by me. Apr 10 at 11:49

1 Answer 1

8

it then determines the physical memory location of the "previous"-stackpointer in the "previous" memory space (e.g. the user mapping) and then stores it then on that stack

I believe this description to be backwards. MTPI pops a word off the current stack, and stores it in the destination address as calculated in the 'previous mode' address space. That seems to be the expectation of your code, despite your description.

; this address in kernel space should be 060000 in userspace
    MOV #020000,R0
    MTPI    (R0)

So this:

    MOV #01234,-(SP)
    MOV #020000,R0
    MTPI    (R0)]

has the result of moving 1234 into address 20000 in the previous I-space.

And if your mapping is correct, 1234 should show up where you expect it in current I-space.


Here's what the 11/70 handbook has to say about MTPI:

The address of the destination operand is determined in the current address space. MTPI then pops a word off the current stack and stores that word in the destination address in the previous mode's I space (bits 13, 12 of PS).

OK, so we determine that the destination address is 20000, pop 1234 off the current stack, and store that 1234 at 20000 in the previous-mode I-space.

That seems to accord with what I understand the intent of your code to be.


tl;dr: your MTPI use is fine, your memory management isn't.

Here's my guess; it is based on my assumption that if you don't explicitly initialize a PAR/PDR pair, it's unpredictable.

For user space, you point page 1 to a 32KW page at physical 00060000. No other page is defined. Looks ok to me.

For kernel space, you point page 0 to a 32KW page at physical 00000000 (which is probably where your code is running out of?). No other page is defined.

You are expecting 1234 to show up at kernel virtual 060000. This is page 3. However, you have not set up page 3, so it seems unpredictable where that result will land. You need to initialize KISAR3 and KISDR3 for a virtual=physical mapping.

A little more guesswork: if (as is possible) the page description registers are initialized to zero on CPU reset, then attempts to use a page will cause an MMU abort. But you haven't enabled MMU traps via MMR0 bit 9, so as far as I can tell from the 11/70 handbook, the memory access will just quietly fail to happen.


Virtual addresses to pages crib sheet:

000000  0    020000  1    040000  2    060000  3
100000  4    120000  5    140000  6    160000  7
3
  • Thanks for the elaborate reply. Indeed with setting up the page-3 mappings, it works as expected under simh. Background: I'm writing a PDP-11/70 emulator (because why not) and mine did initialize the page-mappings to something sane at startup which simh (and others) doesn't do. I'm using other emulators to verify that my emulation is correct - xxdp+.rk doesn't touch every aspect I found. Apr 10 at 11:01
  • 1
    Here's an interesting case to consider: MTPI SP. Which stack pointer is written to? I'd hope it would be the appropriate SP for the previous mode, but the handbook does not specify. Apr 10 at 12:29
  • 1
    I checked and: p11-2.10i, simh-3.8.1 and pdp11-js-3.1 use previous mode Apr 10 at 12:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.