Fix up spec, split off to 6502 opcodes doc, add some tests.
Chris Pressey
6 years ago
24 | 24 | * [SixtyPical specification](doc/SixtyPical.md) |
25 | 25 | * [Literate test suite for SixtyPical execution](tests/SixtyPical Execution.md) |
26 | 26 | * [Literate test suite for SixtyPical analysis](tests/SixtyPical Analysis.md) |
27 | * [6502 Opcodes used/not used in SixtyPical](doc/6502 Opcodes.md) | |
27 | 28 | |
28 | 29 | TODO |
29 | 30 | ---- |
30 | ||
31 | For 0.2: | |
32 | ||
33 | * write a few more tests and clean up spec a bit. | |
34 | 31 | |
35 | 32 | For 0.3: |
36 | 33 |
0 | 6502 Opcodes | |
1 | ============ | |
2 | ||
3 | As used or unused in SixtyPical. | |
4 | ||
5 | ### ld ### | |
6 | ||
7 | ld a, 123 → LDA #123 | |
8 | ld a, lives → LDA LIVES | |
9 | ld x, 123 → LDX #123 | |
10 | ld x, lives → LDX LIVES | |
11 | ld y, 123 → LDY #123 | |
12 | ld y, lives → LDY LIVES | |
13 | ld x, a → TAX | |
14 | ld y, a → TAY | |
15 | ld a, x → TXA | |
16 | ld a, y → TYA | |
17 | ||
18 | ### st ### | |
19 | ||
20 | st a, lives → STA LIVES | |
21 | st x, lives → STX LIVES | |
22 | st y, lives → STY LIVES | |
23 | st on, c → SEC | |
24 | st off, c → CLC | |
25 | ||
26 | ### add dest, src ### | |
27 | ||
28 | add a, delta → ADC DELTA | |
29 | add a, 1 → ADC #1 | |
30 | ||
31 | ### inc ### | |
32 | ||
33 | inc x → INX | |
34 | inc y → INY | |
35 | inc lives → INC LIVES | |
36 | ||
37 | ### sub ### | |
38 | ||
39 | sub a, delta → SBC DELTA | |
40 | sub a, 1 → SBC #1 | |
41 | ||
42 | ### dec ### | |
43 | ||
44 | dec x → DEX | |
45 | dec y → DEY | |
46 | dec lives → DEC LIVES | |
47 | ||
48 | ### cmp ### | |
49 | ||
50 | cmp a, delta → CMP DELTA | |
51 | cmp a, 1 → CMP #1 | |
52 | cmp x, 1 → CPX #1 | |
53 | cmp y, 1 → CPY #1 | |
54 | ||
55 | ### and, or, xor ### | |
56 | ||
57 | and a, 8 → AND #8 | |
58 | or a, 8 → ORA #8 | |
59 | xor a, 8 → EOR #8 | |
60 | ||
61 | ### shl, shr ### | |
62 | ||
63 | shl <dest-memory-location> | |
64 | shr <dest-memory-location> | |
65 | ||
66 | shl a → ROL A | |
67 | shl lives → ROL LIVES | |
68 | shr a → ROR A | |
69 | shr lives → ROR LIVES | |
70 | ||
71 | ### call ### | |
72 | ||
73 | call routine → JSR ROUTINE | |
74 | ||
75 | ### if ### | |
76 | ||
77 | if z → BEQ LABEL | |
78 | if not z → BNE LABEL | |
79 | if n → BMI LABEL | |
80 | if not n → BPL LABEL | |
81 | if c → BCS LABEL | |
82 | if not c → BCC LABEL | |
83 | if v → BVS LABEL | |
84 | if not v → BVC LABEL | |
85 | ||
86 | ### 6502 instructions unsupported ### | |
87 | ||
88 | ASL Shift Left One Bit (Memory or Accumulator) | |
89 | LSR Shift Right One Bit (Memory or Accumulator) | |
90 | ||
91 | BIT Test Bits in Memory with Accumulator | |
92 | BRK Force Break | |
93 | ||
94 | CLD Clear Decimal Mode | |
95 | CLI Clear interrupt Disable Bit | |
96 | CLV Clear Overflow Flag | |
97 | ||
98 | NOP No Operation | |
99 | ||
100 | JMP Jump to New Location // but may be generated as part of `if` | |
101 | ||
102 | PHA Push Accumulator on Stack | |
103 | PHP Push Processor Status on Stack | |
104 | PLA Pull Accumulator from Stack | |
105 | PLP Pull Processor Status from Stack | |
106 | ||
107 | RTI Return from Interrupt | |
108 | RTS Return from Subroutine | |
109 | ||
110 | SED Set Decimal Mode | |
111 | SEI Set Interrupt Disable Status | |
112 | ||
113 | TSX Transfer Stack Pointer to Index X | |
114 | TXS Transfer Index X to Stack Pointer |
6 | 6 | |
7 | 7 | This document is nominally normative, but the tests in the `tests` directory |
8 | 8 | are even more normative. |
9 | ||
10 | Refer to the bottom of this document for an EBNF grammar of the syntax of | |
11 | the language. | |
9 | 12 | |
10 | 13 | Types |
11 | 14 | ----- |
121 | 124 | Some combinations, such as `ld x, y`, are illegal because they do not map to |
122 | 125 | underlying opcodes. |
123 | 126 | |
124 | Notes: | |
125 | ||
126 | ld a, 123 → LDA #123 | |
127 | ld a, lives → LDA LIVES | |
128 | ld x, 123 → LDX #123 | |
129 | ld x, lives → LDX LIVES | |
130 | ld y, 123 → LDY #123 | |
131 | ld y, lives → LDY LIVES | |
132 | ld x, a → TAX | |
133 | ld y, a → TAY | |
134 | ld a, x → TXA | |
135 | ld a, y → TYA | |
136 | ||
137 | 127 | ### st ### |
138 | 128 | |
139 | 129 | st <src-memory-location>, <dest-memory-location> |
149 | 139 | After execution, dest is considered initialized. No flags are |
150 | 140 | changed by this instruction (unless of course dest is a flag.) |
151 | 141 | |
152 | Notes: | |
153 | ||
154 | st a, lives → STA LIVES | |
155 | st x, lives → STX LIVES | |
156 | st y, lives → STY LIVES | |
157 | st on, c → SEC | |
158 | st off, c → CLC | |
159 | ||
160 | 142 | ### add dest, src ### |
161 | 143 | |
162 | 144 | add <dest-memory-location>, <src-memory-location> |
173 | 155 | |
174 | 156 | dest and src continue to be initialized afterwards. |
175 | 157 | |
176 | Notes: | |
177 | ||
178 | add a, delta → ADC DELTA | |
179 | add a, 1 → ADC #1 | |
180 | ||
181 | 158 | ### inc ### |
182 | 159 | |
183 | 160 | inc <dest-memory-location> |
192 | 169 | Affects n and z flags, requiring that they be in the WRITES lists, |
193 | 170 | and initializing them afterwards. |
194 | 171 | |
195 | Notes: | |
196 | ||
197 | inc x → INX | |
198 | inc y → INY | |
199 | inc lives → INC LIVES | |
200 | ||
201 | 172 | ### sub ### |
202 | 173 | |
203 | 174 | sub <dest-memory-location>, <src-memory-location> |
214 | 185 | |
215 | 186 | dest and src continue to be initialized afterwards. |
216 | 187 | |
217 | Notes: | |
218 | ||
219 | sub a, delta → SBC DELTA | |
220 | sub a, 1 → SBC #1 | |
221 | ||
222 | 188 | ### dec ### |
223 | 189 | |
224 | inc <dest-memory-location> | |
190 | dec <dest-memory-location> | |
225 | 191 | |
226 | 192 | Decrements the value in dest. Does not honour carry. |
227 | 193 | |
233 | 199 | Affects n and z flags, requiring that they be in the WRITES lists, |
234 | 200 | and initializing them afterwards. |
235 | 201 | |
236 | Notes: | |
237 | ||
238 | dec x → DEX | |
239 | dec y → DEY | |
240 | dec lives → DEC LIVES | |
241 | ||
242 | 202 | ### cmp ### |
243 | 203 | |
244 | 204 | cmp <dest-memory-location>, <src-memory-location> |
245 | 205 | |
246 | Subtracts the contents of src from dest, but does not store the result. | |
206 | Subtracts the contents of src from dest (without considering carry) but | |
207 | does not store the result anywhere, only sets the resulting flags. | |
247 | 208 | |
248 | 209 | * It is illegal if src OR dest is uninitialized. |
249 | 210 | |
250 | 211 | Affects n, z, and c flags, requiring that they be in the WRITES lists, |
251 | 212 | and initializing them afterwards. |
252 | ||
253 | Notes: | |
254 | ||
255 | cmp a, delta → CMP DELTA | |
256 | cmp a, 1 → CMP #1 | |
257 | cmp x, 1 → CPX #1 | |
258 | cmp y, 1 → CPY #1 | |
259 | 213 | |
260 | 214 | ### and, or, xor ### |
261 | 215 | |
276 | 230 | |
277 | 231 | dest and src continue to be initialized afterwards. |
278 | 232 | |
279 | Notes: | |
280 | ||
281 | and a, 8 → AND #8 | |
282 | or a, 8 → ORA #8 | |
283 | xor a, 8 → EOR #8 | |
284 | ||
285 | 233 | ### shl, shr ### |
286 | 234 | |
287 | 235 | shl <dest-memory-location> |
301 | 249 | |
302 | 250 | Affects the c flag, requiring that it be in the WRITES lists of the |
303 | 251 | current routine, and it continues to be initialized afterwards. |
304 | ||
305 | Notes: | |
306 | ||
307 | shl a → ROL A | |
308 | shl lives → ROL LIVES | |
309 | shr a → ROR A | |
310 | shr lives → ROR LIVES | |
311 | 252 | |
312 | 253 | ### call ### |
313 | 254 | |
325 | 266 | * All memory locations listed as TRASHED in the called routine's OUTPUTS |
326 | 267 | list are considered initialized. |
327 | 268 | |
328 | Notes: | |
329 | ||
330 | call routine → JSR ROUTINE | |
331 | ||
332 | - - - - | |
333 | ||
334 | 269 | ### if ### |
335 | 270 | |
336 | if (bit) { | |
337 | true-branch | |
271 | if <src-memory-location> { | |
272 | <true-branch> | |
338 | 273 | } else { |
339 | false-branch | |
274 | <false-branch> | |
340 | 275 | } |
341 | 276 | |
342 | _bit_ is usually one of the flags, z or c. | |
343 | ||
344 | Notes: | |
345 | ||
346 | BEQ Branch on Result Zero | |
347 | BMI Branch on Result Minus | |
348 | BNE Branch on Result not Zero | |
349 | BPL Branch on Result Plus | |
350 | BCC Branch on Carry Clear | |
351 | BCS Branch on Carry Set | |
352 | BVC Branch on Overflow Clear | |
353 | BVS Branch on Overflow Set | |
354 | ||
355 | ||
356 | - - - - | |
277 | Executes the true-branch if the value in src is nonzero, otherwise executes | |
278 | the false-branch. The false-branch is optional may be omitted; in this case | |
279 | it is treated like an empty block. | |
280 | ||
281 | * It is illegal if src is not z, c, n, or v. | |
282 | * It is illegal if src is not initialized. | |
283 | * It is illegal if any location initialized at the end of the true-branch | |
284 | is not initialized at the end of the false-branch, and vice versa. | |
357 | 285 | |
358 | 286 | Grammar |
359 | 287 | ------- |
383 | 311 | | "dec" LocExpr |
384 | 312 | | "call" RoutineIdent |
385 | 313 | | "if" LocExpr Block ["else" Block]. |
386 | ||
387 | ||
388 | ### 6502 instructions unsupported ### | |
389 | ||
390 | ASL Shift Left One Bit (Memory or Accumulator) | |
391 | LSR Shift Right One Bit (Memory or Accumulator) | |
392 | ||
393 | BIT Test Bits in Memory with Accumulator | |
394 | BRK Force Break | |
395 | ||
396 | CLD Clear Decimal Mode | |
397 | CLI Clear interrupt Disable Bit | |
398 | CLV Clear Overflow Flag | |
399 | ||
400 | NOP No Operation | |
401 | ||
402 | JMP Jump to New Location // but may be generated as part of `if` | |
403 | ||
404 | PHA Push Accumulator on Stack | |
405 | PHP Push Processor Status on Stack | |
406 | PLA Pull Accumulator from Stack | |
407 | PLP Pull Processor Status from Stack | |
408 | ||
409 | RTI Return from Interrupt | |
410 | RTS Return from Subroutine | |
411 | ||
412 | SED Set Decimal Mode | |
413 | SEI Set Interrupt Disable Status | |
414 | ||
415 | TSX Transfer Stack Pointer to Index X | |
416 | TXS Transfer Index X to Stack Pointer |
241 | 241 | | } |
242 | 242 | ? IllegalWriteError: a |
243 | 243 | |
244 | ### ... many missing tests ... ### | |
244 | ### sub ### | |
245 | ||
246 | Can't `sub` from or to a memory location that isn't initialized. | |
247 | ||
248 | | routine main | |
249 | | inputs a | |
250 | | outputs a | |
251 | | trashes c, z, v, n | |
252 | | { | |
253 | | st off, c | |
254 | | sub a, 0 | |
255 | | } | |
256 | = ok | |
257 | ||
258 | | byte lives | |
259 | | routine main | |
260 | | inputs a | |
261 | | outputs a | |
262 | | trashes c, z, v, n | |
263 | | { | |
264 | | st off, c | |
265 | | sub a, lives | |
266 | | } | |
267 | ? UninitializedAccessError: lives | |
268 | ||
269 | | byte lives | |
270 | | routine main | |
271 | | inputs lives | |
272 | | outputs a | |
273 | | trashes c, z, v, n | |
274 | | { | |
275 | | st off, c | |
276 | | sub a, lives | |
277 | | } | |
278 | ? UninitializedAccessError: a | |
279 | ||
280 | Can't `sub` to a memory location that isn't writeable. | |
281 | ||
282 | | routine main | |
283 | | inputs a | |
284 | | trashes c | |
285 | | { | |
286 | | st off, c | |
287 | | sub a, 0 | |
288 | | } | |
289 | ? IllegalWriteError: a | |
290 | ||
291 | ### inc ### | |
292 | ||
293 | Location must be initialized and writeable. | |
294 | ||
295 | | routine main | |
296 | | outputs x | |
297 | | trashes z, n | |
298 | | { | |
299 | | inc x | |
300 | | } | |
301 | ? UninitializedAccessError: x | |
302 | ||
303 | | routine main | |
304 | | inputs x | |
305 | | trashes z, n | |
306 | | { | |
307 | | inc x | |
308 | | } | |
309 | ? IllegalWriteError: x | |
310 | ||
311 | | routine main | |
312 | | inputs x | |
313 | | outputs x | |
314 | | trashes z, n | |
315 | | { | |
316 | | inc x | |
317 | | } | |
318 | = ok | |
319 | ||
320 | ### dec ### | |
321 | ||
322 | Location must be initialized and writeable. | |
323 | ||
324 | | routine main | |
325 | | outputs x | |
326 | | trashes z, n | |
327 | | { | |
328 | | dec x | |
329 | | } | |
330 | ? UninitializedAccessError: x | |
331 | ||
332 | | routine main | |
333 | | inputs x | |
334 | | trashes z, n | |
335 | | { | |
336 | | dec x | |
337 | | } | |
338 | ? IllegalWriteError: x | |
339 | ||
340 | | routine main | |
341 | | inputs x | |
342 | | outputs x | |
343 | | trashes z, n | |
344 | | { | |
345 | | dec x | |
346 | | } | |
347 | = ok | |
348 | ||
349 | ### cmp ### | |
350 | ||
351 | TODO: write some tests | |
352 | ||
353 | ### and ### | |
354 | ||
355 | TODO: write some tests | |
356 | ||
357 | ### or ### | |
358 | ||
359 | TODO: write some tests | |
360 | ||
361 | ### xor ### | |
362 | ||
363 | TODO: write some tests | |
364 | ||
365 | ### shl ### | |
366 | ||
367 | TODO: write some tests | |
368 | ||
369 | ### shr ### | |
370 | ||
371 | TODO: write some tests | |
245 | 372 | |
246 | 373 | ### call ### |
247 | 374 |