2e99ed2ce83be0a3f54d1d742646ea19df06a1c9
[dcpu16] / docs / dcpu-16.txt
1 DCPU-16 Specification
2 Copyright 2012 Mojang
3 Version 1.1 (Check 0x10c.com for updated versions)
4
5 * 16 bit unsigned words
6 * 0x10000 words of ram
7 * 8 registers (A, B, C, X, Y, Z, I, J)
8 * program counter (PC)
9 * stack pointer (SP)
10 * overflow (O)
11
12 In this document, anything within [brackets] is shorthand for "the value of the RAM at the location of the value inside the brackets".
13 For example, SP means stack pointer, but [SP] means the value of the RAM at the location the stack pointer is pointing at.
14
15 Whenever the CPU needs to read a word, it reads [PC], then increases PC by one. Shorthand for this is [PC++].
16 In some cases, the CPU will modify a value before reading it, in this case the shorthand is [++PC].
17
18 Instructions are 1-3 words long and are fully defined by the first word.
19 In a basic instruction, the lower four bits of the first word of the instruction are the opcode,
20 and the remaining twelve bits are split into two six bit values, called a and b.
21 a is always handled by the processor before b, and is the lower six bits.
22 In bits (with the least significant being last), a basic instruction has the format: bbbbbbaaaaaaoooo
23
24
25
26 Values: (6 bits)
27 0x00-0x07: register (A, B, C, X, Y, Z, I or J, in that order)
28 0x08-0x0f: [register]
29 0x10-0x17: [next word + register]
30 0x18: POP / [SP++]
31 0x19: PEEK / [SP]
32 0x1a: PUSH / [--SP]
33 0x1b: SP
34 0x1c: PC
35 0x1d: O
36 0x1e: [next word]
37 0x1f: next word (literal)
38 0x20-0x3f: literal value 0x00-0x1f (literal)
39
40 * "next word" really means "[PC++]". These increase the word length of the instruction by 1.
41 * If any instruction tries to assign a literal value, the assignment fails silently. Other than that, the instruction behaves as normal.
42 * All values that read a word (0x10-0x17, 0x1e, and 0x1f) take 1 cycle to look up. The rest take 0 cycles.
43 * By using 0x18, 0x19, 0x1a as POP, PEEK and PUSH, there's a reverse stack starting at memory location 0xffff. Example: "SET PUSH, 10", "SET X, POP"
44
45
46
47 Basic opcodes: (4 bits)
48 0x0: non-basic instruction - see below
49 0x1: SET a, b - sets a to b
50 0x2: ADD a, b - sets a to a+b, sets O to 0x0001 if there's an overflow, 0x0 otherwise
51 0x3: SUB a, b - sets a to a-b, sets O to 0xffff if there's an underflow, 0x0 otherwise
52 0x4: MUL a, b - sets a to a*b, sets O to ((a*b)>>16)&0xffff
53 0x5: DIV a, b - sets a to a/b, sets O to ((a<<16)/b)&0xffff. if b==0, sets a and O to 0 instead.
54 0x6: MOD a, b - sets a to a%b. if b==0, sets a to 0 instead.
55 0x7: SHL a, b - sets a to a<<b, sets O to ((a<<b)>>16)&0xffff
56 0x8: SHR a, b - sets a to a>>b, sets O to ((a<<16)>>b)&0xffff
57 0x9: AND a, b - sets a to a&b
58 0xa: BOR a, b - sets a to a|b
59 0xb: XOR a, b - sets a to a^b
60 0xc: IFE a, b - performs next instruction only if a==b
61 0xd: IFN a, b - performs next instruction only if a!=b
62 0xe: IFG a, b - performs next instruction only if a>b
63 0xf: IFB a, b - performs next instruction only if (a&b)!=0
64
65 * SET, AND, BOR and XOR take 1 cycle, plus the cost of a and b
66 * ADD, SUB, MUL, SHR, and SHL take 2 cycles, plus the cost of a and b
67 * DIV and MOD take 3 cycles, plus the cost of a and b
68 * IFE, IFN, IFG, IFB take 2 cycles, plus the cost of a and b, plus 1 if the test fails
69
70
71
72 Non-basic opcodes always have their lower four bits unset, have one value and a six bit opcode.
73 In binary, they have the format: aaaaaaoooooo0000
74 The value (a) is in the same six bit format as defined earlier.
75
76 Non-basic opcodes: (6 bits)
77 0x00: reserved for future expansion
78 0x01: JSR a - pushes the address of the next instruction to the stack, then sets PC to a
79 0x02-0x3f: reserved
80
81 * JSR takes 2 cycles, plus the cost of a.
82
83
84
85 FAQ:
86
87 Q: Why is there no JMP or RET?
88 A: They're not needed! "SET PC, <target>" is a one-instruction JMP.
89 For small relative jumps in a single word, you can even do "ADD PC, <dist>" or "SUB PC, <dist>".
90 For RET, simply do "SET PC, POP"
91
92 Q: How does the overflow (O) work?
93 A: O is set by certain instructions (see above), but never automatically read. You can use its value in instructions, however.
94 For example, to do a 32 bit add of 0x12345678 and 0xaabbccdd, do this:
95 SET [0x1000], 0x5678 ; low word
96 SET [0x1001], 0x1234 ; high word
97 ADD [0x1000], 0xccdd ; add low words, sets O to either 0 or 1 (in this case 1)
98 ADD [0x1001], O ; add O to the high word
99 ADD [0x1001], 0xaabb ; add high words, sets O again (to 0, as 0xaabb+0x1235 is lower than 0x10000)
100
101 Q: How do I do 32 or 64 bit division using O?
102 A: This is left as an exercise for the reader.
103
104 Q: How about a quick example?
105 A: Sure! Here's some sample assembler, and a memory dump of the compiled code:
106
107 ; Try some basic stuff
108 SET A, 0x30 ; 7c01 0030
109 SET [0x1000], 0x20 ; 7de1 1000 0020
110 SUB A, [0x1000] ; 7803 1000
111 IFN A, 0x10 ; c00d
112 SET PC, crash ; 7dc1 001a [*]
113
114 ; Do a loopy thing
115 SET I, 10 ; a861
116 SET A, 0x2000 ; 7c01 2000
117 :loop SET [0x2000+I], [A] ; 2161 2000
118 SUB I, 1 ; 8463
119 IFN I, 0 ; 806d
120 SET PC, loop ; 7dc1 000d [*]
121
122 ; Call a subroutine
123 SET X, 0x4 ; 9031
124 JSR testsub ; 7c10 0018 [*]
125 SET PC, crash ; 7dc1 001a [*]
126
127 :testsub SHL X, 4 ; 9037
128 SET PC, POP ; 61c1
129
130 ; Hang forever. X should now be 0x40 if everything went right.
131 :crash SET PC, crash ; 7dc1 001a [*]
132
133 ; [*]: Note that these can be one word shorter and one cycle faster by using the short form (0x00-0x1f) of literals,
134 ; but my assembler doesn't support short form labels yet.
135
136 Full memory dump:
137
138 0000: 7c01 0030 7de1 1000 0020 7803 1000 c00d
139 0008: 7dc1 001a a861 7c01 2000 2161 2000 8463
140 0010: 806d 7dc1 000d 9031 7c10 0018 7dc1 001a
141 0018: 9037 61c1 7dc1 001a 0000 0000 0000 0000
142