|
| 1 | +DCPU-16 Specification |
| 2 | +Copyright 1985 Mojang |
| 3 | +Version 1.7 |
| 4 | + |
| 5 | + |
| 6 | + |
| 7 | +=== SUMMARY ==================================================================== |
| 8 | + |
| 9 | +* 16 bit words |
| 10 | +* 0x10000 words of ram |
| 11 | +* 8 registers (A, B, C, X, Y, Z, I, J) |
| 12 | +* program counter (PC) |
| 13 | +* stack pointer (SP) |
| 14 | +* extra/excess (EX) |
| 15 | +* interrupt address (IA) |
| 16 | + |
| 17 | +In this document, anything within [brackets] is shorthand for "the value of the |
| 18 | +RAM at the location of the value inside the brackets". For example, SP means |
| 19 | +stack pointer, but [SP] means the value of the RAM at the location the stack |
| 20 | +pointer is pointing at. |
| 21 | + |
| 22 | +Whenever the CPU needs to read a word, it reads [PC], then increases PC by one. |
| 23 | +Shorthand for this is [PC++]. In some cases, the CPU will modify a value before |
| 24 | +reading it, in this case the shorthand is [++PC]. |
| 25 | + |
| 26 | +For stability and to reduce bugs, it's strongly suggested all multi-word |
| 27 | +operations use little endian in all DCPU-16 programs, wherever possible. |
| 28 | + |
| 29 | + |
| 30 | + |
| 31 | +=== INSTRUCTIONS =============================================================== |
| 32 | + |
| 33 | +Instructions are 1-3 words long and are fully defined by the first word. |
| 34 | +In a basic instruction, the lower five bits of the first word of the instruction |
| 35 | +are the opcode, and the remaining eleven bits are split into a five bit value b |
| 36 | +and a six bit value a. |
| 37 | +b is always handled by the processor after a, and is the lower five bits. |
| 38 | +In bits (in LSB-0 format), a basic instruction has the format: aaaaaabbbbbooooo |
| 39 | + |
| 40 | +In the tables below, C is the time required in cycles to look up the value, or |
| 41 | +perform the opcode, VALUE is the numerical value, NAME is the mnemonic, and |
| 42 | +DESCRIPTION is a short text that describes the opcode or value. |
| 43 | + |
| 44 | + |
| 45 | + |
| 46 | +--- Values: (5/6 bits) --------------------------------------------------------- |
| 47 | + C | VALUE | DESCRIPTION |
| 48 | +---+-----------+---------------------------------------------------------------- |
| 49 | + 0 | 0x00-0x07 | register (A, B, C, X, Y, Z, I or J, in that order) |
| 50 | + 0 | 0x08-0x0f | [register] |
| 51 | + 1 | 0x10-0x17 | [register + next word] |
| 52 | + 0 | 0x18 | (PUSH / [--SP]) if in b, or (POP / [SP++]) if in a |
| 53 | + 0 | 0x19 | [SP] / PEEK |
| 54 | + 1 | 0x1a | [SP + next word] / PICK n |
| 55 | + 0 | 0x1b | SP |
| 56 | + 0 | 0x1c | PC |
| 57 | + 0 | 0x1d | EX |
| 58 | + 1 | 0x1e | [next word] |
| 59 | + 1 | 0x1f | next word (literal) |
| 60 | + 0 | 0x20-0x3f | literal value 0xffff-0x1e (-1..30) (literal) (only for a) |
| 61 | + --+-----------+---------------------------------------------------------------- |
| 62 | + |
| 63 | +* "next word" means "[PC++]". Increases the word length of the instruction by 1. |
| 64 | +* By using 0x18, 0x19, 0x1a as PEEK, POP/PUSH, and PICK there's a reverse stack |
| 65 | + starting at memory location 0xffff. Example: "SET PUSH, 10", "SET X, POP" |
| 66 | +* Attempting to write to a literal value fails silently |
| 67 | + |
| 68 | + |
| 69 | + |
| 70 | +--- Basic opcodes (5 bits) ---------------------------------------------------- |
| 71 | + C | VAL | NAME | DESCRIPTION |
| 72 | +---+------+----------+--------------------------------------------------------- |
| 73 | + - | 0x00 | n/a | special instruction - see below |
| 74 | + 1 | 0x01 | SET b, a | sets b to a |
| 75 | + 2 | 0x02 | ADD b, a | sets b to b+a, sets EX to 0x0001 if there's an overflow, |
| 76 | + | | | 0x0 otherwise |
| 77 | + 2 | 0x03 | SUB b, a | sets b to b-a, sets EX to 0xffff if there's an underflow, |
| 78 | + | | | 0x0 otherwise |
| 79 | + 2 | 0x04 | MUL b, a | sets b to b*a, sets EX to ((b*a)>>16)&0xffff (treats b, |
| 80 | + | | | a as unsigned) |
| 81 | + 2 | 0x05 | MLI b, a | like MUL, but treat b, a as signed |
| 82 | + 3 | 0x06 | DIV b, a | sets b to b/a, sets EX to ((b<<16)/a)&0xffff. if a==0, |
| 83 | + | | | sets b and EX to 0 instead. (treats b, a as unsigned) |
| 84 | + 3 | 0x07 | DVI b, a | like DIV, but treat b, a as signed. Rounds towards 0 |
| 85 | + 3 | 0x08 | MOD b, a | sets b to b%a. if a==0, sets b to 0 instead. |
| 86 | + 3 | 0x09 | MDI b, a | like MOD, but treat b, a as signed. (MDI -7, 16 == -7) |
| 87 | + 1 | 0x0a | AND b, a | sets b to b&a |
| 88 | + 1 | 0x0b | BOR b, a | sets b to b|a |
| 89 | + 1 | 0x0c | XOR b, a | sets b to b^a |
| 90 | + 1 | 0x0d | SHR b, a | sets b to b>>>a, sets EX to ((b<<16)>>a)&0xffff |
| 91 | + | | | (logical shift) |
| 92 | + 1 | 0x0e | ASR b, a | sets b to b>>a, sets EX to ((b<<16)>>>a)&0xffff |
| 93 | + | | | (arithmetic shift) (treats b as signed) |
| 94 | + 1 | 0x0f | SHL b, a | sets b to b<<a, sets EX to ((b<<a)>>16)&0xffff |
| 95 | + |
| 96 | + 2+| 0x10 | IFB b, a | performs next instruction only if (b&a)!=0 |
| 97 | + 2+| 0x11 | IFC b, a | performs next instruction only if (b&a)==0 |
| 98 | + 2+| 0x12 | IFE b, a | performs next instruction only if b==a |
| 99 | + 2+| 0x13 | IFN b, a | performs next instruction only if b!=a |
| 100 | + 2+| 0x14 | IFG b, a | performs next instruction only if b>a |
| 101 | + 2+| 0x15 | IFA b, a | performs next instruction only if b>a (signed) |
| 102 | + 2+| 0x16 | IFL b, a | performs next instruction only if b<a |
| 103 | + 2+| 0x17 | IFU b, a | performs next instruction only if b<a (signed) |
| 104 | + - | 0x18 | - | |
| 105 | + - | 0x19 | - | |
| 106 | + 3 | 0x1a | ADX b, a | sets b to b+a+EX, sets EX to 0x0001 if there is an over- |
| 107 | + | | | flow, 0x0 otherwise |
| 108 | + 3 | 0x1b | SBX b, a | sets b to b-a+EX, sets EX to 0xFFFF if there is an under- |
| 109 | + | | | flow, 0x0 otherwise |
| 110 | + - | 0x1c | - | |
| 111 | + - | 0x1d | - | |
| 112 | + 2 | 0x1e | STI b, a | sets b to a, then increases I and J by 1 |
| 113 | + 2 | 0x1f | STD b, a | sets b to a, then decreases I and J by 1 |
| 114 | +---+------+----------+---------------------------------------------------------- |
| 115 | + |
| 116 | +* The branching opcodes take one cycle longer to perform if the test fails |
| 117 | + When they skip an if instruction, they will skip an additional instruction |
| 118 | + at the cost of one extra cycle. This lets you easily chain conditionals. |
| 119 | +* Signed numbers are represented using two's complement. |
| 120 | + |
| 121 | + |
| 122 | +Special opcodes always have their lower five bits unset, have one value and a |
| 123 | +five bit opcode. In binary, they have the format: aaaaaaooooo00000 |
| 124 | +The value (a) is in the same six bit format as defined earlier. |
| 125 | + |
| 126 | +--- Special opcodes: (5 bits) -------------------------------------------------- |
| 127 | + C | VAL | NAME | DESCRIPTION |
| 128 | +---+------+-------+------------------------------------------------------------- |
| 129 | + - | 0x00 | n/a | reserved for future expansion |
| 130 | + 3 | 0x01 | JSR a | pushes the address of the next instruction to the stack, |
| 131 | + | | | then sets PC to a |
| 132 | + - | 0x02 | - | |
| 133 | + - | 0x03 | - | |
| 134 | + - | 0x04 | - | |
| 135 | + - | 0x05 | - | |
| 136 | + - | 0x06 | - | |
| 137 | + - | 0x07 | - | |
| 138 | + 4 | 0x08 | INT a | triggers a software interrupt with message a |
| 139 | + 1 | 0x09 | IAG a | sets a to IA |
| 140 | + 1 | 0x0a | IAS a | sets IA to a |
| 141 | + 3 | 0x0b | RFI a | disables interrupt queueing, pops A from the stack, then |
| 142 | + | | | pops PC from the stack |
| 143 | + 2 | 0x0c | IAQ a | if a is nonzero, interrupts will be added to the queue |
| 144 | + | | | instead of triggered. if a is zero, interrupts will be |
| 145 | + | | | triggered as normal again |
| 146 | + - | 0x0d | - | |
| 147 | + - | 0x0e | - | |
| 148 | + - | 0x0f | - | |
| 149 | + 2 | 0x10 | HWN a | sets a to number of connected hardware devices |
| 150 | + 4 | 0x11 | HWQ a | sets A, B, C, X, Y registers to information about hardware a |
| 151 | + | | | A+(B<<16) is a 32 bit word identifying the hardware id |
| 152 | + | | | C is the hardware version |
| 153 | + | | | X+(Y<<16) is a 32 bit word identifying the manufacturer |
| 154 | + 4+| 0x12 | HWI a | sends an interrupt to hardware a |
| 155 | + - | 0x13 | - | |
| 156 | + - | 0x14 | - | |
| 157 | + - | 0x15 | - | |
| 158 | + - | 0x16 | - | |
| 159 | + - | 0x17 | - | |
| 160 | + - | 0x18 | - | |
| 161 | + - | 0x19 | - | |
| 162 | + - | 0x1a | - | |
| 163 | + - | 0x1b | - | |
| 164 | + - | 0x1c | - | |
| 165 | + - | 0x1d | - | |
| 166 | + - | 0x1e | - | |
| 167 | + - | 0x1f | - | |
| 168 | +---+------+-------+------------------------------------------------------------- |
| 169 | + |
| 170 | + |
| 171 | + |
| 172 | +=== INTERRUPTS ================================================================= |
| 173 | + |
| 174 | +The DCPU-16 will perform at most one interrupt between each instruction. If |
| 175 | +multiple interrupts are triggered at the same time, they are added to a queue. |
| 176 | +If the queue grows longer than 256 interrupts, the DCPU-16 will catch fire. |
| 177 | + |
| 178 | +When IA is set to something other than 0, interrupts triggered on the DCPU-16 |
| 179 | +will turn on interrupt queueing, push PC to the stack, followed by pushing A to |
| 180 | +the stack, then set the PC to IA, and A to the interrupt message. |
| 181 | + |
| 182 | +If IA is set to 0, a triggered interrupt does nothing. Software interrupts still |
| 183 | +take up four clock cycles, but immediately return, incoming hardware interrupts |
| 184 | +are ignored. Note that a queued interrupt is considered triggered when it leaves |
| 185 | +the queue, not when it enters it. |
| 186 | + |
| 187 | +Interrupt handlers should end with RFI, which will disable interrupt queueing |
| 188 | +and pop A and PC from the stack as a single atomic instruction. |
| 189 | +IAQ is normally not needed within an interrupt handler, but is useful for time |
| 190 | +critical code. |
| 191 | + |
| 192 | + |
| 193 | + |
| 194 | + |
| 195 | +=== HARDWARE =================================================================== |
| 196 | + |
| 197 | +The DCPU-16 supports up to 65535 connected hardware devices. These devices can |
| 198 | +be anything from additional storage, sensors, monitors or speakers. |
| 199 | +How to control the hardware is specified per hardware device, but the DCPU-16 |
| 200 | +supports a standard enumeration method for detecting connected hardware via |
| 201 | +the HWN, HWQ and HWI instructions. |
| 202 | + |
| 203 | +Interrupts sent to hardware can't contain messages, can take additional cycles, |
| 204 | +and can read or modify any registers or memory adresses on the DCPU-16. This |
| 205 | +behavior changes per hardware device and is described in the hardware's |
| 206 | +documentation. |
| 207 | + |
| 208 | +Hardware must NOT start modifying registers or ram on the DCPU-16 before at |
| 209 | +least one HWI call has been made to the hardware. |
| 210 | + |
| 211 | +The DPCU-16 does not support hot swapping hardware. The behavior of connecting |
| 212 | +or disconnecting hardware while the DCPU-16 is running is undefined. |
0 commit comments