HaDesWWW logo
Startseite

Downloads
Geschichte(n)
 
Hardware
FPGA-Board
Prozessor
  Instruktionssatz
Peripherie
  XBus-Referenz
PS/2-Board
Soundboard
USB-MMC-Board
 
PC-Software
HaCom
HoAsm, HLink
Emulator
Connectivity
 
Embedded Software
HAL
Dateimanager
Tetris
PacMan
3D-Engine
Pong
PacMan 3D
 
Kontakt

HaDes XP - Der Instruktionssatz

Diese Referenzseite gibt genaue Informationen über die Wirkung der Instruktionen des HaDes XP-Prozessors.

Im folgenden seien w,a,b Register der HaDes XP (im Assembler mit r0..r15 bezeichnet) und 0 das 0-Register. Konstanten werden durch #k beschrieben.

Die Dauer der Befehle in Takten wird stets für den Gutfall, d.h. alle Caches enthalten bereits die benötigten Daten, angegeben. Bei einem Instruction Cache Miss kommen jeweils nocheinmal 18 Takte zur Ausführungsdauer hinzu. Dies gilt auch für Data Cache Misses (nur bei den Load und Store-Befehlen).

Arithmetische und logische Befehle

Interner Zustand

Der HaDes XP-Prozessor hat neben den 32 Bit General-Purpose-Registern r1 bis r15 noch einige weitere interne Register, die ebenfalls wichtig für die Verarbeitung arithmetischer Befehle sind. Diese werden in der folgenden Tabelle erklärt.

Name Bezeichnung Beschreibung
Overflow (ovMul, ovShift, ovUns, ovSgn) Speichert jeweils, ob bei der letzten
  • Multiplikation (ovMul
  • arithmetischen Linksshift-Operation (ovShift)
  • Addition oder Subtraktion (ovUns, ovSgn)
ein Überlauf aufgetreten ist. Dabei werden die Parameter einer Addition oder Subtraktion bei ovUns als unsigned und bei ovSgn als signed interpretiert.
Der Zugriff erfolgt über die Befehle lflags und sflags, die allerdings im Emulator nicht korrekt implementiert sind.
Modulus rMod Speichert das Ergebnis der Modulo-Operation der zuletzt ausgeführten Division. Das Register kann durch den mod-Befehl gelesen, aber nicht direkt beschrieben werden.
Hochwertige Produktbits rMulHigh Speichert die oberen 32 Bits (Bits 63..32) der zuletzt ausgeführten Multiplikation. Das Register kann mit dem prod-Befehl gelesen, aber nicht direkt beschrieben werden.
Hochwertige Dividendenbits rDiv64 Enthält die oberen 32 Bits (Bits 63..32) des Dividenden für die nächste Division. Das Register kann mit dem div64p Befehl beschrieben, aber nicht direkt ausgelesen werden.
64-Bit-Vorbereitung div64Prep Flag, das angibt, ob die nächste Division die hochwertigen Dividendenbits verwendet.
Memory Protection rMemProt Register für den Speicherschutz, mit dem Teile des Datenspeichers zum Schreiben gesperrt werden können. Beschreiben durch smp möglich, Auslesen unmöglich.

Befehle

Die meisten Befehle sind auch als Immediate-Varianten verfügbar. Zum Befehl OP heißt die Immediate-Version OPI, diese sind erneut aufgeführt. Hierbei ist der B-Operand durch eine 16-Bit-Konstante ersetzt, die vor der Verarbeitung auf 32 Bit expandiert wird. Diese Vorzeichenerweiterung geschieht bei den logischen Befehlen AND, OR, XOR und XNOR unsigned, bei allen anderen Befehlen signed. Die sonstige Abarbeitung entspricht genau den Drei-Register-Varianten. 

Befehl Semantik Dauer (ohne Cache-Misses)
ADD w,a,b
ADDI w,a,#k
Addition
regs[w] = regs[a] + regs[b]
ovUns = unsigned overflow
ovSgn = signed overflow
2 Takte
SUB w,a,b
SUBI w,a,#k
Subtraktion
regs[w] = regs[a] - regs[b]
ovUns = unsigned overflow
ovSgn = signed overflow
2 Takte

MUL w,a,b
MULI w,a,#k
vorzeichenbehaftete Multiplikation (32x32 -> 64 bit)
(rMulHigh, regs[w]) = regs[a] * regs[b]
ovMul wird gesetzt, wenn das Ergebnis nicht in 32 Bits passt; sonst gelöscht
19 Takte
PROD w Zugriff auf die High-Bits des Ergebnisses der letzten Multiplikation
regs[w] = rMulHigh
2 Takte

DIV w,a,b
DIVI w,a,#k
vorzeichenbehaftete Division (64 oder 32/32 -> 32 bit)
temp = (div64Prep ? (rDiv64, regs[a]) : regs[a])
regs[w] = temp / regs[b]
rMod = temp % regs[b]
div64Prep = 0
37 Takte
DIV64P a rDiv64 = regs[a]
div64Prep = 1
MOD w regs[w] = rMod 2 Takte

MULFP w,a,b
MULFPI w,a,#k
vorzeichenbehaftete Fixpoint-Multiplikation für Fixpunktzahlen mit 16 Bit Vor- und Nachkomma
regs[w] = regs[a] *: regs[b]
19 Takte
DIVFP w,a,b
DIVFPI w,a,#k
vorzeichenbehaftete Fixpoint-Division
regs[w] = regs[a] /: regs[b]
div64Prep = 0
37 Takte

AND w,a,b
ANDI w,a,#k
logisches UND 2 Takte
OR w,a,b
ORI w,a,#k
logisches ODER
XOR w,a,b
XORI w,a,#k
logisches Exklusiv-ODER
XNOR w,a,b
XNORI w,a,#k
logisches Not-Exklusiv-ODER (bitweiser Vergleich)

SHL w,a,b
SHLI w,a,#k
nicht-zyklischer Linksshift
ovShift wird gesetzt, falls nicht nur Nullen herausgeschoben werden
abhängig von der Shiftweite b
3 + b/4 + b%4 Takte
4 Takte für b=1
11 Takte für b=31

CSHL w,a,b
CSHLI w,a,#k
zyklischer Linksshift
SHR w,a,b
SHRI w,a,#k
nicht-zyklischer Rechtsshift (Nullen werden nachgeschoben)
CSHR w,a,b
CSHRI w,a,#k
zyklischer Rechtsshift
SHAR w,a,b
SHARI w,a,#k
arithmetischer Rechtsshift (das Vorzeichenbit wird nachgeschoben)

Set-Condition-Befehle

Diese Befehle setzen das angegebene Zielregister w auf den Wert 1 oder 0, je nachdem, ob der entsprechende Registerinhalt-Vergleich zutraf oder nicht zutraf. Auch zu diesen Befehlen gibt es jeweils eine Immediate-Variante SXXI.

Befehl Semantik Dauer
SEQ w,a,b Test auf Gleichheit 2 Takte
SNE w,a,b Test auf Ungleichheit
SLT w,a,b Test, ob Reg[a] < Reg[b]
SGT w,a,b Test, ob Reg[a] > Reg[b]
SLE w,a,b Test, ob Reg[a] < Reg[b]
SGE w,a,b Test, ob Reg[a] > Reg[b]

Sprünge und Verzweigungen

Interner Zustand

Folgende interne Spezialregister sind für die Verarbeitung von Sprungbefehlen wichtig. Zu beachten ist hier, dass die HaDes XP kein separates Stackpointer-Register besitzt. Es kann frei von der Anwendung gewählt werden; in der HAL wird stets r15 benutzt. Auch die Rücksprungadresse bei Funktionsaufrufen wird in ein General-Purpose-Register gespeichert (in der HAL r1) und lediglich bei Bedarf von der Anwendung in den Speicher kopiert.

Name Bezeichnung Beschreibung
Program Counter pc Speicheradresse des aktuellen Befehls.
Wird am Ende der meisten Befehle einfach um eins erhöht und zeigt damit auf den nächsten Befehl.

Die HaDes XP verfügt über folgende bedingte und unbedingte Sprungbefehle. Die meisten sind Immediate-Befehle mit einer absoluten Sprungziel-Adresse (=Befehlsnummer) im Immediate-Operanden. Einige Befehle sind aber auch als indirekte Sprünge verfügbar, das Ziel wird hier aus einem der Register geladen. 

Befehl Semantik Dauer
BEQZ a,#k Sprung nach Adresse k, falls regs[a] = 0
pc = (regs[a] ? pc + 1 : k)
2 Takte
BNEZ a,#k Sprung nach Adresse k, falls regs[a] != 0
pc = (!regs[a] ? pc + 1 : k)
JMP #k Unbedingter Sprung nach Adresse k
Entspricht BEQZ r0,k
RET b
JMPR b
Unbedingter Sprung nach Adresse regs[b]
pc = regs[b]
JAL w,#k
JALR w,b
Aufruf des Unterprogramms an Adresse k (bzw. regs[b])
regs[w] = pc + 1
pc = k (bzw. regs[b])
START #k
STARTR b
Unbedingter Sprung zu Adresse k (bzw. regs[b])
Instruktions- und Datencache wird ungültig gesetzt
Zugriff auf Bootmemory wird deaktiviert
ca. 258 Takte

Lade- und Speicherbefehle

Die Lade- und Speicherbefehle LOAD und STORE ermöglichen den Zugriff auf den Datenspeicher mit indirekter Adressierung + Displacement. Der Adressraum beträgt volle 32 bit (d.h. 4 GB). Da aber der tatsächliche Speicherausbau weitaus kleiner ist, sind nur die unteren Adressen gültig. Ein Zugriff auf eine ungültige Speicheradresse führt zu einem Memory Interrupt. Außerdem ist das Schreiben nur auf Adressen gestattet, die nicht geschützt sind. Dieser Speicherschutz wird durch den SMP-Befehl aktiviert; bei Systemstart ist er ausgeschaltet. 

Die Komfortbefehle LREGS und SREGS ermöglichen das Sichern und Wiederherstellen mehrerer Register in einem Aufwasch. Dabei werden stets die Register 1 bis b (jeweils einschließlich) bearbeitet und an aufeinanderfolgende Speicheradressen, ausgehend von der Speicheradresse regs[a] + k, abgelegt. Die Befehle werden im Prozessor genau wie eine Folge von LOAD- bzw. STORE-Anweisungen verarbeitet.

Befehl Semantik Dauer
LOAD w,a,#k Laden eines 32-Bit-Wortes aus dem Datenspeicher
regs[w] = mem[regs[a] + k]
Tipp: Für absolute Adressierung (globale Variablen) verwende LOAD w,r0,#k.
Achtung: Der Immediate-Operand ist 16 bit groß und vorzeichenbehaftet.
Dies funktioniert also nur für die Adressen 0 bis 0x7FFF.
3 Takte
(+18 bei Data Cache Miss)
STORE b,a,#k Ablegen eines 32-Bit-Wortes im Datenspeicher
mem[regs[a] + k] = regs[b]
LREGS #b,a,#k Laden mehrerer Register
for i from 1 to b do
  regs[i] = mem[regs[a] + k + (i-1)]
3*b Takte
(+ Cache Misses)
SREGS #b,a,#k Sichern mehrerer Register
for i from 1 to b do
  mem[regs[a] + k + (i-1)] = regs[i]
SMP b
SMPI #k
Speicherschutz setzen: Schreibzugriff auf Speicherzellen, deren
Adresse kleiner als rMemProt ist, ist nicht gestattet.
rMemProt = regs[b]
2 Takte

Kommunikation mit Peripherie

Die folgenden Befehle stellen Zugriffsmöglichkeiten auf externe Komponenten bereit. Falls eine angesprochene Portadresse nicht vorhanden ist, wird ein XBus Not Available (XNA) Interrupt ausgelöst.

Befehl Semantik Dauer
IN w,#k
INR w,b
Lesen von Portadresse k (bzw. regs[b])
regs[w] = Port[k]
2 Takte
+ Latenz der angesprochenen Komponente
OUT a,#k
OUTR a,b
Schreiben nach Portadresse k (bzw. regs[b])
Port[k] = regs[a]

Interrupt-Behandlung

Die HaDes XP-CPU verfügt über fünfzehn Interrupts. Für jeden Interrupt kann die Einsprungadresse der Interrupt Service Routine eingestellt werden (SISA), die aufgerufen wird, falls ein Interrupt auftritt und Interrupts global aktiviert sind (ENI). 

Achtung: Nicht alle Interrupts sind in der aktuellen HaDes-Version implementiert. Nur die fett markierten Interrupts werden auch wirklich von der Hardware ausgelöst. 

Kürzel Beschreibung Priorität
USR1 Software-Interrupt zur besonderen Verwendung 1 (niedrig)
XDUMMY1 Reservierter Interrupt für XBus-Komponenten 2
XSOUND XSound meldet "Puffer leer" 3
XUSB XUSB meldet "Daten empfangen bzw. versandt" 4
XTIMER XTimerPro meldet "Timer abgelaufen" 5
XPS2 XPS2 meldet "Daten empfangen bzw. versandt" 6
XCONSOLE XConsole meldet "Taster gedrückt" 7
XJTAG XJtag meldet "Daten empfangen bzw. versandt" 8
XDUMMY2 Reservierter Interrupt für XBus-Komponenten 9
USR2 Software-Interrupt zur besonderen Verwendung 10
OVF ALU Overflow (noch nicht implementiert) 11
DIV0 ALU Division by zero (noch nicht implementiert) 12
XADDR Eine nicht zugeordnete XBus-Adresse wurde angesprochen 13
MEMADDR Memory. Die angegebene Speicheradresse existiert nicht (LOAD, STORE)
oder ist schreibgeschützt (STORE).
14
PCADDR Ein Sprung auf ein nicht vorhandenes Sprungziel soll ausgeführt werden,
d.h. die Zieladresse ist kleiner als 0 oder größer als 0xFFFF.
15 (hoch)

Zu jedem Interrupt kann eine (und nur eine) Anforderung gespeichert werden, die ausgeführt wird, sobald Interrupts wieder aktiviert wurden bzw. das Interrupt Level genügend gesunken ist (durch RETI). 

Interrupts werden stets zwischen Befehlen ausgeführt, d.h. zuerst wird der auslösende Befehl vollständig abgearbeitet (bei IN bzw. LOAD ist das Ergebnis des Befehls undefiniert, falls dadurch ein Interrupt ausgelöst wird), dann wird die Interrupt-Routine aufgerufen, und dann mit dem nächsten Befehl des Hauptprogramms fortgefahren. Folgende Übersicht zeigt, nach welchen Befehlen die Interrupts auftreten können, wenn Interrupts global aktiviert wurden: 

Interrupt Befehl
XSOUND, XUSB, XTIMER, XPS2, XCONSOLE, XJTAG alle außer MUL, MULFP, DIV, DIV64P und deren Immediate-Varianten, wenn der Interrupt bei der entsprechenden XBus-Komponente aktiviert wurde
XADDR IN, OUT
MEMADDR LOAD, STORE
PCADDR BNEZ, BEQZ, START, JAL, JMP, RET und deren Register-Varianten

Durch die Unterdrückung von Peripherie-Interrupts nach Multiplikations- und Divisionsbefehlen wird sichergestellt, dass die High Bits des Ergebnisses bzw. der Rest stets abgeholt werden können und nicht durch eine Operation innerhalb eines Peripherie-Interrupt-Handlers zerstört werden. 

Befehl Semantik
ENI Enable Interrupts
DEI Disable Interrupts
SISAI a,#k
SISA a,b
k (bzw. regs[b]) ist ISR-Adresse für Interrupt regs[a]
RETI Rücksprung aus ISR

Andere Befehle

Diese selten benötigten Befehle passen in keine andere Kategorie. 

Befehl Semantik Dauer
LLEA w Lädt die zuletzt verwendete effektive Speicheradresse
(Ergebnis der Addition von regs[a]+k bei LOAD, STORE, LREGS und SREGS)
2 Takte
LIRA w Lädt die Interrupt-Rücksprungadresse. Falls der Befehl außerhalb
eines Interrupt Handlers aufgerufen wird, ist das Verhalten undefiniert.
LFLAGS w Lädt das Overflow-Register.
SFLAGS b
SFLAGSI #k
Setzt das Overflow-Register.
SLEEP Stoppt die Programmausführung bis zum Eintreten eines Peripherie-Interrupts
(XSOUND, XUSB, XTIMER, XPS2, XCONSOLE oder XJTAG)
unbestimmt

Registerladebefehle

Diese Pseudobefehle laden Werte in Register.

Befehl Semantik Dauer
LDSI w,#k Konstante k (16 bit signed) in Register laden
regs[w] = SignExpand(#k)
2 Takte
LDUI w,#k Konstante k (16 bit unsigned) in Register laden
regs[w] = UnsignedExpand(#k)
LD w,a Kopieren von Registerinhalten
regs[w] = regs[a]
 
rrobek.de Hauptseite
 
Valid HTML 4.01!