0

As I understand it, the PDP-11 has a 16-bit address space with a fully loaded system having 28k words (56k bytes) after reserving some of the address space for I/O, which means if instructions must be at even addresses, 15 bits are necessary to specify a code address in the general case.

It also seems to have a fixed 16-bit instruction format, which means there is no way to pack both an opcode and a general code address into one instruction.

For short branches, this is no problem; according to https://pages.cpsc.ucalgary.ca/~dsb/PDP11/InsSet.html these simply supply a signed 8-bit offset to be added to the current program counter.

But JMP and JSR presumably in general need to jump to anywhere in the program. How do they specify target address? The above document says

"Bits 5-0 designate the destination field that consists of addressing mode and general register fields. This specifies the starting address of the subroutine."

Does that mean you have to load the target address into a register in a separate instruction first?

  • 5
    The question is not well-researched. A simple googling of "PDP-11 addressing modes" brings out the answer. – Leo B. Feb 23 at 7:56
  • 1
    One note: the 4KW page reserved for I/O applies to physical space only, not to virtual space on an -11 with memory management. Naturally, the kernel would surely need I/O space mapped, but task-based code may or may not; in the latter case the page could be used for addressing memory. – another-dave Feb 23 at 12:34
  • 5
    The key feature the question has missed is that the PDP-11 has variable length instructions. Some very early computers, and quite a few RISC processors have fixed length instructions, but the PDP-11 is a fairly sophisticated CISC architecture, from the period when variable-length instructions were easy and commonplace. – John Dallman Feb 23 at 14:51
  • 1
    It just occurred to me to mention that "loading the target address into the register first" (per the OP) would have exactly the same problem: it can't be done in a 1-word instruction. MOV #FOO,R1 assembles the value of FOO into the second word. – another-dave Feb 23 at 20:51
5

But JMP and JSR presumably in general need to jump to anywhere in the program. How do they specify target address? The above document says

Like with any other instruction addressing?

"Bits 5-0 designate the destination field that consists of addressing mode and general register fields. This specifies the starting address of the subroutine."

Keyword here is 'addressing mode'.

Does that mean you have to load the target address into a register in a separate instruction first?

That's one way. Or any other will do.

Addresses in PDP-11 instructions are encoded as a 3 bit mode field (5..3) and 3 bit register field (2..0), the later specifying any of the registers to be used.

Mode itself consists of one of 4 addressing modes (5..4), as there are:

  • 00 - Register
  • 01 - Autoincrement
  • 10 - Autodecrement
  • 11 - Index

The remaining one bit (3) indicating indirect (deferred in PDP-11ish).

In case of index, it's a two word instruction with the index to be added to the register as second word. Thus any 16 bit offset can be specified relative to any register - resulting in an arbitrary 16 bit address. For code relative addressing the PC (R7), makes a great base, isn't it? The result should be an even address. It might also be noteworthy, that register direct is not possible, as a register can not contain code :) (*1)

The usage of R7/PC as register also results in additional modes:

  • Mode 2 (Autoincrement) becomes immediate (Not useful for JMP/JSR) - ADC #label
  • Mode 3 (Autoincrement Indirect) becomes Absolute - JMP @#label
  • Mode 6 (Indexed) is the already mentioned Relative - JMP label

It must be noted, that these are not really additionally implemented modes, but rather side effects of using PC. They are merely nice fitting names for inflexible humans. That's why the assembler supports them with a dedicated syntax (*2).

Examples:

  • Mode 0 - illegal
  • Mode 1, Register Indirect, jumps to wherever the register points - JMP @(R1)
  • Mode 3, Autoincrement Indirect, jumps to address contained in a word addressed by the register and increments the register by two - JMP @(R1)+ (*3)
  • Mode 6, Indexed, jumps to the result of adding a 16 bit word to the register specified - JMP 20(PC)
  • Mode 7, Index Indirect, jumps to address contained in a word addressed by adding a 16 bit word to the register specified - JMP @20(PC)

All of this is usually described in Section 3, Adressing Modes of the processor Handbook, or section 5 of the MACRO-11 manual. I guess the site you're citing doesn't explain it in detail as it's so fundamental that they (like man other) assume that one checking up encoding knows about.


*1 - As Wilson mentions, some PDP-11 variants may allow, under special circumstances, code to reside in a register - still, even these CPUs issue an 'Illegal Instruction' trap when a 'normal' program tries to execute a JMP or JSR in with mode 0 (See p.98 of the PDP-11/20 manual).

*2 - Another great example for the difference between Assembler and Machine-Code. Assembler operates on an abstract level.

*3 - Very handy to build some kind of threaded code structure - did anyone say FORTH?

  • Some PDP-11 models actually can execute code from registers. The /20 could do this and it was a handy feature for testing/debugging a CPU that has no access to core memory. So then is the register direct a legal way to address the target of a jmp? – Wilson Feb 25 at 7:11
  • @Wilson If you want to write non-portable code, sure. But then, why does the PDP-11/20 handbook (p98, top paragraph)as well tell that mode 0 for JSR/JMP issue an illegal instrucion trap? – Raffzahn Feb 25 at 9:53
  • 1
    That answers my question. My guess is if you want to execute code from a register, then you need to jump to the address of that register (which would be 177770 or something like that) – Wilson Feb 25 at 10:00
  • @Wilson Oh, yes, haven't thought of that - my memory is todaymore like a Sibirian country road: not made for fast driving. Yes. That makes sense. After all, one register can only hold one word, thus two word instructions would be equally impossible as program continuation. But the memory where registers are store is ofc not only continuous, but also always present, even if core is disconnected. – Raffzahn Feb 25 at 10:16
  • 1
    @wilson but that would still not mean "register-direct addressing for code" - The register file is considered "memory" by the CPU that just happens to coincide with registers. – tofro Feb 25 at 10:34
4

It also seems to have a fixed 16-bit instruction format, which means there is no way to pack both an opcode and a general code address into one instruction.

You can perhaps debate about which part is actually the 'instruction', but in reality, a PDP-11 instruction is one, two, or three words. The first word has the opcode and (depending on opcode) one or two operand specifiers. Depending on the 'mode' and the particular register in the operand specifier, another word may be required in the instruction stream. If the register is R7, the program counter, it's particularly interesting. I won't bother to repeat the info that is already in other answers here and which can in any case be looked up.

In this respect, JMP and JSR are no different from most other instructions that must specify a memory address. To my mind, the combination of mode/register specifier, and the generalization from having the program counter be just another general register, are a large part of the genius of the PDP-11 ISA.

From the programmer's viewpoint, to jump to a label FOO, one just writes JMP FOO. That's a PC-relative jump (i.e., is conveniently position-independent within a code module). The operand specifier will be mode 6, register 7. The second word of the instruction will be filled in by the assembler with the displacement (address relative to instruction word) of FOO. There are use-cases where you'd prefer an absolute jump; JMP @#FOO results in mode 3, register 7, and the second word contains the absolute address of FOO.

For short branches, this is no problem; (...) these simply supply a signed 8-bit offset to be added to the current program counter.

Branch instructions are in fact one of the exceptions to the mode-and-register arrangement. Instead of the usual operand specifier, they have a simple 'offset from program counter'. This conveniently and efficiently caters for the common case of branching within subroutines (with the occasional frustration when adding "one more instruction" turns out to be the last straw that breaks the branch-camel's back).

2

Often, the JMP and JSR instructions used the Program counter addressing mode: as a result, the next word after the instruction specified an absolute address or a PC-relative offset.

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.