Ganz ehrlich?
Sprache: Schöpfers Licht
Registers: §0000000000000000 ... §FFFFFFFFFFFFFFFF
Ports: %0000000000000000 ... %FFFFFFFFFFFFFFFF
Operationen: add[type] <target> <target_overflow> <source1> <source2>
add[type] <target> <target_overflow> <source> <value>
sub[type] <target> <target_overflow> <source1> <source2>
sub[type] <target> <target_overflow> <source> <value>
get[type] <target> <source>
put[type] <target> <source>
or[type] <target> <source1> <source2>
and[type] <target> <source1> <source2>
not[type] <target> <source>
rotleft[type] <source> <bits>
rotright[type] <source> <bits>
shiftleft[type] <source> <bits>
shiftright[type] <source> <bits>
jump <label>
jump[operator][type] <source1> <source2> <label>
jump[operator][type] <source> <value> <label>
int <interruptlevel>
Definitionen: label ::= "<name> :"
type::= { 8, 16, 32, 64}
operator ::= { EQ, NEQ, LEQ, LTH, GEQ, GTH}
Zur Beschreibung:
§… sind Speicherzellen, in denen man Informationen ablegen kann. Die Speicherzellen sind immer 64 bit breit. Mit dem Type 8 werden die 8 niedrigsten Bits ausgelesen, mit 16 die 16 niedrigsten usw.
%… sind Port Adressen. Sie sind ebenfalls 64 bit breit und können wie die Speicherzellen behandelt werden. Im Unterschied zu den Speicherzellen sind sie aber nicht persistente Speicher. Der Inhalt hängt vom Verhalten des dahinter liegenden Geräts ab und deren Reaktion auf Zeit, Raum und den Aktivitäten von Schöpfers Licht …
target ist immer das Ziel-Register bzw. der Ziel-Port. Das Ergebnis einer Operation wird dort hinein geschrieben. target_overflow wird bei einem Overflow bei einer Berechnung gesetzt, d.h. wenn das 65’te bit angesprochen wird, wird es mit 1, ansonsten mit 0 besetzt.
source ist natürlich das Quell-Register bzw. der Quell-Port.
Besonders Wichtig: Es gibt eine grundsätzliche Vereinbarung, dass im %0000000000000000 der Zeiger auf den nächsten Befehl steht und in %0000000000000001 der Zeiger auf den Stack. Einen Zugriff auf den Programmcode wird dabei aus der Sprache nicht direkt vorgesehen, der Stackzeiger hingegen zeigt immer auf eine Speicherzelle. %0000000000000002 ist für die Maskierung der Interrupts zuständig, spricht alle Stellen mit dem Bit-Wert 1 dürfen als Interrept-Level ausgeführt werden. Das Bit 0 ist dabei ohne Wirkung und wird immer mit 1 belegt.
Die nächsten 64 stellen enthalten die Positionen, die beim Auslösen des entsprechenden Interrupt-Level angesprungen werden.
Befehlsbeschreibungen:
add → Addition
sub → Subtraktion
get → Schreibe einen Wert in target, welcher aus der Adresse, die wiederrum in dem Register/Port source steht, ausgelesen wird.
put → das Gegenteil von get, es schreibt in den Register/Port den wert aus source, welcher in target steht.
or → bitweises ODER
and → bitweises UND
not → bitweise Negation
rotleft, rotright → bitweises rotieren nach links/rechts, wobei das herausgeschobene Bit aus dem Bereich an der anderen Stelle wieder eingeschoben wird (z.B. rotleft 10001 → 00011)
shiftleft, shiftright → bitweises verschieben nach links/rechts, wobei leerstellen mit 0 aufgefüllt werden (z.B. shiftleft 1001 → 00010)
jump → Springe an Position „label:“; Sonderfälle mit bewertung von Inhalten entsprechend den Vergleichsoperatoren.
int → Händisches Auslösen eines Interrupts. 0 → NMI, 1…63 hierarischer INT-Typ
Natürlich enthält diese Sprache bereits redundant ausgelegte Strukturen. So könnte man natürlich schon mal alle sub-Befehle entfernen. Auch die Shift-Befehle sind anders realisierbar. Und die Vergleichsoperatoren könnte man natürlich auch auf EQ, LTH, GTH reduzieren … theoretisch könnte man sogar auf eines von LTH und GTH verzichten…
Gruß,
Jumper, the II.
/EDIT:
Wir sind schon nahe am RISK-Code dran … und auf RISK laufen OS … ergo auch mit diesem hier …
/EDIT2:
Ups … jetzt habe ich das Interrupt vergessen grummel