Reworked memory access. Speed is 40-45% of a real Mac now :)

This commit is contained in:
Jeroen Domburg 2017-05-30 17:24:44 +08:00
parent 075820bd49
commit cca0d7fbbe
2 changed files with 203 additions and 70 deletions

View File

@ -35,6 +35,8 @@ COMPONENT_EXTRA_CLEAN := $(addprefix $(COMPONENT_PATH)/musashi/,$(MUSASHI_GEN_SR
#musashi/m68kopdm.o: CFLAGS += -O3
#musashi/m68kopnz.o: CFLAGS += -O3
emu.o: CFLAGS += -O3
define makeiram
$(1): $(2)
$$(summary) OBJCOPY $(2)

View File

@ -42,62 +42,216 @@ void m68k_instruction() {
if (pc==0x7E56) printf("Mon: SCSIReadSectors exit FAIL\n");
}
typedef uint8_t (*PeripAccessCb)(unsigned int address, int data, int isWrite);
uint8_t unhandledAccessCb(unsigned int address, int data, int isWrite) {
unsigned int pc=m68k_get_reg(NULL, M68K_REG_PC);
printf("Unhandled %s @ 0x%X! PC=0x%X\n", isWrite?"write":"read", address, pc);
return 0xff;
}
uint8_t bogusReadCb(unsigned int address, int data, int isWrite) {
if (isWrite) return 0;
return address^(address>>8)^(address>>16);
}
uint8_t ncrAccessCb(unsigned int address, int data, int isWrite) {
if (isWrite) {
ncrWrite((address>>4)&0x7, (address>>9)&1, data);
return 0;
} else {
return ncrRead((address>>4)&0x7, (address>>9)&1);
}
}
uint8_t sscAccessCb(unsigned int address, int data, int isWrite) {
if (isWrite) {
sccWrite(address, data);
return 0;
} else {
return sccRead(address);
}
}
uint8_t iwmAccessCb(unsigned int address, int data, int isWrite) {
if (isWrite) {
iwmWrite((address>>9)&0xf, data);
return 0;
} else {
return iwmRead((address>>9)&0xf);;
}
}
uint8_t viaAccessCb(unsigned int address, int data, int isWrite) {
if (isWrite) {
viaWrite((address>>9)&0xf, data);
return 0;
} else {
return viaRead((address>>9)&0xf);
}
}
#define FLAG_RO (1<<0);
typedef struct {
uint8_t *memAddr;
union {
PeripAccessCb cb;
int flags;
};
} MemmapEnt;
#define MEMMAP_MAX_ADDR 0x1000000
#define MEMMAP_ES 0x20000
//Memmap describing 128 128K blocks of memory, from 0 to 0x1000000.
MemmapEnt memmap[128];
static void regenMemmap(int remapRom) {
int i;
//Default handler
for (i=0; i<128; i++) {
memmap[i].memAddr=0;
memmap[i].cb=unhandledAccessCb;
}
//0-0x400000 is RAM, or ROM when remapped
if (remapRom) {
memmap[0].memAddr=macRom;
memmap[0].flags=FLAG_RO;
for (i=1; i<0x400000/MEMMAP_ES; i++) {
//Do not point at ROM again, but at... something else. Abuse RAM here.
//If pointed at ROM again, ROM will think this machine does not have SCSI.
memmap[i].memAddr=NULL;
memmap[i].cb=bogusReadCb;
}
} else {
for (i=0; i<0x400000/MEMMAP_ES; i++) {
memmap[i].memAddr=&macRam[(i*MEMMAP_ES)&(TME_RAMSIZE-1)];
memmap[i].flags=0;
}
}
//0x40000-0x50000 is ROM
memmap[0x400000/MEMMAP_ES].memAddr=macRom;
memmap[0x400000/MEMMAP_ES].flags=FLAG_RO;
for (i=0x400000/MEMMAP_ES+1; i<0x500000/MEMMAP_ES; i++) {
//Again, point to crap or SCSI won't work.
memmap[i].memAddr=0;
memmap[i].cb=bogusReadCb;
}
//0x580000-0x600000 is SCSI controller
for (i=0x580000/MEMMAP_ES; i<0x600000/MEMMAP_ES; i++) {
memmap[i].memAddr=NULL;
memmap[i].cb=ncrAccessCb;
}
//0x600000-0x700000 is RAM
for (i=0x600000/MEMMAP_ES; i<0x700000/MEMMAP_ES; i++) {
memmap[i].memAddr=&macRam[(i*MEMMAP_ES)&(TME_RAMSIZE-1)];
memmap[i].flags=0;
}
//0x800000-0xC00000 is SSC
for (i=0x800000/MEMMAP_ES; i<0xC00000/MEMMAP_ES; i++) {
memmap[i].memAddr=NULL;
memmap[i].cb=sscAccessCb;
}
//0xC00000-0xE00000 is IWM
for (i=0xc00000/MEMMAP_ES; i<0xe00000/MEMMAP_ES; i++) {
memmap[i].memAddr=NULL;
memmap[i].cb=iwmAccessCb;
}
//0xE80000-0xF00000 is VIA
for (i=0xE80000/MEMMAP_ES; i<0xF00000/MEMMAP_ES; i++) {
memmap[i].memAddr=NULL;
memmap[i].cb=viaAccessCb;
}
}
const inline static MemmapEnt *getMmmapEnt(const unsigned int address) {
if (address>=MEMMAP_MAX_ADDR) return &memmap[127];
return &memmap[address/MEMMAP_ES];
}
unsigned int m68k_read_memory_8(unsigned int address) {
unsigned int ret;
unsigned int pc=m68k_get_reg(NULL, M68K_REG_PC);
if (address < 0x400000) {
if (rom_remap) {
ret=macRom[address & (TME_ROMSIZE-1)];
} else {
ret=macRam[address & (TME_RAMSIZE-1)];
}
} else if (address >= 0x600000 && address < 0x700000) {
ret=macRam[(address-0x600000) & (TME_RAMSIZE-1)];
} else if (address >= 0x400000 && address<0x500000) {
int romAdr=address-0x400000;
if (romAdr>=TME_ROMSIZE) {
printf("PC %x:Huh? Read from ROM mirror (%x)\n", pc, address);
ret=(address>>12); // ROM checks for same contents at 20000 and 40000 to determine if SCSI is present
} else {
ret=macRom[romAdr&(TME_ROMSIZE-1)];
}
} else if (address >= 0xE80000 && address < 0xf00000) {
ret=viaRead((address>>9)&0xf);
} else if (address >= 0xc00000 && address < 0xe00000) {
ret=iwmRead((address>>9)&0xf);
} else if (address >= 0x580000 && address < 0x600000) {
ret=ncrRead((address>>4)&0x7, (address>>9)&1);
} else if (address >= 0x800000 && address < 0xC00000) {
ret=sccRead(address);
const MemmapEnt *mmEnt=getMmmapEnt(address);
if (mmEnt->memAddr) {
return mmEnt->memAddr[address&(MEMMAP_ES-1)];
} else {
printf("PC %x: Read from %x\n", pc, address);
ret=0xff;
return mmEnt->cb(address, 0, 0);
}
}
unsigned int m68k_read_memory_16(unsigned int address) {
const MemmapEnt *mmEnt=getMmmapEnt(address);
if (mmEnt->memAddr) {
uint8_t *p=&mmEnt->memAddr[address&(MEMMAP_ES-1)];
return (p[0]<<8)|(p[1]);
} else {
unsigned int ret;
ret=mmEnt->cb(address, 0, 0)<<8;
ret|=mmEnt->cb(address+1, 0, 0);
return ret;
}
}
unsigned int m68k_read_memory_32(unsigned int address) {
const MemmapEnt *mmEnt=getMmmapEnt(address);
if (mmEnt->memAddr) {
uint8_t *p=&mmEnt->memAddr[address&(MEMMAP_ES-1)];
return (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|(p[3]);
} else {
unsigned int ret;
ret=mmEnt->cb(address, 0, 0)<<24;
ret|=mmEnt->cb(address+1, 0, 0)<<16;
ret|=mmEnt->cb(address+2, 0, 0)<<8;
ret|=mmEnt->cb(address+3, 0, 0)<<0;
return ret;
}
// printf("Rd %x = %x\n", address, ret);
return ret;
}
void m68k_write_memory_8(unsigned int address, unsigned int value) {
unsigned int pc=m68k_get_reg(NULL, M68K_REG_PC);
if (address < 0x400000) {
if (!rom_remap) macRam[address & (TME_RAMSIZE-1)]=value;
} else if (address >= 0x600000 && address < 0xA00000) {
macRam[(address-0x600000) & (TME_RAMSIZE-1)]=value;
} else if (address >= 0xE80000 && address < 0xf00000) {
viaWrite((address>>9)&0xf, value);
} else if (address >= 0xc00000 && address < 0xe00000) {
iwmWrite((address>>9)&0xf, value);
} else if (address >= 0x580000 && address < 0x600000) {
ncrWrite((address>>4)&0x7, (address>>9)&1, value);
} else if (address >= 0x800000 && address < 0xC00000) {
sccWrite(address, value);
// printf("PC %x: Write to %x: %x\n", pc, address, value);
const MemmapEnt *mmEnt=getMmmapEnt(address);
if (mmEnt->memAddr) {
mmEnt->memAddr[address&(MEMMAP_ES-1)]=value;
} else {
printf("PC %x: Write to %x: %x\n", pc, address, value);
mmEnt->cb(address, value, 1);
}
}
void m68k_write_memory_16(unsigned int address, unsigned int value) {
const MemmapEnt *mmEnt=getMmmapEnt(address);
if (mmEnt->memAddr) {
uint8_t *p=&mmEnt->memAddr[address&(MEMMAP_ES-1)];
p[0]=(value>>8);
p[1]=(value>>0);
} else {
mmEnt->cb(address, (value>>8)&0xff, 1);
mmEnt->cb(address+1, (value>>0)&0xff, 1);
}
}
void m68k_write_memory_32(unsigned int address, unsigned int value) {
const MemmapEnt *mmEnt=getMmmapEnt(address);
if (mmEnt->memAddr) {
uint8_t *p=&mmEnt->memAddr[address&(MEMMAP_ES-1)];
p[0]=(value>>24);
p[1]=(value>>16);
p[2]=(value>>8);
p[3]=(value>>0);
} else {
mmEnt->cb(address, (value>>24)&0xff, 1);
mmEnt->cb(address+1, (value>>16)&0xff, 1);
mmEnt->cb(address+2, (value>>8)&0xff, 1);
mmEnt->cb(address+3, (value>>0)&0xff, 1);
}
}
//Should be called every second.
void printFps() {
struct timeval tv;
@ -121,6 +275,7 @@ void tmeStartEmu(void *ram, void *rom) {
printf("Clearing ram...\n");
for (int x=0; x<TME_RAMSIZE; x++) macRam[x]=0;
rom_remap=1;
regenMemmap(1);
printf("Creating HD and registering it...\n");
SCSIDevice *hd=hdCreate("hd.img");
ncrRegisterDevice(6, hd);
@ -176,36 +331,12 @@ void sccIrq(int req) {
m68k_set_irq(req?2:0);
}
//Mac uses an 68008, which has an external 16-bit bus. Hence, it should be okay to do everything using 16-bit
//reads/writes.
unsigned int m68k_read_memory_32(unsigned int address) {
unsigned int ret;
ret=m68k_read_memory_16(address)<<16;
ret|=m68k_read_memory_16(address+2);
return ret;
}
unsigned int m68k_read_memory_16(unsigned int address) {
unsigned int ret;
ret=m68k_read_memory_8(address)<<8;
ret|=m68k_read_memory_8(address+1);
return ret;
}
void m68k_write_memory_32(unsigned int address, unsigned int value) {
m68k_write_memory_16(address, value>>16);
m68k_write_memory_16(address+2, value);
}
void m68k_write_memory_16(unsigned int address, unsigned int value) {
m68k_write_memory_8(address, (value>>8)&0xff);
m68k_write_memory_8(address+1, value&0xff);
}
void viaCbPortAWrite(unsigned int val) {
int oldRomRemap=rom_remap;
video_remap=(val&(1<<6))?1:0;
rom_remap=(val&(1<<4))?1:0;
regenMemmap(rom_remap);
audio_remap=(val&(1<<3))?1:0;
if (oldRomRemap!=rom_remap) printf("ROM REMAP %d\n", rom_remap);
iwmSetHeadSel(val&(1<<5));