Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
instruction_encoding [2021/03/11 10:00] – pulkomandy | instruction_encoding [2024/07/01 13:29] (current) – [Multiplication] simer | ||
---|---|---|---|
Line 7: | Line 7: | ||
^Contents|Opcode0|Operand A|Opcode1|6-bit Immediate | ^Contents|Opcode0|Operand A|Opcode1|6-bit Immediate | ||
+ | ===== Summary ===== | ||
+ | |||
+ | ^Opcode 0\1 ^ 0 ^ 1 ^ 2 ^ 3 ^ 4 ^ 5 ^ 6 ^ 7 ^ | ||
+ | ^Addressing mode|[BP+Imm6]|# | ||
+ | ^ | ||
+ | ^ | ||
+ | ^ | ||
+ | ^ | ||
+ | ^ | ||
+ | ^ | ||
+ | ^ | ||
+ | ^ | ||
+ | ^ | ||
+ | ^ | ||
+ | ^ | ||
+ | ^ | ||
+ | ^ | ||
+ | ^ | ||
+ | ^ | ||
+ | ^ | ||
+ | |||
+ | * Instructions in bold: uses the addressing mode listed on the first line | ||
+ | * Instructions in italics: only if operand A (destination register) is PC | ||
===== Special instructions ===== | ===== Special instructions ===== | ||
" | " | ||
- | Opcode1 determines the instruction: | + | ==== Multiplication ==== |
- | * 0: MUL | + | ^Instruction |
- | * 1: CALL | + | ^MAC (unsigned*signed) | F | Op.A |
- | * 2: GOTO | + | ^MAC (signed*signed) |
- | * 3: ??? | + | ^MUL (unsigned*signed) | F | Op.A |
- | * 4: MULS | + | ^MUL (signed*signed) |
- | * 5: INT, NOP | + | |
- | * 6: ??? | + | |
- | * 7: ??? | + | |
- | TODO: BREAK is probably somewhere here. | + | Note: Operand A and Operand B cannot be 0, 6 or 7 (it is not possible to multiply SP, SR or PC with something). |
+ | They also can not be 3 or 4 in MAC (MR is used for intermediate results). If the size of the MAC | ||
+ | operation is exactly 16, it will be encoded as N=0. | ||
+ | ==== CALL and GOTO ==== | ||
- | ==== MUL and MULS ==== | + | ^Instruction^Opcode0^Operand A^Opcode1^6-bit Immediate |
- | + | ^ CALL | F | ? | |
- | With OperandN = 1 and OperandA != 7 (other cases are not documented yet?) | + | ^ GOTO |
- | + | ||
- | OperandA and OperandB are multiplied together. | + | |
- | + | ||
- | ==== CALL and GOTO ==== | + | |
The target address is formed by the immediate6 value (for CS:) and another word after the instruction (for PC) | The target address is formed by the immediate6 value (for CS:) and another word after the instruction (for PC) | ||
Line 36: | Line 55: | ||
==== Interrupts ==== | ==== Interrupts ==== | ||
- | OperandA must be 0. | + | ^Instruction |
+ | ^ INT OFF | ||
+ | ^ INT IRQ | ||
+ | ^ INT FIQ | ||
+ | ^ INT IRQ, | ||
+ | ^ FIR_MOV ON | F | ? | ||
+ | ^ FIR_MOV OFF | ||
+ | | | ||
+ | ^ IRQ OFF | ||
+ | ^ IRQ ON | F | ? | ||
+ | | | ||
+ | ^ FIQ OFF | ||
+ | | | ||
+ | ^ FIQ ON | F | ? | ||
+ | | | ||
+ | ^ BREAK | ||
- | The operation depends on the Immediate6 value: | + | FIXME probably |
- | + | ||
- | * 00: INT OFF | + | |
- | * 01: INT IRQ | + | |
- | * 02: INT FIQ | + | |
- | * 03: INT FIQ,IRQ | + | |
- | * 04: FIR_MOV ON | + | |
- | * 05: FIR_MOV OFF | + | |
- | * 06: ??? | + | |
- | * 07: ??? | + | |
- | * 08: IRQ OFF | + | |
- | * 09: IRQ ON | + | |
- | * 0A: ??? | + | |
- | * 0B: ??? | + | |
- | * 0C: FIQ OFF | + | |
- | * 0D: ??? | + | |
- | * 0E: FIQ ON | + | |
- | * 0F: ??? | + | |
- | * 25: NOP | + | |
- | * All other values: ??? | + | |
===== Jump instructions ===== | ===== Jump instructions ===== | ||
- | Jump instructions are identified by Operand A = 0 | + | Jump instructions are identified by Operand A = 7 (makes sense, because they change the PC which is register 7) |
- | The type of jump depends on Opcode0: | + | ^Instruction |
+ | ^ JB, JNAE, JCC | 0 | | ||
+ | ^ JAE, JNB, JCS | 1 | | ||
+ | ^ JGE, JNL, JSC | 2 | | ||
+ | ^ JL, JNGE, JSS | 3 | | ||
+ | ^ JNE, JNZ | 4 | | ||
+ | ^ JE, JZ | 5 | | ||
+ | ^ JPL | ||
+ | ^ JMI | ||
+ | ^ JBE, JNA | 8 | | ||
+ | ^ JA, JNBE | 9 | | ||
+ | ^ JLE, JNG | A | | ||
+ | ^ JG, JNLE | B | | ||
+ | ^ JVC | ||
+ | ^ JVS | ||
+ | ^ JMP | ||
+ | | | ||
- | * 0: JCC JB JNAE | + | Opcode1 indicates the jump direction, and can be 0 (jump forward) or 1 (jump backward). The offset is counted from the opcode // |
- | * 1: JCS JNB JAE | + | |
- | * 2: JSC JGE JNL | + | |
- | * 3: JSS JNGE JL | + | |
- | * 4: JNE JNZ | + | |
- | * 5: JE JZ | + | |
- | * 6: JPL | + | |
- | * 7: JMI | + | |
- | * 8: JBE JNA | + | |
- | * 9: JNBE JA | + | |
- | * A: JLE JNG | + | |
- | * B: JNLE JG | + | |
- | * C: JVC | + | |
- | * D: JVS | + | |
- | * E: JMP | + | |
- | * F: Reserved for special instructions (see above) | + | |
- | + | ||
- | In jump instructions, Opcode1 is 0 to jump forward, and 1 to jump back. The offset is stored as a 6-bit immediate. | + | |
===== ALU instructions ===== | ===== ALU instructions ===== | ||
- | Opcode0 | + | ^Instruction |
- | + | ^ ADD | |
- | | + | ^ ADC |
- | | + | ^ SUB |
- | | + | ^ SBC |
- | | + | ^ CMP |
- | | + | | |
- | * 5: ??? | + | ^ NEG |
- | | + | | |
- | * 7: ??? | + | ^ XOR |
- | | + | ^ LD | |
- | | + | ^ POP |
- | | + | ^ RETF | 9 |5 (SR) |
- | | + | ^ RETI | 9 |5 (SR) |
- | | + | ^ OR | A |Op. A |Addr Mode|Param |
- | | + | ^ AND | B |Op. A |Addr Mode|Param |
- | | + | ^ TEST | |
- | | + | ^ ST | |
- | + | ^ PUSH | D |Last reg -1 | 2 |Register count| Stack pointer reg | | |
- | TODO: I don't know what the TEST instruction does differently from CMP? | + | | |
+ | | | ||
- | For these instructions, Opcode1 defines the addressing | + | Depending on opcode1, various |
- | * 0: [BP+Imm6] | + | ^Addressing mode ^Opcode0^Operand A^Opcode1 |
- | * 1: #Imm6 | + | ^%% [BP+Imm6] |
- | | + | ^%% #Imm6 %%| ALU op| Op. A | 1 |
- | | + | | Special (POP, PUSH) | |
- | * 4: addressing depends on opN | + | ^%% [Rs] %%| ALU op| Op. A | 3 | 0 | Rs | |
- | * 5: Rs LSL/LSR OpN | + | ^%% [Rs--] |
- | | + | ^%% [Rs++] |
- | | + | ^%% [++Rs] |
+ | ^%% D:[Rs] %%| ALU op| Op. A | 3 | 4 | Rs | | ||
+ | ^%% D:[Rs--] | ||
+ | ^%% D: | ||
+ | ^%% D:[++Rs] %%| ALU op| Op. A | 3 | 7 | Rs | | ||
+ | ^%% Rs %%| ALU op| Op. A | 4 | 0 | Rs | | ||
+ | ^%% # | ||
+ | ^%% From [Addr16] %%| ALU op| Op. A | 4 | 2 | Rs* | |16-bit address in next word, Rs is first operand| | ||
+ | ^%% To [Addr16] | ||
+ | ^%% Rs ASR shift %%| ALU op| Op. A | 4 | 4 + (shift - 1) | Rs | | ||
+ | ^%% Rs LSL shift %%| ALU op| Op. A | 5 | shift - 1 | Rs | | ||
+ | ^%% Rs LSR shift %%| ALU op| Op. A | 5 | 4 + (shift - 1) | Rs | | ||
+ | ^%% Rs ROL shift %%| ALU op| Op. A | 6 | shift - 1 | Rs | | ||
+ | ^%% Rs ROR shift %%| ALU op| Op. A | 6 | 4 + (shift - 1) | Rs | | ||
+ | ^%% [Addr6] %%| ALU op| Op. A | 7 | ||
- | When opcode1 is 2: | + | The instructions using Imm16 or Addr16 are 3-operand instructions, |
- | * LD becomes POP | + | '' |
- | * ST becomes PUSH | + | |
- | * Other values of opcode0 are not allowed | + | |
- | In a POP instruction: | + | naken_asm syntax: |
- | * OperandA+1 is the first popped register (it is not possible to push R0/SP) | + | '' |
- | * OperandN is the number of registers to push | + | |
- | * OperandB is the register to use as a stack pointer | + | |
- | RETF is a special case of POP with opA=5, opN=2, opB=0 (restores R6 and R7) | + | All other forms are 2-operand: operand A is always |
- | RETI is a special case of POP with opA=5, opN=3, opB=0 (restores R6, R7, and an extra special register containing interrupt flags) | + | The LD operation uses operand A only as a target. |
- | In a PUSH instruction: | + | The ST operation uses the second source operand (Rs, address, ...) as the target, and operand A (always |
- | * OperandA+1 is the last pushed register | + | Other operations can use both forms, so the "From [Addr16]" |
- | * OperandN is the number of registers to push | + | |
- | * OperandB is the register to use as a stack pointer | + | |
- | When opcode1 is 3, operandN defines incrementation and use of DS: | + | '' |
- | * 0: [Rs] | + | and the " |
- | * 1: [Rs--] | + | |
- | * 2: [Rs++] | + | |
- | * 3: [++Rs] | + | |
- | * 4: DS:[Rs] | + | |
- | * 5: DS:[Rs--] | + | |
- | * 6: DS:[Rs++] | + | |
- | * 7: DS:[++Rs] | + | |
- | When opcode1 is 4, operandN defines more addressing modes: | + | '' |
- | * 0: Rs | + | (so in this case the register encoded in OPA is used as a source, not a destination). |
- | * 1: 16-bit immediate value | + | |
- | * 2: Load from memory address | + | |
- | * 3: Store to memory address | + | |
- | * 4: Rs ASR 1 | + | |
- | * 5: Rs ASR 2 | + | |
- | * 6: Rs ASR 3 | + | |
- | * 7: Rs ASR 4 | + | |
- | When opcode1 is 5 or 6, operandN MSB defines the shift direction, | + | The LD and ST operations with the 16-bit addressing mode ignore |