mirror of
https://github.com/dschmenk/PLASMA.git
synced 2025-04-07 16:41:59 +00:00
Place bytecode in external memory
This commit is contained in:
parent
2315282ec9
commit
b9e9fa2397
@ -31,6 +31,10 @@ byte *lastsym = symtbl;
|
||||
byte *perr;
|
||||
uword keybdbuf = 0x0200;
|
||||
uword heap = 0x0300;
|
||||
typedef struct {
|
||||
uword modofst;
|
||||
uword defaddr;
|
||||
} defxlat_t;
|
||||
/*
|
||||
* Standard Library exported functions.
|
||||
*/
|
||||
@ -157,6 +161,7 @@ unsigned char keypressed(M6502 *mpu)
|
||||
{
|
||||
if (cin == 0x03) // CTRL-C
|
||||
{
|
||||
trace = SINGLE_STEP;
|
||||
mpu->flags |= M6502_SingleStep;
|
||||
paused = 1;
|
||||
}
|
||||
@ -189,15 +194,16 @@ int setPLVMTraps(M6502 *mpu)
|
||||
//
|
||||
// Hooks for BRK, enter VM or native code
|
||||
//
|
||||
M6502_setCallback(mpu, call, VM_IRQ_ENTRY, vm_irq);
|
||||
M6502_setCallback(mpu, call, VM_INLINE_ENTRY, vm_indef);
|
||||
M6502_setCallback(mpu, call, VM_INDIRECT_ENTRY, vm_iidef);
|
||||
M6502_setCallback(mpu, call, VM_EXT_ENTRY, vm_exdef);
|
||||
M6502_setCallback(mpu, call, VM_NATV_ENTRY, vm_natvdef);
|
||||
M6502_setCallback(mpu, call, 0x0000, vm_irq);
|
||||
return 0;
|
||||
}
|
||||
int setApple1Traps(M6502 *mpu)
|
||||
{
|
||||
M6502_setCallback(mpu, call, VM_IRQ_ENTRY, vm_irq);
|
||||
//
|
||||
// Apple 1 memory-mapped IO
|
||||
//
|
||||
@ -212,11 +218,6 @@ int setApple1Traps(M6502 *mpu)
|
||||
M6502_setCallback(mpu, call, 0x9000, bye);
|
||||
M6502_setCallback(mpu, call, 0x900C, cffa1);
|
||||
M6502_setCallback(mpu, call, 0xFFEF, cout);
|
||||
//
|
||||
// !!! Hook Apple 1 VM entrypoints for testing purposes !!!
|
||||
//
|
||||
M6502_setCallback(mpu, call, 0x0283, vm_indef);
|
||||
M6502_setCallback(mpu, call, 0x0293, vm_iidef);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
@ -234,7 +235,7 @@ void M6502_exec(M6502 *mpu)
|
||||
M6502_dump(mpu, state);
|
||||
M6502_disassemble(mpu, mpu->registers->pc, insn);
|
||||
printf("%s : %s\r\n", state, insn);
|
||||
if (paused || (keypressed(mpu) && keypending == 0x83))
|
||||
if ((trace == SINGLE_STEP) && (paused || (keypressed(mpu) && keypending == 0x83)))
|
||||
{
|
||||
keypending = 0;
|
||||
while (!keypressed(mpu));
|
||||
@ -386,6 +387,18 @@ int add_sym(byte *dci, uword addr)
|
||||
/*
|
||||
* DEF routines - Create entryoint for 6502 that calls out to PLVM or native code
|
||||
*/
|
||||
void dump_def(defxlat_t *defxtbl, uword defcnt)
|
||||
{
|
||||
if (defcnt)
|
||||
{
|
||||
printf("DEF XLATE table:\n");
|
||||
while (defcnt--)
|
||||
{
|
||||
printf("$%04X -> $%04X\n", defxtbl->modofst, defxtbl->defaddr);
|
||||
defxtbl++;
|
||||
}
|
||||
}
|
||||
}
|
||||
byte *add_def(byte type, uword haddr, byte *lastdef)
|
||||
{
|
||||
*lastdef++ = 0x20; // JSR opcode
|
||||
@ -416,19 +429,18 @@ byte *add_def(byte type, uword haddr, byte *lastdef)
|
||||
*lastdef++ = haddr >> 8;
|
||||
return lastdef;
|
||||
}
|
||||
uword lookup_def(byte *deftbl, int defaddr)
|
||||
void xlat_def(uword addr, uword ofst, defxlat_t *defxtbl)
|
||||
{
|
||||
int calldef = 0;
|
||||
while (*deftbl)
|
||||
{
|
||||
if ((deftbl[3] | (deftbl[4] << 8)) == defaddr)
|
||||
{
|
||||
calldef = deftbl - mem_6502;
|
||||
break;
|
||||
}
|
||||
deftbl += 5;
|
||||
}
|
||||
return (uword)calldef;
|
||||
while (defxtbl->defaddr)
|
||||
defxtbl++;
|
||||
defxtbl->modofst = ofst;
|
||||
defxtbl->defaddr = addr;
|
||||
}
|
||||
uword lookup_def(defxlat_t *defxtbl, uword ofst)
|
||||
{
|
||||
while (defxtbl->defaddr && defxtbl->modofst != ofst)
|
||||
defxtbl++;
|
||||
return defxtbl->defaddr;
|
||||
}
|
||||
uword add_natv( VM_Callout natvfn)
|
||||
{
|
||||
@ -472,15 +484,27 @@ int load_mod(M6502 *mpu, byte *mod)
|
||||
uword sysflags = 0, defcnt = 0, init = 0;
|
||||
word modfix, modofst;
|
||||
byte *deftbl, *deflast, *moddep, *rld, *esd, *sym;
|
||||
code *extcode;
|
||||
defxlat_t *defxtbl;
|
||||
byte header[128];
|
||||
int fd;
|
||||
char filename[48], string[17];
|
||||
char filename[128], string[17];
|
||||
|
||||
dcitos(mod, filename);
|
||||
printf("Load module %s\n", filename);
|
||||
if (strlen(filename) < 4 || (filename[strlen(filename) - 4] != '.'))
|
||||
if (strlen(filename) > 4 && (filename[strlen(filename) - 4] != '.'))
|
||||
strcat(filename, ".mod");
|
||||
fd = open(filename, O_RDONLY, 0);
|
||||
if (fd <= 0 && filename[0] != '/' && strlen(filename) < 17)
|
||||
{
|
||||
//
|
||||
// Search syspath if module not found
|
||||
//
|
||||
strcpy(string, filename);
|
||||
strcpy(filename, (char *)mem_6502 + SYSPATH_BUF);
|
||||
strcat(filename, string);
|
||||
fd = open(filename, O_RDONLY, 0);
|
||||
}
|
||||
if ((fd > 0) && (len = read(fd, header, 128)) > 0)
|
||||
{
|
||||
moddep = header + 1;
|
||||
@ -521,6 +545,16 @@ int load_mod(M6502 *mpu, byte *mod)
|
||||
len = read(fd, header, 128);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Standard REL file - probaby generated from EDASM
|
||||
//
|
||||
sysflags = 0;
|
||||
bytecode = 0;
|
||||
defcnt = 0;
|
||||
init = 0;
|
||||
}
|
||||
//
|
||||
// Allocate heap space for DEF table.
|
||||
//
|
||||
@ -553,40 +587,55 @@ int load_mod(M6502 *mpu, byte *mod)
|
||||
esd = rld; // Extern+Entry Symbol Directory
|
||||
for (esd = rld; *esd; esd += 4); // Scan to end of RLD
|
||||
esd++; // ESD starts just past RLD
|
||||
if (show_state)
|
||||
if (trace)
|
||||
{
|
||||
//
|
||||
// Dump different parts of module.
|
||||
//
|
||||
printf("Module load addr: $%04X\n", modaddr);
|
||||
printf("Module size: %d\n", end - modaddr + hdrlen);
|
||||
printf("Module code+data size: %d\n", modsize);
|
||||
printf("Module size: $%04X (%d)\n", modsize, modsize);
|
||||
printf("Module code+data size: $%04X (%d)\n", end - modaddr, end - modaddr);
|
||||
printf("Module magic: $%04X\n", magic);
|
||||
printf("Module sysflags: $%04X\n", sysflags);
|
||||
printf("Module bytecode: $%04X\n", bytecode);
|
||||
printf("Module def count: $%04X\n", defcnt);
|
||||
printf("Module init: $%04X\n", init ? init + modofst : 0);
|
||||
if (defcnt)
|
||||
{
|
||||
printf("Module def count: %d\n", defcnt);
|
||||
printf("Module bytecode: $%04X\n", bytecode);
|
||||
printf("Module init: $%04X\n", init ? init + modofst : 0);
|
||||
printf("Module def size: $%04X (%d)\n", end - bytecode, end - bytecode);
|
||||
printf("Module def end: $%04X\n", end);
|
||||
}
|
||||
}
|
||||
//
|
||||
// Add module to symbol table.
|
||||
//
|
||||
add_sym(mod, modaddr);
|
||||
//
|
||||
// Allocate external code memory
|
||||
//
|
||||
if (defcnt)
|
||||
{
|
||||
extcode = code_alloc(end - bytecode);
|
||||
defxtbl = malloc(sizeof(defxlat_t) * defcnt);
|
||||
memset(defxtbl, 0, sizeof(defxlat_t) * defcnt);
|
||||
}
|
||||
//
|
||||
// Print out the Re-Location Dictionary.
|
||||
//
|
||||
if (show_state)
|
||||
if (trace)
|
||||
printf("\nRe-Location Dictionary:\n");
|
||||
while (rld[0])
|
||||
{
|
||||
addr = rld[1] | (rld[2] << 8);
|
||||
if (rld[0] == 0x02)
|
||||
{
|
||||
if (show_state) printf("\tDEF CODE");
|
||||
if (trace) printf("\tDEF CODE");
|
||||
//
|
||||
// This is a bytcode def entry - add it to the def directory.
|
||||
//
|
||||
addr += modofst;
|
||||
deflast = add_def(VM_DEF, addr, deflast);
|
||||
addr += modofst;
|
||||
xlat_def(deflast - mem_6502, addr, defxtbl);
|
||||
deflast = add_def(VM_EXT_DEF, vm_addxdef(extcode + addr - bytecode), deflast);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -611,7 +660,7 @@ int load_mod(M6502 *mpu, byte *mod)
|
||||
//
|
||||
// Resolve external symbol
|
||||
//
|
||||
if (show_state) printf("\tEXTERN[$%02X] ", rld[3]);
|
||||
if (trace) printf("\tEXTERN[$%02X] ", rld[3]);
|
||||
fixup += lookup_extern(esd, rld[3]);
|
||||
}
|
||||
else
|
||||
@ -625,25 +674,26 @@ int load_mod(M6502 *mpu, byte *mod)
|
||||
//
|
||||
// Replace with call def dictionary.
|
||||
//
|
||||
if (show_state) printf("\tDEF[$%04X->", fixup);
|
||||
fixup = lookup_def(deftbl, fixup);
|
||||
if (show_state) printf("$%04X] ", fixup);
|
||||
if (trace) printf("\tDEF[$%04X->", fixup);
|
||||
fixup = lookup_def(defxtbl, fixup);
|
||||
if (trace) printf("$%04X] ", fixup);
|
||||
if (!fixup) pfail("Unresolved DEF");
|
||||
}
|
||||
else
|
||||
if (show_state) printf("\tINTERN ");
|
||||
if (trace) printf("\tINTERN ");
|
||||
}
|
||||
if (rld[0] & 0x80)
|
||||
{
|
||||
//
|
||||
// 16 bit fixup
|
||||
//
|
||||
if (show_state) printf("WORD");
|
||||
if (trace) printf("WORD");
|
||||
mem_6502[addr] = fixup;
|
||||
mem_6502[addr + 1] = fixup >> 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (show_state) printf(rld[0] & 0x40 ? "MSBYTE" : "LSBYTE");
|
||||
if (trace) printf(rld[0] & 0x40 ? "MSBYTE" : "LSBYTE");
|
||||
if (rld[0] & 0x40)
|
||||
//
|
||||
// 8 bit MSB fixup
|
||||
@ -656,10 +706,10 @@ int load_mod(M6502 *mpu, byte *mod)
|
||||
mem_6502[addr] = fixup;
|
||||
}
|
||||
}
|
||||
if (show_state) printf("@$%04X\n", addr);
|
||||
if (trace) printf("@$%04X\n", addr);
|
||||
rld += 4;
|
||||
}
|
||||
if (show_state) printf("\nExternal/Entry Symbol Directory:\n");
|
||||
if (trace) printf("\nExternal/Entry Symbol Directory:\n");
|
||||
while (esd[0])
|
||||
{
|
||||
sym = esd;
|
||||
@ -671,12 +721,12 @@ int load_mod(M6502 *mpu, byte *mod)
|
||||
//
|
||||
addr = esd[1] | (esd[2] << 8);
|
||||
addr += modofst;
|
||||
if (show_state) printf("\tEXPORT %s@$%04X\n", string, addr);
|
||||
if (trace) printf("\tEXPORT %s@$%04X\n", string, addr);
|
||||
if (addr >= bytecode)
|
||||
//
|
||||
// Convert to def entry address
|
||||
//
|
||||
addr = lookup_def(deftbl, addr);
|
||||
addr = lookup_def(defxtbl, addr);
|
||||
//
|
||||
// Add symbol to PLASMA symbol table
|
||||
//
|
||||
@ -691,17 +741,26 @@ int load_mod(M6502 *mpu, byte *mod)
|
||||
pfail("");
|
||||
}
|
||||
//
|
||||
// Reserve heap space for relocated module.
|
||||
// Reserve heap space for relocated module and copy bytecode extrnally.
|
||||
//
|
||||
if (defcnt)
|
||||
{
|
||||
if (init) defcnt--;
|
||||
if (trace) dump_def(defxtbl, defcnt);
|
||||
free(defxtbl);
|
||||
if (trace) printf("Copy bytecode from $%04X to 0x%08X, size %d\n", bytecode, (unsigned int)extcode, end - bytecode);
|
||||
memcpy(extcode, mem_6502 + bytecode, end - bytecode);
|
||||
end = bytecode; // Free up bytecode in main memory
|
||||
}
|
||||
alloc_heap(end - modaddr);
|
||||
//
|
||||
//Call init routine.
|
||||
//
|
||||
if (init)
|
||||
{
|
||||
vm_interp(mpu, mem_6502 + init + modfix - REL_ADDR);
|
||||
if (!(sysflags & SYSFLAG_INITKEEP))
|
||||
release_heap(init + modofst); // Free up init code
|
||||
vm_interp(mpu, extcode + init + modofst - bytecode);
|
||||
//if (!(sysflags & SYSFLAG_INITKEEP))
|
||||
// release_heap(init + modofst); // Free up init code
|
||||
init = mem_6502[++mpu->registers->s + 0x100];
|
||||
init |= mem_6502[++mpu->registers->s + 0x100] << 8;
|
||||
return init;
|
||||
@ -793,6 +852,31 @@ void sysputh(M6502 *mpu)
|
||||
POP_ESTK(prhex);
|
||||
printf("%04X", prhex);
|
||||
}
|
||||
void sysgetc(M6502 *mpu)
|
||||
{
|
||||
char c;
|
||||
//
|
||||
// Push getchar()
|
||||
//
|
||||
c = getchar();
|
||||
PUSH_ESTK(c);
|
||||
}
|
||||
void sysgets(M6502 *mpu)
|
||||
{
|
||||
uword strptr;
|
||||
int len;
|
||||
char instr[256];
|
||||
|
||||
//
|
||||
// Push gets(), limiting it to 128 chars
|
||||
//
|
||||
len = strlen(gets(instr));
|
||||
if (len > 128)
|
||||
len = 128;
|
||||
mem_6502[CMDLINE_STR] = len;
|
||||
memcpy(mem_6502 + CMDLINE_BUF, instr, len);
|
||||
PUSH_ESTK(CMDLINE_STR);
|
||||
}
|
||||
void sysdivmod(M6502 *mpu)
|
||||
{
|
||||
word prhex;
|
||||
@ -813,8 +897,8 @@ void export_cmdsys(void)
|
||||
uword defaddr;
|
||||
mem_6502[cmdsys + 0] = 0x11; // Version 2.11
|
||||
mem_6502[cmdsys + 1] = 0x02;
|
||||
mem_6502[cmdsys + 2] = 0x80; // syspath
|
||||
mem_6502[cmdsys + 3] = 0x02;
|
||||
mem_6502[cmdsys + 2] = (byte)SYSPATH_STR; // syspath
|
||||
mem_6502[cmdsys + 3] = (byte)(SYSPATH_STR >> 8);
|
||||
mem_6502[cmdsys + 4] = (byte)CMDLINE_STR; // cmdline
|
||||
mem_6502[cmdsys + 5] = (byte)(CMDLINE_STR >> 8);
|
||||
defaddr = add_natv(sysexecmod); // sysexecmod
|
||||
@ -849,6 +933,8 @@ void export_cmdsys(void)
|
||||
export_natv("PUTI", sysputi);
|
||||
export_natv("PUTB", sysputb);
|
||||
export_natv("PUTH", sysputh);
|
||||
export_natv("GETC", sysgetc);
|
||||
export_natv("GETS", sysgets);
|
||||
#if 0
|
||||
char sysstr[] = "SYSCALL";
|
||||
char callstr[] = "CALL";
|
||||
@ -892,6 +978,7 @@ int main(int argc, char **argv)
|
||||
//
|
||||
M6502 *mpu = M6502_new(0, mem_6502, 0);
|
||||
M6502_reset(mpu);
|
||||
M6502_setVector(mpu, IRQ, VM_IRQ_ENTRY); // Dummy address to BRK/IRQ on
|
||||
mpu->registers->x = ESTK_SIZE;
|
||||
//
|
||||
// Parse command line options
|
||||
@ -901,10 +988,16 @@ int main(int argc, char **argv)
|
||||
argv++;
|
||||
while (argc && (*argv)[0] == '-')
|
||||
{
|
||||
if ((*argv)[1] == 's')
|
||||
show_state = 1;
|
||||
else if ((*argv)[1] == 't')
|
||||
if ((*argv)[1] == 't')
|
||||
{
|
||||
trace = TRACE;
|
||||
mpu->flags |= M6502_SingleStep;
|
||||
}
|
||||
else if ((*argv)[1] == 's')
|
||||
{
|
||||
trace = SINGLE_STEP;
|
||||
mpu->flags |= M6502_SingleStep;
|
||||
}
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
@ -933,35 +1026,35 @@ int main(int argc, char **argv)
|
||||
//
|
||||
// 64K - 256 RAM
|
||||
//
|
||||
mem_6502[FPL] = 0x00;
|
||||
mem_6502[FPH] = 0xFF;
|
||||
mem_6502[PPL] = 0x00;
|
||||
mem_6502[PPH] = 0xFF;
|
||||
mem_6502[FPL] = 0x00; // Frame pointer = $FF00
|
||||
mem_6502[FPH] = 0xFF;
|
||||
mem_6502[PPL] = 0x00; // Pool pointer = $FF00
|
||||
mem_6502[PPH] = 0xFF;
|
||||
//
|
||||
// Load module from command line - PLVM version
|
||||
//
|
||||
export_cmdsys();
|
||||
stodci(modfile, dci);
|
||||
if (show_state) dump_sym();
|
||||
if (trace) dump_sym();
|
||||
load_mod(mpu, dci);
|
||||
if (show_state) dump_sym();
|
||||
if (trace) dump_sym();
|
||||
}
|
||||
else
|
||||
{
|
||||
setRawInput();
|
||||
setApple1Traps(mpu);
|
||||
//
|
||||
// 32K RAM
|
||||
//
|
||||
mem_6502[FPL] = 0x00;
|
||||
mem_6502[FPH] = 0x80;
|
||||
mem_6502[PPL] = 0x00;
|
||||
mem_6502[PPH] = 0x80;
|
||||
mem_6502[FPL] = 0x00; // Frame pointer = $8000
|
||||
mem_6502[FPH] = 0x80;
|
||||
mem_6502[PPL] = 0x00; // Pool pointer = $8000 (unused)
|
||||
mem_6502[PPH] = 0x80;
|
||||
//
|
||||
// Load Apple 1 emulation - lib6502 version
|
||||
//
|
||||
if (!load(0x280, cmdfile))
|
||||
pfail(cmdfile);
|
||||
setRawInput();
|
||||
mpu->registers->pc = 0x0280;
|
||||
M6502_exec(mpu);
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ enum {
|
||||
flagD= (1<<3), /* decimal mode */
|
||||
flagI= (1<<2), /* irq disable */
|
||||
flagZ= (1<<1), /* zero */
|
||||
flagC= (1<<0) /* carry */
|
||||
flagC= (1<<0) /* carry */
|
||||
};
|
||||
|
||||
struct _M6502_Registers
|
||||
|
122
src/vmsrc/plvm.c
122
src/vmsrc/plvm.c
@ -6,11 +6,17 @@
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include "plvm.h"
|
||||
|
||||
/*
|
||||
* PLVM eval stack
|
||||
*/
|
||||
#define PUSH(v) (*(--esp))=(v)
|
||||
#define POP ((word)(*(esp++)))
|
||||
#define UPOP ((uword)(*(esp++)))
|
||||
#define TOS (esp[0])
|
||||
/*
|
||||
* Debug flag
|
||||
*/
|
||||
int show_state = 0;
|
||||
int trace = 0;
|
||||
/*
|
||||
* VM def routines
|
||||
*/
|
||||
@ -27,8 +33,6 @@ int natv_count = 0;
|
||||
* Memory for 6502 and VM
|
||||
*/
|
||||
byte mem_6502[MEM6502_SIZE];
|
||||
word eval_stack[ESTK_SIZE];
|
||||
word *esp = &eval_stack[ESTK_SIZE];
|
||||
/*
|
||||
* BRK and VM entrypoint hooks
|
||||
*/
|
||||
@ -36,6 +40,7 @@ int vm_irq(M6502 *mpu, uword address, byte data)
|
||||
{
|
||||
uword addr, handle;
|
||||
|
||||
fflush(stdout);
|
||||
if (mem_6502[mpu->registers->s + 0x101] & flagB)
|
||||
{
|
||||
//
|
||||
@ -49,10 +54,10 @@ int vm_irq(M6502 *mpu, uword address, byte data)
|
||||
// default:
|
||||
// fprintf(stderr, "Unkonw BRK value!\n");
|
||||
//}
|
||||
fprintf(stderr, "BRK: $%04X\r\n", addr);
|
||||
fprintf(stderr, "\nBRK: $%04X\r\n", address);
|
||||
exit (-1);
|
||||
}
|
||||
fprintf(stderr, "Unkonw IRQ!\n");
|
||||
fprintf(stderr, "\nUnkonw IRQ!\n");
|
||||
RTI;
|
||||
}
|
||||
//
|
||||
@ -134,23 +139,24 @@ OPTBL DW CN,CN,CN,CN,CN,CN,CN,CN ; 00 02 04 06
|
||||
for (val = ESTK_SIZE - 1; val >= mpu->registers->x; val--) \
|
||||
PUSH(mem_6502[ESTKL + val] | (mem_6502[ESTKH + val] << 8))
|
||||
#define externalize() \
|
||||
mem_6502[FPL] = vm_fp; \
|
||||
mem_6502[FPH] = vm_fp >> 8; \
|
||||
mem_6502[PPL] = vm_pp; \
|
||||
mem_6502[PPH] = vm_pp >> 8; \
|
||||
mem_6502[FPL] = (byte)vm_fp; \
|
||||
mem_6502[FPH] = (byte)(vm_fp >> 8); \
|
||||
mem_6502[PPL] = (byte)vm_pp; \
|
||||
mem_6502[PPH] = (byte)(vm_pp >> 8); \
|
||||
ea = ESTK_SIZE-1; \
|
||||
{ word *vm_sp; \
|
||||
for (vm_sp = &eval_stack[ESTK_SIZE-1]; vm_sp >= esp; vm_sp--) { \
|
||||
mem_6502[ESTKL + ea] = *vm_sp; \
|
||||
mem_6502[ESTKH + ea] = *vm_sp >> 8; \
|
||||
mem_6502[ESTKL + ea] = (byte)*vm_sp; \
|
||||
mem_6502[ESTKH + ea] = (byte)(*vm_sp >> 8); \
|
||||
ea--; \
|
||||
} \
|
||||
}} \
|
||||
mpu->registers->x = ea + 1
|
||||
|
||||
void vm_interp(M6502 *mpu, code *vm_ip)
|
||||
{
|
||||
int val, ea, frmsz, parmcnt;
|
||||
uword vm_fp, vm_pp;
|
||||
word *vm_sp;
|
||||
word eval_stack[ESTK_SIZE], *esp;
|
||||
|
||||
internalize();
|
||||
while (1)
|
||||
@ -158,17 +164,21 @@ void vm_interp(M6502 *mpu, code *vm_ip)
|
||||
if ((esp - eval_stack) < 0 || (esp - eval_stack) > ESTK_SIZE)
|
||||
{
|
||||
printf("Eval stack over/underflow! - $%04X: $%02X [%d]\r\n", (unsigned int)(vm_ip - mem_6502), (unsigned int)*vm_ip, (int)(ESTK_SIZE - (esp - eval_stack)));
|
||||
show_state = 1;
|
||||
exit(-1);
|
||||
}
|
||||
if (show_state)
|
||||
if (trace)
|
||||
{
|
||||
char cmdline[16];
|
||||
word *dsp = &eval_stack[ESTK_SIZE - 1];
|
||||
printf("$%04X: $%02X [ ", (unsigned int)(vm_ip - mem_6502), (unsigned int)*vm_ip);
|
||||
if (vm_ip >= mem_6502 && vm_ip < (mem_6502 + MEM6502_SIZE))
|
||||
printf("$%04X: $%02X [ ", (unsigned int)(vm_ip - mem_6502), (unsigned int)*vm_ip);
|
||||
else
|
||||
printf("0x%08X: $%02X [ ", (unsigned int)vm_ip, (unsigned int)*vm_ip);
|
||||
while (dsp >= esp)
|
||||
printf("$%04X ", (unsigned int)((*dsp--) & 0xFFFF));
|
||||
printf("]\r\n");
|
||||
fgets(cmdline, 15, stdin);
|
||||
if (trace == SINGLE_STEP)
|
||||
fgets(cmdline, 15, stdin);
|
||||
}
|
||||
switch (*vm_ip++)
|
||||
{
|
||||
@ -230,7 +240,48 @@ void vm_interp(M6502 *mpu, code *vm_ip)
|
||||
vm_ip += 2;
|
||||
break;
|
||||
case 0x2E: // CS: TOS = CONSTANTSTRING (IP)
|
||||
PUSH(vm_ip - mem_6502);
|
||||
if (vm_ip >= mem_6502 && vm_ip < (mem_6502 + MEM6502_SIZE))
|
||||
{
|
||||
//
|
||||
// Main memory code, just push address of string
|
||||
//
|
||||
PUSH(vm_ip - mem_6502);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// Copy string to string pool
|
||||
//
|
||||
for (val = vm_pp; val < vm_fp; val++)
|
||||
{
|
||||
if (mem_6502[val] == *vm_ip)
|
||||
{
|
||||
//
|
||||
// Look for mathing string
|
||||
//
|
||||
for (ea = BYTE_PTR(vm_ip); ea; ea--)
|
||||
if (mem_6502[val + ea] != vm_ip[ea])
|
||||
break;
|
||||
if (!ea)
|
||||
{
|
||||
//
|
||||
// Already in string pool
|
||||
//
|
||||
PUSH(val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (val >= vm_fp)
|
||||
{
|
||||
//
|
||||
// Not found, allocate in pool
|
||||
//
|
||||
vm_pp -= BYTE_PTR(vm_ip) + 1;
|
||||
memcpy(mem_6502 + vm_pp, vm_ip, BYTE_PTR(vm_ip) + 1);
|
||||
PUSH(vm_pp);
|
||||
}
|
||||
}
|
||||
vm_ip += BYTE_PTR(vm_ip) + 1;
|
||||
break;
|
||||
/*
|
||||
@ -343,34 +394,35 @@ void vm_interp(M6502 *mpu, code *vm_ip)
|
||||
break;
|
||||
case 0x54: // CALL : TOFP = IP, IP = (IP) ; call
|
||||
mpu->registers->pc = UWORD_PTR(vm_ip);
|
||||
mem_6502[0x00FF] = 0xFF; // RTN instruction
|
||||
mem_6502[mpu->registers->s-- + 0x100] = 0x00; // Address of $FF (RTN) instruction
|
||||
mem_6502[mpu->registers->s-- + 0x100] = 0xFF; // Address of $FF (RTN) instruction
|
||||
mem_6502[mpu->registers->s-- + 0x100] = 0xFE;
|
||||
//mpu->flags |= M6502_SingleStep;
|
||||
externalize();
|
||||
if (show_state)
|
||||
if (trace)
|
||||
printf("CALL: $%04X\r\n", mpu->registers->pc);
|
||||
externalize();
|
||||
M6502_exec(mpu);
|
||||
internalize();
|
||||
vm_ip += 2;
|
||||
break;
|
||||
case 0x56: // ICALL : IP = TOS ; indirect call
|
||||
mpu->registers->pc = UPOP;
|
||||
mem_6502[0x00FF] = 0xFF; // RTN instruction
|
||||
mem_6502[mpu->registers->s-- + 0x100] = 0x00; // Address of $FF (RTN) instruction
|
||||
mem_6502[mpu->registers->s-- + 0x100] = 0xFF; // Address of $FF (RTN) instruction
|
||||
mem_6502[mpu->registers->s-- + 0x100] = 0xFE;
|
||||
externalize();
|
||||
if (show_state)
|
||||
if (trace)
|
||||
printf("ICAL: $%04X\r\n", mpu->registers->pc);
|
||||
externalize();
|
||||
M6502_exec(mpu);
|
||||
internalize();
|
||||
break;
|
||||
case 0x58: // ENTER : NEW FRAME, FOREACH PARAM LOCALVAR = TOS
|
||||
frmsz = BYTE_PTR(vm_ip);
|
||||
vm_ip++;
|
||||
if (show_state)
|
||||
printf("< $%04X: $%04X > ", vm_fp - frmsz, vm_fp);
|
||||
vm_fp -= frmsz;
|
||||
if (trace)
|
||||
printf("<PP:$%04X FP:$%04X FRMSZ:$%02X> ", vm_pp, vm_fp, frmsz);
|
||||
mem_6502[--vm_pp] = (byte)(vm_fp >> 8);
|
||||
mem_6502[--vm_pp] = (byte)vm_fp;
|
||||
vm_fp = vm_pp - frmsz;
|
||||
vm_pp = vm_fp;
|
||||
parmcnt = BYTE_PTR(vm_ip);
|
||||
vm_ip++;
|
||||
while (parmcnt--)
|
||||
@ -378,14 +430,18 @@ void vm_interp(M6502 *mpu, code *vm_ip)
|
||||
val = POP;
|
||||
mem_6502[vm_fp + parmcnt * 2 + 0] = val;
|
||||
mem_6502[vm_fp + parmcnt * 2 + 1] = val >> 8;
|
||||
if (show_state)
|
||||
if (trace)
|
||||
printf("< $%04X: $%04X > ", vm_fp + parmcnt * 2 + 0, mem_6502[vm_fp + parmcnt * 2 + 0] | (mem_6502[vm_fp + parmcnt * 2 + 1] >> 8));
|
||||
}
|
||||
if (show_state)
|
||||
if (trace)
|
||||
printf("\n");
|
||||
break;
|
||||
case 0x5A: // LEAVE : DEL FRAME, IP = TOFP
|
||||
vm_fp += BYTE_PTR(vm_ip);
|
||||
vm_pp = vm_fp + BYTE_PTR(vm_ip);
|
||||
vm_fp = mem_6502[vm_pp++];
|
||||
vm_fp |= mem_6502[vm_pp++] << 8;
|
||||
if (trace)
|
||||
printf("<PP:$%04X FP:$%04X>\n", vm_pp, vm_fp);
|
||||
case 0x5C: // RET : IP = TOFP
|
||||
externalize();
|
||||
return;
|
||||
|
@ -28,17 +28,17 @@ typedef uint16_t address;
|
||||
#define PLP (mpu->registers->p=mem_6502[++mpu->registers->s + 0x100])
|
||||
#define RTI \
|
||||
{ \
|
||||
word pc; \
|
||||
uword pc; \
|
||||
PLP; \
|
||||
pc = mem_6502[++mpu->registers->s + 0x100]; \
|
||||
pc |= mem_6502[++mpu->registers->s + 0x100] << 8; \
|
||||
pc |= mem_6502[++mpu->registers->s + 0x100]<<8; \
|
||||
return pc; \
|
||||
}
|
||||
#define RTS \
|
||||
{ \
|
||||
word pc; \
|
||||
uword pc; \
|
||||
pc = mem_6502[++mpu->registers->s + 0x100]; \
|
||||
pc |= mem_6502[++mpu->registers->s + 0x100] << 8; \
|
||||
pc |= mem_6502[++mpu->registers->s + 0x100]<<8; \
|
||||
return pc + 1; \
|
||||
}
|
||||
/*
|
||||
@ -47,22 +47,15 @@ typedef uint16_t address;
|
||||
#define PUSH_ESTK(v) \
|
||||
{ \
|
||||
--mpu->registers->x; \
|
||||
mem_6502[ESTKL + mpu->registers->x] = (v); \
|
||||
mem_6502[ESTKH + mpu->registers->x] = (v) >> 8; \
|
||||
mem_6502[ESTKL + mpu->registers->x] = (byte)(v); \
|
||||
mem_6502[ESTKH + mpu->registers->x] = (byte)(v)>>8; \
|
||||
}
|
||||
#define POP_ESTK(v) \
|
||||
{ \
|
||||
(v) = mem_6502[ESTKL + mpu->registers->x] \
|
||||
| mem_6502[ESTKH + mpu->registers->x] << 8; \
|
||||
| mem_6502[ESTKH + mpu->registers->x]<<8; \
|
||||
++mpu->registers->x; \
|
||||
}
|
||||
/*
|
||||
* PLVM eval stack
|
||||
*/
|
||||
#define PUSH(v) (*(--esp))=(v)
|
||||
#define POP ((word)(*(esp++)))
|
||||
#define UPOP ((uword)(*(esp++)))
|
||||
#define TOS (esp[0])
|
||||
/*
|
||||
* 6502 memory map
|
||||
*/
|
||||
@ -70,6 +63,8 @@ typedef uint16_t address;
|
||||
#define ESTK_SIZE 16
|
||||
#define CMDLINE_STR 0x01FF
|
||||
#define CMDLINE_BUF 0x0200
|
||||
#define SYSPATH_STR 0x0280
|
||||
#define SYSPATH_BUF 0x0281
|
||||
/*
|
||||
* Zero page VM locations matching Apple ZP
|
||||
*/
|
||||
@ -89,16 +84,23 @@ typedef uint16_t address;
|
||||
#define VM_EXT_DEF 2
|
||||
#define VM_DEF 1
|
||||
#define VM_INLINE_DEF 0
|
||||
#define VM_NATV_ENTRY 0xFFFC
|
||||
#define VM_EXT_ENTRY 0xFFF8
|
||||
#define VM_INDIRECT_ENTRY 0xFFF4
|
||||
#define VM_INLINE_ENTRY 0xFFF0
|
||||
#define VM_NATV_ENTRY 0xFF0E
|
||||
#define VM_EXT_ENTRY 0xFF0C
|
||||
#define VM_INDIRECT_ENTRY 0xFF08
|
||||
#define VM_INLINE_ENTRY 0xFF04
|
||||
#define VM_IRQ_ENTRY 0xFF00
|
||||
/*
|
||||
* Allocate external code memory
|
||||
*/
|
||||
#define code_alloc(size) malloc(size)
|
||||
#define TRACE 1
|
||||
#define SINGLE_STEP 2
|
||||
/*
|
||||
* VM callouts
|
||||
*/
|
||||
void M6502_exec(M6502 *mpu);
|
||||
typedef void (*VM_Callout)(M6502 *mpu);
|
||||
extern int show_state;
|
||||
extern int trace;
|
||||
extern byte mem_6502[];
|
||||
extern byte mem_PLVM[];
|
||||
extern byte *perr;
|
||||
|
Loading…
x
Reference in New Issue
Block a user