Architektur der Nova-Rechner

Die nachfolgenden Informationen wurden dem Handbuch How to use the Nova Computers (Data General Corporation 1970,1971) entnommen und ins Deutsche übersetzt.

Einführung

Vom Typ her sind die Nova-Computer Universalrechner. Ihre Architektur basiert auf dem Von-Neumann-Modell. Sie benutzen eine Wortlänge (Daten- und Adressbus) von 16 Bit. Da das höchste Adressbit als Flag für eine indirekte Adressierung reserviert ist, können maximal 215 = 32 768 Speicherplätze von jeweils 16 Bit adressiert werden (nach heutiger Bezeichnung sind das 64 kB). Der Programmzähler (program counter = PC) hat demzufolge eine Länge von 15 Bit
Alle Maschinen der Baureihe besitzen in der Recheneinheit vier 16-bit-Akkumulatoren (AC0, ..., AC3), von denen zwei als Indexregister verwendet werden können. Die logischen und arithmetischen Operationen arbeiten ausschließlich mit den Akkumulatoren. Jeder von ihnen kann dabei als Ergebnisregister dienen. Gleichzeitig zu einer solchen Operation können als Zusatzfunktionen ein bitweises Schieben des Akkumulatorinhalts und/oder ein vom Resultat abhängiges Überspringen des nächsten Befehls ausgeführt werden. Außerdem gibt es Befehle, um Daten (16-Bit Worte) vom Speicher in einen Akkumulator und zurück zu transportieren, den Inhalt von Speicherzellen zu erhöhen oder zu erniedrigen, Unterroutinen aufzurufen, Sprünge im Programmablauf vorzunehmen und um Daten über eine Schnittstelle (Interface) einzulesen oder auszugeben.
Externe Geräte können über ein I/O-Interface einen Interrupt auslösen. Für die Identifizierung der Interrupt-Quelle gibt es Hardware-Unterstützung durch ein Daisy-Chain-Verfahren. Für den schnellen Datentransfer von oder zu einem Peripheriegerät steht zusätzlich ein direkter Speicher-Zugriff (direct memory access = DMA) zur Verfügung.

Zahlendarstellung

Da Computer in der Regel mit Binärzahlen arbeiten, ist die Dezimaldarstellung von Zahlen etwas unpraktisch. Heute hat sich Darstellung im Hex-Format (Basis 16) allgemein durchgesetzt. In den Nova-Handbüchern wurde damals stattdessen durchgängig das Oktalformat (Basis 8) benutzt, das daher auch nachfolgend verwendet wird.
Bsp.:

  Dez.      Hex      Oktal
  7         7        7
  8         8        10
  10        A        12
  16        10       20
  255       FF       377


Die Befehlsstruktur

Alle Befehle sind genau ein Wort lang (16 Bit). Sie unterteilen sich in vier klar strukturierte funktionsabhängige Gruppen, so dass eine sehr einfache Dekodierung durch die logische Hardware der Zentraleinheit (Central processing unit = CPU) ermöglicht wird:

Adressierungsarten

Alle Befehle, die eine Speicherzelle adressieren (die ersten beiden o.g. Gruppen), können eine der folgenden Methoden benutzen:

Alle Adressierungsarten können zusätzlich für eine indirekte Adressierung verwendet werden. Darüber hinaus kann durch Setzen des Bits 0 einer solchen indirekten, im Speicher abgelegten Adresse (nur die Bits 1..15 bilden eine gültige Adresse) die indirekte Adressierung mehrfach verkettet werden.

Speicher

Es können maximal 32768 Speicherzellen adressiert werden (15 Bit). Jede Speicherzelle enthält 16 Bits (Programm oder Daten). Einige Speicherzellen haben eine besondere Bedeutung:

Grundstruktur der Befehle

Heute ist es üblich, die Bits eines Wortes (oder eines Bytes) von rechts nach links zu nummerieren (Bit 0 hat die niedrigste Wertigkeit, Bit 15 die höchste). In den Nova-Handbüchern ist dies genau anders herum erfolgt: Bit 0 ist das höchstwertige, Bit 15 das niederwertigste Bit. Daher wird diese heute ungewohnte Bezeichnungsweise für die nachfolgenden Beschreibungen übernommen.
Die vier oben genannten Befehlsgruppen werden durch die ersten drei Bits (Bit 0..2) gekennzeichnet:

Sprungbefehle und Speichermodifikation

Sind die drei Bits Null (0 0 0) handelt es sich um einen Sprungbefehl oder um einen Befehl zum Ändern einer Speicherzelle. Die Bits 3 und 4 bestimmen die Funktion (JMP, JSR, ISZ, DSZ), die Bits 6 und 7 die Adressierungsart (s.o.). Das Bit 5 kennzeichnet eine indirekte Adressierung, der 8-Bit-Wert Offset die absolute oder relative Adresse (s.o.):


 

Datentransfer

Haben die ersten drei Bits die Werte 0 0 1 oder 0 1 0 handelt es sich um einen Befehl, Daten vom Speicher zum Akkumulator (LDA) oder umgekehrt (STA) zu bewegen. Die Bits 3 und 4 geben den zu verwendenden Akkumulator an, die Bits 6 und 7 die Adressierungsart. Das Bit 5 kennzeichnet eine indirekte Adressierung, der 8-Bit-Wert Offset die absolute oder relative Adresse (s.o.):


 

Arithmetik und Logik

In diesem Fall ist das erste Bit (Bit 0) gesetzt. Die Bits 1 und 2 geben den Quellakkumulator und die Bits 3 und 4 den Zielakkumulator an. Die auszuführende Funktion wird mit den Bits 5 bis 7 (8 Funktionen: COM, NEG MOV, INC, ADC, SUB, ADD, AND) ausgewählt. Die Bits 8 und 9 legen eine Schiebebedingung (L, R, S), die Bits 10 und 11 eine Modifikation (Z, O, C) des Übertragbits (Carry) und die Bits 13 bis 15 eine vom Ergebnis abhängige Sprungbedingung (SKP, SZC, SNC, SZR, SNR, SEZ, SBN) fest:


 

Ein- und Ausgabe

Bei Befehlen, die eine Ein- oder Ausgabe von oder an ein Peripheriegerät bewirken, haben die ersten drei Bits den Wert 0 1 1. Die Bits 3 und 4 geben den Akkumulator an, der für die zu übertragenden Daten benutzt werden soll. Mit den Bits 5 bis 7 wird eine von 8 Ein-Ausgabe-Funktionen (NIO, DIA, DOA, DIB, DOB, DIC, DOC, SKP) ausgewählt. Mit den Bits 8 und 9 kann ein Steuersignal für das Interface (S, C, P) gewählt werde, die Bits 10 bis 15 geben die Adresse des Geräts an (0 .. 63):


 

Die Befehle im Einzelnen

Befehle mit Speicherreferenzierung

Bei allen Befehlen, die eine Speicherzelle adressieren, haben die Bit 5..15 die gleiche Bedeutung:


 
Symbol Erläuterung
INDX = 00 Direkte Adressierung auf der Speicherseite Null
Offset (0..377) ist die absolute Adresse
  = 01 Relative Adressierung zum Programmzähler (PC)
Offset (-200..177) ist der Abstand im Zweierkomplement
  = 10 Relative Adressierung zum Akkumulator 2 (AC2)
Offset (-200..177) ist der Abstand im Zweierkomplement
  = 11 Relative Adressierung zum Akkumulator 3 (AC3)
Offset (-200..177) ist der Abstand im Zweierkomplement
OFFSET 0 .. 377 Absolute Adresse auf Seite Null (INDX = 0)
  -200..177 Relative Adresse im Zweierkomplement (INDX > 0)
I = 0 Direkte Adressierung: Der Inhalt der über INDX und OFFSET bestimmten Adresse ist Ziel der Operation
  = 1 Indirekte Adressierung: Der Inhalt der über INDX und OFFSET bestimmten Adresse ist die Adresse, die Ziel der Operation ist.

Alle Adressen sind als Oktalzahlen angegeben.

Es lassen sich damit also direkt 1024 Speicherplätze adressieren: 256 direkt auf Seite Null, und jeweils 256 Plätze im Bereich um den Programmzähler, sowie um die Adressen in Akkumulatoren 2 und 3. Wenn das Indirektbit I gesetzt ist, kann der gesamte Speicher adressiert werden. Ist bei einer solchen indirekten Adresse das Bit 0 gesetzt, bedeutet dies eine verkettete indirekte Adressierung.
Bsp. für Adressierung:

  PC = 1415 (oktal)
  1. Befehl: OFFSET = -132, I = 0, INDX = 01 (rel Adr. zum PC)
     Speicher: [1415-132 = 1263] = 2431    (Inhalt der Speicherzelle 1263) 
     ==> eff. Wert = 2431  
  2. Befehl: OFFSET = -132, I = 1, INDX = 01 (rel Adr. zum PC)
     Speicher: [1415-132 = 1263] = 2431    (Inhalt der Speicherzelle 1263) 
               [2431] = 7425               (Inhalt der Speicherzelle 2431)
     ==> eff. Wert = 7425
  3. Befehl: OFFSET = -132, I = 1, INDX = 01 (rel Adr. zum PC)
     Speicher: [1415-132 = 1263] = 102431  (Inhalt der Speicherzelle 1263) 
               [2431] = 7425               (Inhalt der Speicherzelle 2431)
               [7425] = 6215               (Inhalt der Speicherzelle 7425)
     ==> eff. Wert = 6215

  ISZ   123        ; erhöhe den Inhalt von Adr. 123(8)
  ISZ   @123       ; erhöhe den Inhalt der Adresse, auf die in Adr. 123(8) zeigt
  ISZ   -12,3      ; erhöhe den Inhalt der Adresse [AC3]-12  

Sprungbefehle und Speichermodifikation


 

Die Ermittlung der effektiven Adresse ist zuvor beschrieben. Die Bits 3 und 4 legen die auszuführende Funktion fest:

Symbol Mnem. Erläuterung
FKT = 00 JMP Sprung an die angegebene Adresse (Adresse → PC)
  = 01 JSR Sprung in eine Unterroutine (PC+1 → AC3, Adresse → PC)
  = 10 ISZ Addiere 1 zu der angegebene Adresse und überspringe den nächsten Befehl, wenn das Ergebnis Null ist
  = 11 DSZ Subtrahiere 1 von der angegebenen Adresse und überspringe den nächsten Befehl, wenn das Ergebnis Null ist

Hinweis: Im Gegensatz zu den heute üblichen Prozessoren, gab es bei der beschriebenen Baureihe der Nova noch keinen Stack (spätere Modelle, z.B. Nova 4 waren damit ausgestattet). Daher erforderte das Verschachteln von Unterroutinen zusätzliche programmatische Maßnahmen. Da nach dem Aufruf einer Unterroutine (JSR) die Rückspringadresse im Akkumulator 3 (AC 3) abgelegt wurde, musste dieser vor Aufruf einer weiteren verschachtelten Unterroutine an geeigneter Stelle zwischengespeichert werden. Eine einfache, allerdings nicht ablaufinvariante (reentrant) Methode ist das folgende
Beispiel:

          ...
          JSR   Subr1    ; Sprung in Unterroutine
          ...
          JSR   Subr2    ; Sprung in Unterroutine
          ...
  Subr1:  ...
          JMP   0,3      ; Rücksprung 
          ...      
          0
  Subr2:  STA   AC3,Subr2-1        
          ...
          JSR   Subr1    ; Sprung in Unterroutine
          ...
          JMP   @Subr2-1 ; Rücksprung 
          ...

Daten zwischen Speicher und Akkumulatoren bewegen

Die Ermittlung der effektiven Adresse ist oben beschrieben. Die Bits 1 und 2 legen die auszuführende Funktion fest, die Bits 3 und 4 den zu verwendenden Akkumulator:

Symbol Mnem. Erläuterung
FKT = 01 LDA Lade den Inhalt der angegebenen Adresse in den Akkumulator
  = 10 STA Speichere des Inhalt des Akkumulators in die angegebene Adresse
AC = 00 AC0 Daten nach oder von Akkumulator 0
  = 01 AC1 Daten nach oder von Akkumulator 1
  = 10 AC2 Daten nach oder von Akkumulator 2
  = 11 AC3 Daten nach oder von Akkumulator 3

Bsp.:

  LDA   1,23        ; Inhalt von Adr. 23 nach AC1
  LDA   0,5,3       ; Inhalt von [AC3]+5 nach AC0
  STA   1,.-3       ; Inhalt von AC1 nach [PC]-3
  STA   1,@23       ; Inhalt von AC1 nach Adr., auf die Adr. 23 zeigt
  STA   1,@1,3      ; Inhalt von AC1 nach Adr., auf die [AC3]+1 zeigt

Arithmetik und Logik

Die größte Gruppe bilden die Befehle für Arithmetik und Logik. Sie sind durch eine 1 im Bit 0 gekennzeichnet. Alle Befehle beinhalten die Möglichkeit nach einer solchen Operation das Carry-Bit zu manipulieren, ein bitweises Schieben auszuführen und eine ergebnisabhängige Sprungbedingung zu erzeugen. Letzteres ist die einzige Möglichkeit Programmverzweigungen zu bewirken. Ist die Bedingung erfüllt, wird der nächste folgende Befehl übersprungen (Skip).

Symbol Mnem. Erläuterung
AC-S = 00 AC0 Akkumulator 0 (1. Operand)
  = 01 AC1 Akkumulator 1
  = 10 AC2 Akkumulator 2
  = 11 AC3 Akkumulator 3
AC-D = 00 AC0 Akkumulator 0 (2. Operand und Ergebnis)
  = 01 AC1 Akkumulator 1
  = 10 AC2 Akkumulator 2
  = 11 AC3 Akkumulator 3
FKT = 000 COM Bilde das logisches Komplement von AC-S, platziere bei N=0 das Ergebnis nach der angebenen Schiebeoperation (SHFT) in AC-D
  = 001 NEG Bilde das Zweierkomplement von AC-S (Negieren) und platziere bei N=0 das Ergebnis nach der angebenen Schiebeoperation (SHFT) in AC-D
  = 010 MOV Platziere bei N=0 den Wert in AC-S nach der angebenen Schiebeoperation (SHFT) in AC-D
  = 011 INC Erhöhe den Wert von AC-S um Eins und platziere bei N=0 das Ergebnis nach der angegebenen Schiebeoperation (SHFT) in AC-D
  = 100 ADC Addiere das logische Komplement von AC-S zu dem Wert in AC-D und platziere bei N=0 das Ergebnis nach der angegebenen Schiebeoperation (SHFT) in AC-D
  = 101 SUB Subtrahiere den Wert in AC-S zu dem Wert in AC-D (entspricht der Addition des Zweierkomplements) und platziere bei N=0 das Ergebnis nach der angegebenen Schiebeoperation (SHFT) in AC-D
  = 110 ADD Addiere den Wert in AC-S zu dem Wert in AC-D und platziere bei N=0 das Ergebnis nach der angegebenen Schiebeoperation (SHFT) in AC-D
  = 111 AND Bilde das logische Und der Werte in AC-S und AC-D und platziere bei N=0 das Ergebnis nach der angegebenen Schiebeoperation (SHFT) in AC-D
SHFT = 00 keine Schiebeoperation
  = 01 L Schiebe um ein Bit über den Carry nach links (s.u.)
  = 10 R Schiebe um ein Bit über den Carry nach rechts (s.u.)
  = 11 S Vertausche das linke mit dem rechten Byte
CRY = 00 Das Carrybit bleibt unverändert
  = 01 Z Das Carrybit wird auf Null gesetzt
  = 10 O Das Carrybit wird auf Eins gesetzt
  = 11 C Bilde das Komplement des Carrybits
N = 0 Das Ergebnis ersetzt den Inhalt von AC-D
  = 1 # Der Inhalt von AC-D wird nicht verändert (no load)
SKIP = 000 Der nächste Befehl wird immer ausgeführt
  = 001 SKP Der nächste Befehl wird immer übersprungen
  = 010 SZC Der nächste Befehl wird übersprungen, wenn das Carrybit Null ist
  = 011 SNC Der nächste Befehl wird übersprungen, wenn das Carrybit nicht Null ist
  = 100 SZR Der nächste Befehl wird übersprungen, wenn das Ergebnis Null ist
  = 101 SNR Der nächste Befehl wird übersprungen, wenn das Ergebnis nicht Null ist
  = 110 SEZ Der nächste Befehl wird übersprungen, wenn entweder das Carrybit oder das Ergebnis Null ist
  = 111 SBN Der nächste Befehl wird übersprungen, wenn das Carrybit und das Ergebnis nicht Null sind

Schiebebefehle

Schieben nach links:


Schieben nach rechts:


Bytes vertauschen:


Bsp.:

  COM#    1,1,SZR     ; Skip, wenn AC1 = 177777(8)
  ...
  MOVZ    1,3         ; Schiebe AC1 nach AC3 und setze das Carrybit auf Null
  ...
  MOVL#   2,2,SZC     ; Ist AC2 positiv (Bit 0 = 1)?
  MOVOR   2,2,SKP     ; Nein, Carry = 1 und einmal rechts schieben (Division durch 2)
  MOVZR   2,2         ; Ja, Carry 0 0 une einmal rechts schieben (Division durch 2)
  ...
  SUBZ#   1,0,SZC     ; Skip, wenn AC0 < AC1
  ADCZ#   1,0,SZC     ; Skip, wenn AC0 ≤ AC0

Datenein- und -ausgabe

Die nachfolgenden Befehle erlauben den Datentransfer und die Steuerung einer Elektronik für die Datenein- und -ausgabe. Es können damit 62 Geräte (Adressen 1 .. 62) adressiert werden. Die Geräteadresse 0 wird nicht benutzt, die Adresse 63 wird für einige Spezialfunktionen verwendet (z.B Einlesen der Datenschalter der Konsole und die Interruptsteuerung). Jedes Interface kann bis zu drei Datenpuffer A, B und C (16-Bit-Register) sowie vier Flags (in der Hardware durch D-Flip-Flops realisiert): Busy, Done, Int-Disable und Int-Request besitzen. Die Flags werden für das typische Handshake-Verfahren eingesetzt.
Im Ruhezustand sind Busy- und Done-Flag nicht gesetzt. Zu Beginn eines Datentransfer wird vom Programm das Busy-Flag gesetzt. Der weitere Ablauf hängt davon ab, ob es sich um eine Ein- oder Ausgabe handelt:
1. Eingabe
Das Busys-Flag signalisiert dem Gerät, dass ein Datenwort erwartet wird. Sobald dies übertragen ist, setzt das externe Gerät das Done-Flag. Das Done-Flag kann vom Programm abgefragt werden (SKPDx), so dass das übertragene Datenwort mit einem DIx-Befehl abgeholt werden kann (Polling).
Ist das Int-Disable-Flag nicht gesetzt, wird gleichzeitig mit dem Done-Flag das Int-Request-Flag gesetzt, um einen Interrupt anzufordern. Das Programm muss dann eine geeignete Interrupt-Routine bereitstellen.
2. Ausgabe
Nach Setzen des Busys-Flags wird vom Interface ein Datenwort an das externe Gerät ausgegeben. Dieses bestätigt den Empfang durch Setzen des Done-Flags. Die weitere programmatische Verarbeitung kann dann, wie zuvor bei der Eingabe beschrieben, durch Polling oder Interrupt erfolgen.

Symbol Mnem. Erläuterung
AC = 00 AC0 Daten nach oder von Akkumulator 0
  = 01 AC1 Daten nach oder von Akkumulator 1
  = 10 AC2 Daten nach oder von Akkumulator 2
  = 11 AC3 Daten nach oder von Akkumulator 3
FKT = 000 NIO kein Datentransfer
  = 001 DIA Lese Daten aus Puffer A in den Akkumulator
  = 010 DOA Schreibe Daten aus dem Akkumulator in den Puffer A
  = 011 DIB Lese Daten aus Puffer B in den Akkumulator
  = 100 DOB Schreibe Daten aus dem Akkumulator in den Puffer B
  = 101 DIC Lese Daten aus Puffer C in den Akkumulator
  = 110 DOC Schreibe Daten aus dem Akkumulator in den Puffer C
CTRL = 00
  = 01 S Setze das Busy-Flag und Lösche das Done-Flag(Start)
  = 10 C Lösche alle Flags (Clear)
  = 11 P Spezielles geräteabhängiges Steuersignal (Pulse)
FKT = 111 SKP Überspringe den nachfolgenden Befehl (Skip) in Abhängigkeit eines Flags
CTRL = 00 BN Skip, wenn das Busy-Flag nicht Null ist
  = 01 BZ Skip, wenn das Busy-Flag Null ist
  = 10 DN Skip, wenn das Done-Flag nicht Null ist
  = 11 DZ Skip, wenn das Done-Flag Null ist
DEVICE = 0 .. 63 Geräteadresse

 

Standard-Geräteadressen

Adr. (okt) Adr. (hex) Adr. (dez) Masken- Bit Kurzform Gerät
01 01 01 MDV 16/32-bit Multiplizierer und Dividierer
10 08 08 14 TTO Konsolen-Ausgabe (Teletype output)
11 09 09 15 TTI Konsolen-Eingabe (Teletype input)
12 0A 10 11 PTR Lochstreifenleser (Paper tape reader)
13 0B 11 13 PTP Lochstreifenstanze (Paper tape punch)
14 0C 12 13 RTC Zeitgeber (Real time clock)
15 0D 13 12 PLT Digitalplotter (Incremental plotter)
16 0E 14 10 CDR Lochkartenleser(Card reader)
17 0F 15 12 LPT Zeilendrucker (Line printer)
20 10 16 9 DSK Festplatte (Disk)
22 12 18 10 MTA Magnetbandgerät (Magnetic tape)
33 1B 27 ? ? Wechselplatte (Cartridge disk)