CPU fixes from "lockstep" branch; PRINT 5 works

Merge lots of instruction improvements and fixes
Lift keyboard processing out of MAINboard
Make disassembler return a string - could be inserted into a queue for
  later printing if desired
This commit is contained in:
Brad Grantham 2016-11-12 13:20:10 -08:00
parent c52cb2939e
commit bfac8e9736

View File

@ -6,6 +6,8 @@
#include <thread>
#include <ratio>
#include <iostream>
#include <deque>
#include <map>
#include <signal.h>
#include "fake6502.h"
@ -255,6 +257,13 @@ struct MAINboard : board_base
0xC00A, 0xC00B,
};
deque<unsigned char> keyboard_buffer;
void enqueue_key(unsigned char k)
{
keyboard_buffer.push_back(k);
}
MAINboard(unsigned char rom_image[32768]) :
internal_C800_ROM_selected(true)
{
@ -264,12 +273,10 @@ struct MAINboard : board_base
std::copy(rom_image + rom_C300.base - 0x8000, rom_image + rom_C300.base - 0x8000 + rom_C300.size, rom_C300.memory.begin());
std::copy(rom_image + rom_C400.base - 0x8000, rom_image + rom_C400.base - 0x8000 + rom_C400.size, rom_C400.memory.begin());
std::copy(rom_image + rom_C800.base - 0x8000, rom_image + rom_C800.base - 0x8000 + rom_C800.size, rom_C800.memory.begin());
start_keyboard();
}
virtual ~MAINboard()
{
stop_keyboard();
}
virtual bool read(int addr, unsigned char &data)
{
@ -322,7 +329,11 @@ struct MAINboard : board_base
return true;
}
if(addr == 0xC000) {
data = get_keyboard_data_and_strobe();
if(!keyboard_buffer.empty()) {
data = 0x80 | keyboard_buffer[0];
} else {
data = 0x00;
}
if(debug & DEBUG_RW) printf("read KBD, return 0x%02X\n", data);
return true;
}
@ -334,7 +345,10 @@ struct MAINboard : board_base
}
if(addr == 0xC010) {
// reset keyboard latch
data = get_any_key_down_and_clear_strobe();
if(!keyboard_buffer.empty()) {
keyboard_buffer.pop_front();
}
data = 0x0;
if(debug & DEBUG_RW) printf("read KBDSTRB, return 0x%02X\n", data);
return true;
}
@ -430,8 +444,10 @@ struct MAINboard : board_base
}
if(addr == 0xC010) {
if(debug & DEBUG_RW) printf("write KBDSTRB\n");
if(!keyboard_buffer.empty()) {
keyboard_buffer.pop_front();
}
// reset keyboard latch
get_any_key_down_and_clear_strobe();
return true;
}
if(addr == 0xC030) {
@ -460,13 +476,16 @@ struct MAINboard : board_base
struct bus_controller
{
std::vector<board_base*> boards;
vector<board_base*> boards;
map<int, vector<unsigned char> > writes;
map<int, vector<unsigned char> > reads;
unsigned char read(int addr)
{
for(auto b = boards.begin(); b != boards.end(); b++) {
unsigned char data = 0xaa;
if((*b)->read(addr, data)) {
if(debug & DEBUG_BUS) printf("read %04X returned %02X\n", addr, data);
// reads[addr].push_back(data);
return data;
}
}
@ -479,6 +498,7 @@ struct bus_controller
for(auto b = boards.begin(); b != boards.end(); b++) {
if((*b)->write(addr, data)) {
if(debug & DEBUG_BUS) printf("write %04X %02X\n", addr, data);
// writes[addr].push_back(data);
return;
}
}
@ -503,6 +523,22 @@ void write6502(uint16_t address, uint8_t value)
};
bool sbc_overflow(unsigned char a, unsigned char b, int borrow)
{
signed char a_ = a;
signed char b_ = b;
signed short c = a_ - (b_ + borrow);
return (c < -128) || (c > 127);
}
bool adc_overflow(unsigned char a, unsigned char b, int carry)
{
signed char a_ = a;
signed char b_ = b;
signed short c = a_ + b_ + carry;
return (c < -128) || (c > 127);
}
struct CPU6502
{
unsigned char a, x, y, s, p;
@ -522,6 +558,7 @@ struct CPU6502
INT,
} exception;
CPU6502() :
p(0x20),
exception(RESET)
{
}
@ -607,8 +644,6 @@ struct CPU6502
flag_change(Z, v == 0x00);
if(flags & N)
flag_change(N, v & 0x80);
if(flags & V)
flag_change(V, isset(C) != isset(N));
}
void cycle(bus_controller& bus)
{
@ -759,7 +794,7 @@ struct CPU6502
case 0xB1: { // LDA ind, Y
unsigned char zpg = read_pc_inc(bus);
int addr = bus.read(zpg) + bus.read(zpg + 1) * 256 + y;
int addr = bus.read(zpg) + bus.read((zpg + 1) & 0xFF) * 256 + y;
set_flags(N | Z, a = bus.read(addr));
break;
}
@ -802,18 +837,20 @@ struct CPU6502
unsigned char zpg = read_pc_inc(bus);
m = bus.read(zpg);
int borrow = isset(C) ? 0 : 1;
flag_change(C, !(a < m - borrow));
set_flags(N | Z | V, a = a - m - borrow);
flag_change(C, !(a < (m + borrow)));
flag_change(V, sbc_overflow(a, m, borrow));
set_flags(N | Z, a = a - (m - borrow));
break;
}
case 0xF1: { // SBC ind, Y
unsigned char zpg = read_pc_inc(bus);
int addr = bus.read(zpg) + bus.read(zpg + 1) * 256 + y;
int addr = bus.read(zpg) + bus.read((zpg + 1) & 0xff) * 256 + y;
m = bus.read(addr);
int borrow = isset(C) ? 0 : 1;
flag_change(C, !(a < m - borrow));
set_flags(N | Z | V, a = a - m - borrow);
flag_change(C, !(a < (m + borrow)));
flag_change(V, sbc_overflow(a, m, borrow));
set_flags(N | Z, a = a - (m - borrow));
break;
}
@ -821,16 +858,18 @@ struct CPU6502
int addr = read_pc_inc(bus) + read_pc_inc(bus) * 256;
unsigned char m = bus.read(addr);
int borrow = isset(C) ? 0 : 1;
flag_change(C, !(a < m - borrow));
set_flags(N | Z | V, a = a - m - borrow);
flag_change(C, !(a < (m + borrow)));
flag_change(V, sbc_overflow(a, m, borrow));
set_flags(N | Z, a = a - (m + borrow));
break;
}
case 0xE9: { // SBC imm
unsigned char m = read_pc_inc(bus);
int borrow = isset(C) ? 0 : 1;
flag_change(C, !(a < m - borrow));
set_flags(N | Z | V, a = a - m - borrow);
flag_change(C, !(a < (m + borrow)));
flag_change(V, sbc_overflow(a, m, borrow));
set_flags(N | Z, a = a - (m - borrow));
break;
}
@ -839,7 +878,18 @@ struct CPU6502
m = bus.read(zpg);
int carry = isset(C) ? 1 : 0;
flag_change(C, (int)(a + m + carry) > 0xFF);
set_flags(N | Z | V, a = a + m + carry);
flag_change(V, adc_overflow(a, m, carry));
set_flags(N | Z, a = a + m + carry);
break;
}
case 0x79: { // ADC abs, Y
int addr = read_pc_inc(bus) + read_pc_inc(bus) * 256 + y;
m = bus.read(addr);
int carry = isset(C) ? 1 : 0;
flag_change(C, (int)(a + m + carry) > 0xFF);
flag_change(V, adc_overflow(a, m, carry));
set_flags(N | Z, a = a + m + carry);
break;
}
@ -847,7 +897,8 @@ struct CPU6502
m = read_pc_inc(bus);
int carry = isset(C) ? 1 : 0;
flag_change(C, (int)(a + m + carry) > 0xFF);
set_flags(N | Z | V, a = a + m + carry);
flag_change(V, adc_overflow(a, m, carry));
set_flags(N | Z, a = a + m + carry);
break;
}
@ -860,6 +911,15 @@ struct CPU6502
break;
}
case 0x16: { // ASL
unsigned char zpg = read_pc_inc(bus);
m = bus.read((zpg + x) & 0xFF);
flag_change(C, m & 0x80);
set_flags(N | Z, m = m << 1);
bus.write((zpg + x) & 0xFF, m);
break;
}
case 0x0A: { // ASL
flag_change(C, a & 0x80);
set_flags(N | Z, a = a << 1);
@ -875,6 +935,15 @@ struct CPU6502
break;
}
case 0x56: { // LSR zpg, X
unsigned char zpg = read_pc_inc(bus) + x;
m = bus.read(zpg & 0xFF);
flag_change(C, m & 0x01);
set_flags(N | Z, m = m >> 1);
bus.write(zpg, m);
break;
}
case 0x4E: { // LSR
int addr = read_pc_inc(bus) + read_pc_inc(bus) * 256;
m = bus.read(addr);
@ -944,8 +1013,18 @@ struct CPU6502
break;
}
case 0x66: { // ROR
unsigned char zpg = read_pc_inc(bus);
m = bus.read(zpg);
bool c = isset(C);
flag_change(C, m & 0x01);
set_flags(N | Z, m = (c ? 0x80 : 0x00) | (m >> 1));
bus.write(zpg, m);
break;
}
case 0x76: { // ROR
unsigned char zpg = read_pc_inc(bus) + x;
unsigned char zpg = (read_pc_inc(bus) + x) & 0xFF;
m = bus.read(zpg);
bool c = isset(C);
flag_change(C, m & 0x01);
@ -955,7 +1034,7 @@ struct CPU6502
}
case 0x26: { // ROL
unsigned char zpg = read_pc_inc(bus) + x;
unsigned char zpg = read_pc_inc(bus);
bool c = isset(C);
m = bus.read(zpg);
flag_change(C, m & 0x80);
@ -994,7 +1073,7 @@ struct CPU6502
case 0x91: { // STA
unsigned char zpg = read_pc_inc(bus);
int addr = bus.read(zpg) + bus.read(zpg + 1) * 256 + y;
int addr = bus.read(zpg) + bus.read((zpg + 1) & 0xFF) * 256 + y;
bus.write(addr, a);
break;
}
@ -1018,24 +1097,24 @@ struct CPU6502
case 0x24: { // BIT
unsigned char zpg = read_pc_inc(bus);
m = bus.read(zpg);
flag_change(Z, a & m);
flag_change(Z, (a & m) == 0);
flag_change(N, m & 0x80);
flag_change(V, m & 0x70);
flag_change(V, m & 0x40);
break;
}
case 0x2C: { // BIT
int addr = read_pc_inc(bus) + read_pc_inc(bus) * 256;
m = bus.read(addr);
flag_change(Z, a & m);
flag_change(Z, (a & m) == 0);
flag_change(N, m & 0x80);
flag_change(V, m & 0x70);
flag_change(V, m & 0x40);
break;
}
case 0xB4: { // LDY
unsigned char zpg = read_pc_inc(bus);
set_flags(N | Z, y = bus.read(zpg + x));
set_flags(N | Z, y = bus.read((zpg + x) & 0xFF));
break;
}
@ -1085,8 +1164,8 @@ struct CPU6502
case 0xCC: { // CPY
int addr = read_pc_inc(bus) + read_pc_inc(bus) * 256;
m = bus.read(addr);
flag_change(C, m <= a);
set_flags(N | Z, m = a - m);
flag_change(C, m <= y);
set_flags(N | Z, m = y - m);
break;
}
@ -1118,7 +1197,7 @@ struct CPU6502
case 0x51: { // EOR
unsigned char zpg = read_pc_inc(bus);
int addr = bus.read(zpg) + bus.read(zpg + 1) * 256 + y;
int addr = bus.read(zpg) + bus.read((zpg + 1) & 0xFF) * 256 + y;
m = bus.read(addr);
set_flags(N | Z, a = a ^ m);
break;
@ -1126,7 +1205,7 @@ struct CPU6502
case 0xD1: { // CMP
unsigned char zpg = read_pc_inc(bus);
int addr = bus.read(zpg) + bus.read(zpg + 1) * 256 + y;
int addr = bus.read(zpg) + bus.read((zpg + 1) & 0xFF) * 256 + y;
m = bus.read(addr);
flag_change(C, m <= a);
set_flags(N | Z, m = a - m);
@ -1158,7 +1237,7 @@ struct CPU6502
case 0xD5: { // CMP
unsigned char zpg = read_pc_inc(bus) + x;
m = bus.read(zpg);
m = bus.read(zpg & 0xFF);
flag_change(C, m <= a);
set_flags(N | Z, m = a - m);
break;
@ -1223,13 +1302,13 @@ struct CPU6502
case 0x95: { // STA
unsigned char zpg = read_pc_inc(bus);
bus.write((zpg + x) % 0x100, a);
bus.write((zpg + x) & 0xFF, a);
break;
}
case 0x94: { // STY
unsigned char zpg = read_pc_inc(bus);
bus.write((zpg + x) % 0x100, y);
bus.write((zpg + x) & 0xFF, y);
break;
}
@ -1299,11 +1378,13 @@ void cleanup(void)
if(!debugging) {
stop_keyboard();
}
fflush(stdout);
fflush(stderr);
}
bool use_fake6502 = false;
void disassemble_and_print_1(bus_controller &bus, int pc)
string read_bus_and_disassemble(bus_controller &bus, int pc)
{
int bytes;
string dis;
@ -1313,7 +1394,7 @@ void disassemble_and_print_1(bus_controller &bus, int pc)
buf[2] = bus.read(pc + 2);
buf[3] = bus.read(pc + 3);
tie(bytes, dis) = disassemble_6502(pc - 1, buf);
printf("%s\n", dis.c_str());
return dis;
}
int main(int argc, char **argv)
@ -1367,7 +1448,9 @@ int main(int argc, char **argv)
}
fclose(fp);
bus.boards.push_back(new MAINboard(b));
MAINboard* mainboard;
bus.boards.push_back(mainboard = new MAINboard(b));
for(auto b = bus.boards.begin(); b != bus.boards.end(); b++) {
(*b)->reset();
@ -1375,9 +1458,8 @@ int main(int argc, char **argv)
CPU6502 cpu;
if(debugging) {
clear_strobe();
stop_keyboard();
if(!debugging) {
start_keyboard();
}
if(use_fake6502)
@ -1390,16 +1472,23 @@ int main(int argc, char **argv)
char key;
bool have_key = peek_key(&key);
if(have_key && (key == '')) {
if(have_key) {
if(key == '') {
debugging = true;
clear_strobe();
stop_keyboard();
continue;
} else {
mainboard->enqueue_key(key);
clear_strobe();
}
}
chrono::time_point<chrono::system_clock> then;
for(int i = 0; i < 25575; i++) { // ~ 1/10th second
if(debug & DEBUG_DECODE) disassemble_and_print_1(bus, cpu.pc);
string dis = read_bus_and_disassemble(bus, cpu.pc);
if(debug & DEBUG_DECODE)
printf("%s\n", dis.c_str());
if(use_fake6502)
step6502();
else
@ -1432,7 +1521,9 @@ int main(int argc, char **argv)
printf("debug set to %02X\n", debug);
continue;
}
if(debug & DEBUG_DECODE) disassemble_and_print_1(bus, cpu.pc);
string dis = read_bus_and_disassemble(bus, cpu.pc);
if(debug & DEBUG_DECODE)
printf("%s\n", dis.c_str());
if(use_fake6502)
step6502();