sd:isa
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| sd:isa [2026/05/06 12:42] – appledog | sd:isa [2026/06/10 04:36] (current) – appledog | ||
|---|---|---|---|
| Line 38: | Line 38: | ||
| | 67 | JC | JC @label | | 67 | JC | JC @label | ||
| | 68 | JNC | JNC @label | | 68 | JNC | JNC @label | ||
| - | | 84 | CALL | CALL @label | + | | 84 | [[#call|CALL]] | CALL @label |
| | 85 | RET | | 85 | RET | ||
| | 86 | INT | INT 0x10 | Software interrupt | | | | 86 | INT | INT 0x10 | Software interrupt | | | ||
| Line 49: | Line 49: | ||
| === Core-2 instructions | === Core-2 instructions | ||
| - | 16 instructions. Some instructions which are not strictly RISC but still considered core. | + | 29 instructions. Some instructions which are not strictly RISC but still considered core. |
| | 0A | XCHG | XCHG X, Y | Swap dem two -- X an Y trade place, quick quick | | | | 0A | XCHG | XCHG X, Y | Swap dem two -- X an Y trade place, quick quick | | | ||
| Line 55: | Line 55: | ||
| | 21 | DIV | DIV X, Y | Divide X = X / Y | | | | 21 | DIV | DIV X, Y | Divide X = X / Y | | | ||
| | 22 | MOD | MOD X, Y | Modulo X = X % Y | | | | 22 | MOD | MOD X, Y | Modulo X = X % Y | | | ||
| + | | 23 | ADD_REG_IMM | ||
| + | | 24 | SUB_REG_IMM | ||
| + | | 25 | MUL_REG_IMM | ||
| + | | 26 | DIV_REG_IMM | ||
| + | | 27 | MOD_REG_IMM | ||
| | 28 | ADDC | ADDC X, Y | Add with carry; X = X + Y + carry flag | | | | 28 | ADDC | ADDC X, Y | Add with carry; X = X + Y + carry flag | | | ||
| | 29 | SUBC | SUBC X, Y | Subtract with borrow; X = X - Y - borrow | | | | 29 | SUBC | SUBC X, Y | Subtract with borrow; X = X - Y - borrow | | | ||
| + | | 30 | ADDC_REG_IMM | ||
| + | | 31 | SUBC_REG_IMM | ||
| + | | 37 | AND_IMM | ||
| + | | 38 | OR_IMM | ||
| + | |||
| + | export const JN:u8 = 103; // JN addr | ||
| + | export const JNN:u8 = 104; // JNN addr | ||
| + | export const JO:u8 = 107; // JO addr | ||
| + | export const JNO:u8 = 108; // JNO addr | ||
| + | |||
| | 4A | ROL | ROL A | Rotate left | Z, N, C | | | 4A | ROL | ROL A | Rotate left | Z, N, C | | ||
| | 4B | ROR | ROR A | Rotate right | Z, N, C | | | 4B | ROR | ROR A | Rotate right | Z, N, C | | ||
| Line 69: | Line 84: | ||
| === Extended instruction set | === Extended instruction set | ||
| - | 44 instructions. Some of these are more extended than others. For example, PUSHA and POPA are very useful because they are very fast. If you have to push or pop more than 4 registers at once you can consider PUSHA. | + | 50 instructions. Some of these are more extended than others. For example, PUSHA and POPA are very useful because they are very fast. If you have to push or pop more than 4 registers at once you can consider PUSHA. |
| | 03 | LD_REG24 | | 03 | LD_REG24 | ||
| Line 77: | Line 92: | ||
| | 0D | PUSHA | PUSHA | Save all registers in ye treasure chest | | | | 0D | PUSHA | PUSHA | Save all registers in ye treasure chest | | | ||
| | 0E | POPA | POPA | Get the registers back | | | | 0E | POPA | POPA | Get the registers back | | | ||
| + | |||
| + | PUSH2 = 17 // push 2 | ||
| + | POP2 = 18 // pop 2 | ||
| + | PUSH3 = 19 // push 3 | ||
| + | POP3 = 20 // pop 3 | ||
| + | PUSH4 = 21 // push 4 | ||
| + | POP4 = 22 // pop 4 | ||
| ST_PD 25 // pre-dec store. | ST_PD 25 // pre-dec store. | ||
| Line 82: | Line 104: | ||
| ST_FS 27 // store+forward step. STA [BLX, +] | ST_FS 27 // store+forward step. STA [BLX, +] | ||
| - | | 23 | ADD_REG_IMM | ||
| - | | 24 | SUB_REG_IMM | ||
| - | | 25 | MUL_REG_IMM | ||
| - | | 26 | DIV_REG_IMM | ||
| - | | 27 | MOD_REG_IMM | ||
| - | | 30 | ADDC_REG_IMM | ||
| - | | 31 | SUBC_REG_IMM | ||
| | 36 | TEST | TEST dst, src | Non-destructive AND | | | | 36 | TEST | TEST dst, src | Non-destructive AND | | | ||
| - | | 37 | AND_IMM | ||
| - | | 38 | OR_IMM | ||
| | 48 | SHLC | SHLC A | Shift left | Z, N, C | | | 48 | SHLC | SHLC A | Shift left | Z, N, C | | ||
| | 49 | SHRC | SHRC A | Shift right | Z, N, C | | | 49 | SHRC | SHRC A | Shift right | Z, N, C | | ||
| | 4C | ROLC | ROLC A | Rotate left | Z, N, C | | | 4C | ROLC | ROLC A | Rotate left | Z, N, C | | ||
| | 4D | RORC | RORC A | Rotate right | Z, N, C | | | 4D | RORC | RORC A | Rotate right | Z, N, C | | ||
| + | |||
| + | JMPR = 109 // JMPR reg | ||
| + | JZR = 110 // JZR reg | ||
| + | JNZR = 111 // JNZR reg | ||
| + | JNR = 112 // JNR reg | ||
| + | JNNR = 113 // JNNR reg | ||
| + | JCR = 114 // JCR reg | ||
| + | JNCR = 115 // JNCR reg | ||
| + | JOR = 116 // JOR reg | ||
| + | JNOR = 117 // JNOR reg | ||
| + | |||
| | A4 | [[# | | A4 | [[# | ||
| Line 117: | Line 141: | ||
| ST_IDXR 213 // ST [ptr + reg], reg | ST_IDXR 213 // ST [ptr + reg], reg | ||
| | | ||
| + | |||
| | FB | CNOP | CNOP | Instruction Count / Timer | | | | FB | CNOP | CNOP | Instruction Count / Timer | | | ||
| | FC | YIELD | YIELD | Yield thread priority | Y | | | FC | YIELD | YIELD | Yield thread priority | Y | | ||
| Line 130: | Line 155: | ||
| | 8F | [[# | | 8F | [[# | ||
| | 90 | [[# | | 90 | [[# | ||
| + | |||
| + | | 91 | INSQUE | INSQUE | INSQUE REG, REG | | | ||
| + | | 92 | INSQUE_PTR | INSQUE | INSQUE REG, [REG] | | | ||
| + | | 93 | REMQUE | REMQUE | | | | ||
| + | | 94 | [[# | ||
| + | | 95 | SCANQUE_IMM | SCANQUE | | | | ||
| + | |||
| + | |||
| | 98 | [[# | | 98 | [[# | ||
| | 99 | [[# | | 99 | [[# | ||
| Line 141: | Line 174: | ||
| The PPU extended commands are included at the CISC level: | The PPU extended commands are included at the CISC level: | ||
| - | PPIXEL = 220 | + | | #220 | [[# |
| - | PLINE = 221 | + | | #221 | [[# |
| - | PRECT = 222 | + | | #222 | [[# |
| - | | + | | #223 | [[# |
| - | PCIRC = 224 | + | | #224 | [[# |
| - | | + | | #225 | [[# |
| - | | + | | #226 | [[# |
| - | PBLIT = 227 | + | | #227 | [[# |
| - | | + | | #229 | [[# |
| As are the forth acceleration opcodes: | As are the forth acceleration opcodes: | ||
| - | LSTEP = 240 // increment | + | | F0 | [[# |
| - | TTOS = 241 // | + | | F1 | TTOS | TTOS | Test TOS. CD=AB, AB=[ELY], ELY+=4, ZF=(CD==0) |
| - | LIT = 242 // | + | | F2 | LIT | LIT | push AB to stack, load next 4 bytes into AB. | | |
| - | + | | F3 | [[# | |
| == Dictionary | == Dictionary | ||
| here you will find information about each opcode. | here you will find information about each opcode. | ||
| + | |||
| + | <wrap #call />< | ||
| + | **'' | ||
| + | |||
| + | The CALLR instruction takes a register operand and dispatches based on the register' | ||
| <wrap #sez />< | <wrap #sez />< | ||
| Line 192: | Line 231: | ||
| <wrap #cmpc3 /> | <wrap #cmpc3 /> | ||
| **''# | **''# | ||
| + | |||
| + | Note: CMPC3 allows early termination on byte_a == 0: This is the " | ||
| <wrap #skpc /> | <wrap #skpc /> | ||
| **''# | **''# | ||
| + | |||
| + | <wrap #remque /> | ||
| + | The classic VAX semantic for REMQUE used the V flag for "queue was already empty before the call." SD-8516' | ||
| + | |||
| + | * VAX V=1 "you tried to remove from an empty queue" (error condition) | ||
| + | * SD-8516 Z=1 "you successfully removed the last item; the queue is now empty" (state condition) | ||
| + | |||
| + | <wrap #scanque />#148 $98 SCANQUE H, N, O\\ Both SCANQUE forms take three operands; head, needle and offset. SCANQUE_IMM treats offset as an IMM (byte). SCANQUE takes the offset in any register (allowing for larger offsets than +255). | ||
| + | |||
| + | SCANQUE. One-upping the VAX. SCANQUE combines queue traversal with a structured-field match in one fetch-execute cycle, which is the inner loop of every lookup operation in a hash chain, free list, or PCB table. | ||
| + | |||
| + | The split between SCANQUE (register offset) and SCANQUE_IMM (immediate offset) is the pragmatic call: most of the time you know the offset (you are writing CRUD for a struct). However, having the register form means you can write generic kernel-level queue helpers that take "field offset" | ||
| <wrap #pab /> | <wrap #pab /> | ||
| Line 221: | Line 274: | ||
| <wrap #case /> | <wrap #case /> | ||
| **''# | **''# | ||
| + | |||
| + | CASE is unusual because it reads from the instruction stream as data. The inline jump table isn't fetched and decoded, it's just structured bytes. This is the same pattern as LD_IMM (where the operand is fetched), but pushed further: an opcode-controlled variable-size payload. The bookkeeping all comes down to two derived addresses: | ||
| + | |||
| + | * IP + 3 * sel: the table slot containing the jump target. Read with read_24bit. | ||
| + | * IP + 3 * lim + 3: the first byte after the table. Used as the return point (and as the IP destination on OOB). | ||
| + | |||
| + | Both are masked to 24 bits because IP arithmetic in a 24-bit address space wraps. | ||
| + | |||
| + | OOB sets two flags and falls through (doesn' | ||
| + | |||
| + | Flags otherwise untouched. CASE only writes V and ER. Z, N, C, etc. survive across the instruction, | ||
| + | |||
| + | Note: A single entry CASE can be used as a CALLZ. CALL if register is zero, otherwise not. | ||
| <wrap #case3 /> | <wrap #case3 /> | ||
| Line 234: | Line 300: | ||
| **''# | **''# | ||
| + | <wrap #ppixel /> | ||
| + | Draw a pixel at X, Y color in C. | ||
| + | |||
| + | <wrap #lstepm /> | ||
| + | **'' | ||
| + | |||
| + | LDC #0 | ||
| + | LDD #1000 | ||
| + | loop: | ||
| + | <do something> | ||
| + | INC C | ||
| + | CMP C, D | ||
| + | JNZ @loop | ||
| + | |||
| + | This is a tight loop that runs 1,000 times. Many people might try to remove the CMP and use of D by doing this: | ||
| + | |||
| + | LDC #1000 | ||
| + | loop: | ||
| + | <do something> | ||
| + | DEC C | ||
| + | JNZ @loop | ||
| + | |||
| + | This is a tight loop, but this is even tighter: | ||
| + | |||
| + | < | ||
| + | LDFLX $F000 ; loop start | ||
| + | LDA #1 | ||
| + | STA [FLX] | ||
| + | LDA #1000 | ||
| + | STA [FLX+4] | ||
| + | loop: | ||
| + | <do something> | ||
| + | LSTEPM | ||
| + | JNZ @loop | ||
| + | </ | ||
| + | |||
| + | The benefit of this is you can count from X to Y. It is not a DEC loop. And, it's done at [FLX] and [FLX+4]. This is mainly a kludge for Forth and has been generalized in LSTEP. If I can get Forth to use LSTEP I will remove LSTEPM. | ||
| + | |||
| + | <wrap #lstep /> | ||
| + | **'' | ||
| + | |||
| + | |||
| + | < | ||
| + | LDC #1000 ; loop range | ||
| + | |||
| + | loop: | ||
| + | <do something> | ||
| + | LSTEP C, @loop | ||
| + | </ | ||
| + | |||
| + | This is a decrement-and-JNZ in one opcode. It is heavily inspired by the VAX instruction SOB (subtract one and branch) and the 68000' | ||
sd/isa.1778071378.txt.gz · Last modified: by appledog
