-
Notifications
You must be signed in to change notification settings - Fork 0
Redcode
- 84 spec
- 94 spec + reference implementation
- Book: The Armchair Universe: an exploration of computer worlds
- 94 spec guide
- Krieg der Kerne: Handbuch für Einsteiger (German)
An instruction looks like the following:
MOV.AB @-2, #3
It is made up of the following parts:
- Opcode (e.g.
MOV): The instruction name. - Modifier (e.g.
AB): Modifies the instruction by specifying which operands it works on. - Source field (e.g.
@-2and destination field (e.g.#3):- Each made up of an address mode (like
@or#) followed by a number. - The comma separator is necessary!
- Each made up of an address mode (like
Each instruction can have an address mode for each of its fields. The following is a list of all possible address modes:
-
$- direct addressing -
#- immediate -
*- a-field indirect addressing -
@- b-field indirect addressing -
{- a-field indirect addressing with predecrement -
<- b-field indirect addressing with predecrement -
}- a-field indirect addressing with postincrement -
>- b-field indirect addressing with postincrement
Direct addressing directly points to the instruction specified by the number. For example, a MOV $0, $1 copies the 0th instruction (the MOV command itself) one space ahead in memory. The dollar sign is optional, if no address mode is specified, direct addressing is used automatically.
A literal number. If decoded as an address, it always points to address 0.
Indirect addressing looks into the a- or b-field (whichever is chosen by the specific address mode) of the nth instruction. This value is then used as a direct pointer to the instruction that will actually be used. Here is an example:
-1 | DAT #0, #4 ; ---.
0 | MOV 0, @-1 ; |
1 | ... ; | +4
2 | ... ; |
3 | MOV 0, @-1 ; <---'
When the MOV is executed, it looks at the b-field of instruction -1 (the DAT instruction). The value is 4. It then uses that as a pointer from the DAT instruction (not from the MOV!) to reach the actual destination instruction. In conclusion, the MOV copies itself to instruction 3 (4 ahead of the DAT).
If a predecrement or postincrement addressing mode is used, the intermediate value is either
- decremented and then used as a pointer in the case of a predecrement.
- used as a pointer and then incremented in the case of a postincrement.
Modifiers change the operators an instruction works on.
-
A: Operates on the a-field of the source-instruction and the a-field of the destination-instruction.- Example:
ADD.A $1, $2adds the a-field of instruction 1 to the a-field of instruction 2. The result is saved in the a-field of instruction 2.
- Example:
-
B: Operates on the b-field of the source-instruction and the b-field of the destination-instruction.- Example:
ADD.B $1, $2adds the b-field of instruction 1 to the b-field of instruction 2. The result is saved in the b-field of instruction 2.
- Example:
-
AB: Operates on the a-field of the source-instruction and the b-field of the destination-instruction.- Example:
ADD.AB $1, $2adds the a-field of instruction 1 to the b-field of instruction 2. The result is saved in the b-field of instruction 2.
- Example:
-
BA: Operates on the b-field of the source-instruction and the a-field of the destination-instruction.- Example:
ADD.BA $1, $2adds the b-field of instruction 1 to the a-field of instruction 2. The result is saved in the a-field of instruction 2.
- Example:
-
F: Operates on both the a-field of both instructions and the b-field of both instructions respectively. Basically combines theAandBmodifiers.- Example:
ADD.F $1, $2adds the a-field of instruction 1 to the a-field of instruction 2 as well as the b-field of instruction 1 to the b-field of instruction 2. The result is saved in the respective field.
- Example:
-
X: Basically combines theABandBAmodifiers. Works likeF, but with opposing fields.- Example:
ADD.X $1, $2adds the a-field of instruction 1 to the b-field of instruction 2 and saves the result in the b-field of instruction 2. Then it adds the b-field of instruction 1 to the a-field of instruction 2 and saves the result in the a-field of instruction 2.
- Example:
-
I: Operates on the whole instruction. Only used withMOVand comparison instructions (SEQ,SNE). The specifics depend a bit on the instruction itself.- Example:
MOV.I $1, $2moves the entire instruction 1 including opcode and address modes to instruction 2.
- Example:
Kill the process. When all processes of a player are killed, they lose.
Copies data from the source address to the destination address. The specific data is determined by the modifier. For example, the AB modifier copies the a-field from the source instruction to the b-field of the destination instruction. The I modifier copies the entire instruction.
ADD, SUB, MUL, DIV and MOD are all very similar, just computing the specified mathematical operation on the arguments specified by the modifier. For example, the ADD.AB instruction would add the a-field of the source instruction and the b-field of the destination instruction and save it to the b-field of the destination instruction. The I and the F modifiers act the same, computing the operation of the a-fields and the b-fields, then saving the result in the respective field in the destination instruction.
Division by zero using the DIV or MOD instructions acts like a DAT instruction, killing the process and leaving the destination unchanged. If two divisions are done using the F or X modifiers, and one is a divide by zero, the other division is still performed.
Jumps to (queues) the instruction pointed at by the a-field.
This instruction works similar to JMP in that it jumps to (queues) the instruction pointed at by the a-field. However, it only does that after looking at the instruction pointed to by the b-field. The jump is only done if the a- or b-field (or both) of this instruction is zero. Which fields are looked at is determined by the modifier:
-
A,BA: Jumps if the a-field of the instruction is zero -
B,AB: Jumps if the b-field of the instruction is zero -
I,X,F: Jumps only if both fields of the instruction are zero
Works like JMZ, but jumps if the tested value is not zero. If two values are tested (I, X, F modifiers), then the jump is executed if either of the fields are non-zero.
Works like JMN, but the a- and/or b-fields of the instruction pointed at by the b-field are decremented by one before testing.
Creates a new process that starts at the instruction pointed to by the a-field. This new process is queued after the executing the SPL instruction. So the new process will be executed after the current one has been executed again.
Note: CMP is the old name for the instruction before SNE was created. In modern standards, SEQ should be used.
Compares two instructions and skips the next instruction if they are equal. The fields being compared are dependent on the modifier. The I modifier compares the opcode and modifier as well, but ignores the address modes.
Works like SEQ, but skips the next instruction if the tested instructions are not equal.
Skips the next instruction if field(s) in the address pointed at by the a-field are less than the field(s) in the address pointed at by the b-field. The tested fields are specified by the modifier. If the modifier causes two comparisons (I, F, X), both need to be true for the next instruction to be skipped. The I modifier acts like the F modifier, since opcodes do not have an order to them.
Does nothing.