1 |
|
/* |
2 |
|
* CPUC64.cpp - 6510 (C64) emulation (line based) |
3 |
|
* |
4 |
< |
* Frodo (C) 1994-1997,2002 Christian Bauer |
4 |
> |
* Frodo (C) 1994-1997,2002-2005 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 |
479 |
|
*/ |
480 |
|
|
481 |
|
#if PC_IS_POINTER |
482 |
< |
void MOS6510::jump(uint16 adr) |
483 |
< |
{ |
484 |
< |
if (adr < 0xa000) { |
485 |
< |
pc = ram + adr; |
486 |
< |
pc_base = ram; |
487 |
< |
} else |
488 |
< |
switch (adr >> 12) { |
489 |
< |
case 0xa: |
490 |
< |
case 0xb: |
491 |
< |
if (basic_in) { |
492 |
< |
pc = basic_rom + (adr & 0x1fff); |
493 |
< |
pc_base = basic_rom - 0xa000; |
494 |
< |
} else { |
495 |
< |
pc = ram + adr; |
496 |
< |
pc_base = ram; |
497 |
< |
} |
498 |
< |
break; |
499 |
< |
case 0xc: |
500 |
< |
pc = ram + adr; |
501 |
< |
pc_base = ram; |
502 |
< |
break; |
503 |
< |
case 0xd: |
504 |
< |
if (io_in) |
505 |
< |
illegal_jump(pc-pc_base, adr); |
506 |
< |
else if (char_in) { |
507 |
< |
pc = char_rom + (adr & 0x0fff); |
508 |
< |
pc_base = char_rom - 0xd000; |
509 |
< |
} else { |
510 |
< |
pc = ram + adr; |
511 |
< |
pc_base = ram; |
512 |
< |
} |
513 |
< |
break; |
514 |
< |
case 0xe: |
515 |
< |
case 0xf: |
516 |
< |
if (kernal_in) { |
517 |
< |
pc = kernal_rom + (adr & 0x1fff); |
518 |
< |
pc_base = kernal_rom - 0xe000; |
519 |
< |
} else { |
520 |
< |
pc = ram + adr; |
521 |
< |
pc_base = ram; |
522 |
< |
} |
523 |
< |
break; |
524 |
< |
} |
525 |
< |
} |
482 |
> |
#define jump(adr) \ |
483 |
> |
if ((adr) < 0xa000) { \ |
484 |
> |
pc = ram + (adr); \ |
485 |
> |
pc_base = ram; \ |
486 |
> |
} else { \ |
487 |
> |
switch ((adr) >> 12) { \ |
488 |
> |
case 0xa: \ |
489 |
> |
case 0xb: \ |
490 |
> |
if (basic_in) { \ |
491 |
> |
pc = basic_rom + ((adr) & 0x1fff); \ |
492 |
> |
pc_base = basic_rom - 0xa000; \ |
493 |
> |
} else { \ |
494 |
> |
pc = ram + (adr); \ |
495 |
> |
pc_base = ram; \ |
496 |
> |
} \ |
497 |
> |
break; \ |
498 |
> |
case 0xc: \ |
499 |
> |
pc = ram + (adr); \ |
500 |
> |
pc_base = ram; \ |
501 |
> |
break; \ |
502 |
> |
case 0xd: \ |
503 |
> |
if (io_in) { \ |
504 |
> |
illegal_jump(pc-pc_base, (adr)); \ |
505 |
> |
} else if (char_in) { \ |
506 |
> |
pc = char_rom + ((adr) & 0x0fff); \ |
507 |
> |
pc_base = char_rom - 0xd000; \ |
508 |
> |
} else { \ |
509 |
> |
pc = ram + (adr); \ |
510 |
> |
pc_base = ram; \ |
511 |
> |
} \ |
512 |
> |
break; \ |
513 |
> |
case 0xe: \ |
514 |
> |
case 0xf: \ |
515 |
> |
if (kernal_in) { \ |
516 |
> |
pc = kernal_rom + ((adr) & 0x1fff); \ |
517 |
> |
pc_base = kernal_rom - 0xe000; \ |
518 |
> |
} else { \ |
519 |
> |
pc = ram + (adr); \ |
520 |
> |
pc_base = ram; \ |
521 |
> |
} \ |
522 |
> |
break; \ |
523 |
> |
} \ |
524 |
> |
} |
525 |
|
#else |
526 |
< |
inline void MOS6510::jump(uint16 adr) |
528 |
< |
{ |
529 |
< |
pc = adr; |
530 |
< |
} |
526 |
> |
#define jump(adr) pc = (adr) |
527 |
|
#endif |
528 |
|
|
529 |
|
|
534 |
|
void MOS6510::do_adc(uint8 byte) |
535 |
|
{ |
536 |
|
if (!d_flag) { |
537 |
< |
uint16 tmp; |
542 |
< |
|
543 |
< |
// Binary mode |
544 |
< |
tmp = a + byte + (c_flag ? 1 : 0); |
537 |
> |
uint16 tmp = a + (byte) + (c_flag ? 1 : 0); |
538 |
|
c_flag = tmp > 0xff; |
539 |
< |
v_flag = !((a ^ byte) & 0x80) && ((a ^ tmp) & 0x80); |
539 |
> |
v_flag = !((a ^ (byte)) & 0x80) && ((a ^ tmp) & 0x80); |
540 |
|
z_flag = n_flag = a = tmp; |
548 |
– |
|
541 |
|
} else { |
542 |
|
uint16 al, ah; |
543 |
< |
|
544 |
< |
// Decimal mode |
545 |
< |
al = (a & 0x0f) + (byte & 0x0f) + (c_flag ? 1 : 0); // Calculate lower nybble |
554 |
< |
if (al > 9) al += 6; // BCD fixup for lower nybble |
555 |
< |
|
556 |
< |
ah = (a >> 4) + (byte >> 4); // Calculate upper nybble |
543 |
> |
al = (a & 0x0f) + ((byte) & 0x0f) + (c_flag ? 1 : 0); |
544 |
> |
if (al > 9) al += 6; |
545 |
> |
ah = (a >> 4) + ((byte) >> 4); |
546 |
|
if (al > 0x0f) ah++; |
547 |
< |
|
548 |
< |
z_flag = a + byte + (c_flag ? 1 : 0); // Set flags |
549 |
< |
n_flag = ah << 4; // Only highest bit used |
550 |
< |
v_flag = (((ah << 4) ^ a) & 0x80) && !((a ^ byte) & 0x80); |
551 |
< |
|
552 |
< |
if (ah > 9) ah += 6; // BCD fixup for upper nybble |
564 |
< |
c_flag = ah > 0x0f; // Set carry flag |
565 |
< |
a = (ah << 4) | (al & 0x0f); // Compose result |
547 |
> |
z_flag = a + (byte) + (c_flag ? 1 : 0); |
548 |
> |
n_flag = ah << 4; |
549 |
> |
v_flag = (((ah << 4) ^ a) & 0x80) && !((a ^ (byte)) & 0x80); |
550 |
> |
if (ah > 9) ah += 6; |
551 |
> |
c_flag = ah > 0x0f; |
552 |
> |
a = (ah << 4) | (al & 0x0f); |
553 |
|
} |
554 |
|
} |
555 |
|
|
560 |
|
|
561 |
|
void MOS6510::do_sbc(uint8 byte) |
562 |
|
{ |
563 |
< |
uint16 tmp = a - byte - (c_flag ? 0 : 1); |
577 |
< |
|
563 |
> |
uint16 tmp = a - (byte) - (c_flag ? 0 : 1); |
564 |
|
if (!d_flag) { |
579 |
– |
|
580 |
– |
// Binary mode |
565 |
|
c_flag = tmp < 0x100; |
566 |
< |
v_flag = ((a ^ tmp) & 0x80) && ((a ^ byte) & 0x80); |
566 |
> |
v_flag = ((a ^ tmp) & 0x80) && ((a ^ (byte)) & 0x80); |
567 |
|
z_flag = n_flag = a = tmp; |
584 |
– |
|
568 |
|
} else { |
569 |
|
uint16 al, ah; |
570 |
< |
|
571 |
< |
// Decimal mode |
589 |
< |
al = (a & 0x0f) - (byte & 0x0f) - (c_flag ? 0 : 1); // Calculate lower nybble |
590 |
< |
ah = (a >> 4) - (byte >> 4); // Calculate upper nybble |
570 |
> |
al = (a & 0x0f) - ((byte) & 0x0f) - (c_flag ? 0 : 1); |
571 |
> |
ah = (a >> 4) - ((byte) >> 4); |
572 |
|
if (al & 0x10) { |
573 |
< |
al -= 6; // BCD fixup for lower nybble |
573 |
> |
al -= 6; |
574 |
|
ah--; |
575 |
|
} |
576 |
< |
if (ah & 0x10) ah -= 6; // BCD fixup for upper nybble |
577 |
< |
|
578 |
< |
c_flag = tmp < 0x100; // Set flags |
598 |
< |
v_flag = ((a ^ tmp) & 0x80) && ((a ^ byte) & 0x80); |
576 |
> |
if (ah & 0x10) ah -= 6; |
577 |
> |
c_flag = tmp < 0x100; |
578 |
> |
v_flag = ((a ^ tmp) & 0x80) && ((a ^ (byte)) & 0x80); |
579 |
|
z_flag = n_flag = tmp; |
580 |
< |
|
601 |
< |
a = (ah << 4) | (al & 0x0f); // Compose result |
580 |
> |
a = (ah << 4) | (al & 0x0f); |
581 |
|
} |
582 |
|
} |
583 |
|
|
598 |
|
if (i_flag) s->p |= 0x04; |
599 |
|
if (!z_flag) s->p |= 0x02; |
600 |
|
if (c_flag) s->p |= 0x01; |
601 |
< |
|
601 |
> |
|
602 |
|
s->ddr = ram[0]; |
603 |
|
s->pr = ram[1] & 0x3f; |
604 |
|
|
751 |
|
// Any pending interrupts? |
752 |
|
if (interrupt.intr_any) { |
753 |
|
handle_int: |
754 |
< |
if (interrupt.intr[INT_RESET]) |
754 |
> |
if (interrupt.intr[INT_RESET]) { |
755 |
|
Reset(); |
756 |
|
|
757 |
< |
else if (interrupt.intr[INT_NMI]) { |
757 |
> |
} else if (interrupt.intr[INT_NMI]) { |
758 |
|
interrupt.intr[INT_NMI] = false; // Simulate an edge-triggered input |
759 |
|
#if PC_IS_POINTER |
760 |
|
push_byte((pc-pc_base) >> 8); push_byte(pc-pc_base); |
763 |
|
#endif |
764 |
|
push_flags(false); |
765 |
|
i_flag = true; |
766 |
< |
jump(read_word(0xfffa)); |
766 |
> |
adr = read_word(0xfffa); |
767 |
> |
jump(adr); |
768 |
|
last_cycles = 7; |
769 |
|
|
770 |
|
} else if ((interrupt.intr[INT_VICIRQ] || interrupt.intr[INT_CIAIRQ]) && !i_flag) { |
775 |
|
#endif |
776 |
|
push_flags(false); |
777 |
|
i_flag = true; |
778 |
< |
jump(read_word(0xfffe)); |
778 |
> |
adr = read_word(0xfffe); |
779 |
> |
jump(adr); |
780 |
|
last_cycles = 7; |
781 |
|
} |
782 |
|
} |
811 |
|
jump(0xedac); |
812 |
|
break; |
813 |
|
case 0x03: |
814 |
< |
ram[0x90] |= TheIEC->In(&a); |
814 |
> |
ram[0x90] |= TheIEC->In(a); |
815 |
|
set_nz(a); |
816 |
|
c_flag = false; |
817 |
|
jump(0xedac); |