Mercurial > hg > Applications > Tokio
comparison Examples/6502/isp.mc6502 @ 0:cfb7c6b24319
Initial revision
author | kono |
---|---|
date | Thu, 30 Aug 2007 14:57:44 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:cfb7c6b24319 |
---|---|
1 ! ISPS Description of the MOS Technology MCS 6502 Microprocessor | |
2 | |
3 ! G.W.Leive | |
4 ! 10 July 1978 ISPS Version | |
5 ! COPYRIGHT (C) 1978 | |
6 | |
7 MC6502 := | |
8 BEGIN | |
9 | |
10 **MP.STATE** | |
11 MACRO romlow:= |"F800 |, | |
12 MACRO romhi := |"FFFF |, | |
13 MACRO ramlow:= |"0000 |, | |
14 MACRO ramhi := |"1000 |, | |
15 MACRO maxb := |"FFFF |, ! High end of byte memory | |
16 | |
17 Mb[0:maxb]<7:0>, ! Primary memory range | |
18 ram[ramlow:ramhi]<7:0> := mb[ramlow:ramhi]<7:0>, ! RAM | |
19 rom[romlow:romhi]<7:0> := mb[romlow:romhi]<7:0> ! ROM | |
20 | |
21 **PC.STATE** | |
22 | |
23 Pc<15:0>, ! Program counter | |
24 | |
25 Y<7:0>, ! Index register | |
26 X<7:0>, ! Index register | |
27 S<7:0>, ! Stack pointer | |
28 Dl<7:0>, ! Input data latch | |
29 A<7:0>, ! Accumulator | |
30 Ir<7:0>, ! Instruction register | |
31 P<7:0>, ! Processor status | |
32 n<> := P<7>, ! Negative result | |
33 v<> := P<6>, ! Overflow | |
34 b<> := P<4>, ! Break command | |
35 d<> := P<3>, ! Decimal mode | |
36 i<> := P<2>, ! Interrupt disable | |
37 z<> := P<1>, ! Zero | |
38 c<> := P<0>, ! Carry | |
39 | |
40 Irq<>, ! Interrupt request | |
41 Nmi<>, ! Non-maskable interrupt | |
42 IFSync<>, ! High when instruction fetch | |
43 Rw<>, ! Read/Write control pin | |
44 So<>, ! Set overflow pin | |
45 Reset<>, ! Power up bit | |
46 Ready<> ! 1 means run, 0 means stop | |
47 | |
48 **ADDRESS.CALCULATION** | |
49 | |
50 immed()<15:0> := ! Immediate | |
51 BEGIN | |
52 immed = ab = Pc NEXT | |
53 Pc = Pc + 1 | |
54 END, | |
55 | |
56 zp()<15:0> := ! Zero page | |
57 BEGIN | |
58 zp = ab = read(Pc) NEXT | |
59 Pc = Pc + 1 | |
60 END, | |
61 | |
62 abs()<15:0> := ! Absolute | |
63 BEGIN | |
64 abs = ab(Pc + 1, Pc) NEXT | |
65 Pc = Pc + 2 | |
66 END, | |
67 | |
68 indx()<15:0> := ! Indexed indirect - (IND, X) | |
69 BEGIN | |
70 indx = ab((read(Pc) + X + 1)<7:0>, (read(Pc) + X)<7:0>) NEXT | |
71 Pc = Pc + 1 | |
72 END, | |
73 | |
74 indy()<15:0> := ! Indirect indexed - (IND), Y | |
75 BEGIN | |
76 indy = ab = ab(read(Pc) + 1, read(Pc)) + Y NEXT | |
77 Pc = Pc + 1 | |
78 END, | |
79 | |
80 zpx()<15:0> := ! Zero page indexed by X | |
81 BEGIN | |
82 zpx = ab = (read(Pc) + X)<7:0> NEXT | |
83 Pc = Pc + 1 | |
84 END, | |
85 | |
86 zpy()<15:0> := ! Zero page indexed by Y | |
87 BEGIN | |
88 zpy = ab = (read(Pc) + Y)<7:0> NEXT | |
89 Pc = Pc + 1 | |
90 END, | |
91 | |
92 | |
93 absy()<15:0> := ! Absolute modified by Y | |
94 BEGIN | |
95 absy = ab = ab(Pc + 1, Pc) + Y NEXT | |
96 Pc = Pc + 2 | |
97 END, | |
98 | |
99 absx()<15:0> := ! Ablolute modified by X | |
100 BEGIN | |
101 absx = ab = ab(Pc + 1, Pc) + X NEXT | |
102 Pc = Pc + 2 | |
103 END | |
104 | |
105 **SERVICE.FACILITIES** | |
106 | |
107 push(dbb.<7:0>) := ! Push a byte on the stack | |
108 BEGIN | |
109 write(1@S, dbb.) NEXT | |
110 S = S - 1 | |
111 END, | |
112 | |
113 pull<7:0> := ! Pull a byte off the stack | |
114 BEGIN | |
115 S = S + 1 NEXT | |
116 pull = read(1@S) | |
117 END, | |
118 | |
119 opex := ! Operation exception | |
120 BEGIN | |
121 Ready = 0 NEXT | |
122 RESTART run | |
123 END, | |
124 | |
125 setnz(ta.<7:0>) := ! Set neg and zero condition code | |
126 BEGIN | |
127 z = ta. EQL 0; n = ta.<7> | |
128 END, | |
129 | |
130 branch(cond<>) := | |
131 BEGIN | |
132 DECODE cond => | |
133 BEGIN | |
134 0 := Pc = Pc + 1, | |
135 1 := Pc = (Pc + 1) + read(PC) ! Relative addressing | |
136 END | |
137 END, | |
138 | |
139 decimal.adjust(tac.<8:0>) := ! Used by sbc and adc | |
140 BEGIN | |
141 IF A<7> EQV read<7> => v = tac.<7> XOR A<7>; c = tac.<8> NEXT | |
142 IF d => | |
143 BEGIN | |
144 tac.<8> = 0 NEXT | |
145 IF tac.<3:0> GTR{US} "9 => tac. = tac.<7:0> + "6 NEXT | |
146 IF NOT c => c = tac.<8> NEXT | |
147 IF tac.<7:4> GTR{US} "9 => tac. = tac.<7:0> + "60 NEXT | |
148 IF NOT c => c = tac.<8> | |
149 END NEXT | |
150 A = tac.<7:0> NEXT | |
151 setnz(A) | |
152 END, | |
153 | |
154 ab(adh.<15:0>, adl.<15:0>)<15:0> := ! Address buffer | |
155 BEGIN | |
156 ab<15:8> = read(adh.) NEXT | |
157 ab<7:0> = read(adl.) | |
158 END, | |
159 | |
160 ! Read and write memory access routines | |
161 | |
162 read(ab.<15:0>)<7:0> := ! Read from valid memory | |
163 BEGIN | |
164 Rw = 1 NEXT | |
165 IF NOT Ready => RESTART run NEXT | |
166 read = "FF NEXT ! Fake a nonexistant memory access | |
167 IF (ab. GEQ{US} ramlow) AND (ab. LEQ{US} ramhi) => read = ram[ab.]; | |
168 IF (ab. GEQ{US} romlow) AND (ab. LEQ{US} romhi) => read = rom[ab.] | |
169 END, | |
170 | |
171 write(ab.<15:0>, dbb.<7:0>) := ! Write to valid memory | |
172 BEGIN | |
173 IF (ab. GEQ{US} ramlow) AND (ab. LEQ{US} ramhi) => ram[ab.] = dbb.; | |
174 Rw = 0 | |
175 END, | |
176 | |
177 ! Interrupt routines | |
178 | |
179 intstk := ! Interrupt stack operations | |
180 BEGIN | |
181 push(Pc<15:8>) NEXT | |
182 push(Pc<7:0>) NEXT | |
183 push(P) NEXT | |
184 i = 1 | |
185 END, | |
186 | |
187 int := ! Interrupt processing | |
188 BEGIN | |
189 IF NOT Reset => | |
190 BEGIN | |
191 Reset = Irq = Nmi = Ready = 1 NEXT | |
192 Pc = ab("FFFD, "FFFC) NEXT | |
193 i = 1 NEXT | |
194 LEAVE int | |
195 END NEXT | |
196 | |
197 IF NOT Nmi => | |
198 BEGIN | |
199 Nmi = 1 NEXT | |
200 intstk() NEXT | |
201 Pc = ab("FFFB, "FFFA) NEXT | |
202 LEAVE int | |
203 END NEXT | |
204 | |
205 IF b OR (NOT Irq AND NOT i) => | |
206 BEGIN | |
207 intstk() NEXT | |
208 b = 0 NEXT | |
209 Pc = ab("FFFF, "FFFE) | |
210 END | |
211 END | |
212 | |
213 **INSTRUCTION.INTERPRETATION** | |
214 | |
215 run := | |
216 BEGIN | |
217 IF NOT Reset => int() NEXT ! Initial startup | |
218 IF NOT ready => stop() NEXT | |
219 IFSync = 1 NEXT ! Instruction fetch | |
220 Ir = read(Pc) NEXT | |
221 Pc = Pc + 1 NEXT | |
222 IFSync = 0 NEXT ! Execute | |
223 DECODE IR<1:0> => | |
224 BEGIN | |
225 '01 := group1(), | |
226 '10 := group2(), | |
227 '00 := group3(), | |
228 '11 := opex() | |
229 END NEXT | |
230 int() NEXT | |
231 IF So => v = 1 NEXT | |
232 RESTART RUN | |
233 END, | |
234 | |
235 ! Group 1 instruction decode | |
236 | |
237 group1 := | |
238 BEGIN | |
239 DECODE Ir<7:5> => | |
240 BEGIN | |
241 #0 := ora(), | |
242 #1 := and.(), | |
243 #2 := eor(), | |
244 #3 := adc(), | |
245 #4 := sta(), | |
246 #5 := lda(), | |
247 #6 := cmp(), | |
248 #7 := sbc() | |
249 END | |
250 END, | |
251 | |
252 ! Group 2 instruction decode | |
253 | |
254 group2 := | |
255 BEGIN | |
256 DECODE Ir<7:5> => | |
257 BEGIN | |
258 #0 := asl(), | |
259 #1 := rol(), | |
260 #2 := lsr(), | |
261 #3 := ror(), | |
262 #4 := stx(), ! Includes txa, txs | |
263 #5 := ldx(), ! Includes tax, tsx | |
264 #6 := dec(), ! Includes dex | |
265 #7 := inc() ! Includes no.op | |
266 END | |
267 END, | |
268 | |
269 ! Group 3 instruction decode | |
270 | |
271 group3 := | |
272 BEGIN | |
273 DECODE Ir => | |
274 BEGIN | |
275 "00 := brk(), ! Break | |
276 "08 := php(), ! Push status on stack | |
277 "28 := plp(), ! Pull status from stack | |
278 "48 := pha(), ! Push accumulator | |
279 "68 := pla(), ! Pull accumulator | |
280 "10 := bpl(), ! Branch on plus | |
281 "30 := bmi(), ! Branch on minus | |
282 "50 := bvc(), ! Branch if overflow clear | |
283 "70 := bvs(), ! Branch if overflow set | |
284 "90 := bcc(), ! Branch on carry clear | |
285 "D0 := bne(), ! Branch on not equal | |
286 "F0 := beq(), ! Branch if equal | |
287 "B0 := bcs(), ! Branch if carry set | |
288 "18 := clc(), ! Clear carry | |
289 "38 := sec(), ! Set carry | |
290 "58 := cli(), ! Clear interrupt enable | |
291 "78 := sei(), ! Set interrupt enable | |
292 "B8 := clv(), ! Clear overflow | |
293 "D8 := cld(), ! Clear decimal mode | |
294 "F8 := sed(), ! Set decimal mode | |
295 "20 := jsr(), ! Jump to subroutine | |
296 "24 := bit(read(zp())), ! Bit test - zero page | |
297 "2C := bit(read(abs())), ! Bit test - absolute | |
298 "40 := rti(), ! Return from interrupt | |
299 "4C := jmp(), ! Jump - absolute | |
300 "6C := jmp(), ! Jump - indirect | |
301 "60 := rts(), ! Return from subroutine | |
302 "84 := sty(zp()), ! Store Y - zero page | |
303 "8C := sty(abs()), ! Store Y - absolute | |
304 "94 := sty(zpx()), ! Store Y - zero page, X | |
305 "88 := dey(), ! Decrement Y | |
306 "C8 := iny(), ! Increment Y | |
307 "E8 := inx(), ! Increment X | |
308 "98 := tya(), ! Transfer Y to A | |
309 "A8 := tay(), ! Transfer A to Y | |
310 "A0 := ldy(immed()), ! Load Y - immediate | |
311 "A4 := ldy(zp()), ! Load Y - zero page | |
312 "AC := ldy(abs()), ! Load Y - absolute | |
313 "B4 := ldy(zpx()), ! Load Y - zero page, X | |
314 "BC := ldy(absx()), ! Load Y - absolute, X | |
315 "C0 := cpy(immed()), ! Compare immediate to Y | |
316 "C4 := cpy(zp()), ! Compare zero page to Y | |
317 "CC := cpy(abs()), ! Compare absolute to Y | |
318 "E0 := cpx(immed()), ! Compare immediate to X | |
319 "E4 := cpx(zp()), ! Compare zero page to X | |
320 "EC := cpx(abs()), ! Compare absolute to X | |
321 OTHERWISE := opex() | |
322 END | |
323 END | |
324 | |
325 **INSTRUCTION.EXECUTION** | |
326 | |
327 ! Group 1 instruction execution | |
328 | |
329 addrs1()<15:0> := ! Group 1 address generation | |
330 BEGIN | |
331 DECODE Ir<4:2> => | |
332 BEGIN | |
333 #0 := addrs1 = indx(), | |
334 #1 := addrs1 = zp(), | |
335 #2 := addrs1 = immed(), | |
336 #3 := addrs1 = abs(), | |
337 #4 := addrs1 = indy(), | |
338 #5 := addrs1 = zpx(), | |
339 #6 := addrs1 = absy(), | |
340 #7 := addrs1 = absx() | |
341 END | |
342 END, | |
343 | |
344 ora := ! Or | |
345 BEGIN | |
346 A = A OR read(addrs1()) NEXT | |
347 setnz(A) | |
348 END, | |
349 | |
350 and. := ! And | |
351 BEGIN | |
352 A = A AND read(addrs1()) NEXT | |
353 setnz(A) | |
354 END, | |
355 | |
356 eor := ! Exclusive or | |
357 BEGIN | |
358 A = A XOR read(addrs1()) NEXT | |
359 setnz(A) | |
360 END, | |
361 | |
362 adc := (decimal.adjust(A +{US} c + read(addrs1()))), ! Add with carry | |
363 | |
364 sta := (IF Ir NEQ{US} "89 => write(addrs1(),A)), ! Store immediate | |
365 | |
366 lda := ! Load accumulator | |
367 BEGIN | |
368 A = read(addrs1()) NEXT | |
369 setnz(A) | |
370 END, | |
371 | |
372 cmp := ! Compare | |
373 BEGIN | |
374 setnz(A - read(addrs1())) NEXT | |
375 c = A GEQ read | |
376 END, | |
377 | |
378 sbc := (decimal.adjust(A +{US} c + NOT read(addrs1()))), ! Sub/carry | |
379 | |
380 ! Group 2 addressing mode selection | |
381 | |
382 ! Group 2 gets and puts | |
383 | |
384 get2()<8:0> := ! Get the correct operand and return it in "get2" | |
385 BEGIN | |
386 DECODE Ir<4:2> => | |
387 BEGIN | |
388 #1 := get2<7:0> = read(zp()), | |
389 #2 := get2<7:0> = A, | |
390 #3 := get2<7:0> = read(abs()), | |
391 #5 := get2<7:0> = read(zpx()), | |
392 #7 := get2<7:0> = read(absx()), | |
393 OTHERWISE := opex() | |
394 END NEXT | |
395 get2<8> = c | |
396 END, | |
397 | |
398 put2(ta.<7:0>) := ! Put the operand in the proper location | |
399 BEGIN | |
400 DECODE Ir<4:2> => | |
401 BEGIN | |
402 [#1,#3,#5,#7] := write(ab, ta.), | |
403 #2 := A = ta., | |
404 OTHERWISE := opex() | |
405 END NEXT | |
406 setnz(ta.) | |
407 END, | |
408 | |
409 ! Group 2 instruction execution | |
410 | |
411 asl := ! Arithmetic shift left | |
412 BEGIN | |
413 get2 = get2() SL0 1 NEXT | |
414 c = get2<8>; put2(get2) | |
415 END, | |
416 | |
417 | |
418 rol := ! rotate left | |
419 BEGIN | |
420 get2 = get2() SLR 1 NEXT | |
421 c = get2<8>; put2(get2) | |
422 END, | |
423 | |
424 lsr := ! Logical shift right | |
425 BEGIN | |
426 c = get2<2> NEXT | |
427 get2 = get2<7:0> SR0 1 NEXT | |
428 put2(get2) | |
429 END, | |
430 | |
431 ror := ! Rotate right | |
432 BEGIN | |
433 get2 = get2() SRR 1 NEXT | |
434 c = get2<8>; put2(get2) | |
435 END, | |
436 | |
437 stx := ! Store index register | |
438 BEGIN | |
439 DECODE Ir<4:2> => | |
440 BEGIN | |
441 #1 := write(zp(), X), | |
442 #2 := A = X, ! Txa | |
443 #3 := write(abs(), X), | |
444 #5 := write(zpy(), X), | |
445 #6 := S = X, ! Txs | |
446 OTHERWISE := opex() | |
447 END | |
448 END, | |
449 | |
450 ldx := ! Load index register | |
451 BEGIN | |
452 DECODE Ir<4:2> => | |
453 BEGIN | |
454 #0 := X = read(immed()), | |
455 #1 := X = read(zp()), | |
456 #2 := X = A, ! Tax | |
457 #3 := X = read(abs()), | |
458 #4 := opex(), | |
459 #5 := X = read(zpy()), | |
460 #6 := X = S, ! Tsx | |
461 #7 := X = read(absy()) | |
462 END NEXT | |
463 setnz(X) | |
464 END, | |
465 | |
466 dec := ! Decrement | |
467 BEGIN | |
468 DECODE Ir EQL "CA => | |
469 BEGIN | |
470 0 := put2(get2() - 1), | |
471 1 := BEGIN ! Dex | |
472 X = X - 1 NEXT | |
473 setnz(X) | |
474 END | |
475 END | |
476 END, | |
477 | |
478 inc := ! Increment | |
479 BEGIN | |
480 IF Ir NEQ "EA => put2(get2() + 1) ! Op "EA => no.op | |
481 END, | |
482 | |
483 ! Group 3 instruction execution | |
484 | |
485 brk := (b = 1; Pc = Pc+1), ! Break | |
486 | |
487 php := (push(P)), ! Push processor status on stack | |
488 plp := (P = pull()), ! Pull processor status from stack | |
489 pha := (push(A)), ! Push accumulator on stack | |
490 pla := ! Pull accumulator from stack | |
491 BEGIN | |
492 A = pull() NEXT | |
493 setnz(A) | |
494 END, | |
495 | |
496 bpl := (branch(NOT n)), ! Branch on plus | |
497 bmi := (branch(n)), ! Branch on minus | |
498 bvc := (branch(NOT v)), ! Branch on overflow clear | |
499 bvs := (branch(v)), ! Branch if overflow set | |
500 bcc := (Branch(NOT c)), ! Branch on carry clear | |
501 bne := (branch(NOT z)), ! Branch if not equal | |
502 beq := (branch(z)), ! Branch on equal | |
503 bcs := (branch(c)), ! Branch on carry set | |
504 | |
505 clc := (c = 0), ! Clear carry flag | |
506 sec := (c = 1), ! Set carry | |
507 cli := (i = 0), ! Clear interrupt disable bit | |
508 sei := (i = 1), ! Set interrupt disable status | |
509 clv := (v = 0), ! Clear overflow | |
510 cld := (d = 0), ! Clear decimal mode | |
511 sed := (d = 1), ! Set decimal mode | |
512 | |
513 jsr := ! Jump to subroutine | |
514 BEGIN | |
515 push((Pc + 1)<15:8>) NEXT | |
516 push((Pc + 1)<7:0>) NEXT | |
517 Pc = abs() | |
518 END, | |
519 | |
520 bit(ta.<7:0>) := ! Bit test | |
521 BEGIN | |
522 n = ta.<7>; v = ta.<6>; z = (ta. AND A) EQL 0 | |
523 END, | |
524 | |
525 rti := ! Return from interrupt | |
526 BEGIN | |
527 P = pull() NEXT | |
528 Pc<7:0> = pull() NEXT | |
529 Pc<15:8> = pull(); b = 0 | |
530 END, | |
531 | |
532 jmp := ! Jump | |
533 BEGIN | |
534 Pc = abs() NEXT | |
535 IF Ir EQL "6C => Pc = abs() ! Indirect | |
536 END, | |
537 | |
538 ! Group 3 instruction execution (page 2) | |
539 | |
540 rts := ! return from subroutine | |
541 BEGIN | |
542 Pc<7:0> = pull() NEXT | |
543 Pc<15:8> = pull() NEXT | |
544 Pc = Pc + 1 | |
545 END, | |
546 | |
547 sty(ab.<15:0>) := (write(ab., Y)), ! Store index Y in memory | |
548 | |
549 dey := ! Decrement index Y by one | |
550 BEGIN | |
551 Y = Y - 1 NEXT | |
552 setnz(Y) | |
553 END, | |
554 | |
555 tya := ! Transfer index Y to accumulator | |
556 BEGIN | |
557 A = Y NEXT | |
558 setnz(A) | |
559 END, | |
560 | |
561 ldy(ab.<15:0>) := (Y = read(ab.)), ! Load index Y with memory | |
562 | |
563 tay := ! Transfer accumulator to index Y | |
564 BEGIN | |
565 Y = A NEXT | |
566 setnz(Y) | |
567 END, | |
568 | |
569 cpy(ab.<15:0>) := ! Compare memory and index Y | |
570 BEGIN | |
571 setnz(Y - read(ab.)) NEXT | |
572 c = Y GEQ read | |
573 END, | |
574 | |
575 iny := ! Increment index Y by one | |
576 BEGIN | |
577 Y = Y + 1 NEXT | |
578 setnz(Y) | |
579 END, | |
580 | |
581 cpx(ab.<15:0>) := ! Compare memory and index X | |
582 BEGIN | |
583 setnz(X - read(ab.)) NEXT | |
584 c = X GEQ read | |
585 END, | |
586 | |
587 inx := ! Increment index X by one | |
588 BEGIN | |
589 X = X + 1 NEXT | |
590 setnz(X) | |
591 END | |
592 | |
593 | |
594 END ! End of MC6502 | |
595 | |
596 |