/*
|
/*
|
* memory.c -- physical memory simulation
|
* memory.c -- physical memory simulation
|
*/
|
*/
|
|
|
|
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <string.h>
|
#include <string.h>
|
#include <setjmp.h>
|
#include <setjmp.h>
|
|
|
#include "common.h"
|
#include "common.h"
|
#include "console.h"
|
#include "console.h"
|
#include "error.h"
|
#include "error.h"
|
#include "except.h"
|
#include "except.h"
|
#include "cpu.h"
|
#include "cpu.h"
|
#include "memory.h"
|
#include "memory.h"
|
#include "timer.h"
|
#include "timer.h"
|
#include "dspkbd.h"
|
#include "dspkbd.h"
|
#include "term.h"
|
#include "term.h"
|
#include "disk.h"
|
#include "disk.h"
|
#include "output.h"
|
#include "output.h"
|
#include "graph.h"
|
#include "graph.h"
|
|
|
|
|
static Byte *rom;
|
static Byte *rom;
|
static Byte *mem;
|
static Byte *mem;
|
static unsigned int memSize;
|
static unsigned int memSize;
|
static FILE *romImage;
|
static FILE *romImage;
|
static unsigned int romSize;
|
static unsigned int romSize;
|
static FILE *progImage;
|
static FILE *progImage;
|
static unsigned int progSize;
|
static unsigned int progSize;
|
|
|
|
|
Word memoryReadWord(Word pAddr) {
|
Word memoryReadWord(Word pAddr) {
|
Word data;
|
Word data;
|
|
|
if (pAddr <= memSize - 4) {
|
if (pAddr <= memSize - 4) {
|
data = ((Word) *(mem + pAddr + 0)) << 24 |
|
data = ((Word) *(mem + pAddr + 0)) << 24 |
|
((Word) *(mem + pAddr + 1)) << 16 |
|
((Word) *(mem + pAddr + 1)) << 16 |
|
((Word) *(mem + pAddr + 2)) << 8 |
|
((Word) *(mem + pAddr + 2)) << 8 |
|
((Word) *(mem + pAddr + 3)) << 0;
|
((Word) *(mem + pAddr + 3)) << 0;
|
return data;
|
return data;
|
}
|
}
|
if (pAddr >= ROM_BASE &&
|
if (pAddr >= ROM_BASE &&
|
pAddr <= ROM_BASE + ROM_SIZE - 4) {
|
pAddr <= ROM_BASE + ROM_SIZE - 4) {
|
data = ((Word) *(rom + (pAddr - ROM_BASE) + 0)) << 24 |
|
data = ((Word) *(rom + (pAddr - ROM_BASE) + 0)) << 24 |
|
((Word) *(rom + (pAddr - ROM_BASE) + 1)) << 16 |
|
((Word) *(rom + (pAddr - ROM_BASE) + 1)) << 16 |
|
((Word) *(rom + (pAddr - ROM_BASE) + 2)) << 8 |
|
((Word) *(rom + (pAddr - ROM_BASE) + 2)) << 8 |
|
((Word) *(rom + (pAddr - ROM_BASE) + 3)) << 0;
|
((Word) *(rom + (pAddr - ROM_BASE) + 3)) << 0;
|
return data;
|
return data;
|
}
|
}
|
if ((pAddr & IO_DEV_MASK) == TIMER_BASE) {
|
if ((pAddr & IO_DEV_MASK) == TIMER_BASE) {
|
data = timerRead(pAddr & IO_REG_MASK);
|
data = timerRead(pAddr & IO_REG_MASK);
|
return data;
|
return data;
|
}
|
}
|
if ((pAddr & IO_DEV_MASK) == DISPLAY_BASE) {
|
if ((pAddr & IO_DEV_MASK) == DISPLAY_BASE) {
|
data = displayRead(pAddr & IO_REG_MASK);
|
data = displayRead(pAddr & IO_REG_MASK);
|
return data;
|
return data;
|
}
|
}
|
if ((pAddr & IO_DEV_MASK) == KEYBOARD_BASE) {
|
if ((pAddr & IO_DEV_MASK) == KEYBOARD_BASE) {
|
data = keyboardRead(pAddr & IO_REG_MASK);
|
data = keyboardRead(pAddr & IO_REG_MASK);
|
return data;
|
return data;
|
}
|
}
|
if ((pAddr & IO_DEV_MASK) == TERM_BASE) {
|
if ((pAddr & IO_DEV_MASK) == TERM_BASE) {
|
data = termRead(pAddr & IO_REG_MASK);
|
data = termRead(pAddr & IO_REG_MASK);
|
return data;
|
return data;
|
}
|
}
|
if ((pAddr & IO_DEV_MASK) == DISK_BASE) {
|
if ((pAddr & IO_DEV_MASK) == DISK_BASE) {
|
data = diskRead(pAddr & IO_REG_MASK);
|
data = diskRead(pAddr & IO_REG_MASK);
|
return data;
|
return data;
|
}
|
}
|
if ((pAddr & IO_DEV_MASK) == OUTPUT_BASE) {
|
if ((pAddr & IO_DEV_MASK) == OUTPUT_BASE) {
|
data = outputRead(pAddr & IO_REG_MASK);
|
data = outputRead(pAddr & IO_REG_MASK);
|
return data;
|
return data;
|
}
|
}
|
if ((pAddr & IO_DEV_MASK) >= GRAPH_BASE) {
|
if ((pAddr & IO_DEV_MASK) >= GRAPH_BASE) {
|
data = graphRead(pAddr & IO_GRAPH_MASK);
|
data = graphRead(pAddr & IO_GRAPH_MASK);
|
return data;
|
return data;
|
}
|
}
|
/* throw bus timeout exception */
|
/* throw bus timeout exception */
|
throwException(EXC_BUS_TIMEOUT);
|
throwException(EXC_BUS_TIMEOUT);
|
/* not reached */
|
/* not reached */
|
data = 0;
|
data = 0;
|
return data;
|
return data;
|
}
|
}
|
|
|
|
|
Half memoryReadHalf(Word pAddr) {
|
Half memoryReadHalf(Word pAddr) {
|
Half data;
|
Half data;
|
|
|
if (pAddr <= memSize - 2) {
|
if (pAddr <= memSize - 2) {
|
data = ((Half) *(mem + pAddr + 0)) << 8 |
|
data = ((Half) *(mem + pAddr + 0)) << 8 |
|
((Half) *(mem + pAddr + 1)) << 0;
|
((Half) *(mem + pAddr + 1)) << 0;
|
return data;
|
return data;
|
}
|
}
|
if (pAddr >= ROM_BASE &&
|
if (pAddr >= ROM_BASE &&
|
pAddr <= ROM_BASE + ROM_SIZE - 2) {
|
pAddr <= ROM_BASE + ROM_SIZE - 2) {
|
data = ((Half) *(rom + (pAddr - ROM_BASE) + 0)) << 8 |
|
data = ((Half) *(rom + (pAddr - ROM_BASE) + 0)) << 8 |
|
((Half) *(rom + (pAddr - ROM_BASE) + 1)) << 0;
|
((Half) *(rom + (pAddr - ROM_BASE) + 1)) << 0;
|
return data;
|
return data;
|
}
|
}
|
/* throw bus timeout exception */
|
/* throw bus timeout exception */
|
throwException(EXC_BUS_TIMEOUT);
|
throwException(EXC_BUS_TIMEOUT);
|
/* not reached */
|
/* not reached */
|
data = 0;
|
data = 0;
|
return data;
|
return data;
|
}
|
}
|
|
|
|
|
Byte memoryReadByte(Word pAddr) {
|
Byte memoryReadByte(Word pAddr) {
|
Byte data;
|
Byte data;
|
|
|
if (pAddr <= memSize - 1) {
|
if (pAddr <= memSize - 1) {
|
data = ((Byte) *(mem + pAddr + 0)) << 0;
|
data = ((Byte) *(mem + pAddr + 0)) << 0;
|
return data;
|
return data;
|
}
|
}
|
if (pAddr >= ROM_BASE &&
|
if (pAddr >= ROM_BASE &&
|
pAddr <= ROM_BASE + ROM_SIZE - 1) {
|
pAddr <= ROM_BASE + ROM_SIZE - 1) {
|
data = ((Byte) *(rom + (pAddr - ROM_BASE) + 0)) << 0;
|
data = ((Byte) *(rom + (pAddr - ROM_BASE) + 0)) << 0;
|
return data;
|
return data;
|
}
|
}
|
/* throw bus timeout exception */
|
/* throw bus timeout exception */
|
throwException(EXC_BUS_TIMEOUT);
|
throwException(EXC_BUS_TIMEOUT);
|
/* not reached */
|
/* not reached */
|
data = 0;
|
data = 0;
|
return data;
|
return data;
|
}
|
}
|
|
|
|
|
void memoryWriteWord(Word pAddr, Word data) {
|
void memoryWriteWord(Word pAddr, Word data) {
|
if (pAddr <= memSize - 4) {
|
if (pAddr <= memSize - 4) {
|
*(mem + pAddr + 0) = (Byte) (data >> 24);
|
*(mem + pAddr + 0) = (Byte) (data >> 24);
|
*(mem + pAddr + 1) = (Byte) (data >> 16);
|
*(mem + pAddr + 1) = (Byte) (data >> 16);
|
*(mem + pAddr + 2) = (Byte) (data >> 8);
|
*(mem + pAddr + 2) = (Byte) (data >> 8);
|
*(mem + pAddr + 3) = (Byte) (data >> 0);
|
*(mem + pAddr + 3) = (Byte) (data >> 0);
|
return;
|
return;
|
}
|
}
|
if ((pAddr & IO_DEV_MASK) == TIMER_BASE) {
|
if ((pAddr & IO_DEV_MASK) == TIMER_BASE) {
|
timerWrite(pAddr & IO_REG_MASK, data);
|
timerWrite(pAddr & IO_REG_MASK, data);
|
return;
|
return;
|
}
|
}
|
if ((pAddr & IO_DEV_MASK) == DISPLAY_BASE) {
|
if ((pAddr & IO_DEV_MASK) == DISPLAY_BASE) {
|
displayWrite(pAddr & IO_REG_MASK, data);
|
displayWrite(pAddr & IO_REG_MASK, data);
|
return;
|
return;
|
}
|
}
|
if ((pAddr & IO_DEV_MASK) == KEYBOARD_BASE) {
|
if ((pAddr & IO_DEV_MASK) == KEYBOARD_BASE) {
|
keyboardWrite(pAddr & IO_REG_MASK, data);
|
keyboardWrite(pAddr & IO_REG_MASK, data);
|
return;
|
return;
|
}
|
}
|
if ((pAddr & IO_DEV_MASK) == TERM_BASE) {
|
if ((pAddr & IO_DEV_MASK) == TERM_BASE) {
|
termWrite(pAddr & IO_REG_MASK, data);
|
termWrite(pAddr & IO_REG_MASK, data);
|
return;
|
return;
|
}
|
}
|
if ((pAddr & IO_DEV_MASK) == DISK_BASE) {
|
if ((pAddr & IO_DEV_MASK) == DISK_BASE) {
|
diskWrite(pAddr & IO_REG_MASK, data);
|
diskWrite(pAddr & IO_REG_MASK, data);
|
return;
|
return;
|
}
|
}
|
if ((pAddr & IO_DEV_MASK) == OUTPUT_BASE) {
|
if ((pAddr & IO_DEV_MASK) == OUTPUT_BASE) {
|
outputWrite(pAddr & IO_REG_MASK, data);
|
outputWrite(pAddr & IO_REG_MASK, data);
|
return;
|
return;
|
}
|
}
|
if ((pAddr & IO_DEV_MASK) >= GRAPH_BASE) {
|
if ((pAddr & IO_DEV_MASK) >= GRAPH_BASE) {
|
graphWrite(pAddr & IO_GRAPH_MASK, data);
|
graphWrite(pAddr & IO_GRAPH_MASK, data);
|
return;
|
return;
|
}
|
}
|
/* throw bus timeout exception */
|
/* throw bus timeout exception */
|
throwException(EXC_BUS_TIMEOUT);
|
throwException(EXC_BUS_TIMEOUT);
|
}
|
}
|
|
|
|
|
void memoryWriteHalf(Word pAddr, Half data) {
|
void memoryWriteHalf(Word pAddr, Half data) {
|
if (pAddr <= memSize - 2) {
|
if (pAddr <= memSize - 2) {
|
*(mem + pAddr + 0) = (Byte) (data >> 8);
|
*(mem + pAddr + 0) = (Byte) (data >> 8);
|
*(mem + pAddr + 1) = (Byte) (data >> 0);
|
*(mem + pAddr + 1) = (Byte) (data >> 0);
|
return;
|
return;
|
}
|
}
|
/* throw bus timeout exception */
|
/* throw bus timeout exception */
|
throwException(EXC_BUS_TIMEOUT);
|
throwException(EXC_BUS_TIMEOUT);
|
}
|
}
|
|
|
|
|
void memoryWriteByte(Word pAddr, Byte data) {
|
void memoryWriteByte(Word pAddr, Byte data) {
|
if (pAddr <= memSize - 1) {
|
if (pAddr <= memSize - 1) {
|
*(mem + pAddr + 0) = (Byte) (data >> 0);
|
*(mem + pAddr + 0) = (Byte) (data >> 0);
|
return;
|
return;
|
}
|
}
|
/* throw bus timeout exception */
|
/* throw bus timeout exception */
|
throwException(EXC_BUS_TIMEOUT);
|
throwException(EXC_BUS_TIMEOUT);
|
}
|
}
|
|
|
|
|
void memoryReset(void) {
|
void memoryReset(void) {
|
unsigned int i;
|
unsigned int i;
|
|
|
cPrintf("Resetting Memory...\n");
|
cPrintf("Resetting Memory...\n");
|
for (i = 0; i < memSize; i++) {
|
for (i = 0; i < memSize; i++) {
|
mem[i] = rand();
|
mem[i] = rand();
|
}
|
}
|
cPrintf("%6d MB RAM installed", memSize / M);
|
cPrintf("%6d MB RAM installed", memSize / M);
|
if (progImage != NULL) {
|
if (progImage != NULL) {
|
fseek(progImage, 0, SEEK_SET);
|
fseek(progImage, 0, SEEK_SET);
|
if (fread(mem, progSize, 1, progImage) != 1) {
|
if (fread(mem, progSize, 1, progImage) != 1) {
|
error("cannot read program image file");
|
error("cannot read program image file");
|
}
|
}
|
cPrintf(", %d bytes loaded", progSize);
|
cPrintf(", %d bytes loaded", progSize);
|
}
|
}
|
cPrintf(".\n");
|
cPrintf(".\n");
|
for (i = 0; i < ROM_SIZE; i++) {
|
for (i = 0; i < ROM_SIZE; i++) {
|
rom[i] = 0xFF;
|
rom[i] = 0xFF;
|
}
|
}
|
if (romImage != NULL) {
|
if (romImage != NULL) {
|
fseek(romImage, 0, SEEK_SET);
|
fseek(romImage, 0, SEEK_SET);
|
if (fread(rom, romSize, 1, romImage) != 1) {
|
if (fread(rom, romSize, 1, romImage) != 1) {
|
error("cannot read ROM image file");
|
error("cannot read ROM image file");
|
}
|
}
|
cPrintf("%6d KB ROM installed, %d bytes programmed.\n",
|
cPrintf("%6d KB ROM installed, %d bytes programmed.\n",
|
ROM_SIZE / K, romSize);
|
ROM_SIZE / K, romSize);
|
}
|
}
|
}
|
}
|
|
|
|
|
void memoryInit(unsigned int memorySize,
|
void memoryInit(unsigned int memorySize,
|
char *progImageName,
|
char *progImageName,
|
char *romImageName) {
|
char *romImageName) {
|
/* allocate RAM */
|
/* allocate RAM */
|
memSize = memorySize;
|
memSize = memorySize;
|
mem = malloc(memSize);
|
mem = malloc(memSize);
|
if (mem == NULL) {
|
if (mem == NULL) {
|
error("cannot allocate RAM");
|
error("cannot allocate RAM");
|
}
|
}
|
/* possibly load program image */
|
/* possibly load program image */
|
if (progImageName == NULL) {
|
if (progImageName == NULL) {
|
/* no program to load */
|
/* no program to load */
|
progImage = NULL;
|
progImage = NULL;
|
} else {
|
} else {
|
/* load program */
|
/* load program */
|
progImage = fopen(progImageName, "rb");
|
progImage = fopen(progImageName, "rb");
|
if (progImage == NULL) {
|
if (progImage == NULL) {
|
error("cannot open program file '%s'", progImageName);
|
error("cannot open program file '%s'", progImageName);
|
}
|
}
|
fseek(progImage, 0, SEEK_END);
|
fseek(progImage, 0, SEEK_END);
|
progSize = ftell(progImage);
|
progSize = ftell(progImage);
|
if (progSize > memSize) {
|
if (progSize > memSize) {
|
error("program file too big");
|
error("program file too big");
|
}
|
}
|
/* do actual loading of image in memoryReset() */
|
/* do actual loading of image in memoryReset() */
|
}
|
}
|
/* allocate ROM */
|
/* allocate ROM */
|
rom = malloc(ROM_SIZE);
|
rom = malloc(ROM_SIZE);
|
if (rom == NULL) {
|
if (rom == NULL) {
|
error("cannot allocate ROM");
|
error("cannot allocate ROM");
|
}
|
}
|
/* possibly load ROM image */
|
/* possibly load ROM image */
|
if (romImageName == NULL) {
|
if (romImageName == NULL) {
|
/* no ROM to plug in */
|
/* no ROM to plug in */
|
romImage = NULL;
|
romImage = NULL;
|
} else {
|
} else {
|
/* plug in ROM */
|
/* plug in ROM */
|
romImage = fopen(romImageName, "rb");
|
romImage = fopen(romImageName, "rb");
|
if (romImage == NULL) {
|
if (romImage == NULL) {
|
error("cannot open ROM image '%s'", romImageName);
|
error("cannot open ROM image '%s'", romImageName);
|
}
|
}
|
fseek(romImage, 0, SEEK_END);
|
fseek(romImage, 0, SEEK_END);
|
romSize = ftell(romImage);
|
romSize = ftell(romImage);
|
if (romSize > ROM_SIZE) {
|
if (romSize > ROM_SIZE) {
|
error("ROM image too big");
|
error("ROM image too big");
|
}
|
}
|
/* do actual loading of image in memoryReset() */
|
/* do actual loading of image in memoryReset() */
|
}
|
}
|
memoryReset();
|
memoryReset();
|
}
|
}
|
|
|
|
|
void memoryExit(void) {
|
void memoryExit(void) {
|
free(mem);
|
free(mem);
|
free(rom);
|
free(rom);
|
}
|
}
|
|
|