Arquitectura PDP-11
# Arquitectura PDP-11

La arquitectura PDP-11 es una arquitectura de conjunto de instrucciones (ISA) CISC desarrollada por Digital Equipment Corporation (DEC). Está implementada en las unidades centrales de procesamiento (CPU) y los microprocesadores utilizados en los miniordenadores PDP-11. Durante la década de 1970 fue ampliamente utilizada, pero finalmente fue eclipsada en la década de 1980 por la aún más potente arquitectura VAX-11.

## Memoria

### Formatos de datos

Las palabras de 16 bits se almacenan en formato little-endian (los bytes menos significativos aparecen primero). Los datos con 32 bits—soportados como extensiones de la arquitectura básica, p. ej., datos de coma flotante en el conjunto de instrucciones de la FPU, palabra doble o double word en el conjunto de instrucciones extendidas o los datos long en el conjunto de instrucciones comerciales—se almacenan en más de un formato, incluyendo un raro middle-endian al que a veces se nombra como "PDP-endian".

### Gestión de memoria

Las direcciones de 16 bits del PDP-11 pueden direccionar de forma directa hasta un máximo de 64 KiB (65.536 bytes). Para cuando el PDP-11 cedió su puesto al VAX, la notación hexadecimal y los bytes de 8 bits como unidad de medida de almacenamiento se estaban convirtiendo en estándar en la industria; sin embargo, en la arquitectura PDP-11 los valores numéricos utilizan siempre la notación octal y la cantidad de memoria instalada en un PDP-11 siempre se expresa como un número de palabras de 16 bits. Por lo tanto, el espacio de direcciones lógicas básico es de 32.768 palabras direccionables como bytes. Las 4.096 palabras del espacio de direccionamiento superior (direcciones en octal $160000_8$ a $177777_8$ en ausencia de la gestión de memoria) no se utilizan porque los registros de entrada/salida en el bus se corresponden con direcciones en ese rango. Por lo tanto, utilizando la nomenclatura habitual, originalmente un PDP-11 en su configuración máxima disponía de 28.672 palabras de 16 bits.

El procesador reserva algunas direcciones de la memoria baja para almacenar vectores de dos palabras que proporcionan los datos para el contador de programa y la palabra de estado del procesador con los cuales comenzar una rutina de servicio. Cuando un dispositivo de E/S interrumpe un programa, coloca la dirección de su vector en el bus para indicar qué rutina de servicio debe tomar el control. Los vectores inferiores se corresponden con las rutinas de servicio para gestionar varios tipos de trampas. Las trampas o excepciones se generan con algunos errores del programa, como el intento de ejecutar una instrucción no definida, y también cuando el programa ejecuta una instrucción determinada como BPT, EMT, IOT o TRAP para solicitar un servicio del sistema operativo.

### Expansión de memoria

El espacio de direcciones lógicas de 16 bits se convirtió en una limitación que recortaba las posibilidades de desarrollar grandes aplicaciones de software. A lo largo de la vida comercial del PDP-11, se utilizaron las siguientes técnicas para solucionar esta limitación:

* Los últimos procesadores del PDP-11 incluían administración de memoria para soportar el direccionamiento virtual . El espacio de direcciones físicas se amplió de 16 a 18 o 22 bits, lo que permite direccionar hasta 256 KiB o 4 MiB de RAM respectivamente. El espacio de direcciones lógicas (es decir, el espacio de direcciones disponible en cualquier momento sin cambiar la tabla de asignación de memoria) permaneció limitado a 16 bits.
* Algunos modelos, comenzando con el PDP-11/45, se pueden configurar para usar 32K palabras (64 KiB) como el "espacio de instrucciones" para el código de programa y 32K palabras separadas de "espacio de datos". Algunos sistemas operativos, en particular Unix desde la edición V7 y RSX11-M+, están basados en esta característica.
* Algunas técnicas de programación, como la superposición de un bloque de almacenamiento de instrucciones o datos con otro según sea necesario, pueden ocultar los problemas de paginación al programador de aplicaciones. Por ejemplo, el compilador Modula-2 produce código en el que el sistema en tiempo de ejecución intercambia páginas de 8 Kib en la memoria direccionable a medida que los procedimientos individuales reciben el control. (Ver la referencia externa Arquitectura PDP-11#Enlaces externos aquí.)

## Registros de la CPU

La CPU contiene ocho registros de 16 bits de uso general (R0 a R7). El registro R7 es el contador de programa (PC). El registro R6 es el puntero de pila (SP) utilizado para interrupciones de hardware y trampas, aunque adicionalmente cualquier registro puede usarse como puntero de una pila. El registro R5 se utiliza habitualmente para apuntar al entorno de llamada del procedimiento en curso. Para acelerar los cambios de contexto algunos modelos PDP-11 proporcionan conjuntos de registros duales R1-R5. Los modos Kernel, Supervisor (si está presente) y Usuario tienen mapas de memoria separados y también punteros de pila separados (de este modo un programa de usuario no puede causar un mal funcionamiento del sistema almacenando un valor no válido en el registro de puntero de pila).

## Modos de direccionamiento

La mayoría de las instrucciones utilizan seis bits para especificar un operando, tres bits para seleccionar uno de los ocho modos de direccionamiento y otros tres bits para seleccionar uno de los registros de uso general.

La codificación de los seis bits del modo de direccionamiento de operandos es como sigue:

| 5 | | 3 | 2 | | 0 |
| - | - | - | - | - | - |
| Modo | Modo | Modo | Registro | Registro | Registro |

En las siguientes secciones cada elemento incluye un ejemplo de como se escribe el operando en lenguaje ensamblador. Rn designa uno de los 8 registros de uso general, que se aparecerían descritos como R0 a R7.

### Modos de direccionamiento del registro general

Los siguientes ocho modos se pueden aplicar a cualquier registro de uso general. El comportamiento sobre los registros R6 (puntero de pila o SP) y R7 (contador de programa o PC) se detallan de forma separada en las siguientes secciones.

| Código | Nombre | Ejemplo | Descripción |
| - | - | - | - |
| 0n | Registro | Rn | El operando está en Rn |
| 1n | Registro diferido | (Rn) | Rn contiene la dirección del operando |
| 2n | Autoincremento | (Rn)+ | Rn contiene la dirección del operando, después incrementa Rn |
| 3n | Autoincremento diferido | @(Rn)+ | Rn contiene la dirección de la dirección del operando, después incrementa Rn en 2 |
| 4n | Autodecremento | -(Rn) | Disminuye Rn, después utiliza el resultado como la dirección del operando |
| 5n | Autodecremento diferido | @-(Rn) | Disminuye Rn en 2, después utiliza el resultado como la dirección de la dirección del operando |
| 6n | Índice | X(Rn) | Rn+X es la dirección del operando |
| 7n | Índice diferido | @X(Rn) | Rn+X es la dirección de la dirección del operando |

En los modos de índice e índice diferido, X es un valor de 16 bits que se toma de una segunda palabra de la instrucción. En las instrucciones de dos operandos, ambos operandos pueden utilizar estos modos y en el caso de utilizarlo ambos estas instrucciones tienen tres palabras.

Las operaciones de autoincremento y autodecremento en un registro suman y restan de 1 en 1 en instrucciones con operandos de tipo byte y de 2 en 2 en instrucciones que trabajan con palabras. En los modos de autoincremento y autodecremento diferido las operaciones son siempre de 2 en 2 ya que la cantidad a la que se dirige el registro es un puntero de direccionamiento (palabra de 16 bits).

### Modos de direccionamiento del contador de programa

Cuando se especifica R7 como operando (el contador de programa), cuatro de los modos de direccionamiento son útiles de forma obvia:

| Código | Nombre | Ejemplo | Descripción |
| - | - | - | - |
| 27 | Inmediato | #n | El operando es la siguiente palabra de la instrucción. |
| 37 | Absoluto | @#a | La dirección del operando es la siguiente palabra de la instrucción. |
| 67 | Relativo | a | La dirección del operando es la siguiente palabra de la instrucción sumada al PC |
| 77 | Diferido relativo | @a | La dirección de la dirección del operando es la siguiente palabra de la instrucción sumada al PC |

El uso habitual del modo absoluto, cuya sintaxis combina los modos inmediato y diferido, es especificar direcciones de registros de entrada/salida, puesto que en este caso los registros de cada dispositivo tienen direcciones de memoria específicas. El modo relativo tiene una sintaxis más simple y es más típico para referirse a variables de programa y destinos de salto. Un programa que utilice para las referencias internas exclusivamente el modo relativo (y también el diferido relativo) es independiente de la posición: no asume una ubicación específica, con lo que se puede cargar en una ubicación de memoria arbitraria, o incluso moverlo con posterioridad, sin necesidad de ajustar las direcciones para reflejar su ubicación (reubicación). Al calcularse dichas direcciones en relación con la ubicación actual, el procesador realizará la reubicación sobre la marcha.

Los modos inmediato y absoluto se corresponden respectivamente con el modo de autoincremento y de autoincremento diferido aplicados al contador de programa (PC). Cuando la palabra auxiliar está "en la instrucción", como indica la tabla anterior en ambos casos, el PC para la siguiente instrucción se incrementa automáticamente más allá de la palabra auxiliar. Como el PC siempre apunta a palabras, la operación de autoincremento siempre es de 2 en 2.

### Modos de direccionamiento de la pila

Al registro R6 también se le denomina SP (Stack Pointer o puntero de pila) y se utiliza como el apuntador de una pila de hardware para trampas e interrupciones. Una convención impuesta por el conjunto de modos de direccionamiento que proporciona el PDP-11 establece que una pila crece hacia abajo, hacia direcciones inferiores, a medida que los elementos se insertan en ella. Cuando se aplica un modo a SP o a cualquier registro que el programador elija utilizar como una pila de software, los modos de direccionamiento tienen los siguientes efectos:

| Código | Nombre | Ejemplo | Descripción |
| - | - | - | - |
| 16 | Diferido | (SP) | El operando está en la parte superior de la pila. |
| 26 | Autoincremento | (SP)+ | El operando está en la parte superior de la pila, después eliminar el valor. |
| 36 | Autoincremento diferido | @(SP)+ | Un puntero al operando está en la parte superior de la pila, después eliminar el puntero. |
| 46 | Autodecremento | -(SP) | Poner un valor en la pila |
| 66 | Indexado | X(SP) | Este modo designa cualquier elemento de la pila por su distancia positiva desde la parte superior. |
| 76 | Diferido indexado | @X(SP) | Este modo designa un valor que se encuentra en la dirección apuntada por un puntero en la ubicación especificada en la pila. |

Las pilas de software pueden contener bytes pero la pila SP siempre se considera una pila de palabras de 16 bits. Por lo tanto las operaciones de autoincremento y autodecremento sobre SP son siempre de 2 en 2.

## Conjunto de instrucciones

El PDP-11 funciona tanto con bytes (8 bits) como con palabras (16 bits). Los bytes se especifican mediante un número de registro, que en este caso se identifica con el byte de orden inferior del registro, o mediante una ubicación de memoria que puede ser par o impar. Las palabras se especifican mediante un número de registro o mediante la ubicación de memoria del byte de orden inferior, que debe ser siempre un número par. En la mayoría de las instrucciones que utilizan operandos, el bit 15 con valor a 1 especifica el direccionamiento de bytes, o con valor a 0 especifica el direccionamiento de palabra. En las listas de instrucciones de las dos secciones siguientes, en el lenguaje ensamblador se añade la letra B al símbolo de la instrucción para especificar que se trata de una operación con bytes; por ejemplo, MOV se convierte en MOVB.

Algunas instrucciones, como por ejemplo MARK y SOB, no se implementaron en todos los modelos de PDP-11.

### Instrucciones de operando doble

Los cuatro bits superiores especifican la operación a realizar (con el bit 15 habitualmente seleccionando el direccionamiento de palabra o byte). Dos grupos de seis bits especifican el modo de direccionamiento del operando de origen y el modo de direccionamiento del operando de destino de acuerdo a lo definido anteriormente.

| 15 | | | 12 | 11 | | 9 | 8 | | 6 | 5 | | 3 | 2 | | 0 |
| - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - |
| Código de operación | Código de operación | Código de operación | Código de operación | Origen | Origen | Origen | Registro | Registro | Registro | Destino | Destino | Destino | Registro | Registro | Registro |
| Código de operación | Mnemotécnico | Operación |
| 01 | MOV | Mover: Dest ← Src Nota: Mover un byte a un registro se extiende el bit de signo a los bits 8-15 |
| 11 | MOVB | Mover: Dest ← Src Nota: Mover un byte a un registro se extiende el bit de signo a los bits 8-15 |
| 02 | CMP | Comparar: Set-flags(Src − Dest) |
| 12 | CMPB | Comparar: Set-flags(Src − Dest) |
| 03 | UN POCO | Prueba de bits: Set-flags(Src ∧ Dest) |
| 13 | BITB | Prueba de bits: Set-flags(Src ∧ Dest) |
| 04 | BIC | Borrar bi: Dest ← Dest ∧ Ones-complement(Src) |
| 14 | BICB | Borrar bi: Dest ← Dest ∧ Ones-complement(Src) |
| 05 | BIS | Asignar bit: Dest ← Dest ∨ Src |
| 15 | BISB | Asignar bit: Dest ← Dest ∨ Src |
| 06 | ADD | Sumar: Dest ← Dest + Src |
| 16 | SUB | Restar: Dest ← Dest − Src |

Las instrucciones ADD y SUB utilizan direccionamiento de palabras y no tienen variantes orientadas a operar con bytes.

Algunas instrucciones con dos operandos utilizan un operando de modo de direccionamiento y un operando adicional de registro:

| 15 | | | | | | 9 | 8 | | 6 | 5 | | 3 | 2 | | 0 |
| - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - |
| Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Registro | Registro | Registro | Orig/Dest | Orig/Dest | Orig/Dest | Registro | Registro | Registro |

Cuando se utiliza un par de registros (escrito a continuación como "(Reg, Reg+1)", el primer registro contiene la parte de orden inferior del operando y debe ser un registro de número par. El siguiente registro numerado más alto contiene la parte de orden superior del operando (o el resto). Una excepción es la instrucción de multiplicar: el registro puede ser impar pero, si lo es, los 16 bits superiores del resultado no se almacenan.

| Código de operación | Mnemotécnico | Operación |
| - | - | - |
| 070 | MUL | Multiplicar: (Reg, Reg+1) ← Reg × Src |
| 071 | DIV | Dividir: Compute (Reg, Reg+1) ÷ Src; Reg ← cociente; Reg+1 ← resto |
| 072 | ASH | Desplazamiento aritmético: if Src<5:0> < 0 then Reg ← Shift-right(Reg, -Src<5:0>) else Reg ← Shift-left(Reg, Src<5:0>) |
| 073 | ASHC | Desplazamiento aritmético combinado: if Src<5:0> < 0 then (Reg, Reg+1) ← Shift-right((Reg, Reg+1), -Src<5:0>) else (Reg, Reg+1) ← Shift-left((Reg, Reg+1), Src<5:0>) |
| 074 | XOR | Operación O Exclusiva: Dest ← Dest ⊻ Reg |

### Instrucciones de un solo operando

Los diez bits superiores especifican la operación a realizar, con el bit 15 seleccionando en general el direccionamiento de bytes frente a palabras. El grupo restante de seis bits especifica el operando según los modos definidos anteriormente.

| 15 | | | | | | | | | 6 | 5 | | 3 | 2 | | 0 |
| - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - |
| Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Orig/Dest | Orig/Dest | Orig/Dest | Registro | Registro | Registro |
| Código de operación | Mnemotécnico | Operación |
| 0001 | JMP | Saltar: PC ← Src |
| 0003 | SWAB | Intercambiar bytes de palabra: Dest ← Swap-bytes(Dest) |
| 0050 | CLR | Borrar: Dest ← 0 |
| 1050 | CLRB | Borrar: Dest ← 0 |
| 0051 | COM | Complemento a uno: Dest ← Ones-complement(Dest) |
| 1051 | COMB | Complemento a uno: Dest ← Ones-complement(Dest) |
| 0052 | INC | Incremento: Dest ← Dest + 1 |
| 1052 | INCB | Incremento: Dest ← Dest + 1 |
| 0053 | DEC | Decremento: Dest ← Dest − 1 |
| 1053 | DECB | Decremento: Dest ← Dest − 1 |
| 0054 | NEG | Negar (complemento a dos): Dest ← Twos-complement(Dest) |
| 1054 | NEGB | Negar (complemento a dos): Dest ← Twos-complement(Dest) |
| 0055 | ADC | Agregar acarreo: Dest ← Dest + C flag |
| 1055 | ADCB | Agregar acarreo: Dest ← Dest + C flag |
| 0056 | SBC | Restar acarreo: Dest ← Dest - C flag |
| 1056 | SBCB | Restar acarreo: Dest ← Dest - C flag |
| 0057 | TST | Prueba: Set-flags(Src) |
| 1057 | TSTB | Prueba: Set-flags(Src) |
| 0060 | ROR | Rotar a la derecha: Dest ← Rotate-right(Dest, 1) |
| 1060 | RORB | Rotar a la derecha: Dest ← Rotate-right(Dest, 1) |
| 0061 | ROL | Rotar a la izquierda: Dest ← Rotate-left(Dest, 1) |
| 1061 | ROLB | Rotar a la izquierda: Dest ← Rotate-left(Dest, 1) |
| 0062 | ASR | Desplazamiento aritmético a la derecha: Dest ← Shift-right(Dest, 1) |
| 1062 | ASRB | Desplazamiento aritmético a la derecha: Dest ← Shift-right(Dest, 1) |
| 0063 | ASL | Desplazamiento aritmético a la izquierda: Dest ← Shift-left(Dest, 1) |
| 1063 | ASLB | Desplazamiento aritmético a la izquierda: Dest ← Shift-left(Dest, 1) |
| 1064 | MTPS | Mover a PSW: PSW ← Src |
| 0065 | MFPI | Mover desde el espacio I de instrucciones anterior: −(SP) ← Src |
| 1065 | MFPD | Mover desde el espacio D de datos anterior: −(SP) ← Src |
| 0066 | MTPI | Mover al espacio I de instrucciones anterior: Dest ← (SP)+ |
| 1066 | MTPD | Mover al espacio D de datos anterior: Dest ← (SP)+ |
| 0067 | SXT | Extensión de signo: if N flag ≠ 0 then Dest ← -1 else Dest ← 0 |
| 1067 | MFPS | Mover desde PSW: Dest ← PSW |

### Instrucciones de bifurcación

En la mayoría de las instrucciones de bifurcación, la decisión sobre la aplicación de la bifurcación se basa en el estado de los códigos de condición. Una instrucción de bifurcación suele estar precedida por una instrucción CMP (comparar) o BIT (prueba de bits) de dos operandos o una instrucción TST (prueba) de un operando. Las instrucciones aritméticas y lógicas también modifican los códigos de condición. A diferencia de los procesadores Intel en la arquitectura x86, las instrucciones MOV también los modifican, por lo que una instrucción de bifurcación podría usarse para bifurcar dependiendo de si el valor movido era cero o negativo.

El byte de orden superior de la instrucción especifica la operación. Los bits del 9 al 15 son el código de operación y el bit 8 designa como aplicar el código de condición que da como resultado la ejecución o no de la bifurcación. El byte de orden inferior es un desplazamiento con signo de palabras relativo a la ubicación actual del contador del programa. Esto permite bifurcaciones hacia adelante y hacia atrás en el código.

| 15 | | | | | | 9 | 8 | 7 | | | | | | | 0 |
| - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - |
| Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | C | Desplazamiento | Desplazamiento | Desplazamiento | Desplazamiento | Desplazamiento | Desplazamiento | Desplazamiento | Desplazamiento |
| Código de operación | C | Mnemotécnico | Condición u operación |
| 000 | 1 | BR | Bifurcar siempre PC ← PC + 2 × Sign-extend(Offset) |
| 001 | 0 | BNE | Bifurcar si no es igual Z = 0 |
| 001 | 1 | BEQ | Bifurcar si es igual Z = 1 |
| 002 | 0 | BGE | Bifurcar si es mayor o igual que (N ⊻ V) = 0 |
| 002 | 1 | BLT | Bifurcar si es menor que (N ⊻ V) = 1 |
| 003 | 0 | BGT | Bifurcar si es mayor que (Z ∨ (N ⊻ V)) = 0 |
| 003 | 1 | BLE | Bifurcar si es menor o igual (Z ∨ (N ⊻ V)) = 1 |
| 100 | 0 | BPL | Bifurcar si signo positivoN = 0 |
| 100 | 1 | IMC | Bifurcar si signo negativoN = 1 |
| 101 | 0 | BHI | Bifurcar si es más alto (C ∨ Z) = 0 |
| 101 | 1 | BLOS | Bifurcar si es menor o igual (C ∨ Z) = 1 |
| 102 | 0 | BVC | Bifurcar si desbordamiento a cero V = 0 |
| 102 | 1 | BVS | Bifurcación si se establece el desbordamiento a 1 V = 1 |
| 103 | 0 | BCC o BHIS | Bifurcar si el acarreo está a cero, o Bifurcar si es mayor o igual C = 0 |
| 103 | 1 | BCS o BLO | Bifurcar si el acarreo está a uno, o Bifurcar si es menor C = 1 |

El rango limitado de desplazamiento de las instrucciones de bifurcación significaba que, a medida que el código crecía, las direcciones de destino de algunas ramas se volvían inalcanzables. En estos casos el programador cambiaba la instrucción BR de una palabra a la instrucción JMP de dos palabras del siguiente grupo. Como JMP no permite aplicar condiciones, una instrucción como BEQ se cambiaría por BNE para bifurcar rodeando la siguiente instrucción JMP que saltaría al destino deseado.

SOB (Subtract One and Branch - restar uno y saltar) es otra instrucción de bifucación condicional. El registro especificado se reduce en 1, y si el resultado no es cero, se toma una bifurcación inversa basada en el desplazamiento de 6 bits de la palabra .

| 15 | | | | | | 9 | 8 | | 6 | 5 | | | | | 0 |
| - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - |
| Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Reg | Reg | Reg | Desplazamiento | Desplazamiento | Desplazamiento | Desplazamiento | Desplazamiento | Desplazamiento |
| Opcode | Mnemotécnico | Operación |
| 077 | SOB | Restar Uno y Bifurcar: Reg ← Reg - 1; si Reg ≠ 0 entonces PC ← PC - 2 × Offset |

### Instrucciones de subrutina

La instrucción JSR puede guardar cualquier registro en la pila. Los programas que no necesitaban esta característica especificaban PC como el registro (JSR PC, dirección) y la regresaban de la rutina usando RTS PC. Si se llama a una rutina con, por ejemplo, "JSR R4, dirección", entonces el valor antiguo de R4 se almacenaría en la parte superior de la pila y la dirección de retorno (justo después de la instrucción JSR) se asignaría a R4. Esto permite que la rutina llamada tenga acceso a valores dentro del código llamante especificando (R4)+, o a punteros utilizados dentro del código especificando @(R4)+. El mecanismo de autoincremento permitirá ir accediendo a estos datos, y fijará el punto en el que se reanude la ejecución del código que efectúa la llamada. La rutina llamada tendrá que especificar RTS R4 para regresar al llamante.

| 15 | | | | | | 9 | 8 | | 6 | 5 | | 3 | 2 | | 0 |
| - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - |
| Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Reg | Reg | Reg | Orig | Orig | Orig | Registro | Registro | Registro |
| Código de operación | Mnemotécnico | Operación |
| 004 | JSR | Saltar a la subrutina: -(SP) ← Reg; Reg ← PC; PC ← Src |
| 15 | | | | | | | | | | | | 3 | 2 | | 0 |
| Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Reg | Reg | Reg |
| Código de operación | Mnemotécnico | Operación |
| 00020 | RTS | Retorno de la subrutina: PC ← Reg; Reg ← (SP)+ |

### Instrucciones de trampa (trap)

| 15 | | | | | | 9 | 8 | 7 | | | | | | | 0 |
| - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - |
| Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | S | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación |
| Código de operación | S | Mnemotécnico | Operación |
| 104 | 0 | EMT | Trampa del emulador: -(SP) ← PS; -(SP) ← PC; PC ← (30); PS ← (32) |
| 104 | 1 | TRAP | Trampa general: -(SP) ← PS; -(SP) ← PC; PC ← (34); PS ← (36) |
| 15 | 0 |
| Código de operación ||||||||||||||||
| Código de operación | Mnemotécnico | Operación |
| 000002 | RTI | Retorno de la interrupción: PC ← (SP)+; PS ← (SP)+ |
| 000003 | BPT | Trampa de punto de interrupción: -(SP) ← PS; -(SP) ← PC; PC ← (14); PS ← (16) |
| 000004 | IOT | Trampa de E/S: -(SP) ← PS; -(SP) ← PC; PC ← (20); PS ← (22) |
| 000006 | RTT | Retorno de la trampa: PC ← (SP)+; PS ← (SP)+ |

**Asignaciones de direcciones de vectores de excepción y trampa**

| Vector | Condición |
| - | - |
| 000000 | (Reservado) |
| 000004 | Instrucción ilegal, error del bus, límite de la pila |
| 000010 | Instrucción reservada |
| 000014 | Instrucción BPT, traza de trampa |
| 000020 | Instrucción IOT |
| 000030 | Instrucción EMT |
| 000034 | Instrucción TRAP |
| 000244 | Excepción de coma flotante |
| 000250 | Fallo de administración de la memoria |

### Instrucciones misceláneas

| 15 | 0 |
| - | - |
| Código de operación ||||||||||||||||
| Opcode | Mnemotécnico | Operación |
| 000000 | HALT | Detener el procesador: Detiene la ejecución antes de la próxima instrucción |
| 000001 | WAIT | Espera de interrupción: Detiene la ejecución antes de la próxima instrucción; reanuda la ejecución en el siguiente gestor de la instrucción |
| 000005 | RESET | Reinicialización UNIBUS: Activa la línea INIT en UNIBUS durante 10 ms; todos los demás dispositivos se reinicializan al estado de recién encendido |

### Operaciones de código de condición

| 15 | | | | | | | | | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| - | - | - | - | - | - | - | - | - | - | - | - | - | - | - | - |
| Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | Código de operación | 1 | S | N | Z | V | C |
| Código de operación | S | Mnemotécnico | Operación |
| 0002 | 0 | CCC | Borrar códigos de condición: Borra los códigos de acuerdo a los bits N, Z, V, C |
| 0002 | 1 | SCC | Asigna los códigos de condición: Asigna los códigos de acuerdo a los bits N, Z, V, C |

Los cuatro códigos de condición disponibles en la palabra de estado del procesador (PSW) son:

* N indica un valor negativo
* Z indica una condición (igual a) cero
* V indica una condición de desbordamiento, y
* C indica una condición de acarreo.

Las instrucciones de este grupo eran lo que Digital llamaba "microprogramadas": cada bit en la palabra de instrucción hacía referencia a un único código de condición. El ensamblador no definía la sintaxis para especificar cada combinación, pero los símbolos SCC y CCC ensamblaban una instrucción que asignaba o borraba respectivamente cualquiera de los cuatro códigos de condición.

Las instrucciones de borrar o configurar sin indicación de código de condición (códigos de operación 000240 y 000260 respectivamente) podrían considerarse a efectos prácticos como instrucciones de no operación. De hecho, el mnemónico NOP se ensamblaba como 000240.

### Conjuntos de instrucciones opcionales

**Conjunto de instrucciones extendido (EIS - Extended Instruction Set)**

El conjunto de instrucciones extendido o EIS era opcional para los modelos 35/11/40 y para el 03/11 y formaba parte del conjunto de instrucciones estándar en los procesadores más nuevos.

* MUL, DIV multiplican y dividen un operando entero con un registro.
* ASH, ASHC aritméticas - desplaza un registro o un par de registros. Si el operando es un número positivo realiza el desplazamiento a la izquierda y en los números negativos realiza el desplazamiento a la derecha.

**Conjunto de instrucciones de coma flotante (FIS)**

El conjunto de instrucciones de coma flotante o FIS (Floating Instruction Set) era opcional para los modelos PDP-11/35/40 y 11/03

* FADD, FSUB, FMUL, FDIV sólo para operaciones de precisión simple sobre operandos en la pila direccionados por un registro.

**Procesador de coma flotante (FPP)**

El procesador de coma flotante era opcional para el 11/45 y la mayoría de los modelos posteriores.

* Operaciones de coma flotante completas sobre operandos de precisión simple o doble, seleccionados usando el bit simple/doble en el registro de estado de coma flotante (Floating Point Status Register).
* Formato de datos de coma flotante de precisión simple predecesor del formato IEEE 754: bit de signo, exponente de 8 bits, mantisa de 23 bits con bit oculto 24

**Conjunto de instrucciones comerciales (CIS)**

Las instrucciones del CIS se implementaron mediante microcódigo opcional en el modelo 23/11/24, y mediante un módulo adicional en el 44/11 y en una versión del 74/11. Proporcionaba instrucciones de manejo de cadenas de caracteres y números decimales utilizadas por los lenguajes COBOL y Dibol .

**Acceso a la palabra de estado del procesador (PSW)**

La palabra de estado del procesado o PSW se mapeó en la dirección de memoria 177 776, pero instrucciones disponibles en todos los PDP-11 excepto en los primeros permitían a los programas un acceso más directo al registro de estado.

* SPL (establecer el nivel de prioridad)
* MTPS (mover al Estado del Procesador)
* MFPS (mover desde el Estado del Procesador)

**Acceso a otros espacios de memoria**

En los PDP-11 que disponían de múltiples espacios de memoria para instrucciones y datos, un conjunto de instrucciones Move no ortogonales daban acceso a otros espacios. Por ejemplo, las rutinas del sistema operativo que manejaban las llamadas a un servicio en tiempo de ejecución usarían estas instrucciones para intercambiar información con el proceso que las llamaba.

* MTPD (mover al espacio de datos anterior)
* MTPI (mover al espacio de instrucciones anterior)
* MFPD (mover desde el espacio de datos anterior)
* MFPI (mover desde el espacio de instrucciones anterior)

### Instrucciones inconsistentes

Durante la vida útil del PDP-11, surgieron pequeñas diferencias en la implementación de instrucciones y las combinaciones de los modos de direccionamiento, aunque ninguna implementación se consideró correcta por el fabricante. Las inconsistencias no afectaron el uso ordinario del PDP-11.

### Velocidad

La velocidad del procesador del PDP-11 varía según el modelo, la configuración de la memoria, el código de la operación y los modos de direccionamiento. El tiempo de ejecución de una instrucción tenía hasta tres componentes, recuperación/ejecución de la instrucción en sí y tiempo de acceso para el origen y el destino. Los tiempos de los dos últimos componentes dependían del modo de direccionamiento utilizado. Por ejemplo, en el PDP-11/70 (alrededor de 1975), una instrucción como ADD x(Rm),y(Rn) tenía un tiempo de recuperación/ejecución de 1,35 microsegundos más los tiempos de acceso a origen y destino de 0,6 microsegundos cada uno, sumando un tiempo total de instrucción de 2,55 microsegundos. En el caso de que la memoria direccionada no estuviese en la caché suponía 1,02 microsegundos adicionales. La operación de registro a registro ADD Rm, Rn podía ejecutarse desde la caché en 0,3 microsegundos. El cálculo de los tiempos de ejecución de las operaciones de coma flotante era aún más complejo, ya que había cierto solapamiento de proceso entre la CPU y el procesador de coma flotante, pero en general las operaciones de coma flotante eran significativamente más lentas. Una instrucción de suma decimal de precisión simple podía oscilar entre 2,4 y 5,5 microsegundos más el tiempo para recuperar los operandos.

## Interrupciones

El PDP-11 operaba en un nivel de prioridad entre 0 y 7, designado por tres bits en la palabra de estado del procesador (PSW), y los modelos de gama alta podían operar en varios modos como Kernel (privilegiado), Usuario (aplicación), y a veces Supervisor, según dos de los bits de la PSW.

Para solicitar una interrupción, un dispositivo del bus activaba una de las cuatro líneas de bus comunes, BR4 a BR7, hasta que el procesador respondiera. Los números más altos indicaban una mayor urgencia, quizás porque los datos podrían perderse o porque un sector deseado podría girar hasta quedar fuera del contacto con las cabezas de lectura/escritura, a menos que el procesador respondiera rápidamente. La preparación de la impresora para recibir otro carácter tendría la prioridad más baja (BR4), ya que permanecería lista indefinidamente. Si el procesador estuviese funcionando en el nivel de prioridad 5, entonces las interrupciones de las líneas BR6 y BR7 serían atendidas. Si el procesador estuviera funcionando a prioridad 3 o inferior, concedería cualquier interrupción, pero en caso de estar a 7, no concedería ninguna. Las solicitudes del bus que no se concedían no se perdían sino que se aplazaban. El dispositivo que necesitaba obtener una petición de servicio continuaría activando su línea de solicitud de bus.

Cuando una interrupción excedía el nivel de prioridad del procesador, éste activaba la línea de concesión de solicitud de bus correspondiente, de BG4 a BG7. Las líneas de concesión de bus no eran líneas comunes, sino una conexión en cadena o daisy chain: la entrada de cada puerta era la salida de la puerta anterior en la cadena. Había una puerta en cada dispositivo conectado al bus, y un dispositivo físicamente más cercano al procesador estaba antes en la cadena de conexión. Si un dispositivo había realizado una solicitud, al detectar la concesión de bus en su entrada, podía tener la certeza de que obtenía el control del bus y no transmitía la señal de concesión al siguiente dispositivo en el bus. Si el dispositivo no había realizado una solicitud, propagaba la señal de su entrada de concesión de bus a su salida de concesión de bus, dando al siguiente dispositivo más cercano la oportunidad de responder. Si las ranuras adyacentes a la placa del procesador no tenían dispositivos conectados, o existían ranuras vacías entre dispositivos, las "tarjetas de concesión de continuidad" insertadas en las ranuras vacías permitían propagar físicamente la línea de concesión de bus.

Una vez en posesión del control del bus, el dispositivo desactivaba su solicitud y colocaba en el bus la dirección de memoria de su vector de gestión. El procesador guardaba el contador de programa (PC) y la PSW, ingresaba al modo Kernel y los cargaba con nuevos valores de acuerdo a las dos palabras del vector especificado. Por ejemplo, para un dispositivo en la línea BR6, la nueva PSW en su vector habitualmente especificaría 6 como la nueva prioridad del procesador, por lo que el procesador respondería a las solicitudes más urgentes (BR7) durante la rutina de servicio, pero pospondría las solicitudes de igual o menor prioridad. Con el nuevo valor del contador de programa (PC), el procesador saltaba a la rutina de servicio del dispositivo solicitante de la interrupción. Esa rutina haría funcionar el dispositivo, o al menos eliminaría la condición que causó la interrupción. La rutina terminaba con la instrucción RTI (ReTurn from Interrupt), que restauraba el PC y la PSW a los valores existentes justo antes de que el procesador concediera la interrupción.

Si se realizaba una solicitud de bus por error y ningún dispositivo respondía a la concesión del bus, el procesador agotaba el tiempo de espera y lanzaba una trampa que basada en la hipótesis de que algún hardware estaba defectuoso.

## Lenguaje ensamblador MACRO-11

MACRO-11 es el principal lenguaje ensamblador del PDP-11. Es el sucesor del PAL-11 (Program Assembler Loader), una versión anterior de lenguaje ensamblador para el PDP-11 que no disponía de macros. El lenguaje MACRO-11 era compatible con todos los sistemas operativos para DEC PDP-11. En el caso del sistema operativo Unix para PDP-11 también se disponía de un ensamblador adicional (llamado "as"), estructuralmente similar a MACRO-11, pero con diferente sintaxis y menos funcionalidades.

