ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/CPU1541_SC.cpp
Revision: 1.2
Committed: 2003-07-01T17:51:17Z (20 years, 9 months ago) by cebix
Branch: MAIN
Changes since 1.1: +1 -1 lines
Log Message:
updated copyright date

File Contents

# Content
1 /*
2 * CPU1541_SC.cpp - Single-cycle 6502 (1541) emulation
3 *
4 * Frodo (C) 1994-1997,2002-2003 Christian Bauer
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 /*
22 * Notes:
23 * ------
24 *
25 * Opcode execution:
26 * - All opcodes are resolved into single clock cycles. There is one
27 * switch case for each cycle.
28 * - The "state" variable specifies the routine to be executed in the
29 * next cycle. Its upper 8 bits contain the current opcode, its lower
30 * 8 bits contain the cycle number (0..7) within the opcode.
31 * - Opcodes are fetched in cycle 0 (state = 0)
32 * - The states 0x0010..0x0027 are used for interrupts
33 * - There is exactly one memory access in each clock cycle
34 *
35 * Memory map (1541C, the 1541 and 1541-II are a bit different):
36 *
37 * $0000-$07ff RAM (2K)
38 * $0800-$0fff RAM mirror
39 * $1000-$17ff free
40 * $1800-$1bff VIA 1
41 * $1c00-$1fff VIA 2
42 * $2000-$bfff free
43 * $c000-$ffff ROM (16K)
44 *
45 * - All memory accesses are done with the read_byte() and
46 * write_byte() functions which also do the memory address
47 * decoding.
48 * - The possible interrupt sources are:
49 * INT_VIA1IRQ: I flag is checked, jump to ($fffe) (unused)
50 * INT_VIA2IRQ: I flag is checked, jump to ($fffe) (unused)
51 * INT_IECIRQ: I flag is checked, jump to ($fffe) (unused)
52 * INT_RESET: Jump to ($fffc)
53 * - The z_flag variable has the inverse meaning of the
54 * 6502 Z flag
55 * - Only the highest bit of the n_flag variable is used
56 * - The $f2 opcode that would normally crash the 6502 is
57 * used to implement emulator-specific functions
58 * - The 1541 6502 emulation also includes a very simple VIA
59 * emulation (enough to make the IEC bus and GCR loading work).
60 * It's too small to move it to a source file of its own.
61 *
62 * Incompatibilities:
63 * ------------------
64 *
65 * - VIA emulation incomplete
66 */
67
68 #include "sysdeps.h"
69
70 #include "CPU1541.h"
71 #include "CPU_common.h"
72 #include "1541job.h"
73 #include "C64.h"
74 #include "CIA.h"
75 #include "Display.h"
76
77
78 enum {
79 INT_RESET = 3
80 };
81
82
83 /*
84 * 6502 constructor: Initialize registers
85 */
86
87 MOS6502_1541::MOS6502_1541(C64 *c64, Job1541 *job, C64Display *disp, uint8 *Ram, uint8 *Rom)
88 : ram(Ram), rom(Rom), the_c64(c64), the_display(disp), the_job(job)
89 {
90 a = x = y = 0;
91 sp = 0xff;
92 n_flag = z_flag = 0;
93 v_flag = d_flag = c_flag = false;
94 i_flag = true;
95
96 via1_t1c = via1_t1l = via1_t2c = via1_t2l = 0;
97 via1_sr = 0;
98 via2_t1c = via2_t1l = via2_t2c = via2_t2l = 0;
99 via2_sr = 0;
100
101 first_irq_cycle = 0;
102 Idle = false;
103 }
104
105
106 /*
107 * Reset CPU asynchronously
108 */
109
110 void MOS6502_1541::AsyncReset(void)
111 {
112 interrupt.intr[INT_RESET] = true;
113 Idle = false;
114 }
115
116
117 /*
118 * Get 6502 register state
119 */
120
121 void MOS6502_1541::GetState(MOS6502State *s)
122 {
123 s->a = a;
124 s->x = x;
125 s->y = y;
126
127 s->p = 0x20 | (n_flag & 0x80);
128 if (v_flag) s->p |= 0x40;
129 if (d_flag) s->p |= 0x08;
130 if (i_flag) s->p |= 0x04;
131 if (!z_flag) s->p |= 0x02;
132 if (c_flag) s->p |= 0x01;
133
134 s->pc = pc;
135 s->sp = sp | 0x0100;
136
137 s->intr[INT_VIA1IRQ] = interrupt.intr[INT_VIA1IRQ];
138 s->intr[INT_VIA2IRQ] = interrupt.intr[INT_VIA2IRQ];
139 s->intr[INT_IECIRQ] = interrupt.intr[INT_IECIRQ];
140 s->intr[INT_RESET] = interrupt.intr[INT_RESET];
141 s->idle = Idle;
142
143 s->via1_pra = via1_pra; s->via1_ddra = via1_ddra;
144 s->via1_prb = via1_prb; s->via1_ddrb = via1_ddrb;
145 s->via1_t1c = via1_t1c; s->via1_t1l = via1_t1l;
146 s->via1_t2c = via1_t2c; s->via1_t2l = via1_t2l;
147 s->via1_sr = via1_sr;
148 s->via1_acr = via1_acr; s->via1_pcr = via1_pcr;
149 s->via1_ifr = via1_ifr; s->via1_ier = via1_ier;
150
151 s->via2_pra = via2_pra; s->via2_ddra = via2_ddra;
152 s->via2_prb = via2_prb; s->via2_ddrb = via2_ddrb;
153 s->via2_t1c = via2_t1c; s->via2_t1l = via2_t1l;
154 s->via2_t2c = via2_t2c; s->via2_t2l = via2_t2l;
155 s->via2_sr = via2_sr;
156 s->via2_acr = via2_acr; s->via2_pcr = via2_pcr;
157 s->via2_ifr = via2_ifr; s->via2_ier = via2_ier;
158 }
159
160
161 /*
162 * Restore 6502 state
163 */
164
165 void MOS6502_1541::SetState(MOS6502State *s)
166 {
167 a = s->a;
168 x = s->x;
169 y = s->y;
170
171 n_flag = s->p;
172 v_flag = s->p & 0x40;
173 d_flag = s->p & 0x08;
174 i_flag = s->p & 0x04;
175 z_flag = !(s->p & 0x02);
176 c_flag = s->p & 0x01;
177
178 pc = s->pc;
179 sp = s->sp & 0xff;
180
181 interrupt.intr[INT_VIA1IRQ] = s->intr[INT_VIA1IRQ];
182 interrupt.intr[INT_VIA2IRQ] = s->intr[INT_VIA2IRQ];
183 interrupt.intr[INT_IECIRQ] = s->intr[INT_IECIRQ];
184 interrupt.intr[INT_RESET] = s->intr[INT_RESET];
185 Idle = s->idle;
186
187 via1_pra = s->via1_pra; via1_ddra = s->via1_ddra;
188 via1_prb = s->via1_prb; via1_ddrb = s->via1_ddrb;
189 via1_t1c = s->via1_t1c; via1_t1l = s->via1_t1l;
190 via1_t2c = s->via1_t2c; via1_t2l = s->via1_t2l;
191 via1_sr = s->via1_sr;
192 via1_acr = s->via1_acr; via1_pcr = s->via1_pcr;
193 via1_ifr = s->via1_ifr; via1_ier = s->via1_ier;
194
195 via2_pra = s->via2_pra; via2_ddra = s->via2_ddra;
196 via2_prb = s->via2_prb; via2_ddrb = s->via2_ddrb;
197 via2_t1c = s->via2_t1c; via2_t1l = s->via2_t1l;
198 via2_t2c = s->via2_t2c; via2_t2l = s->via2_t2l;
199 via2_sr = s->via2_sr;
200 via2_acr = s->via2_acr; via2_pcr = s->via2_pcr;
201 via2_ifr = s->via2_ifr; via2_ier = s->via2_ier;
202 }
203
204
205 /*
206 * Read a byte from I/O space
207 */
208
209 inline uint8 MOS6502_1541::read_byte_io(uint16 adr)
210 {
211 if ((adr & 0xfc00) == 0x1800) // VIA 1
212 switch (adr & 0xf) {
213 case 0:
214 return (via1_prb & 0x1a
215 | ((IECLines & TheCIA2->IECLines) >> 7) // DATA
216 | ((IECLines & TheCIA2->IECLines) >> 4) & 0x04 // CLK
217 | (TheCIA2->IECLines << 3) & 0x80) ^ 0x85; // ATN
218 case 1:
219 case 15:
220 return 0xff; // Keep 1541C ROMs happy (track 0 sensor)
221 case 2:
222 return via1_ddrb;
223 case 3:
224 return via1_ddra;
225 case 4:
226 via1_ifr &= 0xbf;
227 return via1_t1c;
228 case 5:
229 return via1_t1c >> 8;
230 case 6:
231 return via1_t1l;
232 case 7:
233 return via1_t1l >> 8;
234 case 8:
235 via1_ifr &= 0xdf;
236 return via1_t2c;
237 case 9:
238 return via1_t2c >> 8;
239 case 10:
240 return via1_sr;
241 case 11:
242 return via1_acr;
243 case 12:
244 return via1_pcr;
245 case 13:
246 return via1_ifr | (via1_ifr & via1_ier ? 0x80 : 0);
247 case 14:
248 return via1_ier | 0x80;
249 default: // Can't happen
250 return 0;
251 }
252
253 else if ((adr & 0xfc00) == 0x1c00) // VIA 2
254 switch (adr & 0xf) {
255 case 0:
256 if (the_job->SyncFound())
257 return via2_prb & 0x7f | the_job->WPState();
258 else
259 return via2_prb | 0x80 | the_job->WPState();
260 case 1:
261 case 15:
262 return the_job->ReadGCRByte();
263 case 2:
264 return via2_ddrb;
265 case 3:
266 return via2_ddra;
267 case 4:
268 via2_ifr &= 0xbf;
269 interrupt.intr[INT_VIA2IRQ] = false; // Clear job IRQ
270 return via2_t1c;
271 case 5:
272 return via2_t1c >> 8;
273 case 6:
274 return via2_t1l;
275 case 7:
276 return via2_t1l >> 8;
277 case 8:
278 via2_ifr &= 0xdf;
279 return via2_t2c;
280 case 9:
281 return via2_t2c >> 8;
282 case 10:
283 return via2_sr;
284 case 11:
285 return via2_acr;
286 case 12:
287 return via2_pcr;
288 case 13:
289 return via2_ifr | (via2_ifr & via2_ier ? 0x80 : 0);
290 case 14:
291 return via2_ier | 0x80;
292 default: // Can't happen
293 return 0;
294 }
295
296 else
297 return adr >> 8;
298 }
299
300
301 /*
302 * Read a byte from the CPU's address space
303 */
304
305 uint8 MOS6502_1541::read_byte(uint16 adr)
306 {
307 if (adr >= 0xc000)
308 return rom[adr & 0x3fff];
309 else if (adr < 0x1000)
310 return ram[adr & 0x07ff];
311 else
312 return read_byte_io(adr);
313 }
314
315
316 /*
317 * Read a word (little-endian) from the CPU's address space
318 */
319
320 inline uint16 MOS6502_1541::read_word(uint16 adr)
321 {
322 return read_byte(adr) | (read_byte(adr+1) << 8);
323 }
324
325
326 /*
327 * Write a byte to I/O space
328 */
329
330 void MOS6502_1541::write_byte_io(uint16 adr, uint8 byte)
331 {
332 if ((adr & 0xfc00) == 0x1800) // VIA 1
333 switch (adr & 0xf) {
334 case 0:
335 via1_prb = byte;
336 byte = ~via1_prb & via1_ddrb;
337 IECLines = (byte << 6) & ((~byte ^ TheCIA2->IECLines) << 3) & 0x80
338 | (byte << 3) & 0x40;
339 break;
340 case 1:
341 case 15:
342 via1_pra = byte;
343 break;
344 case 2:
345 via1_ddrb = byte;
346 byte &= ~via1_prb;
347 IECLines = (byte << 6) & ((~byte ^ TheCIA2->IECLines) << 3) & 0x80
348 | (byte << 3) & 0x40;
349 break;
350 case 3:
351 via1_ddra = byte;
352 break;
353 case 4:
354 case 6:
355 via1_t1l = via1_t1l & 0xff00 | byte;
356 break;
357 case 5:
358 via1_t1l = via1_t1l & 0xff | (byte << 8);
359 via1_ifr &= 0xbf;
360 via1_t1c = via1_t1l;
361 break;
362 case 7:
363 via1_t1l = via1_t1l & 0xff | (byte << 8);
364 break;
365 case 8:
366 via1_t2l = via1_t2l & 0xff00 | byte;
367 break;
368 case 9:
369 via1_t2l = via1_t2l & 0xff | (byte << 8);
370 via1_ifr &= 0xdf;
371 via1_t2c = via1_t2l;
372 break;
373 case 10:
374 via1_sr = byte;
375 break;
376 case 11:
377 via1_acr = byte;
378 break;
379 case 12:
380 via1_pcr = byte;
381 break;
382 case 13:
383 via1_ifr &= ~byte;
384 break;
385 case 14:
386 if (byte & 0x80)
387 via1_ier |= byte & 0x7f;
388 else
389 via1_ier &= ~byte;
390 break;
391 }
392
393 else if ((adr & 0xfc00) == 0x1c00)
394 switch (adr & 0xf) {
395 case 0:
396 if ((via2_prb ^ byte) & 8) // Bit 3: Drive LED
397 the_display->UpdateLEDs(byte & 8 ? 1 : 0, 0, 0, 0);
398 if ((via2_prb ^ byte) & 3) // Bits 0/1: Stepper motor
399 if ((via2_prb & 3) == ((byte+1) & 3))
400 the_job->MoveHeadOut();
401 else if ((via2_prb & 3) == ((byte-1) & 3))
402 the_job->MoveHeadIn();
403 via2_prb = byte & 0xef;
404 break;
405 case 1:
406 case 15:
407 via2_pra = byte;
408 break;
409 case 2:
410 via2_ddrb = byte;
411 break;
412 case 3:
413 via2_ddra = byte;
414 break;
415 case 4:
416 case 6:
417 via2_t1l = via2_t1l & 0xff00 | byte;
418 break;
419 case 5:
420 via2_t1l = via2_t1l & 0xff | (byte << 8);
421 via2_ifr &= 0xbf;
422 via2_t1c = via2_t1l;
423 break;
424 case 7:
425 via2_t1l = via2_t1l & 0xff | (byte << 8);
426 break;
427 case 8:
428 via2_t2l = via2_t2l & 0xff00 | byte;
429 break;
430 case 9:
431 via2_t2l = via2_t2l & 0xff | (byte << 8);
432 via2_ifr &= 0xdf;
433 via2_t2c = via2_t2l;
434 break;
435 case 10:
436 via2_sr = byte;
437 break;
438 case 11:
439 via2_acr = byte;
440 break;
441 case 12:
442 via2_pcr = byte;
443 break;
444 case 13:
445 via2_ifr &= ~byte;
446 break;
447 case 14:
448 if (byte & 0x80)
449 via2_ier |= byte & 0x7f;
450 else
451 via2_ier &= ~byte;
452 break;
453 }
454 }
455
456
457 /*
458 * Write a byte to the CPU's address space
459 */
460
461 inline void MOS6502_1541::write_byte(uint16 adr, uint8 byte)
462 {
463 if (adr < 0x1000)
464 ram[adr & 0x7ff] = byte;
465 else
466 write_byte_io(adr, byte);
467 }
468
469
470 /*
471 * Read byte from 6502/1541 address space (used by SAM)
472 */
473
474 uint8 MOS6502_1541::ExtReadByte(uint16 adr)
475 {
476 return read_byte(adr);
477 }
478
479
480 /*
481 * Write byte to 6502/1541 address space (used by SAM)
482 */
483
484 void MOS6502_1541::ExtWriteByte(uint16 adr, uint8 byte)
485 {
486 write_byte(adr, byte);
487 }
488
489
490 /*
491 * Adc instruction
492 */
493
494 inline void MOS6502_1541::do_adc(uint8 byte)
495 {
496 if (!d_flag) {
497 uint16 tmp;
498
499 // Binary mode
500 tmp = a + byte + (c_flag ? 1 : 0);
501 c_flag = tmp > 0xff;
502 v_flag = !((a ^ byte) & 0x80) && ((a ^ tmp) & 0x80);
503 z_flag = n_flag = a = tmp;
504
505 } else {
506 uint16 al, ah;
507
508 // Decimal mode
509 al = (a & 0x0f) + (byte & 0x0f) + (c_flag ? 1 : 0); // Calculate lower nybble
510 if (al > 9) al += 6; // BCD fixup for lower nybble
511
512 ah = (a >> 4) + (byte >> 4); // Calculate upper nybble
513 if (al > 0x0f) ah++;
514
515 z_flag = a + byte + (c_flag ? 1 : 0); // Set flags
516 n_flag = ah << 4; // Only highest bit used
517 v_flag = (((ah << 4) ^ a) & 0x80) && !((a ^ byte) & 0x80);
518
519 if (ah > 9) ah += 6; // BCD fixup for upper nybble
520 c_flag = ah > 0x0f; // Set carry flag
521 a = (ah << 4) | (al & 0x0f); // Compose result
522 }
523 }
524
525
526 /*
527 * Sbc instruction
528 */
529
530 inline void MOS6502_1541::do_sbc(uint8 byte)
531 {
532 uint16 tmp = a - byte - (c_flag ? 0 : 1);
533
534 if (!d_flag) {
535
536 // Binary mode
537 c_flag = tmp < 0x100;
538 v_flag = ((a ^ tmp) & 0x80) && ((a ^ byte) & 0x80);
539 z_flag = n_flag = a = tmp;
540
541 } else {
542 uint16 al, ah;
543
544 // Decimal mode
545 al = (a & 0x0f) - (byte & 0x0f) - (c_flag ? 0 : 1); // Calculate lower nybble
546 ah = (a >> 4) - (byte >> 4); // Calculate upper nybble
547 if (al & 0x10) {
548 al -= 6; // BCD fixup for lower nybble
549 ah--;
550 }
551 if (ah & 0x10) ah -= 6; // BCD fixup for upper nybble
552
553 c_flag = tmp < 0x100; // Set flags
554 v_flag = ((a ^ tmp) & 0x80) && ((a ^ byte) & 0x80);
555 z_flag = n_flag = tmp;
556
557 a = (ah << 4) | (al & 0x0f); // Compose result
558 }
559 }
560
561
562 /*
563 * Reset CPU
564 */
565
566 void MOS6502_1541::Reset(void)
567 {
568 // IEC lines and VIA registers
569 IECLines = 0xc0;
570
571 via1_pra = via1_ddra = via1_prb = via1_ddrb = 0;
572 via1_acr = via1_pcr = 0;
573 via1_ifr = via1_ier = 0;
574 via2_pra = via2_ddra = via2_prb = via2_ddrb = 0;
575 via2_acr = via2_pcr = 0;
576 via2_ifr = via2_ier = 0;
577
578 // Clear all interrupt lines
579 interrupt.intr_any = 0;
580
581 // Read reset vector
582 pc = read_word(0xfffc);
583 state = 0;
584
585 // Wake up 1541
586 Idle = false;
587 }
588
589
590 /*
591 * Illegal opcode encountered
592 */
593
594 void MOS6502_1541::illegal_op(uint8 op, uint16 at)
595 {
596 char illop_msg[80];
597
598 sprintf(illop_msg, "1541: Illegal opcode %02x at %04x.", op, at);
599 if (ShowRequester(illop_msg, "Reset 1541", "Reset C64"))
600 the_c64->Reset();
601 Reset();
602 }
603
604
605 /*
606 * Emulate one 6502 clock cycle
607 */
608
609 // Read byte from memory
610 #define read_to(adr, to) \
611 to = read_byte(adr);
612
613 // Read byte from memory, throw away result
614 #define read_idle(adr) \
615 read_byte(adr);
616
617 void MOS6502_1541::EmulateCycle(void)
618 {
619 uint8 data, tmp;
620
621 // Any pending interrupts in state 0 (opcode fetch)?
622 if (!state && interrupt.intr_any) {
623 if (interrupt.intr[INT_RESET])
624 Reset();
625 else if ((interrupt.intr[INT_VIA1IRQ] || interrupt.intr[INT_VIA2IRQ] || interrupt.intr[INT_IECIRQ]) && (the_c64->CycleCounter-first_irq_cycle >= 2) && !i_flag)
626 state = 0x0008;
627 }
628
629 #define IS_CPU_1541
630 #include "CPU_emulcycle.h"
631
632 // Extension opcode
633 case O_EXT:
634 if (pc < 0xc000) {
635 illegal_op(0xf2, pc-1);
636 break;
637 }
638 switch (read_byte(pc++)) {
639 case 0x00: // Go to sleep in DOS idle loop if error flag is clear and no command received
640 Idle = !(ram[0x26c] | ram[0x7c]);
641 pc = 0xebff;
642 Last;
643 case 0x01: // Write sector
644 the_job->WriteSector();
645 pc = 0xf5dc;
646 Last;
647 case 0x02: // Format track
648 the_job->FormatTrack();
649 pc = 0xfd8b;
650 Last;
651 default:
652 illegal_op(0xf2, pc-1);
653 break;
654 }
655 break;
656
657 default:
658 illegal_op(op, pc-1);
659 break;
660 }
661 }